- Bluetooth пульт для телевизора на arduino
- Trema bluetooth модуль в роли ведомого (slave) принимает данные:
- Trema bluetooth модуль в роли ведущего (master) передаёт данные:
- Исходный код программы
- Код программы для «малыша»:
- Подключаем bluetooth к машинке
- Схема подключения робота quadruped:
- Схема электропитания робота автомобиля
Bluetooth пульт для телевизора на arduino
#include
IRsend irsend;
unsigned long a;
void setup() {
Serial.begin(9600);
Serial.setTimeout(4);
pinMode(ledPin, OUTPUT);
}
unsigned int A_one[78]={4450,4550,400,1800,450,650,450,1800,450,600,500,650,450,650,450,700,450,650,450,1750,450,650,500,1750,450,650,450,650,500,650,450,650,450,700,450,650,450,650,450,1750,450,650,500,650,450,650,500,650,450,650,450,1750,450,1750,500,650,450,1700,500,1750,450,1750,450,1800,450,1700,450};
unsigned int A_two[78]={4450,4550,450,1750,450,650,500,1750,500,600,450,650,450,650,500,650,450,650,500,1700,500,650,450,1800,450,600,500,650,450,650,450,650,500,650,450,1750,450,650,500,1750,450,650,450,650,450,700,450,650,450,650,450,700,450,1750,450,650,450,1700,500,1750,500,1750,450,1750,500,1650,500};
unsigned int A_three[78]={4450,4500,450,1750,450,700,450,1750,450,650,450,650,500,650,450,650,450,650,500,1750,450,650,450,1750,500,600,500,650,450,650,450,650,500,650,450,650,450,1750,500,1750,450,650,450,650,500,650,450,650,450,650,450,1750,500,650,450,650,500,1700,450,1800,450,1700,500,1750,500,1650,500};
unsigned int A_four[78]={4450,4550,450,1750,450,700,450,1750,450,650,450,650,500,650,450,650,450,650,500,1700,500,650,450,1750,500,600,500,650,450,650,450,650,500,650,450,650,450,650,500,650,450,1700,500,600,500,650,450,650,500,600,500,1750,450,1750,500,1750,450,600,500,1750,500,1700,500,1750,500,1650,500};
unsigned int A_five[78]={4450,4550,450,1750,450,650,500,1750,450,650,450,650,500,650,450,650,450,650,500,1750,450,650,450,1750,500,600,500,650,450,650,450,650,500,650,450,1750,450,650,500,650,450,1700,500,650,450,650,450,650,450,700,450,650,450,1750,500,1750,450,650,450,1750,500,1750,450,1750,500,1650,500};
unsigned int A_six[78]={4400,4550,450,1800,400,700,400,1800,450,650,450,700,400,700,450,650,450,650,500,1750,450,650,450,1750,500,600,500,650,450,650,450,700,400,700,450,650,450,1750,500,650,450,1700,500,650,450,650,450,700,400,700,450,1750,450,650,450,1800,450,650,450,1750,500,1750,450,1750,450,1700,500};
unsigned int A_seven[78]={4450,4550,450,1750,450,650,450,1800,450,650,450,650,450,650,500,650,450,650,450,1750,500,600,500,1750,500,600,500,600,500,650,450,650,500,600,500,650,450,650,500,1750,450,1700,500,600,500,650,450,650,450,650,500,1750,450,1750,500,600,500,650,450,1700,550,1700,500,1750,450,1700,500};
unsigned int A_eight[78]={4400,4550,450,1750,450,650,450,1800,450,650,450,650,450,700,400,650,500,650,450,1750,450,700,450,1750,500,600,450,700,450,650,450,650,450,700,450,1750,450,650,450,1800,450,1700,500,650,450,650,450,700,450,600,500,650,450,1750,500,650,450,650,450,1750,450,1800,400,1800,450,1700,450};
unsigned int A_nine[78]={4450,4500,450,1750,500,650,450,1800,450,600,450,650,500,650,450,650,450,700,450,1750,450,650,450,1800,450,650,450,650,450,650,500,600,500,650,450,650,500,1750,450,1750,500,1700,450,650,500,650,450,650,450,650,450,1800,450,650,450,650,450,650,450,1800,450,1750,450,1750,500,1650,500};
unsigned int A_zero[78]={4450,4500,500,1750,450,650,450,1800,450,650,450,650,450,650,500,650,450,650,450,1750,450,650,500,1750,500,600,450,650,500,650,450,650,450,650,500,1750,450,650,450,650,500,650,450,1750,450,650,450,650,500,650,450,650,450,1750,500,1750,450,1750,450,650,450,1750,500,1750,450,1700,450};
unsigned int A_w[78]={4450,4550,450,1750,450,650,500,1750,450,650,450,650,450,650,500,650,450,650,500,1700,500,600,500,1750,500,600,500,650,450,650,450,650,500,650,450,650,450,650,500,600,500,600,500,1750,500,600,500,1700,500,650,450,1750,450,1800,450,1750,450,1750,450,650,450,1750,500,650,450,1700,500};
unsigned int A_on[78]={4450,4550,450,1750,450,650,450,1800,450,650,450,650,450,650,450,700,450,650,450,1750,450,700,450,1750,500,600,450,650,500,650,450,650,450,700,450,650,450,1750,450,650,450,700,450,650,450,650,500,650,450,650,450,1750,450,700,450,1750,450,1750,400,1800,450,1800,400,1800,450,1700,450};
void S1() {irsend.sendRaw(A_one,78,38);delay(500);}
void S2() {irsend.sendRaw(A_two,78,38);delay(500);}
void S3() {irsend.sendRaw(A_three,78,38);delay(500);}
void S4() {irsend.sendRaw(A_four,78,38);delay(500);}
void S5() {irsend.sendRaw(A_five,78,38);delay(500);}
void S6() {irsend.sendRaw(A_six,78,38);delay(500);}
void S7() {irsend.sendRaw(A_seven,78,38);delay(500);}
void S8() {irsend.sendRaw(A_eight,78,38);delay(500);}
void S9() {irsend.sendRaw(A_nine,78,38);delay(500);}
void S0() {irsend.sendRaw(A_zero,78,38);delay(500);}
void Son() {irsend.sendRaw(A_on,78,38);delay(500);}
void loop()
{
if (Serial.available())
{ a = Serial.parseInt();
if (a==101) {Son ();}
if (a==102) {S2();}
if (a==103) {S3();}
if (a==1) {S1();}
if (a==2) {S2();}
if (a==3) {S3();}
if (a==4) {S4();}
if (a==5) {S5();}
if (a==6) {S6();}
if (a==7) {S7();}
if (a==8) {S8();}
if (a==9) {S9();}
if (a==10) {S1();S0();}
if (a==11) {S1();S1();}
if (a==12) {S1();S2();}
if (a==13) {S1();S3();}
if (a==14) {S1();S4();}
if (a==15) {S1();S5();}
if (a==16) {S1();S6();}
if (a==17) {S1();S7();}
if (a==18) {S1();S8();}
if (a==19) {S1();S9();}
if (a==20) {S2();S0();}
if (a==21) {S2();S1();}
if (a==22) {S2();S2();}
if (a==23) {S2();S3();}
if (a==24) {S2();S4();}
if (a==25) {S2();S5();}
if (a==26) {S2();S6();}
if (a==27) {S2();S7();}
if (a==28) {S2();S8();}
if (a==29) {S2();S9();}
if (a==30) {S3();S0();}
if (a==31) {S3();S1();}
if (a==32) {S3();S2();}
if (a==33) {S3();S3();}
if (a==34) {S3();S4();}
if (a==35) {S3();S5();}
if (a==36) {S3();S6();}
if (a==37) {S3();S7();}
if (a==38) {S3();S8();}
if (a==39) {S3();S9();}
if (a==40) {S4();S0();}
if (a==41) {S4();S1();}
if (a==42) {S4();S2();}
if (a==43) {S4();S3();}
if (a==44) {S4();S4();}
if (a==45) {S4();S5();}
if (a==46) {S4();S6();}
if (a==47) {S4();S7();}
if (a==48) {S4();S8();}
if (a==49) {S4();S9();}
if (a==50) {S5();S0();}
if (a==51) {S5();S1();}
if (a==52) {S5();S2();}
if (a==53) {S5();S3();}
if (a==54) {S5();S4();}
if (a==55) {S5();S5();}
if (a==56) {S5();S6();}
if (a==57) {S5();S7();}
if (a==58) {S5();S8();}
if (a==59) {S5();S9();}
if (a==60) {S6();S0();}
if (a==61) {S6();S1();}
if (a==62) {S6();S2();}
if (a==63) {S6();S3();}
if (a==64) {S6();S4();}
if (a==65) {S6();S5();}
if (a==66) {S6();S6();}
if (a==67) {S6();S7();}
if (a==68) {S6();S8();}
if (a==69) {S6();S9();}
if (a==70) {S7();S0();}
if (a==71) {S7();S1();}
if (a==72) {S7();S2();}
if (a==73) {S7();S3();}
if (a==74) {S7();S4();}
if (a==75) {S7();S5();}
if (a==76) {S7();S6();}
if (a==77) {S7();S7();}
if (a==78) {S7();S8();}
if (a==79) {S7();S9();}
if (a==80) {S8();S0();}
if (a==81) {S8();S1();}
if (a==82) {S8();S2();}
if (a==83) {S8();S3();}
if (a==84) {S8();S4();}
if (a==85) {S8();S5();}
if (a==86) {S8();S6();}
if (a==87) {S8();S7();}
if (a==88) {S8();S8();}
if (a==89) {S8();S9();}
if (a==90) {S9();S0();}
if (a==91) {S9();S1();}
if (a==92) {S9();S2();}
if (a==93) {S9();S3();}
if (a==94) {S9();S4();}
if (a==95) {S9();S5();}
if (a==96) {S9();S6();}
if (a==97) {S9();S7();}
if (a==98) {S9();S8();}
if (a==99) {S9();S9();}
if (a==100) {S1();S0();S0(); }
}
}
Trema bluetooth модуль в роли ведомого (slave) принимает данные:
Связь осуществляется между двумя Trema Bluetooth модулями HC-05 использующими библиотеку iarduino_Bluetooth_HC05. Скетч модуля исполняющего роль master приведён в следующем примере.
#include <SoftwareSerial.h> // Подключаем библиотеку SoftwareSerial для общения с модулем по программной шине UART #include <iarduino_Bluetooth_HC05.h> // Подключаем библиотеку iarduino_Bluetooth_HC05 для работы с Trema Bluetooth модулем HC-05 SoftwareSerial softSerial(2,3); // Создаём объект softSerial указывая выводы RX, TX (можно указывать любые выводы Arduino UNO). Вывод 2 Arduino подключается к выводу TX модуля, вывод 3 Arduino подключается к выводу RX модуля iarduino_Bluetooth_HC05 hc05(4); // Создаём объект hc05 указывая любой вывод Arduino, который подключается к выводу K модуля int myArray[3]; // Объявляем массив в который будем получать данные, можно создавать массивы или переменные любых типов в .т.ч и char // void setup(){ // Serial.begin (9600); // Инициируем передачу данных по аппаратной шине UART для вывода результата в монитор последовательного порта Serial.print ("begin: "); // Выводим текст "begin: " в монитор последовательного порта if( hc05.begin(softSerial) ) {Serial.println("Ok");} // Инициируем работу с Trema модулем hc05, указывая объект softSerial через который осуществляется связь по шине UART else {Serial.println("Error");} // Если работа с модулем не инициирована, то выводим сообщение об ошибке Serial.print ("create slave: "); // Выводим текст "create slave: " в монитор последовательного порта if( hc05.createSlave("MyName","4567") ) {Serial.println("Ok");} // Создаем ведомую роль модулю, указывая его имя и pin-код (в примере имя = "MyName", pin-код = "4567") else {Serial.println("Error");} // Если роль не создалась - выводим сообщение об ошибке } // // void loop (){ // if(hc05.available()){ // Если есть принятые данные, то ... hc05.read(myArray); // Читаем полученные данные в ранее объявленный массив myArray Serial.println(myArray[0]); // Выводим 0 элемент массива myArray в монитор последовательного порта Serial.println(myArray[1]); // Выводим 1 элемент массива myArray в монитор последовательного порта Serial.println(myArray[2]); // Выводим 2 элемент массива myArray в монитор последовательного порта } // Функции available() и read() работают только при приёме данных от внешнего Trema Bluetooth модуля использующего данную библиотеку! } // Если передача данных выполняется другим Bluetooth модулем, то приём данных осуществляется посимвольным чтением данных из UART
Инициализация модуля hc05.begin(); и создание ведомой роли hc05.createSlave(); может занять несколько секунд.
В этом примере модуль подключается через программный UART используя библиотеку SoftwareSerial, а при инициализации работы с модулем hc05.begin() указывается объект softSerial.
При использовании Trema Bluetooth модуля HC-05 в качестве ведомого можно однократно вызвать функцию createSlave() с указанием имени и pin кода, после чего навсегда исключить эту функцию из кода. Тогда, при подаче питания, Trema Bluetooth модуля HC-05 будет стартовать в режиме ведомого и соединяться с первым ведущим который правильно укажет имя и pin ведомого.
Функция createSlave() объекта hc05 позволяет создать ведомую роль Trema Bluetooth модулю HC-05 при подключении к любым Bluetooth модулям, но функции available() и read() объекта hc05 работают только при организации связи между двумя Trema Bluetooth модулями HC-05 использующими библиотеку iarduino_Bluetooth_HC05!
... // Если внешним Bluetooth устройством передающим данные является не Trema Bluetooth модуль, то ... void loop(){ // Данные принимаются посимвольным чтением из UART ... if(softSerial.available()){ // Если есть принятые данные, то ... String str; // Создаём строку str while(softSerial.available()){ // Выполняем цикл пока есть что читать ... str1 =softSerial.read(); // Читаем очередной принятый символ из UART в строку str delay(5); // Задержка на 5 мс на случай медленного приёма } // Цикл завершён, значит читать больше нечего Serial.println(str); // Выводим прочитанные данные одной строкой } // } //
Строки кода до функции loop остаются без изменений. Все данные отправленные внешним Bluetooth модулем принимаются как строки.
Trema bluetooth модуль в роли ведущего (master) передаёт данные:
Связь осуществляется между двумя Trema Bluetooth модулями HC-05 использующими библиотеку iarduino_Bluetooth_HC05. Скетч модуля исполняющего роль slave приведён в предыдущем примере.
#include <SoftwareSerial.h> // Подключаем библиотеку SoftwareSerial для общения с модулем по программной шине UART #include <iarduino_Bluetooth_HC05.h> // Подключаем библиотеку iarduino_Bluetooth_HC05 для работы с модулем SoftwareSerial softSerial(2,3); // Создаём объект softSerial указывая выводы RX, TX (можно указывать любые выводы Arduino UNO). Вывод 2 Arduino подключается к выводу TX модуля, вывод 3 Arduino подключается к выводу RX модуля iarduino_Bluetooth_HC05 hc05(4); // Создаём объект hc05 указывая любой вывод Arduino, который подключается к выводу K модуля int myArray[3] = {123,456,789}; // Определяем массив с данными которые будем передавать, можно создавать массивы или переменные любых типов, в т.ч. и char, но не более 54 байт void setup(){ // Serial.begin (9600); // Инициируем передачу данных по аппаратной шине UART для вывода результата в монитор последовательного порта Serial.print ("begin: "); // Выводим текст "begin: " в монитор последовательного порта if( hc05.begin(softSerial) ) {Serial.println("Ok");} // Инициируем работу с Trema модулем hc05, указывая объект softSerial через который осуществляется связь по шине UART else {Serial.println("Error");} // Если работа с модулем не инициирована, то выводим сообщение об ошибке Serial.print ("create master: "); // Выводим текст "create master: " в монитор последовательного порта if( hc05.createMaster("MyName","4567") ){Serial.println("Ok");} // Создаем ведущую роль модулю, указывая имя и pin-код ведомого к которому требуется подключиться (в примере имя = "MyName", pin-код = "4567") else {Serial.println("Error");} // Если роль не создалась или не удалось подключиться к ведомому - выводим сообщение об ошибке } // void loop (){ // Serial.print ("send: "); // Выводим текст "send: " в монитор последовательного порта if( hc05.send(myArray) ) {Serial.println("Ok");} // Передаём данные массива myArray через Trema-модуль bluetooth с проверкой доставки else {Serial.println("Error");} // Если данные не приняты ведомым bluetooth устройством - выводим сообщение об ошибке } // Функция send() предназначена для отправки данных только для Trema Bluetooth модулей использующих данную библиотеку!
Инициализация модуля hc05.begin(); и создание ведущей роли с подключением к ведомому hc05.createMaster(); может занять до минуты.В этом примере модуль подключается через программный UART используя библиотеку SoftwareSerial, а при инициализации работы с модулем hc05.begin() указывается объект softSerial.
Функция createMaster() объекта hc05 позволяет создать ведущую роль Trema Bluetooth модулю HC-05 при подключении к любым Bluetooth модулям, но функция send() объекта hc05 работает только при организации связи между двумя Trema Bluetooth модулями HC-05 использующими библиотеку iarduino_Bluetooth_HC05!
Так как функция send() добавляет 4 служебных байта к передаваемым данным (2 в начале и 2 в конце), которые приёмник будет считать за полученные данные. Если требуется отправить данные на другие Bluetooth модули, это лучше сделать отправкой строки по шине UART, тогда код loop будет выглядеть так:
... // Если внешним Bluetooth устройством принимающим данные является не Trema Bluetooth модуль, то ... void loop(){ // Данные передаются строкой или символами через UART ... softSerial.println(myArray[0]); // Отправляем значение 0 элемента массива myArray, которое будет принято как строка softSerial.println(myArray[1]); // Отправляем значение 1 элемента массива myArray, которое будет принято как строка softSerial.println(myArray[2]); // Отправляем значение 2 элемента массива myArray, которое будет принято как строка } //
Строки кода до функции loop остаются без изменений. Все данные передаются символами (байтами) или строками. По этому элементы массива отправляются по отдельности.
Исходный код программы
В программе первым делом необходимо инициализировать выходные контакты для подключения двигателей (через драйвер мотора).
Затем в функции setup задать направление работы для этих контактов (на вывод данных).
После этого мы будем считывать данные из последовательного порта Arduino, получаемые им от последовательного порта Bluetooth модуля, и выполнять соответствующие инструкции.
Затем мы запрограммируем функции для различных направлений движения машины. Всего будет использоваться пять условий для задания направления движения машины, представленных в следующей таблице:
Далее представлен полный текст программы.
if(str[i-1]==’1′)
{
Serial.println(“Forward”);
forward();
i=0;
}
else if(str[i-1]==’2′)
{
Serial.println(“Left”);
right();
i=0;
}
else if(str[i-1]==’3′)
{
Serial.println(“Right”);
left();
i=0;
}
else if(str[i-1]==’4′)
{
Serial.println(“Backward”);
backward();
i=0;
}
else if(str[i-1]==’5′)
{
Serial.println(“Stop”);
Stop();
i=0;
}
delay(100);
}
}
#define m11 11 // задний двигатель #define m12 12 #define m21 10 // передний двигатель #define m22 9 charstr[2],i; voidforward() { digitalWrite(m11,LOW); digitalWrite(m12,LOW); digitalWrite(m21,HIGH); digitalWrite(m22,LOW); } voidbackward() { digitalWrite(m11,LOW); digitalWrite(m12,LOW); digitalWrite(m21,LOW); digitalWrite(m22,HIGH); } voidleft() { digitalWrite(m11,HIGH); digitalWrite(m12,LOW); delay(100); digitalWrite(m21,HIGH); digitalWrite(m22,LOW); } voidright() { digitalWrite(m11,LOW); digitalWrite(m12,HIGH); delay(100); digitalWrite(m21,HIGH); digitalWrite(m22,LOW); } voidStop() { digitalWrite(m11,LOW); digitalWrite(m12,LOW); digitalWrite(m21,LOW); digitalWrite(m22,LOW); } voidsetup() { Serial.begin(9600); pinMode(m11,OUTPUT); pinMode(m12,OUTPUT); pinMode(m21,OUTPUT); pinMode(m22,OUTPUT); } voidloop() { while(Serial.available()) { charch=Serial.read(); str[i ]=ch; if(str[i–1]==‘1’) { Serial.println(“Forward”); forward(); i=; } elseif(str[i–1]==‘2’) { Serial.println(“Left”); right(); i=; } elseif(str[i–1]==‘3’) { Serial.println(“Right”); left(); i=; } elseif(str[i–1]==‘4’) { Serial.println(“Backward”); backward(); i=; } elseif(str[i–1]==‘5’) { Serial.println(“Stop”); Stop(); i=; } delay(100); } } |
Код программы для «малыша»:
#include <SoftwareSerial.h> // Подключаем библиотеку SoftwareSerial для общения с модулем по программной шине UART #include <iarduino_Bluetooth_HC05.h> // Подключаем библиотеку iarduino_Bluetooth_HC05 для работы с Trema Bluetooth модулем HC-05 SoftwareSerial softSerial(9, 10); // Создаём объект softSerial указывая выводы RX, TX (можно указывать любые выводы Arduino UNO). Вывод 2 Arduino подключается к выводу TX модуля, вывод 3 Arduino подключается к выводу RX модуля iarduino_Bluetooth_HC05 hc05(13); // Создаём объект hc05 указывая любой вывод Arduino, который подключается к выводу K модуля // uint8_t pinShield_H2 = 4; // Вывод, подключенный к драйверу, для задания направления вращения левым мотором uint8_t pinShield_E2 = 5; // Вывод ШИМ, подключенный к драйверу, для задания скорости левого мотора uint8_t pinShield_E1 = 6; // Вывод ШИМ, подключенный к драйверу, для задания скорости правого мотора uint8_t pinShield_H1 = 7; // Вывод, подключенный к драйверу, для задания направления вращения правым мотором uint8_t pinLED_RED = 12; // Вывод с красным светодиодом uint8_t pinLED_BLUE = 11; // Вывод с синим светодиодом uint16_t time_period = 200; // Частота мигания светодиодов (в миллисекундах) uint8_t valSpeed = 255; // Максимальная скорость ШИМ (число от 0 до 255) bool arrRoute[2] = {1, 1}; // Направление движения для каждого мотора ([0]- правый мотор, [1] - левый мотор) uint16_t arrSpeed[2]; // Скорость для каждого мотора ([0]- правый мотор, [1] - левый мотор) uint32_t tmrLED; // Время последнего включения светодиодов uint32_t flgTime; // Флаг для задания времени принятия пакетов от Bluetooth телефона uint8_t flg; // Флаг кнопок uint32_t tmrWait; // Время до начала сопряжения с новыми устройствами bool flg_LED; // Флаг включения светодиодов // </iarduino_bluetooth_hc05.h></softwareserial.h> void setup() { // // BLUETOOTH МОДУЛЬ // Serial.begin (9600); // Инициируем передачу данных по аппаратной шине UART для вывода результата в монитор последовательного порта Serial.print ("begin: "); // Выводим текст "begin: " в монитор последовательного порта if (hc05.begin(softSerial)) {Serial.println("Ok");} // Инициируем работу с Trema модулем hc05, указывая объект softSerial через который осуществляется связь по шине UART else {Serial.println("Error");} // Если работа с модулем не инициирована, то выводим сообщение об ошибке tmrWait = millis(); // Устанавливаем таймер ожидания сопряжения while (!hc05.checkConnect() && millis()<tmrWait 60000) {;} // Ждём в течении 60 секунд сопряжения с последним устройством из памяти if (millis()<tmrWait 60000) {Serial.println("Connect with last ADR");} // Если сопряжение произошло, то выдаём в монитор порта сообщение об этом else { // Если сопряжение не произошло, то if (hc05.createSlave("BT_CAR", "1234")) // Создаем ведомую роль модулю, указывая его имя и pin-код (в примере имя = "BT_CAR", pin-код = "1234") {Serial.println("Slave create");} // Если ведомая роль была создана, выводим сообщение об успехе в монитор порта, else {Serial.println("Slave not create");} // а если не была создана - выводим сообщение об ошибке в монитор порта. } // // МОТОРЫ // pinMode(pinShield_H2, OUTPUT); // Конфигурируем вывод pinShield_H2 как выход (направление вращения левого мотора) pinMode(pinShield_E2, OUTPUT); // Конфигурируем вывод pinShield_E2 как выход (скорость вращения левого мотора, ШИМ) pinMode(pinShield_E1, OUTPUT); // Конфигурируем вывод pinShield_E1 как выход (скорость вращения правого мотора, ШИМ) pinMode(pinShield_H1, OUTPUT); // Конфигурируем вывод pinShield_H1 как выход (направление вращения правого мотора) // СВЕТОДИОДЫ // pinMode(pinLED_RED,OUTPUT); // Конфигурируем вывод pinLED_RED как выход pinMode(pinLED_BLUE,OUTPUT); // Конфигурируем вывод pinLED_BLUE как выход tmrLED = millis(); // Устанавливаем таймер светодиодов равным millis() flg_LED = 0; // Сбрасываем флаг светодиодов } // void loop() { // if (softSerial.available()) { // Если есть принятые данные, то ... String str; // Создаём строку str while (softSerial.available()) { // Выполняем цикл пока есть что читать ... str = char(softSerial.read()); // Читаем очередной принятый символ из UART в строку str delay(5); // Задержка на 5 мс на случай медленного приёма } // Цикл завершён, значит читать больше нечего // КНОПКИ ДВИЖЕНИЯ // // Флаг времени Флаг кнопки // if (str == "II") { flgTime = millis(); flg = 1; } // Кнопка "стрелка вверх-влево" if (str == "FF") { flgTime = millis(); flg = 2; } // Кнопка "стрелка вверх" if (str == "GG") { flgTime = millis(); flg = 3; } // Кнопка "стрелка вверх-вправо" if (str == "RR") { flgTime = millis(); flg = 4; } // Кнопка "стрелка влево" if (str == "SS") { flgTime = millis(); flg = 5; } // СТОП if (str == "LL") { flgTime = millis(); flg = 6; } // Кнопка "стрелка вправо" if (str == "JJ") { flgTime = millis(); flg = 7; } // Кнопка "стрелка вниз-влево" if (str == "BB") { flgTime = millis(); flg = 8; } // Кнопка "стрелка вниз" if (str == "HH") { flgTime = millis(); flg = 9; } // Кнопка "стрелка вниз-вправо" // КНОПКИ ДОПОЛНИТЕЛЬНЫХ ФУНКЦИЙ // // Если кнопка нажата меняем флаг // if (str == "SWS" || str == "SwS") {flg_LED = !flg_LED;} // Кнопка включения светодиодов if (str == "S0S") {flg = 10; } // Ползунок скорости в положении 0 if (str == "S1S") {flg = 11; } // Ползунок скорости в положении 1 if (str == "S2S") {flg = 12; } // Ползунок скорости в положении 2 if (str == "S3S") {flg = 13; } // Ползунок скорости в положении 3 if (str == "S4S") {flg = 14; } // Ползунок скорости в положении 4 if (str == "S5S") {flg = 15; } // Ползунок скорости в положении 5 if (str == "S6S") {flg = 16; } // Ползунок скорости в положении 6 if (str == "S7S") {flg = 17; } // Ползунок скорости в положении 7 if (str == "S8S") {flg = 18; } // Ползунок скорости в положении 8 if (str == "S9S") {flg = 19; } // Ползунок скорости в положении 9 if (str == "SqS") {flg = 20; } // Ползунок скорости в положении 10 // ====================================================================================================================================================== switch (flg) {//Направление левого мотора Направление правого мотора Скорость левого мотора Скорость правого мотора case 1: arrRoute[1] = 1; arrRoute[0] = 1; arrSpeed[1] = (valSpeed / 2); arrSpeed[0] = valSpeed; break; // С-З case 2: arrRoute[1] = 1; arrRoute[0] = 1; arrSpeed[1] = valSpeed; arrSpeed[0] = valSpeed; break; // С case 3: arrRoute[1] = 1; arrRoute[0] = 1; arrSpeed[1] = valSpeed; arrSpeed[0] = (valSpeed / 2); break; // С-В case 4: arrRoute[1] = 1; arrRoute[0] = 1; arrSpeed[1] = 0; arrSpeed[0] = valSpeed; break; // З case 5: arrRoute[1] = 1; arrRoute[0] = 1; arrSpeed[1] = 0; arrSpeed[0] = 0; break; // Стоп case 6: arrRoute[1] = 1; arrRoute[0] = 1; arrSpeed[1] = valSpeed; arrSpeed[0] = 0; break; // В case 7: arrRoute[1] = 0; arrRoute[0] = 0; arrSpeed[1] = (valSpeed / 2); arrSpeed[0] = valSpeed; break; // Ю-З case 8: arrRoute[1] = 0; arrRoute[0] = 0; arrSpeed[1] = valSpeed; arrSpeed[0] = valSpeed; break; // Ю case 9: arrRoute[1] = 0; arrRoute[0] = 0; arrSpeed[1] = valSpeed; arrSpeed[0] = (valSpeed / 2); break; // Ю-В } // } // ======================================================================================================================================================= if (flg == 10){valSpeed = 5;} // 0 режим скорости else if(flg == 11){valSpeed = 30;} // 1 режим скорости else if(flg == 12){valSpeed = 55;} // 2 режим скорости else if(flg == 13){valSpeed = 80;} // 3 режим скорости else if(flg == 14){valSpeed = 105;} // 4 режим скорости else if(flg == 15){valSpeed = 130;} // 5 режим скорости else if(flg == 16){valSpeed = 155;} // 6 режим скорости else if(flg == 17){valSpeed = 180;} // 7 режим скорости else if(flg == 18){valSpeed = 205;} // 8 режим скорости else if(flg == 19){valSpeed = 230;} // 9 режим скорости else if(flg == 20){valSpeed = 255;} // 10 режим скорости // if (flg_LED) { // Если флаг установлен (была нажата кнопка включения фары) if (millis() - tmrLED > time_period) { // мигаем светодиодами с заданной частотой tmrLED = millis(); // сохраняем время digitalWrite(pinLED_RED, digitalRead(pinLED_BLUE)); // управляем питанием красного светодиода digitalWrite(pinLED_BLUE, !digitalRead(pinLED_BLUE)); // управляем питанием синего светодиода } // } else { // если флаг сброшен, то digitalWrite(pinLED_RED, LOW); // гасим светодиоды digitalWrite(pinLED_BLUE, LOW); // } // if (flgTime > millis()) { // Если millis() переполнен, то flgTime = 0; // сбрасываем флаг в ноль } // // ПОДАЧА ЗНАЧЕНИЙ СКОРОСТИ И НАПРАВЛЕНИЯ ВРАЩЕНИЯ НА ВЫВОДЫ // if (flgTime > (millis() - 500)) { // Если сигналы с телефона приходят (в течении 50 мс) digitalWrite(pinShield_H2, arrRoute[1]); // тогда задаем направление вращения правого мотора digitalWrite(pinShield_H1, arrRoute[0]); // и левого мотора analogWrite(pinShield_E2, arrSpeed[1]); // Задаём скорость вращения для правого мотора analogWrite(pinShield_E1, arrSpeed[0]); // и для левого мотора } else { // Если пакеты не приходят analogWrite(pinShield_E2, 0); // Останавливаем работу моторов analogWrite(pinShield_E1, 0); // } // } //
Ссылка для скачивания скетча.
В данном коде управление роботом осуществляется в три основных этапа: получение данных с телефона; изменение значений переменных arrSpeed, arrRoute; подача питания на моторы и задание направления их вращения. Так же в коде присутствуют дополнительные блоки: включение/выключение светодиодов; изменение скорости вращения колёс; вход в режим сопряжения.
- Получение данных с пульта:
- Данный блок начинается с оператора
if
, в условии которого написаноsoftSerial.available()
. Это условие будет верно, если в последовательный порт будут приходить данные с телефона, в противном случае условие будет ложно; - Далее следует еще один оператор
while
, условием которого опять являетсяsoftSerial.available()
. Если условие верно, то значение, поступившее в последовательный порт, будет записано в переменнуюstr
; задержка в 5 миллисекунд сделана для того, чтобы при низкой скорости передачи Arduino успел полностью прочитать значение из последовательного порта в переменнуюstr
;
- Данный блок начинается с оператора
- Изменение значений переменных arrSpeed, arrRoute:
- Данный блок начинается с оператора
if
, в условии которого написаноstr == XX
. В зависимости от значенияXX
, которое принимает переменнаяstr
(одно из 9 для основных функций), сбрасываетсяflgTime
– таймер начала выполнения функции, а так же устанавливается значение флагаflg
(от 1 до 9); - Далее следует конструкция
switch...case
, в которой операторswitch
сравнивает значение флагаflg
с операторомcase
и, в зависимости от значения флагаflg
, выполняет код, где задаётся, на какой мотор будет подано питание (переменнаяarrSpeed
) и с каким направлением вращения ( переменнаяarrRoute
);
- Данный блок начинается с оператора
- Подача питания на моторы и задание направления их вращения:
- Данный блок начинается с оператора
if
, в условии которого написаноflgTime > (millis() - 50)
. Это условие будет верно в течении 50 миллисекунд после начала приёма сигнала от телефона и установит на выводах Arduino значения переменныхarrSpeed
иarrRoute
. Если же сигнала в течении 50 миллисекунд не поступит, то операторelse
сбросит значение скорости в 0 и робот остановится;
- Данный блок начинается с оператора
- Включение/выключение светодиодов:
- Данный блок включает в себя 2 части: получение сигнала с телефона и изменение флага
flg_LED
; включение/выключение светодиодов; - Первая часть начинается с оператора
if
, в условии которого написано( str == "SWS" || str == "SwS")
. Условие будет верно, если значение переменнойstr
будет равноSWS
ИЛИSwS
, что приведёт к установке флагаflg_LED
в противоположное от нынешнего значение; - Вторая часть начинается с оператора
if
, в условии которого написано(flg_LED)
. Условие будет верно, если значение флагаflg_LED
будетtrue
, что приведёт к включению светодиодов. Если же значение флагаflg_LED
будетfalse
, то светодиоды погаснут.
- Данный блок включает в себя 2 части: получение сигнала с телефона и изменение флага
- Изменение скорости вращения колёс:
- Данный бок включает в себя 2 части: получение сигнала с телефона и изменение флага
flg
; изменение значения переменнойvalSpeed
; - Первая часть начинается с оператора
if
, в условии которого написаноstr == XX
. В зависимости от значенияXX
, которое принимает переменнаяstr
(одно из 11 для дополнительных функций), устанавливается значение флагаflg
(от 10 до 20); - Вторая часть начинается с оператора
if
, в условии которого написаноflg == XX
. В зависимости от значенияXX
, которое принимает переменнаяflg
(одно из 11 для дополнительных функций), устанавливается значение переменнойvalSpeed
(от 5 до 255);
- Данный бок включает в себя 2 части: получение сигнала с телефона и изменение флага
- Вход в режим сопряжения (выполняется при подаче питания на робота):
- Данный блок находится в коде
void setup()
и начинается с оператораif
, в условии которого написаноhc05.begin(softSerial)
. Это условие будет верно, если произошла успешная инициализация с Bluetooth модулем по шине UART, о чём будет выведено сообщение в монитор последовательного порта; - Далее происходит сброс таймера
tmrWait
и идёт проверка условия!hc05.checkConnect() && millis()<tmrWait 60000
в операторе циклаwhile
. До тех пор, пока не произойдёт сопряжения Bluetooth модуля робота и телефона И не истечёт минута(60 сек), модуль будет выполнять пустой цикл. - После цика
while
следует операторif
, в условии которого написаноmillis()<tmrWait 60000
. Условие будет верно, если одно из условие!hc05.checkConnect()
цикла while изменится на противоположное и произойдёт это раньше, чем через 60 секунд от подачи питания на робота. Тогда в монитор последовательного порта будет выведено сообщение о том, что сопряжение произошло с ранее созданной парой из памяти устройства. - Если по истечении минуты не произошло сопряжение ранее созданной пары, то далее следует оператор
else
, который выполняет вызов функцииcreateSlave("BT_CAR", "1234")
объектаhc05
, которая назначает Bluetooth модулю робота роль ведомого с именем “BT_CAR” и PIN-кодом “1234”, разрывает ранее установленную связь с мастером (если она была) и стирает список ранее созданных пар. После этого модуль начинает ожидать подключения мастера, который правильно укажет имя и PIN-код модуля. Об успешном или, наоборот, неудачном выполнении функции будет выведено сообщение в монитор последовательного порта.
- Данный блок находится в коде
Получение данных и работа с Trema-модулем Bluetooth HC-05 осуществляется через функции и методы объекта hc05 библиотеки iarduino_Bluetooth_HC05, с подробным описанием которых можно ознакомиться на странице Wiki – Trema-модуль bluetooth HC-05.
Подключаем bluetooth к машинке
Мы собираемся использовать модуль Bluetooth через SoftwareSerial (библиотеку SoftwareSerial.h), поэтому подключаем модуль блютуз к 3 и 4 цифровым пинам ардуино. RX к D3, TX к D4

