Управление машинкой через блютуз

Простая Bluetooth машинка на Arduino

Широкое распространение и дешевизна платформы 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 модулю. Примерно так:

image

Далее нажимаем на кнопку «Blocks» в правом верхнем углу и все тем же методом перетаскивания элементов создаем логику работы нашего android-приложения примерно вот так:

image

Теперь остается скомпилировать приложение, нажав на кнопку «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, которые не поддерживают прозрачный фон. Например, сделать такой дизайн за полчаса или час сможет любой неподготовленный человек:

Читайте также:  Потоковое аудио через bluetooth

image

P.S. Для тех, кто не сталкивался с разработкой приложений в App Inventor 2, я сделал более подробный гайд по разработке этого приложения (для просмотра нужно перейти на ютуб).

P.P.S. Сборник из более 100 обучающих материалов по ардуино для начинающих и профи тут.
Онлайн курс по ардуино на гиктаймс здесь.
UPD 1.02.2017: выложил приложение на play market.
Аналогичные проекты с другими шилдами здесь.

Источник

CxemCAR на Arduino — Bluetooth управление машинкой с Android

Arduino CxemCAR
Первая часть статьи проекта CxemCAR находится здесь. Там же находятся исходники для Android и другая полезная информация. В этой статье я покажу сборку CxemCAR для платформы Arduino. В качестве платы Arduino можно использовать практически любую Arduino-совместимую плату: UNO, Nano, Mega, Leonardo и даже на основе STM32 — Arduino DUE. Я использовал платку Arduino Nano V3, приобретенную на eBay за 9$. Схема подключения Arduino к Bluetooth модулю HC-06 и драйверу двигателей L298N: Схема подключения Arduino к Bluetooth-модулю и драйверу двигателей
В схеме я использовал джампер (на схеме Jmp1), т.к. при подключенном Bluetooth модуле невозможно было загрузить скетч в Arduino. На время прошивки, снятием перемычки обесточивается Bluetooth-модуль. В качестве платформы я использовал небольшую RC DIY платформу, купленную на eBay за 25$. Сама платформа представляет из себя алюминиевое основание, куда крепится два двигателя, редуктор и 4 карданные передачи для 4-х колес. Сверху, на 3-х стойках ставится макетная плата. Платформа RC DIY Mini
Платформа не отличается высоким качеством изготовления. После того, как я ее собрал, попробовал подключить питание — двигателя даже не шевельнулись, много перекосов, недоработок и т.п. Пришлось все разбирать, немного ослабить крепления, кое-где подточить, хорошо все промазать смазкой, а также снял 2 кардана с передней оси. Получилась заднеприводная версия машинки. После этого, я припаял Bluetooth-модуль к Arduino и вывел для него светодиод состояния. О разновидностях Bluetooth модулей, их подключении к Arduino, работы с ними и т.п. можете почитать в данной статье: Arduino и Bluetooth. Модуль HC-06 поместил в термоусадочную трубку 10мм. Светодиод Bluetooth-состояния с токоограничительным резистором также были помещены в термоусадку, но более тонкую — 5мм. Подключаем Bluetooth модуль
В макетной плате, которая шла вместе с платформой, я просверлил отверстия и закрепил драйвер двигателей L298N. Плату Arduino прикрепил при помощи двухстороннего скотча. CxemCAR
Между алюминиевой платформой машинки и макетной платой я разместил 3 Li-Po аккумулятора 3.7В 1100 мА*Ч. Питание контроллера и двигателей раздельное: Arduino запитывается от одного аккумулятора 3.7В, а моторчики и драйвер L298N от двух последовательно соединенных аккумуляторов 3.7В. Предусмотрено два 2-х позиционных выключателя питания — в одном положение питание идет от аккумуляторов к потребителям, в другом положении на клеммы зарядки. Фото машинки на подзарядке: Зарядка аккумуляторов машинки
Программное обеспечение Программа писалась в среде Arduino IDE 1.01. Код программы я постарался хорошо прокомментировать, но если будут вопросы — спрашивайте на форуме, в теме поддержке проекта CxemCAR .

#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[4]; // строковый массив для данных левого мотора L byte L_index = 0; // индекс массива char R_Data[4]; // строковый массив для данных правого мотора R byte R_index = 0; // индекс массива char H_Data[1]; // строковый массив для доп. канала byte H_index = 0; // индекс массива H char F_Data[8]; // строковый массив данных для работы с 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[3]; var_Data[0] = EEPROM.read(1); var_Data[1] = EEPROM.read(2); var_Data[2] = 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[L_index] = incomingByte; // сохраняем каждый принятый байт в массив L_index++; // увеличиваем текущий индекс массива >else if(command == cmdR && incomingByte != cmdR) < R_Data[R_index] = incomingByte; R_index++; >else if(command == cmdH && incomingByte != cmdH) < H_Data[H_index] = incomingByte; H_index++; >else if(command == cmdF && incomingByte != cmdF) < F_Data[F_index] = 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[0],F_Data[1],F_Data[2],F_Data[3],F_Data[4]); >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 по USART от Bluetooth модуля получает готовые данные для левого и правого двигателя. Т.е. все основные расчеты происходят в Android приложении. Код Arduino на GitHub

Читайте также:  Acer aspire 5750zg есть ли блютуз

Источник

Оцените статью
Adblock
detector