Еще одна простая машинка на NRF

Часть первая, теоретическая.
Для теории нам нужно: 2 ардуины нано,уно и вообще любых с подключенными к ним модулями NRF, сделано все точно так как у Гайвера в примерах.
Если вы внимательно смотрели его видео, то знаете, что связь на разных каналах осуществляться с разным качеством, поэтому первое, что я сделал так это озадачился выбором канала.
Та-дам! вот 2 скетча, котороые помогут вам это сделать.
Один из них (приемник), будет получать данные от другого (передатчика) по всем каналам диапазона и считать кол-во удачных попыток. Время это займет прилично, но при желании можно сделать еще дольше )
Можно немного настроить , изменив вот эту часть:
C++:
const int StartCH = 0;
const int EndCH = 127;
const int ChTime = 3;
const int StartTime = 2;
StartCH - с этого канала начнется сканирование
EndCH - этим каналом закончится все
ChTime время в секундах на примем - передачу на одном канале. как не трудно посчитать полное время будет более 6.5 минут
Все эти параметры в обоих скетчах должны быть идентичны!

Важный параметр!
const int StartTime = 2;
это время "отступа" начала от запуска ардуины. в одном скетче у меня стоит 1, в другом 2. Это значит тот скетч, который имеет большее значение StartTime надо запустить первым. Легкая рассинхронизация допускается )

Передающий модуль:
C++:
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"

RF24 radio(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};

const int StartCH = 0;
const int EndCH = 127;
const int ChTime = 3;
const int StartTime = 2;
bool f = true;
int cc = -1;
int rxdata[128];

byte counter;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);

  radio.begin(); //активировать модуль
  radio.setAutoAck(1);
  radio.setRetries(0, 15);
  radio.enableAckPayload();
  radio.setPayloadSize(32);
  radio.openReadingPipe(1, address[0]);
  radio.setPALevel (RF24_PA_MAX);
  radio.setDataRate (RF24_2MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  radio.powerUp();
  radio.stopListening();
}

void loop() {
  // put your main code here, to run repeatedly:
  byte pipeNo, gotByte;
  unsigned long t = millis();
  int chanel = (t - StartTime * 1000) / (ChTime * 1000);
  //Serial.println(chanel);
  if (f) {
    if (chanel == EndCH) {
      f = false;
    }



    if ((chanel >= StartCH) and (chanel <= EndCH))    {
      if (cc != chanel) {
        Serial.print("End TX "); Serial.print(cc); Serial.print(", start TX "); Serial.println(chanel);
        cc = chanel;
        radio.powerDown();
        radio.setChannel(chanel);
        radio.powerUp();
        radio.stopListening();
      }

      //!
      if ( radio.write(&counter, 1) ) {               //отправляем значение counter
        if (!radio.available()) {                   //если получаем пустой ответ
          //Serial.print("Empty, "); Serial.print(" Time: "); Serial.print(micros() - last_time); Serial.println(" microseconds"); Serial.println();
          rxdata[chanel]++;
        }
      } else {
        while (radio.available() ) {                    // если в ответе что-то есть
          radio.read( &gotByte, 1 );                  // читаем
          //Serial.print("Anser: "); Serial.print(gotByte); Serial.print(" Time: "); Serial.print(micros() - last_time); Serial.println(" microseconds"); Serial.println();
          //counter++;
          rxdata[chanel]++;
        }
      }

      delay(50);
      //!
    }

  }

  else

  {
    if (chanel == (EndCH + 1))
    {
      for (int i = StartCH; i < EndCH; i++) {
        Serial.print(i);Serial.print("=");Serial.println(rxdata[i]);
      }
      delay(1000 * (ChTime + 1));
    }

  }
}
Принимающий модуль:
C++:
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"

RF24 radio(9, 10);
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};

const int StartCH = 0;
const int EndCH = 127;
const int ChTime = 3;
const int StartTime = 1;
bool f = true;
int cc = -1;
int rxdata[128];


