nrf24l01 прием и передача

zDimaBY
Offline
Зарегистрирован: 10.06.2018

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

Код пульта

#include <SPI.h>  // Подключаем библиотеку для работы с SPI-интерфейсом
#include "nRF24L01.h" // Подключаем файл конфигурации из библиотеки RF24
#include "RF24.h" // Подключаем библиотеку для работа для работы с модулем NRF24L01
#include "printf.h" // Инфо NRF24L01
#include <Servo.h>

RF24 radio(9, 10); // CE, CSN модуль nrf24l01 + pa + lna на пинах RF24 radio(9,10); Для Уно/нано. RF24 radio(9,53); для Меги.

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

byte transmit_data[4];
byte recieved_data[4];

float vin = 0.0;
int valMotor;
int valServo1;
int valServo2;
int valServo3;
const int potPinMotor = 0;
const int potPinRole = 1;
const int potContainerServo1 = 3;
const int potContainerServo2 = 4;

int timeout = 500; // переменные для разрыва связи
int lastTime = 0;

void setup() {
  Serial.begin(115200);
  pinMode(potPinMotor, INPUT);
  pinMode(potPinRole, INPUT);
  pinMode(potContainerServo1, INPUT);
  pinMode(potContainerServo2, INPUT);

  radio.begin();
  radio.setAutoAck(1);         //режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);    //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах
  radio.openWritingPipe(address[0]);   //мы - труба 0, открываем канал для передачи данных
  radio.openReadingPipe(0, address[1]);      //хотим слушать трубу 0
  radio.setChannel(0x71);  //( Автовыбор канала в котором нет шумов!)
  radio.setPALevel (RF24_PA_MAX); //RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS);//скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  //должна быть одинакова на приёмнике и передатчике!
  radio.powerUp();
  radio.stopListening(); //перестайом слушать эфир, мы передаваемый модуль
  printf_begin();
  radio.printDetails();
}
void loop() {
  valMotor = analogRead(potPinMotor);
  valMotor = map(valMotor, 0, 1023, 25, 255);
  transmit_data[0] = valMotor;
  valServo1 = analogRead(potPinRole);
  valServo1 = map(valServo1, 0, 1023, 80, 103);
  transmit_data[1] = valServo1;
  valServo2 = analogRead(potContainerServo1);
  valServo2 = map(valServo2, 0, 1023, 0, 179);
  transmit_data[2] = valServo2;
  valServo3 = analogRead(potContainerServo2);
  valServo3 = map(valServo3, 0, 1023, 0, 179);
  transmit_data[3] = valServo3;
  //  Serial.print("valMotor: ");
  //Serial.println(transmit_data[0]);
  radio.write(&transmit_data, sizeof(transmit_data));
  radio.startListening();  //начинаем слушать эфир, мы приёмный модуль
  byte pipeNo;
      while (radio.available(&pipeNo)) {    // слушаем эфир со всех труб
        lastTime = millis();
        radio.read( &recieved_data, sizeof(recieved_data) );         // чиатем входящий сигнал
        Serial.println(recieved_data[0]);
      }
  int dt = millis() - lastTime;
  if (dt >= timeout) {
    Serial.println(dt);
  }
  radio.stopListening(); //перестайом слушать эфир, мы передаваемый модуль
}

Код катера

#include <SPI.h>  // Подключаем библиотеку для работы с SPI-интерфейсом
#include "nRF24L01.h" // Подключаем файл конфигурации из библиотеки RF24
#include "RF24.h" // Подключаем библиотеку для работа для работы с модулем NRF24L01
#include "printf.h" // Инфо NRF24L01
#include <Servo.h>

Servo motor;
Servo servo1;
Servo servo2;
Servo servo3;

RF24 radio(9, 10); // CE, CSN модуль nrf24l01 + pa + lna на пинах RF24 radio(9,10); Для Уно/нано. RF24 radio(9,53); для Меги.

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

int timeout = 500; // переменные для разрыва связи
int lastTime = 0;

float vout = 0.0; // переменные для вольтметра
float vin = 0.0;
float R1 = 61000.0; // резистор в R1 (60K)
float R2 = 10000.0; // резистор в R2 (10K)
int value = 0;

byte recieved_data[4];
byte transmit_data[4];

