Sending data from an Uno to Mega

Hi everybody!!!

I am sending an array of 94 bytes using an Arduino Uno to an Arduino Mega. I have used a piece of copper wire to connect the TX terminal of the Uno to the Rx1 terminal of the Mega. Here is the code the I compiled on the Uno:

unsigned char sample[94] = {0x82, 0x81, 0x80, 0x30, 0, 0, 0, 0, 0x21, 0x46, 0x01, 0x1D, 0, 0, 0, 0, 0x3F, 0x01, 0x22, 0x22, 0, 0x06, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0x80, 0x0E, 0, 0, 0, 0, 0xFA, 0, 0, 0x27, 0x85, 0x07, 0x0F, 0x4C, 0x82, 0x80, 0, 0, 0, 0x05, 0x01, 0xC1, 0x13, 0x1D, 0, 0, 0, 0, 0x3F,0x01, 0x22, 0, 0x06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0, 0xFA, 0, 0, 0x27, 0x85, 0x07, 0xBF, 0x7B};

void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600); // talk to car
          
}

void loop() // run over and over
{  
  for(int i = 0; i<94; i++)
  {
  Serial.write(sample[i]);
  }
}

My aim is to create two arrays on Mega. One which will contain all the 94 bytes and a second array that will contain the first 91 bytes.
This is the code that I implemented on Mega to achieve this:

#include <avr/pgmspace.h>

unsigned char buff[94];
unsigned char buff2[90];


void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600); //talk to laptop
  Serial1.begin(9600);
}

void loop() // run over and over
{  
  if (Serial1.available() >= 63)          

  {
    if (Serial1.read() == 0x82)          // Checking if the three starting bytes are present in the incoming data
    {
      if (Serial1.read() == 0x81)
      {
        if (Serial1.read() == 0x80)
        {
          buff[0] = 0x82;
          buff[1] = 0x81;
          buff[2] = 0x80;


          for (int i = 3; i<94; i++)          // Put the incoming 94 bytes in buff
          {
            buff[i] = Serial1.read();
          }
        }
      }
    }

    for ( int j = 0; j < 91; j++)          // Put the first 91 bytes of buff in buff2
    {
      buff2[j] = buff[j];
    }

    for (int k =0; k<91; k++) //for debugging purposes
    {
      Serial.print(buff2[k], HEX);
    }
  }
}

This is a full block of data that I desired the Uno to send to Mega, attained from the serial port:

828180300000214611D00003F1222206000000000C1080700000000223F046030827000000063F0135FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FFFFFFFFFFFFFFFFFF828180300000214611D00003F1222206000000000C1080700000000223F046030827000000063F0135FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0FFFFFFFFFFFFFFFFFF

What’s puzzling me is the appearance of the “FFFFFFFFFFF” bits in the data flow. This keeps happening in the rest of the data iterations as well.
Any ideas what is happening??
Any hints or advice is much appreciated.

"FF" (hex representation of 255 or -1) is the serial port's way of saying "there aren't any characters in the serial buffer".

suggest receiver should use something like:

i=3;
while (Serial1.available())
{ buffer[x++]=read the port;
delay(short time); // sender may be slow
}

…I guess a buffer is overrun. (add: I’m sure. try testcode with changing delay)
Try sending just 1/2 of it…: like e.g. Serial.write(sample,60));

void setup()  // UNO
{
  Serial.begin(9600); // talk to car       
}

void loop() // run over and over
{  
  for(int i = 0; i<26; i++)
  {
   Serial.write(65+i); 
   delay(2); // try 10 ms
  }
}
//**************
char c; // MEGA
void setup()  
{
  Serial.begin(9600);   Serial1.begin(9600);
}

void loop() // run over and over
{  
  if(Serial1.available()) 
  {  c=Serial1.read();  
     if (c=='A') Serial.println();
     Serial.print(c);
  } 
}
  if (Serial1.available() >= 63)

With a 64 byte buffer, waiting until the buffer is nearly full until you start to read is a colossally bad idea.

Expecting the other 30+ bytes to arrive (slowly) while you are zipping through the first 63 is an equally bad idea.

I have used a piece of copper wire to connect the TX terminal of the Uno to the Rx1 terminal of the Mega.

You also need to connect the grounds of the two boards together.

