Robot freaking out about new code???

Hey guys, my robot Walbot started out using just one Ultrasonic sensor to navigate rooms, but I recently tried to add two Sharp IR sensors, and I updated the code to work with them so that if it senses an object on the right it will turn to the left and vice versa, as well as if all three sensors are blocked it will turn around. I have gotten all the components to work properly (I have used the Sharp IR sensors and they give me correct values back) but when I put everything together I started getting a bunch of whack false readings and it just became completely paralyzed. I have gone over the code a couple of times to see what might be causing it to react strangely but I can’t seem to find what the problem is. Any help would be greatly appreciated.

int Motor1A = 10;  // H-Bridge input 1             
int Motor1B = 11;  // H-Bridge input 2               
int enable = 3;     // H-Bridge motor 1 enable
int Motor2A = 9;  // H-Bridge input 3             
int Motor2B = 8;  // H-Bridge input 4               
int enable2 = 5;     // H-Bridge motor 2 enable
int infraAn1 = 1;    // select the input pin for the infrared sensor
int infraAn2 = 2;    // select the input pin for the infrared sensor
float infraDist1 = 0;   // variable that recieves raw infrared analog data
float infraDist2 = 0;   // variable that recieves raw infrared analog data
int ultraAn = 0;    // select the input pin for the ultrasonic sensor
int UltraEnable = 12;    // sets enable to pin 12
int ledPin = 13;    // sets the indicator led to pin 13
float val[10];       // array to store first 10 values coming from the sensor
float valSum=0;      // sum of first 10 readings
float valAvg=0;      // average of the first 10 readings
float dist = 0;      // variable to store the converted distance in inches

void straight() // go straight function
{
    digitalWrite(enable, HIGH);
    digitalWrite(Motor1A, HIGH);
    digitalWrite(Motor1B,LOW);
    digitalWrite(enable2, HIGH);
    digitalWrite(Motor2A, HIGH);
    digitalWrite(Motor2B,LOW);
}

void turnRight() // turn right function          
{
    digitalWrite(enable, HIGH);
    digitalWrite(Motor1A, LOW);
    digitalWrite(Motor1B,HIGH);
    digitalWrite(enable2, HIGH);
    digitalWrite(Motor2A, HIGH);
    digitalWrite(Motor2B,LOW);
}

void turnLeft() // turn right function          
{
    digitalWrite(enable, HIGH);
    digitalWrite(Motor1A, HIGH);
    digitalWrite(Motor1B,LOW);
    digitalWrite(enable2, HIGH);
    digitalWrite(Motor2A, LOW);
    digitalWrite(Motor2B,HIGH);
}

float distCalc() // distance calculating function converts analog input to inches
{ 
 valSum = 0;                           // resets valSum to zero after every loop
  for (int i=0; i<=9; i++)              // for loop to gather first 10 int's
  {
    val[i] = analogRead(ultraAn);       // read the value from the sensor
    valSum = (val[i]+valSum);           // adds the first 10 values for averaging
  }
  digitalWrite(UltraEnable, LOW);            // disables sonar
  valAvg = (valSum/10);                 // calculates the average 
  dist = ((valAvg/204.8)/.009765625);   // converts the analog value to distance in inches
  
  return dist;                         // return the distance values to the rest of the program
}

void avoideWalls()
{  
    infraDist1 = analogRead(infraAn1);       // read the value from the sensor
    infraDist2 = analogRead(infraAn2);       // read the value from the sensor
    
    if(dist < 16)                            // if the distance is less than 20 inches
  {
    digitalWrite(ledPin, HIGH);             // turn on the LED
    turnRight();                            // turns Walbot right using turnRight function
    delay(100);
  }
  
    else if(dist < 16 && infraDist1 > 220)                            // if the distance is less than 20 inches
  {
    digitalWrite(ledPin, HIGH);             // turn on the LED
    turnRight();                            // turns Walbot right using turnRight function
    delay(100);
  }
  
    else if(dist < 16 && infraDist2 > 220)                            // if the distance is less than 20 inches
  {
    digitalWrite(ledPin, HIGH);             // turn on the LED
    turnLeft();                            // turns Walbot right using turnRight function
    delay(100);
  }

  
    else if(dist < 16 && infraDist2 > 220 && infraDist1 > 220)                            // if the distance is less than 20 inches
  {
    digitalWrite(ledPin, HIGH);             // turn on the LED
    turnLeft();                            // turns Walbot around using turnRight function
    delay(175);                            //delay is longer so it turns 180 degrees 
  }
  
  else                                      // otherwise
  {
    digitalWrite(ledPin, LOW);              // turn off the LED
    straight();                            // go straight using the straight function
  }
}

void setup()
{
  pinMode(Motor1A, OUTPUT);      // sets motor pin 1A as output  
  pinMode(Motor1B, OUTPUT);      // sets motor pin 1B as output
  pinMode(Motor2A, OUTPUT);      // sets motor pin 2A as output
  pinMode(Motor2B, OUTPUT);      // sets motor pin 2B as output
  pinMode(enable, OUTPUT);       // sets enable as output
  pinMode(enable2, OUTPUT);      // sets enable2 as output
  pinMode(UltraEnable, OUTPUT);  // sets UltraEnable as output
  pinMode(ledPin, OUTPUT);       // sets ledPin as output
  
  straight(); // initializes Walbot to go straight
}

void loop() {
  digitalWrite(UltraEnable, HIGH);           // turns on sonar
  distCalc();                                // gets the distance value from distCalc function
  avoideWalls();                             // tells Walbot not to run into inanimate objects by calling avoideWalls function
  delay(20);                                 // delay for 20 milliseconds
}

Have you put some serial prints into your code to test the sensor values you're getting? What kind of whack false readings?

FYI - you can get away with using two fewer pins by tying the h-bridge enables to 5V. Usually.

A few more questions - what kind of ultrasonic sensor are you using? I use Pings and Devantech RF04s, but to use them I have to incorporate timing into my code. I'm not seeing that in your code; you might want to read this thread for hints on ultrasonic sensor reading - http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1167315558/9

I haven't used IR sensors yet (although I recently acquired a handful) but my understanding is that they can be read very simply, just an analogRead() from the analog input pin they are connected to. Not true for ultrasonics!

Im using the MaxEZ1 Ultrasonic sensor, its really easy to use cause all the timing and calculating is done in real time on the unit itself, it sends me either a digital or analog value of the actual distance. as for the weird readings, it literally has seizures and detects an object thats not there 5 times a second and it just spazes out jerking on the ground. I have held it up in the air so no object could possibly be in its path, but it still does it. When I unplug the Ultrasound it works fine with the Sharp IR sensors, and when I unplug the IR sensors it works fine with just the sonar, but when both are plugged in they somehow interfere with each other, and I don't know how thats possible.

Hi,
Sounds like you are building a nice bot. I wish mine was that far along.
Anyway, I don’t know exactly why you are getting the spazzing, but your code does have a number of
flaws. I’ll point one or two that I saw.

First, the logic in avoideWalls() probably doesn’ t do what you want. Only the first if condition will ever
be executed. If dist < 16 is true, it will do the first if and skip the rest. If it isn’t < 16, then only the last else is executed. You need to restructure this, probably with nested ifs.
With this code the behavior I would expect would be either the robot keeps going straight, or it
turns in a circle.

Second, unless you really have a dire need for it, float values are not good for these chips. They aren’t
supported in hardware, so even 1 float operation uses a lot of memory. Use fractions whenever possible.

Finally, what’s the size of your sketch? It is possible you are running out of memory, which would result
in lots of strange things happening. Not so much in the sketch space as RAM. Like I said, floating point ops take up a lot.

Hope this gives you a starting point.

I would recommend putting your robot up on "jackstands" (I use a piece of wood); connecting the serial cable, running the bot, and adding debug lines to your code to send the values your sensors are reading out to the serial monitor. This is how I dial in my sensors - and you can debug your logic at the same time.

You can get the sort of interplay between sensors that you describe just by how your wiring is done. When you run cables to sensors, try to use shielded cable, with a connection from the shield (one end only) to your system ground (the ground your circuits, including arduino, should be sharing). I have really reduced my encoder signal noise this way, and the conditioned signal that your ultrasonic is using may not be very noise tolerant either (more shielded cable).

Assuming you aren't doing this already.

All my wires are braided and grounded properly so shielding should not be an issue, I'm curious about what ckiick said about my if statements, to be honest my coding skills are almost non existent, and I'm not really sure about the if statements, and what you mean about nested if statements... could you help me with a little pseudocode outline of what you are talking about?

Here is an example of nested ifs (you can see by the indentation what is meant by “nested”)

  if(usValue > closeUp);
  {
    if(usValue < closeUp)
    {
      stopboth();
      delay(500);
      turnright();
      delay(500);
      usValue = scanfront();
      if(usValue < closeUp)
      {
        usValue = scanback();
        if(usValue > closeUp)
        {
          turnleft();
          delay(500);
          turnleft();
          delay(500);
          usValue = scanfront();
        }
        else
        {
          turnright();
        }
      }
      rampup();
    }
  }

Trying to code a robot’s behavior this way gets complicated fast. I’m reading up on behavior-based programming now, but I haven’t written anything yet.

so would this be better to use?

void avoideWalls()
{  
    infraDist1 = analogRead(infraAn1);       // read the value from the sensor
    infraDist2 = analogRead(infraAn2);       // read the value from the sensor
    
    if(dist < 16)                            // if the distance is less than 20 inches
  {
    if(infraDist1 > 220)                            // if the distance is less than 20 inches
    {
      digitalWrite(ledPin, HIGH);             // turn on the LED
      turnRight();                            // turns Walbot right using turnRight function
      delay(100);
    }
    
    else if(infraDist2 > 220)                            // if the distance is less than 20 inches
    {
      digitalWrite(ledPin, HIGH);             // turn on the LED
      turnLeft();                            // turns Walbot right using turnRight function
      delay(100);
    }
    
    else if(infraDist2 > 230 && infraDist1 > 230)                            // if the distance is less than 20 inches
    {
      digitalWrite(ledPin, HIGH);             // turn on the LED
      turnLeft();                            // turns Walbot around using turnRight function
      delay(175);                            //delay is longer so it turns 180 degrees 
    }
    
    else
    {
      digitalWrite(ledPin, HIGH);             // turn on the LED
      turnLeft();                            // turns Walbot right using turnRight function
      delay(120);
    }
  }
  
  else                                      // otherwise
  {
    digitalWrite(ledPin, LOW);              // turn off the LED
    straight();                            // go straight using the straight function
  }
}

Good changes, pretty close.

You want to put this condition first in the inside if statement: if(infraDist2 > 230 && infraDist1 > 230)

Since it is the most restrictive. Otherwise the more general cases will be hit first and that block will never get used.

One way to save some memory is to use #defines for constant values that don't change, instead of variables. #defines are handled by the compiler.

Keep on coding!

thanks for your help, I’ll try that. About the memory I’m only using about 1/3 or 1/2 the Atmega168’s capacity so I don’t think thats too much of a problem.