[CLOSED] Data corrupted during transfer from arduino to photon using rfm69 library

Hi, would appreciate any help with an issue transferring data between an arduino and a photon using the rfm69 library.

The majority of data appears normal but when I started testing using randomised data I get issues with specific data, for example float 9.00 on the arduino became 2.25 on the Photon, 9.1 becomes 2.26, and 8.00 becomes 2.

Simplifying the datatypes to uint8_t on both devices I get the following:
Arduino ----> Photon
0 -> 0
1 -> 0 ??
2 -> 2
3 -> 3
4 -> 4
5 -> 4 ??
6 -> 6
7 -> 7
8 -> 8
9 -> 8 ??
17 -> 16 ??

It appears to be an issue where x mod 4 = 1

I assumed that LSB/MSB issues only applied to data structures > 2 bytes, so am not sure where to start looking? I thought that I had read that there is a difference in byte encoding between the arduino and stm32 platforms but cannot find the article it again.

Any ideas would be greatly appreciated?

Appears to be a memory usage related - removing the code for displaying data on an OLED causes the issue to go away.

@JohnC, if you can share you code, we might be able to isolate the issue with the OLED code :smile:

< 1m
@peekay123, thanks for the offer. For various reasons have decided to change the hardware design (based on a proof of concept I have working) so it would now be academic. My new approach is to have sensors talk (via RFM69HW radios) to the Photon, which will talk (via Wire) to an arduino pro mini running a 1.8" TFT display, which will give greater flexibility when it comes to choice of display.

Thanks again and thanks for your contributions to the forum, have gain a lot of insight from many of your comments.

@JohnC, you may want to consider an “intelligent” display that you could connect to either the Photon or the Pro Mini. I use Digole displays since they do all the low level graphics work, making the code on the Photon/Mini a LOT simpler. They even have touch capable displays!

1 Like

Hi folks,
I’m having the data corruption issue between my Photon with RFM69 and a moteino with the same transceiver. Using the same code with 2 moteinos I have no issues but once I move the code to the Photon data packets are sent corrupted. I simply used the examples that came with the RFM69 library and removed the SPI.h and SPIFLASH.h libraries and code associated with them on the Photon.

Photon Code:

// This #include statement was automatically added by the Particle IDE.
#include "RFM69/RFM69.h"

#define NODEID      1
#define NETWORKID   100
#define GATEWAYID   99
#define FREQUENCY   RF69_433MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define KEY         "thisIsEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less!
#define LED         D7
#define SERIAL_BAUD 115200
#define ACK_TIME    30  // # of ms to wait for an ack

int TRANSMITPERIOD = 300; //transmit a packet to gateway so often (in ms)
byte sendSize=0;
boolean requestACK = false;
RFM69 radio;

typedef struct {		
  int           nodeId; //store this nodeId
  unsigned long uptime; //uptime in ms
  float         temp;   //temperature maybe?
} Payload;
Payload theData;

void setup() {
  Serial.begin(SERIAL_BAUD);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  //radio.setHighPower(); //uncomment only for RFM69HW!
  radio.encrypt(KEY);
  char buff[50];
  sprintf(buff, "\nTransmitting at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
}

long lastPeriod = -1;
void loop() {
  //process any serial input
  if (Serial.available() > 0)
  {
    char input = Serial.read();
    if (input >= 48 && input <= 57) //[0,9]
    {
      TRANSMITPERIOD = 100 * (input-48);
      if (TRANSMITPERIOD == 0) TRANSMITPERIOD = 1000;
      Serial.print("\nChanging delay to ");
      Serial.print(TRANSMITPERIOD);
      Serial.println("ms\n");
    }
    
    if (input == 'r') //d=dump register values
      radio.readAllRegs();
    //if (input == 'E') //E=enable encryption
    //  radio.encrypt(KEY);
    //if (input == 'e') //e=disable encryption
    //  radio.encrypt(null);
  }

  //check for any received packets
  if (radio.receiveDone())
  {
    Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] ");
    for (byte i = 0; i < radio.DATALEN; i++)
      Serial.print((char)radio.DATA[i]);
    Serial.print("   [RX_RSSI:");Serial.print(radio.readRSSI());Serial.print("]");

    if (radio.ACKRequested())
    {
      radio.sendACK();
      Serial.print(" - ACK sent");
      delay(10);
    }
    Blink(LED,5);
    Serial.println();
  }
  
  int currPeriod = millis()/TRANSMITPERIOD;
  if (currPeriod != lastPeriod)
  {
    //fill in the struct with new values
    theData.nodeId = NODEID;
    theData.uptime = millis();
    theData.temp = 91.23; //it's hot!
    
    Serial.print("Sending struct (");
    Serial.print(sizeof(theData));
    Serial.print(" bytes) ... ");
    if (radio.sendWithRetry(GATEWAYID, (const void*)(&theData), sizeof(theData)))
      Serial.print(" ok!");
    else Serial.print(" nothing...");
    Serial.println();
    Blink(LED,3);
    lastPeriod=currPeriod;
  }
}

void Blink(byte PIN, int DELAY_MS)
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

Moteino (Arduino Uno Compatible running at 16Mhz and 3.3Vdc) Code:

#include <RFM69.h>
#include <SPI.h>
#include <SPIFlash.h>

#define NODEID      99
#define NETWORKID   100
#define FREQUENCY   RF69_433MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define KEY         "thisIsEncryptKey" //has to be same 16 characters/bytes on all nodes, not more not less!
#define LED         9
#define SERIAL_BAUD 115200
#define ACK_TIME    30  // # of ms to wait for an ack

RFM69 radio;
SPIFlash flash(8, 0xEF30); //EF40 for 16mbit windbond chip
bool promiscuousMode = false; //set to 'true' to sniff all packets on the same network