void setup(){
  motor.attach(2);
  servo1.attach(3);
  servo2.attach(4);
  servo3.attach(5);
 
  Serial.begin(115200); //открываем порт для связи с ПК
  radio.begin(); //активировать модуль
  printf_begin(); // 
  radio.setAutoAck(1);         //режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);     //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах
  radio.openWritingPipe(address[1]);   //мы - труба 0, открываем канал для передачи данных
  radio.openReadingPipe(1, address[0]);      //хотим слушать трубу 0
  radio.setChannel(0x71);  //выбираем канал (в котором нет шумов!)
  radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS при самой низкой скорости имеем самую высокую чувствительность и дальность!!
  //должна быть одинакова на приёмнике и передатчике!
  radio.printDetails();
  radio.powerUp(); //начать работу
  radio.startListening();  //начинаем слушать эфир, мы приёмный модуль
  for (int i=0; i <= 255; i++){
      motor.write(i);
      delay(10);
      Serial.print(i);
   }
  delay(2000);
  for (int i=255; i >= 30; i--){
      motor.write(i);
      delay(10);
      Serial.print(i);
   }
   delay(2000);
}
void loop() {
  byte pipeNo;   
      while (radio.available(&pipeNo)) {    // слушаем эфир со всех труб
        lastTime = millis();
        radio.read( &recieved_data, sizeof(recieved_data) );         // чиатем входящий сигнал
        motor.write(recieved_data[0]);
        servo1.write(recieved_data[1]);
        servo2.write(recieved_data[2]);
        servo3.write(recieved_data[3]);
        Serial.print("valMotor: ");
        Serial.println(recieved_data[0]);
      }
  int dt = millis() - lastTime;
  if (dt >= timeout) {
    Serial.println(dt);
    motor.write(29);
    servo1.write(92);
  }
  radio.stopListening(); //перестайом слушать эфир, мы передаваемый модуль
  value = analogRead(A0);
  vout = (value * 5.0) / 1024.0;
  vin = vout / (R2/(R1+R2));
  transmit_data[0] = vin; //Отправляем данные АКБ
  Serial.println(transmit_data[0]);
  radio.write(&transmit_data, sizeof(transmit_data));
  radio.startListening();  //начинаем слушать эфир, мы приёмный модуль
}

 

iconini13ya
Offline
Зарегистрирован: 04.04.2021

Сам с таким боролся - надеюсь поможет - короче - если nrf без антенн - накрути на нее тонкую проволоку колец 20 и сделай усы. Так - сигнал точно будет хорошо доходить. Скидываю фото - как на нем. (надеюсь будет видно). Если не помогло - отпишись, может глубже в код залезу - помогу
 

iconini13ya
Offline
Зарегистрирован: 04.04.2021

Также ,на сколько я понял ты взял пример AG. Попробуй просканить территорию, возможно тот канал, который ты используешь - захламлен 

iconini13ya
Offline
Зарегистрирован: 04.04.2021

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

iconini13ya
Offline
Зарегистрирован: 04.04.2021

Пример моего кода для настройки 
 

void radioSetup() {                        // настройка радио модуля
  radio.begin();                           // активировать модуль
  radio.setAutoAck(1);                     // режим подтверждения приёма, 1 вкл 0 выкл
  radio.setRetries(0, 15);                 // (время между попыткой достучаться, число попыток)
  radio.setPayloadSize(32);                // размер пакета, байт
  radio.openReadingPipe(1, address[0]);    // хотим слушать трубу 0
  radio.openWritingPipe(address[1]);       // хотим писать на трубу по первому адресу
  radio.setChannel(CH_NUM);                // выбираем канал
  radio.setPALevel(SIG_POWER);             // задаем уровень мощности передатчика RF24_PA_MAX
  radio.setDataRate(SIG_SPEED);            // задаем скорость обмена RF24_1MBPS
                                           // должна быть одинакова на приёмнике и передатчике!
                                           // при самой низкой скорости имеем самую высокую чувствительность и дальность!! (логично)
  radio.powerUp();                         // начать работу
  radio.startListening();                  // начинаем слушать эфир, мы приёмный модуль
} 

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Вы с благородным доном  rumata поговорите. У него железные нервы и он с этой хернёй работал. У меня не получилось -  нервный я, похоже...

iconini13ya
Offline
Зарегистрирован: 04.04.2021

mykaida пишет:

Вы с благородным доном  rumata поговорите. У него железные нервы и он с этой хернёй работал. У меня не получилось -  нервный я, похоже...


Зачастую из-за китайских ручек сигнал просто-напросто не пробивает. Думаю человек решит вопрос как только намотает 20 виточков медного провода вокруг nrf

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

zDimaBY пишет:
Подскажите лучше
Знаю, что меня сейчас обматерят и назовут рукожопом (в целом, справедливо), но всё же скажу, лучше возьмите LORA и не трахайте себе мозг :-) Катер же может и отъехать немного. Дальнобойности Лоры точно хватит, а NRF ... я бы не связывался.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

mykaida пишет:

