CxemCAR на Arduino - Bluetooth керування машинкою з Android. Проста Bluetooth машинка на Arduino Блютуз машинка з Ардуін з телефону

Машинка на Ардуїно з Bluetooth керуванням від Android телефону – це дуже простий, але цікавий проект на Arduino UNO з використанням модуля Motor Shield. На цій сторінці ви дізнаєтеся які знадобляться компоненти для виготовлення робота машини на Ардуїно своїми руками, покрокову інструкцію зі збирання електричної схеми і зможете скачати всі необхідні програми для Android і Arduino.

Для цього проекту використовувався модуль Motor Shield L293D, два колеса з редукторами, плата Arduino UNO, блютуз модуль HC-05 та два світлодіоди для фар. Управління відбувається дистанційно через сигнал Bluetooth від смартфона або планшета. Після складання моделі та встановлення програм, ви зможете через додаток на смартфоні повертати машинкою, їздити вперед і назад, вмикати та вимикати фари.

Машинка на Ардуїно своїми руками

Для цього проекту нам знадобиться:

  • плата Arduino Uno / Arduino Nano / Arduino Mega;
  • 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, тут провід можна припаяти безпосередньо до порту. Якщо ви робите кілька машинок з Bluetooth, якими керуватимете одночасно, то рекомендуємо зробити перепрошивку модуля HC-05. Робиться прошивка модуля дуже просто, а потім ви вже не плутатимете машинки, так як у кожної відображатиметься своє унікальне ім'я на Андроїді.

Додаток та скетч для машинки на Ардуїно

Після складання схеми завантажте наступний скетч для машинки (не забудьте відключати Bluetooth модуль від Ардуїно під час завантаження) та встановіть програму на смартфоні. Всі файли для проекту (бібліотека AFMotor.h, скетч для машинки та додаток для Android) можна завантажити одним архівом за прямим посиланням. Роботу скетчу можна перевірити керуванням машинки від комп'ютера через Serial Monitor USB.

#include // Підключаємо бібліотеку для шилду AF_DCMotor motor1(1); // Підключаємо мотор до клемника M1 AF_DCMotor motor2(2); // Підключаємо мотор до клемника M2 int val; // звільняємо пам'ять у контролері void setup () ( Serial .begin (9600); pinMode (2, OUTPUT ); // Порт для світлодіодів motor1.setSpeed ​​(250); motor1.run (RELEASE); // Зупиняємо мотор motor2.setSpeed ​​(250); // задаємо максимальну швидкість двигуна motor2.run (RELEASE); // Зупиняємо мотор) void loop () ( if (Serial .available ()) // перевіряємо, чи надходять якісь команди( val = Serial .read (); if (val == "f") ( // їдемо вперед motor1.run (FORWARD ); motor1.setSpeed ​​(250); motor2.run (FORWARD ); motor2.setSpeed ​​(250) ; ) if (val == "b") ( // їдемо назад motor1.run (BACKWARD ); motor1.setSpeed ​​(200); motor2.run (BACKWARD ); motor2.setSpeed ​​(200); ) if (val == "s") ( // зупиняємось motor1.run (RELEASE); motor2.run (RELEASE); ) if (val == "l") ( // Повертаємо наліво motor1.run (FORWARD); motor1.setSpeed ​​(100); motor2.run (BACKWARD); motor2.setSpeed ​​(250); ) if (val == "r") ( // Повертаємо праворуч motor1.run (BACKWARD); motor1.setSpeed ​​(250); motor2.run (FORWARD); motor2.setSpeed ​​(100); ) if (val == "1") ( // Включаємо світлодіоди digitalWrite (2, HIGH); ) if (val == "0") ( // Вимикаємо світлодіоди digitalWrite (2, LOW); ) ) )

Пояснення до коду:

  1. для тестування можна відправляти команди з комп'ютера через USB;
  2. обертання моторів при підключенні до акумулятора відрізнятиметься;
  3. ви можете ставити свою швидкість обертання двигунами.

Після перевірки роботи машинки, встановіть програму на смартфон або планшет. При першому підключенні до Bluetooth модуля HC-05/06, потрібно зробити пару з Андроїд (потім пару буде виконуватися автоматично). Якщо у вас виникли труднощі із підключенням — прочитайте цю статтю

У статті розглянемо підключення та керування Arduino по bluetooth.

Як блютуз-модуля використовуватиметься широко поширений hc-06.

У нашому проекті будемо через bluetooth вмикати та вимикати світлодіод, підключений до 13 порту.

Почнемо з написання програми на android смартфон. Додаток буде писатися в зручному та простому середовищі програмування App Inventor. Програми складатимуться онлайн.

Пройдіть посилання http://ai2.appinventor.mit.edu/ . Там вас попросять увійти до Google-акаунту, який вам доведеться завести, якщо його ще немає.

Після входу ви потрапите у програму, де зможете створити проект, натиснувши «start new project». Вам потрібно буде ввести ім'я проекту. Назвемо його led_control.

Відкриється порожнє вікно програми.

Тут будемо мати необхідні компоненти. Виберіть ListPicker у вікні ліворуч та помістіть його у проект.

У компоненті ListPicker у вікні праворуч знайдіть властивість Text, і змініть "Text for ListPicker1" на "Виберіть BT-пристрій".

Відкрийте закладку Layout у вікні зліва, помістіть у додаток компонент HorizontalArrangement, змініть його властивість Width на Fill parent. Додайте в HorizontalArrangement 2 кнопки Button, у кожній з них встановіть властивість Width в Fill parent. Повинно вийти так:

