Let's Make Robots!
start-here.asm15.6 KB
StartHere.wmv979.85 KB

Presented here is my rendition of the Start Here robot using a PIC16F690 and programmed in Assembly with the MPASM Assembler. 

In addition to the micro, parts include (approx price paid in US dollars):

Texas Inst SN754410 H-bridge   $2.35
Solarbotics GM6 gear motors  $5.75 (x2)
RC airplane wheels  $2.00
Sharp GP2Y0A21YK proximity sensor w/ JST connector   $17.00
T Pro SG90 servos   $3.00 (x2)

The base is made of styrene and the caster is a cabinet knob.  Other miscellaneous parts include a breadboard, sockets, batteries and holder, resistors and capacitors.

Having built a few little house bots based on various PICAXE parts, I got the urge to learn how to program PICs using Assembly, so I bought the PICKIT 2 starter kit that came with the programmer and a demo board populated with the 16F690.  I decided the best way to figure the whole thing out would be to go soup-to-nuts and migrate from the Start Here.  This approach worked out really well for me.  Rather than sitting and staring at a jumble of tutorials and generic example routines, I had a fairly clear map of what I wanted to accomplish.  The relative simplicity of the Start Here philosophy kept the project manageable, and the fact that I had built each of the sub-assemblies many times with PICAXE meant that I already had an understanding of how they were supposed to work.

I broke the programming/learning task into a number of smaller chunks.  Some basic things required to do a Start Here include:

- Implement fundamental programming constructs such as:
    -Variable Data
    -Conditional Execution (IF/THEN/ELSE)
- Turn pins on and off to drive the H-bridge
- Read an analog sensor
- Control a servo

Although once I got rolling things moved along pretty well, I found getting started with the Assembly language to be challenging.  I had some hobby level experience with Assembly on my Intel 286 way back when, so I had a vague notion of what it means to work in low level language.  Nonetheless, moving into MPASM (Microchip's assembler for PICs) required quite the paradigm shift.  Higher level languages - BASIC, Javascript, C - all have a layer of abstraction that sits between you and the micro.  Tasks that can be accomplished in one or two lines of high level code can require dozens of lines in Assembly.  Because Assembly maps directly to the machine language opcodes that make the micro run, each and every step of every process gets coded.  In a FOR-NEXT loop, for example, you do the following:

- Load the working register with a value for how many loops you want to execute
- Move that value from the working register into a RAM register so that you can use it to keep count
- Mark the spot in the code where the loop begins
- Execute whatever process is internal to the loop
- Subtract 1 from the memory register holding the count
- Test that register to see if you've counted down to zero
- If you have counted down to zero jump out of the loop
- If you haven't counted down to zero jump back to the marker you left

You spend much of your time in Assembly reading and writing to various registers and ports.  All of the peripherals included on a PIC are accessed via a register.  For example, the analog to digital converter (ADC) is managed by flipping various bits in the ADCON register, and then the results are retrieved from the ADRESH and ADRESL registers.  This sounds simple enough (and it is) but in practice it takes some getting used to.

Another factor that made getting going difficult was the fact that much of the reference material I could find assumes that you are already pretty savvy in all aspects of electronics and programming.  This presumption was definitely a problem with the 12 "lessons" that are advertised to accompany the PICKIT.  I doubt anyone could learn much about PICs relying on those lessons!

As stated, however, getting going was the hardest part.  For the 16F "mid-range" PICs, there are only 35 instructions and once my intuition started to develop I was able to start chipping away at my goal of building a basic robot.  By far the most elaborate coding required was to control the servos.  I used two servos in a pan and tilt arrangement.  As most LMR readers will know, to hold a servo position requires a precise pulse of between 1-2 milliseconds that is refreshed about every 20 milliseconds.  Having the PIC do other things in the 16 or so milliseconds between pulses was the hard part.  I had to configure the internal timer and prescaler to operate in the background and then trigger an interrupt.  Fortunately, I was able to find some good examples online, but I still had to really understand the use of the timer and interrupt functions before I could adapt them.

All in all I found the experience of learning to use MPASM and the associated tools very gratifying.  I think it's helped to expand my understanding of how micros function and opened the door to some new ideas.  It's also given me an increased appreciation for PICAXE and all the intricate functionality they've managed to build into the RevEd implementation of BASIC.

For my own next steps, I plan to work on the detect and avoid algorithm on this bot which is sketchy at best, smooth out the readings on the Sharp detector which I think are a little jittery, and then slowly get into some more advanced mapping.  I'd also like to work out a better algo for the servos.  At the moment each servo fires in sequence and I'd like to get them firing simultaneously - perhaps even be able to run my 12 servo hexapod with a single PIC.  I've ordered up some 18F series chips and I'm going to play with them.  I used the 16F because it came with the demo board and it turned out to be a pretty good chip.  However the 18Fs have a lot of interesting features not present on the older architecture that I'm looking forward to playing with.

I've posted the Assembly code here.  I've tried to comment it well enough that someone could follow the logic, and I hope it might be of some use to others who would are just getting started with PIC Assembly.  Although the bot works well enough, I'm sure the code is full of beginner flaws, so please be kind!  I will try to keep up with it and if I develop any fundamental improvements I will update the post.

Thanks to everyone who has contributed to LMR!

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
ralph's picture


Hi Rich,

It's very gratifying to hear how much progress you've made and that my own project was of some help to you.  I've really been enjoying my own journey with PIC asm.  There are only a few of us here so we have to stick together!

Your guess was correct that I have the enable pins tied high on the H-bridge chip.  The little guy will pull off course on longer runs but those Solarbotics motors are pretty well matched.

Keep plugging away.  It sounds like your bot is really coming along.  Let us know your progress and hopefully someday post some video. 

Best Regards,




Thanks for sharing  your code. It got me started on my own start here robot, and best of all , your  code is all asm. :) 

With your driver chip, I guessed you tied the enable pins high? I ended up doing this with mine, as I didn't want to muck around with trying to generate PWM at the time. and only having four lines to fiddle with to control the motors was less confusing.  I also liked how you used the servos for your sharp IR. I decided to keep it super simple and dropped the servo code. and went with a single homebrew analogue IR sensor underneath the robot to act as a cliff/edge dectors.  I used a Pic16f887, l293d. so far it drives forward, gets to a edge and stops. I need to add a couple more sensors and get it to reverse up and turn. 





Nice robot, and very well written asm code as well.  I am also building a start here robot with a PIC16F788. I have been learning as much as I can about the PIC asm code. I have programmed in AVR asm but that was limited, and I think I will stick to C for the AVR, but asm and the PIC now that's another story.  As I have found out that there is no  lack of good PIC asm tutorials around.

Cheers and keep up the good work (FUN)



ralph's picture


Hi TeleFox – Thanks for taking the time to read my code so carefully.  I very much appreciate the good advice for making better use of the timers.  It should really help improve my servo routines on the next revision and for the hexapod.

To answer your question, I was having trouble working with PORTC before I started using the shadow registers.  The outputs that drive the H-bridge would turn on for a flash, and then get immediately zeroed within the interrupt.  I tried a lot of things to isolate and fix the problem without luck until I started using the shadow.  After reading about the so-called “read-write-modify” problem, it seemed to make sense that the AND and XOR ops were not seeing the outputs as 1s.


TeleFox's picture

Hi ralph, nice write-up on your project, always good to see people trying out new stuff =)

I was surprised to see that you used a shadow register for PORTC - were you encountering errors yourself, or was this recommended to you? I've always found that direct port modification was very robust even on the low range PICs, including when using operations like XORWF and similar.

The code is well written, and follows a solid structure. There don't appear to be any flaws, but there are a few areas that could be optimised, after all that's what Assembly is best for =)
Although there's nothing wrong with delay loops, you can squeeze more efficiency out of your micros by instead using the timers more, and not necessarily just for interrupt routines. For example when you've just turned on a servo pin in your servo ISR, you can then reset Timer0 to the appropriate servo pulse delay and then go back to the main loop until it's time to turn the servo pin off again. This might only reclaim a few ms out of every 19ms or so, but that's the kind of improvement that'll really come in handy for your hexapod project =D