roadkill - robotics and autonomous systems project · pdf fileroadkill - robotics and...

47
Roadkill - Robotics and Autonomous Systems Project Report Fredrik Dahlström Jakob Lublin Peter Osagie

Upload: doannhu

Post on 08-Mar-2018

218 views

Category:

Documents


0 download

TRANSCRIPT

Roadkill - Robotics and AutonomousSystems Project Report

Fredrik DahlströmJakob LublinPeter Osagie

Abstract

This report is a part of the course Robotics and Autonomous Systems(2D1426), held at the Royal Institute of Technology, KTH during the au-tumn of 2003. During the course seven teams were to build one robot eachand then compete against each other in a floor hockey tournament.

This report outlines the mechanical and software design solutions that wedecided to implement on our robot.

Contents

1 Introduction 3

1.1 Robot floor hockey . . . . . . . . . . . . . . . . . . . . . . . . 3

1.2 Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.3 Robot constraints . . . . . . . . . . . . . . . . . . . . . . . . . 5

1.4 Tournament . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2 Perception 7

2.1 IR-sensors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.2 Reflex detectors . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.3 Slotted opto detectors . . . . . . . . . . . . . . . . . . . . . . . 7

3 Locomotion 9

3.1 Motors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3.2 Calculating Speed . . . . . . . . . . . . . . . . . . . . . . . . . 9

4 Hardware Design 11

4.1 Electronic components . . . . . . . . . . . . . . . . . . . . . . 11

4.1.1 PIC16F877 - Main microcontroller . . . . . . . . . . . 11

4.1.2 PIC16F876 – Co-processor . . . . . . . . . . . . . . . . 11

4.1.3 Motor driver . . . . . . . . . . . . . . . . . . . . . . . . 12

4.1.4 PC1602D A – LCD display . . . . . . . . . . . . . . . . 12

4.1.5 Keyboard . . . . . . . . . . . . . . . . . . . . . . . . . 12

4.2 Robot layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

4.2.1 Materials and layers . . . . . . . . . . . . . . . . . . . 12

4.2.2 NGHPRLC Interface . . . . . . . . . . . . . . . . . . . 13

5 Software Design 15

5.1 Program states . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

5.1.1 Start Sleep . . . . . . . . . . . . . . . . . . . . . . . . . 16

1

5.1.2 Go to Puck . . . . . . . . . . . . . . . . . . . . . . . . . 16

5.1.3 Goto Goal . . . . . . . . . . . . . . . . . . . . . . . . . 16

5.1.4 Fire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

5.1.5 Getting Unstuck . . . . . . . . . . . . . . . . . . . . . 17

5.1.6 Avoid Goal . . . . . . . . . . . . . . . . . . . . . . . . 17

5.1.7 Return to Centre . . . . . . . . . . . . . . . . . . . . . 17

6 Discussion and Conclusions 19

6.1 Scoring movement . . . . . . . . . . . . . . . . . . . . . . . . 19

6.2 Buttons and LCD . . . . . . . . . . . . . . . . . . . . . . . . . 20

6.3 Modularity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

6.4 Battery . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

6.5 Stable platform . . . . . . . . . . . . . . . . . . . . . . . . . . 20

6.6 Shooting mechanism . . . . . . . . . . . . . . . . . . . . . . . 21

6.7 Speed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

A Part list 23

A.1 Parts on motherboard . . . . . . . . . . . . . . . . . . . . . . . 23

A.2 Other parts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

B Source code 24

B.1 roadkill.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

B.2 extras.inc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37

B.3 Pictures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

2

1 Introduction

Figure 1: An extract from the Collins English Dictionary (Word Finder 7)

In the course Robotics and Autonomous Systems, the students are giventhe assignment of designing, building and programming their own au-tonomous robots, who are to compete against each other in the Robot Ta-ble Hockey Competition.

This project report is part of the undergraduate course in Robotics andAutonomous Systems, at the Royal Institute of Technology. The objectiveof this course is to teach the basics of robotics, and give an understandingfor the complications involved in autonomous systems.

In the course the students are given the task to construct a quite simpleautonomous robot being able to play floor hockey. The main parts of therobot are a PIC 16F877 microcontroller mounted on a motherboard, differ-ent kinds of IR-sensors and two 12 V motors. These parts as well as othermaterial such as LEGOTM and MecconoTM were provided by the courseleader. Concerning the actual construction of the robot the students aregiven a lot of freedom, as long as none of the floor hockey rules are vio-lated. There were a total of seven project groups, with three members ineach group.

Each group were to construct their own robot for the tournament held inthe end of the course.

1.1 Robot floor hockey

The game of robot floor hockey is played by two autonomous robots on arink approximately two and a half meters in length and one and a half inwidth. The surface of the rink is white except for the middle line and thetwo goal zones. The goals and the puck are equipped with infrared lightemitting diodes so that the robots can locate their position. The objective

3

for the robots is to guide the puck into their opponent’s goal without en-tering the goal zone, and to hinder their opponent from doing the same.

Figure 2: The rink

1.2 Rules

The floor hockey rules as described in course notes [1]. When the gamestarts both robots are in their defensive goal zones. A goal is scored when-ever the puck is partly within the red zone at the goal aluminium plateand the goal zone rule has not been violated (see below). The scoringrobot also has to signal the goal by playing its own pre- defined tune onits speaker. After each scored goal the puck will be returned to the centrepoint. A robot may only signal a goal directly after it has tried to score.Other signaling will render the robot 10 seconds off the rink.

A robot is not allowed to grab the puck, and the edge of the vertical pro-jection of the robot body on the floor may not have any concave parts(except for concavities formed between the driving wheels and the rest ofthe robot, provided they can not be used to guide the puck). Any protrud-ing whiskers or bumpers must be flexible enough so that they can not beused to move or guide the puck. The robot must be constructed so that thepuck cannot be on top of any part of the robot.

Each robot may have a stick to guide the puck. It may extend no morethan one puck diameter from the robot body. The part of the stick outsidethe robot body must not be wider than one puck radius, and may not haveany joints or concavities.

When a robot goes past the white line an inch into its own defensive goal

4

zone with any non-flexible part (excluding the stick), it will be taken offthe rink for 10 seconds and then put back far from the puck. The goalzones are marked by black paint on the floor, as is the centre line.

When a robot scores, it may not go past the white line in the goal zonewith any non-flexible part (excluding the stick). If it does the scored goalis not counted. If the puck is left in the goal zone without scoring it will bemoved to the centre point 3 s after a robot last touched it.

A robot that is pushed into a goal zone and is constantly working to getout of it will receive no penalty (i.e. the any goal is approved or the robotis not taken of the rink).

If a robot brakes down during a match, it may be taken off the floor forrepair for a minimum of 30 s and then put back far from the puck.

1.3 Robot constraints

The robot constraints as described in course notes [1]. To be alowed to par-ticipate in the tournament the robot must obey the following constraints:

• A robot must fit in a circle with diameter 250 mm (as measured onthe vertical projection on the floor). This does not apply to flexibleparts or the stick.

• When guiding the puck, the stick (or any whiskers/bumpers) mustnot occlude the IR LEDs of the puck from any direction.

• No device that can harm the opposing robot, on purpose or not, maybe mounted on a robot. Examples include knives, electric guns, wa-ter guns, and electromagnetic interference devices, but also a stickthat is narrow and powerful enough to cause serious damage, shouldthe opponent come in its way when it shoots out in an attempt toscore a goal.

1.4 Tournament

The tournament is started with a round of qualification, which determinesthe robot’s position in the following group play. During qualificationseach robot is given the chance to score as many goals as possible unop-posed during 2 minutes. In the following group play, each robot meets

5

every other robot in the same group in matches of 3 minutes. Two pointsare given to the winner and zero to the loser. If the score are equal after fulltime each robot are given one point. The winner and the first runner upfrom each group continue to the play offs. The semi-finals are 4 minuteslong. The final is 5 minutes long and can not end in a draw. If the scoreare equal after full time, the match goes to sudden death.

6

2 Perception

2.1 IR-sensors

Five TSL261 Light-to-Voltage Optical Sensors [2] were given to each groupto be used at their discression. The technical developers of Team Roadkill,choose to use four sensors for navigation and the fifth as a puck detectormounted at the end of the stick. The navigation sensors were fixed onthe sensor-tower placed on the top of layer three, see figure 3. The towerwas mounted so that two of the IR sensors pointed forward and two back-wards. Sensor telemetry was processed by the co-processor and sent tothe main PIC on regular intervals.

Figure 3: Four IR-sensors where mounted on top of the robot.

2.2 Reflex detectors

Everlight’s ITR8307 Subminiature High Sensitivity Photo Interrupter wasused for floor color detection. Three of these detectors were mounted onthe robot. One on the stick, one in the front and one in the back of therobots main body. The reflex detectors were used to detect the goal zonesand the center line.

2.3 Slotted opto detectors

For speed measurements Everlight’s ITR8010 General Purpose Photo In-terrupter were used. These slotted opto-detectors are shaped like a U. ALED emits light from one side of the opening, to a detector on the otherside. The detector can detect if a non transparent object is placed betweenthe detector and the LED. A decoder disc (see figure 4), a plastic filmwith two non- transparent black zones, was glued to the motor axle. Two

7

opto-detectors were then fitted too each motor so that the decoder disk’srotation could be measured. By using two opto detectors instead of one,it is possible to detect the direction of which the wheel is rotating and aresolution increment by four times is also obtained.

Figure 4: A single encoder disc with opaque and transparent sections.

8

3 Locomotion

Locomotion is an important part, if not the most important in this project.it makes little difference how "smart" a robot is if it is not able to move ina stable and correct manner. And in the game of robot hockey speed is acrucial factor. Being second on the puck may cost you the game.

3.1 Motors

Two 12 V DC motors are used to propel the robot. The motors are equippedwith gearboxes that downshift the speed in order to increase the torque.Each motor is connected to a PWM output on the RAS lab card. This en-ables us to set different speeds on the right and left motor.

Figure 5: The motors are powered by a 9 V alkaline battery pack or a 7.2 VNiCd accumulato located behind the main motor axis.

3.2 Calculating Speed

To steer the robot towards a target we use measurements from the IR-sensors. The navigation procedure is the same for any target – puck or anyof the goals. The correction speed that needs to be applied is calculatedwith the following formula:

∆speed = ctarget

IRlefttarget − IRright

target

IRlefttarget + IRright

target

(1)

where ctarget is a turning constant that is different for each of the targets.

The resulting speed is then simply given by

speednewleft = speedold

left −∆speedspeednew

right = speedoldright + ∆speed.

(2)

9

This algorithm is the same as the winners in the previous three competi-tions [4, 5, 6]. By using this simple and ingenious formula it is relativelyeasy to get the robot to a desired target. However, the speed needs to beadjusted in accordance to what state the robot is in. For example, if therobot is getting close to the offensive goal the speed is reduced so that thewhite line in the goal zone isn’t crossed. Also, the robot needs to executeright and left turns differently depending on if it has the puck or not. Wewant to avoid making hard turns when it has the puck so that it isn’t lost.Furthermore, when it has possession of the puck only left hand turns arepermitted, this again, is to avoid loosing the puck. We also attemptedto reduce the speed when approaching the puck to avoid the puck frombouncing off the robot, but found that rather difficult to implement. In-stead we built a "bumper" that would cushion the impact with the puck.Sometimes a hardware solution is much simpler and effortless to put to-gether.

10

4 Hardware Design

4.1 Electronic components

4.1.1 PIC16F877 - Main microcontroller

To control the robots behavior, a PIC16F877 microcontroller from MicrochipTechnology Inc was used. It is a 40 pin, 8-bit CMOS FLASH microcon-troller with the following characteristics [7]:

• 20 MHz, 5 MIPS RISC architecture

• 8K x 14 bits FLASH program memory

• 368 bytes of SRAM

• 256 bytes of EEPROM non-volatile data memory

One of the largest limitations that one had to keep in mind while develop-ing for the PIC16F877 was that the hardware based call stack had a maxi-mum depth of 8 levels of function calls.

We used MPLAB also from Microchip Technology Inc. to manage our soft-ware project. The Hi Tech PIC C compiler was used to compile, link andgenerate the hex file that was loaded on to the PIC. The code was trans-ferred from a PC on a RS-232 interface in binary format using a boot-loaderprogram that resided in the program memory of the PIC. The boot- loaderwas programmed into the microcontroller at the start of the project to easeupdating and testing of the software.

4.1.2 PIC16F876 – Co-processor

From the same company as the main microcontroller comes the co-processorthat we used to filter the incoming data from the IR-sensors. IR light of dif-ferent modulation was sent out by the puck and the two goals. The filtereddata was sent to the main controller on regular intervals. The co-processoris almost identical to the main controller, not counting the smaller 28-pincapsule. The co-processor was pre programmed to haldle this task.

11

4.1.3 Motor driver

The motherboard also hosted two sets of motor driver circuits. Two of thefour H- bridges were used to feed the motors with a PWM (pulse widthmodulation) signal controlling the speed. One of the other H-bridges wasused to generate sound in the piezo speaker. Using a PWM signal to con-trol the H-bridges prevented them from generating too much heat in thetransistors.

4.1.4 PC1602D A – LCD display

An LCD display capable of showing two rows of 16 characters each wasused as the primary source of debugging information. Another usage wasfor our highly sophisticated menu system that gave us runtime control ofmany internal features of the robot.

4.1.5 Keyboard

To navigate in our menu system, we built a small keyboard of four but-tons that were connected to port B on the main PIC using internal pull-upresistors. The keyboard was mounted on a bent pipe (see figure 6) andfastened on top of the robot for easy access.

Figure 6: The different buttons to access the menu and the LCD display

4.2 Robot layout

4.2.1 Materials and layers

So many things in this world are built upon layers, and so is our robot.We wanted the robot to be as stiff and stable as possible to be able to make

12

Figure 7: The bottom, motherboard and LCD layer.

fast corrections to the speed and the direction of the robot. After some dis-cussion, we decided to build the robot in three different layers using metalpoles to keep them together. This had the added advantage of easy accessfor repairs and maintenance. Also, the components needed not be packedto tightly. The bottom layer was built on top of an aluminium frame cutout to perfectly fit the robot dimensions. On top of the aluminium framewe glued a thin LEGOTM plate to be able to easily fix the motors and thebattery pack on their designated positions using small LEGOTM pieces. Thesecond layer was built in a light but stable pressed paper plate. This ma-terial was chosen to give the robot a low center of gravity without com-promising its stability. It was fixed 3 mm above the wheels using metalnuts. This layer housed the motherboard, power switch, reflex driver cardand the booster card. The RS 232 driver card was also mounted on thislayer together with the keyboard. At the top of the robot, a third layerwas mounted to host the IR sensors and the LCD display. This layer alsohelped in keeping cables from the second layer out of sight from the IRsensors.

4.2.2 NGHPRLC Interface

Figure 8: The NGHPRLC Interface

13

The communication between the layers was conducted through our newlydeveloped NGHPRLC Interface (Next Generation High Performance RobotLayer Communication), which we probably will submit to IEEE for con-sideration in future standards of robotic architecture. This interface madethe robot very modular and easy to take apart. Worth mentioning as anexample, is when one of the gearboxes broke down. We were able to takeapart the robot and change the gearbox in less then 10 minutes. For moreinformation, see figure 8.

14

5 Software Design

We were in agreement from the get go that we would implement our AI asa reactive system – a system that has a tightly coupled perception to actionand is composed of individual behaviors that react directly to sensations.These behaviors, or states, were realized as a finite state machine. Allstates run in parallel with a form of subsumption in order to prioritizebetween the different states.

5.1 Program states

In order to simulate that all states run in parallel we multitask betweenthem. This is simply done by an infinite loop that for every revolutiondetermines the current state of the robot.

To determine what state the robot is in or should switch to some predi-cates are tested. The predicates truth values are based on sensor readingsand/or timers values.

To simplify the programming and increase the readability of the code thepredicates are implemented with macros instead of being functions. Thisis also preferred because of the limited stack depth of the PIC micropro-cessor.

The different states are:

• Avoid Goal

• Start Sleep

• Stuck with Puck

• Stuck without Puck

• Go to Puck

• Go to Goal

• Fire

• Return to Centre

15

Figure 9: The finite state acceptor diagram. If no transition is made therobot remains in the same state, as in Start Sleep.

5.1.1 Start Sleep

The robot starts in the Start sleep state which does nothing until the re-lease button on the keyboard is pressed (see section 4.1.5).

5.1.2 Go to Puck

The Go to Puck state which tries to move the robot towards the puck withaid of the top-mounted IR-sensors. The speed is set in accordance to ( 2)with a turning constant cpuck = 10. If the puck is close to the robot, turningis done with a lesser speed, this to avoid overshooting the turn.

5.1.3 Goto Goal

Go to Goal tries to move the robot in the direction of the offensive goal.The robot can only enter this state if it has found and acquired the puck.

Go to Goal resembles the Go to Puck state except for that only left handturns are allowed, to avoid loosing the puck. Also, the turning constantcpuck is set to 6, this in order to give smoother turns.

16

The speed is additionally reduced when the robot is close to the offensivegoal in order not to enter the goal zone too far.

5.1.4 Fire

When one of the forward reflex detectors detects a black surface the robotenters the Fire state. It immediately stops the motors to avoid overstep-ping into the goal zone. When in Fire state the robot executes one of twogoal scoring functions. It is possible to switch between the two by pressingthe second button on the keyboard (see section 4.1.5). The idea of havingmultiple goal scoring functions was that we could have a fast but not soaccurate and a more reliable but slower one. The switching could then bedone depending on what opponent the robot was facing or in what partof the contest the robot was in.

5.1.5 Getting Unstuck

The Stuck with Puck and Stuck without Puck states are designed to getthe robot unstuck. We decided to implement two different states depend-ing on if the robot has acquired possession of the puck. The main differ-ence is that Stuck with Puck only makes a very short left-hand turn andthen continuous towards the goal. The Stuck without Puck reverses therobot for a brief period and then returns to the Go to Puck state.

5.1.6 Avoid Goal

The Avoid Goal state is entered only when one of the reflex detectors de-tect a black surface. If it is one of the two forward detectors that detectthe surface, the robot is simply reversed for a short while. However, if therear reflex detector detects a black surface the robot drives forward withfull speed for about 200 ms.

This state has highest priority and overrides all the other states. Afterleaving this state the robot returns to the Go to Puck state.

5.1.7 Return to Centre

Return to Centre is only entered if the robot thinks it has scored a goal. Ifthe state is entered the robot reverses towards its own goal for maximally

17

1.5 sec. This, together with the Avoid Goal state, gives a level off redun-dancy in order to avoid entering our own goal zone and be penalized bybeing sent of the rink.

After the robot has returned to the centre it enters the Go to Puck state.

18

6 Discussion and Conclusions

Roadkill ended up scoring just four goals in the qualification round andcame in as number 4 in the tournament. The number of scored goals wasa disappointment to us. In the lab we scored goal after goal during finaltesting the evening before the tournament. Moving the robot and chasinga target worked very well and Roadkill had plenty of chances of scoringgoals. Problems with battery power and the goal movement made us misstoo many opportunities. But you can read all of that on the followingpages.

6.1 Scoring movement

Constructing a good scoring movement to score a goal turned out to bequite difficult. In the beginning we had a really good routine that did notrequire the robot to do anything else then just go at full speed towardsthe goal and do a maximum brake as soon as the goal zone was reached.This worked very well until we became worried about infringement andenergy levels of the battery. At this stage there was not that much time leftto do major modifications to the robot construction and we decided to tryand implement the safer strategy of doing a "score quirk" when reachingthe goal zone. That is when the robot stops, backs up a little and thenpushses the puck with the end of the stick into the goal.

Our first attempts at this new strategy were too much dependant on thestatus of the battery. When it was fully charged, the robot scored just fine,but as the battery drained out, controlling distances and getting controlledmoves out of the motors became really hard. The problems we had whileconstructing our scoring moves could probably have been solved by us-ing the PID regulator that we developed earlier in the project, to controlmovements of the wheels. Time constraints made this impossible for usto try out. Another solution would have been to use the opto- encoders tomeasure distance and getting controlled moves out of that. Since we de-cided to abandon our first "push" strategy close before the tournament thiswas not a viable alternative either. We ended up using timers to controlthe movements in the scroring routine.

19

6.2 Buttons and LCD