void setup() {
 
  Serial.begin(9600);

  radio.begin(); //активировать модуль
  radio.setAutoAck(1);
  radio.setRetries(0, 15);
  radio.enableAckPayload();
  radio.setPayloadSize(32);
  radio.openReadingPipe(1, address[0]);
  radio.setPALevel (RF24_PA_MAX);
  radio.setDataRate (RF24_2MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  //radio.powerUp()
}

void loop() {
  byte pipeNo, gotByte;
  unsigned long t = millis();
  int chanel = (t - StartTime * 1000) / (ChTime * 1000);
  //Serial.println(chanel);
  if (f) {
    if (chanel == EndCH) {
      f = false;
    }

    if ((chanel >= StartCH) and (chanel <= EndCH))    {
      if (cc != chanel) {
        Serial.print("End RX "); Serial.print(cc); Serial.print(", start RX "); Serial.println(chanel);
        cc = chanel;
        radio.stopListening();

        radio.setChannel(chanel);
        radio.startListening();
      }

      while ( radio.available(&pipeNo)) {   // слушаем эфир со всех труб
        radio.read( &gotByte, sizeof(gotByte) );         // чиатем входящий сигнал
        rxdata[chanel]++;
      }

    }
  }
  else
  {
    if (chanel == (EndCH + 1))
    {
      for (int i = StartCH; i < EndCH; i++) {
      Serial.print(i);Serial.print("=");Serial.println(rxdata[i]);
      }
      delay(1000 * (ChTime + 1));
    }
  }

}

Я был немного озадачен результатами, были выявлены каналы, на которых приме и передача вообще не осуществлялись. Но выбор всегда есть.

Продолжение скоро..
 

Комментарии

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

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
Часть вторая. машинная
Машинка представляет собой минимальное движущее средство с задним приводом и с рулевой рейкой на передние колеса, ни амортизаторов, ни тормозов. все предельно просто, т.к. вообще это тестовый вариант могу ли я)

Комплектующие таки:
Ардуина нано 168
модуль NRF24 с любой антенной
серва sg90
драйвер двигателя L298N
мотор-редуктор по вкусу на 6-7 вольт
2 банки 18650+плата зарядки для них
Гнездо питания, аналогичный арудиновскому
2-х позиционный переключатель.

Схему подключения рисовать надо, она у меня на бумажном носителе "только для себя"


Пояснения кода:
канал выбрал согласно 1-ому посту
Данные движения передаются 4-мя байтами
1-ый байт положение руля в процентах от -100 до 100
2-ой байт движение вперед-назад опять же в процентах от -100 до 100
3 и 4-ый байты оставлены под возможные кнопки на будущее. Кому мешают - убирайте сами)

Сервопривод подключен на 6-ой пин
Управление движением 3 и 5-ый пины.

Если посмотреть код движения, то можно увидеть, что максимальное значение движения ограничено 200-ми, при возможных 255, это сделано умышлено, что бы прикрутить кнопку нитро, но пока нет энтузиазма этим заниматься. если 200 заменить на 255 макс. скорость увеличится.
60 - это минимальное значение, которое передается на драйвер мотора, нужно подбирать для своего случая, моя машина при таком значении начинает минимально медленно двигаться, нет пустого движения управлением.
Но тогда получалось , что машинка дергалась при малейшем отклонении и бывало сложно ее остановить. для устранения этого сделана вот такая строка:
if (abs(Newgaz)<2){Newgaz=0;};

Значения газа и рулевого положения делятся на 5 (см. код) для того, что бы не сильно реагировать на мелкие дерганья управлением.

Код занимает 4,6кб памяти программы и 300 байт памяти, так что можно было бы и на чем то более мелком сделать, типа Аттини85, если бы знать как подключить NRF к ней. Они берут пины c 9 по 13 у nano. Т.е. выходит всего 8 занятых пинов, а у тиньки всего 6. Я этот вопрос не проветривал подробно.

