ARDUINO NRF24L01 + NRF24L01

zoommer62

✩✩✩✩✩✩✩
10 Авг 2019
8
2
Товарищи, подскажите пожалуйста. Мне нужно передать с одной NRF24L01 на другую данные. Все хорошо, все передается, НО!!! Мне нужны данные с двумя цифрами после запятой, а все числа округляются до целых, даже точнее не округляются, а отсекаются. В передатчике а=3,76 , в мониторе порта 3,76. А в приемнике на дисплее ОЛЕД а=3.
Как победить проблему??? Писал и float и double.
Как такое решается?// Ps/ передаю напряжение батареи.
Pps/ пока решил проблему так, что добавил отображение процентов. Разделил,умножил :), то есть просто отображается 3 и 95% это значит около 3,75 в . Пока так, ищу решение...
 
Последнее редактирование:

zoommer62

✩✩✩✩✩✩✩
10 Авг 2019
8
2
Умножал и на 100 и на 100.0 и на 100.00 :(. Но на приемной не делил ещё.
Скетчи на работе в компе. Буду на работе, скину код.
За основу взял скетч Alexgyver радиоуправление с телеметрией. Добавил то что мне нужно было. Сделал катер на управлении. В пульте дисплей, на него передается температура, влажность и батарея катера. Температура не особо точная это не страшно тdht11( просто контроль нагрева двигателя, потому что пока без ШИМ), а вот напряжение мне нужно знать хотя бы одну цифру после запятой.
Искал в интернете... И конечно не нашел ни одного скетча управления с обратной связью , где напряжение со знаками после запятой, что бы сравнить.
 
Последнее редактирование:

Wan-Derer

★★★★★✩✩
Команда форума
31 Июл 2018
1,491
319
Москва
wan-derer.ru
@zoommer62, Смысл умножения/деления в том чтобы передавать целое число вместо вещественного. При необходимости надо выполнить приведение типов.
 

zoommer62

✩✩✩✩✩✩✩
10 Авг 2019
8
2
Типы я изначально ставил float и double. На катере в мониторе порта, все как надо : 3,75, а в пульте отображает 3. :(
 

zoommer62

✩✩✩✩✩✩✩
10 Авг 2019
8
2
Интересный вопрос . Даже не задумывался что библиотеки могут не поддерживать типы. То есть изучить библиотеки, классы и тд...??? ууууу , это я долго буду изучать, ткните хотя бы на хороший справочник :)
pss\\ в скетче библиотеки
SPI.h
nRF24L01.h
RF24.h
iarduino _OLED_txt.h
если это библиотека, я думаю это библиотека дисплея.
 
Последнее редактирование:

zoommer62

✩✩✩✩✩✩✩
10 Авг 2019
8
2
извиняюсь, не знаю как нормально код вставить.

//****************************************************************
//************** СКЕТЧ ПРИЁМНИКА ***********************
//****************************************************************
#define CH_NUM 0x60
#define SIG_POWER RF24_PA_LOW
#define SIG_SPEED RF24_2MBPS
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include <Servo.h>
#include <dht11.h>
#define pin 2
dht11 term;
RF24 radio(9, 10);
byte pipeNo;
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};
//------------------------------------------------------------
//--------------------- ПЕРЕМЕННЫЕ ----------------------
//------------------------------------------------------------
float data_V1 ;
float data_V2 ;
float data_H ;
float data_T ;
float volt=A2;

int AA1 = 3; // мотор движения
int AA2 = 5; // мотор движения
int BB1 = 6; // мотор поворота
int BB2 = 7; // мотор поворота
int led1=A3;
int led2=A4;
int led3=A5;
int led4=8;
int lamp =3;
Servo myservo0;
Servo myservo1;
int RX_data[1];
int telemetry[1];

void setup() {

// Serial.begin(9600);
pinMode (volt, INPUT);

pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(lamp, OUTPUT);

pinMode(AA1, OUTPUT);
pinMode(AA2, OUTPUT);
pinMode(BB1, OUTPUT);
pinMode(BB2, OUTPUT);
myservo0.attach(A0);
myservo1.attach(A1);

radioSetup();
}