typedef struct {
  int           nodeId; //store this nodeId
  unsigned long uptime; //uptime in ms
  float         temp;   //temperature maybe?
} Payload;
Payload theData;

void setup() {
  Serial.begin(SERIAL_BAUD);
  delay(10);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  //radio.setHighPower(); //uncomment only for RFM69HW!
  radio.encrypt(KEY);
  radio.promiscuous(promiscuousMode);
  char buff[50];
  sprintf(buff, "\nListening at %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);
  Serial.println(buff);
  if (flash.initialize())
    Serial.println("SPI Flash Init OK!");
  else
    Serial.println("SPI Flash Init FAIL! (is chip present?)");
}

byte ackCount=0;
void loop() {
  //process any serial input
  if (Serial.available() > 0)
  {
    char input = Serial.read();
    if (input == 'r') //d=dump all register values
      radio.readAllRegs();
    if (input == 'E') //E=enable encryption
      radio.encrypt(KEY);
    if (input == 'e') //e=disable encryption
      radio.encrypt(null);
    if (input == 'p')
    {
      promiscuousMode = !promiscuousMode;
      radio.promiscuous(promiscuousMode);
      Serial.print("Promiscuous mode ");Serial.println(promiscuousMode ? "on" : "off");
    }
    
    if (input == 'd') //d=dump flash area
    {
      Serial.println("Flash content:");
      int counter = 0;

      while(counter<=256){
        Serial.print(flash.readByte(counter++), HEX);
        Serial.print('.');
      }
      while(flash.busy());
      Serial.println();
    }
    if (input == 'D')
    {
      Serial.print("Deleting Flash chip content... ");
      flash.chipErase();
      while(flash.busy());
      Serial.println("DONE");
    }
    if (input == 'i')
    {
      Serial.print("DeviceID: ");
      word jedecid = flash.readDeviceId();
      Serial.println(jedecid, HEX);
    }
  }

  if (radio.receiveDone())
  {
    Serial.print('[');Serial.print(radio.SENDERID, DEC);Serial.print("] ");
    Serial.print(" [RX_RSSI:");Serial.print(radio.readRSSI());Serial.print("]");
    if (promiscuousMode)
    {
      Serial.print("to [");Serial.print(radio.TARGETID, DEC);Serial.print("] ");
    }

    if (radio.DATALEN != sizeof(Payload))
      Serial.print("Invalid payload received, not matching Payload struct!");
    else
    {
      theData = *(Payload*)radio.DATA; //assume radio.DATA actually contains our struct and not something else
      Serial.print(" nodeId=");
      Serial.print(theData.nodeId);
      Serial.print(" uptime=");
      Serial.print(theData.uptime);
      Serial.print(" temp=");
      Serial.print(theData.temp);
    }
    
    if (radio.ACKRequested())
    {
      byte theNodeID = radio.SENDERID;
      radio.sendACK();
      Serial.print(" - ACK sent.");

      // When a node requests an ACK, respond to the ACK
      // and also send a packet requesting an ACK (every 3rd one only)
      // This way both TX/RX NODE functions are tested on 1 end at the GATEWAY
      if (ackCount++%3==0)
      {
        Serial.print(" Pinging node ");
        Serial.print(theNodeID);
        Serial.print(" - ACK...");
        delay(3); //need this when sending right after reception .. ?
        if (radio.sendWithRetry(theNodeID, "ACK TEST", 8, 0))  // 0 = only 1 attempt, no retries
          Serial.print("ok!");
        else Serial.print("nothing");
      }
    }
    Serial.println();
    Blink(LED,3);
  }
}

void Blink(byte PIN, int DELAY_MS)
{
  pinMode(PIN, OUTPUT);
  digitalWrite(PIN,HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN,LOW);
}

I left the SPI.h and SPIFLASH.h libraries on the Moteino code because it does have the flash memory chip installed.

I’m getting a message saying “Invalid payload received, not matching Payload struct!” because the size of the struct received is not matching the format on hand even through they both do have the same format.

Could the RFM69 chip be having a timing issue because the Photon is so much faster than the ATmega328P on the Moteino?

Any help would be greatly appreciated.

Thanks in advance!

Hi @Rick_ I had a similar issue. It is caused by differences in data type lengths between the arduino and photon e.g. INT is 2 bytes on the arduino and 4 on the Photon. There also appear to be issues with data types. I eventually did the following:

  1. Changed to uint8_t amd int16_t on both Arduino and Photon
  2. kept number of bytes to <= 12
  3. Avoided floats etc
  4. Added code to debug number of bytes sent and received e.g.

on Arduino

Serial.print("Sending struct: ");
Serial.print(sizeof(theData));
Serial.println(" bytes.");    

on the Photon

if (radio.DATALEN != sizeof(Payload))
{
  Serial.print("[Payload = ");
  Serial.print(sizeof(Payload));
  Serial.print(" / radio.DATALEN = ");
  Serial.print(radio.DATALEN);
  Serial.print("] Invalid payload received, not matching Payload struct!");
}

See:
https://docs.particle.io/reference/firmware/photon/#data-types, and
https://www.arduino.cc/en/Reference/HomePage

Hope this helps.

2 Likes

Thanks @JohnC! This helps a lot.
Changing the int declarations to uint8_t on both Photon and Moteino did the trick. On the actual struct I need I was using int and char. I changed them to uint8_t and byte respectively and that did the trick. All devices will be working harmoniously soon!

@Rick_, your INT should be int16_t, not uint8_t. As @JohnC pointed out, INT on the Arduino is 2 bytes, not one. :wink:

Do you have a example of your working code.
I am having the same problem sending from a pro mini 3v 8mhz to a photon.
Working fine pro mini to pro min.
See my post.
Would greatly appreciate any help.