2

I'm trying to send some big numbers ranging from 0-62000 from one arduino to another via serial communication. I'm using unsigned int to hold values from 0 to 65535. And I'm using serial.print() and serial.write () to send numbers and serial.read()-'0' ; to receive numbers, but I'm unable to send and receive numbers above 9. Please help me.

Here is my code -

(For master)

const int Button_1 = 2;
unsigned int s =0;
void setup () 
{   
   Serial.begin(115200) ;
   pinMode(Button_1,INPUT);
} 
void loop() 
{
  if (digitalRead(Button_1))
  {
     s = 61805;
     Serial.write(highByte(s)) ;
     Serial.write(lowByte(s));
     delay (5);
     s=0;
  } 
  else
  {
     s = 60005;
     Serial.write(highByte(s)) ;
     Serial.write(lowByte(s));
     delay (5);
     s=0;
  } 
} 

(code for slave)

unsigned int upperByte, lowerByte, r=0,p=0;
void setup() 
{
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT) ;
} 
void loop () 
{
  If (Serial.available()>1)
  {
     upperByte = Serial.read();
     lowerByte = Serial.read();
  }
    r = (upperByte << 8) + lowerByte ;

   while (r==61805)
    {
        digitalWrite(LED_BUILTIN, HIGH) ;
    } 
    while (r==60005)
    {
        digitalWrite(LED_BUILTIN, LOW) ;
    } 
} 
5
  • 1
    hint: with serial.write(b) you get to 256. with two serial.write(b) you get to 256*256 (65536)
    – Juraj
    May 21, 2019 at 13:35
  • 2
    If you want to do this in ASCII (opposing to byte values like Juraj suggested), you should use a message delimiter - a special character that marks the end of a number. You can use the newline character \n for this. Then you can read the digits one by one, adding them together to the big number. For further help, we need to see your code.
    – chrisl
    May 21, 2019 at 13:41
  • Using two serial.write (b) is nice idea, but I can't get many numbers which lies between 0-65536 with that logic. And my code is very basic, I'm just using serial.write () to send and serial. read() to receive.. I don't think if it will help you.
    – Mayank
    May 21, 2019 at 14:33
  • What do you mean "I can't get many numbers which lies between 0-65536 with that logic"? You can send as many ints as you want. You would send each int as a pair of bytes, as shown in CrossRoads' answer. Each unsigned int can hold a value from 0-65535.
    – Duncan C
    May 21, 2019 at 16:45
  • i can move up to 32 bytes from one arduino to another using master/slave architecture. if that helps, i can post an answer
    – tony gil
    May 21, 2019 at 17:04

2 Answers 2

3

There are 2 ways to transmit data over serial: As byte data or in ASCII codes

  1. Byte data: Everything, that is digitally stored or processed, is a series of 0s and 1s (bits) (electrically HIGH and LOW level), which are grouped into bytes (8 bits). So all data is just numbers at low level. The different datatypes (like numbers, Strings, executable code) are only reached by different interpretation of the byte data. You can take the number value of a byte directly. A byte like 0b00000101 for example is equivalent to the decimal value 5. So every byte can hold numbers between 0 and 255. (Google the binary system for more information). To hold bigger numbers, more bytes are put together. For example an integer consists of 2 bytes (16 bits) and can hold numbers between 0 and 65535. Note: These are the unsigned types. There are also signed types, that also can hold negative values. To understand this, google binary two's complement. To transmit such a bigger type over serial (which is byte based), you need to seperate the bytes of the type, send them consecutively and put them back together at the receiving side. You can do this with the following code:

    unsigned int number = 54321;
    Serial.write(number & 0xFF); //getting the lower byte of the number by using bitwise AND
    Serial.write(number >> 8); // getting the high byte of the number by shifting the bits of the value 8 bits to the right
    

    There are macros defined for Arduino, that can do this for you:

    Serial.write(lowByte(number));
    Serial.write(highByte(number));
    

    In long term, you should learn, how the bitwise operators work. They are often needed. To put the data back together, you can look at CrossRoads answer.

    Note: Serial.write() will send the byte data unchanged, while Serial.print() will convert the data to ASCII before sending. They are not equal.

  2. ASCII Data: One interpretation of byte data is the ASCII standard (which is really old). Every byte value between 0 and 127 get's a corresponding ASCII value, meaning characters of the alphabet, digits, some special characters and some control characters. Numbers, that are transmitted as ASCII data, consist of multiple bytes, one for each digit. Thats, what you tried. Since the receiver has to seperate the different numbers to process them correctly, you have to mark the end of each number. This is commonly done with the newline character \n (optionally preceeded by the carriage return character \r, windows style). You add this at the end of every number. Serial has an extra function for that: Serial.println() will print the parameter as ASCII and will add a carriage return and newline character. On the receiving side you read the bytes into a buffer, until you see this delimiter sequence. After that, you process the whole buffer. If you want to know, how this Serial communication is done in code, look at the SerialEvent example, that comes with the Arduino IDE.

