joinging Uno and Mega with serial

I've read through most of the serial posts and have a simple project that almost works....

My Uno is sending a value to a Mega

The Mega is providing the power for the UNO and the MEGA is reporting via the serial monitor so the Uno's USB serial is disconnected.

The Uno runs code and produces an interger value.

The part of the Uno code that sends to serial is;

Serial.write(rpm_val / 256);
     
  Serial.write(rpm_val % 256);

   delay(50); //allows all serial sent to be received together

I have set serial.begin at the start to 11520.

The Mega receiver runs this code below;

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

void loop() {
  int receivedRpmval;

     
      while (!Serial1.available()){}
//delay(100); //allows all serial sent to be received together
    byte b1 = Serial1.read();
    while (!Serial1.available()){}
  //  delay(100); //allows all serial sent to be received together
    byte b2 = Serial1.read();

    receivedRpmval = b2 + b1 *256 ;
    Serial.println(receivedRpmval);
    //Serial.println(b1);

}

I know the Uno generates the value as I can see it on the serial monitor when i run it alone.

The Tx light on the Mega flashes indicating it is sending the the serial monitor but I cant see anything. Serial monitor is set to the mega port.

???

while (!Serial1.available()) {}

kpg:
I have set serial.begin at the start to 11520.

The Mega receiver runs this code below;

void setup() {

Serial1.begin(11520);
 Serial.begin(11520);
}




I cant see anything.

Adding an extra "0"to the baud rate would be more conventional, and may even be what you actually want. Also make sure the serial monitor is set to match Mega's output - whatever that might be.

Nick

Thanks. I picked up on my OBVIOUS!! typo and made the Baud 115200. Now the monitor reports numbers like this;

20577
29555
25956
14880
12334
13360
29453
2609
13616
12320
21072
19725
2565
4294958164
26989

The actual number sent from the UNO is around the 2000 number (it is a rev counter) and it limits at 10000 so I must be doing something wrong in the reassembly of the Bytes?

Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

The technique in the 3rd example will be the most reliable. It is what I use for Arduino to Arduino and Arduino to PC communication.

You can send data in a compatible format with code like this (or the equivalent in any other programming language)

Serial.print('<'); // start marker
Serial.print(value1);
Serial.print(','); // comma separator
Serial.print(value2);
Serial.println('>'); // end marker

…R

Robin

I did see that article. I'm a bit new to this so struggling with some of the explanations.

I appreciate the help.

I believe you are implying my send code is also flawed and should have start/end markers as well.

I feel I am trying to do something fairly straight forward that being send the equivelant of a number upto 10000 and read it and store in a variable on the receiver. I seem to have the basic comms working but as you elude to am not controlling the data correctly either at send, receive or both.

The forum is great but some of the articles are just one step up sometimes for a novice.

Thanks again

I,ve found something simpler which I think I understand.

Again I am just trying to send an int with a max of 10000.

Send code (section only) is

byte h = highByte (rpm_val);
byte l = lowByte (rpm_val);
Serial.write(h);
Serial.write(l);
delay(50);

and the receiver code is

void loop() {

int receivedRpmval;

if (Serial1.available()>1)
      {
        byte h = Serial1.read();
        byte l = Serial1.read ();
        receivedRpmval = (h<<8)+1;
      }

    Serial.println(receivedRpmval);
    

}

but now the serial monitor just reports 2561 all the time??

 receivedRpmval = (h<<8)+1;

It’s not clear to me if your are adding a one or a lower case ell variable. It certainly appears like a one.

Don’t use one letter “h” and “l” variable names, for clarity, spend an extra keystroke for “hi” and “lo” if you don’t mind abusing the English language.

Good tip.

I believe it should be an L for the lower byte.
received data is still not right and although it is changing with the rpm it seems a bit jumpy

I just tried a test in the send code and forced the Bytes as in

byte h = highByte (10502);//set to rpm-val in the real prog. This is test send
  
  byte l = lowByte (10502);

The receiver serial monitor with the same previous code above receives 10502 half of the time now and 2601 for the rest and with no serial data being sent.

