Who knows how to use bit shift <<?

I am trying to read an encoder from a motor that puts out a string of Hex numbers.

I attached the manufacturer instructions.

The string I get looks like this:
BYTE 0:0 1:92 2:3 3:8 4:DB 5:F6 6:B1 7:0 8:0 9:0 10:0 11:0 12:0 13:A7

and values are changing as I turn the rotor.

In order to compose the encoder reading I tried:

int64_t Enc_Read = mybuffer_A[5] + mybuffer_A[6] << 8 + mybuffer_A[7] << 16 + mybuffer_A[8] << 24 + mybuffer_A[9] << 32

  • mybuffer_A[10] << 40 + mybuffer_A[11] << 48 + mybuffer_A[12] << 56;

int Enc = Enc_Read;
Serial.println (Enc);

But all I get are Zeros. Arduino page is very short on this command.

Please help

Thanks
Mitch

You will need to cast mybuffer_A to (int64_t) to do the bitshift, otherwise the compiler defaults to a 16-bit integer, which is too small for the shift operation.

Trying to set a 16-bit integer to the value of the 64-bit integer is not going to work either, in your example that would give 0xB1F6, which is a negative number. You could use a 32-bit integer, but would be better to check the value first to make sure it is within range.

Since the data is coming in as 8 bytes, with the least significant byte first, my preference would be to use a union to redefine the 8 bytes as an int64_t and forget the bitshifting.

union {
  uint8_t Byte[8];
  int64_t LongLong;
} Enc_Read;

byte mybuffer_A[] = {0x00, 0x92, 0x03, 0x08, 0xDB, 0xF6, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA7
                    };

void setup() {
  Serial.begin(115200);
  byte checksum = 0;
  for (byte i = 0; i < 8; i++) {
    Enc_Read.Byte[i] = mybuffer_A[i + 5];
    checksum = checksum + mybuffer_A[i + 5];
  }
  int32_t Enc = Enc_Read.LongLong;
  Serial.print("Enc: ");
  Serial.println(Enc);
  Serial.print("Checksum: ");
  if (checksum < 16) {
    Serial.print('0');
  }
  Serial.print(checksum, HEX);
  Serial.println(' ');
  
  int64_t  Enc_Read_2 = (int64_t)mybuffer_A[5] +
                      ((int64_t)mybuffer_A[6] << 8)  +
                      ((int64_t)mybuffer_A[7] << 16) +
                      ((int64_t)mybuffer_A[8] << 24) +
                      ((int64_t)mybuffer_A[9] << 32) +
                      ((int64_t)mybuffer_A[10] << 40) +
                      ((int64_t)mybuffer_A[11] << 48) +
                      ((int64_t)mybuffer_A[12] << 56);
  int32_t Enc_2 = Enc_Read_2;
  Serial.print("Enc2: ");
  Serial.println(Enc_2);
  while (true) {};
}

void loop() {
}

(edit) When using bitshift to combine the bytes into an int64_t, it is more efficient to use bitwise OR instead of addition.

David ,

Thanks a lot, The sketch is running fine on an Ardu Mega
but I am using a teensy 3.6,

I have to.

I am reading 6 motors and I have to have the UART Ports....etc

The Teensy just freezes and won't serial output anything....

Please help

Thanks

Actually , I got it to read on teensy,

I did not declared the union, I just used

void Enc_Calc_A(uint8_t motor_id)

{ Show_Inc_String ('A');
int64_t Enc_Read_2 = (int64_t)mybuffer_A[5] +
((int64_t)mybuffer_A[6] << 8) +
((int64_t)mybuffer_A[7] << 16) +
((int64_t)mybuffer_A[8] << 24) +
((int64_t)mybuffer_A[9] << 32) +
((int64_t)mybuffer_A[10] << 40) +
((int64_t)mybuffer_A[11] << 48) +
((int64_t)mybuffer_A[12] << 56);

long Enc_2 = Enc_Read_2;

Mot_Ang_Read [motor_id] = (360 * Enc_2) / 16383.00;
Serial.print("Enc2: ");
Serial.println(Enc_2);
Serial.print("Mot_Ang_Read deg: ");
Serial.println(Mot_Ang_Read [motor_id]);

}

I got excited when the numbers went up as I turned the shaft and became negative as I went CCW....

Then I applied the conversion to degrees, one full turn is 16383 pulses.

Then I realized that the numbers are wrong twice as high but not exactly twice.

Here is what I get after and approximate positive one turn of 360

A: BYTE 0:0 1:92 2:3 3:8 4:DB 5:2B 6:8C 7:0 8:0 9:0 10:0 11:0 12:0 13:B7 14:0 15:0 16:0 17:80
Enc2: 35883
Mot_Ang_Read deg: 788.49

Here how I process the incoming string:
if (Serial2.available()) { // for motors 12345
uint8_t b = Serial2.read(); // always read the next incoming byte
if (b == 0x3E) {
num_received_A = 0; // if begin of message, forget everything previously received
}

else { // we are done with the header
mybuffer_A[num_received_A + 1] = b; // otherwise, put the byte into the buffer
num_received_A ++;
//Serial.println (num_received_A);

if (num_received_A == (4 + mybuffer_A[3] ))// this is "message Complete" first four bytes + the Data Lenght
{
if (mybuffer_A[1] == 0x92 )
Enc_Calc_A(mybuffer_A[2]);

else if (mybuffer_A[1] == 0x9C)
{ ReadMot_Calc_A(mybuffer_A[2]);
// Show_Inc_String ('A');
}

else if (mybuffer_A[1] == 0x30 or mybuffer_A[1] == 0x31 or mybuffer_A[1] == 0x32) // 30 31 and 32 are pertaining to PID
{ Read_PID_Calc('A');
// Show_Inc_String ('B');
}

else
Show_Inc_String ('A');

}

} // end of "if getting bytes in the array
// check if the buffer is full (shouldn't happen, right?)
if (num_received_A >= 20) {
num_received_A = 0; // discard everything
Serial.print(" Overflow A");
Show_Inc_String ('A');
} // end of else iteration

} // end of ser available

The condition
mybuffer_A[1] == 0x92
applies to receiving this multi angle turn data, calling the function above.

What to do?
Thank you David,