Автономная "смарт" машина на Arduino. Что такое Н-мост? Определение угла поворота
Там же находятся исходники для Android и другая полезная информация. В этой статье я покажу сборку CxemCAR для платформы Arduino. В качестве платы Arduino можно использовать практически любую Arduino-совместимую плату: UNO, Nano, Mega, Leonardo и даже на основе STM32 - Arduino DUE. Я использовал платку Arduino Nano V3, приобретенную на eBay за 9$.
Схема подключения Arduino к Bluetooth модулю HC-06 и драйверу двигателей L298N:
В схеме я использовал джампер (на схеме Jmp1), т.к. при подключенном Bluetooth модуле невозможно было загрузить скетч в Arduino. На время прошивки, снятием перемычки обесточивается Bluetooth-модуль.
В качестве платформы я использовал небольшую RC DIY платформу, купленную на за 25$. Сама платформа представляет из себя алюминиевое основание, куда крепится два двигателя, редуктор и 4 карданные передачи для 4-х колес. Сверху, на 3-х стойках ставится макетная плата.
Платформа не отличается высоким качеством изготовления. После того, как я ее собрал, попробовал подключить питание - двигателя даже не шевельнулись, много перекосов, недоработок и т.п. Пришлось все разбирать, немного ослабить крепления, кое-где подточить, хорошо все промазать смазкой, а также снял 2 кардана с передней оси. Получилась заднеприводная версия машинки.
После этого, я припаял Bluetooth-модуль к Arduino и вывел для него светодиод состояния. О разновидностях Bluetooth модулей, их подключении к Arduino, работы с ними и т.п. можете почитать в данной статье: . Модуль HC-06 поместил в термоусадочную трубку 10мм. Светодиод Bluetooth-состояния с токоограничительным резистором также были помещены в термоусадку, но более тонкую - 5мм.
В макетной плате, которая шла вместе с платформой, я просверлил отверстия и закрепил драйвер двигателей L298N. Плату Arduino прикрепил при помощи двухстороннего скотча.
Между алюминиевой платформой машинки и макетной платой я разместил 3 Li-Po аккумулятора 3.7В 1100 мА*Ч. Питание контроллера и двигателей раздельное: Arduino запитывается от одного аккумулятора 3.7В, а моторчики и драйвер L298N от двух последовательно соединенных аккумуляторов 3.7В. Предусмотрено два 2-х позиционных выключателя питания - в одном положение питание идет от аккумуляторов к потребителям, в другом положении на клеммы зарядки.
Фото машинки на подзарядке:
Программное обеспечение
Программа писалась в среде Arduino IDE 1.01. Код программы я постарался хорошо прокомментировать, но если будут вопросы - спрашивайте на форуме, в .
#include "EEPROM.h" #define D1 2 // направление вращение двигателя 1 #define M1 3 // ШИМ вывод для управления двигателем 1 (левый) #define D2 4 // направление вращение двигателя 2 #define M2 5 // направление вращение двигателя 2 (правый) #define HORN 13 // доп. канал 1 подключен к 13 пину //#define autoOFF 2500 // кол-во миллисекунд через которое робот останавливается при потери связи #define cmdL "L" // команда UART для левого двигателя #define cmdR "R" // команда UART для правого двигателя #define cmdH "H" // команда UART для доп. канала 1 (к примеру сигнал Horn) #define cmdF "F" // команда UART для работы с EEPROM памятью МК для хранения настроек #define cmdr "r" // команда UART для работы с EEPROM памятью МК для хранения настроек (чтение) #define cmdw "w" // команда UART для работы с EEPROM памятью МК для хранения настроек (запись) char incomingByte; // входящие данные char L_Data; // строковый массив для данных левого мотора L byte L_index = 0; // индекс массива char R_Data; // строковый массив для данных правого мотора R byte R_index = 0; // индекс массива char H_Data; // строковый массив для доп. канала byte H_index = 0; // индекс массива H char F_Data; // строковый массив данных для работы с EEPROM byte F_index = 0; // индекс массива F char command; // команда: передача координат R, L или конец строки unsigned long currentTime, lastTimeCommand, autoOFF; void setup() { Serial.begin(9600); // инициализация порта pinMode(HORN, OUTPUT); // дополнительный канал pinMode(D1, OUTPUT); // выход для задания направления вращения двигателя pinMode(D2, OUTPUT); // выход для задания направления вращения двигателя /*EEPROM.write(0,255); EEPROM.write(1,255); EEPROM.write(2,255); EEPROM.write(3,255);*/ timer_init(); // инициализируем программный таймер } void timer_init() { uint8_t sw_autoOFF = EEPROM.read(0); // считываем с EEPROM параметр "включена ли ф-ия остановки машинки при потере связи" if(sw_autoOFF == "1"){ // если таймер останова включен char var_Data; var_Data = EEPROM.read(1); var_Data = EEPROM.read(2); var_Data = EEPROM.read(3); autoOFF = atoi(var_Data)*100; // переменная автовыкл. для хранения кол-ва мс } else if(sw_autoOFF == "0"){ autoOFF = 999999; } else if(sw_autoOFF == 255){ autoOFF = 2500; // если в EEPROM ничего не записано, то по умолчанию 2.5 сек } currentTime = millis(); // считываем время, прошедшее с момента запуска программы } void loop() { if (Serial.available() > 0) { // если пришли UART данные incomingByte = Serial.read(); // считываем байт if(incomingByte == cmdL) { // если пришли данные для мотора L command = cmdL; // текущая команда memset(L_Data,0,sizeof(L_Data)); // очистка массива L_index = 0; // сброс индекса массива } else if(incomingByte == cmdR) { // если пришли данные для мотора R command = cmdR; memset(R_Data,0,sizeof(R_Data)); R_index = 0; } else if(incomingByte == cmdH) { // если пришли данные для доп. канала 1 command = cmdH; memset(H_Data,0,sizeof(H_Data)); H_index = 0; } else if(incomingByte == cmdF) { // если пришли данные для работы с памятью command = cmdF; memset(F_Data,0,sizeof(F_Data)); F_index = 0; } else if(incomingByte == "\r") command = "e"; // конец строки else if(incomingByte == "\t") command = "t"; // конец строки для команд работы с памятью if(command == cmdL && incomingByte != cmdL){ L_Data = incomingByte; // сохраняем каждый принятый байт в массив L_index++; // увеличиваем текущий индекс массива } else if(command == cmdR && incomingByte != cmdR){ R_Data = incomingByte; R_index++; } else if(command == cmdH && incomingByte != cmdH){ H_Data = incomingByte; H_index++; } else if(command == cmdF && incomingByte != cmdF){ F_Data = incomingByte; F_index++; } else if(command == "e"){ // если приняли конец строки Control4WD(atoi(L_Data),atoi(R_Data),atoi(H_Data)); delay(10); } else if(command == "t"){ // если приняли конец строки для работы с памятью Flash_Op(F_Data,F_Data,F_Data,F_Data,F_Data); } lastTimeCommand = millis(); // считываем текущее время, прошедшее с момента запуска программы } if(millis() >= (lastTimeCommand + autoOFF)){ // сравниваем текущий таймер с переменной lastTimeCommand + autoOFF Control4WD(0,0,0); // останавливаем машинку } } void Control4WD(int mLeft, int mRight, uint8_t Horn){ bool directionL, directionR; // направление вращение для L298N byte valueL, valueR; // значение ШИМ M1, M2 (0-255) if(mLeft > 0){ valueL = mLeft; directionL = 0; } else if(mLeft < 0){ valueL = 255 - abs(mLeft); directionL = 1; } else { directionL = 0; valueL = 0; } if(mRight > 0){ valueR = mRight; directionR = 0; } else if(mRight < 0){ valueR = 255 - abs(mRight); directionR = 1; } else { directionR = 0; valueR = 0; } analogWrite(M1, valueL); // задаем скорость вращения для L analogWrite(M2, valueR); // задаем скорость вращения для R digitalWrite(D1, directionL); // задаем направление вращения для L digitalWrite(D2, directionR); // задаем направление вращения для R digitalWrite(HORN, Horn); // дополнительный канал } void Flash_Op(char FCMD, uint8_t z1, uint8_t z2, uint8_t z3, uint8_t z4){ if(FCMD == cmdr){ // если команда чтения EEPROM данных Serial.print("FData:"); // посылаем данные с EEPROM Serial.write(EEPROM.read(0)); // считываем значение ячейки памяти с 0 адресом и выводим в UART Serial.write(EEPROM.read(1)); Serial.write(EEPROM.read(2)); Serial.write(EEPROM.read(3)); Serial.print("\r\n"); // маркер конца передачи EEPROM данных } else if(FCMD == cmdw){ // если команда записи EEPROM данных EEPROM.write(0,z1); // запись z1 в ячейку памяти с адресом 0 EEPROM.write(1,z2); EEPROM.write(2,z3); EEPROM.write(3,z4); timer_init(); // переинициализируем таймер Serial.print("FWOK\r\n"); // посылаем сообщение, что данные успешно записаны } }
В коде используется библиотека для работы с EEPROM памятью AVR. В памяти хранится одна настройка: количество миллисекунд через которое машинка останавливается при потери связи. Можно эту настройку "жестко" прописать в программе, для этого раскомментируйте строчку #define autoOFF 2500 (где 2500 кол-во миллисекунд). После этого, функцию Flash_Op можно удалить, также необходимо будет внести небольшие правки в код, отвечающий за прием команд для работы с EEPROM-памятью.
Подробная история того, как из трех двигателей была собрана машина на Arduino, управляемая Android-устройством по Bluetooth. В нескольких десятках абзацев постараюсь максимально пошагово изложить, куда подключить каждый из проводов, как написать фирменное приложение и на каких детских граблях пришлось попрыгать больше недели.Немного об уровне, авторе и предостережения
Я, автор, пацан 16-17 лет с подмосковной деревни, специализируюсь на написании android-приложений (а там сложнее что-то сжечь), поэтому ответственность за оптимальный подход к решению задач с себя снимаю.Задача
Задача легчайшая – заставить ездить машинку, управляемую Arduino, а пульт заменить андроидом. Но в большинстве моментов пришлось изобретать колесо, потому что в интернетах подходящего решения найдено не было.Понадобится
- Arduino
- Motor Shield (в моем случае две)
- Bluetooth
- Android
- Провода обычные
Основа конструкции
За основу была взята машина Lego Outdoor Challenger (в реальности выглядит менее пафосно). Все, что от нее осталось: корпус (все элементы украшения сняты) и три двигателя.У машинки была своя плата, но одна из задач подразумевала универсальность: это сделал я, это смогут повторить другие. Мозги вынул, поставил Arduino Uno.
Установка Arduino
Создатели почему-то не предусмотрели места для Arduino, потому крепил на шурупы, просверлив пластик. Под плату подложил фанеру, чтобы ничего не закоротило. Под шурупы лучше подсунуть что-то пластиковое (кусочек бутылки), ибо плата от железный болтов не защищена.Поверх платы сразу поставил две motor shiled, так надо. Чтобы управлять второй, придется прокинуть один провод с любого digital порта на H1 (направление) и второй с пина с поддержкой шима (помечены знаком «~», обычно 10, 11) на E1 (скорость).
Определение угла поворота
За поворот машинки отвечает на удивление не сервопривод, а обычный двигатель. Встает проблема: хорошо бы было его не сжечь, ведь угол поворота ограничен, а крутиться двигатель может сколько угодно.Вариант с методом тыка отпадает, так как при разном уровне батареи количество тока, подаваемое на двигатель, будет изменяться, что приведет к постоянно меняющемуся углу. Крутить до упора тоже нельзя, рано или поздно рассыплются шестеренки.
Решение проблемы: отслеживать угол через замыкание. На фото продемонстрирована небольшая штучка, которая крепится недалеко от поворотного механизма. На часть, которая крутится вместе с колесами влево/вправо двигателем, прикрепляется гребешок с железными контактами.
Принцип работы: к каждой линии припаивается провод (всего их четыре), нижний подключается к плюсу (он зажат гребешком всегда, см. картинку), остальные провода уходят на минус. Когда зубик гребешка попадает и на нижний ряд, и на, допустим, третий, происходит замыкание, ток течет, это замечает Arduino.
Благодаря различным комбинациям трех полос, можно определить до семи углов. Например, когда ток есть на всех линиях, колеса повернуты в крайнее правое положение, когда ток есть только на верхней, колеса повернуты максимально влево. В таблице предоставлены все варианты.
Подключение угла и код
Для каждого уровня был выбран свой цвет: нижний – зеленый, первый снизу – красный, второй – черный, третий – белый. На начальном этапе использовались breadboard и светодиоды для визуальной отладки.Схема подключения показана на рисунке. Плюс тянем к зеленому, остальные протягиваем к минусу. Через резистор, установленный для устранения помех и отсутствия КЗ, подключаем провода к выходам A0-A2. Выбраны они просто из экономии остальных портов.
Код дан с комментариями. Подключаем пины и опрашиваем их через digitarRead(). Если напряжение есть, вернется значение true. Далее смотрим, если результат означает, что колеса в крайних положениях, запрещаем дальнейший поворот в эту сторону.
Небольшая хитрость: поскольку выходы на 5В и 3.3В понадобятся в будущем, можно поставить плюс на один из digital-пинов. Перед каждой проверкой угла выдавать ток через digitalWrite(whitePin), потом проверять угол и убирать ток.
Int speedTurn = 180; //скорость поворота, от 0 до 255 //пины для определения поворота int pinRed = A0; int pinWhite = A1; int pinBlack = A2; int pinAngleStop = 12; //выводит ток на светодиод, если достигнут максимальный угол, нужен //только для отладки void setup() { //пины поворота на считывание pinMode(pinRed, INPUT); pinMode(pinBlack, INPUT); pinMode(pinWhite, INPUT); //светодиод pinMode(pinAngleStop, OUTPUT); //пины драйвера двигателя, направление и скорость pinMode(angleDirection, OUTPUT); pinMode(angleSpeed, OUTPUT); Serial.begin(9600); } //функция вызывается из loop(), когда приходит команда с андроида void turn(int angle) { digitalWrite(pinAngleStop, HIGH); //выдаем ток на провод, подключенный к плюсу delay(5); //немного ждем, чтобы ток "успел" дойти if(angle > 149) { if(digitalRead(pinWhite) == HIGH && digitalRead(pinBlack) == LOW && digitalRead(pinBlack) == LOW) { //если достигнуто крайне правое положение, выйти из функции не подавая ток, чтобы не //сжечь мотор return; } //если угол не максимальный, поворачиваем digitalWrite(angleDirection, HIGH); analogWrite(angleSpeed, speedTurn); } else if (angle < 31) { if(digitalRead(pinRed) == HIGH && digitalRead(pinBlack) == HIGH && digitalRead(pinWhite) == HIGH) { //если достигнуто крайне левого положение, выйти из функции не подавая ток, чтобы не //сжечь мотор return; } //если угол не максимальный, поворачиваем digitalWrite(angleDirection, LOW); analogWrite(angleSpeed, speedTurn); } digitalWrite(pinAngleStop, LOW); //убираем ток с определителя угла delay(5); }
Распараллеливание ходовых колес
Изначально два ходовых двигателя соединены вместе. Их рассоединил по двум причинам: поворот эффективней, если колеса крутятся в разные стороны, и два мощных двигателя одна плата не вытянет.Проблема: у motor shield два выхода, каждый из которых выдает до 2 ампер. Каждый двигатель ест по 0,7А. Вроде меньше, но не при максимальных нагрузках. Допустим, машинка застряла в песке или уперлась, ток возрастает выше ампера. Не критично, но потенциально опасно.
А вот критичным оказалось то, что плата греется. Через минуты полторы после заезда, motor shield нагревалась и начинала работать безобразно: токи подаются не те, колеса не крутятся и прочее.
Решение обоих проблем: один двигатель подключил к одной motor shield, второй – к другой. Как ни странно, помогло. Температура упала, перегрев отсутствует. Можно было поставить радиатор, но крепить тяжело.
Подключение Bluetooth
Я использовал модель HC-05, что сыграло роковую шутку. Подключаются все блютузы одинаково: один провод на 3.3В (иногда начинал работать только от 5В), второй на минус, еще два на порт 0 и 1 (чтение и отправка соответственно). Провод, подписанный RXD на bluetooth, втыкается в TXD ардуино, а TXD в RXD (если перепутаете, то данных не увидите).Есть оговорка: порты 0 и 1 по умолчанию используются Serial, через который заливает скетч. То есть, пока воткнут блютуз, скетч не зальется. Есть два выхода: вынимать блютуз на время заливки или переназначить входы и выходы блютуза. Второй вариант осуществляется двумя строчками
#include
Подводный камень, съевший у меня трое суток работы – скорость общения. По привычке установил 9600 и пошел пробовать. То данные не приходили, то была каша символов. И в конце концов ответ – модель HC-05 общается на 38400! Очень сильно обратите внимание на то, что в Setup() я выполню BTSerial.begin(39400), хотя Serial.begin(9600).
Система отправки команд
Статья становится слишком длинной, поэтому рассмотрение кода Arduino и Android вынесу в отдельную вторую часть, а сейчас опишу принцип.На андроид устройстве есть джойстик (круг, о реализации которого также во второй части). Андроид считывает показания с него и конвертирует их в подходящие для ардуино числа: скорость из пикселей превращает в значение от -255 до 255 (отрицательные – задний ход), а также определяет угол. Я сознательно отдал эту задачу телефону, так как он куда мощнее и спокойно справится с подсчетом нескольких сотен значений в секунду.
После установки сокета данные отправляются в следующем формате: @скорость#*угол#. @ - говорит о том, что следующие цифры содержат скорость, # - извещает об окончании значения скорости, * - начало значения угла, # - закончить запись угла. Цикл бесконечен, команды отправляются каждые 100 миллисекунд (цифра подобрана оптимальная). Если ничего не нажато на андроиде, то ничего и не отправляется.
Алгоритм приема данных подробно описан в коде скетча. Он не раз переписывался и, как по мне, работает идеально.
Заключение первой части
В этой статье я попытался раскрыть все, что касается физической части машинки. Вероятнее всего, что-то упустил, так что обязательно спрашивайте.Но самое интересное, как по мне, осталось на второе – программа Arduino и приложение на Android, там творится настоящая магия, по крайней мере, для молодого меня.
Если вы не найдете ответа на какую-то часть и захотите потыкать меня в недостатки лично, жду – [email protected], .
UPD: вторая часть уже вышла -
Широкое распространение и дешевизна платформы Arduino и различных робоплатформ позволило любителям создавать радиоуправляемые машинки на любой вкус. А широкое распространение смартфонов позволило использовать их в качестве контроллеров этих машинок. Главной проблемой для многих любителей Arduino является отсутствие опыта в программировании под Android. Сегодня я расскажу, как легко решить эту проблему, используя среду визуальной разработки android-приложений App Inventor 2.
Постройку любой машинки надо начинать с «железа», поэтому вкратце опишу, что использовал для своей машинки:
arduino nano
bluetooth module HC-05
Z-Mini Motor Sensor Shield L293D
2WD Motor Chassis
Конфигурация «железа» не играет большой роли в этом проекте, поэтому шасси, шилд и саму ардуино можно заменить на любые аналоги.
Теперь перейдем к созданию приложения для Android. App Inventor - среда визуальной разработки android-приложений, работает из браузера. Заходим на сайт, разрешаем доступ к своему аккаунту в Google, нажимаем кнопку «create» и создаем новый проект. В новом проекте методом «Drag and Drop» создаем 4 кнопки для выбора направления движения и одну для подключения к нашему bluetooth модулю. Примерно так:
Теперь остается скомпилировать приложение, нажав на кнопку «Build».
С написанием скетча я думаю у любителей ардуино проблем не возникнет, скажу лишь, что можно взять выбрать из готовых скетчей, где управление машинкой осуществляется с компьютера по sireal порту. Я использовал этот
скетч
int val;
int IN1 = 4;
int IN2 = 7;
int EN1 = 6;
int EN2 = 5;
Void setup()
{
Serial.begin(9600);
pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(EN1, OUTPUT);
pinMode(EN2, OUTPUT);
}
void loop()
{
if (Serial.available())
{
val = Serial.read();
// Задаём движение вперёд
if (val == "W") // При нажатии клавиши «W»
{
// Выводы конфигурируются согласно работе Motor Shield"а
// Моторы крутятся вперед
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, HIGH);
}
// Задаём движение назад
if (val == "S")
{
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
}
// Задаём движение вправо
if (val == "D")
{
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
}
// Задаём движение влево
if (val == "A")
{
digitalWrite(EN1, HIGH);
digitalWrite(EN2, HIGH);
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
}
// Стоп режим
// При отпускании клавиш в программе в порт шлется «T»
if (val == "T") // При нажатии клавиши «T»
{
// Выводы ENABLE притянуты к минусу, моторы не работают
digitalWrite(EN1, LOW);
digitalWrite(EN2, LOW);
}
}
}
Итак, вот такая у меня получилась машинка:
Те, кому нравится дизайн в приложениях, могут немного поменять. Подробно описывать как это делать не буду, там не сложно самому разобраться. Скажу лишь, что для этого в основном нужно использовать.png файлы, вместо.jpeg, которые не поддерживают прозрачный фон. Например, сделать такой дизайн за полчаса или час сможет любой неподготовленный человек:
P.S. Для тех, кто не сталкивался с разработкой приложений в App Inventor 2, я сделал более подробный гайд по разработке этого приложения (для просмотра нужно перейти на ютуб).
P.P.S. Сборник из более 100 обучающих материалов по ардуино для начинающих и профи
Машинка на Ардуино с Bluetooth управлением от Android телефона — это очень простой, но интересный проект на Arduino UNO с использованием модуля Motor Shield. На этой странице вы узнаете какие потребуются компоненты для изготовления робота машинки на Ардуино своими руками, пошаговую инструкцию по сборке электрической схемы и сможете скачать все необходимые программы для Android и Arduino.
Видео. Машинка на блютуз управлении ардуино
Для этого проекта использовался модуль Motor Shield L293D , два колеса с редукторами, плата Arduino UNO, блютуз модуль HC-05 и два светодиода для фар. Управление происходит дистанционно через Bluetooth сигнал от смартфона или планшета. После сборки модели и установки программ, вы сможете через приложение на смартфоне поворачивать машинкой, ездить вперед и назад, включать и выключать фары.
Машинка на Ардуино своими руками
Для этого проекта нам потребуется:
- плата Arduino UNO;
- Motor Control Shield L293D;
- Bluetooth модуль HC-05/06;
- два мотора с редукторами и колесами;
- аккумулятор на 9В (крона);
- 2 резистора и 2 светодиода;
- корпус и колеса от старой машинки;
- паяльник, термопистолет, канцелярский нож;
- провода, припой и изолента.
Схема сборки машинки на Ардуино
Если у вас есть все необходимые детали (в проекте можно обойтись без светодиодов и резисторов), то далее мы рассмотрим, как сделать машинку из ардуино своими руками. Для начала следует припаять к контактам моторчиков провода и зафиксировать их изолентой, чтобы контакты не оторвались. Провода необходимо соединить с клеммниками M1 и M2 на Motor Shield (полярность потом можно будет поменять).
Питание на Bluetooth модуль идет от контактов для сервопривода, в проекте серво нам не понадобятся. А на питание идет стабилизированное напряжение 5 Вольт, что нам подходит. К портам TX и RX удобнее будет припаять коннекторы «мама», а к портам «Pin0» и «Pin1» на Motor Shield припаять штырьки (BLS). Таким образом, вы сможете легко отключать Bluetooth модуль от Arduino при необходимости загрузки скетча.
Управление светодиодами идет от порта «Pin2», здесь провод можно припаять напрямую к порту. Если вы делаете несколько машинок с Блютуз, которыми будете управлять одновременно, то рекомендуем сделать перепрошивку модуля HC-05 . Делается прошивка модуля очень просто, а затем вы уже не будете путать машинки, так как у каждой будет отображаться свое уникальное имя на Андроиде.
Приложение и скетч для машинки на Ардуино
После сборки схемы загрузите следующий скетч для машинки (не забудьте отключать Bluetooth модуль от Ардуино при загрузке) и установите приложение на смартфоне. Все файлы для проекта (библиотека AFMotor.h, скетч для машинки и приложение для Android) можно скачать одним архивом по прямой ссылке .
#includeПояснения к коду:
- Для тестирования, можно отправлять команды с компьютера через USB;
- Вращение моторов при подключении к аккумулятору будут отличаться;
- Вы можете задавать свою скорость вращения моторами.
После проверки работы машинки, установите приложение на смартфон или планшет. При первом подключении к Bluetooth модулю HC-05/06, потребуется сделать сопряжение с Андроид (затем сопряжение будет выполняться автоматически). Если у вас возникли сложности с подключением — прочитайте эту статью