I must have a mis understanding of bytes as I thought the high byte would just repeat the value above 255 and the low byte the value below 255?

"The Uno runs code and produces an interger value.

The part of the Uno code that sends to serial is;"

Might be more simple to just print the value over to the mega with an end of line marker, then convert the number character representation back into a number for use.

kpg:
I believe you are implying my send code is also flawed and should have start/end markers as well.

To be honest I did not look at your code. Using start and end markers gives greater reliability.

...R

Thanks guys

It feels like my high/low byte send/receive code almost works in that my test send force of 10502 which I assumed would be split then rebuit is actually getting through as a number but i am also getting another number on a second line i dont understand.

Converting the int value to a character, sending and rebuilding is still something I'm not sure of and the origional solution seems so close. I just need to understand why it is not quite right and it must be my understanding of how the int value of 10502 is spilt into bytes and rebuilt?

sender code is

byte h = highByte (10502);//forced to test number
byte l = lowByte (10502);
Serial.write(h);
Serial.write(l);
delay(50);

receiver code is

void loop() {

int receivedRpmval;

if (Serial1.available()>1)
      {
        byte h = Serial1.read();
        byte l = Serial1.read ();
        receivedRpmval = (h<<8)+l;
      }

    Serial.println(receivedRpmval);
   

}

How will your receiver know that the byte it is now receiving is the high byte or the low byte?

...R

kpg:
I just tried a test in the send code and forced the Bytes as in

byte h = highByte (10502);//set to rpm-val in the real prog. This is test send

byte l = lowByte (10502);




The receiver serial monitor with the same previous code above receives 10502 half of the time now and 2601 for the rest and with no serial data being sent.

I must have a mis understanding of bytes as I thought the high byte would just repeat the value above 255 and the low byte the value below 255?

10502 = 41 * 256 + 6 so hi = 41 and low = 6
2601 = 10 * 256 + 41 so hi = 10 and low = 41

since the value 10 is also a linefeed, is there any chance some other part of your code is doing a println() to the serial port? This would inject an extra LF into the stream and then things would be off by 1 byte. Which is yet another plug to use Robin's suggestions about more reliable serial transfer.

but i am also getting another number on a second line i dont understand.

Try explicitly initializing receivedRpmval, and place the printing within the Serial reading section.

void loop() {

int receivedRpmval = 0;

if (Serial1.available()>1)
      {
        byte h = Serial1.read();
        byte l = Serial1.read ();
        receivedRpmval = (h<<8)+l;
        Serial.println(receivedRpmval);
      }

   // Serial.println(receivedRpmval);
   

}

since the value 10 is also a linefeed, is there any chance some other part of your code is doing a println() to the serial port? This would inject an extra LF into the stream and then things would be off by 1 byte. Which is yet another plug to use Robin’s suggestions about more reliable serial transfer.

+1

Serves us right for looking at code snippets.

I moved the serial print to inside the IF

if (Serial1.available()>1)
      {
        byte h = Serial1.read();
        byte l = Serial1.read();
        receivedRpmval = (h<<8)+l;//lower case L
        Serial.println(receivedRpmval);
      }

The serial monitor is more randon;

10502
21609
28005
8272
24947
29541
25658
8240
11828
13171
3338
12595
14387
8274
20557

with the 10502 repeating occasionally so i guess I need to start again and try to get more references about controlling sending data.

Thanks

“i guess I need to start again and try to get more references about controlling sending data.”

Sometimes you meed to send the data in a manor that makes reception easier. Below is a simple example of moving “numbers” around in a familiar text form, then using a a function like readString.toInt() (similar to atoi) to convert the text “number” back into an integer for use in a numerical operation.

// zoomkat 7-30-10 serial servo test
// type servo position 0 to 180 in serial monitor
// for writeMicroseconds, use a value like 1500
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.attach(9);
}

void loop() {

  while (Serial.available()) {

    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
      delay(3);
    } 
  }

  if (readString.length() >0) {
    Serial.println(readString);
    int n = readString.toInt();
    Serial.println(n);
    myservo.writeMicroseconds(n);
    //myservo.write(n);
    readString="";
  } 
}