ARDUINO Машинка на nrf24l01

MrDjeb

★✩✩✩✩✩✩
Здарова всем, хочу поделиться своим проектом - машинка под управлением nrf24l01. Машинка получилась очень резвая и быстрая.
Управляется за счёт двух джойстиков от приставки. Ездит на 2 колёсах и одной шаровой опоре.
Делалась она из того, что было, а именно, из какого-то светорассеивающего оргстекла, пульт из распределительной коробки. Корпус это две пластинки из светорассеивающего оргстекла, которые скреплены между собой шестью спейсерами длиной 2 см. Размеры машинки: прямоугольник 10x15 см, у которого спереди по бокам срезано два треугольника 2.5x5 cм, высота 2 см. Размер распределительной коробки: 4 см высота, диаметр 10 см.


фото
P_20180731_172610[1].jpg P_20180731_172521[1].jpg P_20180731_172558[1].jpg

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

КОМПОНЕНТЫ ПУЛЬТА
  • arduino nano
  • nrf24l01 без антенны c адаптером
  • Аккумулятор 610мАч 7.4А (две банки)
  • Джойстики X2
  • Выключатель
Фото внутренностей
P_20180731_181023[1].jpg
КОМПОНЕНТЫ МАШИНКИ
  • arduino nano
  • nrf24l01 с антенной и адаптером
  • Аккумулятор 610мАч 7.4В (две банки)
  • Драйвер моторов двухканальный Pololu на TB6612FNG v2 <1А
  • Мотор-редуктор Gekko MR12-050 turbo X2
  • Колесо Pololu 32x7 X2
  • Выключатель
