Reading a RS232 frame and extracting a byte

Hi everyone,

I'm trying to figure out how to read a frame, know when it begins (obviously...) and extract a byte to then display it on an LCD.

The frame is detailed at this adress : Espiell.com is available at DomainMarket.com. Call 888-694-6735

All of this on a MEGA 2560.

So... I have 4 serial pairs on the MEGA, I figured I might as well use another one than 0&1 to leave it in case I need it on the computer.
If I'm correct (newbie here), because the MEGA has 4 serial pairs I don't need bit-banging or a soft serial library.
So I just need connecting the TX from the device to an RX on the MEGA and we're good right?

And from then on, I don't really know where to start!

If I take the basic serial example, i'd need something like :
Well except that I have to translate it to code of course...

int incomingByte = 0;   // for incoming serial data

void setup() {
        Serial.begin(2400); 
}

void loop() {

        if (Serial.available() > 0) {    //should I really check if I'm only reading??

                incomingByte = Serial.read();
// now I need to compare this to 252 and 253. If one byte is 252 and the following 253 then frame starts.
// I need to count the right number of bytes and read the byte I'm interested in.
// then send it a variable and done!!!
        }
}

Does anyone have an example I could follow? Looked for it on the forum and elsewhere but couldn't find anything simple enough for me to understand... :drooling_face: :frowning:

Thanks everyone!

Marc

Any of those examples can be used on the additional hardware serial ports on the mega2560 as below:

Serial.begin(2400); // use serial port 0
Serial1.begin(2400); // use serial port 1
Serial2.begin(2400); //use serial port 2
Serial3.begin(2400); //use serial port 3

So just edit all of the serial.xxx commands in the example sketches to use the serial port you wish.

That make sense?

When you refer to Serial.begin() it starts using Serial 0 - the one that uses pins 0 and 1

If you look at the Mega board you will see which pins (14 an 15) belong to Serial1. To use that you refer to it with Serial1.begin() etc.

...R

Hi everyone,

Thank you for the answers.
And at the same time, I'm really sorry I guess I didn't make myself understood... :~

I'm looking for guidance on how to :

  • read the incoming bytes
  • compare two bytes
  • extract a byte that would be coming x bytes after a given one (once I know where the beginning of the frame is)

On this I'm really stuck...

This will check if the incoming byte is 252 and will "save" the next 50 bytes in one buffer:

const int frameLength=50;
char buff[frameLength];

void loop() {
   if (Serial.available() > 0) {    //should I really check if I'm only reading??
      incomingByte = Serial.read();
      if (incomingByte == 252) {
         for (int i=0;i<frameLength-1; i++) {
            if (Serial.available() > 0) {    //should I really check if I'm only reading??
               buff[i] = Serial.read();
            }
         } 
      }            
   }
}

If you need to check the 253 too, you need to do:

      if (incomingByte == 252) {
         while (Serial.available() <= 0);
         if (Serial.read() == 253) {
            for (int i=0;i<frameLength-2; i++) {
               if (Serial.available() > 0) {    //should I really check if I'm only reading??
                  buff[i] = Serial.read();
               }
            } 
         }            
   }

This is the easy and very dirty way. It can be done better.

The Arduino code in the demo here is designed to receive all the bytes between given start and end marker bytes. You can easily modify it to suit your own markers. It is also desined to allw bytes to be included in a message that are the same value as the end markers - if you don't need that you can simplify the code.

...R

Hi guys,

Still struggling to interface this FADEC...

So I tried both methods (from Robin and Luisilva) to no avail... I guess I'm doing something wrong, I'm gonna post my code here in the next message.

But first, can someone guide me on why I can't seem to get a reading even in the Arduino serial monitor?

The setup is the following : I'm feeding the Fadec some infos by using the arduino as a signal & servo signal generator (so that I have something to read) and I'm then plugging the TX wire from the FADEC onto a RS232=>USB converter.
They do exchange some informations but for example, here is what I'm reading on the console :

