How to measure the bytes coming in a serial event?

I am reading a "smart Encoder" that is sending me a stream of 12 bytes.

I am putting them in an array like this:

  while (Serial1.available() > 11 ) // Wait 'till there are 9 Bytes waiting
  {
    for (int n = 0; n < 12; n++)
    { in_bytes[n] = Serial1.read();
    
    
    }
    Serial.print("Byte 0:  ");
    Serial.println(in_bytes[0], HEX);
    Serial.print("Byte 1:  ");
    Serial.println(in_bytes[1], HEX);
     Serial.print("Byte 2:  ");
    Serial.println(in_bytes[2], HEX);
    Serial.print("Byte 3:  ");
    Serial.println(in_bytes[3], HEX);
     Serial.print("Byte 4:  ");
    Serial.println(in_bytes[4], HEX);
    Serial.print("Byte 5:  ");
    Serial.println(in_bytes[5], HEX);
     Serial.print("Byte 6:  ");
    Serial.println(in_bytes[6], HEX);
   // Serial.print("Byte 7:  ");
   // Serial.println(in_bytes[7], HEX);
    
    //delay (5);
  }

It seems to work well, but if there is a smarter way, I am all ears.

Now the problem:

Per manufacturer's instructions, the encoder value is composed from the [5] and [6] byte.
I attached the sheet.

How do I compose the full number?

All Arduino references are telling me "Extracts the low-order (rightmost) byte of a variable (e.g. a word)." but nothing about adding those bytes.

Thanks a lot
Mitch

PS
Here is how my serial read looks
Reading Enc: 3
Byte 0: 3E
Byte 1: 90
Byte 2: 3
Byte 3: 6
Byte 4: D7
Byte 5: 236
Byte 6: 39

Screen Shot 2019-12-12 at 12.51.46 PM.png