Our keyboard was first constructed just for fun. It turned out quite earlyin the project to be more than just another cool feature. Together with theLCD we built a menu system that among other things could be used to seeIR values and directions to different targets. One could also use the menusystem to change parameters during testing of the robot. This saved usmany hours that would otherwise have been used for reprogramming therobot with just a few values changed. This was especially obvious whenone saw how much time that was spent fine-tuning IR thresholds and thelike.

6.3 Modularity

Constructing the robot in layers proved to be a good decision. The con-nections between the layers were tagged with small schema-notes of whatcable would go where. This made the robot very easy to take apart andmore importantly to assemble again. As stated earlier switching a brokengearbox took no more than 10 minutes even though the whole robot hadto be taken apart just to get access to the motors.

6.4 Battery

It was recommended to use alkaline batteries for the tournament and therelatively old NiCd accumulators during lab work. In our experience,the NiCd accumulators turned out to be better then the alkaline batteries.Since our robot aimed for speed, we run our motors at maximum powermost of the time. It really felt like a good NiCd accumulator with it’s muchlower inner resistance could better support the high power consumptionthat were needed. With a good NiCd accumulator, the higher energy den-sity of alkaline batteries could easily be dismissed, since the accumulatorwould easily last for the whole tournament.

6.5 Stable platform

Out robot construction was very solid, with the exception of the stick thatcould get a little bent if taking a hard tackle. This exposed some problemswith the reflex sensors. Since we had one reflex sensor at the far end of the

20

stick, it would sometimes get to high above the ice and signal black flooreven when that was not the case. This behavior could have been avoidedif the stick was constructed as an integral part of the base frame instead of,as in our case, later attached to the construction.

6.6 Shooting mechanism

A shooting mechanism of some sort would greatly improve the robotsability to score goals. With just the slightest push to the puck a goal move-ment could have been completely avoided. This would clearly have beenan improvement and probably worth the extra time required to build.

6.7 Speed

Roadkill was relatively fast compared to most of his opponents. Thisproved to be a winning quality which gave him many opportunities toscore goals. Sadly, he often fell short at the goal line, due to an ineffectivegoal "quirk".

21

References

[1] M. Bratt: Course Notes III - Robotics and Autonomous SystemsComputational Vision an Active Perception Laboratory, KTH, 2003.http://www.nada.kth.se/kurser/kth/2D1426/L3_2003b.pdf

[2] Data Sheet for TSL260, TSL261, TSL262 IR LIGHT-TO-VOLTAGEOPTICAL SENSORShttp://www-2.cs.cmu.edu/~RAS/old/DataSheets/tsl260.pdf

[3] C. Robertson et al.: R2D2 an Autonomous RobotMay 23, 2003http://www.nada.kth.se/kurser/kth/2D1426/reports2003/R2D2.pdf

[4] A. Conradi et al: Robotics and Autonomous Systems – Project ReportMay 26, 2003http://www.nada.kth.se/kurser/kth/2D1426/reports2003/FejkOpaque.pdf

[5] P. Alexius et al: Nätagget An Autonomous RobotJune 5, 2002http://www.nada.kth.se/kurser/kth/2D1426/reports2002/Natagget.pdf

[6] K. Danielsson et al: Robotics and Autonomous Systems Report onProject WorkJuly 25, 2001http://www.nada.kth.se/kurser/kth/2D1426/reports2001/Kakmonstret.pdf

[7] PIC16F87X Data Sheet 28/40-Pin 8-Bit CMOS FLASH Microcontrollershttp://www.microchip.com/download/lit/pline/picmicro/families/16f87x/30292c.pdf

22

A Part list

A.1 Parts on motherboard

1. 1 PIC (main porcessor) PIC16F877 40-pin Microchip Technology Inc.

2. 1 PIC (for IR) PIC16F876 28-pin Microchip Technology Inc.

3. 1 Signal converter for RS-232

4. 2 Motor driver circuit L293NE SGS Thomson

A.2 Other parts

1. 3 Reflex detector ITR8307 Everlight

2. 5 IR sensors TSL261 Texas instr.

3. 4 Slotted opto detector ITR8010 Everlight

4. 2 12 V motor with 10:1 gear HL149 Micromotor

5. 1 Piezo electric Speaker

6. 1 LCD PC1602D A Powertip

7. 1 7.2 V NiCd accumulators

8. 1 Voltage booster board, 7.2V to 14.5 V

9. 1 LED driver board

10. 4 Encoder discs, 4 sectors

23

B Source code

B.1 roadkill.c

1 //####################################################################// Main code for the project in 2D1426, Robotics and Autonomous// Systems, per 1 2003// (c) Fredrik Dahlström, Jakob Lublin, Peter Osagie// roadkill.c 2003-10-16//####################################################################

#include <pic.h>10 #include <conio.h>

#include "defines.h"#include "lcd.h"#include "adc.h"#include "button.h"#include "sprint.h"#include "debug.h"#include "ir_comm.h"#include "eeprom.h"#include "pwm.h"

20 #include "intr.h"

__CONFIG(0x3FB2);

// math macros#define MIN(x,y) (x < y ? x : y)#define MAX(x,y) (x > y ? x : y)#define ABS(x) (((x) < 0) ? (-(x)) : (x))#define NOT_ZERO(x) ( ((x)<0) ? (1) : (x) )

30 // constants#define MAX_FWD_SPEED_L 127#define MAX_FWD_SPEED_R 127#define MAX_REV_SPEED_L -128#define MAX_REV_SPEED_R -128#define CURRENT_SPEED ((current_speed_l + current_speed_r)/2)#define SPEED_SAMPLE_INTERVAL 100#define RETURN_TO_CENTER_TIME 500#define STUCK_TIME 1500

40 // reflex constants#define REFLEX_F 0#define REFLEX_S 1#define REFLEX_B 2

24

// reflex macros#define REFLEX_FRONT (sample_ad_channel(REFLEX_F))#define REFLEX_STICK (sample_ad_channel(REFLEX_S))#define REFLEX_BACK (sample_ad_channel(REFLEX_B))#define REFLEX_FRONT_IS_BLACK (REFLEX_FRONT > 240)

50 #define REFLEX_STICK_IS_BLACK (REFLEX_STICK > 200)#define REFLEX_BACK_IS_BLACK (REFLEX_BACK > 200)

// ir constants#define IR_FR 0#define IR_FL 1#define IR_BR 2#define IR_BL 3#define IR_ST 4

60 // ir macros#define IR_FRONT_LEFT(x) (ir_value(IR_FL, x))#define IR_FRONT_RIGHT(x) (ir_value(IR_FR, x))#define IR_BACK_LEFT(x) (ir_value(IR_BL, x))#define IR_BACK_RIGHT(x) (ir_value(IR_BR, x))#define IR_STICK(x) (ir_value(IR_ST, x))#define IR_FRONT(x) (IR_FRONT_LEFT(x) + IR_FRONT_RIGHT(x))#define IR_BACK(x) (IR_BACK_LEFT(x) + IR_BACK_RIGHT(x))#define IR_LEFT(x) (IR_FRONT_LEFT(x) + IR_BACK_LEFT(x))#define IR_RIGHT(x) (IR_FRONT_RIGHT(x) + IR_BACK_RIGHT(x))