C++:
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include <Servo.h>

const int chanel = 125;
int rul, gaz;

Servo Servo1;

RF24 RC_Car(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};

byte trans_data[] = {0, 0, 0, 0};

// функция вывода полученных значений для отладки
void trans_out()
{ Serial.print(trans_data[0]);
  Serial.print(" ");
  Serial.print(trans_data[1]);
  Serial.print(" ");
  Serial.print(trans_data[2]);
  Serial.print(" ");
  Serial.println(trans_data[3]);
};


void setup() {
  RC_Car.begin();
  RC_Car.setAutoAck(1);
  RC_Car.setRetries(0, 15);
  RC_Car.enableAckPayload();
  RC_Car.setPayloadSize(32);
  RC_Car.openReadingPipe(1, address[0]);
  RC_Car.setPALevel (RF24_PA_MAX);
  RC_Car.setDataRate (RF24_2MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  RC_Car.setChannel(chanel);
  RC_Car.powerUp();
  RC_Car.startListening();

  Servo1.attach(6);
  pinMode(5, OUTPUT);
  pinMode(3, OUTPUT);
// вертим колесами влево-вправо до упора и выставляем по центру
  Servo1.write(35);
  delay(300);
  Servo1.write(135);
  delay(300);
  Servo1.write(90);


//  Serial.begin(9600);
}

void loop() {
  delay(30);
  int Newrul, Newgaz;
  byte pipeNo;


  while (RC_Car.available(&pipeNo)) {   // слушаем эфир со всех труб
    RC_Car.read(&trans_data, sizeof(trans_data) );         // чиатем входящий сигнал
   // trans_out();
    Newrul = map(trans_data[0] / 5, 0, 40, 9, 27);
    //Serial.println(rul);
    if (Newrul != rul) {
      Servo1.write(Newrul * 5);
      rul = Newrul;
    };

    Newgaz = map(trans_data[1] / 5, 0, 40, -20, 20);

    if (abs(Newgaz)<2){Newgaz=0;};

    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);

      };
    }

  }
}

Часть третья, управленческая.
Для управления в данный момент используется стандартный шилд с джойстиком а-ля плейстейшн. Вперед, назад, вправо , влево, считываются аналоговые значение и все)
Код чуть ли не еще проще
Пульт работает на уно с подключенным шилдом батарейки , в примере он под комментарием
на А1 подключен поворот, на А0 направление движения
514 - это центральное положение для датчика А1, оно может отличаться для каждого пульта, подобрать самому.
Даже как то писал программу, которая сам определяет центр для джойстка, но почему то отказался от этого. Если нет шилда просто подключите 2 потенциометра к соотв. пинам и все. Я так и начинал тестировать.

C++:
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
// #include <Battery_Shield.h>              // Подключаем библиотеку Battery_Shield , если пульт сборка с шилдом. иначе убрать!


const int chanel=125;

// Battery_Shield pwrBank;
RF24 RC_Pult(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};


byte trans_data[] = {0, 0, 0, 0};
void trans_out()
{ Serial.print(trans_data[0]);
  Serial.print(" ");
  Serial.print(trans_data[1]);
  Serial.print(" ");
  Serial.print(trans_data[2]);
  Serial.print(" ");
  Serial.println(trans_data[3]);
};

void setup() {
  // put your setup code here, to run once:
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);


  Serial.begin(9600);
  digitalWrite(3,HIGH);
  RC_Pult.begin();
  RC_Pult.setAutoAck(1);
  RC_Pult.setRetries(0, 15);
  RC_Pult.enableAckPayload();
  RC_Pult.setPayloadSize(32);
  RC_Pult.openReadingPipe(1, address[0]);
  RC_Pult.setPALevel (RF24_PA_MAX);
  RC_Pult.setDataRate (RF24_2MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  RC_Pult.setChannel(chanel);
  RC_Pult.powerUp();
  RC_Pult.stopListening();
  //Serial.println(true);
//  Serial.println(pwrBank.begin(0.0128f));   
}