void loop() {
int refe = term.read(pin);
while (radio.available(&pipeNo)) {
radio.read( &RX_data, sizeof(RX_data));
//---------------------------------------------------------------------------------------
//----------------- ДВИЖЕНИЕ ВПЕРЕД НАЗАД ------
//---------------------------------------------------------------------------------------
if (RX_data[0] >=123 && RX_data[0] <=255){
digitalWrite (AA1, LOW),
digitalWrite (AA2, HIGH);}
if (RX_data[0] >=233 && RX_data[0] <=100){
digitalWrite (AA1, HIGH),
digitalWrite (AA2, LOW);}
if (RX_data[0] >123 && RX_data[0] <145){
digitalWrite (AA1, LOW),
digitalWrite (AA2, LOW);}
//---------------------------------------------------------------------------------------
//----------------- ДВИЖЕНИЕ ПРАВО ЛЕВО МОТОРОМ -----------
//---------------------------------------------------------------------------------------
if (RX_data[1] >=123 && RX_data[1] <=100){
digitalWrite (BB1, LOW),
digitalWrite (BB2, HIGH);}
if (RX_data[1] >=123 && RX_data[1] <=255){
digitalWrite (BB1, LOW),
digitalWrite (BB2, HIGH);}
if (RX_data[1] >123 && RX_data[1] <145){
digitalWrite (BB1, LOW),
digitalWrite (BB2, LOW);}

// -------------------
myservo0.write(RX_data[2]);
myservo1.write(RX_data[3]);
digitalWrite(lamp, RX_data[4]);
digitalWrite(led1, RX_data[5]);
digitalWrite(led2, RX_data[6]);
digitalWrite(led3, RX_data[7]);
digitalWrite(led4, RX_data[8]);

//-----------------------------------------------------------------------------------
//-------- формируем телеметрию ------------------------
//-----------------------------------------------------------------------------------


data_H = (term.humidity); // DHT11 на моторе
data_T = (term.temperature); // DHT11 на моторе
data_V1 = analogRead(volt)/1023.0*5.0;
data_V2= map((analogRead(volt)/1023.0*5.0),0.0,5.0,0.0,123.0);
// Serial.println (data_V2);
// Serial.println (volt);
telemetry[0] = data_T; // температура DHT11
telemetry[1] = data_H; // влажность DHT11
telemetry[2] = data_V1;
telemetry[3] = data_V2;
//Serial.print ("V1 ");
//Serial.println (data_V1);
//Serial.print ("V2 ");
//Serial.println (data_V2);
//Serial.print ("T ");
//Serial.println (data_T);
radio.writeAckPayload(pipeNo, &telemetry, sizeof(telemetry));//отправляем телеметрию
data_T = 0;
data_H = 0;
}
}

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

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







//**********************************************************************
//************** ЭТО СКЕТЧ ПЕРЕДАТЧИКА!!! *********************
//**********************************************************************

#define CH_NUM 0x90
#define SIG_POWER RF24_PA_LOW
#define SIG_SPEED RF24_1MBPS
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include <iarduino_OLED_txt.h>
iarduino_OLED_txt myOLED(0x3C);
extern uint8_t MediumFontRus[];
extern uint8_t SmallFontRus[];

RF24 radio(9, 10);
byte address[][6] = {"1Node", "2Node", "3Node", "4Node", "5Node", "6Node"};
int button0 = 6;
int button1 = 8;
int button2 = 7;
int sw1 = 5;
int sw2 = 4;
int potent1 = A3;
int potent0 = A2;
int joy1X = A0;
int joy1Y = A1;
int vol_joy1;
int vol_joy2;


int TX_data[1];
int telemetry[1];
byte rssi;
int trnsmtd_pack = 1, failed_pack;
unsigned long RSSI_timer;



void setup() {
// Serial.begin(9600);
pinMode(joy1X, INPUT);
pinMode(joy1Y, INPUT);
pinMode(sw1, INPUT_PULLUP);
pinMode(sw2, INPUT_PULLUP);
pinMode(button0, INPUT_PULLUP);
pinMode(button1, INPUT_PULLUP);
pinMode(button2, INPUT_PULLUP);
pinMode(potent1, INPUT);
pinMode(potent0, INPUT);
}
void loop() {


TX_data[0] = map(analogRead(joy1X), 0, 123, 0, 255);
TX_data[1] = map(analogRead(joy1Y), 0, 123, 1, 180);
TX_data[2] = map(analogRead(potent0), 0, 123, 0, 180);
TX_data[3] = map(analogRead(potent1), 0, 123, 0, 180);// если рулевая серва, тогда здесь 255
TX_data[4] = !digitalRead(sw1), // инвертированный (!) сигнал с выключателя
TX_data[5] = !digitalRead(sw2); // инвертированный (!) сигнал с выключателя
TX_data[6] = !digitalRead(button0);
TX_data[7] = !digitalRead(button1);
TX_data[8] = !digitalRead(button2);
vol_joy1 = TX_data[0];
vol_joy2 = TX_data[1];

myOLED.setFont(SmallFontRus);
myOLED.print( ( TX_data[0] ), 19, 0);
myOLED.print( ( TX_data[1] ), 96, 0);

if (radio.write(&TX_data, sizeof(TX_data))) { // отправка пакета TX_data
trnsmtd_pack++;
if (!radio.available()) {
// если получаем пустой ответ
myOLED.clrScr();
} else {
while (radio.available() ) { // если в ответе что-то есть
radio.read(&telemetry, sizeof(telemetry)); // читаем
//---------------------------------------------------------
//---- получили телеметрию от приёмника -------
//---------------------------------------------------------
myOLED.setFont(SmallFontRus);
myOLED.print("ТЕМПЕРАТУРА", OLED_L, 2);
myOLED.print( ( telemetry[0]), OLED_R, 2);
myOLED.print("ВЛАЖНОСТЬ", OLED_L, 3);
myOLED.print( ( telemetry[1]), OLED_R, 3);
myOLED.print("БАТАРЕЯ- V", OLED_L, 5);
myOLED.print( ( telemetry[2]), OLED_R, 5);
myOLED.print("БАТАРЕЯ- %", OLED_L, 6);
myOLED.print( ( telemetry[3]), OLED_R, 6);

}
}
} else {
failed_pack++;
myOLED.clrScr();
myOLED.setFont(MediumFontRus);
myOLED.print( "НЕТ" , OLED_C, 2);
myOLED.print("СЕТИ", OLED_C, 4);
myOLED.clrScr();
}

if (millis() - RSSI_timer > 1000) { // таймер RSSI

// расчёт качества связи (0 - 100%) на основе числа ошибок и числа успешных передач
rssi = (1 - ((float)failed_pack / trnsmtd_pack)) * 100;
myOLED.clrScr();
myOLED.setFont(SmallFontRus);
myOLED.print( ( rssi ), 62, 0);
//******** сбросить значения ********
failed_pack = 0;
trnsmtd_pack = 0;
RSSI_timer = millis();
}
}
void radioSetup() {
radio.begin();
radio.setAutoAck(1);
radio.setRetries(0, 15);
radio.enableAckPayload();
radio.setPayloadSize(32);
radio.openWritingPipe(address[0]);
radio.setChannel(CH_NUM);
radio.setPALevel(SIG_POWER);
radio.setDataRate(SIG_SPEED);
radio.powerUp();
radio.stopListening();
}

PS ! Важно ! что бы школьники хоть немного думали, в скетче нужно посмотреть дефайны канала и скорости радиомодуля. изменить массивы передаваемых данных и цифры в "IF"
 

zoommer62

✩✩✩✩✩✩✩
10 Авг 2019
8
2
Нашел решение !
Кому интересно : в приемнике /1023,0*500,0
в пульт добавляем : float volts= telemetry[2]/100;
в строке myOLED.print( ( telemetry[2]), OLED_R, 5);
не нужно лепить к правому борту, точка и знаки за запятой уходят за экран !
меняем на : myOLED.print( ( volts), 105, 5);
и все! есть и точка, и две цифры после точки !!!
 
Последнее редактирование:

Иринка

✩✩✩✩✩✩✩
26 Авг 2019
2
0
Здравствуйте.
Помогите пожалуйста решить мою проблему:
C++:
#ifndef    PACKET_H
#define    PACKET_H

struct AllThePorts{
uint8_t    text, adr, crc;


    void setCRC(void) { crc = getCRC(); }
    
    uint8_t getCRC(void) const {
        const uint8_t * p = reinterpret_cast<const uint8_t *>(this);
        uint8_t crc = 0xFF;
        for (uint8_t n = 0; n < sizeof(*this) - sizeof(crc); n++) {
            crc ^= *p++;
            for (uint8_t i = 0; i < 8; i++) crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1;
        }
        return crc;
    }

}  __attribute__ ((packed));

#endif    //    PACKET_H

C++:
#include "Packet.h"

#include <SPI.h>
#include "nRF24L01.h" 
#include "RF24.h"
RF24 radio(9, 10);
byte address="Test";
byte pipeNo;   

void setup(){
Serial.begin(9600);
radio.begin();
radio.setAutoAck(0);
//radio.setRetries(0,15);
radio.enableAckPayload();
radio.setPayloadSize(32);
radio.openReadingPipe(1,address);
radio.setChannel(0x60);
radio.setPALevel (RF24_PA_MAX);
radio.setDataRate (RF24_250KBPS);
radio.powerUp();
radio.startListening(); 
}

void loop() {
if (radio.available(&pipeNo)) { 
AllThePorts ports;  
radio.read((char *) & ports, sizeof(ports));
if (ports.getCRC() == ports.crc){
Serial.println(ports.text, BIN); 
Serial.println(ports.adr, BIN); 
}else{
Serial.print("Transmission error: ");
}
}
}



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

RF24 radio(9, 10);
byte address = "Test";
unsigned long TimeOtpr;
bool FlagTx = true;

void setup() {
    Serial.begin(9600);
    radio.begin();
    radio.setAutoAck(0);
    //radio.setRetries(0, 15);
    radio.enableAckPayload();
    radio.setPayloadSize(32);
    radio.openWritingPipe(address);
    radio.setChannel(0x60);
    radio.setPALevel(RF24_PA_MAX);
    radio.setDataRate(RF24_250KBPS);
    radio.powerUp();
}




void loop() {

    if (FlagTx) {
        FlagTx = false;
        radio.stopListening();
        delay(20);
        AllThePorts ports;
        ports.text = B11100111;
        ports.adr = B11111101;
        ports.setCRC();
        radio.write((char * ) & ports, sizeof(ports));
        Serial.println("Sent: ");
        TimeOtpr = millis();
    } 


    if (!FlagTx && millis() - TimeOtpr >= 1000) FlagTx = true;



} //loop()

В монитор порта скетча "Передатчик" отправляется сообщение "Sent: ", но приёмник сообщения не получает.
Если изначально bool FlagTx будет равен false (в условиях поменять на true), то скетч работает.
Что за беда?

 

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

★★★★★★✩
14 Авг 2019
2,336
637
Москва
У меня посмотреть пока нет возможности, я на работе до завтра и пока без части "знаний" в виде домашнего компа
НО, Гайвер показывал сканер сети (в принципе стандартная демка для НРФ), дома я модифицировал такой сканер , сделал приемник и передатчик, которые передают и принимают пакеты данных , а так же подсчитывают их количество, определенное фиксированное время по всем каналам. А далее я уже смотрю результаты, на какой частоте сколько было удачных попыток. Интересный эффект: на некоторых частотах передавать данные просто не получается.... к чему все это я... А! Каналы пробовали разные ?

на 250кбпс не работает автоответ! помните об этом ?

if (!FlagTx && millis() - TimeOtpr >= 1000) FlagTx = true;

а вот тут может скобочки добавить для явного указания порядка действий ? как то так
if (!FlagTx &&( (millis() - TimeOtpr )>= 1000)) FlagTx = true;


ЗЫ. Вот что значит невнимательно прочитать вопрос и отвлекаться... написал кучу ненужного.. но оставлю как есть..
 
Последнее редактирование:

Иринка

✩✩✩✩✩✩✩
26 Авг 2019
2
0
на 250кбпс не работает автоответ! помните об этом ?
Да, помню, но дальность больше, поэтому 250

C++:
#include "Packet.h"
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
RF24 radio(9, 10);
byte address="Test";


void setup() {
delay(2000); 
Serial.begin(115200);
radio.begin();
radio.setAutoAck(0);
//radio.setRetries(0, 15);
radio.enableAckPayload();
radio.setPayloadSize(32);
radio.openWritingPipe(address);
radio.setChannel(0x60);
radio.setPALevel (RF24_PA_MAX);
radio.setDataRate (RF24_250KBPS);
radio.powerUp();
radio.stopListening();
}


