Реклама ⓘ
Главная » Радиоуправление
Призовой фонд
на апрель 2024 г.
1. 100 руб.
От пользователей

Похожие статьи:


Реклама ⓘ

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

Прикрепленные файлы:

Теги:

Опубликована: 06.01.2013 Изменена: 19.07.2013 0 3
Я собрал 1 0
x

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

  • Техническая грамотность
  • Актуальность материала
  • Изложение материала
  • Полезность устройства
  • Повторяемость устройства
  • Орфография
0

Средний балл статьи: 0 Проголосовало: 0 чел.

Комментарии (53) | Я собрал (0) | Подписаться

0
MaFiX #
Эту программу под iOS делать сможете? Просто есть iPad.
Ответить
0

[Автор]
talibanich #
А у меня просто нет iPad
Ответить
0
Артём #
А как установить программу? Не получается.
Ответить
0

[Автор]
talibanich #
Еще раз: под iPad'ы я не делал приложение. Android приложения насколько я знаю под iOS запустить нельзя. Соответственно не вижу смысла устанавливать на iPad'ы это ПО.
Ответить
-1
Mark 42 #
А как на Android?
Ответить
0

[Автор]
talibanich #
Вы не знаете как установить на Android приложение?
http://bit.ly/1w9TuZm
Ответить
0
Mark 42 #
Нет. Надо скачать по сыллке указанной в проекте или както по другому?
Ответить
0

[Автор]
talibanich #
Скачать APK файл и установить его в устройство с ОС "Android". Готовый APK можно взять либо со статьи, либо в проекте на гитхабе.
Ответить
0
Александр #
Меня интересует а управление по модулю NRF24L01+ возможно? Вместо БТ. И управление к примеру 3-4 машинками с Android с ОС по координатам?
Ответить
0

[Автор]
talibanich #
Да возможно
Ответить
0
spymixer911 #
С телефона нельзя, это не вай-фай! Можно сделать просто пульт сразу для 4-х устройств
Ответить
0
Тарас #
Вопросик по платформе. Немного не понял чем фиксируются двигатели, они прижимаются макетной платой?
Ответить
0

[Автор]
talibanich #
Движки надежно прикручиваются болтами с торцов.
Ответить
0
Олег Гільжинський #
Сколько часов работает ваш аккумулятор 3,7v на 1100mAh ?
Ответить
0
Олег Гільжинський #
Я сейчас делаю подобную машинку с 4-ма движками и лёгкой платформой из пластика. Сколько и каких аккумуляторов надо и как их подключить?
Ответить
0

[Автор]
talibanich #
Все зависит от конкретной реализации. Нужно учитывать напряжение питания двигателей, контроллера и т.п.
Ответить
0
Эльдар #
Ардуино стабильно работает от 3.7в 1s? Или лучше 5в подать?
Ответить
0

[Автор]
talibanich #
У меня никаких проблем при питании от 3.7В не было
Ответить
0
Олег Гільжинський #
3.7В давай, а то блютуз модулю не поздоровится
Кто скажет, если я подаю на l298n 6В, то сколько будет на выходе?
Ответить
0
Сёма #
Люди помогите, такая проблема (сразу скажу что я начинающий)купил L298N вот такой http://www.geekonfire.com/wiki/index.php?title=Dual_H-Bridge_Motor_Driver теперь не знаю как подключить к Ардуино Нано, здесь на схеме надо IN1,IN2,IN3,IN4 а у меня ещё ENA и ENB теперь надо или программу переписывать или можно ENA и ENB на 5вольт подвесить?
Ответить
0

[Автор]
talibanich #
Ответить
0
Антон #
У меня плата Arduino UNO. Там код будет такой же, только выходы нужно будет заменить, или ещё какие-то изменения нужно будет внести?
Ответить
0

[Автор]
talibanich #
Все тоже.
Ответить
0
Евгений #
У меня вот такой драйвер. Новый двойной H мост постоянного тока шагового двигателя привода совета модуль L298N для arduino. По 13 уроку и по скетчу я так понимаю что нужно enb и ena подвесить на 5 вольт?
Прикрепленный файл: IMG_20160216_090143_-1473864863.jpg
Ответить
0
Олег Гільжинський #
Как подключить питание? Не понимаю почему к l298n минус с одного аккумулятора, а плюс с другого? Тогда же не будет круга для второго аккумулятора. Почему нельзя ардуину к 1 акку, а l298n ко второму?
Ответить
0

[Автор]
talibanich #
Arduino и двигатель (плюс драйвер L298N) питаются разными источниками питания. Смотрите внимательнее схему, общий один, а плюсы подключаются каждый к своему потребителю.
Если проблемы с пониманием, то попробуйте запитать от одного источника, но от броска тока могут быть лаги ардуино платки. Можно применить фильтр.
Ответить
0
никита #
А минус от 3 аккумляторов вместе?
Ответить
0
Сергей #
А можно вместо Bluetooth модуля использовать USB Bluetooth адаптер? Как-нибудь подпаяться что-ли?
Ответить
0