Вы с благородным доном  rumata поговорите. У него железные нервы и он с этой хернёй работал. У меня не получилось -  нервный я, похоже...

А я ведь предупреждал)) 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Rumata пишет:

mykaida пишет:

Вы с благородным доном  rumata поговорите. У него железные нервы и он с этой хернёй работал. У меня не получилось -  нервный я, похоже...

А я ведь предупреждал)) 

В итоге купил ESP32. Дон Румата - Вы были на 100% правы. херня.

zDimaBY
Offline
Зарегистрирован: 10.06.2018

Конденсаторы стоят, эфир чист, питание от специального стабилизатора для NRF24L01. Но когда модули используют 1 роль: 1-й модуль передатчик, 2-й приемник тогда работает без нареканий плавал в 740 метров от передатчика. У меня модуль nrf24l01 + pa + lna

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

Так вот экспериментировал.. так как в ответе приёмника могут присутствовать и те данные которые мы хотим отправить передатчику.

radio.writeAckPayload (1, &ackData, sizeof(ackData) );     // Помещаем данные всего массива ackData в буфер FIFO. Как только будут получены любые данные от передатчика на 1 трубе, то данные из буфера FIFO будут отправлены этому передатчику вместе с пакетом подтверждения приёма его данных.

Но при этих условия модули используют только 1 роль приемник и передатчик. но что-то у меня не работает.(пока что)

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

zDimaBY, спацифика проблем NRF24 как раз связана с отработкой ack на разных версиях модуля. Проблема на системном уровне не решаемая в принципе, поскольку относится к степени кривизны конкретного клона модуля. В идеале (не для идеальной работы, а для снятия части проблем),  автоответ желательно отключать. Роли - это вообще немного о другом. Я бы прислушался к совету ЕвгенияП по поводу ЛорЫ. Катер целее будет, да и ебли с кодом в разы меньше

b707
Offline
Зарегистрирован: 26.05.2017

Rumata пишет:

zDimaBY, спацифика проблем NRF24 как раз связана с отработкой ack на разных версиях модуля.

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

не знаю, не испытывал проблем заставить НРФ-ки работать с переключением между  приемом и передачей.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

b707 пишет:

Rumata пишет:

zDimaBY, спацифика проблем NRF24 как раз связана с отработкой ack на разных версиях модуля.

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

не знаю, не испытывал проблем заставить НРФ-ки работать с переключением между  приемом и передачей.

Да, все так, это базовая практика. АвтоАск первым отключается при поиске проблем. Но только проблемы на этом не заканчиваются)) 

Green
Offline
Зарегистрирован: 01.10.2015

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

zDimaBY
Offline
Зарегистрирован: 10.06.2018

Передатчик 

#include <SPI.h>  // Подключаем библиотеку для работы с SPI-интерфейсом
#include "nRF24L01.h" // Подключаем файл конфигурации из библиотеки RF24
#include "RF24.h" // Подключаем библиотеку для работа для работы с модулем NRF24L01
#include "printf.h" // Инфо NRF24L01
#include <Servo.h>

RF24 radio(9, 10); // CE, CSN модуль nrf24l01 + pa + lna на пинах RF24 radio(9,10); Для Уно/нано. RF24 radio(9,53); для Меги.

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

byte transmit_data[4];
float ackData[1];

int valMotor;
int valServo1;
int valServo2;
int valServo3;
const int potPinMotor = 0;
const int potPinRole = 1;
const int potContainerServo1 = 3;
const int potContainerServo2 = 4;

void setup() {
  Serial.begin(115200);
  pinMode(potPinMotor, INPUT);
  pinMode(potPinRole, INPUT);
  pinMode(potContainerServo1, INPUT);
  pinMode(potContainerServo2, INPUT);

  radio.begin();
  //radio.setRetries(0, 15);    //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах
  radio.openWritingPipe(address[0]);   //мы - труба 0, открываем канал для передачи данных
  radio.setChannel(0x71);  //( Автовыбор канала в котором нет шумов!)
  radio.setPALevel (RF24_PA_MAX); //RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS);//скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  //должна быть одинакова на приёмнике и передатчике!
  printf_begin();
  radio.printDetails();
}

