Do you think my program will work?

Hi guys, I really need your help! I have a project to do for school and if I do not succed it, I won't get my diploma...

So my project, is to make a car that can follow an other vehicule and stops when it detects it in a range of 30 cm. If the vehicule turns, my car will have to turn also. When the car turns, a LED flash and when it stops, it ony lights.

So right know, my car is finished. The motor has been tested with arduino,the servomotor and the sensors too. Only the code is remaining. However, we are Thursday and I won't be able to test my car until next Monday... and I really don't have much time left!

Can you please check my code and see if my car will do what I want it to do?

I used two sensors, a Ping and a MaxSonar EZ2. I also used a servomotor.
My idea was that there's a sensor on each side of the car, and if one stops detecting something infront and the other still does, well, the car will turn. If they both don't detect anything in a range of 30 cm, the car advances. If they both detect someting,the car stops.

So, here's my code and tell me what you think about it. I just want to say that arduino didn't detected any errors. Little precison: a bit of my code is in French. moteur= Motor and DEL=LED. And since I'm not very good with Arduino, I used the example of the Ping and of the servo (sweep).

const int pingPin = 7;
int moteur= 3;
#include <Servo.h> 
int DEL = 6;
Servo myservo;
int pos = 0;
const int maxsonar = 1; 
long anVolt, inches, cm2;
int sum=0;
int avgrange=60;
long duration,cm;




void setup() {
  

pinMode(moteur, OUTPUT);
pinMode(DEL, OUTPUT);
myservo.attach(9);
pinMode(maxsonar,INPUT);

}




void loop()
{
  
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

 

  cm = microsecondsToCentimeters(duration);
  

  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  
  delay(100);
}

long microsecondsToInches(long microseconds)
{
  
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29 / 2;



  for(int i = 0; i < avgrange ; i++)
  {

    anVolt = analogRead(maxsonar)/2;
    sum += anVolt;
    delay(10);

  }  

  inches = sum/avgrange;
  cm2 = inches * 2.54;


  sum = 0;

  delay(500);
if (cm2>30,cm>30 ) 
{
digitalWrite(moteur,HIGH);
delay(1000);
digitalWrite(moteur,LOW);
delay(500);
digitalWrite(moteur,HIGH);
delay(1000);
digitalWrite(moteur,LOW);
delay(500);
digitalWrite(moteur,HIGH);
delay(1000);
digitalWrite(moteur,LOW);
delay(500);
}

if (cm < 30, cm2 <30 )
{
    digitalWrite(moteur,LOW);
  delay(500);
  digitalWrite(DEL,HIGH);
  delay(500); 
 }
   
  if(cm2>30,cm<30)
  
    { 
     digitalWrite(moteur, HIGH);
  delay(500);
  digitalWrite(moteur,LOW);
  delay(500); 
        for(pos = 0; pos < 180; pos += 1)  
  {                                   
    myservo.write(pos);            
    delay(150);  
    
   } 
 digitalWrite(DEL,HIGH);
 delay(500);
 digitalWrite(DEL,LOW);
delay(500); }
  
  if(cm2<30,cm>30)
{  
  digitalWrite(moteur, HIGH);
  delay(500);
  digitalWrite(moteur,LOW);
  delay(500); 
   for(pos = 180; pos>=1; pos-=1)      
  {                                
    myservo.write(pos);               
    delay(15);                       
  } 
  digitalWrite(DEL,HIGH);
 delay(500);
 digitalWrite(DEL,LOW);
delay(500); 
   } 

}}

Will it work? Thank you very much! :slight_smile: If you have questions, just ask :wink:

Your code as posted here will not compile so I can say with some certainty that it will not work.

Even if it did compile, then because every if statement in your code, such as

  if(cm2<30,cm>30)

is wrong, so it would not work anyway.

Also, in this block of code

    digitalWrite(moteur,HIGH);
    delay(1000);
    digitalWrite(moteur,LOW);
    delay(500);
    digitalWrite(moteur,HIGH);
    delay(1000);
    digitalWrite(moteur,LOW);
    delay(500);
    digitalWrite(moteur,HIGH);
    delay(1000);
    digitalWrite(moteur,LOW);
    delay(500);

