ARDUINO – Машинка на nrf24l01 | AlexGyver Community

ARDUINO - Машинка на nrf24l01 | AlexGyver Community Самолеты

Arduino – машинка на nrf24l01

Здарова всем, хочу поделиться своим проектом – машинка под управлением nrf24l01. Машинка получилась очень резвая и быстрая.

Управляется за счёт двух джойстиков от приставки. Ездит на 2 колёсах и одной шаровой опоре.

Делалась она из того, что было, а именно, из какого-то светорассеивающего оргстекла, пульт из распределительной коробки. Корпус это две пластинки из светорассеивающего оргстекла, которые скреплены между собой шестью спейсерами длиной 2 см. Размеры машинки: прямоугольник 10×15 см, у которого спереди по бокам срезано два треугольника 2.5×5 cм, высота 2 см. Размер распределительной коробки: 4 см высота, диаметр 10 см.

фото
P_20230731_172610[1].jpgP_20230731_172521[1].jpgP_20230731_172558[1].jpg

Перейдём к внутренностям:

КОМПОНЕНТЫ ПУЛЬТА

  • arduino nano
  • nrf24l01 без антенны c адаптером
  • Аккумулятор 610мАч 7.4А (две банки)
  • Джойстики X2
  • Выключатель

Фото внутренностей

P_20230731_181023[1].jpg
КОМПОНЕНТЫ МАШИНКИ

  • arduino nano
  • nrf24l01 с антенной и адаптером
  • Аккумулятор 610мАч 7.4В (две банки)
  • Драйвер моторов двухканальный Pololu на TB6612FNG v2 <1А
  • Мотор-редуктор Gekko MR12-050 turbo X2
  • Колесо Pololu 32×7 X2
  • Выключатель

Фото внутренностей

P_20230731_181942[1].jpg
СХЕМА МАШИНКИ
машинка схема.PNG

СХЕМА ПУЛЬТА
Схема пульт_xx.png

Принцип работы кода. Скорости вычисляются так: у нас есть 4 значения от 0 до 1023, измеряющихся в реальном времени (я решил использовать только два и разбил их на две части каждую, в итоге получили 4). Теперь преобразовываем их так, чтобы при сгибании 1-го джойстика из центра до максимума вперёд получали значения от 0 да 255, и при сгибании из центра назад было бы тоже самое. Со 2-м джойстиком, тоже из центра влево от 0 до 255 и в право от 0 да 255. В первой версии кода мы просто складывали эти скорости, то есть третье с четвёртым прибавляем к первым двум, и скорость движения вперёд просто пишем через if, чтобы можно было стоять . Это лишало нас способности поворачивать при движении вперёд на максимальной скорости. В version 2 (отдельное спасибо Nashatirkoза помощь в написании кода) c джойстика, отвечающего за поворот ось Y, мы снимаем коэффициент скорости колеса от 0 да 100, что более разумно. И вот так высчитываем скорость одного колеса: spr = x1p * y2r / 100. Скачать скетчи можно по ссылке.
КОД ПУЛЬТА

/*   Данный скетч модернизация скетча AlexGyver

*    исходник тут https://github.com/AlexGyver/nRF24L01

*/



#include <SPI.h>          // библиотека для работы с шиной SPI

#include "nRF24L01.h"     // библиотека радиомодуля

#include "RF24.h"         // ещё библиотека радиомодуля



RF24 radio(9, 10);





byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"}; //возможные номера труб

byte transmit_data[4];





void setup() {

  Serial.begin(9600); //открываем порт для связи с ПК



  radio.begin(); //активировать модуль

  radio.setAutoAck(0);         //режим подтверждения приёма, 1 вкл 0 выкл

  radio.setRetries(0, 0);    //время между попыткой достучаться, число попыток

  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал

  radio.setPayloadSize(32);     //размер пакета, в байтах



  radio.openWritingPipe(address[0]);   //мы - труба 0, открываем канал для передачи данных

  radio.setChannel(0x60);  //выбираем канал (в котором нет шумов!)



  radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX

  radio.setDataRate (RF24_1MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS

  //должна быть одинакова на приёмнике и передатчике!

  //при самой низкой скорости имеем самую высокую чувствительность и дальность!



  radio.powerUp(); //начать работу

  radio.stopListening();  //не слушаем радиоэфир, мы передатчик

}
void loop() {

  transmit_data[0] = map(analogRead(A0), 0, 1023, 0, 255); //считываем и обрезаем показания с джостика 1 оси X

  transmit_data[1] = map(analogRead(A1), 0, 1023, 0, 255); //считываем и обрезаем показания с джостика 1 оси Y

  transmit_data[2] = map(analogRead(A2), 0, 1023, 0, 255); //считываем и обрезаем показания с джостика 2 оси X

  transmit_data[3] = map(analogRead(A3), 0, 1023, 0, 255); //считываем и обрезаем показания с джостика 2 оси Y

  radio.write(&transmit_data, sizeof(transmit_data)); //отправляем получившийся массив
}

КОД МАШИНКИ Version 2

/*   Данный скетч модернизация скетча AlexGyver
*    исходник тут https://github.com/AlexGyver/nRF24L01
*/

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"

RF24 radio(9,10); // "создать" модуль на пинах 9 и 10 Для Уно
//RF24 radio(9,53); // для Меги

byte address[][6] = {"1Node","2Node","3Node","4Node","5Node","6Node"};  //возможные номера труб
byte recieved_data[4];
void setup(){
  Serial.begin(9600); //открываем порт для связи с ПК

  pinMode(4, OUTPUT);

  pinMode(A0, OUTPUT);
  pinMode(A1, OUTPUT);
  pinMode(5, OUTPUT);

  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(6, OUTPUT);


  radio.begin(); //активировать модуль
  radio.setAutoAck(0);         //режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0,15);     //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах

  radio.openReadingPipe(1,address[0]);      //хотим слушать трубу 0
  radio.setChannel(0x60);  //выбираем канал (в котором нет шумов!)

  radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_1MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  //должна быть одинакова на приёмнике и передатчике!
  //при самой низкой скорости имеем самую высокую чувствительность и дальность!!

  radio.powerUp(); //начать работу
  radio.startListening();  //начинаем слушать эфир, мы приёмный модуль
}

void loop() {
    byte pipeNo;               
    while( radio.available(&pipeNo)){    // слушаем эфир со всех труб
      radio.read( &recieved_data, sizeof(recieved_data) ); //читаем присланный массив
      digitalWrite(4, HIGH);

      int x1p = constrain(map(recieved_data[1], 128, 255, 0, 255), 0, 255); //обрезаем и переворачиваем значения
      int x1b = constrain(map(recieved_data[1], 128, 0, 0, 255), 0, 255); //обрезаем и переворачиваем значения
      int y2r = constrain(map(recieved_data[2], 122, 255, 100, 1), 0, 100); //обрезаем и переворачиваем значения
      int y2l = constrain(map(recieved_data[2], 122, 0, 100, 1), 0, 100); //обрезаем и переворачиваем значения

      int stl = constrain(map(recieved_data[2], 123, 255, 0, 255), 0, 255); //обрезаем и переворачиваем значения
      int str = constrain(map(recieved_data[2], 122, 0, 0, 255), 0, 255); //обрезаем и переворачиваем значения

      //Serial.print(x1p); Serial.print(" | "); Serial.print(x1b); Serial.print(" | "); Serial.print(y2r); Serial.print(" | "); Serial.print(y2l); Serial.println();
      int spr = constrain(x1p * y2r / 100, 0, 255); //скорость правого колеса
      int spl = constrain(x1p * y2l / 100, 0, 255); //скорость левого колеса
      int bspr = constrain(x1b * y2r / 100, 0, 255); //скорость правого колеса назад
      int bspl = constrain(x1b * y2l / 100, 0, 255); //скорость левого колеса назад
      Serial.print(stl); Serial.print(" | "); Serial.print(str); Serial.println();
      //Serial.print(recieved_data[2]); Serial.println();
      if (recieved_data[1]>138)
    { digitalWrite(A1, LOW);
      digitalWrite(A0, HIGH);
      analogWrite(5, spr);

      digitalWrite(7, LOW);
      digitalWrite(8, HIGH);
      analogWrite(6, spl);
    } else if (recieved_data[1]<118)
    { digitalWrite(A1, !LOW);
      digitalWrite(A0, !HIGH);
      analogWrite(5, bspr);

      digitalWrite(7, !LOW);
      digitalWrite(8, !HIGH);
      analogWrite(6, bspl);
    }else if (118<recieved_data[1]<138)
    { digitalWrite(A1, LOW);
      digitalWrite(A0, HIGH);
      analogWrite(5, str);

      digitalWrite(7, LOW);
      digitalWrite(8, HIGH);
      analogWrite(6, stl);
      }
  }
}

Я думаю, нужно усовершенствовать код. И машинке хорошо бы придумать применение, чтоб она не только была как игрушка для детей. К примеру, сверху держатель для бутылки приделать, чтобы возить напитки, не вставая с дивана, но это слишком просто. Предлагайте свои идеи по поводу кода и апгрейда.

Кстати скоро выйдет версия с камерой как у Алекса.

Всем спасибо за внимание!

Arduino и соединение

Для начала определимся со схемой подключения двигателей. Так как я брал корпус от уже готовой машинки, то мне с двигателями повезло – они уже там были. Передний отвечал за повороты (влево, вправо, прямо), а задний за движение (мне пришлось его поменять на двигатель кнопки блокировки дверей какого-то ВАЗа).

Управлять нагрузками можно ардуиной с помощью полевых транзисторов (95N2LH5, но я использовал IRF 630, потому что и эти ели нашел в своём городе). Подключение такое: земля транзистора – к управляющему пину ардуины, source – к земле ардуины и минусу питания нагрузки, drain – к минусу нагрузки, плюс питания к плюсу нагрузки.

Но таким образом мы сможем ездить только вперед и поворачивать только в одну сторону. Для того чтобы справиться с проблемой, к нам на помощь спешит реле с двумя группами контактов. У меня один двигатель (передний) питался 6 вольтами, а другой 12. При этом использовалось два 6 вольтовых аккумулятора (один из них — свинцово-кислотный от бесперебойника), учитывая, что минус роутера позже придется соединить с землей ардуины, то получить 6 вольт для роутера не получается (проверяйте сколько вольт подаёте на роутер — мне пришлось покупать еще один после того, как я подал на него 12 вольт). Поэтому пришлось использовать еще одну релюшку для подачи/неподачи питания на передний двигатель.

Схема


Схему рисовал давно. Теперь там все транзисторы полевые и нет резисторов.

Теперь о самом коде. У меня все довольно просто – есть 4 команды, у которых есть свой параметр размером 1 байт:

Вот мой код программы для ардуины:

int inByte, val;

void setup() {     
 Serial.begin(9600);
 pinMode(2, OUTPUT);
 pinMode(4, OUTPUT);
 pinMode(7, OUTPUT);
}

void loop() {
 if (Serial.available() > 0)
 {
  inByte = Serial.read();
  if ((inByte=='n')||(inByte=='e')){
   while (Serial.available()==0) {}
   val=Serial.read();
   if (inByte=='n'){
    if (val=='1'){
     digitalWrite(2, HIGH);
     Serial.print("Writing to 2 pinnr");
    }
    if (val=='0'){
     digitalWrite(2, 0);
     Serial.print("Writing to 2 pinnr");
    }
   } 
   if (inByte=='e'){
    if (val=='1'){
     digitalWrite(4, HIGH);
     Serial.print("Writing to 4 pinnr");
    }
    if (val=='0'){
     digitalWrite(4, LOW);
     Serial.print("Writing to 4 pinnr");
    }
   }
  }
  if ((inByte=='m')||(inByte=='r')){
   while (Serial.available()==0) {}
   val=Serial.read();
   if (inByte=='m'){
    if (val!='0')
     analogWrite(3, val);
    else
     analogWrite(3, 0);
    Serial.print("Writing to 3 pinnr");
   }
   if (inByte=='r'){
    if (val=='1'){
     digitalWrite(7, HIGH);
     Serial.print("Writing to 7 pinnr");
    }
    if (val=='0'){
     digitalWrite(7, LOW);
     Serial.print("Writing to 7 pinnr");
    }
   }
  }
 }
}

Как видно, задний двигатель у меня подключен к 3 пину, передний – к 7, реле заднего – к 2 пину, переднего – к 4. Так как 3 – это ШИМ-пин, то используя analogWrite(3, val);, где val от 0 до 255, мы можем управлять напряжением на двигателе.


Разбираем наш маршрутизатор. Видим UART порт. Соединяем его с ардуиной.

UART на роутере

Теперь смотрим, как это все работает. Подключаемся телнетом к нашему порту и проверяем:

Для отладки работы с ком портом на роутере можно использовать minicom (

opkg install minicom

Rc авто c gps на платформе arduino nano

ARDUINO - Машинка на nrf24l01 | AlexGyver Community

Моя идея: узнать максимальную скорость в радиоуправляемой машинке и запоминание при выключение питания, добавить включение фар при наборе скорости, включение поворотников при поворотах, включение стопсигналов при торможение, включение габаритных огней при стоянке, мигалок при нажатие кнопки на машинке(кнопка сброса максимальной скорости).

Машинка, которая используется в комплектации:

Задача сделать на имеющей машинке:

  1. Установить все световые огни и кнопку
  2. Установить аппаратуру ардуино
  3. Закачать программу в ардуино
  4. Настройка программы

Установка световых огней. Я взял готовые светодиоды с проводами из набора «RC Car Flashing Light System».

ARDUINO - Машинка на nrf24l01 | AlexGyver Community
Установка передних фар (они же являются габаритами) и поворотников

ARDUINO - Машинка на nrf24l01 | AlexGyver Community
Установка аппаратуры ардуино Nano и GPS, все закрепил двухсторонем скотчем и винтами

ARDUINO - Машинка на nrf24l01 | AlexGyver Community
Установка LCD на заднем стекле, закрепил винтами

Что понадобится для сборки:
Arduino Nano, цена от 200 р.
GPS приемник, цена от 900 р.
Светодиоды, цена от 100 р. / Светодиоды белые, 3 шт. (передние фары и задний ход), красные 2 шт. (тормоз), оранжевые 2 шт. (поворотники)
Провода, цена от 100 р.
LCD и I2C, цена от 200 р.
Кнопка и резистор, цена от 100 р. / Кнопка (сброс скорости и включение мигалок) и резистор 10 кОм

Цена проекта получилось 1600 рублей.

1. Arduino Nano

ARDUINO - Машинка на nrf24l01 | AlexGyver Community

2. LCD 1602 и I2C

ARDUINO - Машинка на nrf24l01 | AlexGyver Community
LCD

ARDUINO - Машинка на nrf24l01 | AlexGyver Community
Задняя сторона LCD и припаял к нему модуль I2C

3. GPS-GY-NEO-6MV2 (GPS приемник)

ARDUINO - Машинка на nrf24l01 | AlexGyver Community
GPS-приемник

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

Если не хватает библиотеки, то нужно их скачать и установить на компе: LiquidCrystal_I2C.h, EEPROM.h, Wire.h, SoftwareSerial.h, TinyGPS.h.

Сам скетч:

СКЕТЧ

#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); //I2C: SDA pin A4 / SCL pin A5 /VCC pin 3,3V /GND pin GND
#include <SoftwareSerial.h>
#include <TinyGPS.h>
TinyGPS gps;
SoftwareSerial ss(4, 3); // GPS: RX pin D4, TX pin D3, VCC pin 5V ,GND pin GND
static void smartdelay(unsigned long ms);
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
float flat, flon; //
unsigned long fix_age, time, date, speed, course; //
int value;
int value2;
int pin = 7; //поворотник D7
int pins = 8; //движение D8
int pin1 = 11;//Светодиод оранжевый: влево D11
int pin2 = 12;// Светодиод оранжевый: вправо D12
int pin3 = 10;// Светодиоды красные: тормоз D10
int pin4 = 9;// Светодиоды белые : вперед D9
int pin6 = 6;// Светодиод белый : задний ход D6
unsigned long duration1;//центр 1372 ,влево 1834 ,вправо973
unsigned long duration2;//тормоз 1834 ,вперед 973
int pin7 = 2;// Светодиод мигалка красная: pin D2
int pin8 = 13;// Светодиод мигалка синяя pin D13
const int buttonPin = 5; // Кнопка (сброса) номер входа, подключенный к кнопке pin D5
int buttonState = 0; // переменная для хранения состояния кнопки
void setup()
{
pinMode(pin, INPUT);
pinMode(pin1, OUTPUT);
pinMode(pin2, OUTPUT);
pinMode(pins, INPUT);
pinMode(pin3, OUTPUT);
pinMode(pin4, OUTPUT);
pinMode(pin6, OUTPUT);
pinMode(pin7, OUTPUT);
pinMode(pin8, OUTPUT);
pinMode(buttonPin, INPUT); // инициализируем пин, подключенный к кнопке, как вход
Serial.begin(115200); //для отладки
ss.begin(9600); //gps
Serial.println("RRRR777");
lcd.init(); // инициализация ЖК
lcd.clear();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("RRRR777 2023");
lcd.setCursor(0, 1);
lcd.print(" GPS RCavto");
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500); // ждем
digitalWrite(pin8, HIGH); //
digitalWrite(pin7, LOW); //
delay(500); // ждем
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500); // ждем с
digitalWrite(pin8, HIGH); //
digitalWrite(pin7, LOW); //
delay(500); // ждем
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500); // ждем
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500); // ждем
digitalWrite(pin8, HIGH); //
digitalWrite(pin7, LOW); //
delay(500); // ждем
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500); // ждем с
digitalWrite(pin8, HIGH); //
digitalWrite(pin7, LOW); //
delay(500); // ждем
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500);
digitalWrite(pin7, LOW); //
digitalWrite(pin8, LOW); //
delay(500); // ждем
lcd.clear();
delay(500);
}
void loop()
{
duration1 = pulseIn(pin, HIGH);
duration2 = pulseIn(pins, HIGH);
if ((duration1 > 1500) && (duration1 < 2000))
{digitalWrite(pin1, HIGH); // зажигаем светодиод LEFT
delay(250); // ждем секунду
digitalWrite(pin1, LOW); // выключаем светодиод
}
if ((duration1 < 1300) && (duration1 > 800))
{digitalWrite(pin2, HIGH); // зажигаем светодиод RIGHT
delay(250); // ждем секунду
digitalWrite(pin2, LOW); // выключаем светодиод
}
if ((duration2 > 1480) && (duration2 < 2000))//ФАРЫ
{ analogWrite(pin4, 20); //габариты задние
analogWrite(pin3, 255); // зажигаем светодиод фары
delay(500); // ждем
}
if ((duration2 < 1480) && (duration2 > 800)) //ТОРМОЗ
{analogWrite(pin4, 255); // светодиод тормоз
analogWrite(pin3, 20); // зажигаем светодиод фары габариты *
digitalWrite(pin6, LOW); // выключаем светодиод
delay(50);
}
if ((duration2 < 1400) && (duration2 > 800))//Задний ход
{//digitalWrite(pin4, LOW); // зажигаем светодиод
digitalWrite(pin6, HIGH); // зажигаем светодиод
delay(500); // ждем секунду
}
float flat, flon;
unsigned long age, date, time, chars = 0;
unsigned short sentences = 0, failed = 0;
float h = gps.f_speed_kmph(); // speed in km/hr
int h1 = (h-(int)h)*100;
Serial.println(h);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Mersedes GT3"); // название машины
lcd.setCursor(0, 1);
lcd.print("S=");
lcd.print(h);
lcd.setCursor(8, 1);
lcd.print("MS=");
value = EEPROM.read(0); //чтение из памяти
value2 = EEPROM.read(1);
lcd.print(value);
lcd.print(".");
lcd.print(value2);
buttonState = digitalRead(buttonPin);// считываем значения с входа кнопки
if (buttonState == HIGH)// LOW) ///
{
EEPROM.write (0,0);
EEPROM.write (1,0);
lcd.setCursor(8, 1);
lcd.print("MS=RESET");
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500); // ждем
digitalWrite(pin8, HIGH); //
digitalWrite(pin7, LOW); //
delay(500); // ждем
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500); // ждем с
digitalWrite(pin8, HIGH); //
digitalWrite(pin7, LOW); //
delay(500);
lcd.setCursor(0, 1);
lcd.print("[email protected]");
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500); // ждем
digitalWrite(pin8, HIGH); //
digitalWrite(pin7, LOW); //
delay(500); // ждем
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500); // ждем с
digitalWrite(pin8, HIGH); //
digitalWrite(pin7, LOW); //
delay(500); // ждем
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500);
digitalWrite(pin8, HIGH); //
digitalWrite(pin7, LOW); //
delay(500); // ждем
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500); // ждем с
digitalWrite(pin8, HIGH); //
digitalWrite(pin7, LOW); //
delay(500); // ждем
digitalWrite(pin7, HIGH); //
digitalWrite(pin8, LOW); //
delay(500);
digitalWrite(pin7, LOW); //
digitalWrite(pin8, LOW); //
}
if (h > value)//RECORD
{
EEPROM.write (0,h);
EEPROM.write (1,h1);
}
smartdelay(500);
}
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
static void print_float(float val, float invalid, int len, int prec)
{
if (val == invalid)
{
while (len-- > 1)
Serial.print('*');
Serial.print(' ');
}
else
{
Serial.print(val, prec);
int vi = abs((int)val);
int flen = prec (val < 0.0 ? 2 : 1); // . and -
flen = vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; i)
Serial.print(' ');
}
smartdelay(0);
}
static void print_int(unsigned long val, unsigned long invalid, int len)
{
char sz[32];
if (val == invalid)
strcpy(sz, "*******");
else
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i<len; i)
sz[i] = ' ';
if (len > 0)
sz[len-1] = ' ';
Serial.print(sz);
smartdelay(0);
}
static void print_date(TinyGPS &gps)
{
int year;
byte month, day, hour, minute, second, hundredths;
unsigned long age;
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
if (age == TinyGPS::GPS_INVALID_AGE)
Serial.print("********** ******** ");
else
{
char sz[32];
sprintf(sz, "d/d/d d:d:d ",
month, day, year, hour, minute, second);
Serial.print(sz);
}
print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
smartdelay(0);
}

