Skocz do zawartości

Transmisja danych nrf24l01 pomiędzy Arduino pro mini 3.3V a ESP32 wrom-32


javjaff

Pomocna odpowiedź

Cześć.

Próbuję zastąpić centralkę Arduino mega z dodatkowym internet shield mniejszym rozwiązaniem na ESP32 wroom-32, ale niestety rozsypują mi się odebrane dane.

Opis funkcjonalności w skrócie:
Pomiar temperatury i wilgotności na Arduino pro mini 3.3V 8Mhz przekazuje po nrf24L01 dane do centralki na Arduino mega z podpiętym internet shield (wystawienie danych do Home Assistanta).

Problem:
Dane wysłane przez Arduino pro mini i odebrane przez ESP32 nie są takie jak powinny.  Wygląda tak jakby dane między Arduino a ESP nie były kompatybilne.

Przeprowadzone testy:
Bazując na tym samym kodzie (zmieniają się piny dla rnf24 w zależności od płytki):
Nadajnik -> Odbiornik
Arduino pro mini -> Arduino Mega - dane odebrane poprawnie (np. "unit 13 :: deb|1.00").;
Arduino pro mini -> ESP32 wroom-32 - dane niepoprawne (poniżej screen "unit 18: 69414403 :: v|0.00");
ESP8266 -> ESP32 wroom-32 - dane odebrane poprawnie (np. "unit 13 :: deb|1.00").

Dołączam screen z monitora, gdzie ESP32 jest odbiornikiem; do tego mamy dwa nadajniki: Arduino pro mini i ESP2866.

esp32wroom32_nrf24l01_receiver.thumb.png.2262ecdc5e8c58af9a671ecee2758d59.png

Transmitter

#include <RF24.h>
#include <SPI.h>

const int UNIT_ID  = 13;
typedef struct {
  int unit_id;        // Sensor unit ID UNIT_ID.
  char parameter[4];  // Parameter name.
  float value;        // Value.
} myData;
const uint64_t address_center = 0xF9A3F7BBE00L;
RF24 radio(2, 4);  // ESP2866
//RF24 radio(9, 10);  // Arduino pro mini 3.3V
int counter = 0;

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

  // Radio initialize.
  radio.begin();
  radio.setPALevel(RF24_PA_HIGH);    // RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH or RF24_PA_MAX.
  radio.setChannel(108);              // Above most Wifi Channels.
  radio.setDataRate(RF24_250KBPS);    // RF24_250KBPS, RF24_1MBPS, RF24_2MBPS
  radio.openWritingPipe(address_center);
  radio.stopListening();
//  radio.printDetails();
}

void loop()
{
  counter++;
  postData("deb", counter);
  delay(5000);
}

bool postData(char* parameter, float value)
{
  // Prepare data to send.
  myData post_data;
  post_data.unit_id = UNIT_ID;
  strncpy(post_data.parameter, parameter, sizeof(post_data.parameter));
  post_data.value = value;

  bool result = radio.write(&post_data, sizeof(myData));
  if (result)
  {
    return true;
  }
  return false;
}

Receiver


#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

/**
* Receiver nRF24L01 config.
*/
RF24 radio(4, 5); // CE, CSN
const uint64_t address_getway    = 0xF9A3F7BBE00L;

/**
* Data structure received from sensors.
*/
struct unitDataStructure {
  int id;
  char parameter[4];
  float value;
};

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

  // Initialize RF24 Radio.
  radio.begin();
  radio.setPALevel(RF24_PA_HIGH);      // RF24_PA_MIN or RF24_PA_MAX
  radio.setChannel(108);              // Above most Wifi Channels
  radio.setDataRate(RF24_250KBPS);    // RF24_250KBPS, RF24_1MBPS, RF24_2MBPS
  radio.openReadingPipe(1, address_getway);
  radio.startListening();
  radio.printDetails();
}

void loop() {
  unitDataStructure unitData;

  // Received radio data.
  if ( radio.available() ) {
    radio.read(&unitData, sizeof(unitDataStructure));
    Serial.println("<- unit " + String(unitData.id) + ": " + String(unitData.parameter) + "|" + String(unitData.value));
  }
}

Próbowałem kilku bibliotek rf24 po stronie nadajnika i odbiornika (łączeni z software SPI) ale efekt był ciągle ten sam.
Jak widać na przykładzie kody oraz odbiornik i nadajnik działają:
Arduino -> Arduino Mega ok;
ESP2866 -> ESP32 ok
Adruino pro mini -> ESP32 błędne dane.

Co przeoczyłem? Co robię źle?

Edytowano przez javjaff
Link do komentarza
Share on other sites

Odpowiedz na dwa pytania:

  • Ile bitów ma int w Arduino?
  • Ile bitów ma int w ESP32?

Do tego dochodzi wyrównanie w strukturze i masz dokładny galimatias.

Jeśli zastosujesz int32_t zamiast int to powinno przejść.

 

 

  • Lubię! 1
Link do komentarza
Share on other sites

Dzięki. Dokładnie to było źródło problemu.

Zmieniłem int na int8_t w strukturze danych dla unit_id, ale nie udało mi się wygooglać/wykombinować, jaki byłby najlepszy zamiennik dla float - wartości w float nie są poprawne po stronie odbiornika (otrzymuję 0.00).

Próbowałem przekonwertować wartości z float na int, a następnie z powrotem na float (np. nadajnik: 23.01 * 100 -> odbiornik: 2301 / 100), ale int8_t jest za mały a int16_t lub int32_t nie działa między Arduino pro mini a ESP32 (nie otrzymam poprawnych danych po stronie odbiornika).

Użyłem "char value[5];" dla zmiennej value (float to char -> char to float) i to działa, ale wydaje mi się, że to nie jest dobra praktyka.

Podsumowując, teraz mam po obu stronach:

struct unitDataStructure {
  int8_t id;
  char parameter[4];
  char value[8];
};

 

Link do komentarza
Share on other sites

5 minut temu, javjaff napisał:

int32_t nie działa między Arduino pro mini a ESP32 (nie otrzymam poprawnych danych po stronie odbiornika).

Co dokładnie otrzymujesz?

Co dostaniesz, jeśli Arduino wyśle 1 jako int32_t?

Co do floatów pogadamy jak się rozwiąże sprawa z int32_t.

 

  • Pomogłeś! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Dzięki ethanak. Testy zrobione; przez wzgląd na wygodę, do testów przerzuciłem się na nadajnik Arduino UNO.

Wrzucam do wglądu dla potomnych:
transmitter -> receiver

int16_t
1 -> 0
-1 -> 255
128 -> 0
-128 -> 255
1024 -> 4
-1024 -> 252

int32_t
1 -> 0
-1 -> 255
128 -> 0
-128 -> 255
1024 -> 0
-1024 -> 255

Źródło problemu: przesunięcie (tak to się chyba nazywa).

Teraz rozwiązanie problemu: dodatkowy atrybut danych struct po stronie 32 bit odbiornika.

struct unitDataStructure {
  int8_t id;
  char parameter[4];
  float value;
} __attribute__((packed, aligned(1)));

Po dodaniu tego atrybutu poprawnie przechodzą wartości typu int16_t, int32_t oraz float.
Dla ID układu nadajnika zostawiłem int8_t ponieważ aż tak dużą liczbą nadajników nie dysponuję 😉

  • Pomogłeś! 1
Link do komentarza
Share on other sites

No pisałem o wyrównaniu 🙂

Przy okazji to wcale nie jest taki dobry pomysł - ESP potrzebuje, aby 32-bitowe wartości (w tym przypadku float) były wyrównane do 4; w przeciwnym razie potrzebuje czterech dostępów do pamięci zamiast jednego. Lepszy byłby układ struktury:

struct cośtam {
  float f;
  char[4] p;
  uint8_t id;
}

 

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.