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';
      }
    }
  }
}

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.