Подключение проводов к ардуино:

Провода

I2C: SDA pin A4 / SCL pin A5 /VCC pin 3,3V /GND pin GND (установить максимальная яркость и подсветку)

GPS: RX pin D4, TX pin D3, VCC pin 5V ,GND pin GND

Кнопка сброса (нормально разомкнутая кнопка): один контакт VCC pin 5V, другой контакт на pin D5, резистор на pin D5 и pin GND

Светодиоды: Фары передние (габариты) белые « » на pin D9

Светодиоды: Фары задние (габариты) красные « » на pin D10

Светодиод: Задний ход белый « » на pin D6

Светодиоды: Фары передние (габариты) белые « » на pin D9

Светодиод: Поворот влево оранжевый « » на pin D11

Светодиод: Поворот вправо оранжевый « » на pin D12

Светодиод: Мигалка красный « » на pin D2

Светодиод: Мигалка синий « » на pin D13

Для всех Светодиодов «-» на pin GND

Подключаем провод для поворотников на pin D7 от входа сервомашинки поворотов (три провода обычно это белый к нему подпаеваемся и выводим провод на pin D7, красный — питание плюс, черный — питание минус, подключается к приемнику).

Подключаем провод для движения на pin D8 от входа сервомашинки двигателя (три провода: обычно это белый, к нему подпаеваемся и выводим провод на pin D8, красный — питание плюс, черный — питание минус, подключается к приемнику).

