Let's Make Robots!

Integers, floats, arrays, structs... (Arduino)

I need a bit of programming help. What I want to do is sent integers, floats, longs from an Arduino to another Arduino using nRF24L01 modules. I use the RF24 library to handle the wireless modules. At the moment I only sent an array of integers from one Arduino to another.

Piece of my current code:

int remote[5];

if ( radio.available() )
  {
    // Dump the payloads until we've gotten everything
    bool done = false;
    while (!done)
    {
      // Fetch the payload, and see if this was the last one.
      done = radio.read( &remote, sizeof(remote) );
    }

Now what is the best way to sent a mix of different integers, floats, longs? I honestly have no clue how to accomplish this.

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

OddBot, the nRF24L01 modules use the SPI bus. I have used the easytransfer library on my hexapod to let 2 ATmegas talk to each other. That library does what Mogul says, serialize the data. But I don't have the programming skills to adapt that library so it can talk with the RF24 library.

bdk6 Thank you for the explanation, that 's the thing with Arduino. Arduino is very nice for someone like me that was never taught programming. But once you want to do more advanced things you hit a wall. One of my biggest frustrations is all the libraries, some are well written some not. I have a couple of sketches that I can't get to work because of libraries that are incompatible with each other. For example try to do some I2C communication using the Arduino Wire library and use the Arduino servo library at the same time. At random intervals the servos will do weird things, the 2 libraries use the same timer and that causes some interference. An experienced programmer will find a way around that by making some changes to the libraries, I don't know where to start. One year ago I started playing with Arduino to learn a bit about programming.  I have learned a lot in that year, but I would really need to take a decent C++ course to take my programming a step further. Unfortunately where I live I can only find Visual C or Java courses. C/C++ does not seem to be popular over here :(

Be careful passing anything larger than a byte this way:  int, float, double, and ESPECIALLY structs.  There are two issues:

1.  Endianness --  This most likely will never be a problem between (ATMega) Arduinos, but between different types of processors it can be.  Different processors, and sometimes different compilers on the same processor, store values larger than 1 byte in different order, usually called big endian and little endian.  High byte first and low byte first, respectively.  Blindly transferring values between these will garble your data.  Communication protocol stacks usually have functions or macros to switch them as needed for that very reason.

2.  Alignment -- Processors and compilers usually have requirements or preferences on how to store multi byte data for ease/speed of access.  A struct may be "padded" with extra bytes to fill gaps between values to ensure values are aligned on some particular boundary (2,4,8, or even 16 bytes).  The SAME compiler on the same processor with different optimization settings may align things differently.  Your data can get garbled, and worse, you may transfer a larger struct to a smaller one that holds the same data and overwrite memory used for something else.

I make my living writing code like this and I've been bitten more than once.  I don't speak Arduino, but I use the GCC compilers it's based on a lot and I know they generally prefer at least 16 bit alignment.

This reminded me of a library that Patrick posted about.

http://letsmakerobots.com/node/27108

This might solve all your problems or at least give you a new set of problems :D

Found the solution :)

bool ok = radio.write( &X, sizeof(X) );

bool ok = radio.write( &remote_t, sizeof(remote_t) );

This gives an error? The remote_t is not the correct way to define the package?
#include <SPI.h>
#include <nRF24L01.h>
#include "RF24.h"

typedef struct{
  int X;
  int Y;
  float Xa;
  float Ya;
}remote_t;

RF24 radio(8,9);

const uint64_t pipes[2] = { 
  0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

void setup(){
  Serial.begin(9600);
  radio.begin();
  radio.openWritingPipe(pipes[0]);
  radio.openReadingPipe(1,pipes[1]);
  radio.startListening();
}

void loop(){
remote_t X;
  X.X = analogRead(A0);
  X.Y = analogRead(A1);
  X.Xa = X.X /1023;
  X.Ya = X.Y /1023;
    radio.stopListening();

    bool ok = radio.write( &remote_t, sizeof(remote_t) );

    radio.startListening();  
  }

Hmm, serialization looks a bit to complex for me. Is a struct a solution? Never used a struct before and the example I find don't make much sense. How do you define and access data with a struct?

 

 

Struct is a way to bundle variables. A typical example is to have 3 8-bit integers together and then call them R, G and B.

Structs is an obvious technique to explore when serializing data of more then one type. They cant do all the work, but a good intermediate step on your way to complex arduino-to-arduino communication

 

typedef struct 
{
  int A;
  int B;
  long result;
} factors_t;


void setup() 
{  
  Serial.begin(9600); 
}


// function prototype, important when passing typedefs
// - and please notice that I'm passing by reference, to
// get result out with us afterwards
long multiply(factors_t &f);

long multiply(factors_t &f)
{
  f.result = (long)f.A * f.B;
}

void loop()
{
  factors_t X;
  X.A = 123;
  X.B = 321;
  multiply(X);


  Serial.println(X.result);
  delay(500);
}

 

What you need is called serialization. With serialization you take "some data" and transform them into a serial stream. Of cause you also have a concept called de-serialization, which as you would expect, take a serial stream and transform it into a set of data understood in your C program.

A basic requirement is a common understanding between the two ends about the data and their format. Then structure have to be the same in both ends.

I have not tried to do serialization myself with uC's yet, but a simple google search returned a package called simpleserialization which eventually is the stuff you need.