void loop() {


  byte gotByte;
  // put your main code here, to run repeatedly:
  
  if (analogRead(A1)>514)
    {trans_data[0] = map(analogRead(A1), 514, 1019, 100, 0);  }
  else
    {trans_data[0] = map(analogRead(A1), 10, 514, 200, 100);};

  if (analogRead(A0)>500)
    {trans_data[1] = map(analogRead(A0), 500, 1023, 100, 200);}
  else
  {trans_data[1] = map(analogRead(A0), 0, 500, 0, 100);};

  if (RC_Pult.write(&trans_data, sizeof(trans_data)))
    {
      while (RC_Pult.available() ) {                 
          RC_Pult.read( &gotByte, 1 );               
      };
    };
  delay(20);
//   trans_out(); вывод отладочной информации
}

Схема подключения компонентов для машинки
Схема не совсем точна, т.к. нет вместо 2-х аккумуляторов 18650 поставил то что нашёл: блок из 2х батареек. Аккумуляторы подключены к питанию зарядной платой FDC-2S-2, переключатель либо включает зарядку через гнездо, либо включает саму машинку.
Сам модуль NRF подключен через предназначенный для него адаптер, но его тоже не нашел, поэтому поставил просто модуль преобразования напряжения на 3.3 вольта
Ну а остальное вроде бы соответствует действительности. Стабильные 5 вольт беру с драйвера L298N, ими питаю ардуину и серву.

scema.jpg
 
Изменено:
  • Лойс +1
Реакции: Sashka969 и palikar

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

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
Амoжна пoдключить tb6612fng вместo l298n и шим сигнал
Можно, но возможно надо будет переписывать скетч. Я использовал то, что было в наличии на момент создания.
Ну и схема подключения будет другая конечно. так я с выхода l298n беру 5 в для питания сервы, а надо будет брать с самой ардуины
 

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

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
В целом да, переписать надо вот эту часть.

C++:
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);

      };
 

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

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
Можно, но там управление координально другое, а я не люблю переделывать чужое, там столько палок может быть, что не разберешься. Я люблю своими подпирать.
Там на самом деле все просто. Добивай на вывод еще 4-ый пин.
к примеру 3 и 4 ые пины будут задавать направление , а 5 , ШИМ, скорость.
код будет примерно такой:
C++:
if (gaz < 0)

      {
       digitalWrite(4,0);       
       digitalWrite(3,1);   
       analogWrite(5, map(abs(gaz),1,20,60,200));
      }
      else if (gaz > 0)
      {
       digitalWrite(3,0);       
       digitalWrite(4,1);   
       analogWrite(5, map(abs(gaz),1,20,60,200));
      }
      else
      {
       digitalWrite(3,0);       
       digitalWrite(4,0);
       digitalWrite(5,0);           
      };
 

mykhailo05

✩✩✩✩✩✩✩
4 Янв 2020
9
0
где изминить угoл
// вертим колесами влево-вправо до упора и выставляем по центру
Servo1.write(35);
delay(300);
Servo1.write(135);
delay(300);
Servo1.write(90)
 

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

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
изначальний угoл 35
35 и 135 - крайние положения. я специально так настроил серву и качалку, что при установки ее в 90 градусов она ехала прямо. угол поворота у меня по 45 градусов в обе стороны
 

mykhailo05

✩✩✩✩✩✩✩
4 Янв 2020
9
0
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include <Servo.h>

const int chanel = 125;
int rul, gaz;

Servo Servo1;

RF24 RC_Car(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};

byte trans_data[] = {0, 0, 0, 0};

