Which GND for Serial D0/D1 to use ?
Hello,
I have been using the industruino to control an Odrive motor control board with success using Serial1 (D10/D5) and connecting the Odrive GND with the industruino ISO2 GND.
Now I would like to use the second serial (D0/D1) to control a second Odrive board.
First I tried to use the Serial (D0/D1) with one Odrive, by moving the switch away from the RS485, linking the Odrive ground to the ISO2 GND. At this stage I have issues very similar to the ones I had before, due to grounding problems (starts to communicate but then stops).
I then tried connecting the Odrive GND to the RS485 GND instead of the ISO2 but there was no communication at all.
I think I am doing something wrong with the GND when I want to use D0/D1 (instead of D10/D5), which ground shall I connect to the Odrive board GND ?
Thanks in advance for your help,
Best regards,
Pak
Hello Tom,
Thanks for the precisions on the grounds. I have made more tests :
- When I use D0/D1 there is communication in the end but with a large delay (1min 37s) in the response.
In the code below, when I launch the motor calibration (line 53) it does the calibration but then it takes 1min37s before getting to AXIS_STATE_CLOSED_LOOP_CONTROL (line 57) .
When I use Serial1, it goes into closed loop control state directly after calibration.
Code:
//#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
//SoftwareSerial odrive_serial(8, 9); //RX (ODrive TX), TX (ODrive RX)
// ODrive object
#define odrive_serial Serial
ODriveArduino odrive(odrive_serial);
void setup() {
// ODrive uses 115200 baud
odrive_serial.begin(115200);
// Serial to PC
SerialUSB.begin(115200);
while (!SerialUSB) ; // wait for Arduino Serial Monitor to open
SerialUSB.println("ODriveArduino");
SerialUSB.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 " << 40000.0f << '\n';
odrive_serial << "w axis" << axis << ".motor.config.current_lim " << 10.0f << '\n';
// This ends up writing something like "w axis0.motor.config.current_lim 10.0\n"
}
SerialUSB.println("Ready!");
SerialUSB.println("Send the character '0' or '1' to calibrate respective motor (you must do this before you can command movement)");
SerialUSB.println("Send the character 's' to exectue test move");
SerialUSB.println("Send the character 'b' to read bus voltage");
SerialUSB.println("Send the character 'p' to read motor positions in a 10s loop");
}
void loop() {
if (SerialUSB.available()) {
char c = SerialUSB.read();
// Run calibration sequence
if (c == '0' || c == '1') {
int motornum = c-'0';
int requested_state;
requested_state = ODriveArduino::AXIS_STATE_FULL_CALIBRATION_SEQUENCE;
SerialUSB << "Axis" << c << ": Requesting state " << requested_state << '\n';
odrive.run_state(motornum, requested_state, true);
requested_state = ODriveArduino::AXIS_STATE_CLOSED_LOOP_CONTROL;
SerialUSB << "Axis" << c << ": Requesting state " << requested_state << '\n';
odrive.run_state(motornum, requested_state, false); // don't wait
}
// Sinusoidal test move
if (c == 's') {
SerialUSB.println("Executing test move");
float pos_m0 = 2000.0f;
float pos_m1 = -2000.0f;
float pos_m2 = 0.0f;
odrive.SetPosition(0, pos_m0);
delay(1000);
odrive.SetPosition(0, pos_m1);
delay(1000);
odrive.SetPosition(0, pos_m2);
delay(1000);
}
// Read bus voltage
if (c == 'b') {
odrive_serial << "r vbus_voltage\n";
SerialUSB << "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";
SerialUSB << odrive.readFloat() << '\t';
}
SerialUSB << '\n';
}
}
}
}
If you need, some librairies are available here (https://github.com/madcowswe/ODrive/tree/master/Arduino/ODriveArduino) for the Odrive.
Thanks for the help,
Best Regards,
Pak
Hi Tom, Yes D10/D5 Serial1 works well, I get the feedback of the run_state command as soon as the calibration sequence is finished and then it switches into AXIS_STATE_CLOSED_LOOP_CONTROL without any delay. You are correct, there is a timeout after 100seconds, when I reduce it I can see the effect. I confirm the INDIO is powered with 24V, using the 14-pin IDC and RS485 switch (only switch on the board right?) is away from RS485. I tried to swap D0/D1 and I cannot launch the calibration sequence so the previous cabling was correct. If I wait for the timeout to happen (100s or I can also reduce it in the library), I can actually launch the SetPosition or SetVelocity commands and it works fine. It seems I can give orders to the Odrive but not receive feedback, which affects only the feedback after calibration.
hi, i have tested with a simple serial echo sketch and i observe no difference between Serial and Serial1 when the hardware switch is correctly positioned. please send an email to connect@industruino.com so we can send you some details.
Hi, yes indeed the 2 hardware serials (D10/D5 and D0/D1) share the same GND (ISO2 GND on the pinout map) so i'm not sure your problem is with GND.
The INDIO baseboard has 3 isolated zones: digital, analog, and MCU; you want to stay in the MCU zone so don't use the other GNDs.
Make sure you are using the correct names of the serials:
- SerialUSB for USB (Serial Monitor)
- Serial for hardware serial on D0/D1
- Serial1 for hardware serial on D10/D5
If still no luck, can you post a simple piece of code so we can investigate.
Your answer
Please try to give a substantial answer. If you wanted to comment on the question or answer, just use the commenting tool. Please remember that you can always revise your answers - no need to answer the same question twice. Also, please don't forget to vote - it really helps to select the best questions and answers!
Keep Informed
About This Forum
This community is for professionals and enthusiasts of our products and services.
Read GuidelinesQuestion tools
Stats
Asked: 3/15/19, 1:29 PM |
Seen: 3169 times |
Last updated: 3/17/19, 2:33 PM |
Hi, can you confirm that everything works with D10/D5 Serial1, the 2-way communication works? That first run_state command has a timeout function with a counter to 100, and you get a timeout after about 100 seconds, so it seems the RX is not working (serial read timeout), so no data received. Can you confirm that you are powering the INDIO with 24V, and using the 14-pin IDC connector for the pins, and your RS485 switch on the baseboard is set away from the RS485 screw connectors on the bottom. Are you sure the RX/TX is wired correctly; can you see that any TX data is going to the odrive? if not sure please check you have D0 and D1 connected correctly (just swap them to see what happens).