70 #define IR_TOTAL(x) (IR_FRONT(x) + IR_BACK(x) + IR_STICK(x))#define IR_TOP(x) (IR_FRONT(x) + IR_BACK(x))

// combined ir macros#define HAVE_PUCK (IR_STICK(PUCK) >= 5000)#define CAN_SEE(x) (IR_TOTAL(x) > 20)#define IS_TO_LEFT(x) (IR_LEFT(x) >= IR_RIGHT(x))#define IS_TO_RIGHT(x) (IR_LEFT(x) < IR_RIGHT(x))#define IS_INFRONT(x) (IR_FRONT(x) >= IR_BACK(x))#define IS_BEHIND(x) (IR_FRONT(x) <= IR_BACK(x))

80 #define IS_HARD_LEFT(x) (IR_BACK_LEFT(x)> IR_FRONT_LEFT(x) &&IR_LEFT(x)>IR_RIGHT(x))#define IS_HARD_RIGHT(x) (IR_BACK_RIGHT(x)> IR_FRONT_RIGHT(x) &&IR_RIGHT(x)>IR_LEFT(x))#define IN_FQ(t) (IR_FRONT(t) > IR_BACK(t) && IR_FRONT(t) > IR_LEFT(t)&&IR_FRONT(t) > IR_RIGHT(t))#define TRYING_TO_SCORE (IS_CLOSE_TO_GOAL(OFF_GOAL) &&state==GOTO_GOAL ||state==FIRE || state==RETURN_TO_CENTER)

90 #define IS_CLOSE_TO_GOAL(x) (IR_TOP(x)>130)#define IS_CLOSE_TO_ANY_GOAL (IS_CLOSE_TO_GOAL(OFF_GOAL) ||IS_CLOSE_TO_GOAL(DEF_GOAL))#define ANY_REFLEX_IS_BLACK (REFLEX_FRONT_IS_BLACK ||

25

REFLEX_STICK_IS_BLACK ||REFLEX_BACK_IS_BLACK)

// state constants#define AVOID_GOAL 0#define START_SLEEP 2

100 #define STUCK_WITH_PUCK 3#define STUCK_WITHOUT_PUCK 4#define GOTO_PUCK 5#define GOTO_GOAL 6#define FIRE 7#define RETURN_TO_CENTER 8

// button modes#define RELEASE 1enum button_t {FUNCTION_B=0, GOAL_B, UP_B, DOWN_B};

110 enum button_mode_t {CHANGE_SPEED, MODE1, MODE2, MODE3, MODE4, MODE5,MODE6,MODE7, MODE8, MODE9, MODE10, MODE11, MODE12, MODE13, LAST_MODE}button_mode =CHANGE_SPEED;

// variablesbank2 int past_speed_buff_l[4] = {0};bank2 int past_speed_buff_r[4] = {0};bank2 int current_speed_l;

120 bank2 int current_speed_r;bank2 int current_power_l = 0;bank2 int current_power_r = 0;signed char last_speed_l=0;signed char last_speed_r=0;bank3 signed int button_value=0;bank3 char motor_diff_r=0;bank3 unsigned int puck_score_distance=50;bank3 unsigned char batt_power_constant = 128;bit start_sleep_switch;

130 bank2 unsigned char state;char buffer[7]; // can’t be in another bankbank3 int last_move_time = 0;bit should_be_moving = 0;bank3 unsigned int return_to_center_started;bank3 unsigned int pause_display;bank3 unsigned int loop_time=0;bank3 char fire_version = 1;bank3 unsigned int last_move_time_ticks = 0;

140 // tunesconst char nothing[] = {0,0};const char mini[] = {0x22,20, 0,0};

26

const char hard_right[] = {0x11,5, 0,0};const char hard_left[] = {0x33,5, 0,0};const char go_home_tune[] = {0x10,20, 0x20,20,0x30,20,0x40,20,0x50,20,0,0};const char avoid_goal_tune[] = {0xF0,10, 0x20,10,0xF0,10,0x20,10,0,0};const char goal_tune[] = {0x10,20, 0x20,20,

150 0x30,20,0x40,20,0x50,20,0,0};const char mini2[] = {0x55,20, 0,0};const char no_goal[] = {0x55,20, 0x25,20, 0xFF,20, 0x55,20, 0x25,20,0,0};const char no_goal2[] = {0x55,10, 0x25,10, 0,0};const char no_limit[] = {

0x29,16, 0xFF,16, 0x29,16, 0xFF,16, 0x29,16, 0x27,16, 0x29,16, 0x30,16,0x29,16, 0xFF,16, 0x29,16, 0xFF,16, 0x29,16, 0x27,16, 0x29,16, 0x30,16,0x29,16, 0xFF,16, 0x29,16, 0xFF,16, 0x29,16, 0x27,16, 0x29,16, 0x30,16,0x22,16, 0xFF,16, 0x22,16, 0xFF,16, 0x25,16, 0x22,16, 0x25,16, 0x27,16,

160 0,0};

// forward declaration of functionsvoid init(void);void sleep(int);void turn_to_puck(void);void check_buttons(void);void move_to_puck(void);void set_speed2(signed int l, signed int r); // compensationvoid show_data(char mode, signed int n, char target);

170 void update_last_move_time(void);void sample_speed(void);

// state-functionsvoid avoid_goal(void);void start_sleep(void);void stuck_with_puck(void);void stuck_without_puck(void);void goto_puck(void);void goto_goal(void);

180 void fire(void);void fire2(void);void return_to_center(void);void set_state(void);

// include delay and display functions#include "extras.inc"

//--------------------------------------------------------------------void main() {

190 static int last_loop;start_sleep_switch = 1;

27

init();

while (1) {loop_time = soft_time() - last_loop;last_loop = soft_time();

// no ir_wait() is used, since we want the extra time for other200 things

//ir_wait();

check_buttons();update_last_move_time();sample_speed();set_state(); // selects what state we are in

switch (state) {case AVOID_GOAL:

210 avoid_goal();break;

default:case START_SLEEP:

start_sleep();break;

case STUCK_WITH_PUCK:stuck_with_puck();break;

case STUCK_WITHOUT_PUCK:220 stuck_without_puck();

break;case GOTO_PUCK:

goto_puck();break;

case GOTO_GOAL:goto_goal();break;

case FIRE:if (fire_version == 1) // fire variable controlled via menu

230 systemfire();

elsefire2();

break;case RETURN_TO_CENTER:

return_to_center();break;

}}

240 }

28

//--------------------------------------------------------------------void avoid_goal(void) {

