Code support for Dc motor and Servo reacting to IR Sensor feedback

Apologies in advance if this question has been answered, I could not find it on this forum (or anywhere else, for that matter).

I'm trying to develop my coding skills by weaving together two tasks together and have exhausted my ideas on solving this.

What I am working on:
A four wheeled rover with a DC motor driving two wheels, a servo turning the other set of wheels and an IR
Sensor that provides feedback on how to behave.

What I want the rover to do:

Move forward until the IR Sensor detects an obstacle.
Move backward and turn the wheels to reorient the rover.
Move forward again.

So far, I have been successful at either turning the wheels left and right or rolling forward and backward as separate sketches.
My code is missing the component that weaves these two activities together.

Here is my code so far:

#include <Servo.h>

const int EN=9;  //Half bridge 1 enable
const int MC1=3;  //MOtor control 1 on pin 3
const int MC2=2;  //MOtor control 2 on pin 2
const int IR=0;  //IR on analog pin 0
const int SERVO=10; //Half bridge 3,4 enable


Servo myServo;  //Servo object
int dist1 = 0;  //forward
int dist2 = 0;  //reverse
int dist3 = 0;  //brake

int val = 0;   //for storing the reading from the pot
int velocity = 0;  //For storing the desired velocity (from 0-255)

void setup()
{
  Serial.begin(9600);
  myServo.attach(SERVO);
  
  pinMode(EN, OUTPUT);
  pinMode(MC1, OUTPUT);
  pinMode(MC2, OUTPUT);
  
  brake();  //Initialize with motor stopped
}

void loop()
{
  Serial.println(val);
  val = analogRead(IR);    //read IR
  val = map(val, 0, 1023, 0, 179);  //scale it to servo range
  myServo.write(val);    //sets the servo
  //delay(15);           //waits for the servo

  dist1 = readDistance(0);  //measure IR distance at zero degrees
    analogWrite(SERVO, dist1);
    delay(300);             //delay before next measurement

  dist2 = readDistance(25);  //measure IR distance at zero degrees
    analogWrite(SERVO, dist2);
    delay(300);

  dist3 = readDistance(0);
    analogWrite(SERVO, dist1);
    delay(300);              //delay before next measurement    
 

  //go forward
  if (val > 108)
  {
    velocity = map(val, 108, 1023, 0, 255);
    forward(velocity);
    digitalWrite(MC2, 140);
    
    //dist1 = readDistance(0);  //measure IR distance at zero degrees
    //analogWrite(SERVO, dist1);
    //delay(30);             //delay before next measurement
  }

  //go backward
  else if (val < 107)
  {
    velocity = map(val, 107, 1023, 0, 255);
    reverse(velocity);
    digitalWrite(MC1, 190);
    dist2 = readDistance(15);  //measure IR distance at zero degrees
    
    //analogWrite(SERVO, dist2);
    //delay(30);
  }

  //brake
  else
  {
    brake();
    dist3 = readDistance(0);
    analogWrite(SERVO, dist1);
    delay(30);              //delay before next measurement
  }

 
}


//Motor goes forward at given rate (from 0-255)

void forward (int rate)
{
  digitalWrite(EN, HIGH);
  digitalWrite(MC1, HIGH);
  digitalWrite(MC2, LOW);
  analogWrite(EN, rate); 
}



//Motor goes backward at given rate (from 0-255)
void reverse (int rate)

{
  digitalWrite(EN, HIGH);
  digitalWrite(MC1, LOW);
  digitalWrite(MC2, HIGH);
  analogWrite(EN, rate);
  
}



//stops motor
void brake()
{
  digitalWrite(EN, LOW);
  digitalWrite(MC1, LOW);
  digitalWrite(MC2, LOW);
  digitalWrite(EN, LOW); 
}

int readDistance(int pos)
{
  
  int dist = analogRead(IR);  //read ir sensor
                 
}

Attached are the circuits. IR replaces the trim pot.
Any advise is appreciated. Thank you.

Well it doesn't compile because you have an extra }. Also readDistance() takes a parameter which is never used and is declared as an int but doesn't return anything. That's not going to help.

There may be other problems but why not at least get it compiling first then test it and let us know what it does and doesn't do.

Steve

Thanks Slipsstick, I'll look into that.

slipstick:
Well it doesn't compile because you have an extra }. Also readDistance() takes a parameter which is never used and is declared as an int but doesn't return anything. That's not going to help.

There may be other problems but why not at least get it compiling first then test it and let us know what it does and doesn't do.

Steve

I'm not seeing an extra } (was it in the void loop() area?)

It compiles, but only the direction guiding servo works. The forward and backward servo does not.
This puts me back to square one. I can fanangle the code to perform one function and ignore the other function.

I think I am crossing the variables declared either in the void setup() or void loop() sections. Somehow, the servo and motor need to use the same IR sensor data but perform their separate tasks.

If it were pseudo code, the logic I am after would be:

move forward //until encountering an object at 88>=i<=102
brake
move backward while turning direction for 5 seconds then straighten wheels
brake
repeat

For what it's worth, here is my script as of right now.

I think I set the IR sensor twice, and it should only be set once.
Could this be the issue?

#include <Servo.h>

const int EN=9;  //Half bridge 1 enable
const int MC1=3;  //MOtor control 1 on pin 3
const int MC2=2;  //MOtor control 2 on pin 2
const int IR=0;  //IR on analog pin 0
const int SERVO=10; //Half bridge 3,4 enable


Servo myServo;  //Servo object
int dist1 = 0;  //forward
int dist2 = 0;  //reverse
int dist3 = 0;  //brake

int val = 0;   //for storing the reading from the pot
int velocity = 0;  //For storing the desired velocity (from 0-255)

void setup()
{
  Serial.begin(9600);
  myServo.attach(SERVO);
  
  pinMode(EN, OUTPUT);
  pinMode(MC1, OUTPUT);
  pinMode(MC2, OUTPUT);
  
  brake();  //Initialize with motor stopped
}

void loop()
{
  Serial.println(val);
  val = analogRead(IR);    //read IR
  val = map(val, 0, 1023, 0, 179);  //scale it to servo range
  myServo.write(val);    //sets the servo
  //delay(15);           //waits for the servo

  
    analogWrite(SERVO, dist1);
    delay(300);             //delay before next measurement

  dist2 = readDistance(25);  //measure IR distance at zero degrees
    analogWrite(SERVO, dist2);
    delay(300);

  dist3 = readDistance(0);
    analogWrite(SERVO, dist1);
    delay(300);              //delay before next measurement    


  //go forward
  if (val > 108)
  {
    velocity = map(val, 108, 1023, 0, 255);
    forward(velocity);
    digitalWrite(MC2, 140);
    
    //dist1 = readDistance(0);  //measure IR distance at zero degrees
    //analogWrite(SERVO, dist1);
    //delay(30);             //delay before next measurement
  }

  //go backward
  else if (val < 107)
  {
    velocity = map(val, 107, 1023, 0, 255);
    reverse(velocity);
    digitalWrite(MC1, 190);
    dist2 = readDistance(15);  //measure IR distance at zero degrees
    
    //analogWrite(SERVO, dist2);
    //delay(30);
  }

  //brake
  else
  {
    brake();
    dist3 = readDistance(0);
    analogWrite(SERVO, dist1);
    delay(30);              //delay before next measurement
  }
}

//Motor goes forward at given rate (from 0-255)

void forward (int rate)
{
  digitalWrite(EN, HIGH);
  digitalWrite(MC1, HIGH);
  digitalWrite(MC2, LOW);
  analogWrite(EN, rate); 
}

//Motor goes backward at given rate (from 0-255)
void reverse (int rate)

{
  digitalWrite(EN, HIGH);
  digitalWrite(MC1, LOW);
  digitalWrite(MC2, HIGH);
  analogWrite(EN, rate);
  
}



//stops motor
void brake()
{
  digitalWrite(EN, LOW);
  digitalWrite(MC1, LOW);
  digitalWrite(MC2, LOW);
  digitalWrite(EN, LOW); 
}

int readDistance(int pos)
{
  
  int dist = analogRead(IR);  //read ir sensor
                 
}

It would help if the comments made a bit more sense e.g." const int SERVO=10; //Half bridge 3,4 enable" but just on a quick look:

Your function readDistance still doesn't return anything. Try putting "return dist;" in it.

In functions forward() and reverse() you're setting EN (Enable?) HIGH/LOW but then later sending PWM to the same pin with an analogwrite(). What motor driver/shield are you using that works like that?

And why are you using write() from the Servo library just once but ever after confusing things by doing loads of analogwrite() i.e. PWM commands to the same pin ? If it's a servo on the SERVO pin then PWM doesn't work. PWM is for motors.

Also look at your use of val. You map it into 0-180 and then later on treat it as though it still has a value from 108-1023.

And you have one place where you do a readDistance which should set dist3 and then you do an analogwrite() of dist1.

Your best bet is probably to put a lot more serial.prints in to find out exactly what is and isn't being set as you are expecting.

It might also help to know exactly what motor and motor driver/shield and servo you are using and how you have them wired. A circuit diagram would be good.

Steve

Thanks for taking the time, Steve.
I'm pulling all of the code out of Exploring Arduino by Jeremy Blum.
So far, I have been able to weave different lessons into one piece of code, but my chops are really weak and this combo has slowed me down.

the two circuits that I merged are these (the trim pot is replaced with an IR sensor).
I'm not using a shield. I didn't think it was necessary. If I am wrong about this, how? I would like to learn from this.

The two circuits are below.

The code comes directly from these two projects:

/*
Exploring Arduino - Code Listing 4-4: Servo Potentiometer Control
http://www.exploringarduino.com/content/ch4

Copyright 2013 Jeremy Blum ( http://www.jeremyblum.com )
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License v3 as published by
the Free Software Foundation.
*/

//Servo Potentiometer Control

#include <Servo.h>

const int SERVO=9; //Servo on Pin 9
const int POT=0;    //POT on Analog Pin 0

Servo myServo;
int val = 0;     //for storing the reading from the POT

void setup()
{
    myServo.attach(SERVO);
}

void loop()
{
    val = analogRead(POT);           //Read Pot
    val = map(val, 0, 1023, 0, 179); //scale it to servo range 
    myServo.write(val);              // sets the servo 
    delay(15);                       // waits for the servo
}
/*
Exploring Arduino - Code Listing 4-3: H-Bridge Potentiometer Speed Control
http://www.exploringarduino.com/content/ch4

Copyright 2013 Jeremy Blum ( http://www.jeremyblum.com )
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License v3 as published by
the Free Software Foundation.
*/

//Hbridge Motor Control
const int EN=9;   //Half Bridge 1 Enable
const int MC1=3;  //Motor Control 1
const int MC2=2;  //Motor Control 2
const int POT=0;  //POT on Analog Pin 0

int val = 0;      //for storing the reading from the POT
int velocity = 0; //For storing the desired velocity (from 0-255)

void setup()
{
    pinMode(EN, OUTPUT);
    pinMode(MC1, OUTPUT);
    pinMode(MC2, OUTPUT);
    brake(); //Initialize with motor stopped
}

void loop()
{
    val = analogRead(POT);
 
    //go forward
    if (val > 562)
    {
        velocity = map(val, 563, 1023, 0, 255);
        forward(velocity);
    }
 
    //go backward
    else if (val < 462)
    {
        velocity = map(val, 461, 0, 0, 255);
        reverse(velocity);
    }
 
    //brake
    else
    {
        brake();
    }
}

//Motor goes forward at given rate (from 0-255)
void forward (int rate)
{
    digitalWrite(EN, LOW);
    digitalWrite(MC1, HIGH);
    digitalWrite(MC2, LOW);
    analogWrite(EN, rate);
}

//Motor goes backward at given rate (from 0-255)
void reverse (int rate)
{
    digitalWrite(EN, LOW);
    digitalWrite(MC1, LOW);
    digitalWrite(MC2, HIGH);
    analogWrite(EN, rate);
}

//Stops motor
void brake ()
{
    digitalWrite(EN, LOW);
    digitalWrite(MC1, LOW);
    digitalWrite(MC2, LOW);
    digitalWrite(EN, HIGH);
}

I still have a lot to learn.

Well let us know when you've applied the changes already suggested and then we can carry on trying to improve it from there.

Unfortunately I can't see anything useful in those weedy little Fritzing pictures so I still have no idea what sort of servo, motors, driver etc you're using. But I hope you're driving it with something more powerful than one of those nasty 9V batteries. They cause all sorts of problems.

Steve

I hope you're driving it with something more powerful than one of those nasty 9V batteries. They cause all sorts of problems.

Hmmm....noted. Perhaps I'll connect it to my voltage generator.

I'll update when I can (summer has run away from me again!).