[SOLVED] Trouble passing integer values from Uno to Mega using rx-tx

I want to thank the community for all of these great posts on this forum! I have been reading code and learning for weeks now and don't know what I would have done without this forum.

Still working on passing integer values from Arduino Uno that is monitoring sensors and relaying information back to Mega 2560.

After a week I finally got the Mega to read data using "Serial1" and looking at info on "Serial" from the Uno sending on rx-tx. Uno has wire from pin 1 (tx) to Mega pin 19 (rx1) and they are grounded together.

I found a sketch on here by Mr Gammon that sends bytes with delimiters on the front and back of the byte and it is working great. I am sending 5 bytes from Uno to Mega. They come out of Uno Serial screen like this.


etc..

My problem is I can read the correct value out from Mega on com serial screen right when the number gets read, but I can't assign a value to a variable to pass the info into the program so I can do something with it. I have tried pointers, counters, arrays, integers, functions and about everything else I can possibly think of, and still can't get the values be able to use them in my code. Would like to be able to call on a function "getdata" and have it pass what is read from Uno to useable data in Mega scetch. Sure could use some help, thanks

This code displays the correct values on Mega com screen.

 const char startOfNumberDelimiter = '<';
 const char endOfNumberDelimiter   = '>';

 int counter = 0;
 int cdata[5];

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

void loop() {
  static long receivedNumber = 0;
  static boolean negative = false;
  byte c = Serial1.read ();
  switch (c) {
    case endOfNumberDelimiter:  
      if (negative){ 
        cdata[counter] = (- receivedNumber);
        Serial.println(receivedNumber);  
        counter = counter + 1;
        if(counter > 4)
          counter = 0;
      } 
      else{
        cdata[counter] = receivedNumber;
        Serial.println(cdata[counter]);
        counter = counter + 1;
        if(counter > 4)
          counter = 0;
        }
    case startOfNumberDelimiter: 
      receivedNumber = 0; 
      negative = false;
      break;
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';
      break;
    case '-':
      negative = true;
      break;
    } 

}

This code does not work, how can I get these bytes read from Uno to be able to use them?

  const char startOfNumberDelimiter = '<';
  const char endOfNumberDelimiter   = '>';

  int counter = 0;
  int cdata[5];

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

void loop() {
  static long receivedNumber = 0;
  static boolean negative = false;
  byte c = Serial1.read ();
  switch (c) {
    case endOfNumberDelimiter:  
      if (negative){ 
        cdata[counter] = (- receivedNumber);
        counter = counter + 1;
        if(counter > 4)
          counter = 0;
      } 
      else{
        cdata[counter] = receivedNumber;
        counter = counter + 1;
        if(counter > 4)
          counter = 0;
        }
    case startOfNumberDelimiter: 
      receivedNumber = 0; 
      negative = false;
      break;
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';
      break;
    case '-':
      negative = true;
      break;
    } 
  Serial.println(cdata[0]);
  Serial.println(cdata[1]);
  Serial.println(cdata[2]);
  Serial.println(cdata[3]);
  Serial.println(cdata[4]);  
  Serial.println();  
  delay(2000);
}

You should really be looking if there is anything to read before attempting to read it. Serial.available() is your friend for this.

If you read() with nothing available it will return -1. Place that into a byte and it will end up as 255.

The way you have written your program that shouldn't matter, but it's best to be safer than sorry.

One thing that springs out at me: You are reading your numbers into a LONG, then storing them in an INT. What is the exact symptom you are seeing? The wrong numbers being stored? Only one number? No numbers at all?

That doesn't look all that much like my code. For one thing you are printing something in loop, whether or not you have the number. This was my example:

// Example of receiving numbers by Serial
// Author: Nick Gammon
// Date: 31 March 2012

const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';

void setup ()
  { 
  Serial.begin (115200);
  Serial.println ("Starting ...");
  } // end of setup
  
void processNumber (const long n)
  {
  Serial.println (n);
  }  // end of processNumber
  