Платформа робота готова! Теперь осталось загрузить прошивку для контроллера Ардуино и программу для смартфона RC CAR. Вы можете посмотреть на нашем сайте обзор Android приложений для работы с Arduino.
Схема подключения робота quadruped:
Соберите механику, подключите Tream-Power Shield, сервоприводы, датчик расстояния и откалибруйте робота, как это описано на странице Сборка QUADRUPED. Электроника Калибровка. Далее на боковые панели установите Bluetooth HC-05 и кнопку, первый модуль подключается к шине UART (в примере используется аппаратная шина UART), а второй к любому выводу Arduino Uno (в примере используется вывод D12).
Вы можете изменить выводы 2 и 3 для подключения датчика HC-SR04 на любые другие, указав их в скетче при объявлении объекта objSensor.
Сервоприводы | Trema Power Shield | |
---|---|---|
1 конечность | Горизонтальный сустав (№ 0) | вывод 4 на белой колодке |
Вертикальный сустав (№ 1) | вывод 5 на белой колодке | |
2 конечность | Горизонтальный сустав (№ 2) | вывод 6 на белой колодке |
Вертикальный сустав (№ 3) | вывод 7 на белой колодке | |
3 конечность | Горизонтальный сустав (№ 4) | вывод 8 на белой колодке |
Вертикальный сустав (№ 5) | вывод 9 на белой колодке | |
4 конечность | Горизонтальный сустав (№ 6) | вывод 10 на белой колодке |
Вертикальный сустав (№ 7) | вывод 11 на белой колодке |
Вы можете изменить выводы 4-11 для подключения сервоприводов на любые другие, указав их в скетче при объявлении массива объектов pinServo[8]. Трехпроводные шлейфы сервоприводов устанавливаются следующим образом:
- Оранжевый провод подключается к выводу на белой колодке.
- Красный провод подключается к выводу на красной колодке.
- Коричневый провод подключается к выводу на чёрной колодке.
Bluetooth | Trema Power Shield | |
---|---|---|
Bluetooth HC-05 | вывод RX | вывод TX на колодке Serial |
вывод TX | вывод RX на колодке Serial | |
вывод K (Key) | вывод A0 на белой колодке | |
вывод V (Vcc) | любой вывод на красной колодке | |
вывод G (GND) | любой вывод на чёрной колодке |
Вы можете изменить вывод A0 для подключения Bluetooth на любой другой, указав его в скетче при объявлении объекта objHC05.
Выводы RX и ТХ модуля подключаются проводами к выводам TX и RX колодки с надписью Serial. Трёхпроводной шлейф подключённый к выводам K, V, G, устанавливается следующим образом:
- Вывод K (Key) подключается к выводу на белой колодке.
- Вывод V (Vcc) подключается к выводу на красной колодке.
- Вывод G (GND) подключается к выводу на чёрной колодке.
Кнопка | Trema Power Shield | |
---|---|---|
Trema-кнопка | вывод S (Signal) | вывод 12 на белой колодке |
вывод V (Vcc) | любой вывод на красной колодке | |
вывод G (GND) | любой вывод на чёрной колодке |
Вы можете изменить вывод D12 для подключения кнопки на любой другой, указав его в скетче при определении константы pinK.
Трёхпроводной шлейф подключённый к выводам S, V, G, устанавливается следующим образом:
- Вывод S (Signal) подключается к выводу на белой колодке.
- Вывод V (Vcc) подключается к выводу на красной колодке.
- Вывод G (GND) подключается к выводу на чёрной колодке.
Представленная ниже схема совпадает со схемой из инструкции по сборке QUADRUPED, но к ней добавились два модуля: bluetooth (подключается к выводам A0, TX и RX) и кнопка (подключается к выводу D12).
Элементы схемы: «Э0»…«Э7» – сервоприводы, «Э8» – датчик расстояния, «Э9» – Trema bluetooth модуль, «Э10» Trema кнопка.
Схема электропитания робота автомобиля
Вопрос организации правильного стабильного электропитания является одним из самых важных в любом проекте.В нашей модели применена рекомендованная нами схема питания, основанная на использовании литийионных аккумуляторов формата 18650 и платы защиты их от переразряда и перезаряда.
Давайте разберем самый простой вариант схемы питания электромоторов. Перед началом сборки лучше заранее припаять провода к моторам.

Все достаточно стандартно и вы найдете в интернете десятки подобных примеров. Но в этой схеме есть большой минус – в случае полного разряда аккумуляторы придут в негодность.

Для добавления контроллера разряда придется внести следующие изменения в схему:

Теперь аккумуляторы будут защищены, но здесь нет возможности заряжать их.

Для зарядки можно использовать модуль повышения напряжения с 5v до необходимого уровня зарядки, который зависит от количества серий используемых аккумуляторов. Он имеет гнездо типа микро USB и при частом использовании оно может сломаться, поэтому мы рекомендуем установить дополнительное гнездо для последующей подзарядки пяти вольтовым блоком питания. Для зарядки двух литий-ионных аккумуляторов необходимо настроить выходное напряжение на 8,4 Вольта.
