3
$\begingroup$

I am writing a code in Arduino IDE for NodeMCU Board to control a differential drive 2 wheeled robot.

I am able to steer only one direction for some reason and the steering response time is a little awkward.

Is there perhaps a better strategy for the code that I am using?`

I am using an app called Blynk that has a virtual joystick that controls that feeds the data through Virtual Pins. V1 param 0 and 1 are x and y. x would be left to right on the joystick and y would be forward and back.

Information about the App is available here: http://www.blynk.cc/. I have it working for the most part, but there is some latency since it is through a cloud service.

The main problem I am stuck on is steering while driving forward and backward.

    //#define BLYNK_DEBUG
//#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>


int motorA ;
int motorB ;
int X=0;
int Y=0;
int Steer=0;
int maximo=0;

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "b41ff7f1659b4badb694be4c59601c2c";

void setup()
{
  // Set console baud rate
  Serial.begin(9600);


 Blynk.begin(auth,"100Grand","Mob4life");

 pinMode(motorA, OUTPUT); 
 pinMode(motorB, OUTPUT);
 pinMode(0,OUTPUT);
 pinMode(2,OUTPUT);
 pinMode(4,OUTPUT);
 pinMode(5,OUTPUT);

}

 BLYNK_WRITE(V1) 
{
  int X1 = param[0].asInt();
  X=X1;
  int Y1 = param[1].asInt();
 Y=Y1;

}

 BLYNK_WRITE(V0)//      slider  de 100 a 255!!!!
{
 int vel = param.asInt(); 
 maximo=vel;
}

void loop()
{

  if(X == 128  &&  Y == 128)  //  Stop
  {
   motorA = 0;
   motorB = 0;
   analogWrite(5, motorA);  
   analogWrite(4, motorA);
   analogWrite(0, motorB);  
   analogWrite(2, motorB);
   } 

   if(Y > 130 && X > 127 && X < 129)   //Forward
  {
    motorA = Y;
    motorB = Y;

    motorA = map(motorA, 450,maximo,130, 255);
    analogWrite(5, motorA);
    digitalWrite(0,LOW);
    motorB = map(motorA, 450,maximo,130, 255);
    analogWrite(4, motorB);
    digitalWrite(2,HIGH);
  }

  else if(Y < 126 && X > 127 && X < 129)   //Reverse
  {
    motorA = Y;
    motorB = Y;

    motorA = map(motorA, 450,maximo,126, 0);
    analogWrite(5, motorA);
    digitalWrite(0,HIGH);
    motorB = map(motorA, 450,maximo,126, 0);//something is wrong with HIGH signal
    analogWrite(4, motorB);
    digitalWrite(2,LOW);
  }

   if(Y > 130 && X < 126)   //Steer Left
  {
    motorA = Y;
    motorB = Y;
    Steer = map(X, 450,maximo, 126,0);
     Steer = X / maximo;

    motorA = map(motorA, 450,maximo,130, 255);
    analogWrite(5, motorA * (1 + Steer));
    digitalWrite(0,LOW);
   motorB = map(motorA, 450,maximo,130, 255);
    analogWrite(4, motorB * (1 - Steer));
    digitalWrite(2,HIGH);
  }

   if(Y > 130 && X > 130)   //Steer Right
  {
    motorA = Y;
    motorB = Y;
    Steer = map(X, 450,maximo, 126,0);
    Steer = X / maximo;

    motorA = map(motorA, 450,maximo,130, 255);
    analogWrite(5, motorA * (1 - Steer));
    digitalWrite(0,LOW);
    motorB = map(motorA, 450,maximo,130, 255);
    analogWrite(4, motorB * (1 + Steer));
    digitalWrite(2,HIGH);
  }

  Blynk.run();
}

Any help would be appreciated. Thanks!`

$\endgroup$
2
  • $\begingroup$ Where do X and Y get updated? What range of values do you expect for X, Y, and maximo? Did you realize you map motorA based on the original motorA (Y), but then you map motorB based on the modified motorA? Can you post a line-by-line explanation of what you think the steering code is doing? $\endgroup$
    – Chuck
    Feb 4, 2016 at 14:50
  • $\begingroup$ Converting joystick input to left/right motor commands is quite common in robotics. There is no standard equation for it though. See this thread: How do I convert joystick values to motor direction $\endgroup$
    – Ben
    Feb 17, 2021 at 15:38

3 Answers 3

1
$\begingroup$

You named a question "Standard equation for steering differential drive robot", so instead of going deep into your code, I'll try to give you a simple example, how can you steer a differential drive robot.

Assumption: joystick steering - two input variables, throttle (forward speed) and steering. It would be easiest if they change from -255 (full revesre/left) to 255 (full ahead/right).

Here is a code that I wrote for motor controller based on DRV8833 drivers:

void runMotor(int channel, int _pwm) {
    // make sure PWM is within boundaries
    constr(_pwm, -255,255);
    if(channel <=4) {
        // spin the motors forward...
        if(_pwm >= 0) {
            //and write the PWM     
            //in1Pin and in2Pin are arrays of pin numbers   
            analogWrite(in1Pin[channel], 255 - _pwm);
            analogWrite(in2Pin[channel], 255);          

        }
        // ...or backward
        else {          
            analogWrite(in1Pin[channel], 255);
            analogWrite(in2Pin[channel], 255 + (_pwm));         
        }
    }

}
void loop() {
    int throttle = getThrottle(); //get new throttle value
    int steering = getSteering(); //get new steering value

    /* here is the essential part:
    * if both values will be 0, the robot will stop
    * if throttle is positive, the robot will go forward, if negative - backward
    * if throttle is 0, but there is some steering, robot will turn in place
    int leftSpeed = throttle + steering; 
    int rightSpeed = throttle - steering; 

    runMotor(1, leftSpeed);
    runMotor(2, rightSpeed);
}

You will need to adjust the code for your drivers, but the essentials are the same: for one motor you add steering to throttle, for the another you subtract. This should give you very nice control over your robot.

$\endgroup$
0
$\begingroup$

What is Y? What is X? What is maximo? What are the digitalWrite commands supposed to be doing? Did you notice they are the same for both turns?

Possible problems:

  1. Your map command is changing motorA and motorB from a range of 126-0 to a range of 450-maximo. (or from 130-255 to 450-maximo).
  2. You set motorA and motorB to Y, and you only call these turns if Y is greater than 130.
  3. Combine #2 with #1 above, and the output of the function looks like it will set motorA and motorB to some value higher than 450. This is problematic because analogWrite only goes from 0-255.
  4. You try to modulate the motorA and motorB values with some +/- Steer, but again not knowing what X, Y, or maximo is it's not clear what Steer is, but that doesn't matter because motorA and motorB are way over the limit for what you should be feeding to analogWrite.

Coul you revise your question to include a brief summary of what you think your code is doing? Please also include how it's called - i.e., what the inputs are (X,Y,maximo, and every other variable that's not defined in the code you explicitly post).

$\endgroup$
1
  • $\begingroup$ Thank you! I have edited the question. I am also looking at your suggestions in my code. $\endgroup$ Feb 4, 2016 at 7:33
0
$\begingroup$

I used ESP8266 with BL HC-10 and L293D motor controller to operate RC car with the differential steering. I used a factor, "f" to adjust (tune) the steering The code is as follows

#include <SoftwareSerial.h>
#include <ArduinoBlue.h>

int prevThrottle = 49;
int prevSteering = 49;
int throttle, steering;

SoftwareSerial bluetooth(13, 15);
ArduinoBlue phone(bluetooth);

void setup()
{
  pinMode(16, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(14, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(0, OUTPUT);

  Serial.begin(9600);

  bluetooth.begin(9600);

  delay(100);

  Serial.println("setup complete");

}
void loop()
{
  throttle = phone.getThrottle();
  steering = phone.getSteering();

  if (prevThrottle != throttle || prevSteering != steering) {
    Serial.print("Throttle: "); Serial.print(throttle); Serial.print("\tSteering: "); Serial.println(steering);
    prevThrottle = throttle;
    prevSteering = steering;
    int f = 25;     // factor for steering response
    
    if (throttle > 49 && steering > 49) {

      digitalWrite(16, HIGH);   // L side wheels
      digitalWrite(4, LOW);
      analogWrite(5, (throttle - 50) * 20);

      digitalWrite(14, HIGH);   // R side wheels
      digitalWrite(12, LOW);
      analogWrite(0, ((throttle - 50) * 20  - (steering - 50)*f));
    }


    if (throttle > 49 && steering < 50) {

      digitalWrite(16, HIGH);
      digitalWrite(4, LOW);
      analogWrite(5, (throttle - 50) * 20 - (49 - steering)* f) ;

      digitalWrite(14, HIGH);
      digitalWrite(12, LOW);
      analogWrite(0, ((throttle - 50) * 20));
    }

    if (throttle < 50 && steering > 49) {

      digitalWrite(16, LOW);
      digitalWrite(4, HIGH);
      analogWrite(5, ((49 - throttle) * 20));

      digitalWrite(14, LOW);
      digitalWrite(12, HIGH);
      analogWrite(0, (49 - throttle) * 20 - (steering - 50)* f);
    }

    if (throttle < 50 && steering < 50) {

      digitalWrite(16, LOW);
      digitalWrite(4, HIGH);
      analogWrite(5, (49 - throttle) * 20 - (49 - steering)* f);

      digitalWrite(14, LOW);
      digitalWrite(12, HIGH);
      analogWrite(0, (49 - throttle) * 20);
    }

  }

}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.