Roboclaw (2x60) always has an extra command execution

General discussion of using Roboclaw motor controllers
Post Reply
bmat
Posts: 7
Joined: Tue Nov 27, 2018 7:10 am
Roboclaw (2x60) always has an extra command execution

Post by bmat »

Setup:
I am using an arduino to talk to two roboclaws (2x60) via packet serial. The arduino has two serial TX ports being connected to each roboclaw (i.e. Serial1 -> RoboClaw1 and Serial2 -> RoboClaw2). The 5V and GND pins from RoboClaw1 is used to power the arduino. A single voltage supply is connected to each roboclaw. When turning on the voltage supply, the roboclaws receive power and they both have their STAT1 light turn green and subsequently the arduino begins receiving power.

The Issue:
After everything is powered, I connect the arduino to a PC via USB. Once connection is established, the roboclaw that is not powering the arduino (in this case Roboclaw2) now has both the STAT1 and STAT2 lights turn green. When I send a command from PC -> Arduino, Roboclaw1 (the one powering the arduino) executes that command twice while Roboclaw2 (the one not powering the arduino) executes the command only once. I checked to make sure that the arduino is not sending duplicate signals to any of the roboclaws and it is indeed not. Any help would be greatly appreciated!

Code: Select all

#include "RoboClaw.h"

#define address_m1 0x80
#define address_m2 0x81

RoboClaw robo_x(&Serial1, 1000);
RoboClaw robo_y(&Serial2, 1000);


void setup() {
  Serial.begin(38400);
  robo_x.begin(38400);
  robo_y.begin(38400);
  
}

void loop() {
    while(Serial.available() > 0) {
    String incoming;
    incoming = Serial.readStringUntil('\n');

    int beginning = incoming.indexOf("z");

    String temp = incoming.substring(beginning+1, incoming.length());
    
    int size = temp.length();
    char* inputarray = new char[size+1];
    strcpy(inputarray, temp.c_str());
    inputarray[size] = '\0';

    int controllerCMDS[8];
    char* outputs = strtok(inputarray, ",");
    int index = 0;
    while (outputs != 0) {
      controllerCMDS[index] = strtol(outputs, NULL, 10);
      outputs = strtok(0, ",");
      index++;
    }

    // Current controllerCMDS array configuration: 
    // index[0] = input for motor 1 of roboclaw_x
    // index[1] = time delay for input 1
    // index[2] = input for motor 2 of roboclaw_x
    // index[3] = time delay for input 2
    // index[4] = input for motor 1 of roboclaw_y
    // index[5] = time delay for input 3
    // and so on..

    
    if (controllerCMDS[0] > 0) {
      robo_x.ForwardM1(address_m1, controllerCMDS[0]);
      delay(controllerCMDS[1]);
      robo_x.ForwardM1(address_m1, 0);
    } else if (controllerCMDS[0] < 0) {
      robo_x.BackwardM1(address_m1, controllerCMDS[0]);
      delay(controllerCMDS[1]);
      robo_x.ForwardM1(address_m1, 0);
    } else {
      robo_x.ForwardM1(address_m1, 0);
      delay(controllerCMDS[1]);
    }
    
    if (controllerCMDS[2] > 0) {
      robo_x.ForwardM2(address_m1, controllerCMDS[2]);
      delay(controllerCMDS[3]);
      robo_x.ForwardM2(address_m1, 0);
    } else if (controllerCMDS[2] < 0) {
      robo_x.BackwardM2(address_m1, controllerCMDS[2]);
      delay(controllerCMDS[3]);
      robo_x.ForwardM2(address_m1, 0);
    } else {
      robo_x.ForwardM2(address_m1, 0);
      delay(controllerCMDS[3]);
    }
    

    if (controllerCMDS[4] > 0) {
      robo_y.ForwardM1(address_m2, controllerCMDS[4]);
      delay(controllerCMDS[5]);
      robo_y.ForwardM1(address_m2, 0);
    } else if (controllerCMDS[4] < 0) {
      robo_y.BackwardM1(address_m2, controllerCMDS[4]);
      delay(controllerCMDS[5]);
      robo_y.ForwardM1(address_m2, 0);
    } else {
      robo_y.ForwardM1(address_m2, 0);
      delay(controllerCMDS[5]);
    }

    if (controllerCMDS[6] > 0) {
      robo_y.ForwardM2(address_m2, controllerCMDS[6]);
      delay(controllerCMDS[7]);
      robo_y.ForwardM2(address_m2, 0);
    } else if (controllerCMDS[6] < 0) {
      robo_y.BackwardM2(address_m2, controllerCMDS[6]);
      delay(controllerCMDS[7]);
      robo_y.ForwardM2(address_m2, 0);
    } else {
      robo_y.ForwardM2(address_m2, 0);
      delay(controllerCMDS[7]);
    }

    
  }
}
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Roboclaw (2x60) always has an extra command execution

Post by Basicmicro Support »

1. Did you actualyl change the address of the second Roboclaw? If you are using 2 seperate serial ports then you can leave the address set to the default on both boards.

2. If the STAT2 LED turns on(but not the ERR LED) then one or both motors are active on that controller. STAT2 lights up when a motor is running(when ERR is not lit).

3. My guess is you have a logic bug in your code that is handling ControllerCMDs. I suggest you run a test that doesnt have any of that code. The test should just send commands to the two controllers to move forward, pause some time, move backward and then stop. I suspect you will find each controller only runs the commands once. Then you will need to debug your code that is handling input to the arduino(eg ControllerCMDS{}).
bmat
Posts: 7
Joined: Tue Nov 27, 2018 7:10 am
Re: Roboclaw (2x60) always has an extra command execution

Post by bmat »

1. Yes, each roboclaw has a unique address. Thank you for the suggestion.

2. Ahh, that makes sense.

3. Thank you. I will look into this.

I appreciate the help!
bmat
Posts: 7
Joined: Tue Nov 27, 2018 7:10 am
Re: Roboclaw (2x60) always has an extra command execution

Post by bmat »

Thank you for your help! There was a logic error. The while() loop should've just been a for loop. Somehow, a pointer found its way into the array that pointed to two values.

Thanks!
User avatar
Basicmicro Support
Posts: 1594
Joined: Thu Feb 26, 2015 9:45 pm
Re: Roboclaw (2x60) always has an extra command execution

Post by Basicmicro Support »

No problem. Let me know if you need anything else.

Post Reply