What is wrong with this code???? It won't Compile and I don't know why? Please Help

/*******************************************************************************
*

  • TITLE: navigate.c
  • VERSION: 1.0
  • DATE: 08-Jan-2004
  • AUTHOR: Richard D. Petras
  • COMMENTS:

  • CHANGE LOG:
  • DATE REV DESCRIPTION

  • 04-Dec-2003 0.2 RDP Added Tracker to drive robot to goal
  • 06-Dec-2003 0.3 RDP First implementation of drive algorithm
  • 07-Dec-2003 0.4 RDP Got rid of servo glich by NOT disabling interrupts in
  •                     Timer 1 handler
    
  • 08-Jan-2004 1.0 RDP The version used at the 2004 kickoff

*******************************************************************************/

#include “ifi_picdefs.h”
#include “ifi_default.h”
#include “ifi_aliases.h”
#include “ifi_utilities.h”
#include “printf_lib.h”
#include “user_routines.h”
#include “navigate.h”

// Global Variables

int Navigator_State = WAIT_TO_DRIVE;

/*******************************************************************************
*

  • FUNCTION: Navigate()
  • PURPOSE: Controls the left and right drive motors in order to
  •   			drive to an infrared beacon.  This routine depends on two
    
  •   			beacon trackers to point the the IR beacon.  It then uses
    
  •   			the current servo angles to determine when to turn
    
  •   			the robot to get to the goal.  When the angles are
    
  •   			sufficiently small, we are at the target and stop.
    
  •               The vehicle starts out stopped (WAIT_TO_DRIVE)
    
  •               You might want to skip this state in autonomous mode :-)
    
  •               When a button is pressed it starts to drive (DRIVE_TO_CENTER).
    
  •               This drive is very short(just enough to move away from the
    
  •               wall.  Next we search until one of the trackers sees the 
    
  •               beacon (TURN_TO_TARGET).  Then we drive toward the target
    
  •               (DRIVE_TO_TARGET) until we pass it (PASSED_TARGET).  Then  
    
  •               drive until the trackers are both beyond the goal point
    
  •               (AT_TARGET).  During all of this we are watching the current
    
  •               to see if it exceeds the expected maximum value(OVER_CURRENT).
    
  • PARAMETERS: none
  • RETURNS: nothing
  • COMMENTS: The values set in navigate.h are very dependent on the
  •   			particular robot configuration and will require some tuning
    
  •               for your robot.
    

*******************************************************************************/

void Navigate()
{

// Note: Statics are used to retain the variable values across
// calls. Otherwise, the values stored inside a function are not
// guarenteed to remain the same.
static unsigned int Old_Clock = 0; // A place to store the last clock value
static unsigned char drive_timer = 0; // Timer for driving forward in 26 msec steps

static unsigned char left_drive_set = LSTOP; // Start out stopped
static unsigned char right_drive_set = RSTOP;
static unsigned char left_servo_set = 127; // Trackers pointed straight ahead
static unsigned char right_servo_set = 127;

int left_error, right_error; // Errors from the tracker goal
int left_state, right_state; // Left and right tracker state
static unsigned int left_current[10] = {0}; // This is a circular buffer for
static unsigned int right_current[10] = {0}; // storing current values. We
// need this because the sensors
// are noisy. We’ll take an avg
// of the last ten values.
static int i = 0; // Current buffer counter
unsigned int left_current_avg, right_current_avg;
int n; // Counter
int drive_state = DR_UNDEFINED;
if (Clock > Old_Clock) // stay synchronized to beacon data updates (this is important)
{
left_current* = Get_Analog_Value( rc_ana_in01 ); // Get the currents for
right_current* = Get_Analog_Value( rc_ana_in02 ); // each wheel. Just comment
// out all the current code
// if not using current sensors

// If we get a high current value, check the last ten to be sure its not just a glitch
if (((left_current* > MAX_CURRENT) || (right_current* > MAX_CURRENT)) && 
				(Navigator_State != WAIT_TO_DRIVE) && (Navigator_State != AT_TARGET))
	{
	// Maybe this is real, but current sensors can be noisy
	// Check the last ten values to see if they agree
	left_current_avg = 0;
	right_current_avg = 0;
	for (n = 0; n < 10; n++)
		{
		left_current_avg += left_current[n];
		right_current_avg += right_current[n];
		} 
	left_current_avg /= 10;
	right_current_avg /= 10;
	if ((left_current_avg > MAX_CURRENT) || (right_current_avg > MAX_CURRENT))
		{
		Navigator_State = OVER_CURRENT;
		printf("Left_current = %d Right_current = %d

", left_current_avg, right_current_avg);
printf("OVER_CURRENT
"); // Over current
drive_timer = 0;
}
}
if (i++ >= 10) i=0; // Reset our circular buffer counter if needed

// This is the main Navigator state machine implemented as a switch statement
switch (Navigator_State)
	{
	// Just wait until a button is pressed before we start (skip for autonomous mode)

// case WAIT_TO_DRIVE:
{
// Don’t go anywhere
left_drive_set = LSTOP;
right_drive_set = RSTOP;
// Eyes forward
left_servo_set = 127;
right_servo_set = 127;
if (p1_sw_trig)
{
Navigator_State = DRIVE_TO_CENTER;
printf("DRIVE_TO_CENTER
"); // Driving to center
left_servo_set = 127;
right_servo_set = 127;
}
break;
}
case DRIVE_TO_CENTER:
{
// Drive away from the wall.
left_drive_set = FFWD;
right_drive_set = FFWD;
if (drive_timer++ > DRIVE_TO_CENTER_TIME)
{
Navigator_State = TURN_TO_TARGET;
printf("TURN_TO_TARGET
"); // Done driving to center
left_servo_set = 127;
right_servo_set = 127;
}
break;
}
case OVER_CURRENT:
{
// If we get here let’s back off a little and start over
// Note: we could do better here if we remembered that we
// passed the target. (Exercise left to the student :-))
left_drive_set = LSTOP;
right_drive_set = RSTOP;
if (drive_timer++ > DRIVE_TO_CENTER_TIME)
{
Navigator_State = TURN_TO_TARGET;
printf("TURN_TO_TARGET
"); // Done driving to center
left_servo_set = 127;
right_servo_set = 127;
}
break;
}
case TURN_TO_TARGET:
{
// Point trackers straight ahead, then turn
// until at least one tracker sees the beacon
left_servo_set = 127;
right_servo_set = 127;
left_drive_set = SBWD;
right_drive_set = SFWD;
if (((LL) && (LR)) || ((RL) && (RR)))
{
Navigator_State = DRIVE_TO_TARGET; // At least one sensor sees the target
printf("DRIVE_TO_TARGET
");
}
break;
}
case DRIVE_TO_TARGET:
case PASSED_TARGET:
{
// As long as we are locked on to the beacons with both targets
// drive toward them
Track_Beacon(LEFT); // allow the left beacon tracker state machine to run
Track_Beacon(RIGHT); // allow the right beacon tracker state machine to run

		// update the servo PWM values with the values calculated by Track_Beacon() above
		left_servo_set = Tracker_Data[LEFT].Position;
		right_servo_set = Tracker_Data[RIGHT].Position;

		if ((Tracker_Data[LEFT].Status == BOTH_IN_VIEW) &&
			(Tracker_Data[RIGHT].Status == BOTH_IN_VIEW))
			{			
			// We are locked on with both targets, so drive!

			// Find out which way the servoes are pointed
			if (left_servo_set < 127)      // Left servo pointed left
				{
				left_state = DR_LEFT;
				}
			else if (left_servo_set > LEFT_GOAL)     // Left servo pointed right
				{
				left_state = DR_RIGHT;
				} 
			else
				{
				left_state = DR_CENTER;
				}

			if (right_servo_set > 127)      // Right servo pointed right
				{
				right_state = DR_RIGHT;
				}
			else if (right_servo_set < RIGHT_GOAL)     // Right servo pointed left	
				{
				right_state = DR_LEFT;
				} 
			else
				{
				right_state = DR_CENTER;
				}

			// Now find out the drive state
			if (left_state == DR_LEFT && right_state == DR_LEFT)
				drive_state = DR_BOTH_LEFT;
			else if (left_state == DR_RIGHT && right_state == DR_RIGHT)
				drive_state = DR_BOTH_RIGHT;
			else if (left_state == DR_RIGHT && right_state == DR_LEFT)
				drive_state = DR_BOTH_CENTER;                    // At goal
			else if (left_state == DR_CENTER && right_state == DR_CENTER)
				drive_state = DR_BOTH_STRAIGHT;
			else if (left_state == DR_CENTER)
				drive_state = DR_LEFT_STRAIGHT;
			else if (right_state == DR_CENTER)
				drive_state = DR_RIGHT_STRAIGHT;
			else
				drive_state = DR_REFLECTION;         // Impossible angle, but could happen

		
			drive_timer = 0;    // As long as we see the target keep driving
			
			//  Drive logic starts here
			switch (drive_state)
				{
				case DR_UNDEFINED:
					{
					// We should not be able to get here
					printf("DR_UNDEFINED

");
break;
}
case DR_BOTH_LEFT:
{
// Go straight until we pass the target
if (Navigator_State == DRIVE_TO_TARGET)
{
// Don’t turn left
left_drive_set = SFWD;
right_drive_set = SFWD;
}
else
{
// We are in PASSED_TARGET state
// Turn left
left_drive_set = SBWD;
right_drive_set = SFWD;
}
if (left_servo_set < LEFT_PASS)
{
Navigator_State = PASSED_TARGET;
printf("PASSED_TARGET
");
}
break;
}
case DR_BOTH_RIGHT:
{
// Go straight until we pass the target
if (Navigator_State == DRIVE_TO_TARGET)
{
// Don’t turn right
left_drive_set = SFWD;
right_drive_set = SFWD;
}
else
{
// We are in PASSED_TARGET state
// Turn right
left_drive_set = SFWD;
right_drive_set = SBWD;
}
if (right_servo_set > RIGHT_PASS)
{
Navigator_State = PASSED_TARGET;
printf("PASSED_TARGET
");
}
break;
}

				// The beacon is ahead in all these cases so just drive
				case DR_BOTH_STRAIGHT:
				case DR_LEFT_STRAIGHT:
				case DR_RIGHT_STRAIGHT:
				// Note: we don't know what to do here but we might as well keep
                // going. 
				case DR_REFLECTION:
					{
					// Find the error from ideal on each side
					left_error =  (int)LEFT_GOAL - (int)Tracker_Data[LEFT].Position;
					right_error = (int)Tracker_Data[RIGHT].Position - (int)RIGHT_GOAL;

					// Scale the error
					left_error *= DRIVE_GAIN;
					right_error *= DRIVE_GAIN;

					// Use these if you want fractional gain values
					// Be sure to comment out the above gain lines
//					left_error /=  DRIVE_GAIN;
//					right_error /= DRIVE_GAIN;

					// Make sure the errors are in range
					if (left_error &gt; (255 - SFWD)) left_error = 255 - SFWD;
					if (right_error &gt; (255 - SFWD)) right_error = 255 - SFWD;
					if (left_error &lt; -SFWD) left_error = -SFWD;
					if (right_error &lt; -SFWD) right_error = -SFWD;
	
					// If we are pointed left, drive the right drive faster and vice versa
					// Use the next two lines to turn toward the goal

// left_drive_set = SFWD + right_error;
// right_drive_set = SFWD + left_error;
// These two lines keep driving straight
left_drive_set = SFWD;
right_drive_set = SFWD;

// printf("Lerr = %d Rerr = %d
",left_error,right_error);
// End of drive logic
break;
}
case DR_BOTH_CENTER:
{
Navigator_State = AT_TARGET; // Both servos are within the target threshold
printf("AT_TARGET
");
break;
}
}
}
else
{
// We are not locked on - Stop
// give the trackers a chance to catch up
left_drive_set = LSTOP;
right_drive_set = RSTOP;
drive_timer++ ;
if (drive_timer > LOST_TARGET_TIMEOUT)
{
Navigator_State = TURN_TO_TARGET;
printf("TURN_TO_TARGET
"); // Done driving to center
left_servo_set = 127;
right_servo_set = 127;
}
}
break;
}
case AT_TARGET:
{
// We are at the goal - Stop driving
left_drive_set = LSTOP;
right_drive_set = RSTOP;
break;
}
default:
{
left_drive_set = LSTOP;
right_drive_set = RSTOP;
printf("Not a valid state
");
break;
}
}

// Send all the control values to the pwm controller

//printf("Left = %d Right = %d
", (int)left_drive_set, (int)right_drive_set);

left_servo = left_servo_set;
right_servo = right_servo_set;
left_drive = left_drive_set; 
right_drive = right_drive_set; 

// left_drive = 255 - left_drive_set; // This drive is reversed
// right_drive = 255 - right_drive_set; // This drive is reversed

Old_Clock = Clock; // take a snapshot of the clock
}

}

//PLEASE HELP ME IF YOU CAN!!!****

Post the output of the compiler where it gives the error - right now we don’t even know which lines to be looking at!

Sorry… here it is:

Deleting intermediary files… done.
Executing: “C:\mcc18\bin\mcc18.exe” -p=18F8520 “ifi_startup.c” -fo=“ifi_startup.o” /i"C:\MCC18\h" -D_FRC_BOARD -O-
Executing: “C:\mcc18\bin\mcc18.exe” -p=18F8520 “ifi_utilities.c” -fo=“ifi_utilities.o” /i"C:\MCC18\h" -D_FRC_BOARD -O-
Executing: “C:\mcc18\bin\mcc18.exe” -p=18F8520 “main.c” -fo=“main.o” /i"C:\MCC18\h" -D_FRC_BOARD -O-
Executing: “C:\mcc18\bin\mcc18.exe” -p=18F8520 “navigate.c” -fo=“navigate.o” /i"C:\MCC18\h" -D_FRC_BOARD -O-
H:\Working on it\Robot
avigate
avigate.c:367:Error [1105] symbol
Halting build on first failure as requested.
BUILD FAILED: Wed Mar 24 09:46:42 2004

//Hope that will allow u to help me!

Here’s what I found in the users guide:

1105: symbol ‘%s’ has not been defined
A symbol has been referenced before it has been defined. Common causes
include a misspelled symbol name, a missing header file that declares the
symbol, and a reference to a symbol valid only in an inner scope.

On the error line when you compile, is there something after the word ‘symbol’? (i.e. did it not get pasted to CD right, or does it just not show up?)

I pasted your code into an editor and it looks like line 367 is “if (drive_timer > LOST_TARGET_TIMEOUT)”, is that correct? If so, can you show us the section from the header file that defines “LOST_TARGET_TIMEOUT”?

That was all there was in the compile box and I posted the whole .c file; is there a different file that you want to see??? :confused:

1- use the

 tag.
2- Is this a file you wrote/modified?
3- Is there a Navigate.h? that might be what he is talking about.
4- Did you write this code?

Hi,

He’d like you to post your Navigate.h header file, to look at how LOST_TARGET_TIMEOUT is defined…if that is where it is defined.

You could also do a search, through the folder that you have your code in, to see if it turns up anywhere. If not, then the you’ve found your error :cool:

Eric Schreffler

Or, in MPLAB, Project>Find in Project files… and type in “LOST_TARGET_TIMEOUT” (w/o quotes). in the Output window, see where it comes up.

Dave’s right, the compiler is complaining about line 367:

if (drive_timer > LOST_TARGET_TIMEOUT) 

But the compiler output appears to be truncated. It’s supposed to tell you what name it doesn’t recognize. There might be an invisible character in the source file on that line, which the compiler would choke on and be unable to display. The easiest thing to do at this point would be to duplicate the line, character by character, without doing a copy/paste, then delete the original line and try compiling again.

If that doesn’t help, then show us the section of the header file where LOST_TARGET_TIMEOUT is defined (probably in navigate.h).

(Oh, and next time you need to post programs here, surround it with CODE] and /CODE] so the formatting is preserved.)

This C stuff is new to me, but the { }'s around line 367 I can’t figure out if they all make sense, I think you may have some that are unmatched. Hope this helps

Oh, my. There’s certainly something odd going on:


case DR_BOTH_CENTER:
{
    Navigator_State = AT_TARGET; // Both servos are within the target threshold
    printf("AT_TARGET
");
    break;
}
}
}
    else
    {
        // We are not locked on - Stop
        // give the trackers a chance to catch up
        left_drive_set = LSTOP;
        right_drive_set = RSTOP;
        drive_timer++ ;
        if (drive_timer > LOST_TARGET_TIMEOUT) 
        {
            Navigator_State = TURN_TO_TARGET;
            printf("TURN_TO_TARGET
"); // Done driving to center
            left_servo_set = 127;
            right_servo_set = 127;
        }
    }
    break;
}

There are three **}**s in a row right before a naked else statement. This source code is apparently missing a few lines, including an if.

There is also a case statement commented out near the top of the big switch. That can’t be doing what you want, can it? If you want to “skip” that state, as the comments suggest, I think you need to initialize your state variable to DRIVE_TO_CENTER instead of WAIT_TO_DRIVE in line 37.

Looks weird, but I think they match up.
357 matches to 353 (case DR_BOTH_CENTER)
358 matches to 258(switch drive_state)
359 matches to 207(if Tracker_Data…)

I think that you’re onto something with that commented case at line 131. That’s definately not right

I used a Diff program to compare the code posted with my navigate.c, and there is no differences in the vicinity of the error line which should cause an error. (If there were any unprintable characters, the diff program should have told me.)

Is LOST_TARGET_TIMEOUT defined in your navigate.h? (It is in mine. It’s at line 147: #define LOST_TARGET_TIMEOUT 100)

I believe the three braces are OK. If you move your cursor in turn to each of those braces and type Ctrl-M, the editor will take you to their matching opening braces. They look fine to me.

As to the commented out case label, THAT does look strange, but I highly doubt that would cause the compile error in question. I don’t know what the compiler will do with a chunk of code inside a switch statement without a case label. My guess is that it will simply be unreachable.

When compiling with GCC, and an unmodified navigate.h, I only get one warning “warning: unreachable code at beginning of switch statement” So, the braces do all line up, and that commented out case caused a warning. It’s possible that the problem is with that, and CrashZero should comment out that whole block. However, I would think that it’s more likely that something was modified in navigate.h

indent…indent…indent

Okay, I see the if and the nested switch now. The lost formatting of the post made it darn near impossible for me to tell what the structure of the code was supposed to be. (By the way, Ctrl-M just adds a new line when I type it.)

If the trouble is with an unprintable character in the source code, the problem character probably wouldn’t have survived being pasted here. But I believe that the definition of LOST_TARGET_TIMEOUT in navigate.h is a likely culprit and should be investigated.

Are you using the MPLAB IDE? I don’t think I did anything special to enable this functionality. It’s also on the “Edit” menu: “Match”.

Um, no. I’m using Internet Explorer. :rolleyes: I’m not anywhere near the computer we use to program the robot – in fact, it’s halfway to Chicago at the moment. I interpreted your mention of “the editor” as referring to viewing the HTML source of the page, where at least a little of the c file’s formatting seems to be visible.

well here is the navigate.h file:


/*******************************************************************************
*
*	TITLE:		navigate.h 
*
*	VERSION:	1.0                          
*
*	DATE:		08-Jan-2004
*
*	AUTHOR:		Richard D. Petras
*
*	COMMENTS:
*
********************************************************************************
*
*	CHANGE LOG:
*
*	DATE         REV  DESCRIPTION
*	-----------  ---  ----------------------------------------------------------
*	03-Dec-2003  0.1  
*   08-Jan-2004  1.0  RDP The version used at the 2004 kickoff
*
*******************************************************************************/
#ifndef _navigate_h
#define _navigate_h

#include "tracker.h"

// Navigator state machine values
// These values will be stored in a global variable called 
// Navigator_State.  As each state transition is detected,
// the state will change to describe how the vehicle should
// operate.
#define WAIT_TO_DRIVE 0
#define	DRIVE_TO_CENTER 1
#define	TURN_TO_TARGET 2
#define	DRIVE_TO_TARGET 3
#define	PASSED_TARGET 4
#define	AT_TARGET 5
#define OVER_CURRENT 6

// Drive state 
// These values are stored in the drive_state variable.  They tell
// us where the beacon is with respect to each tracker on the robot.
#define DR_UNDEFINED 0
#define DR_BOTH_LEFT 1
#define DR_BOTH_RIGHT 2
#define DR_BOTH_STRAIGHT 3
#define DR_BOTH_CENTER 4
#define DR_LEFT_STRAIGHT 5
#define DR_RIGHT_STRAIGHT 6
#define DR_REFLECTION 7

// Some values for each individual tracker
#define DR_LEFT 0
#define DR_CENTER 1
#define DR_RIGHT 2

// Which pwms are our tracker servoes and drive motors?  It
// is nice to only have to change this in one place.
#define left_servo pwm10
#define right_servo pwm11
#define left_drive pwm14 
#define right_drive pwm15

// Simplify the big structure for beacon quality
// from the tracker code.
#define LL Sensor_Stats[0].Beacon_Quality[Tracker_Data[LEFT].Beacon_Type]
#define LR Sensor_Stats[1].Beacon_Quality[Tracker_Data[LEFT].Beacon_Type]
#define RL Sensor_Stats[2].Beacon_Quality[Tracker_Data[RIGHT].Beacon_Type]
#define RR Sensor_Stats[3].Beacon_Quality[Tracker_Data[RIGHT].Beacon_Type]

// The rest of these defines are tweekable parameters to fit
// the characteristics of different drive trains.  You might
// want to divide these into a separate set of values for the
// left and right side drives if your motor characteristics
// are sufficiently different.  This would require changing
// navigator.c, but the places to make the changes should be 
// obvious. :-)

//  Stop values
#define LSTOP 127      
#define RSTOP 127

// Fast backward
#define FBWD (LSTOP - 90)

// Slow Backward
#define SBWD (LSTOP - 55)

// Very Slow Backward
#define VSBWD (LSTOP - 10)

// Very Slow Forward
#define VSFWD (LSTOP + 10)

// Slow Forward
#define SFWD (LSTOP + 55)

// Fast Forward
#define FFWD (LSTOP + 90)

// Note: All the logic assumes the servo max points right
// Its not too hard to change the code to accomidate the other
// direction, in fact the code started out that way...

// These values are the servo settings (assuming 127 is straight
// ahead) that tells you that the beacon is between the trackers
// and about 1/2 meter ahead.  The exact values will depend on the
// baseline of your trackers.
#define LEFT_GOAL 135
#define RIGHT_GOAL 120

// These values tell you when the target is far to the left of the
// left servo, or far to the right of the right servo.  We switch
// navigator states at this point
#define LEFT_PASS 60
#define RIGHT_PASS 195

// Adjust these for your drive train

// This is the gain that is multiplied by your pointing error.
// It can be used as part of a feedback loop to steer toward the
// goal.  Note: the error calculation is included in the code
// as an example, but was not used in the actual kickoff demo.
// (we wanted to drive straight until we passed the goal)
#define DRIVE_GAIN 2

// This is a timer for the short drive away from the wall before
// we startt to turn in place toward the beacon.
#define DRIVE_TO_CENTER_TIME 5

// I bet you didn't know we were using the current sensors in the
// kickoff demo.  If the current sensor reading got above this 
// value, we might be up against the wall.  In that case we might
// want to stop driving for a short time to allow the robot to level 
// out.
#define MAX_CURRENT 700


// If we haven't seen the target with any of the trackers for 
// a while,  just start searching again by turning in place.  
//#define LOST_TARGET_TIMEOUT 100

// Declaration for the Navigate function
void Navigate(void);

#endif // _navigate_h