Добавление nRF24L01 в проект

У меня есть проект уровня жидкости, который в настоящее время использует Oled-дисплей. Я только что обнаружил существование модуля беспроводной связи nRF24L01, и это именно то, что мне нужно, чтобы сделать мой проект более удобным для пользователя.

В конце концов, я хочу иметь приборную панель, которая объединяет всю мою информацию в одном месте, но пока я просто хочу выяснить, как получить передачу моего проекта уровня жидкости, а также получить данные на другом Arduino и просмотреть их на последовательном мониторе. Как и все, что он делает, это распечатывает "?" на последовательном мониторе.

У меня есть этот скетч на уровне жидкости проекта Arduino:

#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
SSD1306AsciiAvrI2c oled;
#define I2C_ADDRESS 0x3C
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>


double SensorAnalogValue;
uint8_t calculation=1;
String Show_value; 

//create an RF24 object
RF24 radio(9, 8);  // CE, CSN

//address through which two modules communicate.
const byte address[6] = "00001";

void setup()
{
  
  Serial.begin(9600);
  oled.begin(&Adafruit128x64, I2C_ADDRESS);
  oled.setFont(CalLite24);
  oled.clear();
  
  radio.begin();
  
  //set the address
  radio.openWritingPipe(address);
  
  //Set module as transmitter
  radio.stopListening();
  
}


void loop()
{

  
  SensorAnalogValue = analogRead(A0) * 5.0 / 1023.0;
  if (SensorAnalogValue < 1.726) {
    calculation=0;
    Show_value="Low";
  }
  if (SensorAnalogValue > 4.04) {
    calculation=0;
    Show_value="High";
  }
  if(calculation!=0){
  //  Serial.println(SensorAnalogValue);
    Show_value=(String)Liquid_Volume(SensorAnalogValue);
  }
  Serial.println(SensorAnalogValue);

oled.setCursor(20, 0);
  oled.print(Show_value);
  oled.print(" L");
  oled.println(" ");
  oled.print(Show_value);
  oled.print("L");
  oled.println(" ");
delay(500);
   oled.clear();
  
  radio.write(&Show_value, sizeof(Show_value));
  delay(1000);
   
  calculation=1;
}
int Liquid_Volume(double Volt) {
  double A =   2.81842;
  double B = -11.00151 ;
  double C =  14.4765 ;
  double D =  28.73579 ;

  return A * Volt * Volt * Volt + B * Volt * Volt + C * Volt + D;
}

А в Приемнике есть вот что:

//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

//create an RF24 object
RF24 radio(9, 8);  // CE, CSN

//address through which two modules communicate.
const byte address[6] = "00001";

void setup()
{
  while (!Serial);
    Serial.begin(9600);
  
  radio.begin();
  
  //set the address
  radio.openReadingPipe(0, address);
  
  //Set module as receiver
  radio.startListening();
}

void loop()
{
  //Read the data if available in buffer
  if (radio.available())
  {
    char Show_value[32] = {0};
    radio.read(&Show_value, sizeof(Show_value));
    Serial.println(Show_value);
  }
}

Я думаю, что проблема заключается в следующем:

radio.write(&Show_value, sizeof(Show_value));

Я считаю, что "radio.write" используется вроде как Serial.print или oled.print, но я действительно не понимаю часть "sizeof", может быть, в этом и проблема?

, 👍0


1 ответ


1
radio.write(&Show_value, sizeof(Show_value));

Я считаю, что "radio.write" используется как Serial.print или oled.print, но я действительно не понимаю часть "sizeof", может быть, в этом проблема?

Вроде того. Есть две взаимосвязанные проблемы. Главный из них заключается в том, что фактические данные строки не содержатся с самим фактическим строковым типом. Он распределяется в куче. Класс String содержит указатель на него и некоторые числа для отслеживания выделенного размера и используемой суммы.

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

sizeof(Show_value) вычисляет размер в байтах самого класса String, который представляет собой размер указателя и пары целых чисел, около 6 байт, а не размер содержимого строки.

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

Попробуйте:

radio.write(Show_value.c_str(), Show_value.length());

функция .c_str() возвращает указатель на само фактическое содержимое строки. А .length () - это фактический размер используемой части выделенной области строкив куче.

Тем не менее, лучше избегать String там, где это разумно возможно.


Что касается:

Означает ли это также, что мне нужно заменить radio.read(&Show_value, sizeof(Show_value));

Так и будет. Сделать это немного сложнее, так как .c_str() дает const char *; String не предназначен для того, чтобы сделать доступ для записи к своим базовым данным таким простым.

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

char buffer[33] = "";   // Примечание: это фактически заполнит весь буфер '\0', что некоторых удивляет.
// Идея вышеизложенного состоит в том, чтобы вместить максимальный размер пакета RH24L01 в 32 байта плюс место для нулевого терминатора.

radio.read(buffer, sizeof buffer - 1);  /// Мы делаем доступным только 32-байтовый фрагмент для вызова .read() и оставляем последний байт для его значения '\0', чтобы в любом случае принудительно завершить нулевое завершение

String s = buffer;

Это предполагает, что вы либо заполняете пакет байтами, либо включаете в него нулевой терминатор, либо и то, и другое. Если вы используете динамический размер полезной нагрузки, а не инициализируете массив с помощью = "";, то его можно оставить неинициализированным, а полученный размер пакета можно использовать для размещения нулевого терминатора в нужном месте.

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

,

Спасибо timemage, Означает ли это также, что мне нужно заменить radio.read (и значение Show_, значение размера(Значение Show_)); С: radio.read(Значение шоу.c_str(), Значение шоу.длина()); В скетче получения?, @SV Savannah

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

Я упустил тот факт, что вы уже более или менее делаете вышеописанное в отношении наличия буфера и его заполнения, просто не добавляя дополнительное пространство байтов или не присваивая его "Строке". Если единственное, что вы делаете со строкой, - это отправляете ее через "Serial", вы можете переключиться с "println ()" на использование "write ()" с аргументом size, установленным на правильный номер, и в этом случае вам вообще не нужно завершать., @timemage