I have a sketch that has been working properly on Uno.
But the same exact sketch is not working properly on Due.
Specifically, the data (float, char) that is sent by nRF24L01 radio, appears garbled when received on Due.
On the UNO, I receive the data properly formatted as expected, for example like so;
RFL_YAW_STR: -168.25
RFL_PCH_STR : 132.65
RFL_PRX_MSG: GTRK,
But on the DUE, I get the same exact data showing up garbled or wrongly terminated/formatted.
RFL_YAW_STR: 0.00
RFL_PCH_STR : 227634315264.00
RFL_PRX_MSG: K,
The sketch is only changed where necessary, so that it compiles and runs on Due, which it does.
But is there something more, that is specific to the Due that has to be changed?
Make sure you have the data order set correctly on both ends. If the SPI is sending the MSB first and the receiver expects the LSB first you will get that kind of corruption.
[In this context, the "B" in LSB and MSB refers to "byte" not "bit".]
On the Uno, the SPI data order is set in the SPCR control register, the bit is called DORD.
I can't find if there's an equivalent setting in the Due's datasheet.
Both processors are little-endian, so multi-byte data items are stored in memory with the LSB first. The Due datasheet makes this clear. The Uno's datasheet doesn't seem to mention it but other forum postings make this claim.
It's also not clear if both chips use the same floating-point format. I think this is driven more by the compiler than the chip itself.
ok, this is getting more complicated than I expected...
Another person on github mentioned the possibility that
arm gcc aligns structure members differently than avr does.
What do you think ?
I will have to do some investigating, but will let you know how things go.
BTW, I expected Due to essentially run the same arduino code that runs on Uno,
with a few extra features added. Was that a miss-understanding on my part,
or is the documentation on here miss-leading?
Yes, the sketch is the same code but the underlying infrastructure is totally different. It's like a Swiss Army knife versus a regular knife. Except the Swiss Army one has some of the tools welded shut (like the RTC and the Ethernet interface) and you're going to cut yourself if you try to use some of the other tools.
useKnife() may look like the same function but the actions to achieve that are totally different between the two knives.
Looking again at the example data you showed, it looks like it "ate" 3 bytes because the "K" is still there at the end. Perhaps the byte is stored on the Due in a 32-bit space and the struct has to include those bytes? I'm guessing. Try it without the byte. That will test the byte-alignment theory. Then put it back by explicitly declaring it as uint32_t on both ends.
When communicating with different architectures, don't use a struct. Send bytes individually or create a higher-level protocol that will encapsulate those differences. A protocol like HTTP (which you're using to read this) is an example of a protocol that allows totally different architectures to communicate.
Ok, I also got similar advice on github, which was the answer in this case.
As you suggest too, structure memory representation is platform specific and you have to care for proper serializing when transporting via network. arm gcc aligns structure members differently than avr does.
I added this into the structure definition to avoid aligning: