RC car Steering Code for

Hello again everyone. My code is working for clockwise and counterclockwise, for forwards and backwards. I'm trying to repeat this to turn left and right. I'm trying to keep the speed to turn left and right moderate, so it won't be too fast. I'm not great at coding C++, but I thought I could use similar techniques for the Arduino. I thought I could use analogWrite, and constant for this command. However, the error code keep saying "not declared", and I can't define them. Could someone please help me out with this?

#define mAl 5  // PWM motor pin IN2 motor A                 

#define mAr 6  // PWM motor pin IN1 motor A

#define TsA 3  // button for clockwise motor A

#define BsA 2  // button for counter clockwise motor A

#define mBl 11 // PWM motor pin IN2 motor B

#define mBr 10 //PWM motor pin IN1 motor B

#define LsB 4  // button for clockwise motor B

#define RsB 7  // button for counter clockwise motor B

#define const int pwm 10,11

#define analogWrite 



void setup() {

  Serial.begin(9600);

  pinMode(pwm, OUTPUT); //we have to set pwm pin as output

  pinMode(mAl, OUTPUT);

  pinMode(mAr, OUTPUT);

  pinMode(TsA, INPUT);

  pinMode(BsA, INPUT);

  pinMode(mBl, OUTPUT);

  pinMode(mBr, OUTPUT);

  pinMode(LsB, INPUT);

  pinMode(RsB, INPUT);

  

}

void loop() {


 int Pot = analogRead(A0);

 Pot = map(Pot, 0, 1023, 0, 255);

 Serial.println(Pot);

 int top = digitalRead(TsA);

 int bottom = digitalRead(BsA);

 int left = digitalRead(LsB);

 int right = digitalRead(RsB);

 if(top == LOW && bottom == HIGH)

 {

  analogWrite(mAl, Pot);

  digitalWrite(mAr,LOW);

  

 }

 else if(top == HIGH && bottom == LOW)

 {

  digitalWrite(mAl, LOW);

  analogWrite(mAr, Pot);

 }

 else{

  digitalWrite(mAl, HIGH);

  digitalWrite(mAr,HIGH);

 }

  //For Clock wise motion for motor B, mBl = High , mBr = Low

 if (left == LOW && right == HIGH)

 {

 digitalWrite(mBl, HIGH);

 digitalWrite(mBr, LOW);

 analogWrite(pwm, 60);

 /* setting pwm of the motor to 60 we can change the speed of rotation 

 by changing pwm input but we are only using arduino so we are using highest

 value to drive the motor*/

 }

 else if(left == HIGH && right == LOW)

 {

  //For Anti Clock-wise motion - mBl = LOW , mBr = HIGH

 digitalWrite(mBl,LOW) ;

 digitalWrite(mBr,HIGH) ;

 analogWrite(pwm, 60);

 //For brake

 digitalWrite(in_1,HIGH) ;

 digitalWrite(in_2,HIGH) ; 

 }

 

 //For brake

 digitalWrite(mBl,HIGH) ;

 digitalWrite(mBr,HIGH) ;

 

}

What is that please?
What is the intent?

If you get error messages, please post those too.

No, we don't - analogWrite does it for us.

the above certainly don't make sense. they redefine "const" as "int pwm10,11" and define "analogWrite" as nothing. also, "pwm", "in1", and "in2" are not defined, hence code doesn't compile

but to support turns, why not drive the inside wheel slower

maybe have just 2 buttons to control direction and one to toggle forward/reverse

Here is your code edited to work:

#define mAl 5  // PWM motor pin IN2 motor A                 
#define mAr 6  // PWM motor pin IN1 motor A
#define TsA 3  // button for clockwise motor A
#define BsA 2  // button for counter clockwise motor A
#define mBl 11 // PWM motor pin IN2 motor B
#define mBr 10 // PWM motor pin IN1 motor B
#define LsB 4  // button for clockwise motor B
#define RsB 7  // button for counter clockwise motor B

void setup()
{
  Serial.begin(9600);

  pinMode(mAl, OUTPUT);
  pinMode(mAr, OUTPUT);
  pinMode(TsA, INPUT);
  pinMode(BsA, INPUT);
  pinMode(mBl, OUTPUT);
  pinMode(mBr, OUTPUT);
  pinMode(LsB, INPUT);
  pinMode(RsB, INPUT);
}

