Wall Following RC car using 16F887

Here are two videos of my hobby level radio control car following the wall around a room.  This car uses channel 3 of the radio control system to toggle between RC control and autonomous control.

http://video.yahoo.com/watch/7184507/18716445

http://video.yahoo.com/watch/7169550/18673820

The idea is to hook middle school kids (USA grades 7th and 8th.  ages 11 - 14) into Science, Technology, Engineering and Math.  This offers the speed and excitement of RC car
 racing, the trial and error of RC race car design plus the clear thinking and discipline of computer programming.

 
 THE COMPETITION:  A car race.

 Build an oval race track on a polished wooden gymnasium floor defined on the inside by
 cardboard boxes large enough to echo back a SRF05 sonar proximity detector's signal.

 The race is to lap the track, say, six times;  three by radio control;  three by autonomous control.  Either time trials or multiple cars at the same time.  If the race has multiple cars on the track at one time, some more work must be done on the car to avoid collision.

  I will design and build a PIC kit that attaches to almost any RC car that has Electronic Speed Control (ESC) driving the wheels and a servo driven steering mechanism.  It will use the car's 7+ volt battery, knocked down to 5 volts by the ESC.  There must be a third channel on the RC system to tell the car who is boss.

 I need to borrow, steal, or design a microcontroller programming language that forces the students to think about the signals from the front and side facing sonars and create the corresponding commands to the wheels and the steering.  Presently the 16F887 compiler runs on a WINDOWS PC and communicates to the car via special hardware connected to the USB port.  (Available from MicroChip Inc.)

----------The post below seems to be way ahead of me----------

Author: bendjamin
| Title: I made some similar robots a

I made some similar robots a while ago.  I'll try and post a video of them.  They are designed to race around a track, in other words they are doing wall avoiding so when you make a track with walls on the inside and outside they will go around and around.  I made the robots myself, they are differential steering with a body made from laser cut polycarbonate.  I used the sharp IR rangefinders for navigation and have four on each robot, two forward facing and two side facing. They also have four bumber switches, one pair in front and the other at the rear.

| Link: https://www.robotshop.com/letsmakerobots/node/696#comment-43464

What do you all think?

 Ken

 

https://www.youtube.com/watch?v=4oFTzyMuSjA

Sounds like a very cool

Sounds like a very cool project, and for a noble cause too.

Considering the age of your prospective students, I wonder if PICBASIC might be a solid choice for a convenient language? It’s easy to read and write, still offers a good amount of control and complexity, and there are many BASIC language compilers available for PICs. Unfortunately I can’t suggest which compiler to go for, since I stick to Assembly and C myself, but I know there are other projects here on LMR that have used different forms of BASIC to program PIC micros with great success.

Been thinking that a good

Been thinking that a good middle school STEM hook would be simple racing on an oval indoor (gymnasium basketball court) track delineated by large cardboard boxes (big enough to be detected by the SRF05 sonar proximity detectors) on the inside. I imagine a ten lap race. For six laps the kids control the cars with their radio transmitters. For four laps the cars are autonomous.

I think I can design a PBP template that would make coding the PIC reasonably simple. The template would contain the code state machine. The students’ job would be to choose the steering/wheels commands associated with each state.

I have a question for you all.

If I were to add a black tape line around the track, what electronic gimmick might I put on an RC car to make it into a line follower? Is there a commercially available light source and photo cell combo similar to the pre-canned SRF05 sonar device?

On the subject of compiler-of-choice, I am using PICBASIC PRO.  It is expensive.  C comes for free from MIcroChip as part of a  PICkit 2 purchase. I don’t think I should worry about cost right at the moment.

Ken

There are several free

There are several free PICBASIC IDEs around too, GCBASIC, MicroCode, Proton, etc.

There are some nice IR reflectance units such as the QRD1114 that only require 2 extra resistors, but if you want a completed unit similar to the SRF05 you could go for something like this or this from SparkFun. The first sensor board is a nice simple digital output board (low signal = high reflectance), while the second sensor requires you to set the signal line to output a high signal to charge the onboard capacitor, and then you set the line back to an input and measure the time it takes for the signal to go low again (shorter time = higher reflectance). The first sensor is naturally easier to use, while the second allows for an analog value to be determined for the reflectance, so you can actually calibrate the sensitivity.

Sorry Old Man!

Sorry Old Man! But hooking kids on drugs is safer than this…

I have a serious timing problem…

I keep saying that my RC car is meant to be a race car while being autonomous. Struggling to find its way around a room is not the demo that I want. I think an oval track in the gym bounded on the inside by many cardboard boxes at least a couple feet high. The kids with the RC transmitters must sit still in the lower seats of the roll out stands. The cars would be out of their sight when on the far side of the track.

My serious problem is that as a race car driver my 16F887 is not doing very well. It does not query the SRF05s quickly enough. The trigger pulses get to the sonars about one per second.

I am at a loss to figure what is consuming all the PIC compute time.

QUESTION? What would be the easiest, most efficient way for me to get on board with Assembly Language 16F887 coding? Machine language is not new to me. I used it professionally till somewhere in the 1980’s.  What is a clear and complete document on this ASM?

Ken

progress.gif

edit.gif

Things have been going better.

I have not yet had to fall back on ASM code.

I did discover:

1. My PIC was resetting because of regressive subroutine calls. Changing a couple GOSUB’s to GOTO’s solved that.

smile.gif



2. My car was not being driven smoothly because of occasional zero responses from the SRF05’s (or at least one of the SF05’s). Implementing a - check again if the sensor says zero - routine after polling the sonar sensors smoothed things out.

biggrin.gif



I did notice that adding an IF THEN statement to the PBP code increased the size of the HEX code considerably. I still feel I need to understand the two compile processes.

frown.gif

Frustration, thy name is trying to go faster…

Not going well at all.

When I up the speed the car does not respond quickly enough.  At a corner Instead of seeing (hearing) ahead and turning, it crashes into the on coming wall, backs up, and tries again. Part of my problem is not  understanding the machine language code behind the PICBASIC PRO commands.  Another part is the PIC getting into little loops or resetting and thereby ignoring the real time signals.  Lastly I need to expand the distances to which the code reacts.  If the velocity is greater, it must start turning or braking sooner.

On the bench, the machine seems to behave as expected, but on the race track.  NOPE.

Ken

Hi Ken, good to hear you

Hi Ken, good to hear you have been making progress. Would you be able to post your PICASIC code for us to have a poke at?

I think your problem is seeing what happens when

What I would do:

First; Make a version that goes so much slower; Drive slower, and make things work, then gradually speed up.

Second; when problems arise only at higher speeds:

Add a speaker, or a bright LED to the robot.

When the turning should happen, make this beep or flash.

Film it.

Analyze; The LED or Sound will make it possible to see excactly at what distance to the wall the action is taken, and you can make slow motion and watch them. Question will be; At the speed & weight it has, is it even physical possible to turn and avoid?

PS: If it turns out that

PS: If it turns out that everything works at lower speeds, but the robot seams to react later at higher speeds, it may be because your sampling frequency is too low.

If you only measure distance at say 2 times pr second, it does not matter at low speeds where you have only moved 20 cm between, but is a problem at higher speeds, where it could be 2 meters.

Yes, I will post my code, but

I have been distracted.  Folks in another forum suggested that I up the effective oscillator to 8Mhz.  This made three things not work.

1.  HPWM command is throughly confused.  For good reason.  The Electronic Speed control wants pulses less than 2ms at a rate of 50 per second.  HPWM does not really do that.  I think I must go to interrupt driven code to be true to the spec.

2. PULSIN and recognizing the PWM input from Channel 3 which tells the car to toggle between PIC control and radio control.  The threshold needed adjusting (doubling for the twice as fast oscillator).

3. Interpreting the information in the echo response pulse from the SRF05’s needed adjusting as well as timing the 10usec trigger pulse.

Once I clean up the mess this change made, I’ll post what I have.

Thank you for asking.

Ken

Here is my code.

Is it OKAY to post code in this manner?

Sorry I can’t make the commands stand out like they do on

the MicroCode Studio page.

-------------start snip--------------16F887 PICBASIC PRO code–

symbol trigright = PORTB.0 ’ Define output pin for Trigger pulse
symbol trigfront = PORTB.1 ’ Define output pin for Trigger pulse

symbol echoright = PORTC.6 ’ Define input pin for Echo pulse
symbol echofront = PORTC.5 ’ Define input pin for Echo pulse

SYMBOL channel3 = PORTC.4  ’ Define input pin for Channel 3 PWM
TRISC = %11110000
’OSCCON = %01100001 ’ 4mhz clock - default
’define OSC 4 ‘not needed but does no harm
CNT  VAR BYTE

’------------
                   
b0 var word
rangeright var word
rangeright = 100
rangefront var word
oldrangeright var word
differencerangeright var word
frontfreetostopreverse var word
reversecount VAR WORD
reversecount = 0
switchtoPIC VAR WORD
switchtoPIC = 1
radiocontrol var word
radiocontrol = 0


symbol frontdanger = 500 ’ is about 34 inches. We
'realize we are getting too close. Back up. (note that breaking
‘takes a lot, so this should be much higher than the real distance)

symbol frontfreetostopreversesetup = 502’  must be
'higher than “frontdanger” - higher value means more
‘backing out after close encounters

symbol frontfree = 600’ is about 40 inches.
'I set higher to turn earlier when something is in front
’fritsl says it get less skid-turning,
'but more likeliness to miss sharp right turns.  My racing
’model has no sharp right turns.

symbol desiredtrack = 360 ’ about 24 inches.
symbol outertrack = 600 ‘about 40 inches


HPWM 1,100,50     ’ Straignt discovered by experiment.
                    ’ slow to center at 100

’--------start----------
gosub blinkloop01  ‘This delay is to let me get ahead of the car.
‘portd = %00000000
low portc.0        ’ Set up initially as PIC control

’–Beginning run–
’ Steering already straight.  Make wheels 1/2forward.

 
main:
hpwm 2,113,50   'WheelsHalfForward
oldrangeright = rangeright

aftermain:
gosub puls
gosub RCcontrolsense
  if switchtoPIC > 150 then
  'radiocontrol = 1
  gosub MakeRadioControl 
  else
  'radiocontrol = 0
  gosub MakePICControl
endif

goto skidandreverse

goingforward:                         
frontfreetostopreverse = frontfreetostopreversesetup

’Here we are going forward.
if rangefront < frontfree then 'turn left as there is
'something ahead in front
HPWM 1,70,50 'SteerFullLeft
goto aftermain 'this is second priority above all loop till this is secured
endif

if rangeright > outertrack then 'turn right as we are too far away
Hpwm 1,110,50    'SteerQuarterRight
’gosub  SteerQuarterRight
endif

if rangeright < desiredtrack and oldrangeright < rangeright then
hpwm 1,100,50   ‘SteerStraight
’ drive straight forward as we are on the wrong
'side of desired track, but we are moving the right direction
endif
 
if rangeright > desiredtrack and oldrangeright > rangeright then
hpwm 1,100,50   ‘SteerStraight
’ drive straight forward as we are on the wrong
'side of desired track, but we are moving the right direction
endif

if rangeright > desiredtrack and oldrangeright < rangeright then
Hpwm 1,110,50   'SteerHalfRight
’gosub SteerHalfRight  'turn right as we are in the outer lane and getting away
endif

if rangeright < desiredtrack and oldrangeright > rangeright then
’if rangeright < desiredtrack then
HPWM 1,85,50 'SteerHalfLeft
’gosub SteerHalfLeft  'turn left as we are in the inner lane and getting closer
endif

goto aftermain



’Skidright:   'Nothing calls this subroutine
’gosub blinkloop7
’b0 = 0
’while rangefront > frontfreetostopreverse and rangeright > outertrack and b0 < 20
’gosub puls
’b0 = b0 +1
’wend

’low forrev  'set in forward gear
’hpwm 2,112,50 'WheelsHalfForward
’gosub WheelsHalfForward
’pause 300 why did I put in this pause?
'return



reverseoutoftrouble:
'hpwm 2,100,50 'WheelsStop 
HPWM 1,140,50      'SteerFullRight 
HPWM 2,92,50  'WheelsHalfBack
Pause 100


go_reverse:
frontfreetostopreverse = frontfreetostopreversesetup

keepreversing:
frontfreetostopreverse = frontfreetostopreverse - 25
’Making sure we are not backing and reversing and going
‘nowhere, as we have a wall behind us.

if frontfreetostopreverse < 50 then
goto stuckerror
endif

gosub puls

if rangefront < frontfreetostopreversesetup then
’ We have not reversed far enough

   if rangeright < desiredtrack and oldrangeright < rangeright and rangefront > frontdanger then
   hpwm 1,110,50  'SteerQuarterRight
   ’ Going backwards.  On the correct side.
   'Moving away the wall.  Turn right to get parallel with the wall.
   'gosub puls
   'goto go_reverse
   endif

   if rangeright > desiredtrack and oldrangeright > rangeright and rangefront > frontdanger then
   hpwm 1,100,50 'SteerStraight
  ''Going backwards.  On far side of desired track. Moving
   ''towards the wall. Go straight.
   endif

   if rangeright > desiredtrack and oldrangeright < rangeright and rangefront > frontdanger then
   hpwm 1,110,50  'SteerQuarterRight    
   'Going backwards.  On far side of desired track.  Moving
   'away from the wall. Steer to get back on desired track.
   endif

   if rangeright < desiredtrack and oldrangeright > rangeright then
   'Going backwards. On correct side of desired track. Moving
   'toward the wall.  Steer left to get parallel to wall.
   hpwm 1,80,50 'SteerQuarterLeft
   endif

   goto keepreversing

   'hpwm 2,100,50 'WheelsStop
   ‘Pause 500
 endif ’  This refers back five “IF’s” ago. It means
’ it is time to stop reversing and try going forward.
Hpwm 1,70,50  'SteerFullLeft
hpwm 2,112,50 'start going forward again.
goto aftermain 'was RETURN ‘from gosub to reverseoutoftrouble.  There is
’ no gosub there.


'

skidandreverse:

if rangefront < frontdanger then ’ too close
goto reverseoutoftrouble
goto aftermain ’ this is first priority above all - loop till this is secured
endif
goto goingforward

********

puls: ’ produce 10uS trigger pulse (must be minimum of 10uS)
low trigright
HIGH trigright
PAUSE 1
LOW trigright
’measures the range in 10uS steps
’zero could be legal here
pulsin echoright,1,rangeright ’ measures the range in 10uS steps

pulsf:  ’ produce 10uS trigger pulse (must be minimum of 10uS)
low trigfront
hIGH trigfront
PAUSE 1
LOW trigfront
pulsin echofront,1,rangefront ’ measures the range in 10uS steps
if rangefront = 0 then goto pulsf
return

RCcontrolsense:
define pulsin_max 10000
PULSIN channel3,1,switchtoPIC
return


stuckerror:
HPWM 1,100,50 'SteerStraight
hpwm 2,100,50 'WheelsStop


dadaa:
high portd.6
pause 5000   'Indicates trouble.
'RCControl or PICControl pulse sensing.  Prefer RCControl if stuck.
PULSIN channel3,1,switchtoPIC
if switchtoPIC > 150 then
radiocontrol = 1
gosub MakeRadioControl 
else
radiocontrol = 0
GOSub MakePICControl
’PORTD = %00000000
endif
goto aftermain
’goto dadaa

MakeRadioControl:
high portc.0
return

MakePICControl:
low portc.0
RETURN

blinkloop01:
FOR CNT = 1 TO 5
HIGH PORTD.0
LOW PORTD.1
PAUSE 500
LOW PORTD.0
HIGH PORTD.1
PAUSE 500
NEXT CNT
RETURN

blinkloop6:
'PORTD = %00000000
HIGH PORTD.6
PAUSE 500
LOW PORTD.6
RETURN


Difference between HPWM and electronic speed control spec.

The Electronic Speed Control wants this PWM signal to arrive at 50 hz.

I was not clear in my last posting. The Electronic Speed Control PWM specification is for a single positive pulse no less than 1ms and no more than 2ms once per 20 ms, ie 50 pulses per second. The one to two millisecond pulse width is divided into 256 parts. 1.5 ms corresponds to 128 which corresponds to neutral in a servo.

Neutral is steering straight on a steering servo. Neutral is stopped on a wheel driving servo.

I discovered that using HPWM with the 4mhz default oscillator a pulse width of 100 to 110 gets the behavior of ‘neutral’ on my car. For example “HPWM 1, 100, 50” turns the front wheels of my car to straight. See the attached picture. Channel 2 is the HPWM version of neutral. Channel 3 is what the radio receiver sends.

I’ve got it responding better…

Turns out that one of my problems has been the length of the trigger pulses that I have been sending the SRF05s.  They were too long using PAUSE 1 with the 4mhz oscillator.

I changed the technique to the following:

SYMBOL trigright PORTD.0

LOW trigright

HIGH trigright

HIGH trigright

LOW trigright

With this technique I can make positive pulses as short as 10usec and grow them in units of the HIGH command…

Ken

Latest adventure with speed.

I now have the sonic ping devices (SRF05’s) flashing continuously.  This means that there is no blockage in the PIC’s processing.

Now the car is reacting too quickly. There is a bit of code that used to guarantee a 1/2 second backing up when backing up was necessary.  Now the count down for this delay is instantaeous.   While turning a corner the proximity sensor data gets confusing.  Both the side sensors and the forward sensors are hearing important echos.   I might need to adjust the positions of the two SRF05’s.  I am not sure…

 

Ken

Is there a cover for this car?

Is there a cover for this car? Or did you bust it up already?

I have the cover, but

I have the cover for the car, but I have not put it on because all my circuitry is in  the prototype stage.

Once I get a vehicle that really races I will purchase a different radio transmitter - one with a pistol grip that has three channels.  I will also select a new car or truck.  I need to neaten up my prototyping system so that it will fit on most any chassie.  That plus the PICkit 2 might do the trick.

Since the system is running

Since the system is running so much faster now, maybe you can afford to add a delay between when the front and right SRF05’s run their detection subroutine? It wouldn’t have to be a ‘dumb’ delay where you just waste cycles, but instead you could for example run ‘puls’ in one iteration of the main loop and then run ‘pulsf’ in the next iteration, just to give the SRF05’s a bit of breathing room so they don’t interfere with each other.

As the car speeds up the problems change.

Here is a video of my car on my version of a race track.

It works some times and not other times.  It seems that as the speed increases something is becoming less sensitive.  Maybe the reactions are too slow, but that should be fixable.

http://www.youtube.com/watch?v=bx8KKDknAx0