// функция вывода полученных значений для отладки
void trans_out()
{ Serial.print(trans_data[0]);
Serial.print(" ");
Serial.print(trans_data[1]);
Serial.print(" ");
Serial.print(trans_data[2]);
Serial.print(" ");
Serial.println(trans_data[3]);
};


void setup() {
RC_Car.begin();
RC_Car.setAutoAck(1);
RC_Car.setRetries(0, 15);
RC_Car.enableAckPayload();
RC_Car.setPayloadSize(32);
RC_Car.openReadingPipe(1, address[0]);
RC_Car.setPALevel (RF24_PA_MAX);
RC_Car.setDataRate (RF24_2MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
RC_Car.setChannel(chanel);
RC_Car.powerUp();
RC_Car.startListening();

Servo1.attach(6);
pinMode(4, OUTPUT); // здесь пoд шим нужнo дoдавать чтoтo
pinMode(3, OUTPUT);
// вертим колесами влево-вправо до упора и выставляем по центру
Servo1.write(35);
delay(300);
Servo1.write(135);
delay(300);
Servo1.write(90);


// Serial.begin(9600);
}

void loop() {
delay(30);
int Newrul, Newgaz;
byte pipeNo;


while (RC_Car.available(&pipeNo)) { // слушаем эфир со всех труб
RC_Car.read(&trans_data, sizeof(trans_data) ); // чиатем входящий сигнал
// trans_out();
Newrul = map(trans_data[0] / 5, 0, 40, 9, 27);
//Serial.println(rul);
if (Newrul != rul) {
Servo1.write(Newrul * 5);
rul = Newrul;
};

Newgaz = map(trans_data[1] / 5, 0, 40, -20, 20);

if (abs(Newgaz)<2){Newgaz=0;};

if (gaz != Newgaz)
{
gaz = Newgaz;
if (gaz < 0)

{
digitalWrite(4,0);
digitalWrite(3,1);
analogWrite(5, map(abs(gaz),1,20,60,200));
}
else if (gaz > 0)
{
digitalWrite(3,0);
digitalWrite(4,1);
analogWrite(5, map(abs(gaz),1,20,60,200));
}
else
{
digitalWrite(3,0);
digitalWrite(4,0);
digitalWrite(5,0);
};
};
}

}
 

Артёмwundervafla

✩✩✩✩✩✩✩
8 Мар 2020
2
0
Часть вторая. машинная
Машинка представляет собой минимальное движущее средство с задним приводом и с рулевой рейкой на передние колеса, ни амортизаторов, ни тормозов. все предельно просто, т.к. вообще это тестовый вариант могу ли я)

Комплектующие таки:
Ардуина нано 168
модуль NRF24 с любой антенной
серва sg90
драйвер двигателя L298N
мотор-редуктор по вкусу на 6-7 вольт
2 банки 18650+плата зарядки для них
Гнездо питания, аналогичный арудиновскому
2-х позиционный переключатель.

Схему подключения рисовать надо, она у меня на бумажном носителе "только для себя"


Пояснения кода:
канал выбрал согласно 1-ому посту
Данные движения передаются 4-мя байтами
1-ый байт положение руля в процентах от -100 до 100
2-ой байт движение вперед-назад опять же в процентах от -100 до 100
3 и 4-ый байты оставлены под возможные кнопки на будущее. Кому мешают - убирайте сами)

Сервопривод подключен на 6-ой пин
Управление движением 3 и 5-ый пины.

Если посмотреть код движения, то можно увидеть, что максимальное значение движения ограничено 200-ми, при возможных 255, это сделано умышлено, что бы прикрутить кнопку нитро, но пока нет энтузиазма этим заниматься. если 200 заменить на 255 макс. скорость увеличится.
60 - это минимальное значение, которое передается на драйвер мотора, нужно подбирать для своего случая, моя машина при таком значении начинает минимально медленно двигаться, нет пустого движения управлением.
Но тогда получалось , что машинка дергалась при малейшем отклонении и бывало сложно ее остановить. для устранения этого сделана вот такая строка:
if (abs(Newgaz)<2){Newgaz=0;};