(Sorry about the attached printscreen, can't seem to copy/paste in the monitor.)

I'm @2400bauds, as specified... I honestly don't know where to go frome here...

Thanks for the telp!

Marc

You need to post your code.

Also can you provide a sample of the sort of input data that the Arduino is expecting to get.

What is FADEC?

And I don't understand this

The setup is the following : I'm feeding the Fadec some infos by using the arduino as a signal & servo signal generator (so that I have something to read) and I'm then plugging the TX wire from the FADEC onto a RS232=>USB converter.

...R

Hi Robin,

Thanks for following up,

So the FADEC is an engine (gas turbine in this case) control unit. The one I'm trying to extract data from is a R/C unit.
So I'm just simulating a RPM signal with a 50% duty PWM signal and a servo signal in order to enable it to run.

The data frame is detailed in the link I gave in the first post and copied below :
http://www.espiell.com/fadprot.pdf

So here is one of my code ( I just deleted the other one by mistake and will reconstruct it tonight) :

#include <Servo.h> 
#include <SoftwareSerial.h>

SoftwareSerial fadec (8,9);


Servo myservo;  // create servo object to control a servo 

double incomingByte;
const int frameLength=50;
char buff[frameLength];

int temp=1100;

void setup() 
{ 
  myservo.attach(2);  // attaches the servo on pin 9 to the servo object 
  Serial.begin(2400);
  Serial.println("Salut");
  fadec.begin(2400);

} 

void loop() 
{ 
  myservo.write(50);                  // enables FADEC to be in running mode
  delay(5);                           // waits for the servo to get there 
  analogWrite(3,127);                 //simulates RPM signal (~29KRPM)

  if (incomingByte == 252) {
    while (fadec.available() <= 0);
    if (fadec.read() == 253) {
      for (int i=0;i<frameLength-2; i++) {
        if (fadec.available() > 0) {    //should I really check if I'm only reading??
          buff[i] = fadec.read();
          Serial.println(buff[i]);
          Serial.println("test");
        }
      } 
    }            
  }
  if (millis()-temp>1000)
  {
    Serial.println(buff[40]);
    Serial.println(millis());
    temp=millis();
  }

}

A few things jump out ...

Why is incomingByte not defined as a byte. And double is a floating point type which won't be good at byte/integer comparisons

How does incomingByte get to be 252?

What is the role of 252 and 253? - if they are start and end markers for input data you might look at how that is handled in the Arduino code in this Thread.

I thought you are using a Mega with multiple hardware serial ports - why bother with Software Serial?

...R

Reading a RS232

The arduino uses TTL serial protocol, so have you converted the rs232 to TTL before connecting to the arduino?

Hi guys,

Ok so first : yes it's already TTL signal, I also controlled it with a scope and it's 0/5V so no conversions needed.

Now robin, going through it, I realised there were quite a lot of huge mistakes in that code...

Here's a better one (hopefully...)

252 and 253 are the beginnning markers (no end markers, the last byte is a value).

Thanks for the help,

Marc

Of course I forgot the code (it's below).
I also changed buff from char to byte.

Oh and I did check the example you provided and also tried to make it work but with no results so far... I'll include the code when I get it a bit presentable.

And finally yes, I'm using a MEGA but I'm testing on an uno ... :confused:

#include <Servo.h> 
#include <SoftwareSerial.h>

SoftwareSerial fadec (8,9);


Servo myservo;  // create servo object to control a servo 

byte incomingByte;
const int frameLength=50;
byte buff[frameLength];

long temp=1100;

void setup() 
{ 
  myservo.attach(2);  // attaches the servo on pin 9 to the servo object 
  Serial.begin(2400);
  Serial.println("Salut");
  fadec.begin(2400);

} 

void loop() 
{ 
  myservo.write(50);                  // enables FADEC to be in running mode
  delay(5);                           // waits for the servo to get there 
  analogWrite(3,127);                 //simulates RPM signal (~29KRPM)

  if (fadec.available() > 0) {    //should I really check if I'm only reading??
    incomingByte = fadec.read();
    if (incomingByte == 252) {
      while (fadec.available() <= 0);
      if (fadec.read() == 253) {
        for (int i=0;i<frameLength-2; i++) {
          if (fadec.available() > 0) {    //should I really check if I'm only reading??
            buff[i] = fadec.read();
            //Serial.println(buff[40]);
            //Serial.println("test");
          }
        } 
      }            
    }
  }
  if (millis()-temp>1000)
  {
    Serial.println(buff[39]);
    Serial.println(buff[48]);
    Serial.println(buff[49]);
    Serial.println(millis());
    temp=millis();
  }

}

I'm not sure my code has much to offer if the 252 and 253 are both at the start.

I think your logic is a little bit off as it won't easily handle the situation where something other than 253 appears as the second byte. I don't think your WHILE is in the right place. I think it should come after the check for the 253.

...R

Ok,

I will work on putting the while at the right place.

Thanks,

Marc

I have a couple of questions though :

I've been reading everything I can (understand...) about serial but I still don't get several things :

when serial.available returns more than one (which means bytes have already arrived), how do I know what I'm reading afterwards? I see a lot of codes looking like this :

if(serial.available>0)
{
for(i=0,i<x,i++)
{char*=serial.read()}*
}
Now how do I know which byte I'm reading? I'm not seeing any relation between the i that's incrementing the position on the array (and also why always char?) and the serial.read()
So how do I know I'm reading this byte and not another one?
Also, when I'm done reading, does the buffer automatically erase it's memory and starts where it left off? If not we're skipping data everytime we stop reading, am I right?
Thanks for the help,
Marc

Now how do I know which byte I'm reading?

Below is very simple code that converts the bytes being received into various formats that are printable for inspection.

//zoomkat serial echo test 7-31-2011

char c; // incoming serial data

void setup() {
  Serial.begin(9600);	// set serial port at desired value
  Serial.println("serial echo test 0021"); // echo test
  Serial.println();
}

void loop() {

  if (Serial.available() > 0) { // check for serial buffer input
    c = Serial.read(); // read the incoming byte:

    Serial.println(c); // print the input
    //select an output format
    Serial.println(c, DEC);  // print as an ASCII-encoded decimal
    Serial.println(c, HEX);  // print as an ASCII-encoded hexadecimal
    Serial.println(c, OCT);  // print as an ASCII-encoded octal
    Serial.println(c, BIN);  // print as an ASCII-encoded binary
    Serial.println();
    //Serial.println(); // print new line for better reading
  }
}

Hi Zoomkat,

thanks for the code, at least it will show me if everything else is working / correct.

Though my question still is :

for example if serial.available returns 50, what will serial.read point to??

Also, if serial.available returns 1 and I immediately do serial.read, does it erase the buffer and then serial.available will return 0?

Thanks,

Marc

Serial.read() always reads the bytes in the order they have been received so if the PC sends (in this order) A B C the first Serial.read() will give you the A, the second one the B etc.

In case you are wondering the input buffer is a byte array organized as what is referred to as a circular buffer so it appears to have no start or finish - just two references to the head and tail. Serial.read() reads from the tail and moves it on one place. When the tail is the same as the head it means the buffer is empty. Then some input will arrive and will be written at the head and the head will move on one place. If too much input arrives (so that the head catches up with the tail) data will probably be lost.

...R

Zoomkat, I did implement your code to see what's coming in on the serial and I have to say I'm even more puzzled than before...

So I declared a char c and here what I get on the serial monitor :

No trace of 253 or 254 in any case... And the rest is unreadable to me, it just doesn't make sense...

S
83
53
123
1010011

C
67
43
103
1000011

ý
-3
FFFFFFFD
37777777775
11111111111111111111111111111101

0
48
30
60
110000

i
105
69
151
1101001

 
32
20
40
100000

[01]
1
1
1
1

ß
-33
FFFFFFDF
37777777737
11111111111111111111111111011111

[00]
0
0
0
0

p
112
70
160
1110000

[00]
0
0
0
0

 
32
20
40
100000

$
36
24
44
100100

0
48
30
60
110000

ý
-3
FFFFFFFD
37777777775
11111111111111111111111111111101

0
48
30
60
110000

[00]
0
0
0
0

S
83
53
123
1010011

[02]
2
2
2
10

 
32
20
40
100000

@
64
40
100
1000000

0
48
30
60
110000

@
64
40
100
1000000

C
67
43
103
1000011

[00]
0
0
0
0

9
57
39
71
111001

$
36
24
44
100100

0
48
30
60
110000

0
48
30
60
110000

[01]
1
1
1
1

2
50
32
62
110010

$
36
24
44
100100

N
78
4E
116
1001110

[00]
0
0
0
0

O
79
4F
117
1001111

[00]
0
0
0
0

 
32
20
40
100000

@
64
40
100
1000000

L
76
4C
114
1001100

[00]
0
0
0
0

 
32
20
40
100000

[02]
2
2
2
10

0
48
30
60
110000

@
64
40
100
1000000

0
48
30
60
110000

[1D]
29
1D
35
11101

L
76
4C
114
1001100

[00]
0
0
0
0

w
119
77
167
1110111

[00]
0
0
0
0

ý
-3
FFFFFFFD
37777777775
11111111111111111111111111111101

C
67

43
103
1000011

[00]
0
0
0
0

 
32
20
40
100000

[00]
0
0
0
0

=
61
3D
75
111101

@
64
40
100
1000000

0
48
30
60
110000

0
48
30
60
110000

 
32
20
40
100000

[02]
2
2
2
10

0
48
30
60
110000

[10]
16
10
20
10000

ß
-33
FFFFFFDF
37777777737
11111111111111111111111111011111

[00]
0
0
0
0

O
79
4F
117
1001111

[00]
0
0
0
0

A
65
41
101
1000001

@
64
40
100
1000000

0
48
30
60
110000

0
48
30
60
110000

ü
-4
FFFFFFFC
37777777774
11111111111111111111111111111100

C
67
43
103
1000011

[00]
0
0
0
0

=
61
3D
75
111101

[02]
2
2
2
10

0
48
30
60
110000

[02]
2
2
2
10

i
105
69
151
1101001

 
32
20
40
100000

[00]
0
0
0
0

I
73
49
111
1001001

[00]
0
0
0
0

 
32
20
40
100000

[00]
0
0
0
0

O
79
4F
117
1001111

[00]
0
0
0
0

2
50
32
62
110010

[10]
16
10
20
10000

ß
-33
FFFFFFDF
37777777737
11111111111111111111111111011111

[10]
16
10
20
10000

C
67
43
103
1000011

[00]
0
0
0
0

w
119
77
167
1110111

[00]
0
0
0
0

w
119
77
167
1110111

[00]
0
0
0
0

i
105
69
151
1101001

0
48
30
60
110000

$
36
24
44
100100

9
57
39
71
111001

ü
-4
FFFFFFFC
37777777774
11111111111111111111111111111100

R
82
52
122
1010010

[00]
0
0
0
0

O
79
4F
117
1001111

[02]
2
2
2
10

L
76
4C
114
1001100

@
64
40
100
1000000

ß
-33
FFFFFFDF
37777777737
11111111111111111111111111011111

@
64
40
100
1000000

C
67
43
103
1000011

[00]
0
0
0
0

=
61
3D
75
111101

w
119
77
167
1110111

}
125
7D
175
1111101

9
57
39
71
111001

@
64
40
100
1000000

0
48
30
60
110000

0
48
30
60
110000

o
111
6F
157
1101111

[00]
0
0
0
0

G
71
47
107
1000111

[00]
0
0
0
0

G
71
47
107
1000111

R
82
52
122
1010010

 
32
20
40
100000

R
82
52
122
1010010

[00]
0
0
0
0

=
61
3D
75
111101

@
64
40
100
1000000

L
76
4C
114
1001100

[00]
0
0
0
0

T
84
54
124
1010100

[01]
1
1
1
1

T
84
54
124
1010100

P
80
50
120
1010000

m
109
6D
155
1101101

2
50
32
62
110010

[00]
0
0
0
0

 
32
20
40
100000

[10]
16
10
20
10000

I
73
49
111
1001001

[00]
0
0
0
0

A
65
41
101
1000001

R
82
52
122
1010010

L
76
4C
114
1001100

2
50
32
62
110010

[01]
1
1
1
1

ß
-33
FFFFFFDF
37777777737
11111111111111111111111111011111

[00]
0
0
0
0

 
32
20
40
100000

[00]
0
0
0
0

 
32
20
40
100000

 
32
20
40
100000

ý
-3
FFFFFFFD
37777777775
11111111111111111111111111111101

w
119
77
167
1110111

}
125
7D
175
1111101

2
50
32
62
110010

[10]
16
10
20
10000

L
76
4C
114
1001100

[01]
1
1
1
1

 
32
20
40
100000

@
64

Thanks for the help.

Marc