void loop() {
  valMotor = analogRead(potPinMotor);
  valMotor = map(valMotor, 0, 1023, 25, 255);
  transmit_data[0] = valMotor;
  valServo1 = analogRead(potPinRole);
  valServo1 = map(valServo1, 0, 1023, 80, 103);
  transmit_data[1] = valServo1;
  valServo2 = analogRead(potContainerServo1);
  valServo2 = map(valServo2, 0, 1023, 0, 179);
  transmit_data[2] = valServo2;
  valServo3 = analogRead(potContainerServo2);
  valServo3 = map(valServo3, 0, 1023, 0, 179);
  transmit_data[3] = valServo3;
  radio.write(&transmit_data, sizeof(transmit_data));
  if( radio.isAckPayloadAvailable()){  // Если в буфере имеются принятые данные из пакета подтверждения приёма, то ...
    radio.read(&ackData, sizeof(ackData));  // Читаем данные из буфера в массив ackData указывая сколько всего байт может поместиться в массив.
    Serial.println(ackData[0]);
  }else{Serial.println("not ask");}
//  Serial.print("valMotor: ");
//  Serial.println(transmit_data[0]);
}

Приемник 

#include <SPI.h>  // Подключаем библиотеку для работы с SPI-интерфейсом
#include "nRF24L01.h" // Подключаем файл конфигурации из библиотеки RF24
#include "RF24.h" // Подключаем библиотеку для работа для работы с модулем NRF24L01
#include "printf.h" // Инфо NRF24L01
#include <Servo.h>

Servo motor;
Servo servo1;
Servo servo2;
Servo servo3;

RF24 radio(9, 10); // CE, CSN модуль nrf24l01 + pa + lna на пинах RF24 radio(9,10); Для Уно/нано. RF24 radio(9,53); для Меги.

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

int timeout = 900; // интервал разрыва связи
int lastTime = 0;

float vout = 0.0; // переменные для вольтметра
float vin = 1.0;
float R1 = 61000.0; // resistance of R1 (60K) -see text!
float R2 = 10000.0; // resistance of R2 (10K) – see text!
int value = 0;

byte recieved_data[4];
float ackData[1];

void setup(){
  motor.attach(2);
  servo1.attach(3);
  servo2.attach(4);
  servo3.attach(5);
 
  Serial.begin(115200); //открываем порт для связи с ПК
  radio.begin(); //активировать модуль
  printf_begin(); // 
  radio.setRetries(0, 15);     //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах
  radio.openReadingPipe(1, address[0]);      //хотим слушать трубу 0
  radio.setChannel(0x71);  //выбираем канал (в котором нет шумов!)
  radio.setPALevel (RF24_PA_MAX); //уровень мощности передатчика. На выбор RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH, RF24_PA_MAX
  radio.setDataRate (RF24_250KBPS); //скорость обмена. На выбор RF24_2MBPS, RF24_1MBPS, RF24_250KBPS
  //должна быть одинакова на приёмнике и передатчике!
  //при самой низкой скорости имеем самую высокую чувствительность и дальность!!
  radio.printDetails();
  radio.startListening();  //начинаем слушать эфир, мы приёмный модуль
  for (int i=0; i <= 255; i++){
      motor.write(i);
      delay(10);
      Serial.print(i);
   }
  delay(2000);
  for (int i=255; i >= 30; i--){
      motor.write(i);
      delay(10);
      Serial.print(i);
   }
   delay(2000);
}
void loop() {
  if(radio.available()){    // слушаем эфир со всех труб
    lastTime = millis();
    radio.read( &recieved_data, sizeof(recieved_data) );  // чиатем входящий сигнал
    motor.write(recieved_data[0]);
    servo1.write(recieved_data[1]);
    servo2.write(recieved_data[2]);
    servo3.write(recieved_data[3]);
    Serial.println(recieved_data[0]);
    value = analogRead(A0);
    vout = (value * 5.0) / 1024.0; // see text
    vin = vout / (R2/(R1+R2));
    Serial.println(vin);
    ackData[0] = vin;
    radio.writeAckPayload (1, &ackData, sizeof(ackData) );  // запишем в radio.enableAckPayload();
  }
  int dt = millis() - lastTime;
  if (dt >= timeout) {
    Serial.println(dt);
    motor.write(29);
    servo1.write(92);
  }
}

Хмм.. Сделал, но radio.writeAckPayload (1, &ackData, sizeof(ackData) ); почему-то не работает с radio.setRetries(0, 15);    //(время между попыткой достучаться, число попыток) на передатчике как будто не принимает пакеты закомментировал radio.setRetries  работает.  А radio.setRetries(0, 15); как-бы нужная опция ? Еще заметил перебой когда подключен сервопривод и на джойстике с опцией radio.setRetries(0, 15);  не было перебоев.. перебои делаются из-за питания когда серво двигается наверно.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

zDimaBY

а почему у вас интервал в setretries 0? Косяк

Самая стабильная работа на RF24_1MBPS

Нужно иметь ввиду, что на многих клонах инвертирован NoAck. Определяется методом научного тыка и использованием эталонного модуля.

Если вам так сильно не хватает секаса в организме, либо другие типы радиомодулей не можете использовать по религиозным соображениям, я бы настоятельно рекомендовал прочитать тему ИгоряК на форуме Амперки. Там проведена огромная научно-изыскательская работа по понуждению этих модулей к вступлению в связь. У нас, кмк, не так много энтузиастов этого дела.

 

 

zDimaBY
Offline
Зарегистрирован: 10.06.2018

Аа.. setretries 0 15 потому-что предположим 15 это и есть интервал (время чтобы это сделать), а setretries 1 15 делать это через 1мс. или не так я понимаю ?

Таа.. это не се*с это как-бы хоби в свободное время кто-то телевизор смотрит кто-то ютуб, а я делаю такое.. Я бы и использовал другие модули (как посоветовали лору) но есть только эти.. На RF24_250KBPS тоже работает стабильно но без серво (очень восприимчив в питании) хотя с конденсаторами. Пойже попробую разделить цепь питания.. Я то на Ардуино форумах не сидел.. найду ИгоряКа почитаю.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Есть такая аппаратура, она работает и с передатчиком на NRF24L01, прошивка OpenTX

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

zDimaBY пишет:

Аа.. setretries 0 15 потому-что предположим 15 это и есть интервал (время чтобы это сделать), а setretries 1 15 делать это через 1мс. или не так я понимаю ?

Обычно интервал (первый параметр) ставят в районе 15-20 миллис, чтобы приемник успевал Аск прислать. По русски setretries(15, 5) - в случае неудачи повторять попытку 5 раз с интервалом 15 мс. 

Курите маны библиотеки: https://nrf24.github.io/RF24/classRF24.html

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

ua6em пишет:

Есть такая аппаратура, она работает и с передатчиком на NRF24L01, прошивка OpenTX

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Rumata пишет:

ua6em пишет:

Есть такая аппаратура, она работает и с передатчиком на NRF24L01, прошивка OpenTX

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

я к тому, что в некоторых китайских игрушках используется NRF24L01, сей пульт с ними умеет общаться, и не только с ними )))
(только для информации)

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

zDimaBY пишет:

найду ИгоряКа почитаю.

А чего его искать, 80% всех поисковых запросов на тему нрф24 ведут в ту тему

zDimaBY пишет:

Я бы и использовал другие модули (как посоветовали лору) но есть только эти.

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

я вот не пойму, при весьма скромной цене на комплект от флайская с гарантированной дальнобойность в 1 км, зачем?

zDimaBY
Offline
Зарегистрирован: 10.06.2018

ua6em пишет:

я вот не пойму, при весьма скромной цене на комплект от флайская с гарантированной дальнобойность в 1 км, зачем?

Дороговато 2нрф 2нано пару кнопок и пару потенциометров дешевле выходит. + мне нужны хотя бы ещё 2 серво потенциометра на пульт. А ковырять этого пульта за 75$ не. не. не.

Rumata пишет:

zDimaBY пишет:

найду ИгоряКа почитаю.

А чего его искать, 80% всех поисковых запросов на тему нрф24 ведут в ту тему

zDimaBY пишет:

Я бы и использовал другие модули (как посоветовали лору) но есть только эти.

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

пусть уже этот проект будет на нрф24 на следующий будет лора.

zDimaBY
Offline
Зарегистрирован: 10.06.2018

Вот и сейчас не могу понять как работать с SoftwareSerial и Servo вместе. (NEO-6M в роли GPS приемника + серво) так как После подключение GPS все сервы с интервалом в 1 секунду (когда GPS отправляет пакет на ардуино нано) уходят в крайнее левое положение и возвращаются в центр циклически. При отключенном GPS такой проблемы нет.

пульт

#include <SPI.h>  // Подключаем библиотеку для работы с SPI-интерфейсом
#include "nRF24L01.h" // Подключаем файл конфигурации из библиотеки RF24
#include "RF24.h" // Подключаем библиотеку для работа для работы с модулем NRF24L01
#include "printf.h" // Инфо NRF24L01
#include <iarduino_OLED_txt.h> // OLED SSD1306
#include <Servo.h>

RF24 radio(9, 10); // CE, CSN модуль nrf24l01 + pa + lna на пинах RF24 radio(9,10); Для Уно/нано. RF24 radio(9,53); для Меги.
iarduino_OLED_txt myOLED_1(0x3D); // Объявляем объект myOLED_1_1, указывая адрес первого дисплея на шине I2C: 0x3C.

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

uint32_t myTimer1; //таймер

byte transmit_data[4];
float ackData[5];

int error = -1;

float input_volt = 0.0; // переменные для вольтметра
float temp = 0.0;
float r1 = 101000.0; //сопротивление резистора r1
float r2 = 10000.0; // сопротивление резистора r2
int value = 0;
byte speedGPS;
byte GPSsatelite;
int compass;
float VoltageShip;
int valMotor;
int valServo1;
int valServo2;
int valServo3;
const int potPinMotor = 0;
const int potPinRole = 1;
const int potContainerServo1 = 3;
const int potContainerServo2 = 6;

void setup() {
  //Serial.begin(115200);
  myOLED_1.begin();
  radio.begin();
  pinMode(potPinMotor, INPUT);
  pinMode(potPinRole, INPUT);
  pinMode(potContainerServo1, INPUT);
  pinMode(potContainerServo2, INPUT);
  myOLED_1.setFont(SmallFontRus);
  //radio.setRetries(0, 15);    //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах
  radio.openWritingPipe(address[0]);   //мы - труба 0, открываем канал для передачи данных
  radio.setChannel(0x71);  //( Автовыбор канала в котором нет шумов!)
  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
  //должна быть одинакова на приёмнике и передатчике!
  printf_begin();
  radio.printDetails();
  myOLED_1.print  ("Скорость:", 0, 0);
  myOLED_1.print  ("%>", 70, 0);
  myOLED_1.print  ("КМ/ч", 103, 0);
  myOLED_1.print  ("Джойстик:", 0, 1);
  myOLED_1.print  ("АКБ пульта:", 0, 2);
  myOLED_1.print  ("v", 92, 2);
  myOLED_1.print  ("АКБ катера:", 0, 3);
  myOLED_1.print  ("v", 97, 3);
  myOLED_1.print  ("GPS спутников:", 0, 4);
  myOLED_1.print  ("GPS компас:", 0, 5);
  myOLED_1.print  ("Ошибок связи:", 0, 7);
}

void loop() {
  valMotor = analogRead(potPinMotor);
  valMotor = map(valMotor, 0, 1023, 28, 255);
  transmit_data[0] = valMotor;
  valMotor = map(valMotor, 28, 255, 0, 99);
  valServo1 = analogRead(potPinRole);
  valServo1 = map(valServo1, 0, 1023, 80, 103);
  transmit_data[1] = valServo1;
  valServo2 = analogRead(potContainerServo1);
  valServo2 = map(valServo2, 0, 1023, 0, 179);
  transmit_data[2] = valServo2;
  valServo3 = analogRead(potContainerServo2);
  valServo3 = map(valServo3, 0, 1023, 0, 179);
  transmit_data[3] = valServo3;
  radio.write(&transmit_data, sizeof(transmit_data));
  if ( radio.isAckPayloadAvailable()) { // Если в буфере имеются принятые данные из пакета подтверждения приёма, то ...
    radio.read(&ackData, sizeof(ackData));  // Читаем данные из буфера в массив ackData указывая сколько всего байт может поместиться в массив.
    VoltageShip = ackData[0];
    GPSsatelite = ackData[1];
    speedGPS = ackData[2];
    compass = ackData[3];
  } else {
    error++;
    myOLED_1.setCursor(80, 7);
    myOLED_1.print  (error);
    myOLED_1.print  ("    ");
  }
  int analogvalue = analogRead(A7);
  temp = (analogvalue * 5.0) / 1024.0; // формула для конвертирования значения напряжения
  input_volt = temp / (r2 / (r1 + r2));
  if (input_volt < 0.1)
  {
    input_volt = 0.0;
  }
  valServo1 = map(valServo1, 80, 103, 15, -15);
  myOLED_1.setCursor(53, 0);
  myOLED_1.print(valMotor);
  myOLED_1.print  (" ");
  myOLED_1.setCursor(87, 0);
  myOLED_1.print  (speedGPS);
  myOLED_1.print  (" ");
  myOLED_1.setCursor(53, 1);
  myOLED_1.print  (valServo1);
  myOLED_1.print  (" Град. ");
  myOLED_1.setCursor(66, 2);
  myOLED_1.print  (input_volt);
  myOLED_1.setCursor(66, 3);
  myOLED_1.print  (VoltageShip);
  myOLED_1.setCursor(87, 4);
  myOLED_1.print  (GPSsatelite);
  myOLED_1.print  (" ");
  myOLED_1.setCursor(66, 5);
  myOLED_1.print  (compass);
  myOLED_1.print  (" Град. ");
  if (millis() - myTimer1 >= 1000) {   // ищем разницу (количество мс)
    myTimer1 = millis();              // сброс таймера
  }
  //  Serial.print("valMotor: ");
  //  Serial.println(transmit_data[0]);
}

катер

