Arduino to oDrive communication UART

Hi,

i have oDrive board v3.6, i updated software to v0.4.11. If i connect arduino to oDrive board, comunication doesnť work. For example if i send comand to read voltage arduino return 0.0000 V. If i send comand pc to oDrive board, answer is 24.01 V.

I tried Arduino Uno/Mega 2560. I was looking for solution on this forum, but i can not find solution.

Do you have some ideas how fix this problem?

Thanks
Hynek

You have connected TX and RX and GND from the Arduino to the ODrive? Can you share how your Arduino code?

I have exactly the same problem. oDrive board v3.6, software v0.4.11, Arduino nano using hardware serial. (Ard TX - oDrv RX, Ard RX - oDrv TX, Ground - Ground)

I can send position commands to oDrive but cannot receive data.

However, I am able to send and receive serial data when connected to oDrive via USB and using MaxMSP.

Heres the arduino code…just a mangled version of the example

//#include <SoftwareSerial.h>
#include <ODriveArduino.h>

HardwareSerial & odrive_serial = Serial;


// Printing with stream operator
template<class T> inline Print& operator <<(Print &obj,     T arg) { obj.print(arg);    return obj; }
template<>        inline Print& operator <<(Print &obj, float arg) { obj.print(arg, 4); return obj; }

// Serial to the ODrive
//SoftwareSerial odrive_serial(7, 8); //RX (ODrive TX), TX (ODrive RX)
// Note: you must also connect GND on ODrive to GND on Arduino!

// ODrive object
ODriveArduino odrive(odrive_serial);

void setup() {
  // ODrive uses 115200 baud
  odrive_serial.begin(115200);

  // Serial to PC
  Serial.begin(115200);
  while (!Serial) ; // wait for Arduino Serial Monitor to open

  Serial.println("ODriveArduino");
  Serial.println("Setting parameters...");

  // In this example we set the same parameters to both motors.
  // You can of course set them different if you want.
  // See the documentation or play around in odrivetool to see the available parameters
 // for (int axis = 0; axis < 2; ++axis) {
 //   odrive_serial << "w axis" << axis << ".controller.config.vel_limit " << 22000.0f << '\n';
 //   odrive_serial << "w axis" << axis << ".motor.config.current_lim " << 11.0f << '\n';
    // This ends up writing something like "w axis0.motor.config.current_lim 10.0\n"
  //}

  Serial.println("Ready!");
  Serial.println("Send the character '0' or '1' to calibrate respective motor (you must do this before you can command movement)");
  Serial.println("Send the character 's' to exectue test move");
  Serial.println("Send the character 'b' to read bus voltage");
  Serial.println("Send the character 'p' to read motor positions in a 10s loop");
  Serial.println("Send the character 'g' go to 20000");
  Serial.println("Send the character 'h' go to 0");
}

void loop() {

  if (Serial.available()) {
    char c = Serial.read();

    // Run calibration sequence
    if (c == '0' || c == '1') {
      int motornum = c-'0';
      int requested_state;

      requested_state = ODriveArduino::AXIS_STATE_MOTOR_CALIBRATION;
      Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
      odrive.run_state(motornum, requested_state, true);

      requested_state = ODriveArduino::AXIS_STATE_ENCODER_OFFSET_CALIBRATION;
      Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
      odrive.run_state(motornum, requested_state, true);

      requested_state = ODriveArduino::AXIS_STATE_CLOSED_LOOP_CONTROL;
      Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
      odrive.run_state(motornum, requested_state, false); // don't wait
    }

    // Sinusoidal test move
    if (c == 's') {
      Serial.println("Executing test move");
      for (float ph = 0.0f; ph < 6.28318530718f; ph += 0.01f) {
        float pos_m0 = 20000.0f * cos(ph);
       // float pos_m1 = 20000.0f * sin(ph);
        odrive.SetPosition(0, pos_m0);
      //  odrive.SetPosition(1, pos_m1);
        delay(5);
      }
    }
    
if (c == 'g') {
      Serial.println("g = go to 20000");
        odrive.SetPosition(0, 20000);
        delay(5);
      }
if (c == 'h') {
      Serial.println("g = go to 0");
        odrive.SetPosition(0, 0);
        delay(5);
      }

      
    

    // Read bus voltage
    if (c == 'b') {
      odrive_serial << "r vbus_voltage\n";
      Serial << "Vbus voltage: " << odrive.readFloat() << '\n';
    }

    // print motor positions in a 10s loop
    if (c == 'p') {
      static const unsigned long duration = 10000;
      unsigned long start = millis();
      while(millis() - start < duration) {
        for (int motor = 0; motor < 2; ++motor) {
          odrive_serial << "r axis" << motor << ".encoder.pos_estimate\n";
          Serial << odrive.readFloat() << '\t';
        }
        Serial << '\n';
      }
    }
  }
}
1 Like

Are you trying to use the same serial port for the odrive as for your user control interface?

The USB for the oDrive is unplugged, only the USB to the arduino is connected.

No, i mean this line:

HardwareSerial & odrive_serial = Serial;

I’m not so familiar with Arduino, but does this mean that all the messages that you are printing on Serial, also go to the odrive?
If so, it would confuse the interface with many unexpected characters.

1 Like

Yes, that was it. Thankyou!

1 Like

How did you fix this issue?

In the end I was using an ESP32 and OSC over WiFi to control the ODrive but I believe to get the Arduino serial working I used two separate serial ports. All the communication to the computer was done on “Serial” while the communication with ODrive was done on “Serial1”. If you look at the Odrive Arduino Test example file it shows how this can be setup with different Arduino boards. Hope that helps.

I have same problem where I am using different Serial Port but still not getting communication between odrive and arduino uno

#include <SoftwareSerial.h>
#include <ODriveArduino.h>

// Printing with stream operator
template inline Print& operator<<(Print& obj, T arg) {
obj.print(arg);
return obj;
}
template<> inline Print& operator<<(Print& obj, float arg) {
obj.print(arg, 4);
return obj;
}

// Serial to the ODrive
SoftwareSerial odrive_serial(8, 9); //RX (ODrive TX), TX (ODrive RX)
// Note: you must also connect GND on ODrive to GND on Arduino!

// ODrive object
ODriveArduino odrive(odrive_serial);

void setup() {
// ODrive uses 115200 baud
odrive_serial.begin(115200);

// Serial to PC
Serial.begin(115200);
while (!Serial)
; // wait for Arduino Serial Monitor to open

Serial.println(“ODriveArduino”);
Serial.println(“Setting parameters…”);

// In this example we set the same parameters to both motors.
// You can of course set them different if you want.
// See the documentation or play around in odrivetool to see the available parameters
for (int axis = 0; axis < 2; ++axis) {
odrive_serial << “w axis” << axis << ".controller.config.vel_limit " << 40.0f << ‘\n’;
odrive_serial << “w axis” << axis << ".motor.config.current_lim " << 30.0f << ‘\n’;
}

Serial.println(“Ready!”);
Serial.println(“Send the character ‘0’ or ‘1’ to calibrate respective motor (you must do this before you can command movement)”);
Serial.println(“Send the character ‘s’ to exectue test move”);
Serial.println(“Send the character ‘b’ to read bus voltage”);
Serial.println(“Send the character ‘p’ to read motor positions in a 10s loop”);
}

void loop() {

if (Serial.available()) {
char c = Serial.read();

// Run calibration sequence
if (c == '0' || c == '1') {
  int motornum = c - '0';
  int requested_state;

  requested_state = ODriveArduino::AXIS_STATE_MOTOR_CALIBRATION;
  Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
  odrive.run_state(motornum, requested_state, true);

  requested_state = ODriveArduino::AXIS_STATE_ENCODER_OFFSET_CALIBRATION;
  Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
  odrive.run_state(motornum, requested_state, true);

  requested_state = ODriveArduino::AXIS_STATE_CLOSED_LOOP_CONTROL;
  Serial << "Axis" << c << ": Requesting state " << requested_state << '\n';
  odrive.run_state(motornum, requested_state, false);  // don't wait
}

// Sinusoidal test move
if (c == 's') {
  Serial.println("Executing test move");
  for (float ph = 0.0f; ph < 6.28318530718f; ph += 0.01f) {
    float pos_m0 = 50.0f * cos(ph);
    // float pos_m1 = 50.0f * sin(ph);
    odrive.SetPosition(0, pos_m0);
    //odrive.SetPosition(1, pos_m1);
    delay(5);
  }
}

// Read bus voltage
if (c == 'b') {
  odrive_serial << "r vbus_voltage\n";
  Serial << "Vbus voltage: " << odrive.readFloat() << '\n';
}

// print motor positions in a 10s loop
if (c == 'p') {
  static const unsigned long duration = 10000;
  unsigned long start = millis();
  while (millis() - start < duration) {
    for (int motor = 0; motor < 2; ++motor) {
      odrive_serial << "r axis" << motor << ".encoder.pos_estimate\n";
      Serial << odrive.readFloat() << '\t';
    }
    Serial << '\n';
  }
}

}
}

Hi Harsh,
I am new to odrive too. Also, to interface ARDUINO, CAN and odrive I also faced the same issue. There were errors in my case. If you have solved it, can you elaborate it…

Thanks you.

Hi Payal,
I solved the problem, but I used the UART for communication between odrive & Arduino. where Baud rate problem in Odrive side. you can use my code. it is given as below.

dev0.config.gpio1_mode = GPIO_MODE_UART_A

dev0.config.gpio2_mode = GPIO_MODE_UART_A

dev0.config.enable_uart_a=True

dev0.config.uart_a_baudrate = 19200

dev0.config.uart0_protocol=STREAM_PROTOCOL_TYPE_ASCII_AND_STDOUT

dev0.save_configuration().

I tried typing this in but my command prompt does not recognize gpio1.