void processInput ()
  {
  static long receivedNumber = 0;
  static boolean negative = false;
  
  byte c = Serial.read ();
  
  switch (c)
    {
      
    case endOfNumberDelimiter:  
      if (negative) 
        processNumber (- receivedNumber); 
      else
        processNumber (receivedNumber); 

    // fall through to start a new number
    case startOfNumberDelimiter: 
      receivedNumber = 0; 
      negative = false;
      break;
      
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';
      break;
      
    case '-':
      negative = true;
      break;
      
    } // end of switch  
  }  // end of processInput
  
void loop ()
  {
  
  if (Serial.available ())
    processInput ();
    
  // do other stuff here
  } // end of loop

The function processNumber is called when a number has arrived. That is where you assign the resulting number to a variable and process it.

Thank you Mr Gammon! I sure do appreciate you!!!! Here it is Labor Day and you are trying to help out wannabe programmers. You should be out having a BBQ!

Okay I started over from scratch using your program. This is what I changed. The counter so I can asign a number to the array. I printed the info out to com screen up in the processNumber where the counter is, like you said and everything is perfect, It all prints out just like it is supposed to, incoming data, the counter number and passing n to cdata[].
I have a 3 second delay on the Uno sending the 5 bytes. As soon as I try to print the data out in the program where I would use it, it scrolls really fast and still looks like zeros or data not in the right place. For some reason the counter is making the code skip and miss the if Serial1.available? The array values are okay up at processNumber but not anywhere else in the program.

BTW my sketch would not compile at 115200 rate.

 void processNumber (const long n)
{
  cdata[counter] = n;
  counter = counter + 1;
  if(counter > 4)
    counter = 0;  
}  // end of processNumber

This is the code on the bottom of the sketch I am trying to use the array values and it still doesn't seem to work. I left the processInput code untouched.

 void loop ()
{
  if (Serial1.available ())
    processInput ();

  Serial.print("code: ");
  Serial.println(cdata[0]);  
  Serial.print("temp: ");
  Serial.println(cdata[1]);
  Serial.print("humid: ");
  Serial.println(cdata[2]);
  Serial.print("light: ");
  Serial.println(cdata[3]);  
  Serial.print("volts: ");
  Serial.println(cdata[4]);
  // do other stuff here
} // end of loop

Nick's approach is appropriate, however since you are sending from serial-to-serial there is another less c'ish way to accomplish the same thing:

The code in the link reads a verb (instruction, 3 character fix-length) fro the ASCII serial and then gets an arbitrary number of numeric arguments against which some calculations are performed. ParseInt() and parseFloat() are the Serial methods used to 'pull' digits from Serial until a delimiter is reached.

http://forum.arduino.cc/index.php/topic,147550.0.html

Ray

If you add this code, it should only print once the data has been refreshed.

