I am using a 24v V3.6 odrive with razoredge firmware.
The Arduino code I used is basically the example code with small modifications. The code is attached at the end of the post.
Symptom:
I can check the voltage and encoder readings on Arduino just fine. But the motor freezes randomly when I try to set its positions via UART. Most of the time, the motor follows the position command for a while and freezes randomly.
I tried two different commands to set the motor position. Both of them would stall the odrive randomly.
Serial1 << "p " << 1 << " " << pos_m1 << '\n';
Serial1 << "w axis" << 1 << ".controller.input_pos " << pos_m1 << '\n';
When frozen, Odrive does not respond to any odrivetool commands or UART inputs from the Arduino. The only way to reset is to cut power and reboot.
Sending the motor position at different frequency doesn’t seem to help. I have tried 200Hz (delay(5)) and 20Hz (delay(50)).
Does anyone else have the same problem? What’s the cause of the problem? Any help is appreciated!
EDIT:
https://discourse.odriverobotics.com/t/uart-communication-maximum-frequency-timeout/844/2
This post suggests some changes in the firmware. Will try it later on.
#include <SoftwareSerial.h>
#include <ODriveArduino.h>
// 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
// Note: you must also connect GND on ODrive to GND on Arduino!
// ODrive object
ODriveArduino odrive(Serial1);
void setup() {
// ODrive uses 115200 baud
Serial1.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) {
Serial1 << "w axis" << axis << ".controller.config.vel_limit " << 22000.0f << '\n';
Serial1 << "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' to set odrive to idle");
Serial.println("Send the character '1' to set odrive to calibration");
Serial.println("Send the character '2' to set odrive to closed loop control");
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();
// set odrive to idle
if (c == '0') {
Serial1 << "w axis" << 1 << ".requested_state " << 1 << '\n';
c = '3';
}
// Run calibration sequence
if (c == '1') {
Serial1 << "w axis" << 1 << ".requested_state " << 3 << '\n';
c = '3';
}
// set odrive to closed loop ctrl
if (c == '2') {
Serial1 << "w axis" << 1 << ".requested_state " << 8 << '\n';
c = '3';
}
// Sinusoidal test move
if (c == 's') {
Serial.println("Executing test move");
for (float ph = 0.0f; ph < 6.28318530718f; ph += 0.01f) {
float pos_m1 = 20000.0f * sin(ph);
// Serial1 << "w axis" << 1 << ".controller.input_pos " << pos_m1 << '\n';
Serial1 << "p " << 1 << " " << pos_m1 << '\n';
delay(10);
}
}
// Read bus voltage
if (c == 'b') {
Serial1 << "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) {
Serial1 << "r axis" << motor << ".encoder.pos_estimate\n";
Serial << odrive.readFloat() << '\t';
}
Serial << '\n';
}
}
}
}