Getting feedback position via serial on a 21v3

Hello all, I’m working on a robotics project and I have no clue what I’m doing :slight_smile: I have 3 21v3 units that are controlling 3 linear actuators to move the legs on my bot. I have the legs moving the way I want them to via serial from my Arduino, but now I’d like to be able to read the current feedback. Long story short, I have two outer legs that need to be in a certain position before my 3rd leg starts moving.

Here’s the code I’m working with so far

         myLeftSerial.write(0xAA); //tells the controller we're starting to send it commands
         myLeftSerial.write(0xD);   //This is the pololu device # you're connected too that is found in the config utility(converted to hex). I'm using #13 in this example
         myLeftSerial.write(0xA5);

         word extend_uiFeedback = myLeftSerial.read();
        

        Serial.print ("Value after left retract: ");
        Serial.println(extend_uiFeedback); //print it out for fun
        Serial.print("\n");

The results I’m seeing are all over the place so I’m probably doing something very wrong. Any help would be greatly appreciated.

It looks like you are using the variable command byte 0xA5. This specifies that you are requesting both the low and high return bytes, but you are only reading one of those bytes. The returned bytes should be little endian, so the first byte returned will be the least-significant byte, and the second will be the most-significant byte. You can then combine those to get the returned feedback value. More information about this can be found in the “Variable Reading Commands” section of the jrk user’s guide.

If you try reading and combining both bytes and continue to have problems, you can post your updated code, and I would be glad to take a look.

-Brandon

Thanks! I think I’m getting closer. Here’s my code.

void Extend() {
    MoveCenter(centerExtend);
    delay(3700);
    MoveRight(legExtend);
    MoveLeft(legExtend);
    delay(5000);

    
     myLeftSerial.write(0xAA); //tells the controller we're starting to send it commands
     myLeftSerial.write(0xD);   //This is the pololu device # you're connected too that is found in the config utility(converted to hex). I'm using #13 in this example
     myLeftSerial.write(0xA5);
  
     word lowBit =  myLeftSerial.read();
     word highBit = myLeftSerial.read();
     word extend_uiFeedback = word(highBit,lowBit);
    
  
    Serial.print ("Value after left extend: ");
    Serial.println(extend_uiFeedback); 
    Serial.print("\n");

    lowBit = 0; highBit=0; retract_uiFeedback = 0;
}


void Retract() {
    MoveRight(legRetract);
    MoveLeft(legRetract);
    delay(3700);
    MoveCenter(centerRetract);
    delay(5000);


     myLeftSerial.write(0xAA); //tells the controller we're starting to send it commands
     myLeftSerial.write(0xD);   //This is the pololu device # you're connected too that is found in the config utility(converted to hex). I'm using #13 in this example
     myLeftSerial.write(0xA5);
  
     word lowBit =  myLeftSerial.read();
     word highBit = myLeftSerial.read();
     word retract_uiFeedback = word(highBit,lowBit);


    Serial.print ("Value after left retract: ");
    Serial.println(retract_uiFeedback ); 
    Serial.print("\n");

    lowBit = 0; highBit=0; retract_uiFeedback = 0;
}

and here’s my serial output

Program begin
My i2c address: 7
Waiting for i2c command
Extend
Value after left extend: 65535

Retract
Value after left retract: 2538

Extend
Value after left extend: 1448

Retract
Value after left retract: 2538

Extend
Value after left extend: 1449

Retract
Value after left retract: 2540

My target is set to 4000 on the extend and 700 on the retract. It looks like the numbers are moving in the right direction, except for the first time reading. Am I reading the wrong variables in? If I change it target (0xA3) I get 4000 and 700 exactly back every time but the first. Is that the actual position of the actuator or just what the actuator was told to go to?

It looks like the first time you read the feedback, it is returning all high bits (resulting in 0xFFFF). This is likely caused by trying to read the returned bytes before the jrk has processed the command and send the response back, which would also explain why your retracted values are high and your extended values are low (since all of your readings are behind by one). Either that or you have the “invert motor direction” option checked in the “Motor” tab of the Jrk Configuration Utility. You might try either adding a small delay after sending the command byte, or using something like while(!Serial.available()); to wait until you receive the response before continuing.

Aside from that, it looks like you are reading the variables in the right order, and they could be reasonable depending on how your feedback scaling is set. The “Target” variable is returning what target was last commanded (so it is good to see the same values you sent when you read it back).

Since you are reading the feedback variable, it will correspond to the voltage being read from your potentiometer when the read variable command is sent. The Scaled Feedback variable (command byte 0xA7) will give you the value after it is mapped according to the scaling calibration set in the “Feedback” tab of the Jrk Configuration Utility, so if you read the scaled feedback instead, it should return a value closer to the target (depending on your PID settings).

If you try making those adjustments and still have some problems, could you post your complete code so I can see what your other functions do (e.g. MoveCenter, MoveRight, MoveLeft)? Also, from your serial monitor, it looks like you might be doing something with I2C, so it sounds like you might have some other stuff going on in your system. If this is the case and you think your complete code would be too lengthy for troubleshooting just the jrk code, can you try writing a simplified sketch that demonstrates the problem (e.g. set the target, wait for it to reach the target, read the scaled feedback)?

-Brandon

FYI: this code worked for me:

int GetMyJrkPosition(byte command)
{
  char response[2];
  myJrk.listen();
  myJrk.write(0xAA);
  myJrk.write(0x0B);//the Device Number is set in the Serial Interface box in the Input tab of your jrk config utility
  myJrk.write(command);
  while (myJrk.available() < 2);//wait for it to become available
  myJrk.readBytes(response,2);
  return word(response[1],response[0]);
}

void GetCurrentPosition()
{
  word feedbackPosition = GetMyJrkPosition(0xA5);
  Serial.print("feedbackPosition: ");
  Serial.println(feedbackPosition);
  word scaledFeedbackPosition = GetMyJrkPosition(0xA7);
  Serial.print("scaledFeedbackPosition: ");
  Serial.println(scaledFeedbackPosition);
}
1 Like