Hello again,

So I tried to put the things you guys mentioned together and implemented the following modifications:

  1. I Connected the grounds of the two boards.
  2. As you can see in my code I inserted a 10 ms delay after sending each byte to prevent buffer over-run.
  3. I divided the receiving of the 94 bytes into two staged to prevent buffer over-run.

Here is the modified code on Uno:

unsigned char sample[94] = {0x82, 0x81, 0x80, 0x30, 0, 0, 0, 0, 0x21, 0x46, 0x01, 0x1D, 0, 0, 0, 0, 0x3F, 0x01, 0x22, 0x22, 0, 0x06, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0x80, 0x0E, 0, 0, 0, 0, 0xFA, 0, 0, 0x27, 0x85, 0x07, 0x0F, 0x4C, 0x82, 0x80, 0, 0, 0, 0x05, 0x01, 0xC1, 0x13, 0x1D, 0, 0, 0, 0, 0x3F,0x01, 0x22, 0, 0x06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0, 0xFA, 0, 0, 0x27, 0x85, 0x07, 0xBF, 0x7B};

void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600); // talk to car
          
}

void loop() // run over and over
{  
  for(int i = 0; i<94; i++)
  {
  Serial.write(sample[i]);
  delay(10);
  }
}

Here is the modified code on Mega:

#include <avr/pgmspace.h>
unsigned char buff[94];
unsigned char buff2[90];


void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600); //talk to laptop
  Serial1.begin(9600);
}

void loop() // run over and over
{  
  while (Serial1.available () <34)
  {
  }
  if (Serial1.available() >= 34)          

  {
    if (Serial1.read() == 0x82)          // Checking if the three starting bytes are present in the incoming data
    {
      if (Serial1.read() == 0x81)
      {
        if (Serial1.read() == 0x80)
        {
          buff[0] = 0x82;
          buff[1] = 0x81;
          buff[2] = 0x80;


          for (int i=3; i<35; i++)          // Putting the first incoming 34 bytes in buff
          {
            buff[i] = Serial1.read();
          }
        }
      }
    }
  }
  while (Serial1.available () <60)
  {
  }
  if (Serial1.available() >= 60)          

  {
    for (int l =34  ; l<94; l++)          // Put the rest of the incoming bytes in buff
    {
      buff[l] = Serial1.read();
    }
// The code bellow was used for debugging
    
for (int b = 0;b<94;b++) {
      Serial.print(buff[b], HEX);
      Serial.print(" ");
    }
  }
}

Here is one block of the result I got back for buff:

82 81 80 30 0 0 0 0 21 46 1 1D 0 0 0 0 3F 1 22 22 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 80 E 0 0 0 0 FA 0 0 27 85 7 F 4C 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 1 C1 13 1D 0 0 0 0 3F 1 22 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 80 0 0 0 0 FA 0 0 27 85 7 BF 7B

I was wondering if you guys can give me a suggestion as the reason for the excessive number of zeros between ‘4C’ and ‘5’. The excessive zeros keep repeating in the rest of the data blocks as well. Also if you think I am making a mistake with my code, please let me know.
Cheers!! XD

  1. As you can see in my code I inserted a 10 ms delay after sending each byte to prevent buffer over-run.

Diddling around not reading data from the buffer is NOT how you prevent the buffer from getting full.

Try putting the below simple code on both arduinos, then send a string to the uno via the serial monitor. The string sent should be echoed back to the uno serial monitor and also be sent to the mega. Using a separate serial monitor instance for the mega, see if the mega sends the string to its serial monitor.

// zoomkat 7-30-11 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later

String readString;

void setup() {
  Serial.begin(9600);
  Serial.println("serial test 0021"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    delay(2);  //delay to allow byte to arrive in input buffer
    char c = Serial.read();
    readString += c;
  }

  if (readString.length() >0) {
    Serial.println(readString);

    readString="";
  } 
}

I sent the below string from one arduino to another using the code I posted above and the string was printed out on the second arduino's serial monitor.

828180300000214611D00003F1222206000000000C1080700000000223F046030827000000063F0135*end

First I would like to apologize for the late reply. I think I understand what you are doing zoomkat. However, the reason I placed the data in an array rather than a string was so I can access particular bytes and manipulate them. Eventually I decided to compile a different code on Mega. This code was posted on Gammon software solutions and I changed it slightly to fit my purpose:

/*
Example of processing incoming serial data without blocking.
 
 Author:   Nick Gammon
 Date:     13 November 2011. 
 Modified: 31 August 2013.
 
 Released for public use.
 */

// how much serial data we expect before a newline
const unsigned int MAX_INPUT = 95;

// start of CRC functions
static PROGMEM prog_uint32_t crc_table[16] = {
  0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 
  0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 
  0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 
  0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};

unsigned long crc_update(unsigned long crc, byte data)
{
  byte tbl_idx;
  tbl_idx = crc ^ (data >> (0 * 4));
  crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
  tbl_idx = crc ^ (data >> (1 * 4));
  crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
  return crc;
}

unsigned long crc_string( char *s)
{
  unsigned long crc = ~0L;
  while (*s)
    crc = crc_update(crc, *s++);
  crc = ~crc;
  return crc;
}
//end of CRC functions
void setup ()
{  
  Serial.begin (9600);
  Serial1.begin (9600);
} // end of setup

// here to process incoming serial data after a terminator received
void process_data (char * data)
{
  // for now just display it
  // (but you could compare it to some value, convert to an integer, etc.)

  Serial.print(crc_string(data)); //calculating CRC 32
  
}  // end of process_data

void processIncomingByte (const byte inByte)
{
  static char input_line [MAX_INPUT];
  static unsigned int input_pos = 0;
  //static unsigned int i = 0;

  switch (inByte)
  {

  case '\0':   // end of text
    input_line [input_pos] = 0;  // terminating null byte

    // terminator reached! process input_line here ...
    

    process_data (input_line);
    // reset buffer for next time
    input_pos = 0;  
    break;

  case '\r':   // discard carriage return
    break;

  default:
    // keep adding if not full ... allow for terminating null byte
    if (input_pos < (MAX_INPUT - 1))
      input_line [input_pos++] = inByte;

    break;
  }  // end of switch*/
} // end of processIncomingByte  

void loop()
{
  // if serial data available, process it
  if (Serial1.available () > 0)
    processIncomingByte (Serial1.read ());

  // do other stuff here like testing digital input (button presses) ...
}  // end of loop

I would like thank Nick Gammon a lot for his effort. Also I found the CRC chunk of functions marked in the above code from:

http://excamera.com/sphinx/article-crc.html

Then I changed my code on Uno slightly as well:

// Sending 95 bytes of data. Consider that the last byte is the terminating null.
unsigned char sample[95] = {0x82, 0x81, 0x80, 0x30, 0, 0, 0, 0, 0x21, 0x46, 0x01, 0x1D, 0, 0, 0, 0, 0x3F, 0x01, 0x22, 0x22, 0, 0x06, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 0, 0, 0x80, 0x0E, 0, 0, 0, 0, 0xFA, 0, 0, 0x27, 0x85, 0x07, 0x0F, 0x4C, 0x82, 0x80, 0, 0, 0, 0x05, 0x01, 0xC1, 0x13, 0x1D, 0, 0, 0, 0, 0x3F,0x01, 0x22, 0, 0x06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0, 0xFA, 0, 0, 0x27, 0x85, 0x07, 0xBF, 0x7B,'\0'};

void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(9600); // talk to car
          
}

void loop() // run over and over
{  
  for(int i = 0; i<95; i++)
  {
  Serial.write(sample[i]);
 
  }
   
}

Consider that the last four bytes in the sample are the CRC bytes. Now what I am trying to do is to:

  1. Cut my sample array received by Mega, so it will not include the last four CRC bytes.
    2.Use the CRC function to calculate the CRC bytes of the shortened array and confirm that they match the CRC bytes that were cut off.

I tried a couple of ways to cut the CRC bytes, but since I failed, I ended up modifying the data sent. I removed the CRC bytes from the transmitted data and tested the CRC function. It did not give me the correct CRC bytes.
I would really appreciate it if you would suggest a way to remove the CRC bytes when data is received on Mega and also let me know how I am using the CRC function incorrectly.
I used Realterm to monitor serial ports.

I apologize once again for the prolonged delay and thank everyone for being really supportive. :slight_smile: