I know your all familiar with C (how about a tip)

I need a quick bit of help, whats keeping my functions in the loop() from executing? I haven't spent much time with C...I'm a mechanical engineer trying to learn some mechatronics on his own.

If some of the commands may seem foreign, I'm using a motor shield/controller from ladyada. Any suggestions would be greatly appreciated, this is my first project with the Arduino.

Follows is code:

// Parker Conroy
// Moves a robot in the direction of the most space in front of it
// not completed

#include <Servo.h>
#include <AFMotor.h>

int new_ang;
int old_ang=90; // Base direction is forward
int base = 25; // Left most side of servo
int top= 179; // Right most side of servo
int rf= 1; // pin the rf is on
int range[179]; // same as in void find_ranges and magnitude of top variable ^
int led_1_Pin = 13; // LED connected to Analog pin 13

Servo servo; // create servo object to control a servo
AF_DCMotor motor(1, MOTOR12_64KHZ); // create motor #2, 64KHz pwm

void setup()
{

servo.attach(9); // attaches the servo on pin 9 to the servo object
Serial.begin(9600); // setup serial talk @ 9600 bps
pinMode(led_1_Pin, OUTPUT); // sets the analog pin as output
//Vars

motor.setSpeed(200); //200/255 of full speed

}

void loop()
{

//Funks
digitalWrite(led_1_Pin, HIGH); // debug actions************************************
delay(1000);
digitalWrite(led_1_Pin, LOW); // debug actions************************************

find_ranges(base, top, rf, range); // array passed into
new_ang = find_max_range(top, base, range);
smart_move(new_ang, old_ang);
old_ang=new_ang;
//need funk for moving forward ( based on refresh rate for sampling new range info)

}

//Funk for rangefinding over basetop degrees
void find_ranges(int base, int top, int rf, int range[179])
{

int pos = base; // variable to store the servo position
// int range[top]; //array for graphing or AI control ( not used yet; array passed into funk now)
int sweep_dir=1; //Var for direction of sweeping motion

servo.write(pos); //Set position to move
range[pos]=analogRead(rf);
Serial.print("You are ");
range[pos] = 3027.4/range[pos]; // read the value from the sensor
range[pos]= (pow(range[pos],1.2134));
Serial.print(range[pos]);
Serial.print(" away at ");
Serial.println(pos);
delay(25);

if (pos == top)
{
sweep_dir = 0;
}
else if (pos == base)
{
sweep_dir =1;
}

if (sweep_dir)
{
pos++;
}
else
{
pos= pos-1;
}

}
// Funk for finding the new angle for movement
int find_max_range(int top, int base, int range[179] )
{
int big_range;
int i=base;
int new_dir;

while (i<=top)
{
if (range[i+1] > range*)*

  • {*
  • new_dir= i+1;*
  • }*
  • }*
  • new_ang=new_dir;*
    return new_ang;
    }
    // Code for moving step motor to rotate robot a certain number of degrees.
    void smart_move(int new_ang, int old_ang)
    {
  • int diff_ang=new_ang-old_ang;*
  • if (abs(diff_ang) >= 15) //if diference in directional angle is more then three*
  • {*
  • if (diff_ang <0)*
  • {*
  • //rotate right wheel for a change of neg angle*
  • // Dependent on size of wheels*
  • }*
  • else*
  • {*
  • //rotate left wheel for change of pos angle*
  • // Dependent on size of wheels*
  • }}*
    else
    motor.run(FORWARD);
    {
  • }*
    }

in situations like this, it often helps to put some serial print debug statements in each function to see where it is getting stuck.

Also, check for and while loops to see if the termination conditions can be met.
For example in the following function:

int find_max_range(int top, int base, int range[179] )
{
 int big_range;
 int i=base;
 int new_dir;

 while (i<=top)
 {
   if (range[i+1] > range[i])
   {
     new_dir= i+1;
   }
 }
 new_ang=new_dir;
return new_ang;
}

the while loop will only exit when i is greater than top. But i and top are not modified in the function so it will never exit if the function is called with top greater than i

I hope that helps

I think mem made a good observation about the infinite loop. Another thing that gives me some anxiety is this:

range[pos]=analogRead(rf);
 Serial.print("You are "); 
 range[pos] = 3027.4/range[pos];   // read the value from the sensor

If analogRead ever returns 0 you'll get a division by zero exception.

Mikal

Thanks again for all your help. I seem to be getting erratic behavior from my servo now. It moves +ve well but when it reaches its +ve limit it snaps to position ~ 180 and then the system counts down, then moving back to the base position. If the program executes correctly, the pos variable will never be less then the base (avoiding zero) or more than the top.

Can you guys see whats keeping the servo moving function from moving the servo fluidly back and forth from the top position to the base position and then back?

Your help has been awesome.

Follows is code v_2:
// Parker Conroy
// Moves a robot in the direction of the most space in front of it
// v2

#include <Servo.h>
#include <AFMotor.h>

int new_ang;
int old_ang=90; // Base direction is forward
int base = 75; // Left most side of servo
int top= 150; // Right most side of servo
int rf= 1; // pin the rf is on
int range[149]; // same as in void find_ranges and magnitude of top variable ^
int led_1_Pin = 13; // LED connected to Analog pin 13

//In find_ranges
int pos = base; // variable to store the servo position
int sweep_dir=1; //Var for direction of sweeping motion

//In find_max_range
int big_range;
int i=base;
int new_dir;

Servo servo; // create servo object to control a servo
AF_DCMotor motor(1, MOTOR12_64KHZ); // create motor #2, 64KHz pwm

void setup()
{

servo.attach(9); // attaches the servo on pin 9 to the servo object
Serial.begin(9600); // setup serial talk @ 9600 bps
pinMode(led_1_Pin, OUTPUT); // sets the analog pin as output
//Vars

Serial.println("Setup Completed"); // Debug action*************************

motor.setSpeed(100); //100/255 of full speed

}

void loop()
{

Serial.println("Loop Begun");// Debug action*************************

find_ranges(base, top, rf, range); // array passed into
new_ang = find_max_range(top, base, range);
smart_move(new_ang, old_ang);
old_ang=new_ang;
//need funk for moving forward ( based on refresh rate for sampling new range info)

}

//Funk for rangefinding over basetop degrees
void find_ranges(int base, int top, int rf, int range[149])
{
Serial.println("Find_ranges Begun");// Debug action*************************

servo.write(pos); //Set position to move
range[pos]=analogRead(rf);
Serial.print("You are ");
range[pos] = 3027.4/range[pos]; // read the value from the sensor
range[pos]= (pow(range[pos],1.2134));
Serial.print(range[pos]);
Serial.print(" away at ");
Serial.println(pos);
delay(1);

if (pos >= top){

sweep_dir = 0;
Serial.println("sweep_dir =0");// Debug action*************************

}
if (pos <= base){

sweep_dir =1;
Serial.println("sweep_dir = 1");// Debug action*************************
}

if (sweep_dir)
{
pos++;
Serial.println("In sweep dir: Pos ++");// Debug action*************************
}
else
{
pos= pos-1;
Serial.println("In sweep dir: Pos --");// Debug action*************************
}

}
// Funk for finding the new angle for movement
int find_max_range(int top, int base, int range[149] )
{
Serial.println("Find_max_range Begun");// Debug action*************************

for ( i <= top; i++;){

if (range[i+1] > range*)*

  • {*
  • new_dir= i+1;*
  • }*
  • }*
  • new_ang=new_dir;*
    return new_ang;
    }
    // Code for moving step motor to rotate robot a certain number of degrees.
    void smart_move(int new_ang, int old_ang)
    {
    Serial.println("Smart_move Begun");// Debug action*************************
  • int diff_ang=new_ang-old_ang;*
  • if (abs(diff_ang) >= 15) //if diference in directional angle is more then three*
  • {*
  • if (diff_ang <0)*
  • {*
  • //rotate right wheel for a change of neg angle*
  • // Dependent on size of wheels*
  • }*
  • else*
  • {*
  • //rotate left wheel for change of pos angle*
  • // Dependent on size of wheels*
  • }}*
    else
    motor.run(FORWARD);
    {
  • }*
    }

I see what appears to be a malformed for loop in find_max_range. I'm just speculating, but I think that with 2 changes,

for ( i <= top; i++;)

should become

for (i=base; i < top-1; i++)

Note that in addition to adding the "init" clause "i=base", I have changed "i <= top" to "i < top-1". This is because you use the expression "range[i+1]" at one point, so if "i" were ever to reach the value "top" or even "top-1", you would exceed the upper bound of the array! This is a no no!

[Edits added after reading mem's post.]

Mikal

(Mikal posted while I was composing this , but here is my reply)

I suggest that you test each module of your code separately before trying to get the whole application to work. It may seem like a long winded approach but I think you will find that it will be much easier to see what each part is doing and test that its working correctly.

For example, have you tested the new routine for find_max_range ? Why not have a simple sketch that feeds this routine with some representative values and print the results to see if its working as you think it should. I expect you will find the for loop is not doing what you want. I would guess you want this function to be more like this:

Funk for finding the new angle for movement
int find_max_range(int top, int base, int range[149] )
{
 Serial.println("Find_max_range Begun");// Debug action*************************

for (int  i = base; i <= top; i++;){
 
   if (range[i+1] > range[i])
   {
       return i+1;
   }
 }
 return some default value here just in case range[i+1] is never greater than range[i] !!!!!!;
}

I have not looked at the other functions in your code but urge you to test each function on its own if the app still doesn't work.

I second what mem said :slight_smile:

Also making every other line of code print out stuff is not a bad thing when debugging your code

#define DEBUG

void setup()                    // run once, when the sketch starts
{
}

void loop()
{
}
// Funk for finding the new angle for movement
int find_max_range(int top, int base, int range[149])
{
Serial.println("Find_max_range Begun");
for (int  i = base; i <= top; i++)
{
#ifdef DEBUG
Serial.println("inside the loop base=");
Serial.println(base);
Serial.println("top=");
Serial.println(top);
#endif
   if (range[i+1] > range[i])
   {
#ifdef DEBUG
Serial.println("inside if range[i]=");
Serial.println(range[i]);
Serial.println("range[i+1]=");
Serial.println(range[i+1]);
#endif
         return i+1;
   }
 }
#ifdef DEBUG
Serial.println("returning from function find_max_range");
#endif

// return some default value here just in case range[i+1] is never      // greater than range[i] !!!!!!;
}

Remember the preprocessor and the print functions are your best friends when debugging code

:slight_smile: