Voicy's buggy project

Voicy

Resident Panty Kicker
I was going through my closet looking for something - and as always, you find EVERYTHING except what you're looking for. That's when I stumbled upon my old buggy project.

It's been almost 6 years since I finished my studies in engineering and one of my classes was rather unusual. This might not be of interest to most of you, but I decided to do a write up for those 2 or 3 who are interested in micro-controllers.

The Buggy Project

The course, Micro Systems Design, was rather unusual given that on the very first day our lecturer told us that the course did not require us to write any tests or exams. Given our ignorance we were obviously ecstatic. However, we grew silent (and equally perplexed) fairly quickly when the lecturer drew a grid on the board.

We were told that in order to pass the course, we had to achieve 3 tasks.
  • Research a topic relevant to the course and deliver a keynote presentation on it. (Simple enough - basically testing your presentation skills as a future engineer)
  • Build the Altera EMP7032S FPLD development board & code a useful program into it using VHDL. (Hooray for soldering skills! I just went with a standard Binary - hex - octal - decimal - hexadecimal converter.)
  • Build a buggy that will guide itself through a maze without any user input or assistance via remote control. In essence, you switch the buggy on, place it in the maze and it has to find its own way out of the maze. You could make use of the Altera FPLD above, which was issued with the course or make use of your own controller - as long as it operated independently. If it passes through the maze, you pass the course. If it doesn't, neither do you. No pressure.
Altera FPLD development board

attachment.php


The Altera makes use of AHDL/VHDL to program it, which means it works on a logic gate (boolean algebra) array When you're done hard coding it, you can also export a visual gate array which you can use to check your code before killing the chip, as below:

attachment.php


As mentioned, this one is a very simple program that allows you to enter a 4 digit binary code using the dip switches on the board, then select the output (hexal/octal/decimal/HEX) to display on the 7-segment LED Display.

The Grid

attachment.php


The grid comprised of a 8x8 matrix of (150mm x 150mm) blocks with interchangeable barriers, which would be placed in an unknown maze format on the day of the final test. Therefore, you could not pre-program a route to follow into your design's logic controller.

Given the dimensions, your buggy has to be small enough to fit into the maze and turn around as well as having sensors low enough to detect the boundaries...but be robust enough to clear the small grooves separating each block. Some buggies just didn't have the horsepower to cross those small gaps.
 
The Buggy


I decided to go for a PIC16F84 micro-controller since I have worked with it on previous projects and knew the registers and operation quite well, which makes use of Assembler to code it. The only problem with it is that it only has 12 I/O ports. By ports I mean single connections. You need 8 of those to output an 8-bit parallel instruction. Also, the register only has 1KB of memory (or 1000 lines of code, which seems like a lot, but it really isn't).

My initial concern was where I would find the resources which would enable me to build a buggy which would inevitably have to guide itself through a maze. The lecturer aided students who were resource limited in attaining stepper motors and sorts to use in their buggies and as one can see from the photos, my buggy became the creation of all things used and abused around the kitchen.


attachment.php



The “shell” of my buggy is a margarine tub with a punch-machine paper guide at the bottom which acts as a support beam. A year’s supply of cable ties and super glue went into fixing the stepper motors onto the lid of the margarine tub. This proves that with a little creative thinking one could build the buggy out of just about anything.

attachment.php


The logic which my buggy follows is quite simple in concept. It will move forward unless disturbed. (picked up by the micro switch sensors located at the front of the buggy). If the buggy moves off course, one of the side sensors will alert it to correct itself into a straighter line.

Once it bumps an object from the front, it will turn left 90 degrees and continue moving forward. If it hits another object within a certain number of steps it realizes that it is in a corner and then turns 180 degrees to its right and attempts to move forward once more.

I had to install side bumpers (micro switches) since getting a cheap stepper motor to make a perfect 90/180 degree turn with 4 bit inputs is damn near impossible. So if a side bumper makes contact, the buggy would reverse 2 steps, to back up from the wall, then make a +/- 15 degree turn to correct itself before carrying on with its movement. That way it zigzags across the maze to ensure that it stays on course.

attachment.php

(Yes that is an old CT aquarium ticket. I had no spare cash for material so I used it to insulate the PC board from the stepper motors below)

Theoretically this would guide the buggy out of any situation. The buggy was also designed NOT to turn left or right if a gap in the wall is present in order to make it a generic design which will let it move forward in a real world situation instead of turning in circles if it’s located in an open space.

attachment.php


The buggy runs off external 12V DC. The 16F84 development board was selected for its sequential operation and all I/O pins were used. It contains onboard power to the board by 4 x 1.5V AA batteries which also aids in weighting down the back of the buggy. It makes use of 6 micro switches for sensing purposes and 1 activation button located at the top to start the buggy’s logic. The “GT racing stripes” were added for the lulz.

Result

My buggy was one of the few which made it through the maze. You were allowed 2 finger bumps in case it got stuck due to your casing etc. Mine required 1 finger bump to remove one of the maze boundary walls that fell over.
 
Last edited:
Here are some of the other "contestants" with their interesting designs:

Successful buggies

attachment.php

This one was a very nice design, but the front sensor kept catching on the bumps in the tracks as it slid over it.

Semi-successful buggies

attachment.php
Nice concept, but it was too "buggy" and kept needing pushes to help it decide what to do.
attachment.php
This one was on the right track, but about as road worthy as most of the taxis on our road. Its wheels also kept falling off.

Unsuccessful buggies

attachment.php

This oke decided to make a dune-buggy instead of a maze buggy. His buggy didn't respond to the sensors and he ended up 4x4'ing over the whole maze. Damn wall hacks!

There are a few more pics but due to the 4x img limit per post I only included the better ones.

Hope some of you enjoyed the read.
 
Last edited:
The Code

I made use of Assembler to code the 16F84. For those of you not familiar with it (Different to 'assembly' language) it's basically low level programming one up from binary entries.

Things to take into consideration was obviously coding space, but on an electronic level you have to account for "switch "de-bouncing" and "Antennae".

Switch de-bouncing is when you press the switch and the controller registers multiple presses. This is because the controller runs at 4micro seconds per instruction, so if you press the switch once (for 100ms at the shortest), the controller could register that as 25,000 presses.

That's why you need to switch off the input-reader for around 150ms after each button has been pressed in order to register it as a single press. The human finger can't press a switch faster than that, so it's a safe buffer to distinguish between multiple presses.

Antennae are metallic objects that pic up radio waves and even something as small as a leg (pin) on an IC that isn't grounded or set to +5V can pick up radio waves and the controller can falsely interpret it as an input signal.

Therefore, everytime an input is not required, you need to ground the pin by assigning a 0V to it avoid having the pin affect pins around it that are being used as inputs, thereby eliminating floating points.

For those interested, this is what the assembler code looks like for the buggy:

The first section is not so much creating variables as it is renaming ports and registers to something more understandable than just its number.

Code:
; ====== symbol setup ============


        STATUS        EQU            03
        OPT        EQU            01
        RPO        EQU            05
        PORTA        EQU            05
        TRISA        EQU            05
        PORTB        EQU            06
        TRISB        EQU            06
        RBPU        EQU            07
        ZFLAG        EQU            02
        rightsensor     EQU            04
        leftsensor    EQU            05
        frontsensor    EQU            06
        STRTBTN        EQU            07
        DelayL        EQU            0C                
        DelayM        EQU            0D                
        DelayH        EQU            0E    
        RecHits        EQU            0F        


; ====== port setup ============


START               BSF        STATUS,RPO
                    CLRF        TRISA                ; port a = outputs
                MOVLW        B'11110000'
                MOVWF        TRISB                ; rb4-rb7 = input, rb0 - rb3 = output
                    BCF         OPT,RBPU            ; enable pull ups
                BCF            STATUS,RPO


anfang                NOP    
                CLRF        PORTA                ; initialize ports
                CLRF         PORTB
                CLRF        RecHits                ; clear recorded hits by sensors


                CALL        Delay2000
STRTLP                BTFSC           PORTB,STRTBTN        ; waits for activate button to begin...
                    GOTO            STRTLP
                GOTO        BEGIN                
                
BEGIN               CALL        Delay2000            ; x4 = 2sec delay after start button pushed.


resume                NOP
                CALL        run
                GOTO        anfang

     
;======== 500 ms delay loop=====


DELAY500            CLRF        DelayL
                CLRF        DelayM
                MOVLW        H'1'            ;Fixed delay entry point
                MOVWF        DelayH            ;Variable Delay Entry point
LOOPD                DECFSZ        DelayL
                GOTO        LOOPD            ;returns to loop while counter > 0
                DECFSZ        DelayM
                GOTO        LOOPD
                DECFSZ        DelayH
                GOTO        LOOPD


    RETURN                                    ; return to program

;======= fwd =====


fwd                 MOVLW        B'1001'
                MOVWF        PORTA
                MOVWF        PORTB
                CALL        DELAY500
                BTFSS        PORTB,frontsensor
                BSF        RecHits,04
                BTFSS        PORTB,rightsensor
                BSF        RecHits,05
                BTFSS        PORTB,leftsensor
                BSF        RecHits,06


                BTFSC        RecHits,04
                GOTO        exitfwd
                BTFSC        RecHits,05
                GOTO        exitfwd
                BTFSC        RecHits,06
                GOTO        exitfwd
                
                MOVLW        B'1010'
                MOVWF        PORTA
                MOVWF        PORTB
                CALL        DELAY500
                BTFSS        PORTB,frontsensor
                BSF        RecHits,04
                BTFSS        PORTB,rightsensor
                BSF        RecHits,05
                BTFSS        PORTB,leftsensor
                BSF        RecHits,06


                BTFSC        RecHits,04
                GOTO        exitfwd
                BTFSC        RecHits,05
                GOTO        exitfwd
                BTFSC        RecHits,06
                GOTO        exitfwd
                MOVLW        B'0110'
                MOVWF        PORTA
                MOVWF        PORTB
                CALL        DELAY500
                BTFSS        PORTB,frontsensor
                BSF        RecHits,04
                BTFSS        PORTB,rightsensor
                BSF        RecHits,05
                BTFSS        PORTB,leftsensor
                BSF        RecHits,06


                BTFSC        RecHits,04
                GOTO        exitfwd
                BTFSC        RecHits,05
                GOTO        exitfwd
                BTFSC        RecHits,06
                GOTO        exitfwd


                MOVLW        B'0101'
                MOVWF        PORTA
                MOVWF        PORTB
                CALL        DELAY500
                BTFSS        PORTB,frontsensor
                BSF        RecHits,04
                BTFSS        PORTB,rightsensor
                BSF        RecHits,05
                BTFSS        PORTB,leftsensor
                BSF        RecHits,06


exitfwd                MOVLW        B'1001'
                MOVWF        PORTA
                MOVWF        PORTB
                
    RETURN


left                MOVLW        B'1001'
                MOVWF        PORTA
                MOVLW        B'1001'
                MOVWF        PORTB
                CALL        DELAY500

                MOVLW        B'0101'
                MOVWF        PORTA
                MOVLW        B'1010'
                MOVWF        PORTB
                CALL        DELAY500

                MOVLW        B'0110'
                MOVWF        PORTA
                MOVLW        B'0110'
                MOVWF        PORTB
                CALL        DELAY500

                MOVLW        B'1010'
                MOVWF        PORTA
                MOVLW        B'0101'
                MOVWF        PORTB
                CALL        DELAY500

                 MOVLW        B'1001'
                MOVWF        PORTA
                MOVLW        B'1001'
                MOVWF        PORTB


    RETURN

adjusta                MOVLW        B'1001'                ; move left wheel backwards
                MOVWF        PORTA
                CALL        DELAY500

                MOVLW        B'0101'
                MOVWF        PORTA
                CALL        DELAY500

                MOVLW        B'0110'
                MOVWF        PORTA
                CALL        DELAY500

                MOVLW        B'1010'
                MOVWF        PORTA
                CALL        DELAY500


                MOVLW        B'1001'
                MOVWF        PORTA
                
    RETURN

 circleleft            CALL        adjusta
                CALL        left
                CALL        left
                CALL        left
                BSF        RecHits,01            ; record bump to trigger right turn on next bump
                CALL        fwd
                BTFSC        RecHits,04            ; test if bumping front
                RETURN
                CALL        fwd
                BTFSC        RecHits,04
                RETURN
                CALL        fwd
                BTFSC        RecHits,04
                RETURN
                CALL        fwd
                BTFSC        RecHits,04
                RETURN
                CALL        fwd
                BCF        RecHits,01            ; recording of bump cleared, next turn left, not right on bump.
    
    RETURN

  adjustleft            CALL        back
                CALL        adjustb
    RETURN

run                CALL        fwd
                CALL        align
                BCF        RecHits,05
                BCF        RecHits,06
                BTFSS        RecHits,04
                goto        run
                BCF        RecHits,04
                BTFSS        RecHits,01
                CALL        circleleft
                BCF        RecHits,04
                BTFSS        RecHits,01
                GOTO        run
                CALL        circleright
                GOTO        run

     RETURN

    END

EDIT: I removed half of the code due to the 10,000 char limit per post ... but the essentials of how it works is in tact.
 
Last edited:
Ah, finally the famous buggy project rears its head! :)

hehe yeah it's been long overdue. When I unearthed it last night I found the battery & controller board still working. Man I used to solder a lot in my young days.

dude dis fokken awesome!

Thanks Mappy :) Can't tell you how high I got from all the coffee and superglue that went into getting that thing to work. :p
 
very nice man, what projects you work on now?

Sadly I've gone over to heavy current. So I mostly do reticulation designs and automatic backup generator conversions of old manual LV panels etc. The SLD's I do now are for panels that are between R350k-R550k.

I miss playing with electronics though. I've lost most of my programming abilities etc. through the years. :(
 
Sheesh, that looks like fun, and mighty impressive, Voicy. I'm a mechie, with a feel for control systems, but no experience in it, and I've always wanted to play around with something like that. Just with real motors, you know? :p

Seriously, your work looks amazing!
 
Sheesh, that looks like fun, and mighty impressive, Voicy. I'm a mechie, with a feel for control systems, but no experience in it, and I've always wanted to play around with something like that. Just with real motors, you know? :p

Seriously, your work looks amazing!

thanks dooder. Yeah I know what you mean, unfortunately they only introduced mechatronics when I was busy with my final year. Otherwise I would've enjoyed going into that field. I think mechanical guys are much more adept to fiddle with electronics than electronic boys are willing to fiddle with proper mechanical equipment. I'd give my kingdom for a room full of actuators, VSD's and solenoids.

I wish I did more PLC programming. I only briefly touched on ladder logic to simulate traffic lights and whatnot. If I wasn't doing what I'm doing now, I would've loved to get involved with Siemens products.

PLC's are pretty much beefed up micro-controllers with built in relays. For my one project where I switched lights on/off via WAP on my cell (before the days of smart phones /3g etc.) I had to do a 3 stage switching signal. 5V signal to transistors (via opto-isolators), which switches 12V signal to relays, which switches 220V supplies to lights / whatever.

That was 6 years ago ... and already completely obsolete. :/
 
Wow, very cool man. Assembly code FTW.

Pity you went over to the heavy current dark side though, lol :p
 
PLC's are pretty much beefed up micro-controllers with built in relays. For my one project where I switched lights on/off via WAP on my cell (before the days of smart phones /3g etc.) I had to do a 3 stage switching signal. 5V signal to transistors (via opto-isolators), which switches 12V signal to relays, which switches 220V supplies to lights / whatever.

That was 6 years ago ... and already completely obsolete. :/

And yet I still nerdgasmed "whistling:

thanks dooder. Yeah I know what you mean, unfortunately they only introduced mechatronics when I was busy with my final year. Otherwise I would've enjoyed going into that field. I think mechanical guys are much more adept to fiddle with electronics than electronic boys are willing to fiddle with proper mechanical equipment. I'd give my kingdom for a room full of actuators, VSD's and solenoids.

In general, I think you're right, since mechies tend to be jack-of-all-trade's, but I think I suck at it. Varsity taught me enough about both high and low voltage to know that I should sub-contract all that shit! :D
 
Back
Top