The Bitshift << drives me crazy, please HELP

Status
Not open for further replies.

laptophead

Well-known member
I am reading this fancy encoder sending me a Hex string, see attach link from the manufacturer.
http://dow.gyems.cn/RMD-servo motor control protocol (RS485) V1.6.pdf

I am trying to accomplish chapter 9 , multi turn angle read.

Here is my incoming string processing, Paul taught me, thank you,

HTML:
  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

To figure the multi turn angle I tried:

HTML:
void Enc_Calc_A(uint8_t motor_id)
{ //uint16_t  Enc_Read = mybuffer_A[5] + (mybuffer_A[6] << 8);


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;

   
   sprintf(data, "mybuffer_A[5]:%u  mybuffer_A[6]:%u   mybuffer_A[7]:%u  Enc_Read:%u  Deg:%.1f° ", mybuffer_A[5], mybuffer_A[6] << 8, mybuffer_A[7] << 16, Enc_2,  Mot_Ang_Read[motor_id]);
   Serial.println(data);


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 couple examples of what I get.

A: BYTE 0:0 1:92 2:3 3:8 4:DB 5:58 6:13 7:0 8:0 9:0 10:0 11:0 12:0 13:6B 14:0 15:0 16:0 17:0
mybuffer_A[5]:88 mybuffer_A[6]:4864 mybuffer_A[7]:0 Enc_Read:4952 Deg:108.8°




here is after a 360 deg positive turn.
A: BYTE 0:0 1:92 2:3 3:8 4:DB 5:E 6:8C 7:0 8:0 9:0 10:0 11:0 12:0 13:9A 14:0 15:0 16:0 17:0
mybuffer_A[5]:14 mybuffer_A[6]:35840 mybuffer_A[7]:0 Enc_Read:35854 Deg:787.9°

What am I missing?

By the way, Teensy can't Serial print a int64_t, so I converted it to long.

Please help

Mitch
 
Hi,

just curious, how did you determine that 16383 corresponds to a full 360 turn? Sorry, I just skimmed the data sheet, but couldn't immediately find anything.
 
Actually that was it. The pulses vary based on single turn or multi turn...

For multi turn, this is the correct formula, in case others need it

long Enc_2 = Enc_Read_2;
Mot_Ang_Read [motor_id] = Enc_2 / 100.00;

case closed
 
Status
Not open for further replies.
Back
Top