Фото внутренностей
P_20180731_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. Скачать скетчи можно по ссылке.
КОД ПУЛЬТА
C++:
/*   Данный скетч модернизация скетча 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
C++:
/*   Данный скетч модернизация скетча 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);
      }
  }
}
Я думаю, нужно усовершенствовать код. И машинке хорошо бы придумать применение, чтоб она не только была как игрушка для детей. К примеру, сверху держатель для бутылки приделать, чтобы возить напитки, не вставая с дивана, но это слишком просто. Предлагайте свои идеи по поводу кода и апгрейда. Кстати скоро выйдет версия с камерой как у Алекса.
Всем спасибо за внимание!
 
Изменено:

qazwsx1212

✩✩✩✩✩✩✩
4 Авг 2018
1
1
управление пвм сигналом (серво, модельные регуляторы и проч.)
 
Привет, в данной конфигурации вращение колес зависимое, то есть: для поворота влево - левый мотор должен работать на 50% медленнее правого, потому что радиусы для поворота разные (трансмиссия вида МОСТ).
Тебе надо пропорционально снижать их скорости.
Через constrain'ы, которые будут вычитать:
Добавить диапазоны влево-право от стика и далее.
При стике влево: левое колесо минус значение 50% стика (влево), ну а направо тоже самое только наоборот.
 

MrDjeb

★✩✩✩✩✩✩
Кстати, если вычитать из скорости езды вперёд(x1p) скорость поворота (y2r, y2l), а не складывать как раньше. То на максимальной скорости можно будет поворачивать нормально, а на маленькой скорости можно будет поворачивать так-же тупо, как на максимальной раньше.
 

MrDjeb

★✩✩✩✩✩✩
Привет, в данной конфигурации вращение колес зависимое, то есть: для поворота влево - левый мотор должен работать на 50% медленнее правого, потому что радиусы для поворота разные (трансмиссия вида МОСТ).
Тебе надо пропорционально снижать их скорости.
Через constrain'ы, которые будут вычитать:
Добавить диапазоны влево-право от стика и далее.
При стике влево: левое колесо минус значение 50% стика (влево), ну а направо тоже самое только наоборот.
А вот если брать значение процентов со стика, тогда я смогу изменять радиус поворота. Чем сильнее стик к примеру вправо согнуть тем больше процент (коофицент) поворота. Спасибо, надо попробовать!
 
Наоборот! она появится, так как вычитание "газа" для поворота будет пропорциональным между стиком поворота и самим маневром. Но для такой схемы рекомендую один стик сделать именно для вперед-назад, другой руления. Рекомендую выкинуть стики ардуиновские и заменить например с БУ от Playstation (или у кого найти даром более менее качественный пульт от сломанной игрушки). А то на ардуиновских угол работы около 10-14%, для такого проекта пойдет, а вот более веселой машинки уже будет очень неудобно.
 
На хороших стиках диапазон "выше" за счет угла работы, можно изменять более плавно. Особенно если машинка едет выше 10км/ч (моя была 25+ 3д принт) или аккуратного преодоления препятствий.

Можем в ВК посидеть, https://vk.com/nashatirko
 

Tsepa

✩✩✩✩✩✩✩
22 Июн 2019
18
1
@MrDjeb, Не правильно нарисована схема подключения моторов к драйверу,перепроверьте пожалуйста
 
Изменено:
  • Лойс +1
Реакции: Nick_79

MrDjeb

★✩✩✩✩✩✩
@MrDjeb, Не правильно нарисована схема подключения моторов к драйверу,перепроверьте пожалуйста
Хорошо проверю. Скоро выложу обещанную версию, к тому же, с презентацией к ней.
 

MrDjeb

★✩✩✩✩✩✩
0J4621.600x480.jpg
По логике, контакты на этом фото отражены зеркально относительно моей схемы. Но всё равно вижу, что там что-то не ладное-GND вместо VCC. В ближайшее время исправлю.
 

Tsepa

✩✩✩✩✩✩✩
22 Июн 2019
18
1
@MrDjeb, Вместо этого один проводок от мотора подключен к земле
 

UnckleM

✩✩✩✩✩✩✩
29 Авг 2019
5
0
а можно ли подключить еще один мотор (плюс двк кнопки к нему: за часовой и против часовой без регулирования скорости)? тоисть еще один драйвер моторов? я только начинаю с ардуино и мало понимаю
 

MrDjeb

★✩✩✩✩✩✩
а можно ли подключить еще один мотор (плюс двк кнопки к нему: за часовой и против часовой без регулирования скорости)? тоисть еще один драйвер моторов? я только начинаю с ардуино и мало понимаю
Если хотите подключить ещё один похожий мотор, то нужен ещё один драйвер. Данный драйвер рассчитан на два мотора, с характеристиками: рекомендуемое напряжение двигателя (VMOT) от 4.5 V до 13.5 V, непрерывной выходной ток 1 A на канал.
 

UnckleM

✩✩✩✩✩✩✩
29 Авг 2019
5
0
Если хотите подключить ещё один похожий мотор, то нужен ещё один драйвер. Данный драйвер рассчитан на два мотора, с характеристиками: рекомендуемое напряжение двигателя (VMOT) от 4.5 V до 13.5 V, непрерывной выходной ток 1 A на канал.
драйвер сменил на помошнее L298N. Подключаю ещё один мотор(третий). Беру ещё один L298N. И нужен (если я правильно понимаю) ещё один ШИМ выход.
 

MrDjeb

★✩✩✩✩✩✩

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
Я L298 подключал по 2 шимам, перемычки были установлены ниже кусок кода
Небольшие пояснения. моторы на полную мощность не включаю, вместо 255, ограничил 200, т.к. в последствии планирую сделать кнопку турбо, вот она будет врубать максимум, постоянно работать не будет.
изменение скорости происходит только при изменении передаваемого значения . принимает значение от -20 до 20, что бы уменьшить дребезг. -20 полный назад, 20 полный вперед.
так, что на 1 мотор я трачу только 2 цифровых вывода,
C++:
if (gaz != Newgaz)
    {
      gaz = Newgaz;
      if (gaz < 0)
      {
        analogWrite(3, 0);  
        analogWrite(5, map(abs(gaz),1,20,60,200));
        Serial.println(map(abs(gaz),1,20,60,200));  
      }
      else if (gaz > 0)
      {
        analogWrite(3, map(gaz,1,20,60,200));
        analogWrite(5, 0);
        //Serial.println(map(abs(gaz),1,20,60,200));
      }
      else
      {
        analogWrite(3, 0);
        analogWrite(5, 0);

      };
    }

из с L298 беру 5 вольт на питание сервы, что пропадать бес толку хорошему выходу :D
На схеме крона, а на самом деле стоит 2 акб 18650 c платой зарядки. Переключатель либо включает машинку, либо переключает на разъем питания для зарядки

rc_car.png

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

UnckleM

✩✩✩✩✩✩✩
29 Авг 2019
5
0
вот такая схема. мне подключить еще один мотор(только один через драйвер) и концевики к нему и не знаю как подключить. машинка едет вперед назад поворачивает на двух моторах (левый плюс правый). еще однм мотор переворачивает машинку по нажатию кнопни. по нажатию другойй кнопки механизм переворота прячется (мотор1 крутится в другую сторону). незнаю как лучше зделать тот мотор на время гдето пол секунды или на концевик.
moya.jpg
.
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,159
1,267
Москва
вот такая схема. мне подключить еще один мотор(только один через драйвер) и концевики к нему и не знаю как
А зачем 3-ий мотору и функционал концевиков ? D2 и D5 можно освободить. Замкнув джамперы