Writing the Code

In the past I've used MikroElektronika's free C compilers for writing the code for my PIC18 projects. Recently I've been developing some dsPIC33 code and found that the new MikroElektronika compilers for that processor were still a bit buggy. I decided to switch to the compilers offered by Microchip.

I think that the MikroElektronika compilers are a bit easier to use but on the other hand they limit you to 2K of code with the free version. It's generous but a bit limiting. For this project I thought I would hit the limit so I decided to try the Microchip C18 compiler.

Driving the Servos

First off we need to produce nice clean pulses for the servos. I used TIMER1 in conjunction with a comparator to generate interrupts for the beginning and end of pulses. There are three states in which the servo code can be.

0 - start servo A pulse; increment state
1 - stop servo A pulse and start servo B pulse; increment state
2 - stop servo B pulse and start a pause; state = 0

At state 2 I also begin the A/D conversions. These should finish before the pause finishes.

A/D Conversions

The two phototransistor sensors are attached to AN0 and AN1. The trimmer potentiometer that I use for zeroing the motion of the servos is attached to AN6. Each time an A/D conversion is finished, an interrupt occurs. There are 5 states for the A/D.

0 - measure downward facing line sensor; increment state; start next conversion
1 - measure forward facing range sensor; increment state; start next conversion
2 - measure trim potentiometer; start next conversion
3 - measure downward facing line sensor with LED; increment state; start next conversion
4 - measure forward facing range sensor with LED; increment state

After state 4, the A/D conversions will cease. They'll restart in state 0 once the next two servo pulses have been produced.

As the A/D conversions are completed, the code will populate a number of variables that will signal light levels and changes in light levels. These will be used by the AI code.

Bumpers and Mode Buttons

The three buttons are attached to INT0, INT1 and INT2. Each of these lines causes an interrupt when the lines are pulled low. I never got around to using the two bumpers as bumpers. Instead I use these to select servos during calibration mode. The mode button selects between the different behaviours of the robot. As is, the code supports three modes. When changing modes I blink different LED's.

Status LED's

There are four LED's on the robot. One is hardwired to 5V via a 220 ohm resistor. The others are tied to digital I/O lines on the PIC. I flash the LED's to signal mode changes; A (bottom left) - Line Follower, B (top left) - Sumo, C (bottom right) - Follower. The A and B LED's also blink when the bumpers are hit.

Calibration Mode

The modded servos are unlikely to remain motionless at exactly a 1.5 msec pulse. Entering calibration mode allows us to adjust the servo pulse lengths to zero any residual servo motion. You enter calibration mode by pressing the mode button until all three LED's, A, B and C blink on and then off.

To zero the motion of the left servo press the left bumper switch. Now adjust the trim potentiometer until the servo is motionless. Press the left bumper again to store the trim value in the EEPROM. Press the right bumper to zero the right servo. Adjust the trim potentiometer until the servo is motionless. Press the right bumper again to store the trim value in the EEPROM.

Each of the modes waits for the range sensor to report a NEAR object before starting. This allows the robot to wait until you're ready for it to start.

In line follower mode, the robot first tries to find a line by spinning in place. If no dark-to-light transition (LIGHTEN event) is sensed, it goes back to sleep waiting for another NEAR signal.

If a LIGHTEN event occurs, the robot switches direction and follows a forward moving curve. Unless the line curves aggressively, the robot's line sensor should cross the line again. Again there is a LIGHTEN event and the the robot switches direction. This basic loop repeats until the line is no longer sensed.

Once the line is lost, the robot will perform one more spin and if nothing is found it'll go to sleep.

In Sumo mode, the robot uses the line sensor to keep it within a black ring. The range sensor is used to hunt the targets so they can be pushed from the ring.

The robot is always looking for a DARKEN event on the line sensor. This signals that the robot is about to drive out of the ring. When this event is detected, the robot turns some large angle before resuming it's normal behaviour.

Normal behaviour is to follow a meandering path through the ring. If an object is sensed far away (FAR reading) the robot will move toward it. If the signal is lost, the robot will hunt left and right trying to find it. If the object is close (NEAR reading) the robot will rush straight ahead hoping to push it from the ring. This trusts that the line sensor will keep the robot from exiting the ring.

Finally, in Follower mode the goal is to have the robot follow an object like a finger..

Normally, the robot will sit quietly. When a NEAR signal is detected, the robot will move toward it. If the signal is lost, the robot will hunt left and right trying to find it. It will remember which direction worked last time and search that direction first the next time the signal is lost. This will allow someone to lead the robot around using their hand.

If the target gets too close, the robot stop.

Here's the current hex code for the robot. The source code for the C18 compiler from Microchip is available as a zip file. I used a Pickit 2 to program the PIC18F1320 chip. I found that in my case, the chip would only program correctly at 3.3V. Since the battery pack has a higher voltage I had to use a bench supply during programming.

Have fun. If you come up with interesting behaviours drop me a line.

Next Section: Projects