Питание для Ардуино берется прямо из аккумулятора « » на pin VIN (в моем 7,2в). Общий провод GND для Ардуино прямо из аккумулятора «-».

Настройка: если не правильно срабатывает при поворотах или движении, то через программу на компьютере изменяем значения на свои: в строчках if ((durationХ > ХХХХ) && (durationХ < ХХХХ)) если не обрабатывается данные и горит зеленый светодиод на плате GPS, TX/RX возможно нужно поменять местами RX pin D4, TX pin D3,)

P.S. Идея оказалось несложной, зная программирование, можно еще добавить в эту машинку температуру в двигателе и оповещение о ней, добавить моточасы, тахометр и видеокамеру на «Mercedes-Benz GT3».

Всем удачи!

Исходный код программы

В программе первым делом необходимо инициализировать выходные контакты для подключения двигателей (через драйвер мотора).

Затем в функции setup задать направление работы для этих контактов (на вывод данных).

После этого мы будем считывать данные из последовательного порта Arduino, получаемые им от последовательного порта Bluetooth модуля, и выполнять соответствующие инструкции.

Затем мы запрограммируем функции для различных направлений движения машины. Всего будет использоваться пять условий для задания направления движения машины, представленных в следующей таблице:

Далее представлен полный текст программы.

Общие принципы управления машиной по bluetooth

Разрабатываемая нами машина будет управляться по протоколу Bluetooth с помощью приложения, установленного на мобильном телефоне с операционной системой Android. Для управления машиной нужно будет всего лишь нажимать кнопки в этом приложении. То есть телефон с Android будет выступать в роли передающего устройства, а Bluetooth модуль, расположенный на машине – в качестве приемного устройства, выполняющего все команды, поступающие с телефона (движение вперед, назад, направо, налево, остановка).

Bluetooth модуль структурно состоит из двух блоков: модуль последовательного интерфейса (для последовательной передачи данных) и адаптер Bluetooth. Модуль последовательного интерфейса предназначен для конвертации данных Bluetooth в данные для передачи по последовательному порту.

После приобретения модуля Bluetooth в магазине вам нет никакой необходимости изменять его настройки – он полностью готов к работе. По умолчанию скорость передачи данных у него составляет 9600 бод/с. Вам просто необходимо подсоединить его контакты rx и tx к микроконтроллеру и подать питающее напряжение постоянного тока 5 В.

Bluetooth модуль может работать в двух режимах: главный режим (master mode) и подчинённый режим (slave mode). Любой из этих режимов можно установить с помощью соответствующих АТ команд. Далее приведены некоторые из АТ команд.

Первым делом при работе с данным модулем необходимо войти в AT режим со скоростью передачи 38400 бод/с при помощи нажатия кнопки EN на Bluetooth модуле или с помощью подачи сигнала высокого уровня на контакт EN. Примечание: все команды должны заканчиваться rn (0x0d и 0x0a) или нажатием клавиши ENTER на клавиатуре.