You have total of 4 seconds delay during which time the car will not be able to do anything but turn the motor on and off. Why are you doing that anyway ?

So I only have to use

digitalWrite(moteur,HIGH);
    delay(1000);
    digitalWrite(moteur,LOW);
    delay(500);

one time? I don't want the car to go too fast. An analog pin would be better you think?

And whythis part of code wouldn't work? Why is it wrong?

if(cm2<30,cm>30)

Thank you for your answer!

@UKHeliBob
Not only that, but look at his microsecondsToCentimeters function.

Something in here is not right either.

Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();

What does this do?

for(int i = 0; i < avgrange ; i++)
{
anVolt = analogRead(maxsonar)/2;
sum += anVolt;
delay(10);
}

inches = sum/avgrange;
cm2 = inches * 2.54;

sum = 0;

Im guessing this is his attempt at PWM.

if (cm2>30,cm>30 )
{
digitalWrite(moteur,HIGH);
delay(1000);
digitalWrite(moteur,LOW);
delay(500);
digitalWrite(moteur,HIGH);
delay(1000);
digitalWrite(moteur,LOW);
delay(500);
digitalWrite(moteur,HIGH);
delay(1000);
digitalWrite(moteur,LOW);
delay(500);
}

Right now, this code is not going to work at all, at least not the way he wants it to.

if(cm2<30,cm>30)

Two possible ways it should be.
You either want the values to between cm2<30 or cm>30 or cm2<30 and cm>30

Ohhh ya I forgot, I removed this part

Serial.print("in, ");
Serial.print(cm);
Serial.print("cm");
Serial.println();

And well, I used this code found in the internet, tested it on my maxsonar and it worked

const int anPin = 1;

//variables needed to store values
long anVolt, inches, cm;
int sum=0;//Create sum variable so it can be averaged
int avgrange=60;//Quantity of values to average (sample size)

void setup() {

  //This opens up a serial connection to shoot the results back to the PC console
  Serial.begin(9600);

}

void loop() {

  //MaxSonar Analog reads are known to be very sensitive. See the Arduino forum for more information.
  //A simple fix is to average out a sample of n readings to get a more consistant reading.\\ 
  //Even with averaging I still find it to be less accurate than the pw method.\\ 
  //This loop gets 60 reads and averages them

  for(int i = 0; i < avgrange ; i++)
  {

    //Used to read in the analog voltage output that is being sent by the MaxSonar device.
    //Scale factor is (Vcc/512) per inch. A 5V supply yields ~9.8mV/in
    //Arduino analog pin goes from 0 to 1024, so the value has to be divided by 2 to get the actual inches
    anVolt = analogRead(anPin)/2;
    sum += anVolt;
    delay(10);

  }  

  inches = sum/avgrange;
  cm = inches * 2.54;
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();

  //reset sample total
  sum = 0;

  delay(500);

}

HazardsMind:

if(cm2<30,cm>30)

Two possible ways it should be.
You either want the values to between cm2<30 or cm>30 or cm2<30 and cm>30

Oh ok, I'll change it right now to and!

I don't want the car to go too fast. An analog pin would be better you think?

Not an analogue pin, a PWM pin, and I hope that you are not driving the motor straight from the Arduino, or are you ?

Just spotted this

    for(pos = 0; pos < 180; pos += 1)  
    {                                   
      myservo.write(pos);            
      delay(150);  

    }

Work out how long it is going to take the servo to move through 180 degrees. Is nearly 27 seconds acceptable ?

UKHeliBob:

I don't want the car to go too fast. An analog pin would be better you think?

Not an analogue pin, a PWM pin, and I hope that you are not driving the motor straight from the Arduino, or are you ?

Just spotted this

    for(pos = 0; pos < 180; pos += 1)  

{                                  
     myservo.write(pos);            
     delay(150);

}


Work out how long it is going to take the servo to move through 180 degrees. Is nearly 27 seconds acceptable ?

Alright, the pin A5 is good?
And no, I'm using a 7V battery with a voltage regulator and a transistor. Don't worry :smiley:

Well, I was going to leave it that way and when I will do the tests with my car, change the values until I find something good... But if you a have a suggestion ,I'll obvioulsy take it! But yes... 150 ms is way too quick... I'll change it to 27 seconds...

Heum no I meant the pin 3

No, 27 seconds is the overall delay if that function.

Oh, you mean that even with a delay of 150, my car will take approximatively 27 seconds to turn?

That delay is reason it takes 27 second to turn. Take the delays out.

Oh I get it! I'll remove them.

So right know, this is my code. Since my motor was already on a PWM pin, I only changed every digitalWrite by a analogWrite

const int pingPin = 7;
int moteur= 3;
#include <Servo.h> 
int rouge = 6;
int vert = 5;
int bleu= 4;
Servo myservo;
int pos = 0;
const int maxsonar = 1; 
long anVolt, inches, cm2;
int sum=0;
int avgrange=60;
long duration,cm;




void setup() {
  

pinMode(moteur, OUTPUT);
pinMode(rouge, OUTPUT);
pinMode(vert,OUTPUT);
pinMode(bleu,OUTPUT);
myservo.attach(9);
pinMode(maxsonar,INPUT);

}




void loop()
{
  
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

 

  cm = microsecondsToCentimeters(duration);
  


  
  delay(100);
}

long microsecondsToInches(long microseconds)
{
  
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29 / 2;



  for(int i = 0; i < avgrange ; i++)
  {

    anVolt = analogRead(maxsonar)/2;
    sum += anVolt;
    delay(10);

  }  

  inches = sum/avgrange;
  cm2 = inches * 2.54;


  sum = 0;

  delay(500);
if (cm2>30 and cm>30 ) 
{
digitalWrite(rouge,HIGH);
delay(500);
digitalWrite(rouge,LOW);
delay(500);  
digitalWrite(vert,HIGH);
delay(500);
digitalWrite(vert,LOW);
delay(500); 
digitalWrite(bleu,HIGH);
delay(500);
digitalWrite(bleu,LOW);
delay(500);
  
analogWrite(moteur,170);
delay(500);


}

if (cm < 30 and cm2 <30 )
{
    analogWrite(moteur,0);
  delay(500);
  digitalWrite(rouge,HIGH);
  delay(500); 
 }
   
  if(cm2>30 and cm<30)
  
    { 
     analogWrite(moteur, 90);
  delay(500);
  
        for(pos = 0; pos < 180; pos += 1)  
  {                                   
    myservo.write(pos);            

    
   } 
 digitalWrite(vert,HIGH);
 delay(500);
 digitalWrite(vert,LOW);
delay(500); }
  
  if(cm2<30 and cm>30)
{  
  analogWrite(moteur, 90);
  delay(500);
  
   for(pos = 180; pos>=1; pos-=1)      
  {                                
   myservo.write(pos);               
                      
  } 
  digitalWrite(bleu,HIGH);
  delay(500);
  digitalWrite(bleu,LOW);
  delay(500); 
   } 

}

Now, my program is good enough?

    for(pos = 0; pos < 180; pos += 1)  
    {                                   
      myservo.write(pos);            


    }

Now the delay in the for loop has been removed you don't need the for loop anyway. The code is telling the servo output to move 179 steps so fast that you might as well just use

 myservo.write(179);

It may not matter in practice, but your servo commands left and right are not balanced. In one direction you turn it from 0 to 179 whilst in the other direction you turn it from 180 to 1. What I don't see is where you move it to the centre so that the car runs straight.

As to the use of analogWrite() to control the speed of the car, it may work but we do not have any details of the motor or its exact wiring.

So to turn left I should write myservo.write(179); ?

And to turn right I should write myservo.write(-179); 

Should put a delay after those commands and set myservo.write(0); to go straight than?

And the motor is a 6V motor from a car my teacher bought in a supermarket... It's a RC car. It has two wires.

ANd maybe I should have written this before but here are my sources.

Ping:

 /* Ping))) Sensor
  
   This sketch reads a PING))) ultrasonic rangefinder and returns the
   distance to the closest object in range. To do this, it sends a pulse
   to the sensor to initiate a reading, then listens for a pulse 
   to return.  The length of the returning pulse is proportional to 
   the distance of the object from the sensor.
     
   The circuit:
	* +V connection of the PING))) attached to +5V
	* GND connection of the PING))) attached to ground
	* SIG connection of the PING))) attached to digital pin 7

   http://www.arduino.cc/en/Tutorial/Ping
   
   created 3 Nov 2008
   by David A. Mellis
   modified 30 Aug 2011
   by Tom Igoe
 
   This example code is in the public domain.

 */

// this constant won't change.  It's the pin number
// of the sensor's output:
const int pingPin = 7;

void setup() {
  // initialize serial communication:
  Serial.begin(9600);
}

void loop()
{
  // establish variables for duration of the ping, 
  // and the distance result in inches and centimeters:
  long duration, inches, cm;

  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // convert the time into a distance
  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);
  
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  
  delay(100);
}

long microsecondsToInches(long microseconds)
{
  // According to Parallax's datasheet for the PING))), there are
  // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
  // second).  This gives the distance travelled by the ping, outbound
  // and return, so we divide by 2 to get the distance of the obstacle.
  // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return microseconds / 29 / 2;
}

maxsonar: Arduino Playground - MaxSonar

 const int anPin = 1;

//variables needed to store values
long anVolt, inches, cm;
int sum=0;//Create sum variable so it can be averaged
int avgrange=60;//Quantity of values to average (sample size)

void setup() {

  //This opens up a serial connection to shoot the results back to the PC console
  Serial.begin(9600);
}

void loop() {

  //MaxSonar Analog reads are known to be very sensitive. See the Arduino forum for more information.
  //A simple fix is to average out a sample of n readings to get a more consistant reading.\\ 
  //Even with averaging I still find it to be less accurate than the pw method.\\ 
  //This loop gets 60 reads and averages them

  for(int i = 0; i < avgrange ; i++)
  {
    //Used to read in the analog voltage output that is being sent by the MaxSonar device.
    //Scale factor is (Vcc/512) per inch. A 5V supply yields ~9.8mV/in
    //Arduino analog pin goes from 0 to 1024, so the value has to be divided by 2 to get the actual inches
    anVolt = analogRead(anPin)/2;
    sum += anVolt;
    delay(10);
  }  
  inches = sum/avgrange;
  cm = inches * 2.54;
  Serial.print(inches);
  Serial.print("in, ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  //reset sample total
  sum = 0;
  delay(500);
}

pro3000:
So to turn left I should write myservo.write(179); ?

And to turn right I should write myservo.write(-179); 

Should put a delay after those commands and set myservo.write(0); to go straight than?

And the motor is a 6V motor from a car my teacher bought in a supermarket... It's a RC car. It has two wires.

To turn the servo (and I assume the steering) one way

 myservo.write(170);

and the other way

 myservo.write(0);

and straight between the two

 myservo.write(90);

What is there between the Arduino and the car ?

UKHeliBob:

pro3000:
So to turn left I should write myservo.write(179);  ?

And to turn right I should write myservo.write(-179);  

Should put a delay after those commands and set myservo.write(0); to go straight than?

And the motor is a 6V motor from a car my teacher bought in a supermarket... It's a RC car. It has two wires.

To turn the servo (and I assume the steering) one way

 myservo.write(170);

and the other way

 myservo.write(0);

and straight between the two

 myservo.write(90);

What is there between the Arduino and the car ?

Thank you! And as I said before, I'm using a 7V battery with a tension regulator of 6V. Also I use a transistor.

So,there's the Arduino, after, I use a resistor. After, It's the transistor, the motor, the tension regulator and the battery.

My teacher made this circuit for us. I tested the circuit with the motor only and some digitalWrite in the Arduino and it worked perfectly.

Also, I've been told that the function return would stop my program so my second sensor wouldn't work. It's true? should I remove it?