I am reading a "smart Encoder" that is sending me a stream of 12 bytes.

    for (int n = 0; n < 12; n++)
    { in_bytes[n] = Serial1.read();

How many bytes are you reading ?
How and where is in_bytes declared ?
How many elements does the array have ?

In declarations before setup I defined
byte in_bytes[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};

I am reading all 12 bytes , but I dont need them all.

Does this help?

If you want to create an int from two bytes in an array, and assuming the second of the pair is the high byte you can do this

Edit to make a correction. My first version was like this
int myNumber = in_bytes[5] + in_bytes[6] << 8;

and it should be

int myNumber = in_bytes[5] + (in_bytes[6] << 8);

The << operator shifts the data to the left, in this case 8 times.

...R

Robin , thanks for your help.

I implemented your command and I am printing out the new composed number as a DEC.

As I turn the encoder, the number is changing (Good) but the values are not increasing proportional to the turn , they seem to be random.

here is the code

if (in_bytes[1] == 0x90) // this  is to know the encoder responded.
    { Serial.print("ENC Byte 5:  ");
      Serial.println(in_bytes[5], HEX);
      Serial.print("ENC Byte 6:  ");
      Serial.println(in_bytes[6], HEX);
      int Enc_Read = in_bytes[5] + in_bytes[6] << 8;
      Serial.print("Reading Enc: ");
    //  Serial.println(motor_id);
      Serial.println(Enc_Read, DEC);
    }

Here are the readings:

ENC Byte 5: 37
ENC Byte 6: 2E
Reading Enc: 25856
ENC Byte 5: 9
ENC Byte 6: 2F
Reading Enc: 14336
ENC Byte 5: 76
ENC Byte 6: 2D
Reading Enc: 41728

Here is what they user guide says I should get

Driver respond(12byte)
The motor replies to the computer host after receiving the command, and the reply data contains the following parameters.
1.Encoder position encoder (uint16_t type, 14bit encoder value range 0~16383), which is the original position of encoder minus encoder offset.
2.Original position of encoder (uint16_t type, 14bit encoder value range 0~16383).
3.EncoderOffset (uint16_t type, 14bit encoder value range 0~16383), and this point is taken as the 0 point of the motor Angle.
Data Field Instructions Data
DATA[0] Head byte 0x3E
DATA[1] Command byte 0x90
DATA[2] ID byte 0x01~0x20
DATA[3] Data length byte 0x06
DATA[4] Frame header check byte DATA[0]~DATA[3]Byte checksum
DATA[5] Encoder data in low bytes =*(uint8_t )(&encoder)
DATA[6] Encoder data in high bytes =
((uint8_t )(&encoder)+1)
DATA[7] Encoder original position low byte =
(uint8_t )(&encoderRaw)
DATA[8] Encoder original position high byte =
((uint8_t *)(&encoderRaw)+1)
DATA[9] Encoder zero low byte = *(uint8_t *)(&encoderOffset)
DATA[10] Encoder zero high byte = *((uint8_t *)(&encoderOffset)+1)
DATA[11] Data check byte DATA[5]~DATA[10]Byte checksum

Can you figure it please?

Thanks a lot
Mitch

laptophead:
here is the code

Can you figure it please?

I made a mistake in Reply #3. The code should have brackets like this

int myNumber = in_bytes[5] + (in_bytes[6] << 8);

If that does not solve the problem please post the complete program and also post a link to the datasheet for the encoder.

...R

Robin
That worked, thanks a lot,

However I am facing other problems. The same serial port is receiving all kind of other data , some of it in different lengths (other than 12 bytes at the time.)

When I boot the teensy , it all works fine, based on the
if (in_bytes[1] == 0x90)

I am able to extract my encoder and convert it to angle degrees.
int Enc_Read = in_bytes[5] + (in_bytes[6] << 8);
double Mot_Ang_Read = (360 * Enc_Read) / 16383.00;

But when I send other commands , for example 's' from the keyboard Stops the motors, then my incoming byte order gets confused.
I am no longer able to use 'e' for read encoder and to obtain an angle.

here is what the Serial puts out:

e

e
3 Mot_Ang_Read : 155.99°

e
3 Mot_Ang_Read : 155.99°

s
3 Mot_Ang_Read : 227.63°
Byte 0: 3E
Byte 1: 81
Byte 2: 1
Byte 3: 0
Byte 4: C0
Byte 5: 3E
Byte 6: 81
Byte 7: 2
Byte 8: 0
Byte 9: C1
Byte 10: 3E
Byte 11: 81
Byte 12: 0
Byte 13: 0
Byte 14: 0
Byte 15: 0
Byte 16: 0
Byte 17: 0

So what I want to do:
clean the buffer so when I place an 'e" command my if gets recognition
and I can read the angles.

here is the function for 'e'

void Read_Enc ( unsigned char motor_id)

{
  // 16383 steps per turn
   in_bytes[0] = 0;
  in_bytes[1] = 0;
  in_bytes[2] = 0;
  in_bytes[3] = 0;
  in_bytes[4] = 0;
  byte cmd_send_buf[5];
  cmd_send_buf[0] = 0x3E;  //header
  cmd_send_buf[1] = 0x90;   // cmd_id-- Read enc
  cmd_send_buf[2] = motor_id; 
  cmd_send_buf[3] = 0x00;      // data lenght
  cmd_send_buf[4] = cmd_send_buf[0] + cmd_send_buf[1]+ cmd_send_buf[2]+ cmd_send_buf[3]; // check sum
 
  Serial1.write (cmd_send_buf, 5);
  //Serial.println ("Reading Enc");
  delay (2);// wait for response
}

The spec sheet of this motor with controller can be found at

http://dow.gyems.cn/RMD-servo%20motor%20control%20protocol%20(RS485)%20V1.6.pdf

Thanks a lot

Mitch

laptophead:
However I am facing other problems. The same serial port is receiving all kind of other data , some of it in different lengths (other than 12 bytes at the time.)

I don't have much time today but I find your Reply #6 very confusing.

Start by explaining how the serial port can be receiving other kinds of data and provide an example of each type of message.

...R

I am communicating to encoded motor via serial write and serial read
I am receiving bytes, as hex numbers.

Sometimes I get 12 bytes, that is encoder reading.
Sometimes I get 18 bytes , that is a motor confirming a command.

I want to distinguish the situations, so I can call the encoder read anytime and get results correctly

so I wrote

void serialEvent() {
  if (Serial1.available() ==12) {

    for (int n = 0; n < 12; n++)
    { in_bytes[n] = Serial1.read();

    }
    // /*

    if (in_bytes[1] == 0x90)
    { //Serial.print("ENC Byte 5:  ");
      //Serial.println(in_bytes[5], HEX);
      //Serial.print("ENC Byte 6:  ");
      //Serial.println(in_bytes[6], HEX);
      int Enc_Read = in_bytes[5] + (in_bytes[6] << 8);
      double Mot_Ang_Read = (360 * Enc_Read) / 16383.00;

      Serial.print(in_bytes[2], DEC);
      Serial.print(" Mot_Ang_Read : ");
      Serial.print(Mot_Ang_Read, 2);
      Serial.println("°");
      //  Serial.println(motor_id);
      //Serial.println(Enc_Read, DEC);
    }

    else if (Serial1.available() ==18) 
    { Serial.print("Byte 0:  ");
      Serial.println(in_bytes[0], HEX);
      Serial.print("Byte 1:  ");
      Serial.println(in_bytes[1], HEX);
      Serial.print("Byte 2:  ");
      Serial.println(in_bytes[2], HEX);
      Serial.print("Byte 3:  ");
      Serial.println(in_bytes[3], HEX);
      Serial.print("Byte 4:  ");
      Serial.println(in_bytes[4], HEX);
      Serial.print("Byte 5:  ");
      Serial.println(in_bytes[5], HEX);
      Serial.print("Byte 6:  ");
      Serial.println(in_bytes[6], HEX);
      Serial.print("Byte 7:  ");
      Serial.println(in_bytes[7], HEX);

      Serial.print("Byte 8:  ");
      Serial.println(in_bytes[8], HEX);
      Serial.print("Byte 9:  ");
      Serial.println(in_bytes[9], HEX);
      Serial.print("Byte 10:  ");
      Serial.println(in_bytes[10], HEX);
      Serial.print("Byte 11:  ");
      Serial.println(in_bytes[11], HEX);
      Serial.print("Byte 12:  ");
      Serial.println(in_bytes[12], HEX);
      Serial.print("Byte 13:  ");
      Serial.println(in_bytes[13], HEX);
      Serial.print("Byte 14:  ");
      Serial.println(in_bytes[14], HEX);
      Serial.print("Byte 15:  ");
      Serial.println(in_bytes[15], HEX);
      Serial.print("Byte 16:  ");
      Serial.println(in_bytes[16], HEX);
      Serial.print("Byte 17:  ");
      Serial.println(in_bytes[17], HEX);
      //*/
    } // end of else
  } // end of while serial available

}// end of serial event

The problem:
This works well only when my transmissions are 12 bytes,.

When I receive 18 bytes, it gets confused and it does not execute the first if or else.

Please help
Thanks
Mitch

Isn't this just more of the same project that we have been helping with in your other Thread. Please click Report to Moderator and ask to have the Threads merged so we have all the info in one place.

...R

PS ... you have not answered my question in the other Thread

Robin,
I think the two threads are merged, they are identical.

I think I solved the problem. Alongside the "serial event" I also did a read of the serial1 in the main loop

if (Serial1.available()) { // this is necessary so all bytes get read and dont linger in the buffer
byte inByte = Serial1.read();
}

This seems to flush all the incoming data and makes the buffer fresh for the next transmission.

My serial event looks like this

void serialEvent() {

  
  
  while (Serial1.available() > 8 ) // serial will wait for "Bytes_In_A"  before
  {
    for (int n = 0; n < 8; n++)
    { in_bytes[n] = Serial1.read();
      if (n == 7)
      { Show_Inc_String ();
      }
    } // end of for loop
    if  (in_bytes[1] == 0x90  )
    { int Enc_Read = in_bytes[5] + (in_bytes[6] << 8);
      double Mot_Ang_Read = (360 * Enc_Read) / 16383.00;

      Serial.print(in_bytes[2], DEC);  // the motor id, there are up to 8 on a bus.
      Serial.print(" Mot_Ang_Read : ");
      Serial.print(Mot_Ang_Read, 2);
      Serial.println("°");
      //  Serial.println(motor_id);
      //Serial.println(Enc_Read, DEC);
      
    }// end of encoder if
  } // end of while serial avail

So I think I am good for right now.

Hope this helps others.
Thank you
Mitch