void loop()
{
  int Pot = analogRead(A0) / 4;
  Serial.println(Pot);

  int top = digitalRead(TsA);
  int bottom = digitalRead(BsA);
  int left = digitalRead(LsB);
  int right = digitalRead(RsB);

  // Motor A:
  if (top == LOW && bottom == HIGH)
  {
    analogWrite(mAl, Pot);
    digitalWrite(mAr, LOW);
  }
  else if (top == HIGH && bottom == LOW)
  {
    digitalWrite(mAl, LOW);
    analogWrite(mAr, Pot);
  }
  else
  {
    // Brake
    digitalWrite(mAl, HIGH);
    digitalWrite(mAr, HIGH);
  }

  // Motor B
  if (left == LOW && right == HIGH)
  {
    //For Clockwise motion
    analogWrite(mBl, Pot);
    digitalWrite(mBr, LOW);
  }
  else if (left == HIGH && right == LOW)
  {
    //For Anti-Clockwise motion
    digitalWrite(mBl, LOW) ;
    analogWrite(mBr, Pot);
  }
  else
  {
    //For brake
    digitalWrite(mBl, HIGH) ;
    digitalWrite(mBr, HIGH) ;
  }

}
1 Like

I know, I was just reading off of an Arduino website, and was trying to tweak it.

Well, I'm using 4 buttons sir. I was trying to save money by not using a joystick. I was also aiming to duplicate a gamepad look, like Nintendo :grin:. I've seen videos with it.

Exactly, I was trying to to slow the speed of turning down without a potentiometer.

Thanks a bunch as always sir for your help :grin:. I was trying to adjust the speed without a potentiometer though. This way, the speed will be constant. Sorry, I should've clarified that :grin:. It seems when I turn up the speed, the turns would be too hard. I figured I could always go into the code, and find the best speed to compliment turns, when the speed goes up?

[quote="anon43666536, post:2, topic:1019764"]

What is that please?
What is the intent?

I know, it's gibberish. I just put it there, because I want the turn speed to be at a constant rate.

If you get error messages, please post those too.

Gotcha, sorry about that. I meant to copy paste that as well. My computer was freezing up as I reached out to you all, and it was late.

Right, but I thought the motor A analog write would mess this up, so I was thinking now, do I have to do an analog write for motor B? Thank you so much for reaching out sir :grin:.

typical motor shields (L298N) have 3 inputs for each motor. IN1 and IN2 are used to control direction and EN the speed.

IN1 and IN2 are either High/Low for one direction or Low/High for the other. of course, High/Low/Low

consider

#define MaI1 6  // IN1 motor A
#define MaI2 12 // IN2 motor A
#define MaEn 10 // PWM motor A

#define MbI1 7  // IN1 motor B
#define MbI2 13 // IN2 motor B
#define MbEn 11 // PWM motor B

const byte pinsOut [] = { MaI1, MaI2, MbI1, MbI2 };

const byte pinsBut [] = { A1, A2, A3 };
#define N_BUT   sizeof(pinsBut)
byte butState [N_BUT];

byte dir;

// -----------------------------------------------------------------------------
void
direction (
    int   forward )
{
    digitalWrite (MaI1,   forward);
    digitalWrite (MaI2, ! forward);

    digitalWrite (MbI1,   forward);
    digitalWrite (MbI2, ! forward);
}

// -----------------------------------------------------------------------------
void loop ()
{
    int pot = analogRead (A0);
    int spd = map (pot, 0, 1023, 0, 255);

    Serial.println (spd);

    if (LOW == digitalRead (pinsBut [0]) && LOW == digitalRead (pinsBut [1])) {
        analogWrite (MaEn, spd);
        analogWrite (MbEn, spd);
    }
    else if (LOW == digitalRead (pinsBut [0]))  {   // left
        analogWrite (MaEn, 230);    // spd/2);
        analogWrite (MbEn, spd);
    }
    else if (LOW == digitalRead (pinsBut [1]))  {   // right
        analogWrite (MaEn, 230);    // spd);
        analogWrite (MbEn, spd/2);
    }
    else {                                          // no throttle, release brk
        direction (dir);
        analogWrite (MaEn, 0);
        analogWrite (MbEn, 0);
    }

    byte but = digitalRead (pinsBut [2]);
    if (butState [2] != but)  {
        butState [2] = but;

        if (LOW == but)
            dir = !dir;
    }
}


// -----------------------------------------------------------------------------
void setup () {
    Serial.begin (9600);

    for (unsigned n = 0; n < sizeof (pinsOut); n++)  {
        digitalWrite (pinsOut [n], LOW);
        pinMode (pinsOut [n], OUTPUT);
    }
    
    for (unsigned n = 0; n < sizeof (pinsBut); n++)
        pinMode (pinsBut [n], INPUT_PULLUP);
}