play_tune(avoid_goal_tune);if (REFLEX_STICK_IS_BLACK) {

set_speed2(-128,-128);show_data(AVOID_GOAL, 0, OFF_GOAL);sleep(150);

}250 if (REFLEX_FRONT_IS_BLACK) {

set_speed2(-128,-128);show_data(AVOID_GOAL, 0, OFF_GOAL);sleep(200);

}if (REFLEX_BACK_IS_BLACK) {

set_speed2(127,127);show_data(AVOID_GOAL, 0, OFF_GOAL);sleep(200);

}260 }

//--------------------------------------------------------------------void start_sleep(void) {

set_speed2(0,0);show_data_realtime(START_SLEEP, 0, OFF_GOAL);

}//--------------------------------------------------------------------void stuck_with_puck(void) {

if (IR_RIGHT(OFF_GOAL) > IR_LEFT(OFF_GOAL) || IR_LEFT(DEF_GOAL) >IR_RIGHT(DEF_GOAL)) {

270 show_data(STUCK_WITH_PUCK, 0, OFF_GOAL);play_tune(no_goal);set_speed2(-128, 127);sleep(700);set_speed2(-115, 115);sleep(500);

}}//--------------------------------------------------------------------void stuck_without_puck(void) {

280 show_data(STUCK_WITHOUT_PUCK, 0, OFF_GOAL);play_tune(go_home_tune);set_speed2(-128, -128);sleep(200);

}//--------------------------------------------------------------------void goto_puck(void) {

bank3 static signed int diff;static bit brake_done = 0;bank3 static int speed;

29

290diff = IR_FRONT_LEFT(PUCK) - IR_FRONT_RIGHT(PUCK);diff = (10 * diff) / IR_FRONT(PUCK);

if (IN_FQ(PUCK)) {speed = ABS(diff)<7 ? 127 : 115; // if straight ahead, go fastspeed = IS_CLOSE_TO_GOAL(OFF_GOAL)? 100:127;set_speed2(speed-diff, speed+diff);

} else {speed = 127;

300 if (IS_HARD_LEFT(PUCK)) { // hard leftbrake_done = 0;set_speed2(-(speed),speed);//play_tune(hard_left);

} else if (IS_HARD_RIGHT(PUCK)) { // hard rightbrake_done = 0;set_speed2(speed,-(speed));//play_tune(hard_right);

} else if (IS_TO_LEFT(PUCK)){brake_done = 0;

310 set_speed2(-100, 100); // easy left} else if (IS_TO_RIGHT(PUCK)){ // easy right

brake_done = 0;set_speed2(100, -100);

} else {speed = ABS(diff)<7 ? 127 : 115; // everything else...set_speed2(speed-diff, speed+diff);

}}

320 show_data_realtime(GOTO_PUCK, diff, PUCK);}//--------------------------------------------------------------------void goto_goal(void) {

bank3 static signed int diff;bank3 static int speed;

diff = IR_FRONT_LEFT(OFF_GOAL) - IR_FRONT_RIGHT(OFF_GOAL);diff = (7* diff) / IR_FRONT(OFF_GOAL);

330 if (ABS(diff)<6 && IR_TOP(OFF_GOAL)>100) {speed = IS_CLOSE_TO_GOAL(OFF_GOAL)? 105 : 127;set_speed2(speed-diff/2, speed+diff/2);

}

if (diff<5 && diff>-13 && IS_INFRONT(OFF_GOAL)) {speed = IS_CLOSE_TO_GOAL(OFF_GOAL)? 105 : 127;set_speed2(speed-diff, speed+diff);

} else {

30

speed = 127; // 120 before340 if (IS_HARD_LEFT(OFF_GOAL)) { // hard left

set_speed2(-(speed),speed);} else if (IS_HARD_RIGHT(OFF_GOAL)) { // hard right not allowed,

go leftset_speed2(-speed,speed);

} else if (IS_TO_LEFT(OFF_GOAL)){set_speed2(-115, 115); // easy left (100 before)

} else if (IS_TO_RIGHT(OFF_GOAL)){ // easy right not allowd, goleft

set_speed2(-115, 115);350 } else {

speed = 127; // everything elseset_speed2(speed-diff, speed+diff);

}}show_data_realtime(GOTO_GOAL, diff, OFF_GOAL);

}//--------------------------------------------------------------------void fire(void) {

unsigned int ticks=0;360 int diff;

set_speed2(-128,-128);sleep(400);set_speed2(-128,0);sleep(80); // was 100

#define G_DIR -7for (;;) {

diff = IR_FRONT_LEFT(PUCK) - IR_FRONT_RIGHT(PUCK);370 diff = (10* diff) / IR_FRONT(PUCK);

if (diff<G_DIR) { //-1set_speed2(127,-128);sleep(10);set_speed2(-80,80);sleep(10);

} else if(diff>G_DIR) { //+1set_speed2(-128,127);sleep(10);set_speed2(80,-80);

380 sleep(10);} else {

break;}

}

for (;;) {

31

if (REFLEX_FRONT_IS_BLACK) {//play_tune(mini);

390 break;}set_speed2(118,118);if (++ticks>8000) { // 5000 is almost ehough

break;}

}

set_speed2(-128,-128);sleep(500);

400play_tune(no_limit);

return_to_center_started = soft_time();state = RETURN_TO_CENTER;return;

}410 //--------------------------------------------------------------------

void fire2(void) {unsigned int ticks=0;int diff;

#define S_DIR -7set_speed2(-128,-128);sleep(200);for (;;) {

diff = 8*IR_LEFT(PUCK) - IR_RIGHT(PUCK);420 if (diff>0) { //-1

set_speed2(-128,127);sleep(10);set_speed2(0,0);sleep(10);

} else {break;

}}set_speed2(-128,-128);

430 sleep(400);

#define G_DIR -7for (;;) {

diff = IR_FRONT_LEFT(PUCK) - IR_FRONT_RIGHT(PUCK);diff = (10* diff) / IR_FRONT(PUCK);if (diff<G_DIR) { //-1

32

set_speed2(127,-128);sleep(10);set_speed2(-80,80);

440 sleep(10);} else if(diff>G_DIR) { //+1

set_speed2(-128,127);sleep(10);set_speed2(80,-80);sleep(10);

} else {break;

}

450 }

for (;;) {if (REFLEX_FRONT_IS_BLACK) {

//play_tune(mini);break;

}set_speed2(118,118);if (++ticks>15000) { // 5000 is almost ehough

break;460 }

}

set_speed2(-128,-128);sleep(500);

play_tune(no_limit);

return_to_center_started = soft_time();state = RETURN_TO_CENTER;

470 return;

}//--------------------------------------------------------------------void return_to_center(void) {

bank2 static char speed = 127;bank2 static int diff = 0;diff = IR_BACK_LEFT(DEF_GOAL) - IR_BACK_RIGHT(DEF_GOAL);diff = (10 * diff) / IR_FRONT(DEF_GOAL);set_speed2(-(speed-diff),-(speed+diff));

480 show_data_realtime(RETURN_TO_CENTER, diff, DEF_GOAL);}//--------------------------------------------------------------------void update_last_move_time(void) {

static unsigned char old_enc1 = 0;static unsigned char old_enc2 = 0;

33

if (CURRENT_SPEED==0) {last_move_time_ticks++;

} else {last_move_time_ticks = 0;

490 }}

//--------------------------------------------------------------------void sample_speed(void){

bank2 static unsigned int ticks = 0;bank2 static unsigned char speed_buf_index = 0;bank2 static unsigned char old_enc1_pos = 0, old_enc2_pos = 0;

if(++ticks >SPEED_SAMPLE_INTERVAL) {500 ticks = 0;

past_speed_buff_l[speed_buf_index] = (enc1_pos - old_enc1_pos);past_speed_buff_r[speed_buf_index++] = (enc2_pos - old_enc2_pos);current_speed_l =

(past_speed_buff_l[0]+past_speed_buff_l[1]+past_speed_buff_l[2]+past_speed_buff_l[3]);

current_speed_r =(past_speed_buff_r[0]+past_speed_buff_r[1]+past_speed_buff_r[2]+past_speed_buff_

510 r[3]);current_speed_l= (signed char)current_speed_l;current_speed_r = (signed char)current_speed_r;if (speed_buf_index == 4)

speed_buf_index = 0;current_speed_l = (150*current_speed_l)/SPEED_SAMPLE_INTERVAL;current_speed_r = (150*current_speed_r)/SPEED_SAMPLE_INTERVAL;old_enc1_pos = enc1_pos;old_enc2_pos = enc2_pos;

}520 }

//--------------------------------------------------------------------// selects a state based on sensor information and the current statevoid set_state(void) {#ifndef RELEASE

static unsigned char times_cant_see_puck = 0;#endif

// if a START command has not been issued from the menu system, dont530 move.

if (start_sleep_switch == 1) {state = START_SLEEP;return;

}

34

// level 1 (overrides all levels) - ’goalzone’ sensingif (!TRYING_TO_SCORE && ANY_REFLEX_IS_BLACK && IS_CLOSE_TO_ANY_GOAL)

{state = AVOID_GOAL;

540 return;}if (REFLEX_FRONT_IS_BLACK || REFLEX_STICK_IS_BLACK) {

if (IR_TOP(OFF_GOAL)>150 && state==GOTO_GOAL) {state = FIRE;return;

}}

// level 2 - ’stuck’ sensing550 if (should_be_moving==1 && last_move_time_ticks>3000) {

last_move_time_ticks = 0;if (HAVE_PUCK) {

state = STUCK_WITH_PUCK;} else {

state = STUCK_WITHOUT_PUCK;}return;

}

560 if (state == RETURN_TO_CENTER) {if ((IR_BACK_LEFT(DEF_GOAL)<25 && IR_BACK_RIGHT(DEF_GOAL)<25) ||

(IR_BACK(DEF_GOAL)<80) &&!passed(return_to_center_started + RETURN_TO_CENTER_TIME)){

return;} else {

set_speed2(0, 0);state = GOTO_PUCK;

}}

570#ifndef RELEASE

if (CAN_SEE(PUCK)) {times_cant_see_puck =0;

} else {++times_cant_see_puck;if (times_cant_see_puck > 50) {

start_sleep_switch = 1;state=START_SLEEP;return;

580 }}

#endif

35

if (HAVE_PUCK) {state = GOTO_GOAL;

} else {state = GOTO_PUCK;

}}

590

36

B.2 extras.inc

1 //####################################################################// External functions for roadkill.ce for the project in 2D1426,// Robotics and Autonomous Systems, per 1 2003// (c) Fredrik Dahlström, Jakob Lublin, Peter Osagie// extras.inc 2003-10-16//####################################################################

//--------------------------------------------------------------------10 // Initialize the hardware and the software

void init(void) {ir_init(); //initialize IR co-processor communicationinit_pwm(); //initialize pwm for motor controlinit_soft_tmr(); //initialize soft timerinit_sound(); //initialize sound generatorinit_enc();ADCON1 = 0b00000100;TRISA0 = TRISA1 = TRISA3 = 1;PEIE = 1; // peripheral interrupts enable

20 ei(); // global interrupt enableset_lcd_power(1);sleep(100);init_lcd();init_buttons();

}

//--------------------------------------------------------------------void show_data_realtime(char m, signed int n, char t) {

static int times;30 if (++times%45 != 0)

return;show_data(m,n,t);

}

//--------------------------------------------------------------------void show_data(char mode, signed int n, char target) {

if (!passed(pause_display + 2000) && pause_display != 0) {return;

}40 pause_display = 0;

clear_disp();switch (mode) {

case AVOID_GOAL:lcd_print1("AG", 0);sprint16(buffer, REFLEX_STICK);lcd_print1("s ", 4);

37

lcd_print_at_cursor(buffer);sprint16(buffer, REFLEX_FRONT);

50 lcd_print2("f ", 4);lcd_print_at_cursor(buffer);sprint16(buffer, IR_TOP(OFF_GOAL));lcd_print1("o", 10);lcd_print_at_cursor(buffer);sprint16(buffer, IR_TOP(DEF_GOAL));lcd_print2("d", 10);lcd_print_at_cursor(buffer);return; //break;

case GOTO_PUCK:60 lcd_print1("PUC", 0); break;

case START_SLEEP:lcd_print1("SSL", 0); break;

case GOTO_GOAL:lcd_print1("GOA", 0); break;

case FIRE:lcd_print1("FIR", 0); break;

case STUCK_WITH_PUCK:lcd_print1("ST+", 0); break;

case STUCK_WITHOUT_PUCK:70 lcd_print1("ST-", 0); break;

case RETURN_TO_CENTER:lcd_print1("RET", 0); break;

default:lcd_print1("!!!", 0); break;

}

if (button_mode == MODE1) {sprint16(buffer, (signed int)last_speed_l);lcd_print1("#", 4);

80 lcd_print_at_cursor(buffer);

sprint16(buffer, (signed int)last_speed_r);lcd_print1("#", 10);lcd_print_at_cursor(buffer);

lcd_print2("MOT", 0);

} else if (button_mode>= MODE2 && button_mode<= MODE4 ) {if (button_mode == MODE2) {

90 target = OFF_GOAL;lcd_print2("OFF", 0);

}else if (button_mode == MODE3) {target = DEF_GOAL;lcd_print2("DEF", 0);

}else if (button_mode == MODE4) {target = PUCK;

38

lcd_print2("PUC", 0);}

100 sprint16(buffer, IR_FRONT(target));lcd_print1("F", 4);lcd_print_at_cursor(buffer);

sprint16(buffer, IR_BACK(target));lcd_print1("B", 10);lcd_print_at_cursor(buffer);

sprint16(buffer, IR_LEFT(target));lcd_print2("L", 4);

110 lcd_print_at_cursor(buffer);

sprint16(buffer, IR_RIGHT(target));lcd_print2("R", 10);lcd_print_at_cursor(buffer);return;

} else if (button_mode>= MODE5 && button_mode<= MODE7 ) {if (button_mode == MODE5) {

target = OFF_GOAL;lcd_print2("OFF", 0);

120 }else if (button_mode == MODE6) {target = DEF_GOAL;lcd_print2("DEF", 0);

}else if (button_mode == MODE7) {target = PUCK;lcd_print2("PUC", 0);

}

sprint16(buffer, IR_FRONT_LEFT(target));lcd_print1("#", 4);

130 lcd_print_at_cursor(buffer);

sprint16(buffer, IR_FRONT_RIGHT(target));lcd_print1("#", 10);lcd_print_at_cursor(buffer);

sprint16(buffer, IR_BACK_LEFT(target));lcd_print2("#", 4);lcd_print_at_cursor(buffer);

140 sprint16(buffer, IR_BACK_RIGHT(target));lcd_print2("#", 10);lcd_print_at_cursor(buffer);return;

} else if (button_mode == MODE8) {sprint16(buffer, loop_time);

39

lcd_print1("loop time:", 4);lcd_print2(buffer,0);return;

} else if (button_mode == MODE9) {150 sprint16(buffer, REFLEX_STICK);

lcd_print1("S", 4);lcd_print_at_cursor(buffer);sprint16(buffer, REFLEX_FRONT);lcd_print1("F", 10);lcd_print_at_cursor(buffer);sprint16(buffer, REFLEX_BACK);lcd_print2("B", 4);lcd_print_at_cursor(buffer);return;

160 } else if (button_mode == MODE10) {sprint16(buffer, current_speed_l);lcd_print1("SPL:", 4);lcd_print1(buffer,10);sprint16(buffer, current_speed_r);lcd_print2("SPR:", 4);lcd_print2(buffer,10);sprint16(buffer, (current_speed_l+current_speed_r)/2);lcd_print2(buffer,0);return;

170 } else if (button_mode == MODE11) {sprint16(buffer, IR_STICK(PUCK));lcd_print1("STICK:", 4);lcd_print1(buffer,10);return;

} else if (button_mode == MODE12) {sprint16(buffer, IR_TOP(OFF_GOAL));lcd_print1("OFF:", 4);lcd_print1(buffer,10);sprint16(buffer, IR_TOP(DEF_GOAL));

180 lcd_print2("DEF:", 4);lcd_print2(buffer,10);return;

} else {sprint16(buffer, IR_FRONT_LEFT(target));lcd_print1("#", 4);lcd_print_at_cursor(buffer);

sprint16(buffer, IR_FRONT_RIGHT(target));lcd_print1("#", 10);

190 lcd_print_at_cursor(buffer);

sprint16(buffer, n);lcd_print2(buffer, 0);

40

sprint16(buffer, IR_BACK_LEFT(target));lcd_print2("#", 4);lcd_print_at_cursor(buffer);

sprint16(buffer, IR_BACK_RIGHT(target));200 lcd_print2("#", 10);

lcd_print_at_cursor(buffer);}

}

//--------------------------------------------------------------------void check_buttons(void){

char i;for(i=0;i<4;i++) handle_button(i); //handle all four buttonsif(bittst(buttons[UP_B],PRESSED)) {

210 button_value+=10;clear_disp();sprint16(buffer, button_value);lcd_print1("VALUE ",0);lcd_print_at_cursor(buffer);pause_display = soft_time();if (button_mode == MODE13) batt_power_constant = button_value;

}if(bittst(buttons[DOWN_B],PRESSED)) {

button_value-=10;220 clear_disp();

sprint16(buffer, button_value);lcd_print1("VALUE ",0);lcd_print_at_cursor(buffer);pause_display = soft_time();if (button_mode == MODE13) batt_power_constant = button_value;

}if(bittst(buttons[GOAL_B],PRESSED)) {

if (start_sleep_switch == 1) {clear_disp();

230 lcd_print1("STARTING",0);start_sleep_switch =0;pause_display = soft_time();

} else {clear_disp();if (++fire_version == 3)

fire_version = 1;lcd_print1("FIRE ",0);sprint16(buffer, fire_version);lcd_print_at_cursor(buffer);

240 pause_display = soft_time();}

}if(bittst(buttons[FUNCTION_B],PRESSED)) { // the only one still

41

workingplay_tune(mini);button_mode++;if (button_mode == LAST_MODE) {

button_mode = CHANGE_SPEED;}

250 clear_disp();switch (button_mode) {

default: lcd_print1("ILLEGAL MODE",0); break;case CHANGE_SPEED: lcd_print1("0 IR TARGET",0); break;case MODE1: lcd_print1("1 MOTORSPEED",0); break;case MODE2: lcd_print1("2 IR ZONES OFF-G",0); break;case MODE3: lcd_print1("3 IR ZONES DEF-G",0); break;case MODE4: lcd_print1("4 IR ZONES PUC",0); break;case MODE5: lcd_print1("5 IR OFF-G",0); break;case MODE6: lcd_print1("6 IR DEF-G",0); break;

260 case MODE7: lcd_print1("7 IR PUCK",0); break;case MODE8: lcd_print1("8 LOOP TIME",0); break;case MODE9: lcd_print1("9 REFLEX",0); break;case MODE10: lcd_print1("10 SPEED",0); break;case MODE11: lcd_print1("11 IR STICK",0); break;case MODE12: lcd_print1("12 IR TOP",0); break;case MODE13: lcd_print1("13 SC-DISTANCE",0);

button_value=batt_power_constant; break;}pause_display = soft_time();

270 }clear_button_events();

}

//--------------------------------------------------------------------void set_speed2(signed int l, signed int r) {

if (r<0) r-=motor_diff_r; // compensate for bad motorif (r>0) r+=motor_diff_r;if (l>MAX_FWD_SPEED_L) l = MAX_FWD_SPEED_L;if (l<MAX_REV_SPEED_L) l = MAX_REV_SPEED_L;

280 if (r>MAX_FWD_SPEED_R) r = MAX_FWD_SPEED_R;if (r<MAX_REV_SPEED_R) r = MAX_REV_SPEED_R;last_speed_l = l;last_speed_r = r;/*if (last_power_time==0 && l!=0 && r!=0) {

last_power_time = soft_time();} else if (l==0 && r==0) {

last_power_time = 0;}*/

290 should_be_moving = (l!=0 && r!=0)?1:0;motors(l,r);

}

42

//--------------------------------------------------------------------void sleep(int msec) {

static int sometime;sometime = soft_time();while(1) {

if (!TRYING_TO_SCORE && ANY_REFLEX_IS_BLACK &&300 IS_CLOSE_TO_ANY_GOAL) {

state = AVOID_GOAL;break;

}if (passed(sometime + msec)) {

break;}

}}

43

B.3 Pictures

Figure 10: Top view showing the motherboard-section.

44

Figure 11: Another view from the front side.

45