После того как вы передадите на модуль AT команду модуль ответит вам OK (после ее выполнения).

AT → Test CommandAT ROLE=0 → Slave Mode select (выбор подчиненного режима)AT ROLE=1 → Master Mode select (выбор главного режима)AT NAME=xyz → Set Bluetooth Name (установка Bluetooth имени)AT PSWD=xyz → Set Password (установка пароля)AT UART=<value1>,<value2>,<value3> → set Baud rate (установка бодовой скорости)Eg. AT UART=9600,0,0

Распиновка Bluetooth модуля:1. STATE → Open (открыто)2. Rx → Serial receiving pin (контакт приема данных)3. Tx → Serial transmitting pin (контакт передачи данных)4. GND → ground (земля)5. Vcc → 5volt dc ( 5 В постоянного тока)6. EN → to enter in AT mode (вход в AT режим)

Определение угла поворота

За поворот машинки отвечает на удивление не сервопривод, а обычный двигатель. Встает проблема: хорошо бы было его не сжечь, ведь угол поворота ограничен, а крутиться двигатель может сколько угодно.

Вариант с методом тыка отпадает, так как при разном уровне батареи количество тока, подаваемое на двигатель, будет изменяться, что приведет к постоянно меняющемуся углу. Крутить до упора тоже нельзя, рано или поздно рассыплются шестеренки.

Решение проблемы: отслеживать угол через замыкание. На фото продемонстрирована небольшая штучка, которая крепится недалеко от поворотного механизма. На часть, которая крутится вместе с колесами влево/вправо двигателем, прикрепляется гребешок с железными контактами.

Принцип работы: к каждой линии припаивается провод (всего их четыре), нижний подключается к плюсу (он зажат гребешком всегда, см. картинку), остальные провода уходят на минус. Когда зубик гребешка попадает и на нижний ряд, и на, допустим, третий, происходит замыкание, ток течет, это замечает 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);
}

Простая 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);
}
}
}

Итак, вот такая у меня получилась машинка:

ARDUINO - Машинка на nrf24l01 | AlexGyver Community

Те, кому нравится дизайн в приложениях, могут немного поменять. Подробно описывать как это делать не буду, там не сложно самому разобраться. Скажу лишь, что для этого в основном нужно использовать .png файлы, вместо .jpeg, которые не поддерживают прозрачный фон. Например, сделать такой дизайн за полчаса или час сможет любой неподготовленный человек:

image

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

https://www.youtube.com/watch?v=y2jAJ05s2EQ

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

Работа схемы

Схема устройства представлена на следующем рисунке.

Схема роботизированной машины на Arduino, управляемая по BluetoothДрайвер мотора используется для управления двигателями машины. Его контакты 2, 7, 10 и 15 подсоединены к цифровым контактам Arduino 12, 11, 10 и 9 соответственно. Один из двигателей подключен к выходным контактам драйвера мотора 3 и 6, а другой – к контактам 11 и 14. Батарейка 6 Вольт также используется для питания драйвера мотора – а через него для питания двигателей. Контакты rx и tx Bluetooth модуля непосредственно подключены к контактам tx и rx платы Arduino. Батарейка 9 Вольт используется для подачи питания на контакт Arduino Vin.

Сборка

Можно купить готовое шасси для машинки сразу вместе с моторами и колёсами. Останется только установить электронику и всё подключить.

Но намного интереснее создать это самому. Для изготовления подойдёт любой листовой материал, который вам будет легко обрабатывать, и который достаточно лёгкий. Например, оргалит, текстолит, фанера. Я выбрал оргстекло, что сделало мою машинку даже очень похожей на шасси из магазина.

Из инструментов могут понадобиться:

  • Ручной или электрический лобзик (я пользовался ручным), чтобы отрезать нужные куски от материала.
  • Дрель или шуроповёрт, свёрла.
  • Крепёжные элементы — болты, гайки и саморезы любого подходящего диаметра.

Получилось дёшево и сердито. А главное работает.

Паять я тоже ничего не стал, чтобы потом можно было бы легко разобрать эту машинку и модернизировать. Припаивал только провода к моторам.

В магазинном наборе для крепления моторов используются специальный кронштейны, к которым сам мотор прикручивается болтами диаметром 3 мм. Но болтов нужного диаметра и длины у меня не оказалось, хоть и можно было изготовить аналогичный кронштейн. Поэтому пришлось изощряться и использоваться даже детали детского конструктора, чтобы надёжно прикрепить моторы. На видео крепление моторов рассмотрено лучше.

Платы в идеале лучше прикручивать короткими болтами с диаметром 3 мм. Но и таких у меня не оказалось. Поэтому пришлось делать в оргстекле отверстия 2 мм и прикручивать платы саморезами. Держится вполне нормально.

У модуля Bluetooth особая проблема крепления — там отверстий для крепления нет вообще. Пришлось прижимать плату к раме другой деталью из оргстекла. Тут главное не сжать слишком сильно, чтобы не повредить.

Аккумулятор крепится аналогично Bluetooth модулю, только снизу.

И обязательно прикручиваем мебельное поворотное колесо, которое станет опорным, и не будет приводным. Следите за тем, чтобы вся конструкция была в горизонтальном положении, когда стоит на всех трёх колёсах.

Шаг 1: нужные части и инструмент

Я воспользовался готовыми решениями, и все запчасти и инструменты были приобретены через интернет.

Запчасти:

  1. Набор шасси 4WD для робота (GearBest)
  2. Arduino Nano (GearBest)
  3. Модуль H-моста LM298 (GearBest)
  4. Модуль bluetooth HC-06 (Amazon)
  5. Литий-ионные батарейки 2 x 18650 (GearBest)
  6. Отсек для батареек 2x 18650 (GearBest)
  7. Небольшая макетная плата (GearBest)
  8. Провода сечением 0.5 мм2
  9. Провода с джамперами папа-мама (Amazon)
  10. Провода с джамперами мама-мама (Amazon)
  11. Малярная лента, изолента или что-то подобное (Amazon)

Для робота, объезжающего препятствия:

Ультразвуковой модуль измерения расстояния HC — SR04 (GearBest)

Необходимый инструмент :

  1. Паяльник (Amazon)
  2. Кусачки (Amazon)
  3. Стриппер для провод (GearBest)
  4. Клеевой пистолет (GearBest)

Шаг 11: источник питания

Чтобы управлять приводами (моторами) и питать контроллер, роботу нужен источник питания. Большинство роботов питается от батарей. Когда мы говорим о батареях, то имеем в виду множество вариантов:

  1. Алкалиновые батарейки AA (не заряжаются)
  2. Никель-металгидридные или никель-кадмиевые батарейки AA (заряжаются)
  3. Литий-ионные батареи
  4. Литий-полимерные батареи

В зависимости от ваших нужд, нужно выбрать подходящий вид батарей. По-моему мнению, нужно всегда выбирать заряжаемые батареи достаточной ёмкости. Я использовал 2 литий-ионные батареи стандарта 18650 ёмкостью 2600mAh. Если для автономности вам нужно больше мощности, используйте большой комплект батарей, например 5A turnigy.

Отсек для батарей:Отсек для батарей я заказал в Китае, он не подходил для батарей с плоским верхом, поэтому я использовал два неодимовых магнита для придания батарейкам нужной формы.

Зарядка:Для зарядки батарей нужен хороший зарядник. По моему опыту, эти зарядники хорошо зарекомендовали себя:

  1. PowerEx AA Charger-Analyzer (Amazon)
  2. XTAR LiIon Battery Charger (Amazon)
  3. Turnigy LiPo Battery Charger (Amazon)

Шаг 5. ардуино контроллер

Arduino UNO – это плата микроконтроллера с открытым исходным кодом, основой которой служит микроконтроллер Microchip ATmega328P и разработанная Arduino.cc.

Плата оснащена наборами цифровых и аналоговых пинов ввода/вывода (I/O), которые могут быть подключены к различным платам расширения (экранам) и другим цепям. Плата имеет 14 цифровых контактов, 6 аналоговых контактов и программируется с помощью Arduino IDE (интегрированная среда разработки)

Эталонный дизайн оборудования распространяется под лицензией Creative Commons Attribution Share-Alike 2.5 и доступен на веб-сайте Arduino. Макет и производственные файлы для некоторых версий оборудования также доступны. «Uno» означает один на итальянском языке и был выбран в честь выпуска Arduino Software (IDE) 1.0.

Плата Uno является первой в серии плат Arduino c USB и эталонной моделью для последующих платформ. ATmega328 на Arduino Uno поставляется с предварительно запрограммированным загрузчиком, который позволяет загружать новый код без использования внешнего аппаратного программера с использованием оригинального протокола STK500.

Микроконтроллеры обычно программируются с использованием диалекта функций из языков программирования C и C . В дополнение к использованию традиционных наборов инструментов компилятора проект Arduino предоставляет интегрированную среду разработки (IDE).

Шаг 6. h-мост (модуль lm 298)

Термин H-мост (англ. H-bridge) выведен из типичного графического представления такой схемы. Это схема, которая может приводить двигатель постоянного тока в прямом и обратном направлении, см. рисунок выше для понимания работы H-моста.

Он состоит из 4 электронных переключателей S1, S2, S3 и S4 (транзисторы / МОП-транзисторы (MOSFET) / IGBTS). Когда переключатели S1 и S4 замкнуты (а S2 и S3 разомкнуты), на двигатель идет положительное напряжение. Поэтому он вращается в прямом направлении.

Примечание. Переключатели в одном и том же плече (S1, S2 или S3, S4) никогда не замыкаются в одно и то же время, это приведет к короткому замыканию.

H-мосты доступны в виде интегральных микросхем, или вы можете создать свой собственный, используя 4 обычных транзистора или полевых транзистора (MOSFET). В нашем случае мы используем микросхему H-моста LM298, которая позволяет контролировать скорость и направление вращения двигателей. Ниже перейдем к описанию пинов:

Выход 1: двигатель постоянного тока 1 ” ” или шаговый двигатель A

Выход 2: двигатель постоянного тока 1 “-” или шаговый двигатель A-

Выход 3: двигатель постоянного тока 2 ” ” или шаговый двигатель B

Выход 4: двигатель B выведен

12В контакт: 12В вход, но вы можете использовать от 7 до 35 В

GND: земля

Вывод 5В: выход 5 В, если перемычка 12 В на месте, идеально подходит для питания вашего Arduino

EnA: включает сигнал ШИМ для двигателя А

IN1: включить двигатель A

IN2: включить двигатель A

IN3: включить двигатель B

IN4: включить двигатель B

EnB: включает сигнал ШИМ для двигателя B

Смотрите про коптеры:  GitHub - dsidov/ArduinoCar: Скетчи и инструкция для робота-машинки на базе Arduino.
Оцените статью
Радиокоптер.ру
Добавить комментарий