What way you use for transmitting data, is up to you and depends on your needs. If you only want to transmit number data, nothing else, you can use byte data. For complex or diverse data types, you can use the ASCII representation.


EDIT: I have described above, that - when using ASCII data - you can use one or more special characters to delimit one message/number. The receiver can then distinguish between the numbers in that row of digits. This is just some kind of protocol, that you impose on the data. You state, that every message is ended with this special character, much like very sentence in the english language is ended with a dot.

An important requirement is, that the special character does not occure inside of a message/number. So cannot use the character '1' as delimiter, since it will also occur inside of your numbers and you would chop the numbers in the wrong way.

The same principle can be imposed as protocol onto a byte stream. For example: You define, that every message/number will be ended with a special byte sequence, so that the receiver always can say: "This is the whole data of a number and not just a part of it." As above, the special byte sequence must not occur inside of the valid data. You wrote, that your numbers are always in the range of 0 to 62000. This means, that the value 65535 will never occur as valid data, thus you can use it as delimiter. In hex 65535 is written als 0xFFFF, which means, that you send two bytes with every bit set to 1 (each byte having a decimal value of 255). In your code everytime, that you are receiving something, you can check, if you have got 2 consecutive bytes with the value 255 (or written as 0xFF). If not, write the data into a buffer. If yes, that means, that you can process the data inside the buffer to a number.

For sending that would look like this:

Serial.write(lowByte(number));
Serial.write(highByte(number));
Serial.write(0xFF);
Serial.write(0xFF);

Note: This protocol will make sure, that sender and receiver cannot get out of sync. But still the first reading after a transmission problem (for example that a byte got send before the receiver was ready) will be garbage. That will happen very very rarely, so for most people it's not a problem. There are more principles, that you can use in your protocol to mitigate those problems, if you want to. For example you can define another special byte sequence as the start of a message/number. Or you can calculate a checksum of the number and only use messages/numbers, that fit to that checksum.

12
  • Oh ok ty, I think it will help for sure (:
    – Mayank
    May 22, 2019 at 1:21
  • I have posted my code, sry it is not arranged coz I'm using it on my phone so can't see any option to arrange it.. It is not working, I'm trying a basic program to send and receive those high numbers.. Please check it, ty (:
    – Mayank
    May 22, 2019 at 2:51
  • Logic is not working I don't know what's the problem, please help me to solve it
    – Mayank
    May 22, 2019 at 2:52
  • @Mayank How it is not working? What behaviour do you actually see with that code? Do you use an external pulldown resistor for the button? And the receiver code will only react once, since it will get stuck as soon as one of the two values for r are received, because in the while loops r cannot change. Instead of while use an if statement for testing.
    – chrisl
    May 22, 2019 at 7:23
  • 1
    Note that, with binary transfer, if the receiver misses the first byte (maybe it takes longer than the sender to boot), it will get out of sync. It will stick the second byte of the first number together with the first byte of the second number, and get a bogus result. There are ways out of this (checksums, frame delimiters + escape code...), but they are not so simple. ASCII is way easier and should be preferred as long as throughput is not an issue. May 22, 2019 at 7:32
1

Try something like this to send and receive/recombine two bytes:

Send side:

Serial.write (highByte (your unsigned int));
Serial.write (lowByte (your unsigned int));

Receive side:

if (Serial.available() >1){ // two byte received
upperByte = Serial.read();
lowerByte = Serial.read();
}
newInt = (upperByte <<8) + lowerByte;
7
  • Does I can get 257 as a output too? With that logic?
    – Mayank
    May 21, 2019 at 14:44
  • 257 decimal = 0x0101. highbyte = 0x01, lowbyte = 0x01. x01 << 8 + 0x01 = 257 decimal, so sure.
    – CrossRoads
    May 21, 2019 at 14:57
  • Yes, you can use this method to send any value from 0 to 65535 (2^16 - 1). If you need larger values than that you can send an unsigned long using 4 bytes. That will give you a huge range of values. (0 to 2^32-1, which is over 4 billion.)
    – Duncan C
    May 21, 2019 at 16:47
  • Oh cool! Ty ((:
    – Mayank
    May 22, 2019 at 1:22
  • What are upperbyte and lowerByte ? Int type data type?
    – Mayank
    May 22, 2019 at 1:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.