[Автор]
talibanich #
Отвечу коротко: в данном случае нельзя, просто подпаяться тоже нельзя.
Ответить
0
Сергей #
А если использовать Bluetooth/Wi-Fi модуль с какого-нибудь ноутбука?
Ответить
0
kuxer #
Имею вот такой модуль. Можно ли его использовать для создания такого робота?
Ответить
0
oztima #
Мне тоже пришла такая платформа из Китая, я думал я криворукий, т.к. собрал и все крутилось еле еле, подтачивал смазывал, вроде лучше. В вот тут на видео такая же машинка летает просто: http://www.youtube.com/watch?v=rDjLI9XPWlA
Ответить
0

[Автор]
talibanich #
Ну я бы по видео не сказал, что она летает. И меня и то кажется по шустрее ездит. А платформа согласен - шлак еще тот...
Дешевле 100$ хороших платформ под DIY думаю нет. Я уже три перепробовал, везде есть недочеты, особенно с соосностью.
Ответить
+1
Антон #
В качестве платформы можно использовать базу от танка хенг лонг, на форуме рц дезайн и на диарамном форуме люди апгрейдят танки и за копейки продают нижнюю пластикувую часть от танков, как вариант - очень отлично, тем более там есть даже какая никакая подвеска
Ответить
0
Werrizzone #
А можно все это сделать под квадрокоптер? Т.е. та же машинка, только вместо колес приспособить пропеллеры, немного поменять код, железо... Ведь квадрокоптер на акселерометре будет намного удобнее.
Ответить
0
Den346 #
Я не могу собрать приложение CxemCar по вашим исходникам в eclipse. Весь код в cbluetooth пишет ошибка и все. Кто может скинуть готовое приложение?
Ответить
0

[Автор]
talibanich #
Там, где брали исходники, строкой выше готовое приложение
Ответить
0
Александр #
Можно ли использовать вместо этого драйвера двигателей Motor Shield v3? Если да, то код будет идентичный?
Ответить
0

[Автор]
talibanich #
Motor Shield v3 не щупал. Но код думаю будет такой же, единственное может быть придется переопределить пины в скетче
Ответить
0
Anton Petrovich #
Не нашел ссылку на CxemCar версии 1.3. Только 1.2 нашел. Ткните носом пожалуйста.
Ответить
0

[Автор]
talibanich #
Ответить
0
Anton Petrovich #
Извините, я имел ввиду apk файл.
Ответить
0
Anton Petrovich #
Как собрать с гитхаба все в apk файл? На версии 1,2 у меня залипают кнопки "направо", либо "налево"
Ответить
0
Yuki007 #
При попытке подключиться пишет - "Socket failed". Телефон Xperia GO Samsung galaxy s4. Bluetooth terminal подключается нормально.
В чем может быть проблема?
Ответить
0
Alex #
Такая же проблема. Отпишитесь кто знает как ее решить пожалуйста
Ответить
0
thealicecooper #
Я решил эту проблему, подключив не к 3.3 а +5V, у меня HC-06, RXD подключал в TX, а TXD в RX.
Отредактирован 04.06.2014 10:46
Ответить
0
val674 #
В программе управления пишет - "incorrect Bluetooth address" - MAC ввел правильно, Bluetooth terminal подключается. Может кто сталкивался?
Ответить
0
val674 #
Сам отвечу: проблема решена переустановкой программы управления
Ответить
0
Олег #
Собрал схему, но есть одна проблема шасси у меня построена так, что один движек выполняет движение вперед, назад, а второй отвечает за руление, я нажимаю кнопку вправо, влево, вперед, назад, то есть любой кнопку и работают оба движка. Что ковырять? Аппаратную часть или проблема с программой?
Ответить
0
vitja2000122 #
Делаю точь такой же проект, только на другой платформе и столкнулся с проблемой: у меня драйвер л298н не реагирует на команды, всё подключено как в этом проекте, но на выходах для двигателей когда даю команды всего есть 0.23 вольт, а если подключить провода тогда вообще 0, что мне делать питание даю 7 вольт
Ответить
0
Spymixer911 #
Проверь землю, должна земля быть общая?
Ответить
0
vitja2000122 #
Нет, отдельный блок 7,4 вольт
Ответить
0
dead_alex228 #
Как подключить дополнительный канал?
Ответить
Добавить комментарий
Имя:
E-mail:
не публикуется
Текст:
Защита от спама:
В чем измеряется сила тока?
Файлы:
 
Для выбора нескольких файлов использйте CTRL

Квадрокоптер Syma X11
Квадрокоптер Syma X11
Набор начинающего радиолюбителя Мультиметр DT9205A
вверх