Problem with set_linear_position(0) in Arduino

Hi all

I have no problem using the odrivetool to use set_linear_position(0) but when I use arduino, it gives the following:

123124

Somehow it was successful momentarily then went back to the old value
I use the command in arduino:Serial1 << "w axis" << 1 << ".encoder.set_linear_position(0)\n";

Any idea what’s wrong?

The most obvious thing to me is it looks like serial communication stalls for several seconds right before you receive a response of zero. It looks like you’re continuously calculating and updating the setpoint. You may be trying to send data too fast and overflowing the UART buffer either on your microcontroler or the ODrive. Try sending data at regular intervals and see if that improves your results. The release candidate branch has a feature that allows you adjust the UART baudrate if you need additional bandwidth.
You also may have issues with electrical noise interfering with UART communications. It’s impossible to properly troubleshoot without an Oscilliscope but it may be worth adjusting your setup to make your UART lines shorter and try keeping them farther away from your motor power wires.

Interesting. odrive uses 115200 baud rate. Are you saying I should go slower? I even put delays as such:

  Serial1 << "w axis" << 1 << ".encoder.set_linear_count(0)\n"; 
  delay(50);
  Serial1 << "w axis" << 0 << ".encoder.set_linear_count(0)\n";
  delay(50);

I also tried:

  static const unsigned long duration = 500;
  unsigned long start = millis();
  while(millis() - start < duration) {
    for (int motor = 0; motor < 1; ++motor) {
      Serial1 << "w axis" << motor << ".encoder.set_linear_count(0)\n";
      delay(10);
    }
  }

I also moved UART lines far from motor but still doesn’t work…

What sort of Arduino board are you using? I noticed you are using Serial1 to do your UART communication which on most Arduino boards would be a software emulation of a serial port. You really want to be using a true hardware UART peripheral for doing real time control. Look at the documentation that came with your Arduino board and ensure that are using the hardware UART peripheral.

I’m doing things very similarly in that I am sending frequent position setpoint update. I am not familiar with encoder.set_linear_count() though. Instead I am using commands that look like this “w axis0.controller.pos_setpoint XXXX”. I’ve had no problem sending position setpoints as fast as 100Hz.

I am communicating through ASCII using the USB (CDC interface set to the usbser driver in zadig). I meant to try connecting to the physical UART port of the ODrive but I have not yet.

Not sure if that’s helpful. Perhaps you could try sending commands using pos_setpoint instead. If the problem persists then more than likely the issue might be related to the UART port (lagging or otherwise).

Cheers

I’m using Arduino Mega 2560, specifically Naked Mega. It has four specialised UART port and Serial1 is one of them.

I’m trying to reset the encoder readings back to zero. that’s what encoder.set_linear_count() does. But as you can see, it was zero momentarily and then start counting back from the old value…

I’m don’t think UART port is the problem. I’ve been able to r and w other commands but somehow when it comes to encoder.set_linear_count(), it fell short…

I see the problem. The ASCII protocol has the unfortunate limitation of being unable to call functions within the ODrive interface. The 0 reading you were seeing must have been due to a glitch. What you probably are going have to do is modify your code to measure an offset between your “soft” zero position and use that to send a position that reflects your new zero.

I thought of doing that workaround. I’m not sure about the limitation of the call functions you spoke of. For example:

  1. I’m able to use Serial1 << "w axis" << axis << ".controller.config.vel_limit " << VEL_LIMIT << '\n'; and then the change will be reflected when I used Serial1 << "r axis" << axis << ".controller.config.vel_limit " << VEL_LIMIT << '\n';
  2. I’m able to use Serial1 << "w axis" << axis << ".controller.config.vel_gain " << vel_Gain << '\n'; and then the change will be reflected when I used Serial1 << "r axis" << axis << ".controller.config.vel_gain\n";

However, as in my original post, I used Serial1 << "w axis" << 1 << ".encoder.set_linear_position(0)\n"; but the change was only reflected momentarily (the 2 zeros you saw) after I used Serial1 << "r axis" << axis << ".encoder.pos_estimate\n"; to read the current position…

vel_gain and simillar are properties, not functions. Note the lack of of parenthesis. When you try to use a function over the ASCII protocol the ODrive will return an error over the UART interface. I suspect that the reason you are seeing a zero value returned is that the Arduino serial library is unable to parse the error message as a numerical value, times out, and returns a zero. You should be able to see the error returned by the ODrive by modifying your code to print out the returned string value read in from the UART interface Serial.readString().