Змінимо підписи на кнопках: першою буде написано LED ON, другою — LED OFF.

Нижче додамо Label та очистимо його Text.

Залишилося додати компонент, що організує передачу даних по bluetooth. Відкрийте закладку Connectivity та розмістіть у проекті BluetoothClient. Цей компонент виявиться над екрані телефону, а під ним, т.к. він не є візуальним.

Тепер можна розпочинати написання програми. У верхній правій частині програми виберіть Blocks.

Тут складатиметься програма із графічних блоків. Ліворуч клацніть на компонент ListPicker1 і виберіть ListPicker1.BeforePicking.

Натисніть знову на ListPicker1 і виберіть set ListPicker1.Elements to

Поставте його як на скріншоті.

Цим ми отримали перелік пов'язаних bluetooth-пристроїв. Тепер підключимося до вибраного пристрою. Напишіть блок як на скріншоті нижче.

Рожевий блок із написом Connected — це перший блок у закладці Text. Впишіть Connected у порожнє віконце.

Тепер напишемо оброблювач кнопок. При натисканні на першу кнопку надсилатиметься текст «led_on», а при натисканні на другу — «led_off». Також змінюватиметься і напис в Label1.

Залишилося завантажити проект у ваш смартфон. Натисніть Build і виберіть спосіб завантаження.

Для першого варіанта вам знадобляться інтернет та зчитувач QR-кодів. Натисніть та дочекайтеся закінчення складання проекту та формування QR-коду, після чого відкрийте зчитувач QR-кодів на смартфоні та рахуйте код. Залишиться лише завантажити та встановити файл.

У другому варіанті проект у форматі.apk збережеться на ваш комп'ютер і ви зможете скинути його на смартфон будь-яким зручним способом (наприклад USB).

Тепер займемося програмою Arduino.

Прийом-передача даних здійснюється через COM-порт, тому використовуватимемо Serial. Посимвольно прийматимемо сигнали, формуватимемо рядок і далі порівнюватимемо сформований рядок з командами led_on і led_off.

Arduino