Значения газа и рулевого положения делятся на 5 (см. код) для того, что бы не сильно реагировать на мелкие дерганья управлением.

Код занимает 4,6кб памяти программы и 300 байт памяти, так что можно было бы и на чем то более мелком сделать, типа Аттини85, если бы знать как подключить NRF к ней. Они берут пины c 9 по 13 у nano. Т.е. выходит всего 8 занятых пинов, а у тиньки всего 6. Я этот вопрос не проветривал подробно.

C++:
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include <Servo.h>

const int chanel = 125;
int rul, gaz;

Servo Servo1;

RF24 RC_Car(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};

byte trans_data[] = {0, 0, 0, 0};

// функция вывода полученных значений для отладки
void trans_out()
{ Serial.print(trans_data[0]);
  Serial.print(" ");
  Serial.print(trans_data[1]);
  Serial.print(" ");
  Serial.print(trans_data[2]);
  Serial.print(" ");
  Serial.println(trans_data[3]);
};


void setup() {
  RC_Car.begin();
  RC_Car.setAutoAck(1);
  RC_Car.setRetries(0, 15);
  RC_Car.enableAckPayload();
  RC_Car.setPayloadSize(32);
  RC_Car.openReadingPipe(1, address[0]);
  RC_Car.setPALevel (RF24_PA_MAX);
  RC_Car.setDataRate (RF24_2MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  RC_Car.setChannel(chanel);
  RC_Car.powerUp();
  RC_Car.startListening();

  Servo1.attach(6);
  pinMode(5, OUTPUT);
  pinMode(3, OUTPUT);
// вертим колесами влево-вправо до упора и выставляем по центру
  Servo1.write(35);
  delay(300);
  Servo1.write(135);
  delay(300);
  Servo1.write(90);


//  Serial.begin(9600);
}

void loop() {
  delay(30);
  int Newrul, Newgaz;
  byte pipeNo;


  while (RC_Car.available(&pipeNo)) {   // слушаем эфир со всех труб
    RC_Car.read(&trans_data, sizeof(trans_data) );         // чиатем входящий сигнал
   // trans_out();
    Newrul = map(trans_data[0] / 5, 0, 40, 9, 27);
    //Serial.println(rul);
    if (Newrul != rul) {
      Servo1.write(Newrul * 5);
      rul = Newrul;
    };

    Newgaz = map(trans_data[1] / 5, 0, 40, -20, 20);
 
    if (abs(Newgaz)<2){Newgaz=0;};
 
    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);

      };
    }

  }
}

Часть третья, управленческая.
Для управления в данный момент используется стандартный шилд с джойстиком а-ля плейстейшн. Вперед, назад, вправо , влево, считываются аналоговые значение и все)
Код чуть ли не еще проще
Пульт работает на уно с подключенным шилдом батарейки , в примере он под комментарием
на А1 подключен поворот, на А0 направление движения
514 - это центральное положение для датчика А1, оно может отличаться для каждого пульта, подобрать самому.
Даже как то писал программу, которая сам определяет центр для джойстка, но почему то отказался от этого. Если нет шилда просто подключите 2 потенциометра к соотв. пинам и все. Я так и начинал тестировать.

C++:
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
// #include <Battery_Shield.h>              // Подключаем библиотеку Battery_Shield , если пульт сборка с шилдом. иначе убрать!


const int chanel=125;

// Battery_Shield pwrBank;
RF24 RC_Pult(9, 10); // "создать" модуль на пинах 9 и 10 Для Уно
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};


byte trans_data[] = {0, 0, 0, 0};
void trans_out()
{ Serial.print(trans_data[0]);
  Serial.print(" ");
  Serial.print(trans_data[1]);
  Serial.print(" ");
  Serial.print(trans_data[2]);
  Serial.print(" ");
  Serial.println(trans_data[3]);
};

void setup() {
  // put your setup code here, to run once:
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);


  Serial.begin(9600);
  digitalWrite(3,HIGH);
  RC_Pult.begin();
  RC_Pult.setAutoAck(1);
  RC_Pult.setRetries(0, 15);
  RC_Pult.enableAckPayload();
  RC_Pult.setPayloadSize(32);
  RC_Pult.openReadingPipe(1, address[0]);
  RC_Pult.setPALevel (RF24_PA_MAX);
  RC_Pult.setDataRate (RF24_2MBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  RC_Pult.setChannel(chanel);
  RC_Pult.powerUp();
  RC_Pult.stopListening();
  //Serial.println(true);
//  Serial.println(pwrBank.begin(0.0128f));    
}

void loop() {


  byte gotByte;
  // put your main code here, to run repeatedly:
   
  if (analogRead(A1)>514)
    {trans_data[0] = map(analogRead(A1), 514, 1019, 100, 0);  }
  else
    {trans_data[0] = map(analogRead(A1), 10, 514, 200, 100);};

  if (analogRead(A0)>500)
    {trans_data[1] = map(analogRead(A0), 500, 1023, 100, 200);}
  else
  {trans_data[1] = map(analogRead(A0), 0, 500, 0, 100);};

  if (RC_Pult.write(&trans_data, sizeof(trans_data)))
    {
      while (RC_Pult.available() ) {                  
          RC_Pult.read( &gotByte, 1 );                
      };
    };
  delay(20);
//   trans_out(); вывод отладочной информации
}
Здравствуйте не могли бы вы оставить ссылку на схему подключения приёмника.
 

palikar

✩✩✩✩✩✩✩
22 Янв 2020
9
0
Калининград
@Старик Похабыч, спасибо за скетч, то что нужно. Долго искал. Вот только проблема есть. Ардуино, которая на приёмнике, виснет почти всегда. Даю газу, на моторчик, погазую чуть и всё, на этих же оборотах и виснет, мотор крутится и ардуино на команды не реагирует. Что может быть?
Код писать не умею, могу только подправить что-то по рекомендации чьей-то.
 

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

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
От чего питается ардуина на приемнике ? Я беру 5 воль с самого драйвера, т.е. стабилизированное питаени. Если брать из другого места могут быть такие вот глюки, говорят конденсатор по питанию помогает.

"Погазую чуть" это сколько по времени ?
Пример покатушек:

А акб не может быт слабозаряжен ?
 

palikar

✩✩✩✩✩✩✩
22 Янв 2020
9
0
Калининград
Проверяю пока всё на макетной плате. Питание от телефонной зарядки 5v 1A, и ардуино и драйвер. Драйвер MX1508 1586164874229.png. По времени газую по-разному, бывает сразу виснет, бывает пару раз газануть, бывает побольше. И это одинаково виснет, хоть от зарядки, хоть питание от самой ардуино. Так нельзя, но кратковременно пробовал.
 

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

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
Я бы проверил обратные токи, поставил бы конденсатор на питание ардуины. Или попробовать вообще развязать питание драйвера и ардуины.
В этом видео :
на 10-ой минуте тоже завис приемник. Там помогло разделение питания вроде бы.
 

palikar

✩✩✩✩✩✩✩
22 Янв 2020
9
0
Калининград
@Старик Похабыч, попробовал раздельное питание, ардуино от паурбанка, nrf от ардуино, серва и драйвер от зарядки - работает нормально. Кондер ставить не пробовал. Очень не хотелось раздельное питание, но, по ходу, от этого никуда не денешься.
Спасибо за ответ.
 

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

★★★★★★★
14 Авг 2019
4,192
1,281
Москва
Хоть драйвер L298N не любят, но у него есть выход 5 в, который я и использовал для логики, он уже защищен от помех двигателей.