I have some code working!

Now I plan to improve it and maybe learn a bit more.

The code was written to emulate (sort of) some communications code running on two serially connected (UART) arduino units which I had been working on with some considerable difficulty given that I did not know which unit was causing which problem.

My objective was to successfully transfer a structure containing both byte and float variables through a single byte interface and re-create the data successfully. This now works as intended using just the one arduino (actually a nano)

I could now move on to using this same approach on the two arduino's (one is a nano the other a mega 2560) but a helpful friend told me my approach is all wrong as I should be using pointers.

So, my question is: Should I continue with this approach or is there a far better method?

Please be gentle, my only previous experience with coding was during the 1980's using assembler.

/*
This test code is designed to explore how an array containing both bytes and floats
can be transferred through a byte sized interface and re-constructed with the same
data format and content.

The idea is to simulate passing byte size variables over a serial link using two
arduino units

pseudo code:

fill the sending structure with dummy data

// Now pass the data via a single byte variable to represent the serial port

for(i = 0; i < totalMessageSize; i++)
{
  transferByte = sending strucure[i];
  receivingStructure[i] = transferByte;
}


*/

// First define the source data

  #define shortMessageSize  6
  #define longMessageSize   4
  #define totalMessageSize (shortMessageSize + (longMessageSize * 4) + 2)

byte dummyBytes[] = {2,4,6,8,3,3};
float dummyFloats[] = {3.141, 2.453, 56.4, 2234.5};
float tempFloat = 0;
int i;

// Construct the transmit data container

typedef struct 
 {
   byte txShortMessage[shortMessageSize];
   byte txShortMessageLRC; 
   float txLongMessage[longMessageSize];
   byte txLongMessageLRC;
 } txArray;


typedef union
{
  txArray tx;
  byte newArray[sizeof(txArray)];  
} UTX;

  UTX tx;


// Define the transfer location

byte transferByte = 0;

// Construct the receiving data container

typedef struct 
 {
   byte rxShortMessage[shortMessageSize];
   byte rxShortMessageLRC;
   float rxLongMessage[longMessageSize];
   byte rxLongMessageLRC;
 } rxArray;

typedef union
{
  rxArray rx;
  byte newArray[sizeof(rxArray)];  
} URX;

  URX rx; 



void setup()
{

  Serial.begin(9600);
  // Now populate the source array with data from dummyBytes & dummyFloats
  
    for(i = 0; i < shortMessageSize; i++)
   {

      tx.tx.txShortMessage[i] = dummyBytes[i];
   }
   
   tx.tx.txShortMessageLRC = 55; // Any rubbish will do for testing
     
    for(i = 0; i < longMessageSize; i++)
   {

      tx.tx.txLongMessage[i] = dummyFloats[i];
     
   }     
  
  
  
  // Now pass the data across the invisible wire to the receiver one
  // byte at a time
  


  for(i = 0; i <= totalMessageSize; i++)
   {
    transferByte = tx.tx.txShortMessage[i];
    
    Serial.print(transferByte,DEC); // Print the byte being transferred
    
    
    rx.rx.rxShortMessage[i] = transferByte;
   }
    
}


void loop()
{

  for(i = 0; i < longMessageSize; i++)
  {    
    tempFloat = rx.rx.rxLongMessage[i];
    printDouble(tempFloat, 4);
    Serial.print(" ");
  }
Serial.println("");

}



// **************************************************************************
  
void printDouble( double val, byte precision)
{
 // prints val with number of decimal places determined by precision
 // precision is a number from 0 to 6 indicating the desired decimal places
 // example: printDouble( 3.1415, 2); // prints 3.14 (two decimal places)

 Serial.print (int(val));  //prints the int part
 if( precision > 0)
 {
   Serial.print("."); // print the decimal point
   unsigned long frac;
   unsigned long mult = 1;
   byte padding = precision -1;
   while(precision--)
      mult *=10;
     
   if(val >= 0)
     frac = (val - int(val)) * mult;
   else
     frac = (int(val)- val ) * mult;
   unsigned long frac1 = frac;
   while( frac1 /= 10 )
     padding--;
   while(  padding--)
     Serial.print("0");
   Serial.print(frac,DEC) ;
 }
}

BrianDrury:
I could now move on to using this same approach on the two arduino's (one is a nano the other a mega 2560) but a helpful friend told me my approach is all wrong as I should be using pointers.

If it does what you want how can it be "all wrong?" :wink:

What if another friend tells you it would be better using references? Would that make the first friend "all wrong" too? If s/he was really helpful, s/he would have shown you what s/he meant!

By the way, why did you decide to go with (virtually) identical structs for the TX object and an RX object? Can't you just define a Message object and call it TX or RX?

why do you typedef twice the same structure?

typedef struct 
 {
   byte rxShortMessage[shortMessageSize];
   byte rxShortMessageLRC;
   float rxLongMessage[longMessageSize];
   byte rxLongMessageLRC;
 } rxArray;
typedef struct 
 {
   byte txShortMessage[shortMessageSize];
   byte txShortMessageLRC; 
   float txLongMessage[longMessageSize];
   byte txLongMessageLRC;
 } txArray;

txArray and rxArray are identical... what you need is just 1 structure, which is a message basically

using struct and union to access bytes could be OK but not really needed (and you are at risk of compiler optimization of the structure of the data). so having a pointer to the start of the structure and sending that byte then moving to the next byte until the end of the struct would be as simple

That being said _ I'm a bit confused. Is this what you call sending the data ?

     for(i = 0; i <= totalMessageSize; i++)
   {
    transferByte = tx.tx.txShortMessage[i];
        Serial.print(transferByte,DEC); // Print the byte being transferred  
        rx.rx.rxShortMessage[i] = transferByte;
   }

ie you believe that sending them all in ASCII represantion, all tucked together will actually work on the receiving end? here it works because of your last line actually reads the actual byte, but if you had 2 arduinos, then forget it... that won't fly

you need to send the bytes as bytes, with a start flag and end flag to ensure the data was well sent (possibly with checksum if you want to do error spotting)

if you want to send in ASCII (slower) then you need to separate each byte value with some separator... challenge being that since you send binary data, there is no meaningful separator you can use because it could actually be real data... so won't work...

My 'real' code will require two structures because there are two processors. The test code is supposed to represent the two processors but using only one.

The 'real' code uses variable sized packets with headers and byte count. The test code does not need that because there is no 'piece of wire' to send the data over.

BrianDrury:
My 'real' code will require two structures because there are two processors.

well that will be exactly the same structure on both side... Call that message and everyone will understand that's what is being passed around

BrianDrury:
The test code is supposed to represent the two processors but using only one.

The test code is copying manually data from one struct to the other in memory... not sure how you say this is representing anything... you'd have written

int rx, tx;
tx = 3;
Serial.print(tx);
rx = tx;

and you'd be at about the same spot....

BrianDrury:
The 'real' code uses variable sized packets with headers and byte count. The test code does not need that because there is no 'piece of wire' to send the data over

so what's the intent of the test code? it fakes transmission by copying data in memory, does not address the variable size nature of your data, the headers check etc...

you lost me...