#include <SPI.h>  // Подключаем библиотеку для работы с SPI-интерфейсом
#include "nRF24L01.h" // Подключаем файл конфигурации из библиотеки RF24
#include "RF24.h" // Подключаем библиотеку для работа для работы с модулем NRF24L01
#include "printf.h" // Инфо NRF24L01
#include <Servo.h>
#include <TinyGPS++.h> //Работа с GPS
#include <SoftwareSerial.h> //Для GPS

Servo motor;
Servo servo1;
Servo servo2;
Servo servo3;
TinyGPSPlus gps;

RF24 radio(9, 10); // CE, CSN модуль nrf24l01 + pa + lna на пинах RF24 radio(9,10); Для Уно/нано. RF24 radio(9,53); для Меги.
SoftwareSerial SerialGPS(7, OUTPUT);

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

int timeout = 500; // интервал разрыва связи
int lastTime = 0;

float input_volt = 0.0; // переменные для вольтметра
float temp = 0.0;
float r1 = 93150.0; //сопротивление резистора r1
float r2 = 10000.0; // сопротивление резистора r2
int value = 0;

byte recieved_data[4];
float ackData[5];

void setup() {
  motor.attach(2);
  servo1.attach(3);
  servo2.attach(4);
  servo3.attach(5);

  Serial.begin(115200); //открываем порт для связи с ПК
  SerialGPS.begin(9600); //открываем порт для связи с GPS (только 9600 - читать мануал)
  radio.begin(); //активировать модуль
  printf_begin(); //
  radio.setRetries(0, 15);     //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах
  radio.openReadingPipe(1, address[0]);      //хотим слушать трубу 0
  radio.setChannel(0x71);  //выбираем канал (в котором нет шумов!)
  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.printDetails();
  radio.startListening();  //начинаем слушать эфир, мы приёмный модуль
  for (int i = 0; i <= 255; i++) {
    motor.write(i);
    delay(10);
    Serial.print(i);
  }
  delay(2000);
  for (int i = 255; i >= 30; i--) {
    motor.write(i);
    delay(10);
    Serial.print(i);
  }
  delay(2000);
}
void loop() {
  if (radio.available() > 0) {  // слушаем эфир со всех труб
    lastTime = millis();
    radio.read( &recieved_data, sizeof(recieved_data) );  // чиатем входящий сигнал
    motor.write(recieved_data[0]);
    servo1.write(recieved_data[1]);
    servo2.write(recieved_data[2]);
    servo3.write(recieved_data[3]);
    Serial.write(recieved_data[1]);
    int analogvalue = analogRead(A0);
    temp = (analogvalue * 5.0) / 1024.0; // формула для конвертирования значения напряжения
    input_volt = temp / (r2 / (r1 + r2));
    ackData[0] = input_volt;
    while (SerialGPS.available() > 0) { //Работа с TinyGPS++
      if (gps.encode(SerialGPS.read())) {
        ackData[1] = gps.satellites.value();
        ackData[2] = gps.speed.kmph();
        ackData[3] = gps.course.deg();
      }
    }
    radio.writeAckPayload (1, &ackData, sizeof(ackData) );  // запишем в radio.enableAckPayload();
  }
  int dt = millis() - lastTime;
  if (dt >= timeout) {
    Serial.println(dt);
    motor.write(29);
    servo1.write(91);
  }
}

 

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Я чего-то не догоняю, в 16 строке OUTPUT (tx?) где объявлен?

 

sadman41
Offline
Зарегистрирован: 19.10.2016

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

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

с ардуино.сс:

Hello!

I've solved this problem with AltSoftSerial and ServoTimer2. https://github.com/vrxfile/track_robot

In ServoTimer2.h it is necessary to comment the line typedef uint8_t boolean;

https://github.com/nabontra/ServoTimer2 https://github.com/PaulStoffregen/AltSoftSerial

sadman41
Offline
Зарегистрирован: 19.10.2016

Занятие первого таймера - это одна из проблем. Вторая заключается в том, что софтсериал блочит прерывания и Серво.х вызывает процедуру дерганья ногами по таймера неравномерно. Вследствие чего заполнение pwm начинает плавать, и серва дергается в момент работы SoftSerial.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

продолжали есть кактус )))

zDimaBY
Offline
Зарегистрирован: 10.06.2018

Rumata пишет:

Я чего-то не догоняю, в 16 строке OUTPUT (tx?) где объявлен?

 

tx для GPS в этом случае не нужен так как он только отправляет пакеты. Или как написать ардуинке что можно без tx ?

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

Так и есть. Поэтому в ATmega328p есть 3 таймера. Мне покачто как-то сложно с ними работать.. Не до конца воображается как это. 