{
bool dataRefreshed = flase; //Declare as global variable
void loop(){
  if (Serial1.available ()) { 
    processInput ();
  }

  if(dataRefreshed == true){
    //Print outputs here
    dataRefreshed = false;
  }
}

You will need to set dataRefreshed to TRUE when you find the end delimiter

Still doing the same thing, data printed out in loop all zeros then starts getting data slowly as it loops. Data printed out up in processNumber is perfect. There is some problem with Serial1.available. It is not waiting for data, it is just blowing throught the loop and not waiting. If it is trying to read data and there is nothing there because it is going too fast would that matter? Take the delay out and if just loops fast. If I wait a while the values start to show up in the right place after going all zeros a bunch of times with delay. Do not quite understand the refresh thing, it didn't help any at all. I have been working on this for weeks. I think about it in my sleep, all I get is brain drain and frustration! I am at my wits end. I sure appreciate you guys helping me!!

 const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';
boolean dataRefreshed = false; //Declare as global varia
int counter = 0;
int cdata[5];

void setup(){
  Serial1.begin(9600);
  Serial.begin(9600);
  //  Serial.println ("Starting ...");
} // end of setup

void processNumber (const long n)
{
  cdata[counter] = n;
  counter = counter + 1;
  if(counter > 4){
    dataRefreshed = true; 
    counter = 0;  
  }
}  // end of processNumber

void processInput ()
{
  static long receivedNumber = 0;
  static boolean negative = false;

  byte c = Serial1.read ();

  switch (c)
  {

  case endOfNumberDelimiter:  
    if (negative) 
      processNumber (- receivedNumber); 
    else
      processNumber (receivedNumber); 

    // fall through to start a new number
  case startOfNumberDelimiter: 
    receivedNumber = 0; 
    negative = false;
    break;

  case '0' ... '9': 
    receivedNumber *= 10;
    receivedNumber += c - '0';
    break;

  case '-':
    negative = true;
    break;

  } // end of switch  
}  // end of processInput

void loop ()
{
  if(Serial1.available() > 0){
    processInput ();
  }
  if(dataRefreshed = true){
    Serial.print("code: ");
    Serial.println(cdata[0]);  
    Serial.print("temp: ");
    Serial.println(cdata[1]);
    Serial.print("humid: ");
    Serial.println(cdata[2]);
    Serial.print("light: ");
    Serial.println(cdata[3]);  
    Serial.print("volts: ");
    Serial.println(cdata[4]);
  }
  dataRefreshed = true;
//  delay(3000);
  // do other stuff here
} // end of loop

You are closer however:

  if(dataRefreshed = true){

Should be:

  if(dataRefreshed == true){

Or even:

  if(dataRefreshed){

And then after printing the data, do this:

dataRefreshed = false;

Oops this one was my fault

  if(dataRefreshed = true){}
  if(dataRefreshed){}
  if(dataRefreshed == true){}

Both may work, but the latter is easier to read at a glance.

The code i posted will not print anything until it has been sent the "endOfNumberDelimiter"
So in "processInput" you will need to change "dataRefreshed" to true, if you are sent the "endOfNumberDelimiter".

You need to have this inside the same if statment that you are printing in, not outside of it.

dataRefreshed = false;

E.g

if(dataRefreshed == true){
  Serial.print("I'M TALKING HERE!!"); 
  dataRefreshed = false;

OMG it works!!!!!!!! Nice! You guys are great to have available to answer questions. Can't thank you enough, I may even sleep tonight.

Hope after I get a lot more under my belt I can return the favor to others. Thank you so much!

fastmike75:
OMG it works!!!!!!!! Nice! You guys are great to have available to answer questions. Can't thank you enough, I may even sleep tonight.

Hope after I get a lot more under my belt I can return the favor to others. Thank you so much!

:slight_smile: :slight_smile: :slight_smile:
Great to know!! Can you post your new code? Also if you can add [SOLVED] to the title so if anyone is looking for help they can try here.

Wanted to print both codes on here, so others may not have to go through one heck of a learning process I have gone through, but that is the whole idea behind Arduino. Sure these are everyday things for Arduino as projects.

Problem: I live in a big building and have a small apartment in the back. If someone is at the front door or in my driveway, I can't hear them. So I am setting up several PIR sensors inside and out, temp/humid sensors and a LDR light sensor to a relay to turn on light outside if dark and triggered. Uno will set codes for different levels of activity outside and send to Mega 2560, like code 1 is a car in the driveway, code 2 someone at the front door/side door, etc.. Am setting up a Mega to play recordings (with adafruit wave shield) of what is going on outside, monitor the weather and the building. I am using DHT11 temp/humid sensors, placed in different locations attic/shop/outside, hope to have a fire/smoke sensor in the building also, LDR on roof, PIR sensors around the outside, Honeywell IS-215T PIR on driveway, relay to control 12V or 120V lights. Have it all working independantly from 120V on a 12V 8Ah battery, with small solar charger going through controller to charge battery. With LM7805 regulator chip running sensors at 5V and LM7808 regulator running Arduinos at 8V. Using a NE555 Timer chip to blink led outside if someone gets close (can just hit an Arduino pin on high and keep going, no delay to wait through for program, turn it low when you want to turn off).

I am sending 5 bytes from Uno in front to Mega in back TX-RX. This is the program to send and recieve those 5 bits.

Is still a work in progress so use at your own risk. Sure these are common questions in beginner coding, hope this helps.

Thanks to the guys on here that are real programmers!

Send data program from UNO

 #include <dht11.h>

dht11 DHT11;

#define DHT11PIN (A0)

const int LDRpin (A1);
const int Warnpin = 12;

const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';

byte code = 0;
byte temp = 0;
byte humid = 0;
byte light = 0;
byte volt = 0;
byte cdata[5];

void setup(){
  Serial.begin(9600); 
  //  pinMode(Warnpin, OUTPUT); // output to NE555 timer 
  pinMode(LDRpin, INPUT);
  pinMode(DHT11PIN, INPUT); 
}

void loop()
{
  cdata[0]= 1;                    //code to let Mega know what is going on with Uno
  int chk = DHT11.read(DHT11PIN); //checks temp sensor
  cdata[1] = DHT11.temperature;   // put a value to array
  cdata[2] = DHT11.humidity;      // put a value to array
  cdata[3] = analogRead(LDRpin);  // reads LDR 
  cdata[4] = 12;                  //check battery voltage/solar output

  for (int i = 0; i < 5; i++){ // sends 5 bytes, 0-4, program by Nick Gammon
    Serial.print (startOfNumberDelimiter); // to Uno TX pin 1  
    Serial.print (cdata[i]);               // send a byte
    Serial.print (endOfNumberDelimiter);  
    Serial.println ();
  }  // end of for

  delay (3000);
}

Receiving code for Mega 2560

 const char startOfNumberDelimiter = '<';  //delimiters to recive data
const char endOfNumberDelimiter   = '>';

boolean dataRefreshed = false; //Declare as global variable

int counter = 0; //counter for array 
int cdata[5];    // data array global

void setup(){
  Serial1.begin(9600);
  Serial.begin(9600);
  //  Serial.println ("Starting ...");
} // end of setup

void processNumber (const long n)  //writes the data to array
{
  cdata[counter] = n;
  counter = counter + 1;
  if(counter > 4){
    dataRefreshed = true; 
    counter = 0;  
  }
}  // end of processNumber

void processInput () //read bytes and change from ASCII to integer (number)
{
  static long receivedNumber = 0;
  static boolean negative = false;

  byte c = Serial1.read ();

  switch (c)
  {

  case endOfNumberDelimiter:  
    if (negative) 
      processNumber (- receivedNumber); 
    else
      processNumber (receivedNumber); 

    // fall through to start a new number
  case startOfNumberDelimiter: 
    receivedNumber = 0; 
    negative = false;
    break;

  case '0' ... '9': 
    receivedNumber *= 10;
    receivedNumber += c - '0';
    break;

  case '-':
    negative = true;
    break;

  } // end of switch  
}  // end of processInput

void loop ()
{
  if(Serial1.available() > 0){
    processInput ();
  }
  if(dataRefreshed == true){
    Serial.print("code: ");
    Serial.println(cdata[0]);  
    float farin = (1.8 * cdata[1] + 32); //cdata[1] is celsius, convert
    Serial.print("temp: ");
    Serial.println(farin, 1);
    Serial.print("humid: ");
    Serial.println(cdata[2]);
    Serial.print("light: ");
    Serial.println(cdata[3]);  
    Serial.print("volts: ");
    Serial.println(cdata[4]);
    Serial.println();
  }
  dataRefreshed = false;

  // do other stuff here
  // like do something with the different codes
  // interface with processing to monitor info on your computer
} // end of loop

That sounds great. I was going to make something like this awhile back but never got around to it. anyway once you finish you should look into post a guide with the code a schematics and http://www.instructables.com/ so other can make it.

Good luck!! :wink:

Yes, I will do that when I get it farther along, something like this could never be done though. Run solar panel motors to change with sun angle, keep the garden/trees watered, water leak/smoke/fire monitor, monitor or trigger video cameras, tie in a dialer so would call your cell phone if problem and show you a video (movie Day and Knight, that was so cool!). Will have fun with this for years.

Thank you so much for your help, probably not the last time you hear me say that.