Right, that's my problem sir :smile:. Believe it or not, I'm using Adafruit's DRV8871. I've been reading articles dealing with these drivers, so I was trying to tweak it with this single terminal driver :grin:. I'm eyeing some L298N models, makes sense to have one of these, instead of two single boards. I really, really appreciate you alls help. Any book recommendations for coding on Arduino. I have one from, I think the name of the author is Jeffrey Blum.

have you looked at the drv8871 datasheet?

i can now see why you're driving one of the inputs digitally and the other as a PWM. but when in reverse, shouldn't the PWM timing be reversed (255-n)?

the code i posted needs modification to use with this part

Oh, then:

const byte mAl = 5;  // PWM motor pin IN2 motor A                 
const byte mAr = 6;  // PWM motor pin IN1 motor A
const byte TsA = 3;  // button for clockwise motor A
const byte BsA = 2;  // button for counter clockwise motor A
const byte mBl = 11; // PWM motor pin IN2 motor B
const byte mBr = 10; // PWM motor pin IN1 motor B
const byte LsB = 4;  // button for clockwise motor B
const byte RsB = 7;  // button for counter clockwise motor B

const byte PotPin = A0;
const byte MotorBSpeed = 60;

void setup()
{
  Serial.begin(9600);

  pinMode(mAl, OUTPUT);
  pinMode(mAr, OUTPUT);
  pinMode(TsA, INPUT);
  pinMode(BsA, INPUT);
  pinMode(mBl, OUTPUT);
  pinMode(mBr, OUTPUT);
  pinMode(LsB, INPUT);
  pinMode(RsB, INPUT);
}

void loop()
{
  int motorASpeed = analogRead(PotPin) / 4; // Speed from 0 to 255

  Serial.println(motorASpeed);

  int top = digitalRead(TsA);
  int bottom = digitalRead(BsA);
  int left = digitalRead(LsB);
  int right = digitalRead(RsB);

  // Motor A:
  if (top == LOW && bottom == HIGH)
  {
    analogWrite(mAl, motorASpeed);
    digitalWrite(mAr, LOW);
  }
  else if (top == HIGH && bottom == LOW)
  {
    digitalWrite(mAl, LOW);
    analogWrite(mAr, motorASpeed);
  }
  else
  {
    // Brake
    digitalWrite(mAl, HIGH);
    digitalWrite(mAr, HIGH);
  }

  // Motor B
  if (left == LOW && right == HIGH)
  {
    //For Clockwise motion
    analogWrite(mBl, MotorBSpeed);
    digitalWrite(mBr, LOW);
  }
  else if (left == HIGH && right == LOW)
  {
    //For Anti-Clockwise motion
    digitalWrite(mBl, LOW) ;
    analogWrite(mBr, MotorBSpeed);
  }
  else
  {
    //For brake
    digitalWrite(mBl, HIGH) ;
    digitalWrite(mBr, HIGH) ;
  }

}

modified for DRV8871

i think using a pair of buttons to control speed and turning is easier than needing to move finger between 3 buttons

#define MaIn1 12 // IN1 motor A
#define MaPwm 10 // PWM motor A

#define MbIn1 13 // IN1 motor B
#define MbPwm 11 // PWM motor B

const byte pinsBut [] = { A1, A2, A3 };
#define N_BUT   sizeof(pinsBut)
byte butState [N_BUT];

byte dirForward = true;

// -----------------------------------------------------------------------------
void
motor (
    int   pinIn1,
    int   pinPwm,
    int   spd )
{
    if (dirForward) {
        digitalWrite (pinIn1, LOW);
        analogWrite  (pinPwm, spd);
    }
    else  {
        digitalWrite (pinIn1, HIGH);
        analogWrite  (pinPwm, 256 + spd);   // PWM active LOW
    }
}

// -----------------------------------------------------------------------------
void
brake (void)
{
    digitalWrite (MaIn1, HIGH);
    digitalWrite (MaPwm, HIGH);

    digitalWrite (MbIn1, HIGH);
    digitalWrite (MbPwm, HIGH);
}

// -----------------------------------------------------------------------------
void loop ()
{
    int pot = analogRead (A0);
    int spd = map (pot, 0, 1023, 0, 255);

    Serial.println (spd);

    if (LOW == digitalRead (pinsBut [0]) && LOW == digitalRead (pinsBut [1])) {
        motor (MaIn1, MaPwm, spd);
        motor (MbIn1, MbPwm, spd);
    }
    else if (LOW == digitalRead (pinsBut [0]))  {   // left
        motor (MaIn1, MaPwm, spd/2);
        motor (MbIn1, MbPwm, spd);
    }
    else if (LOW == digitalRead (pinsBut [1]))  {   // right
        motor (MaIn1, MaPwm, spd);
        motor (MbIn1, MbPwm, spd/2);
    }
    else
        brake ();

    byte but = digitalRead (pinsBut [2]);
    if (butState [2] != but)  {
        butState [2] = but;

        if (LOW == but)
            dirForward = ! dirForward;
    }
}


// -----------------------------------------------------------------------------
void setup () {
    Serial.begin (9600);

    pinMode (MaIn1, OUTPUT);
    pinMode (MbIn1, OUTPUT);
    
    for (unsigned n = 0; n < sizeof (pinsBut); n++)
        pinMode (pinsBut [n], INPUT_PULLUP);
}

Are you sure you want to reverse the PWM sense? I haven't come across such an idea, so I ask if you are speaking from experience or knowledge of this.

I'll look at the data sheet, yes.

L8R: OK, did. I think section 7.3.1 Bridge Control makes it clear enough that the PWM signal when an input is used as such does not change sense with direction.

Also if the sense were to reverse, since analogWrite() input ranges from 0..255, you probably meant

  analogWrite  (pinPwm, 255 - spd);   // PWM active LOW

if that does indeed turn out to be necessary.

a7

correct.
wrote it this way because i originally thought spd might be negative

so if to go forward, and IN1 is LOW and IN2 HIGH, then driving IN2 with PWM makes sense.

but if in reverse, IN1 needs to be HIGH and IN2 LOW, i had thought the PWM signal IN2 should be inverted. but isn't brake when both IN1 and IN2 are HIGH? if so, how to you use a PWM signal with this chip?

Haha, going blind with the data sheet:

When using PWM, it typically works best to switch between driving and braking. For example, to drive a motor forward with 50% of its max RPM, IN1 = 1 and IN2 = 0 during the driving period, and IN1 = 1 and IN2 = 1 during the other period. Alternatively, the coast mode (IN1 = 0, IN2 = 0) for fast current decay is also available. The input pins can be powered before VM is applied.

So… if you follow the recommendation, an inverted PWM signal is used.

One direction

 IN1 HIGH
 IN2 inverted PWM (LOW driving, HIGH not driving)

and swap the rolls of IN1 and IN2 for the other. Direction.

Note the PWM signal is always invert.

Gonna have to add a dose of I think here, summer time ya know.

More: I find many places use IN1 for direction, and then the PWM does need to change sense depending.

But this also means that in one case you are using the recommended HIGH/HIGH braking mode during the off period, and in the other direction using the other off method LOW/LOW coasting mode.

Which seems like you wouldn't want to do. One mode (braking) or the other (coasting) should be chosen, on what basis I have no idea, and used for both.

And another shot of I think.

a7

could always drive the "HIGH" IN pin with a PWM signal

Man, thank y'all so much. Y'all are some code wizards :grin:. I'm about to try some of these out now. I just woke up from a nap, from staying up until 4 am on this coding :grin:.

I've looked at the schematics, but not sure if I saw the actual data sheet. Yeah, that mapping part is confusing to me. Do you care to explain that to me please :grin:? Is it saying the rpm increases from 0 - 1,023? It only maxes out at 255 though.

This seems to complement my code well. I was just going to keep my potentiometer part, to increase and decrease the speed, for forwards and backwards. I wanted to use the constant character to ease the speed of turning :grin:.

analog Read returns a 10 bit value (0-1023). analogWrite takes an 8 bit value.

you'll have to determine what the PWM to rpm mapping is.

OK I am with myself on the idea that most DRV8871 code has been uncritically copied from someone who got it to work w/o reading the data sheet. Or with reason to do something asymmetrical. Or not caring.

This, seen everywhere, runs one way between driving and braking, and the other way between driving and coasting.

    if (forward) {
        digitalWrite(IN1, LOW);
        analogWrite(IN2, speed);
    }
    else  {
        digitalWrite(IN1, HIGH);
        analogWrite(IN2, 255 - speed);
    }

The data sheet is clear, even if I do not understand why:

When using PWM, it typically works best to switch between driving and braking.

So it should be

    if (forward) {
        digitalWrite(IN1, HIGH);
        analogWrite(IN2, 255 - speed);
    }
    else  {
        analogWrite(IN1, 255 - speed);
        digitalWrite(IN2, HIGH);
    }

if you follow the recommendation of the data sheet and use braking during the off phase of the PWM.

Or

    if (forward) {
        digitalWrite(IN1, LOW);
        analogWrite(IN2, speed);
    }
    else  {
        analogWrite(IN1, speed);
        digitalWrite(IN2, LOW);
    }

if you like coasting.

This means that the DRV8871 should have PWM capable outputs driving both its inputs.

Now only the mystery of the counterintuitive prefernce of the manufacturer for braking.

a7