String val = ""; void setup() ( Serial.begin(9600); pinMode(13, OUTPUT); ) void loop() ( while (Serial.available()) ( //поки приходять дані char c = Serial.read(); // зчитуємо їх val += c; //і формуємо рядок delay(3); ) if (val != "") ); ) else if (val == "led_off") ( digitalWrite(13, LOW); ) val = ""; )

String val = "";

void setup () (

Serial. begin (9600);

pinMode (13, OUTPUT);

void loop () (

while (Serial . available () ) ( //поки надходять дані

char c = Serial. read(); //зчитуємо їх

val + = c; //і формуємо рядок

delay (3);

}

Завантажте код Arduino.

Тепер можна підключити модуль Bluetooth HC-06. Підключається він дуже просто:

Vcc 5v (можна 3,3 v)

ЯКЩО СПРОБУТИСЯ ЗАВАНТАЖИТИ ПРОГРАМУ В ARDUINO З ПІДКЛЮЧЕНИМ МОДУЛЕМ, ТО ВИЛІЗЕ ПОМИЛКА, Т.К. І МОДУЛЬ І ЗАВАНТАЖЕННЯ ПРОГРАМИ ЗАДАЮТЬ ПОРТИ RX І TX!

Подайте харчування на Arduino. На bluetooth-модулі повинен заморгати світлодіод, це означає, що він очікує на підключення. Візьміть смартфон, знайдіть у налаштуваннях bluetooth, увімкніть його та запустіть пошук. Знайдіть пристрій з іменем hc-06 та підключіться до нього. З першого разу може не вийти. Після успішного одноразового сполучення можна запускати програму на смартфоні.

Спочатку натисніть на «Виберіть BT-пристрій» та виберіть модуль серед сполучених пристроїв. Далі натискайте кнопки увімкнення та вимкнення світлодіода. Якщо все зроблено правильно, то все працюватиме.

Ми зробили дуже простий додаток з використанням Bluetooth, без дизайну і навіть перевірки, чи підключилися до модуля чи ні. У наступних уроках будемо робити більш складні програми та краще познайомимося з App Inventor.

І роботу із ним.

Модернізація Motor Shield

Вийшло так, що виробники модуля Motor Shield позбавили своїх покупців можливості встановлювати поверх свого продукту інший модуль. Мабуть, їм подобається бути зверху або просто затиснули нормальну панельку контактів.

Мене цей нюанс зовсім не влаштовує. Саме тому я вирішив взятися за паяльник і привести Motor Shield до зручного для мене вигляду.


Акуратно видер рідні панельки контактів і викинув їх нафіг.


Встановив на їхнє місце нормальні.


У такому вигляді модулем почало користуватися набагато зручніше. Тепер я зможу нормально підключити дроти від Bluetooth до роз'ємів, а не припаювати їх намертво до контактів на Motor Shield.

Bluetooth модуль JY-MCU для Arduino


Сам Bluetooth модуль JY-MCU досить мініатюрний. В комплект поставки входить кабель для підключення. Призначення висновків розписане на звороті.


Запитати його можна від джерела живлення 36-6В. Це надає можливість підключити його безпосередньо до Arduino без використання стабілізатора або дільника напруги.

Код, який використовується при підключенні до пристрою: 1234.

Підключення Bluetooth JY-MCU до Arduino Mega 2560

Підключення досить просте.

Офіційна схема підключення:

  • TXT на JY-MCU підключаємо до RX (0) на Arduino
  • RXD на JY-MCU підключаємо до TX (1) на Arduino

При такому варіанті підключення доведеться щоразу відключати живлення модуля Bluetooth перед завантаженням скетчу. Не забувайте про це.

Мене такий варіант не влаштовує, тому вирішив використовувати дискретні порти з підтримкою Serial.

Неофіційна схема підключення:

  • VCC на JY-MCU підключаємо до +5В Arduino
  • GND на JY-MCU підключаємо до GND Arduino
  • TXT на JY-MCU підключаємо до дискретного PIN 50 на Arduino
  • RXD на JY-MCU підключаємо до дискретного PIN 51 на Arduino

Ось тепер можна завантажувати скетчі без вимкнення живлення модуля Bluetooth.

Щоб закріпити Bluetooth, я вирішив використати плату Proto Shield та мініатюрну безпайкову макетну плату. До неї в майбутньому і підключатиму інше обладнання, елементи управління та індикації.




Скетч для управління роботом на Arduino через Bluetooth через смартфон на Android

У своєму скетчі я реалізував такі функції:

  • Рух вперед
  • Рух тому
  • Розворот вліво
  • Розворот праворуч
  • Плавний поворот вліво під час руху вперед
  • Плавний поворот праворуч під час руху вперед
  • Плавний поворот вліво під час руху назад
  • Плавний поворот праворуч під час руху назад
  • Зупинка
  • Встановлення швидкості 0%

    Встановлення швидкості 10%

    Встановлення швидкості 20%

    Встановлення швидкості 30%

    Встановлення швидкості 40%

    Встановлення швидкості 50%

    Встановлення швидкості 60%

    Встановлення швидкості 70%

    Встановлення швидкості 80%

    Встановлення швидкості 90%

    Встановлення швидкості 100%

У скетчі використовував функції, щоб не дублювати код при подібних подіях.

#include // Підключаємо бібліотеку для керування двигунами
#include // Підключаємо бібліотеку для сервоприводів
#include // Підключаємо бібліотеку для роботи з Serial через дискретні порти

//Створюємо об'єкти для двигунів
AF_DCMotor motor1(1); //канал М1 на Motor Shield - лівий задній
AF_DCMotor motor2(2); //канал М2 на Motor Shield - задній правий
AF_DCMotor motor3(3); //канал М3 Motor Shield - передній лівий
AF_DCMotor motor4(4); //канал М4 на Motor Shield - передній правий

// Створюємо об'єкт для сервоприводу
Servo vservo;

SoftwareSerial BTSerial(50, 51); // RX, TX

// Створюємо змінну для Bluetooth
char vcmd;
// Створюємо змінні для запам'ятовування швидкості двигунів
int vspdL, vspdR;
/* Створюємо змінну, значення якої буде зменшуватися швидкість при плавних поворотах.
Поточна швидкість повинна бути більшою за це значення. В іншому випадку двигуни з боку напрямку повороту просто не будуть обертатися */
int vspd = 200;

void setup() (
// Встановлюємо швидкість передачі даних через Bluetooth
BTSerial.begin(9600);
// Встановлюємо швидкість передачі даних по кабелю
Serial.begin(9600);
// Вибираємо пін до якого підключено сервопривід
vservo.attach(9); // або 10, якщо встромили в крайній роз'єм
// Повертаємо сервопривід у положення 90 градусів при кожному включенні
vservo.write(90);
// Встановлюємо максимальну швидкість обертання двигунів
vspeed(255,255);
}

void loop() (
// Якщо є дані
if (BTSerial.available())
{
// Читаємо команди і заносимо їх у змінну. char перетворює код символу команди на символ
vcmd = (char)BTSerial.read();
// Відправляємо команду в порт, щоб їх можна було перевірити в "Моніторі порту"
Serial.println(vcmd);

// Вперед
if (vcmd == "F") (
vforward();
}
// Назад
if (vcmd == "B")
{
vbackward();
}
// Ліворуч
if (vcmd == "L")
{
vleft();
}
// Праворуч
if (vcmd == "R")
{
vright();
}
// Прямо і вліво
if (vcmd == "G")
{
vforwardleft();
}
// Прямо і праворуч
if (vcmd == "I")
{
vforwardright();
}
// Назад і ліворуч
if (vcmd == "H")
{
vbackwardleft();
}
// Назад і праворуч
if (vcmd == "J")
{
vbackwardright();
}
// Стоп
if (vcmd == "S")
{
vrelease();
}
// Швидкість 0%
if (vcmd == "0")
{
vspeed(0,0);
}
// Швидкість 10%
if (vcmd == "1")
{
vspeed(25,25);
}
// Швидкість 20%
if (vcmd == "2")
{
vspeed(50,50);
}
// Швидкість 30%
if (vcmd == "3")
{
vspeed(75,75);
}
// Швидкість 40%
if (vcmd == "4")
{
vspeed(100,100);
}
// Швидкість 50%
if (vcmd == "5")
{
vspeed(125,125);
}
// Швидкість 60%
if (vcmd == "6")
{
vspeed(150,150);
}
// Швидкість 70%
if (vcmd == "7")
{
vspeed(175,175);
}
// Швидкість 80%
if (vcmd == "8")
{
vspeed(200,200);
}
// Швидкість 90%
if (vcmd == "9")
{
vspeed(225,225);
}
// Швидкість 100%
if (vcmd == "q")
{
vspeed(255,255);
}
}
}

// Вперед
void vforward() (
vspeed(vspdL, vspdR);
vforwardRL();
}

// Вперед для RL
void vforwardRL() (
motor1.run (FORWARD);
motor2.run (FORWARD);
motor3.run (FORWARD);
motor4.run (FORWARD);
}

// Назад
void vbackward() (
vspeed(vspdL, vspdR);
vbackwardRL();
}

// Назад для RL
void vbackwardRL() (
motor1.run(BACKWARD);
motor2.run(BACKWARD);
motor3.run(BACKWARD);
motor4.run(BACKWARD);
}

// Ліворуч
void vleft() (
vspeed(vspdL, vspdR);
motor1.run(BACKWARD);
motor2.run (FORWARD);
motor3.run(BACKWARD);
motor4.run (FORWARD);
}

// Праворуч
void vright() (
vspeed(vspdL, vspdR);
motor1.run (FORWARD);
motor2.run(BACKWARD);
motor3.run (FORWARD);
motor4.run(BACKWARD);
}

// Вперед та вліво
void vforwardleft() (
if (vspdL > vspd) (
vspeed(vspdL-vspd,vspdR);
}
else
{
vspeed(0,vspdR);
}
vforwardRL();
}

// Вперед та вправо
void vforwardright() (
if (vspdR > vspd) (
vspeed(vspdL, vspdR-vspd);
}
else
{
vspeed(vspdL,0);
}
vforwardRL();
}

// Назад і ліворуч
void vbackwardleft() (
if (vspdL > vspd) (
vspeed(vspdL-vspd,vspdR);
}
else
{
vspeed(0,vspdR);
}
vbackwardRL();
}

// Назад і праворуч
void vbackwardright() (
if (vspdR > vspd) (
vspeed(vspdL, vspdR-vspd);
}
else
{
vspeed(vspdL,0);
}
vbackwardRL();
}

// Стоп
void vrelease()(
motor1.run(RELEASE);
motor2.run(RELEASE);
motor3.run(RELEASE);
motor4.run (RELEASE);
}

// Зміна швидкості
void vspeed(int spdL,int spdR)(
if (spdL == spdR) (
vspdL=spdL;
vspdR=spdR;
}
motor1.setSpeed(spdL);
motor2.setSpeed(spdR);
motor3.setSpeed(spdL);
motor4.setSpeed(spdR);
}

Програма Bluetooth RC Car – управління роботом-машинкою зі смартфона на Android

У свій смартфон я встановив програму Bluetooth RC Car. На мій погляд – це найкраща софтинка для керування роботом-машинкою.


Програма дозволяє передавати команди при натисканні на кнопки або реагувати на дані з акселерометра в смартфоні, регулювати швидкість руху повзунком, включати передні та задні ліхтарі, включати та вимикати звуковий сигнал, включати та вимикати сигнал “аварійка”.




Для роботи програми потрібна Android версія 2.3.3 або вище. Розмір програми 3 мегабайти.

Список команд:

  • F – вперед
  • B – назад
  • L – ліворуч
  • R – праворуч
  • G – прямо та вліво
  • I – прямо та вправо
  • H – назад та вліво
  • J – назад та вправо
  • S – стоп
  • W – передня фара увімкнена
  • w – передня фара вимкнена
  • U – задня фара увімкнена
  • u – задня фара вимкнена
  • V – звуковий сигнал увімкнено
  • v – звуковий сигнал вимкнено
  • X – сигнал “аварійка” увімкнено
  • x - сигнал "аварійка" вимкнено
  • 0 – швидкість руху 0%
  • 1 – швидкість руху 10%
  • 2 – швидкість руху 20%
  • 3 – швидкість руху 30%
  • 4 – швидкість руху 40%
  • 5 – швидкість руху 50%
  • 6 – швидкість руху 60%
  • 7 – швидкість руху 70%
  • 8 – швидкість руху 80%
  • 9 – швидкість руху 90%
  • q – швидкість руху 100%

Як бачите, полігон для творчості цілком непоганий. Я ще додав би можливість роздільного включення правих і лівих ліхтарів для передніх і задніх фар.

Жирним я виділив команди, підтримка яких уже реалізована у скетчі. Інші я збираюся використовувати за іншим призначенням.

Принцип передачі команд: при натисканні на кнопку в програмі команда передається по Bluetooth один раз, а при відпусканні кнопки відразу передається команда S-зупинка.

Демонстрація роботи

Наступного разу я планую підключити до роботи ультразвуковий далекомір та реалізувати алгоритм об'їзду перешкод.

Не купуватимемо погані іграшки у Китайців, а купимо у них дешевий конструктор-шасі, кілька модулів і прикладемо руки!

Ось що у мене вийшло в результаті: шасі, що проходить, кероване - ТА-ТА!!! - З мого смартфона на Андроїді.


«Я і прямо, я і боком,
З поворотом, і з підскоком,
І з розбігу, і на місці,
І двома ногами разом…»

Сьогодні ми зберемо кумедну машинку з дистанційним керуванням по Bluetooth. Вихідники програми управління під Android у комплекті.

Гідний зразок іграшки

У мене двоє дітей, дочка та син. Обом на дні народження дарують іграшки. Те, що дарують доньці, зазвичай не викликає моїх негативних реакцій. А синові, як і належить, дарують всілякі машинки, танки та іншу техніку. З усієї цієї прорви китайщини у мене не викликає нарікань лише іграшкова бензопила, яку я сам і подарував.

Чому так? Напевно тому, що ця пила продавалася в магазині інструментів «STIHL». Як я вважаю, STIHL зробив іграшковий аналог своєї продукції невеликим рекламним тиражем. В результаті з'явилася на світ цілком осудна іграшка, дуже схожа на свого старшого брата. Ланцюг гумовий - крутиться, відсотків на 80 реалізовані органи управління. Є навіть шнур із ручкою для заводу пили, вимикач, кнопка газу. У комплекті є запасний ланцюг та інструмент для зміни ланцюга.


Ось така іграшкова пилка

Що це я? Ах, так, про архітектуру! Це я до того, що за бажання чудову іграшку зробити можна. І є на що дорівнювати.

Будуватимемо машинку з ДУ!

Практичний та технічний інтерес викликають іграшки з радіокеруванням. Однак дитині у віці 4-6 років не даруватимуть іграшки з «дорослим» пропорційним управлінням. Найімовірніше, іграшка буде зламана, а гроші викинуті на вітер.
У результаті зазвичай дарують щось недороге. З усього цього - "недорогого" - машинки або дуже швидкі або гальмівні; танки кволі; та інші очевидні та приховані недоліки. І звичайно ніякого пропорційного управління.

Одного дня в однієї з машинок перестало обертатися праве колесо. Розібрав, перевірив моторчик – справний.
На платі керування три мікросхеми - Китай голий, документації, що осудна, знайти не зміг. Один чіп – приймач радіосигналу з логічними виходами та два мостові драйвери двигунів. Один із драйверів вийшов з ладу. Палити відразу бруківку драйвер двигуна з дискретних компонентів у мене не вийшло.

У місцевому магазині радіодеталей нічого придатного не було. Ось я й подався в далекі країни за диво-мікросхемами. Зібрав пожитки, набив кишені сухарями, налив чашку кави, запустив браузер і пішов.
Знайшов відповідний за параметрами драйвер двигуна, замовив одразу два. Про всяк випадок, раптом один буде несправний або сам спалю. Ось тоді і почала зароджуватись думка про свою машинку. Після того, як посилка дійшла зі славетного Китаю, я успішно замінив драйвер, і машинка була відремонтована.

Не відкладаючи в довгу скриньку ідею про свою машинку, я знову подався для вибору основи - шасі майбутньої машинки. Шасі бувають різні, для наземного транспорту: гусеничні, колісні, із двома, трьома, чотирма колесами тощо.

Як я вибирав шасі

По-перше, я вибрав наземний вид транспорту, отже, і шасі у мене буде наземне. Гусеничні шасі, як правило, дорожчі і не надто швидкохідні. Двох-трьох-колісні мені здаються слабкими, таке шасі зможе їздити тільки по рівній поверхні.
Я зупинився на. На мою думку, таке шасі матиме відмінну прохідність і швидкість.


У комплекті шасі:
дві пластини з акрилу з купою технологічних отворів для кріплення всіх можливих датчиків, плат керування та інших компонентів
4 колеса
4 приводи у зборі (електродвигун + редуктор)
4 диски з прорізами для датчиків швидкості, по одному на кожне колесо
кріплення
Так, це знову Китай. Так, дешевий. Так, непогано якісний. АЛЕ! Нам би спершу спробувати. Адже «доросле» шасі і стоїть по-дорослому, ми ще не доросли.

Болото думок та Техзавдання

Коли тримаєш у руках перспективну річ, наприклад, у плані можливостей з обвісу моделі всілякими датчиками, серво тощо, починаєш тонути в болоті думок і трясовині перспектив. Але, скажімо собі – СТОП! І складемо собі міні-ТЗ на прототип із коротким описом усіх вузлів.
У нас має вийти RC-модель наземного транспортного засобу з управлінням по Bluetooth, з можливістю реверсу та плавного регулювання швидкості обертання коліс.

Що нам знадобиться для збирання машини?

.


Поворотні колеса відсутні, отже управління поворотом буде як у гусеничного ТС. Тобто, для прямого руху, вперед/назад, правий і лівий бік приводів обертаються з однаковою швидкістю. А для здійснення повороту швидкість обертання на одній зі сторін повинна бути меншою або більшою.


Для дистанційного керування машиною використовуємо канал Bluetooth. Модуль "HC-06" - це міст Bluetooth, послідовний інтерфейс, що дозволяє передавати дані в обидві сторони. На вході - TTL-сигнали послідовного інтерфейсу RxD і TxD для підключення до мікроконтролера (цільової плати).
Як пульт дистанційного керування буде служити мобільний телефон з Android. Напишемо свою програму!



Драйвер двоканальний, на ліву та праву пару коліс. Драйвер має логічні входи для зміни полярності виходу (напрямки обертання) та вхід ШІМ, можна буде зробити керування швидкістю обертання.


Обрано цю плату т.к. валялася в шухляді столу і повністю підходить для нашої мети. Є дискретні входи/виходи, виведені сигнали МК RxD і TxD, куди буде підключений HC-06.
Забігаючи наперед скажу, що продукт Олімекс MOD-IO – це жорсткий перебір. Прекрасно можна буде застосувати і звичайну, про що у продовженні історії!

Разом:шасі + плата керування + Bluetooth-модуль + програма керування під Android.

Загальна схема підключення

Чи не схема в чистому вигляді, а саме схема підключення, так як всі плати у нас вже готові, і залишається їх з'єднати між собою.

Схема у Протеусі


Розписувати, що й куди я не підключив. Швидше за все, у вас буде інша плата управління. Вихідники я прикладаю, так що прошивку зможете редагувати. Ну, а якщо хтось не в змозі скомпілювати прошивку під свою плату, звертайтесь – допоможу у міру вільного часу.

Програма мікроконтролера

Програма МК вміє приймати команди з послідовного інтерфейсу з Bluetooth-модуля.
І, відповідно до команд, керувати лівою та правою парою приводів. Реверс та управління швидкістю працюють за допомогою ШІМ.

Код достатньо прокоментований. Хочу окремо зупинитися на моїй реалізації обміну даними.
Прийом даних у мене реалізовано через кільцевий буфер. Річ не нова та реалізацій багато.

Функції кільцевого буфера у мене винесені в окрему бібліотеку, що складається з:
заголовного файлу ring_buffer.hта файлу реалізацій функцій ring_buffer.с
Для використання бібліотеки її потрібно підключити до main.c
#include "ring_buffer.h"

Далі, у заголовному файлі необхідно налаштувати бібліотеку. Для налаштування необхідно задати лише чотири директиви:
#define RX_PACKET_SIZE 7 // Розмір RxD пакета #define BUFFER_SIZE 16 // Розмір приймального буфера. Повинен бути вдвічі більшим за RX_PACKET_SIZE #define START_BYTE "s" // Стартовий байт #define STOP_BYTE "e" // Стоповий байт

Власне, налаштовувати більше нічого.

Використання кодуУ main.c налаштовуємо USART мікроконтролера.
Викликаємо функцію налаштування USART
USART_Init(MYUBRR);

#define BAUD 9600 #define MYUBRR F_CPU/16/BAUD-1 void USART_Init(unsigned int ubrr) ( /* Set baud rate */ UBRRH = (unsigned char)(ubrr >> 8); UBRRL = (unsigned char)ubrr; /* Enable receiver and transmitter */ UCSRB = (1<< TXCIE) | (1 << RXCIE)| (1 << TXEN) | (1 << RXEN); /* Set frame format: 8data, 2stop bit */ UCSRC = (1 << URSEL) | (0 << USBS) | (3 << UCSZ0); }

Прийом пакета даних

У функції обробника переривання прийому байта по USART, нам необхідно лише покласти прийнятий байт в кільцевий буфер. Розбір пакету робитимемо потім.
ISR(USART_RXC_vect) (uint8_t Data = UDR; RB_push_char(Data); // Складаємо прийнятий байт в кільцевий буфер)
Так, я поки що знехтував усілякими перевірками кадру.

Тепер нам залишається час від часу перевіряти наш буфер. Для цього я ініціював таймер, в якому я встановлюю прапор, що дозволяє перевірити кільцевий буфер.
ISR(TIMER0_OVF_vect) ( TCNT0 = 0x64; ReadRingBuffer = 1; )

В основному циклі додаємо умову для перевірки прапора.
if (ReadRingBuffer) ( if (RB_read_buffer((uint8_t*)&RxPacket) == 1) Читання буфера ( // Розбираємо пакет, робимо щось ) ReadRingBuffer = 0; )

Функція RB_read_bufferперевіряє кільцевий буфер, якщо розмір пакета, стартовий і стопові байти перебувають у своїх місцях - пакет вважається валідним, функція повертає "1». Як аргумент, функція приймає покажчик, куди складати прийнятий пакет.
Для більшої надійності пакет можна забезпечити контрольною сумою, в одному зі своїх комерційних проектів я так і зробив. Тобто до перевірки розміру старт/стопового байтів додається ще перевірка контрольної суми. Але поки що обійдемося без неї.

Як я розумію пакет

Тепер найцікавіше, як я розумію пакет. У пакеті можуть передаватися дані розмірністю більше байта, знакові дані, дані з точкою, що плаває.
Поясню на прикладі пакета для керування шасі. Окрім стартового та стопового байтів, у своєму пакеті мені необхідно передавати одну команду, та два значення ШІМ, для лівої та правої сторони приводів. Для команди мені достатньо одного байта, а для кожного значення ШІМ, я передаю int16- 16 біт, знаковий тип. Тобто я не передаю прапор (байт/ознака) напряму. Для зміни напряму, я передаю позитивне чи негативне значення ШІМ.

Прийомний пакет у мене організовано у вигляді структури.
struct RxPacket ( uint8_t StartByte; uint8_t Command; int16_t Left_PWM; int16_t Right_PWM; uint8_t StopByte; ) RxPacket;

Викликаючи функцію RB_read_buffer ((uint8_t*)&RxPacket ), Як аргумент передаємо покажчик на структуру приймального пакета. Тобто при прийнятому пакеті буде все розкладено по своїх поличках у структурі RxPacket. Далі залишається прочитати ці дані зі структури, наприклад:
lCmd = RxPacket.Command; lLPWM = RxPacket.Left_PWM; lRPWM = RxPacket.Right_PWM;

Передача пакету даних

Хоча у моїй програмі передача поки що не використовується, проте можливість передачі реалізована. Передавати дані простіше. Так само, як і для приймального пакета, створимо структуру:
struct TxPacket ( uint8_t StartByte; uint8_t Rc5System; uint8_t Rc5Command; uint8_t StopByte; ) TxPacket;

Де є стартовий і стоповий байт та інформаційна частина. Ми вже ініціалізували приймач USART.
Для ініціювання передачі пакета – викликаємо функцію
void send_packet() ( // Запис стартового байта в регістр UDR UDR = START_BYTE; )
У даному прикладі, в цій функції, я записую тільки стартовий байт у регістр UDR. Начебто небагато, але в цій функції можна реалізувати підготовку пакета або ще щось корисне. І це, як на мене, більш логічно. Логічно щодо самодокументування коду. Тобто, якщо я в коді, просто запишу значення в регістр UDR це може бути сприйнято як передача всього одного байта, а викликаючи функцію, що самоговорить send_packet()- я говорю про те, що я відправляю пакет даних.

Далі, коли передавач USART відправить весь байт з регістру UDR - буде викликаний обробник переривання передачі.
ISR(USART_TXC_vect) ( unsigned char *Pointer = (unsigned char *)&(TxPacket); static unsigned char TxIndex = 1; if (TxIndex< sizeof(TxPacket)) { UDR = *(Pointer + TxIndex); TxIndex++; } else TxIndex = 1; }

У обробнику я оголошую змінну покажчика і надаю її адресу структури TxPacket. Далі оголошується статична змінна - індекс байта, що передається, якій при оголошенні присвоєно значення 1 . Починаємо з одного тому, що перший байт із структури ми вже відправили. Загалом у структурі можна обійтися і без стартового байта, все одно я його відправляю окремо, але оголошення цього байта залишено в структурі для розуміння того, як виглядає пакет.

Умова if (TxIndex< sizeof(TxPacket)) проверяет, что индекс меньше чем размер пакета. Если условие верно, то записываем байт в регистр UDR: UDR = *(Pointer + TxIndex);
інкрементуємо TxIndex. Коли USART передасть черговий байт, ми знову потрапимо в обробник, але буде переданий вже наступний байт із структури і так будуть передані всі байти структури. Коли TxIndex буде більшим за розмір структури - умова буде не вірна і ми потрапимо в else TxIndex = 1; Де буде проініціалізовано TxIndex, але в регістр UDR вже нічого не записується, відповідно обробник більше не буде викликано до наступного ініціювання передачі пакета. Таким чином, процес передачі повністю автоматичний, і навіть, якщо ми змінимо структуру пакета, обробник переписувати не доведеться.

У рамках опису програми МК залишилося розповісти про реалізацію управління драйверами. Драйвер керується трьома сигналами: A1 (B1), A2 (B2) та PWMA (PWMB). A1 і A2 призначені для увімкнення/вимкнення драйвера і для зміни полярності виходу. На вхід PWMA подається ШИМ сигнал із МК - можна керувати швидкістю обертання. Для ШІМ сигналу я задіяв два апаратних ШІМ таймера 1.
#define _WGM13 0 #define _WGM12 1 #define _WGM11 0 #define _WGM10 1 // Timer 1 init TCCR1A = (1<< COM1A1) | (0 << COM1A0) | (1 << COM1B1) | (0 << COM1B0) | (_WGM11 << WGM11) | (_WGM10 << WGM10); TCCR1B = (0 << CS12) | (0 << CS11) | (1 << CS10) | (_WGM13 << WGM13) | (_WGM12 << WGM12); TCNT1 =0x0000; OCR1A = 0; OCR1B = 0;

Таймер 16-бітний, але ШІМ ініціалізований на 8 біт. І як ви напевно вже помітили, у приймальному пакеті у мене є два значення для завдання ШІМ, для лівого та правого приводу відповідно. Змінні знакові 16-бітові.
Поясню, чому я так зробив.

По першеЦе пішло від програми під Андроїд. Справа в тому, що в Java немає без знакових типів і я вже наступав на ці граблі. І для передачі числа від 0 до 255 мені довелося б якось викрутитися. Я вирішив піти більш простим шляхом - надсилаю знакове 16-біт число. При цьому 16 біт знакового типу це від -32786 до 32768 нам вистачить.

По-друге, Так на мій погляд більш прозоро - швидкість обертання та напрямки описується лише однією змінною.

І по-третє, як не крути, для наших цілей менше ніж у три байти не вкластися. Пожертвуємо ще одним байтом, зате все стає зрозуміло, позитивне значення ШІМ – пряме обертання, негативне значення – зворотне обертання.

Для керування приводами я написав функцію drive (int leftPWM, int rightPWM);.
void drive(int leftPWM, int rightPWM) ( // Рух ВПЕРЕД ліве колесо if (leftPWM > 0)( ClearBit(A2_PORT, A2_PIN); SetBit(A1_PORT, A1_PIN); ) // Рух НАЗАД ліве колесо< 0){ ClearBit(A1_PORT, A1_PIN); SetBit(A2_PORT, A2_PIN); } // Движение ВПЕРЁД правое колесо if (rightPWM >0)( ClearBit(B2_PORT, B2_PIN); SetBit(B1_PORT, B1_PIN); ) // Рух НАЗАД праве колесо if (rightPWM< 0){ ClearBit(B1_PORT, B1_PIN); SetBit(B2_PORT, B2_PIN); } // Остановка if (leftPWM == 0){ ClearBit(A1_PORT, A1_PIN); ClearBit(A2_PORT, A2_PIN); } // Остановка if (rightPWM == 0){ ClearBit(B1_PORT, B1_PIN); ClearBit(B2_PORT, B2_PIN); } set_PWM((uint8_t)(abs(leftPWM)), (uint8_t)(abs(rightPWM))); }
Відповідно до значення ШІМ, здійснюється керування сигналами A1 (B1), A2 (B2) і встановлюється значення ШІМ викликом функції set_PWM (leftPWM, rightPWM).

Уфф, видихся...
Підсумуємо: прийняли пакет, розібрали, передали значення ШІМ у функцію drive.

Додаток під Android для машинки

Ні, так докладно як програму для МК я розбирати не буду. У розробці ПЗ під Android я ще новачок і не готовий розповідати досить компетентно та глибоко.

Основна функція програми- передача даних модулю HC-06 каналом Bluetooth. Програма має невигадливий інтерфейс.

Зверху список спарених Bluetooth пристроїв для вибору модуля. Спочатку цього списку не було, але вже під кінець роботи над статтею вирішив зробити по-людськи, адже не всі зможуть розібратися у вихідниках.

Далі кнопка "Вимк" - включає/відключає зв'язок з "HC-06". Нижче зліва направо: значення ШІМ лівого каналу, тип датчика, значення правого каналу. Нижче два слайдери регулювання чутливості швидкості та повороту.

У програмі реалізовано два типи керування машинкою. Щоб переключити тип датчика, торкніться напису назви датчика: «Нахил» або «Шаркати».

1. Керування машиною за допомогою нахилу телефону.Нульове положення телефону – горизонтальне. При нахилі телефону вперед значення ШІМ збільшується пропорційно нахилу в діапазоні від 0 до 255 . При нахилі телефону назад значення ШІМ зменшується пропорційно нахилу в діапазоні від 0 до -255


Щоб повернути ліворуч або праворуч, потрібно нахилити телефон вперед або назад і, одночасно, ліворуч або праворуч відповідно. Так, як у справжній машині, поки не піддаси газку поворот не здійснюється.

2. Управління торканням.Моя фірмова назва для такого управління – «шаркати».


Можна сприймати як тачпад. При торканні в сірому квадраті значення ШІМ збільшується/зменшується в залежності від місця торкання, чим далі від центру вниз або вгору тим більше/менше значення.

Жодних «красивостей» і наворотів немає. От начебто б і все.

Трохи дьогтю на «лижі»

Є косяк біля мого телефону. Ага, телефон "лижа" - LG G2 mini. На ньому з'єднання Bluetooth встановлюється неадекватно. З'єднання встановлюється нормально тільки, якщо Bluetooth увімкнено безпосередньо перед запуском програми.
Я зробив так: при запуску додатку перевіряю чи увімкнений Bluetooth, якщо вимкнений - роблю запит на увімкнення. А при «згортанні», закритті програми – примусово вимикаю Bluetooth.
І ще один момент, при зміні орієнтації екрану, Bluetooth вимикається і знову видається запит на увімкнення, доводиться вимикати автоматичне перемикання розвороту екрана.

Резюме

Я вважаю, що досяг мети! При невеликих зусиллях я створив RC-модель з осудним пропорційним керуванням. Машинкою можна із захопленням грати навіть дорослому, роблячи розвороти дома, виписуючи складні піруети, пригальмовуючи і прискорюючись за необхідності.
І її легко полагодити при поломці.

Є ще поле для діяльності, є куди зростати. Можна «навертати» шасі, можна модернізувати та покращувати ПЗ для телефону.
І про це буде продовження!


У цьому матеріалі пропонуємо дізнатися, як можна зробити радіокеровану машину в домашніх умовах.

Для виготовлення машинки нам знадобиться:
- іграшкова машинка;
- дві карти Arduino Uno;
- Дві плати радіо модуля NRF24;
- конденсатор на 470 мф, 25 вольт;
- Плата драйвера двигуна L298N;
- Двигун;
- сервопривід;
- аналоговий джойстик;
- акумуляторні батарейки;
- батарейка крона;
- дві кнопки включення та вимикання;
- Корпус.

Насамперед необхідно припаяти конденсатор на висновки живлення радіо модуля. Також потрібно зібрати акумуляторні батарейки, щоб отримати сумарну потужність в 12 вольт для живлення двигуна і плати Arduino.

Необхідно подбати про поворотну систему автомобіля. Для цього вирізаємо частину, призначену для кріплення передніх коліс.

Тепер необхідно зробити отвори діаметром 4 мм у нижній частині корпусу машинки та колесах.

Збираємо все. Просовуємо гвинт у колесо і фіксуємо двома гайками.

Просовуємо ще один гвинт у отвір на корпусі, фіксуємо гайками.

В кінці залишається надіти колесо з куточком на гайку в корпусі машини і зафіксувати ще кількома гайками. Виконуємо те саме з другим колесом.

Тепер необхідно з'єднати сервопривід до поворотної системи.

Також у двигуні є спеціальні кріпильні отвори, в які потрібно вставити два гвинтики, щоб закріпити двигун на корпусі машинки.

Тепер потрібно залити код на плату Arduino. Наприкінці статті буде представлений код для приймача, а також код передавача.

Представляємо схему складання джойстика або передавача.

Нижче ви можете побачити схему складання приймача.

Наприкінці залишається зібрати електроніку та механіку саморобного радіокерованого автомобіля. При включенні треба спочатку увімкнути пульт керування, після чого саму машинку.

Як і обіцяли, нижче даємо посилання на коди, необхідні для програмування плати
Код для приймача: (завантажень: 3609)
Код для передавача: (скачувань: 2617)

Також представимо коротку інструкцію з прошивки плат Arduino Uno. Плату потрібно підключити до комп'ютера через кабель USB. Далі з офіційного сайту () потрібно завантажити безкоштовну програму, встановити її, встановити драйвери плати та прошити її за допомогою цієї програми.

Якщо ж ви використовуєте китайську плату, то її драйвер можете завантажити за цим посиланням: