Newbie to Odrive: Needs help with a school graduation project

Hello, I’m new to the ODrive scene. I’m working on my school graduation project in which I need to control the velocity of an electric motor with an ODrive S1 and an Arduino Uno. Unfortunately, I haven’t been able to get my code running. Can somebody help me with this?
With kind regards from Austria!

#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#define I2C_ADDRESS 0x3c

#include <ODriveUART.h>     // ODrive
#include <SoftwareSerial.h> // ODrive

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd1(0x27, 16, 2);
LiquidCrystal_I2C lcd2(0x3F, 16, 2);

/* MASTER */
#define NODE_MAX_NUMBER 5
#define PAYLOAD_SIZE 2
int nodePayload[NODE_MAX_NUMBER][PAYLOAD_SIZE];

SSD1306AsciiWire oled;

const int button1 = 2;
const int button2 = 3;
const int button3 = 4;
const int outputPin = 7;
const int button4 = 5;
const int button5 = 6;
const int outputPin1 = 12;

bool output = false;
int frequency = 900;
int step = 20;
int maxmodes = 3;

int Modus = 1;
int Modus1 = 0;
int Modus2 = 0;
int Modus3 = 0;

// ODrive
ODriveUART odrive(Serial);

void setup() {
  lcd1.init();
  lcd2.init();
  lcd1.backlight();
  lcd2.backlight();

  Wire.begin();
  Wire.setClock(400000L);
  oled.begin(&Adafruit128x64, I2C_ADDRESS);

  Serial.begin(115200);

  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  pinMode(outputPin, OUTPUT);
  pinMode(outputPin1, OUTPUT);
  outputoled();
  outputlcd();
}

void loop() {
  int button1state = digitalRead(button1);
  int button2state = digitalRead(button2);
  int button3state = digitalRead(button3);
  int button4state = digitalRead(button4);
  int button5state = digitalRead(button5);

  if (button1state == HIGH) {
    output = !output;
    updatedisplays();
  }

  if (button2state == HIGH) {
    frequency += step;
    updatedisplays();
  }

  if (button3state == HIGH) {
    frequency -= step;
    updatedisplays();
  }

  if (button4state == HIGH) {
    if (Modus + 1 > maxmodes) {
      Modus = 1;
    } else {
      Modus += 1;
    }
    updatedisplays();
  }

  if (button5state == HIGH) {
    if (Modus - 1 <= 0) {
      Modus = maxmodes;
    } else {
      Modus -= 1;
    }
    updatedisplays();
  }

  if (output == 1) {
    if (frequency < 1) { frequency = 1; }
    Modus1 = ((1000 / (frequency / 60)) * 2) / 6;
    Modus2 = (1000 / (frequency / 60)) * 0;
    Modus3 = (1000 / (frequency / 60)) * 2;

    switch (Modus) {
      case 3:
        digitalWrite(outputPin, HIGH);
        delay(Modus3);
        digitalWrite(outputPin, LOW);
        delay(Modus3);
        // Setze die Drehzahl des Motors über ODrive
        setMotorSpeed(frequency / 2); // Drehzahl auf frequency/2 setzen
        break;
      case 2:
        digitalWrite(outputPin, HIGH);
        delay(Modus2);
        digitalWrite(outputPin, LOW);
        delay(Modus2);
        // Setze die Drehzahl des Motors über ODrive
        setMotorSpeed(frequency / 2); // Drehzahl auf frequency/2 setzen
        break;
      case 1:
        digitalWrite(outputPin, HIGH);
        delay(Modus1);
        digitalWrite(outputPin, LOW);
        delay(Modus1);
        // Setze die Drehzahl des Motors über ODrive
        setMotorSpeed(frequency / 2); // Drehzahl auf frequency/2 setzen
        break;
      default:
        digitalWrite(outputPin, LOW);
        // Setze die Drehzahl des Motors über ODrive auf 0
        setMotorSpeed(0);
        break;
    }

    digitalWrite(outputPin1, HIGH);
  } else {
    digitalWrite(outputPin1, LOW);
    // Setze die Drehzahl des Motors über ODrive auf 0
    setMotorSpeed(0);
  }
}

int updatedisplays() {
  outputoled();
  outputlcd();
  delay(100);
}

int outputlcd() {
  lcd2.clear();

  if (output) {
    lcd2.setCursor(0, 0);
    lcd2.print("Modus:");
    switch (Modus) {
      case 1:
        lcd2.setCursor(0, 1);
        lcd2.print("CR");
        break;
      case 2:
        lcd2.setCursor(0, 1);
        lcd2.print("ESP");
        break;
      case 3:
        lcd2.setCursor(0, 1);
        lcd2.print("BENZ");
        break;
      default:
        lcd2.setCursor(0, 1);
        lcd2.print("Modus nicht vorhanden");
    }
  } else {
    lcd2.setCursor(0, 0);
    lcd2.print("HTL1/Bosch ELHA");
    lcd2.setCursor(0, 1);
    lcd2.print("Druecken Sie Start");
  }
}

int outputoled() {
  oled.setLetterSpacing(2);
  oled.clear();

  if (output) {
    oled.setFont(Cooper19);
    oled.println("RPM");
    oled.print(frequency);
    oled.print(" U/MIN");
  } else {
    oled.setFont(Cooper19);
    oled.println("HTL 1");
    oled.println("BOSCH ELHA");
    oled.setFont(TimesNewRoman16);
    oled.println("Druecken Sie Start");
  }
}

void setMotorSpeed(float targetRPM) {
  // Konvertiere die Ziel-Drehzahl von U/min in Schritte pro Sekunde (counts/s)
  float targetVelocity = targetRPM * ODRIVE_COUNTS_PER_REV / 60.0;

  // Setze die Drehzahl des Motors
  odrive.SetVelocity(0, targetVelocity);
}

Hi there!

The Arduino Uno only has a single serial port (used for the Arduino serial console and programming), which means you need to use SoftwareSerial for the additional serial port to talk to the ODrive.

Probably worth checking out the Arduino UART guide here.

Note that SoftwareSerial is a little janky on the best of days - if possible, may be worth switching to an Arduino with more than one serial port - like a Mega, or a Teensy 3/4.

Also - consider joining the Discord if possible - may get faster replies there.

1 Like

Hi!
I tried it now with an Arduino MEGA 2560 R3, but unfortunately, I still can’t establish a connection. In the ODrive settings, I have set:

odrv0.config.uart_a_baudrate, 
odrv0.config.enable_uart_a, 
odrv0.config.gpio12_mode,
odrv0.config.gpio13_mode.

What could be the issue?

My arduino code is:

#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#define I2C_ADDRESS 0x3c

#include <ODriveUART.h>
#include <SoftwareSerial.h>

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd1(0x27, 16, 22);
LiquidCrystal_I2C lcd2(0x3F, 16, 2);

SSD1306AsciiWire oled;



SoftwareSerial odrive_serial(19, 18);
int baudrate = 19200;
ODriveUART odrive(odrive_serial);



const int button1 = 2;
const int button2 = 3;
const int button3 = 4;
const int outputPin = 7;
const int button4 = 5;
const int button5 = 6;
const int outputPin1 = 12;

bool output = false;
int frequency = 900;
int step = 20;
int maxmodes = 3;

int Modus = 1;
int Modus1 = 0;
int Modus2 = 0;
int Modus3 = 0;

void setup() {
  lcd1.init();
  lcd2.init();
  lcd1.backlight();
  lcd2.backlight();

  Wire.begin();
  Wire.setClock(400000L);
  oled.begin(&Adafruit128x64, I2C_ADDRESS);

  Serial.begin(19200);
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(button3, INPUT);
  pinMode(outputPin, OUTPUT);
  pinMode(outputPin1, OUTPUT);
  outputoled();
  outputlcd();

  Serial.begin(19200);
  Wire.begin();


  odrive_serial.begin(baudrate);
  
  Serial.begin(19200); // Serial to PC
  delay(10);

  Serial.println("Waiting for ODrive...");
  //while (odrive.getState() == AXIS_STATE_UNDEFINED) {
  //delay(100);
  //}

  Serial.println("found ODrive");
  Serial.print("DC voltage: ");
  Serial.println(odrive.getParameterAsFloat("vbus_voltage"));
  Serial.println("Enabling closed loop control...");

  while (odrive.getState() != AXIS_STATE_CLOSED_LOOP_CONTROL) {
    odrive.clearErrors();
    odrive.setState(AXIS_STATE_CLOSED_LOOP_CONTROL);
    delay(10);
  }
  Serial.println("ODrive running!");
}

void loop() {
  int button1state = digitalRead(button1);
  int button2state = digitalRead(button2);
  int button3state = digitalRead(button3);
  int button4state = digitalRead(button4);
  int button5state = digitalRead(button5);

  if (button1state == HIGH) {
    output = !output;
    updatedisplays();
  }

  if (button2state == HIGH) {
    frequency += step;
    updatedisplays();
  }

  if (button3state == HIGH) {
    frequency -= step;
    updatedisplays();
  }

  if (button4state == HIGH) {
    if (Modus + 1 > maxmodes) {
      Modus = 1;
    } else {
      Modus += 1;
    }

    updatedisplays();
  }

  if (button5state == HIGH) {
    if (Modus - 1 <= 0) {
      Modus = maxmodes;
    } else {
      Modus -= 1;
    }
    updatedisplays();
  }

  if (output == 1) {
    if (frequency < 1) { frequency = 1; }
    Modus1 = ((1000 / (frequency / 60)) * 2)/6;
    Modus2 = (1000 / (frequency / 60))*0;
    Modus3 = (1000 / (frequency / 60))*2;

    switch (Modus) {
      case 3:
        digitalWrite(outputPin, HIGH);
        delay(Modus3);
        digitalWrite(outputPin, LOW);
        delay(Modus3);
        break;
      case 2:
        digitalWrite(outputPin, HIGH);
        delay(Modus2);
        digitalWrite(outputPin, LOW);
        delay(Modus2);
        break;
      case 1:
        digitalWrite(outputPin, HIGH);
        delay(Modus1);
        digitalWrite(outputPin, LOW);
        delay(Modus1);
        break;
      default:
        digitalWrite(outputPin, LOW);
        break;  // Wird nicht benötigt, wenn Statement(s) vorhanden sind
    }

    digitalWrite(outputPin1, HIGH);
  } else {
    digitalWrite(outputPin1, LOW);
  }
}

int updatedisplays() {
  outputoled();
  outputlcd();
  delay(100);
}

int outputlcd() {
  lcd2.clear();

  if (output) {
    lcd2.setCursor(0, 0);
    lcd2.print("Modus:");
    switch (Modus) {
      case 1:
        lcd2.setCursor(0, 1);
        lcd2.print("CR");
        break;
      case 2:
        lcd2.setCursor(0, 1);
        lcd2.print("ESP");
        break;
      case 3:
        lcd2.setCursor(0, 1);
        lcd2.print("BENZ");
        break;
      default:
        lcd2.setCursor(0, 1);
        lcd2.print("Modus nicht vorhanden");
    }
  } else {
    lcd2.setCursor(0, 0);
    lcd2.print("HTL1/Bosch ELHA");
    lcd2.setCursor(0, 1);
    lcd2.print("Druecken Sie Start");
  }
}

int outputoled() {
  oled.setLetterSpacing(2);
  oled.clear();

  if (output) {
    oled.setFont(Cooper19);
    oled.println("RPM");
    oled.print(frequency);
    oled.print(" U/MIN");
  } else {
    oled.setFont(Cooper19);
    oled.println("HTL 1");
    oled.println("BOSCH ELHA");
    oled.setFont(TimesNewRoman16);
    oled.println("Druecken Sie Start");
  }

  float vel = frequency/60;
  void setVelocity();
  odrive.setVelocity(frequency/60);
}

Hi - for usability can you please surround your code block with ``` symbols?

Such as this

```
code goes here
```

This will make it much more

readable

:wink:

1 Like