void loop() {
radio.powerUp(); 
radio.stopListening(); 

AllThePorts ports;
ports.text = B11100111;
ports.adr = B11111101;
ports.setCRC();
//Serial.println(ports.text, BIN);
//Serial.println(ports.adr, BIN);
radio.write((char *) & ports, sizeof(ports));
Serial.println("Sent: ");
//delay(1000);


}
Убираю паузу - приемник получает данные, ставлю паузу, отправка идет, но приемник ничего не получает.

C++:
if (FlagTx){
//FlagTx=false; 
//radio.powerDown();
//delay(100); 
radio.powerUp(); 
delay(20); 
radio.stopListening(); 
delay(20);
AllThePorts ports;
ports.text = B11100111;
ports.adr = B11111101;
ports.setCRC();
//Serial.println(ports.text, BIN);
//Serial.println(ports.adr, BIN);
radio.write((char *) & ports, sizeof(ports));
TimeOtpr = millis();
Serial.println("Sent: ");
delay(1000);
}
С паузой я разобралась. Теперь стабильно раз в секунду данные отправляются-принимаются.
Как я поняла модуль "засыпает", и 5 строчкой я его "бужу".
НО:

C++:
if (FlagTx){
FlagTx=false; 
//radio.powerDown();
//delay(100); 
radio.powerUp(); 
delay(20); 
radio.stopListening(); 
delay(20);
AllThePorts ports;
ports.text = B11100111;
ports.adr = B11111101;
ports.setCRC();
//Serial.println(ports.text, BIN);
//Serial.println(ports.adr, BIN);
radio.write((char *) & ports, sizeof(ports));
TimeOtpr = millis();
Serial.println("Sent: ");
delay(1000);
}

if(!FlagTx && millis()-TimeOtpr >= 2000) {
FlagTx=true;
}
Без паузы попрежнему не работает

C++:
#include "Packet.h"
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
RF24 radio(9, 10);
byte address="Test";
bool FlagTx=false;
unsigned long TimeOtpr;



void setup() {
delay(2000);
Serial.begin(115200);
radio.begin();
radio.setAutoAck(0);
//radio.setRetries(0, 15);
radio.enableAckPayload();
radio.setPayloadSize(32);
radio.openWritingPipe(address);
radio.setChannel(0x60);
radio.setPALevel (RF24_PA_MAX);
radio.setDataRate (RF24_250KBPS);
radio.powerUp();
//radio.stopListening();
}


void loop() {

if (!FlagTx){
FlagTx=true;
//radio.powerDown();
//delay(100);
radio.powerUp();
delay(20);
radio.stopListening();
delay(20);
AllThePorts ports;
ports.text = B11100111;
ports.adr = B11111101;
ports.setCRC();
//Serial.println(ports.text, BIN);
//Serial.println(ports.adr, BIN);
radio.write((char *) & ports, sizeof(ports));
TimeOtpr = millis();
Serial.println("Sent: ");
//delay(1000);
}

if(FlagTx && millis()-TimeOtpr >= 1000) {
FlagTx=false;
}


}

и если изначально значение флага false, то работает
 

Максименко Пётр

✩✩✩✩✩✩✩
24 Ноя 2020
2
0
Добрый вечер. Возник вопрос, хочу сделать гусеничное шасси, движки есть, NRF24L01 тоже и т.д. Как я понял для самих шасси нужны двигатели, конденсаторы, Ардуино, NRF24L01 с антенной А для пульта Ардуино, NRF24L01 с антенной и джостик.
И тут возникло несколько вопросов:
  • Как это всё подключить(если не сложно то можно схему)
  • какой взять пульт
  • как правильно для этого написать код, сколько не пытался, написал бред
Заранее спасибо
 

bort707

★★★✩✩✩✩
21 Сен 2020
474
122
на сколько С++ сложный, сомневаюсь что осилю, если честно
а как же вы скетчи пробовали писать?

Насколько сложный - судить не могу. Думаю, что очень, я на нем лет 20 пишу - и наверно меньше половины еще знаю :)
Другой вопрос, что для обычных самоделок вся эта глубина не требуется. Но если хотите не просто тупо повторять чужие поделки, а действительно писать сами - хотя бы первую половину любого учебника страниц на 500 прочитать стоит. Переменные, распределение памяти, условия и циклы, массивы и структуры, ссылки и указатели... как минимум