Rumata пишет:

с ардуино.сс:

Hello!

I've solved this problem with AltSoftSerial and ServoTimer2. https://github.com/vrxfile/track_robot

In ServoTimer2.h it is necessary to comment the line typedef uint8_t boolean;

https://github.com/nabontra/ServoTimer2 https://github.com/PaulStoffregen/AltSoftSerial

Серво работает, a GPS нет. Хмм. #include <AltSoftSerial.h> что-то не видит пакеты из GPS

#include <SPI.h>  // Подключаем библиотеку для работы с SPI-интерфейсом
#include "nRF24L01.h" // Подключаем файл конфигурации из библиотеки RF24
#include "RF24.h" // Подключаем библиотеку для работа для работы с модулем NRF24L01
#include "printf.h" // Инфо NRF24L01
#include <TinyGPS++.h> //Работа с GPS
#include <ServoTimer2.h>
#include <AltSoftSerial.h> //Для GPS

ServoTimer2 motor;
ServoTimer2 servo1;
ServoTimer2 servo2;
ServoTimer2 servo3;
TinyGPSPlus gps;

RF24 radio(9, 10); // CE, CSN модуль nrf24l01 + pa + lna на пинах RF24 radio(9,10); Для Уно/нано. RF24 radio(9,53); для Меги.
AltSoftSerial SerialGPS(7, OUTPUT);

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

int timeout = 500; // интервал разрыва связи
int lastTime = 0;

float input_volt = 0.0; // переменные для вольтметра
float temp = 0.0;
float r1 = 93150.0; //сопротивление резистора r1
float r2 = 10000.0; // сопротивление резистора r2
int value = 0;

byte recieved_data[4];
float ackData[5];

void setup() {
  motor.attach(2);
  servo1.attach(3);
  servo2.attach(4);
  servo3.attach(5);

  Serial.begin(9600); //открываем порт для связи с ПК
  SerialGPS.begin(9600); //открываем порт для связи с GPS (только 9600 - читать мануал)
  radio.begin(); //активировать модуль
  printf_begin(); //
  radio.setRetries(0, 15);     //(время между попыткой достучаться, число попыток)
  radio.enableAckPayload();    //разрешить отсылку данных в ответ на входящий сигнал
  radio.setPayloadSize(32);     //размер пакета, в байтах
  radio.openReadingPipe(1, address[0]);      //хотим слушать трубу 0
  radio.setChannel(0x71);  //выбираем канал (в котором нет шумов!)
  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.printDetails();
  radio.startListening();  //начинаем слушать эфир, мы приёмный модуль
  for (int i = 0; i <= 255; i++) {
    motor.write(i);
    delay(10);
    Serial.print(i);
  }
  delay(2000);
  for (int i = 255; i >= 30; i--) {
    motor.write(i);
    delay(10);
    Serial.print(i);
  }
  delay(2000);
}
void loop() {
  if (radio.available() > 0) {  // слушаем эфир со всех труб
    lastTime = millis();
    radio.read( &recieved_data, sizeof(recieved_data) );  // чиатем входящий сигнал
    motor.write(map(recieved_data[0], 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH));
    servo1.write(map(recieved_data[1], 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH));
    servo2.write(map(recieved_data[2], 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH));
    servo3.write(map(recieved_data[3], 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH));
    Serial.println(recieved_data[1]);
    int analogvalue = analogRead(A0);
    temp = (analogvalue * 5.0) / 1024.0; // формула для конвертирования значения напряжения
    input_volt = temp / (r2 / (r1 + r2));
    ackData[0] = input_volt;
    while (SerialGPS.available() > 0) { //Работа с TinyGPS++
      if (gps.encode(SerialGPS.read())) {
        ackData[1] = gps.satellites.value();
        ackData[2] = gps.speed.kmph();
        ackData[3] = gps.course.deg();
      }
    }
    radio.writeAckPayload (1, &ackData, sizeof(ackData) );  // запишем в radio.enableAckPayload();
  }
  int dt = millis() - lastTime;
  if (dt >= timeout) {
    Serial.println(dt);
    motor.write(map(28, 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH));
    servo1.write(map(91, 0, 180, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH));
  }
}

ua6em пишет:

продолжали есть кактус )))

Нуу такое.. Ардуино СИЛА!) Разнообразие, свобода.. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

zDimaBY пишет:

ua6em пишет:

продолжали есть кактус )))

Нуу такое.. Ардуино СИЛА!) Разнообразие, свобода.. 

ааа, поиграться...тогда я сам такой )))

zDimaBY
Offline
Зарегистрирован: 10.06.2018

Если брать лору SX1278 будет норм ?