Jaws

45
Project report Robotics and Autonomous systems 2D1426 Nada, KTH Erik Joelsson, Stefan Nystr ¨ om and Fredrik Sj ¨ ogren 31st May 2002 Abstract In the course 2D1426 Robotics and Autonomous systems at Nada, KTH, groups of three people were to build a robot capable of playing a special game called robot hockey. Some vital parts, like motors and various detec- tors, were given each group but most of the design and construction was done by the students. This paper describes in detail how Jaws, one of these robots, was built and programmed. 1

Transcript of Jaws

Page 1: Jaws

Project reportRobotics and Autonomous systems 2D1426

Nada, KTH

Erik Joelsson, Stefan Nystrom and Fredrik Sjogren

31st May 2002

Abstract

In the course 2D1426 Robotics and Autonomous systems at Nada, KTH,groups of three people were to build a robot capable of playing a specialgame called robot hockey. Some vital parts, like motors and various detec-tors, were given each group but most of the design and construction wasdone by the students. This paper describes in detail how Jaws, one of theserobots, was built and programmed.

1

Page 2: Jaws

Contents

1 Background 41.1 The game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.2 Constraints on the robot . . . . . . . . . . . . . . . . . . . . . . . 41.3 Material . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2 Sensing 62.1 IR sensors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.2 Reflex sensors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3 Manipulation, locomotion and navigation 103.1 Construction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.2 Strategy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.3 Navigation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.4 Manipulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.5 Goal swing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

4 Communication 11

5 Programming environment and computer hardware 115.1 PIC microcontrollers . . . . . . . . . . . . . . . . . . . . . . . . . 115.2 Boards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125.3 Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125.4 Bootloader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

6 Electronics 136.1 Power . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136.2 Motors and speaker . . . . . . . . . . . . . . . . . . . . . . . . . . 146.3 IR sensors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146.4 The main PIC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146.5 LED driver board . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

7 Software implementation 147.1 Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157.2 Watchdog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

8 Results and conclusions 15

9 References 17

A RAS Motherboard schematic 18

B Parts list 19

C Source code 20

D Extra pictures 44

2

Page 3: Jaws

List of Figures

1 The rink. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 The puck. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 One of the goals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 The placement of the sensors. . . . . . . . . . . . . . . . . . . . . 75 The placement of the puck sensor. . . . . . . . . . . . . . . . . . 86 The placement of the reflex sensors (yellow circles), the motors

and the support points. . . . . . . . . . . . . . . . . . . . . . . . . 97 The placement of the boards. . . . . . . . . . . . . . . . . . . . . 128 Updating the software. . . . . . . . . . . . . . . . . . . . . . . . . 139 The question tree. . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

3

Page 4: Jaws

Figure 1: The rink.

1 Background

An important part of the course 2D1426 Robotics and Autonomous Systems [3]at NADA, KTH was constructing a robot. The students formed teams of threeand all teams built a robot capable of playing robot hockey. At the end of thecourse all robots competed in a course tournament.

1.1 The game

In each game [4] two robots faced each other on a rink that measured approxi-mately 2.40×1.20 m (See image 1 on page 4). At both ends of the rink there wasa semicircular black goal zone that the robots were not allowed to enter (Seeimage 3 on page 6). Both goals, the puck and all robots were equipped withIR LEDs blinking at different frequencies. By sorting these frequencies out therobots were able to navigate the rink.

A goal was scored when the puck (See image 2 on page 5) was in contactwith the red area in the center of the goal zone. The robot had to be aware thatit has scored a goal and show this by playing a tune. Failure to do this wouldresult in the goal being discarded. The robots were not allowed to grab thepuck but they did have a stick to guide it with.

1.2 Constraints on the robot

There were several constraints a robot must meet in order to participate inthe competition [4]. Among these were constraints on the size and shape ofthe robot as well as restrictions on what kinds of devices the robot may beequipped with.

4

Page 5: Jaws

Figure 2: The puck.

5

Page 6: Jaws

Figure 3: One of the goals.

1.3 Material

Each group were given some basic equipment to start from. A complete listcan be found in Appendix B. Among these were motors, a speaker for goalsignaling and a mothorboard with controller circuits. Some prewritten code forlow level control of motors, interpretation of IR signals and sound generation,were also given.

2 Sensing

2.1 IR sensors

The robot Jaws used five different IR sensors [11] for sensing its environment.Four of these sensors were used for sensing the direction and distance to

different objects such as the two goals, the puck and the opponent. Thesesensors were placed around the robot at different angles. By sensing whichwas the strongest and the second strongest sensor for an object, and checkingthe IR values for these sensors, it was possible to decide when the robot wasturned towards that object using a ratio between the strongest and the sec-ond strongest sensor combined with some ad hoc solutions. The sensors alsoenabled the robot to sense if it was close to an object using non trivial thresh-olding. See figure 4 on page 7 and appendix C (questions.h).

The fifth sensor was located at the front of the robot, sensing if the robothad the puck. This sensor was placed lower than the other sensors, level withthe IR transmitters of the puck. The reason for this was that it was only usedfor sensning the puck and never any other objects. The sensor was placed inlevel with the IR transmitters of the puck. If the input of the puck on this sensorwas higher than a threshold value, the robot thought it had the puck. This way

6

Page 7: Jaws

Forward

Sensor 1Sensor 0

Robot

Sensor 2Sensor 3

Figure 4: The placement of the sensors.

7

Page 8: Jaws

Figure 5: The placement of the puck sensor.

no mecanical sensor, like for example a button, was needed for sensing if therobot had the puck. See figure 5 on page 8.

2.2 Reflex sensors

Under the robot there were three reflex sensors. See figure 6 on page 9. Thesewere used for detecting the black markings on the white surface of the rink. Bysending the input from these sensors to an A/D-converter and then comparingreadings with threshold values, it was possible to find out if the sensor waslocated above a white surface or a black marking.

One of the reflex sensors also had another task. When the robot movedthe small vibrations and the small changes of color on the floor would give asmall but detectable change in the the reading from the sensor. If the changewas smaller than a threshold value for twelve subsequent readings, the robotthought it was stuck and would do an evasive maneuver. This way it waspossible to detect almost every time it happened, even if the wheels did notstop because of the slipperiness of the floor. Sensors detecting the rotation ofthe wheel could not have accomplished that.

8

Page 9: Jaws

Figure 6: The placement of the reflex sensors (yellow circles), the motors andthe support points.

9

Page 10: Jaws

3 Manipulation, locomotion and navigation

3.1 Construction

To be able to move, Jaws was equiped with two wheels driven by separatemotors [9]. The wheels position can be viewed in figure 4 on page 7. The speedand direction of each motor could be controlled individually which made itpossible to make the robot both spin around on the spot and go forwards andbackwards.

With only two wheels a robot would have a hard time keeping its balance.Jaws had two supporting points in addition to the wheels to make this possible.

The first stick was just a bit of meccano sticking out from the robot body. Itwas effective enough but we wanted the robot to be able to turn faster whileguiding the puck. Since the rules stated that the robot was not permitted tograb the puck, it was decided to build a stick with a rotating rubber band usinga third motor [10] (see figure 5 on page 8). By also putting rubber on the robotbody the intention was to make the puck stick there. It did not prove to be anenormous improvement but it probably gave some effect.

3.2 Strategy

The strategy was simple. First look for the puck, turn to face it and then go toit. Whith the puck securely between the stick and the body of the robot, try tofind the opponents goal and turn anti-clockwise, positioning it in front of therobot. Go forward until the goal is reached and do the special goal swing toscore.

3.3 Navigation

To navigate the rink input from the IR sensors was used. In some cases it washard to find constant threshold values to compare the input to. The reason wasthat the IR sensors was very sensitive to direction but not in a linear way, thusgiving much stronger input from a target in front of one sensor than if the targetwas between two sensors. This problem was never completely solved but themethod used was taking the quotient of the strongest and second strongest IRinput and comparing it with a threshold value. The exact expression can befound in the source code.

3.4 Manipulation

The most obvious actions will not be described here, instead we will look intosome of the harder problems encountered.

An early idea was to almost never let the robot go straight forward. Thereason was that the motors were not equally strong, and it was hard to exactlyface a target.

When the robot was looking for the puck it often turned too much and tooquickly, describing a pendular motion back and forth, instead of just facingthe puck. Also when it came forward at full speed it knocked away the puckand had to follow it for a while before getting hold of it. The solution to thisproblem was to reduce the speed when close to the puck.

10

Page 11: Jaws

When turning with the puck it was hard to keep it close enough to therobot’s body. Therefore the center of rotation was moved from the center of therobot to the left wheel. Later that wheel was even given a little speed forwardto be able to turn around even faster with the puck. The obvious drawbackwas the increased radius of a turn, resulting in the robot getting stuck againstthe wall.

It was also very hard for the robot to stop fast enough before the goal zone.Trying to slow down was very hard when the motors had reached a high speedand going slow also meant losing power. If the motors were set to go as slowas was needed when coming at full speed they would not have enough powerto move the puck from zero speed. The solution was to let the motors alter-nate between full speed and stop for short periods of time (about 50 ms). Thisproved very effective and the robot always stopped in time.

As described above the floor sensors were used to detect if the robot wasmoving at all. If it was not, the robot most likely had the puck pushed againsta wall and was trying to turn to the goal (anti-clockwise). A simple way to getout of this situation was to back the left wheel a bit to turn the robot from thewall without losing the puck.

3.5 Goal swing

Many different techniques for scoring were tried and discarded. The finalchoice was to stop at the goal zone, turning anti-clockwise a little bit to putthe puck in the right position and then turn clockwise at full speed hitting thePuck staight into the goal. In the first turn the technique with full speed atshort intervalls was used to get the puck in a more accurate position.

4 Communication

The main means of communication of the Jaws robot was the LCD situatedon its top. The LCD displayed the current values of the different sensors aswell as other useful debug information. Also used for debugging were twoLEDs (positioned as the eyes of the robot). These LEDs indicated if the mainprogram and the interrupt routine were running. The speaker of the robot wasalso used to communicate information. It played a tune at startup to ensurethat everything was switched on and to detect if the robot had reset. It alsoplayed a tune to communicate that the robot had reached the edge of the goalzone. When the robot scored a goal it played the theme of Alfons Aberg [1].In order to be able to play such an advanced tune the handed out code wasaltered slightly to enable longer tunes.

5 Programming environment and computer hardware

5.1 PIC microcontrollers

The robot was based on two PIC micro controllers [7]. One of these, a PIC16F876,was preprogrammed by the course director to control the IR beacon and per-form the analysis of the IR values. The simplified data was transmitted to the

11

Page 12: Jaws

Figure 7: The placement of the boards.

main microcontroller, a PIC16F877. The main microcontroller did all the workcontrolling the robot.

5.2 Boards

The robot contained several boards (See image 7 on page 12). The most impor-tant was the main board containing the two PICs, electronics for controlling themotors, speakers and servos and connectors for the IR receivers. To the main-board a RS232 connector board was connected. The IR beacon and the reflexdetectors was connected to a LED driver board. An LCD was connected to themother board for debugging. The whole robot was powered by a 7.2 V battery.A voltage booster card, which transformed the 7.2 V from the battery to 14.5 V,was used to give more power to the main motors and the LED driver board.

5.3 Compiler

All code was written in C using MPLAB [8] as a developing environment.MPLAB used Hi-Tech PIC C [6] for compiling.

5.4 Bootloader

A special program, the bootloader, was preprogrammed into the main PIC bythe course director. The bootloader made it possible to, via the serial RS232interface, download an updated version of the program for the main PIC (notincluding the bootloader) and write it into the onboard flash memory. Thebootloader was normally not the program started when the robot was reset. Tomake this happen pin RC0 on the main PIC had to be changed from 1 (Normal

12

Page 13: Jaws

Figure 8: Updating the software.

mode) to 0 (Bootloader mode). This was done by connecting a switch to thispin which could change the level between 1 and 0.

To update the program, the robot was connected to an ordinary PC via aserial adapter. To activate the bootloader, the switch to pin RC0 had to bechanged from 1 to 0 and the robot reset. The bootloader would then start andwait for a program to be sent on the serial port. The PC then had to start theprogram ntload.exe that would send a HEX-file (generated by MPLAB) to therobot. The command line to use with ntload.exe looked like this:

ntload -PCOM1 -DEBUG_MODE=1 jaws.hex

6 Electronics

6.1 Power

The motherboard (see Appendix A) was connected to the 7.2 V battery as wellas to a voltage booster card with 14 V output. The higher voltage was usedto power the locomotion motors while the low voltage was used for the rest

13

Page 14: Jaws

of the motherboard. The high voltage was also connected to the LED driverboard which controlled the IR LEDs and the reflex detectors.

6.2 Motors and speaker

The two motors used for locomotion [9] were connected to the J11 pins (motor1)(see Appendix A bottom right). The speaker and the stick motor [10] wereconnected to pins J12 (motor2) (see Appendix A bottom right). All motors(including the speaker) were controlled by the J8 pins (see Appendix A bottommiddle) which were connected to the main PIC.

6.3 IR sensors

The five IR sensors [11] were connected to the five locking headers J3 throughJ7 (see Appendix A top left). These were in turn connected to the IR PIC.

6.4 The main PIC

The reflex detectors output signal was connected to the RA0 through RA3 A/Dinputs of the PIC (see Appendix A). Pins RA4 and RA5 were used as directionpins for the locomotion motors. The enable pins for the locomotion motorswere pins 16 and 17. The sound was controlled by pins RE0 and RE1. The stickmotor was controlled by pins RB6 and RB7.

Pin 15 was used to decide if the bootloader should be run at startup. It wasconnected to a button on top of the robot.

Pins 18, 23 and 24 was where the main PIC got IR sensor data from the IRPIC.

The LCD was connected to pins 19 through 22 and 27 through 30. RB0 andRB (pins 33 and 34) were connected to two LEDs (the eyes of the robot) fordebugging purposes.

6.5 LED driver board

The LED driver board controlled the IR LEDs that told the opponent where therobot was. It also controlled the reflex detectors situated under the robot.

7 Software implementation

All implementation was done in PIC C [6]. Some extra functions for handlingbasic steering, sensor input and speaker and LCD output were given by thecourse director.

The source code was divided into separate files for sensing, locomotion,stick manipulation, music playing, LCD printing, questions and state defini-tions.

The program flow was constructed so that the main loop always executedwithout any delays. At the beginning of the loop all sensor values were up-dated and some debug info was displayed on the LCD. Then it checked whetherthe special delay state flag was set or not, and if it was, the rest of the loop wascanceled. This was a way of implementing a delay without prolonging the

14

Page 15: Jaws

Has puck?

Turned goal?

Close goal?

At goal?

Turned puck?

Cloase goal or at goal?

Close puck?

Turn to goal

Go to goal

Go to goal slow

Score

Evasive maneuver

Turn to puck

Go to puck

Go to puck slow

Yes

Yes

Yes

Yes

Yes

Yes

No

No

No

No

No

No

Yes No

Figure 9: The question tree.

main loop’s execution time. The rest of the loop was more or less a traversala tree of questions to determine what actions to take. There were also somespecial states, when scoring for example, where state transitions were forced.

7.1 Questions

To be able to determine what situation the robot was currently in, a number ofquestions were formulated. The complete question tree is displayed in figure 9on page 15.

To answer these questions, input from the sensors described earlier wasused.

7.2 Watchdog

There was some trouble with the program hanging. It happened every nowand then and at different places in the code, sometimes often and sometimesless often. Since the interrupt routine continued to operate and as no othersolution seemed to appear, a software watchdog timer was implemented. Theinterrupt routine made sure that the main loop had executed the last 200 msand if not, the program counter was set to zero, thus restarting the PIC.

8 Results and conclusions

Overall the robot performed well. It could locate, move to and get the puck. Itdid have some problems seeing the puck over a long distance because of thebackground light being stronger than the IR sent from the puck. There wasno real solution for this, but after being confused for a while, as it didn’t see

15

Page 16: Jaws

the puck, the robot almost always got a glimpse of something so it could startgoing in the right direction.

The stick, with its rotating rubber band, worked well. During rotation withpuck the robot seldom lost control of it.

The robot could locate the goal and approach it with rather high precision.Detecting the goal zone using the reflex detectors worked well most of the timebut sometimes the robot had problems stopping. This was probably caused bythe changing friction depending on how much potato powder there was onthe rink. The shooting mecanism could, if the robot had stopped at the rightposition, shoot the puck into the goal with good margin.

The biggest problem was probably the robots inability to stop itself fromgoing into its own goal zone. The reason for this was mostly lack of time but itwas also easy to forget since Jaws never got to practise against real opponents.Jaws received many penalties for this during the tournament and at least onegame could have been won otherwise.

Because of the unidentified bug, causing the program to hang, in combina-tion with the software watch dog, the robot reset itself about once every twominutes. This caused almost no trouble since the software was almost stateless.The only critical point was during the scoring sequence.

During the tournament the robot obtained a third place in the group playand therefor did not make it to the semifinals. This was a shame since wethink our robot could have had a good chance on the third place in the wholetournament.

16

Page 17: Jaws

9 References

References

[1] Andersson P., Alfons Aberg, official homepage:http://www.alfons.se,Bok-makaren AB, 2002

[2] Bengtsson, F., Flodstrom, P., Roterman M., Project report for The Sliderrobot:http://www.nada.kth.se/kurser/kth/2D1426/reports2001/Slider.pdf,2D1426 Robotics and Autonomous Systems, 2001

[3] Bratt, Mattias, Course homepage:http://www.nada.kth.se/kurser/kth/2D1426,Robotics and autonom systems, 2002

[4] Bratt, Mattias, Rules for the game:http://www.nada.kth.se/kurser/kth/2D1426/rules2002.pdf,Robotics and autonom systems, 2002

[5] Danielsson, K., Elvers G., Jacobsson B., Report on project work:http://www.nada.kth.se/kurser/kth/2D1426/reports2001/Kakmonstret.pdf,2D1426 Robotics and Autonomous Systems, 2001

[6] Hi-tech, PIC C Manual, Hi-Tech, 2002

[7] Microchip Technology Inc., Datasheet for 20-pin 8-Bit CMOS FLASHMicro controller PIC:http://www.microchip.com/download/lit/pline/picmicro/families/16f87x/30292c.pdf,Microchip Technology Inc., 2001

[8] Microchip Technology Inc., MPLAB Manual. MPLAB IDE, Simulator, Ed-itor User’s Guide, Microchip Technology Inc., 2002

[9] Micromotors, Data for 12 V motor:http://www.stegia.se/Produkter/Micromotors/pages/hv149.htm,Micromotors, 2002

[10] Micromotors, Data for 6 V motor:http://www.stegia.se/english/Products/Micromotors/pages/l149.htm,Micromotors, 2002

[11] Texas Instruments, Datasheet for IR Light-to-Voltage Optical SensorTSL261:http://www.taosinc.com/pdf/tsl260.pdf,Texas Instruments, 2000

17

Page 18: Jaws

A RAS Motherboard schematic

12

34

56

78

A B C D E F G H

1M

CLR

2R

A0/

AN

03

RA

1/A

N1

4R

A2/

AN

2

9R

E1/

AN

610

RE

2/A

N7

8R

E0/

AN

5

7R

A5/

AN

4

11V

dd12

Vss

13O

SC

114

OS

C2

15R

C0

16R

C1/

CC

P2

17R

C2/

CC

P1

18R

C3/

SC

K

5R

A3/

AN

3/V

ref

6R

A4/

T0C

Ki

19R

D0

20R

D1

21R

D2

22R

D3

23R

C4/

SD

I24

RC

5/S

DO

25R

C6

26R

C7

27R

D4

28R

D5

29R

D6

30R

D7

31V

ss

32V

dd

33R

B0/

INT

34R

B1

35R

B2

36R

B3

37R

B4

38R

B5

39R

B6

40R

B7

MC

1

PIC

16F

877

Vcc

C1

0.1u

F

Vcc

Y1

20M

C2

30p

C3

30p

1R

12

R2

3R

34

R4

5R

56

R6

7R

78

R8

9C

MRR

1

8x47

0

1R

12

R2

3R

34

R4

5R

56

R6

7R

7

8R

8

9C

M

RR

2

8x4.

7k

Vcc

1 2 3 4 5 6 7 8

J1

GN

D

1R

1

2R

2

3R

3

4R

45

R5

6R

67

R7

8R

8

9C

MRR

3

8x47

0

1 2 3 4 5 6 7 8

J2

Vcc C

4

0.1u

F

RR

4

8x47

0 Y

220

MC

530

p

C6

30p

1 2 3J3 IR0

R1

100kVcc

1 2 3J4 IR1

R2

100kVcc

1 2 3J5 IR2

R3

100kVcc

1 2 3J6 IR3

R4

100kVcc

1 2 3J7 IR4

R5

100kVcc

1 2 3 4 5 6 7 8

J8

MO

T_C

TR

L

U1A

U1B

U1C

U1D

74H

CT

04

1R

12

R2

3R

34

R4

5R

56

R6

7R

78

R8

9C

M

RR

5

8x4.

7k

1E

NB

L1

2IN

P1

3O

UT

1

4G

ND

5G

ND

6O

UT

27

INP

2

8V

s9

EN

BL2

10IN

P3

11O

UT

3

12G

ND

13G

ND

14O

UT

415

INP

4

16V

ss

U2

L293

DN

1E

NB

L1

2IN

P1

3O

UT

1

4G

ND

5G

ND

6O

UT

27

INP

2

8V

s9

EN

BL2

10IN

P3

11O

UT

3

12G

ND

13G

ND

14O

UT

415

INP

4

16V

ss

U3

L293

NE

Vcc

C7

0.1u

F

C8

0.1u

F

C9

0.1u

F

Vcc

C10

22uF

C11

0.47

uF

Vcc

1 2 3J9

BA

TT

Vs

Vcc

123

J10

CT

RL

1 2 3 4J11

MO

TO

R1

1 2 3 4J12

MO

TO

R2

1 2 3 4 5 6 7 8 9 10J13

1 2 3 4 5 6 7 8 9 10 J14

1 2 3 4 5 6 7 8 9 10

J15

J16

2GND

1IN

3O

UT

U4

LM29

40

R6

81

R7 4.7k

1 3 5 7 9 11 13 15

2 4 6 8 10 12 14 16

J17 8L

ED

S

1 3 5 7 9 11 13 15

2 4 6 8 10 12 14 16

J18

8JP

S

1 3 5 7 9 11 13 15

2 4 6 8 10 12 14 16

J19

8LE

DS

1 3 5 7 9 11 13 15

2 4 6 8 10 12 14 16

J20

8LE

DS

1 3 5 7 9 11 13 15

2 4 6 8 10 12 14 16

J21

8JP

S

Vcc

S2

1R

12

R2

3R

34

R4

5R

56

R6

7R

78

R8

9C

M

RR

6

8x4.

7k

gnd

RA

4 is

ope

n dr

ain

(74H

CT

04)

12345678

J23

V6,

Vcc

Vcc

R9

8.2,

6W

750

mA

max

C13

0.33

uF

V8

Vs

2GND

1IN

3O

UT

U5

7808

CV

R10

3.9,

6W

1 A

max

V8

12345678

J24

GN

D

V8

Vs

S3

Loco

mot

ion

PW

R

S4

5V 8V

Vcc

C0

0.1u

F

12345

J22

SE

RV

O

S1

RE

SE

T

C12

0.1u

F

+ +−

MC

2

PIC

16F

876

14.4

V in

RA

S M

othe

rboa

rd S

chem

atic

Pre

−pr

ogra

mm

ed P

IC

Mai

n P

IC

Mot

or D

river

s

Vol

tage

reg

ulat

ors

18

Page 19: Jaws

B Parts list

• 3 reflex detectors ITR8307Subminiature High Sensitivity Photo InterrupterManufacturer: EverlightPart no: ITR8307

• 1 PIC PIC16F876 20-pin 8-Bit CMOS FLASH Micro controllerManufacturer: Microchip Technology IncPart no: PIC16F876

• 1 PIC PIC16F877 40-pin 8-Bit CMOS FLASH Micro controllerManufacturer: Microchip Technology IncPart no: PIC16F877

• 4 IR diodes SFH485P GaAlAs Infrared EmitterManufacturer: SiemensPart no: SFH485P

• 5 IR sensors TSL261 IR Light-to-Voltage Optical SensorManufacturer: Texas Advanced Optoelectronic Solutions (TAOS)Part no: TSL261

• 2 12Vmotors HL149 12V 10:1 MotorManufacturer: MicromotorsPart no: HL149

• 1 6V motor

• 2 7.2V NiCd accumulator packs

• 1 Mother board

• 1 LCD display

• 1 LED driver board

• 1 Voltage booster card

• 1 Serial RS232 card

19

Page 20: Jaws

C Source code

jaws.c

#include <pic.h>#include <conio.h>#include "lib\defines.h"#include "lib\lcd.h"#include "lib\adc.h"#include "lib\sprint.h"#include "lib\ir_comm.h"#include "lib\eeprom.h"#include "lib\pwm.h"#include "lib\intr.h"//#include "lib\serialio.h"#include "question.h"#include "club.h"#include "sensors.h"#include "printinf.h"#include "move.h"#include "music.h"#include "states.h"

// no code protect, no WDT, no BOD, power up timer, HS Xtal// (has no effect when writing the program using the// boot loader)__CONFIG(0x3FB2);

/* clrwdt */

main() {

reset_soft_wdt();

TRISB1 = TRISB0 = 0;

ir_init(); //initialise IR co-processor communicationinit_pwm(); //initialise pwm for motor controlinit_soft_tmr();init_sound(); //initialise sound generator

/* Our own initializations */init_floor_sens(); //initialize floor sensorsinit_club(); //initialize club rotation control

// enable interruptsPEIE = 1; // peripheral interrupts enableei(); // global interrupt enable

20

Page 21: Jaws

set_lcd_power(1); //turn on lcd

// wait for 100msSET_HOLD(100);while (IS_HOLDING)

reset_soft_wdt();RESET_HOLD;

// and theninit_lcd();

// play ’laser’ sound at startupplay_tune(laser);

// start rotation of clubrot_club_in();

/*********************** Start of Main loop.*/for (;;) {

// Reset the software watchdog timerreset_soft_wdt();

// Flip debug LED. (Also used as angry twinkling eye)RB1 = !RB1;

// Update sensor inputread_floor_sens();update_ir_max_dir();

// Print some information. Some lines commented out.// print_floor_sens();print_front_sens();// sprint16(buffer, soft_time());// lcd_print1("", 9);// lcd_print_at_cursor(buffer);// lcd_print_at_cursor(" ");

// Check for hold state// (a hold state lasts a certain amount of time)if (IS_NOT_HOLDING) {

RESET_HOLD;// Flib debug LED. (Also used as other angry twinkling eye)RB0 = !RB0;

21

Page 22: Jaws

/******************************************************* States directly following a previous state: (score)******************************************************/if (STATE_IS(SCORE_FIRST_STOP)) {

/* Score push puck */hold_state = 13;SET_STATE(SCORE_PUSH_PUCK);SET_HOLD(score_push_puck_go());

} else if (STATE_IS(SCORE_PUSH_PUCK)) {if (hold_state > 0) {

/* Score push puck state (continue) */if (hold_state-- & 1) {

SET_HOLD(score_push_puck_stop());} else {

SET_HOLD(score_push_puck_go());}

} else {

/* Score smash puck state */SET_STATE(SCORE_SMASH_PUCK);SET_HOLD(score_smash_puck());

}} else if (STATE_IS(SCORE_SMASH_PUCK)) {

/* Score go middle state */SET_STATE(SCORE_GO_MIDDLE);SET_HOLD(score_go_middle());

} else if (has_not_moved()) {

/* Get loose state */SET_STATE(GET_LOOSE);SET_HOLD(get_loose());

}

/************************************************ Normal states (as described question tree)***********************************************/else if (HAS_PUCK) {

print_ir_max_dir(OFF_GOAL);if (TURNED_GOAL) {

22

Page 23: Jaws

if (CLOSE_GOAL) {if (AT_GOAL) {

/* Score first stop */SET_STATE(SCORE_FIRST_STOP);play_tune(laser);SET_HOLD(score_first_stop());

} else {

/* Go goal slow state */if (STATE_IS(GO_GOAL)) {

SET_STATE(GO_GOAL_SLOW_FIRST_STOP);SET_HOLD(go_goal_slow_first_stop());

}

if (STATE_NOT(GO_GOAL_SLOW_STOP)) {SET_STATE(GO_GOAL_SLOW_STOP);SET_HOLD(go_goal_slow_stop());

} else {SET_STATE(GO_GOAL_SLOW_GO);SET_HOLD(go_goal_slow_go());

}}

} else if (STATE_NOT(GO_GOAL_SLOW_GO)) {

/* Go goal state */SET_STATE(GO_GOAL);go_goal();

}} else { /* !TURNED_GOAL */

if (CLOSE_GOAL) {if (AT_GOAL) {

/* Turn goal close state */SET_STATE(TURN_GOAL_CLOSE);turn_goal_close();play_tune(laser);

} else {

/* Turn goal slow state */SET_STATE(TURN_GOAL_SLOW);turn_goal_slow();

}} else {

/* Turn goal state */SET_STATE(TURN_GOAL);

23

Page 24: Jaws

turn_goal();

}}

} else {/* Looking for puck, print sensor values */print_ir_max_dir(PUCK);

if (TURNED_PUCK) {if (AT_GOAL_NOT_CLUB && CLOSE_GOAL) {

/* Flee goal state */SET_STATE(FLEE_GOAL);SET_HOLD(flee_goal());play_tune(laser);

} else {if (CLOSE_PUCK) {

/* Go puck slow state */SET_STATE(GO_PUCK_SLOW);go_puck_slow();

} else {

/* Go puck state */SET_STATE(GO_PUCK);go_puck();

}}

} else {

/* Turn puck state */SET_STATE(TURN_PUCK);turn_puck();

}}

// Print current state on lcdprint_state();

}}

}

states.h

/** Definitions and variables for state transmissions

24

Page 25: Jaws

*/

unsigned int hold = 0;char hold_state = 0;bank1 static unsigned int sometime;

#define SET_STATE(x) (state = (x))#define STATE_NOT(x) (state != (x))#define STATE_IS(x) (state == (x))#define STATE state#define SET_HOLD(x) sometime=soft_time(); hold = (x)#define IS_HOLDING hold != 0 && !passed(sometime+hold)#define IS_NOT_HOLDING hold == 0 || passed(sometime+hold)#define RESET_HOLD hold = 0;

// Defines for states#define SCORE_PUSH_PUCK 1#define SCORE_SMASH_PUCK 2#define SCORE_GO_MIDDLE 3#define GO_GOAL_SLOW_GO 4#define GO_GOAL_SLOW_STOP 5#define GO_GOAL 6#define TURN_GOAL_CLOSE 7#define TURN_GOAL_SLOW 8#define TURN_GOAL 9#define FLEE_GOAL 10#define GO_PUCK_SLOW 11#define GO_PUCK 12#define TURN_PUCK 13#define GET_LOOSE 14#define GO_GOAL_SLOW_FIRST_STOP 15#define SCORE_FIRST_STOP 16

question.h

/** Macros and declarations for questions we like to ask* often.*/

#define HAS_PUCK (ir_value(4, PUCK) > 4900)

#define CLOSE_PUCK (ir_value(4, PUCK) > 1500)

#define VISIBLE_PUCK (ir_value(irpmax, PUCK) > 10)

#define TURNED_PUCK (((irpmax + irpnmax == 1) && \(ir_value(irpmax, PUCK) + \ir_value(irpnmax, PUCK) < 300)) || \

25

Page 26: Jaws

((irpmax == 1 && irpnmax == 0) && \((ir_value(irpmax, PUCK) << 8) / \(ir_value(irpnmax, PUCK) + 1) < (256))))

#define TURNED_GOAL (((irgmax == 0 && irgnmax == 1) && \((ir_value(irgmax, OFF_GOAL) << 6) / \(ir_value(irgnmax, OFF_GOAL) + 1) < (11*64)) && \

(ir_value(1, OFF_GOAL) - ir_value(3, OFF_GOAL) > 6)) || \((irgmax == 1 && irgnmax == 0) && \((ir_value(irgmax, OFF_GOAL) << 6) / \(ir_value(irgnmax, OFF_GOAL) + 1) < (6*64))))

#define CLOSE_GOAL (((irgmax + irgnmax == 1) && \((ir_value(irgmax, OFF_GOAL) >> 1) * \(ir_value(irgnmax, OFF_GOAL) >> 1) > 700)) || \((ir_value(irgmax, OFF_GOAL) >> 1) * \(ir_value(irgnmax, OFF_GOAL) >> 1) > 1100))

#define AT_GOAL (floor[0] > 235 || floor[1] > 220 || \floor[2] > 220)#define AT_GOAL_NOT_CLUB (floor[1] > 220 || \floor[2] > 220)

#define SCORE_PUSH_FINISHED (floor[2] < 210)

extern char has_not_moved();

question.c

#include "sensors.h"#include "lib\defines.h"

#define LOCKED_COUNT 12

/** This question had to be a function because of its complexity.*/

char has_not_moved() {static int count = 0;if (ABS(floor[1] - floor_old) < 2) {

++count;if (count == LOCKED_COUNT) {

return 1;}

} else {count = 0;

}return 0;

26

Page 27: Jaws

}

move.h

/** Functions controling the movement (locomotion) of the robot.*/

extern void turn_puck();extern void go_puck();extern void go_puck_slow();extern void turn_goal();extern void turn_goal_slow();extern void turn_goal_close();extern void go_goal();extern unsigned int go_goal_slow_go();extern unsigned int go_goal_slow_stop();extern unsigned int go_goal_slow_first_stop();extern unsigned int score_first_stop();extern unsigned int score_push_puck_go();extern unsigned int score_push_puck_stop();extern unsigned int score_smash_puck();extern unsigned int score_go_middle();extern unsigned int get_loose();extern unsigned int flee_goal();

move.c

#include <pic.h>#include "lib\pwm.h"#include "lib\ir_comm.h"#include "lib\defines.h"#include "lib\intr.h"#include "lib\lcd.h"#include "sensors.h"#include "club.h"#include "music.h"#include "lib\sprint.h"

/** Turn towards the puck. Turn fast if puck is behind robot.*/

void turn_puck() {if (irpmax == 1)

motors(95, -95);else if (irpmax == 2)

27

Page 28: Jaws

motors(127, -128);else if (irpmax == 0)

motors(-95, 95);else /* irpmax == 3) */

motors(-128, 127);}

/** Go forward or almost forward after the puck.*/

void go_puck() {if (ABS(ir_value(irpmax, PUCK) - ir_value(irpnmax, PUCK)) < 200)

motors(127, 127);if (irpmax == 0)

motors(120, 127);else if (irpmax == 1)

motors(127, 120);}

/** Go forward or almost forward after the puck at slower speed.* Used when close to the puck.*/

void go_puck_slow() {if (ABS(ir_value(irpmax, PUCK) - ir_value(irpnmax, PUCK)) < 200)

motors(100, 100);if (irpmax == 0)

motors(95, 105);else if (irpmax == 1)

motors(105, 95);}

/** Turn anti-clockwise to goal.*/

void turn_goal() {motors(40, 115);

}

/** Turn anti-clockwise to goal but slower.* Used when close to the goal.*/

void turn_goal_slow() {motors(0, 110);

}

/** Turn to goal but rotate slowly around robot center.* Used when very close to the goal. (floor sensor in goal zone)

28

Page 29: Jaws

*/void turn_goal_close() {

motors(-100, 100);}

/** Go forward or almost forward towards the goal.*/

void go_goal() {if (irgmax == 0)

motors(120, 127);else if (irgmax == 1)

motors(127, 120);}

/** Go forward or almost forward towards the goal for 40 milliseconds.*/

unsigned int go_goal_slow_go() {if (irgmax == 0)

motors(105, 123);else if (irgmax == 1)

motors(123, 105);return 40;

}/** Stand still for 70 milliseconds.*/

unsigned int go_goal_slow_stop() {motors(0, 0);return 70;

}/** Stand still for 200 milliseconds.*/

unsigned int go_goal_slow_first_stop() {motors(0, 0);return 200;

}

/** These functions make up the scoring sequense.*/

unsigned int score_first_stop() {motors(-128, -128);return 20;

}unsigned int score_push_puck_go() {

motors(-128, 127);return 40;

29

Page 30: Jaws

}unsigned int score_push_puck_stop() {

motors(0, 0);return 70;

}unsigned int score_smash_puck() {

motors(127, -128);return 1300;

}unsigned int score_go_middle() {

motors(127, 127);play_tune(alfons);return 1100;

}

/** Called when stuck somewhere*/

unsigned int get_loose() {motors(-128, 0);return 600;

}

/** Called when trying to go inte the goal zone without the puck*/

unsigned int flee_goal() {motors(-128, -128);return 500;

}

musicdef.h

/** Pic Music Markup Language. ;)*/

#define END 0,0

/* Note length */#define T 8#define S 16#define Sp 24#define E 32#define Ep 48#define Q 64#define Qp 96#define H 128

30

Page 31: Jaws

#define Hp 192#define W 256

/* Note length for non legato tones */#define SS 15, 0xff, 1#define SE 31, 0xff, 1#define SEp 47, 0xff, 1#define SQ 63, 0xff, 1#define SQp 95, 0xff, 1#define SH 127, 0xff, 1#define SHp 191, 0xff, 1#define SW 255, 0xff, 1

/* Note length at different speed *//*#define T 5#define S 10#define Sp 15#define E 20#define Ep 30#define Q 40#define Qp 60#define H 80#define Hp 120#define W 160

#define SS 9, 0xff, 1#define SE 19, 0xff, 1#define SEp 29, 0xff, 1#define SQ 39, 0xff, 1#define SQp 59, 0xff, 1#define SH 79, 0xff, 1#define SHp 119, 0xff, 1#define SW 159, 0xff, 1*/

#define P 0xFF

/* Key definitions */#define C0 0x00#define Db0 0x01#define D0 0x02#define Eb0 0x03#define E0 0x04#define F0 0x05#define Gb0 0x06#define G0 0x07#define Ab0 0x08#define A0 0x09

31

Page 32: Jaws

#define Bb0 0x0A#define B0 0x0B

#define C1 0x10#define Db1 0x11#define D1 0x12#define Eb1 0x13#define E1 0x14#define F1 0x15#define Gb1 0x16#define G1 0x17#define Ab1 0x18#define A1 0x19#define Bb1 0x1A#define B1 0x1B

#define C2 0x20#define Db2 0x21#define D2 0x22#define Eb2 0x23#define E2 0x24#define F2 0x25#define Gb2 0x26#define G2 0x27#define Ab2 0x28#define A2 0x29#define Bb2 0x2A#define B2 0x2B

#define C3 0x30#define Db3 0x31#define D3 0x32#define Eb3 0x33#define E3 0x34#define F3 0x35#define Gb3 0x36#define G3 0x37#define Ab3 0x38#define A3 0x39#define Bb3 0x3A#define B3 0x3B

music.h

extern const char laser[];extern const char laser2[];extern const char alfons[];

32

Page 33: Jaws

music.c

#include "musicdef.h"

/** Short tune to signal minor events.*/

const char laser[]={0x00,2,0x02,2,0x04,2,0x06,2,0x08,2,0x0A,2,0x10,2,0x12,2,0x14,2,0x16,2,0x18,2,0x1A,2,0x20,2,0x22,2,0x24,2,0x26,2,0x28,2,0x2A,2,0x30,2,0x32,2,0x34,2,0x36,2,0,0};

/** Three laser in a row. Used to signal goals when testing* as the other tune is a bit long*/

const char laser2[]={0x00,2,0x02,2,0x04,2,0x06,2,0x08,2,0x0A,2,0x10,2,0x12,2,0x14,2,0x16,2,0x18,2,0x1A,2,0x20,2,0x22,2,0x24,2,0x26,2,0x28,2,0x2A,2,0x30,2,0x32,2,0x34,2,0x36,2,0x00,2,0x02,2,0x04,2,0x06,2,0x08,2,0x0A,2,0x10,2,0x12,2,0x14,2,0x16,2,0x18,2,0x1A,2,0x20,2,0x22,2,0x24,2,0x26,2,0x28,2,0x2A,2,0x30,2,0x32,2,0x34,2,0x36,2,0x00,2,0x02,2,0x04,2,0x06,2,0x08,2,0x0A,2,0x10,2,0x12,2,0x14,2,0x16,2,0x18,2,0x1A,2,0x20,2,0x22,2,0x24,2,0x26,2,0x28,2,0x2A,2,0x30,2,0x32,2,0x34,2,0x36,2,0,0};

/** The goal tune. Theme from Alfons Aberg.** The arrangement tries to simulate accompainment by fast* switching between many short tones.** The first note on each line is the melody tone (played by a sax* in the original) and the rest is an approximation of the comp* (played by a trombone) in the first part of the tune. In the* second part it’s just the base and fifth of the cords. (Since* I couldn’t make out the trombone part there)** To be able to play this the index variable of the playing routine* had to be decleared int instead of char and the routine modified* according to that.*/

const char alfons[]={Gb2,S, D1,S, A0,S,A2,SS,

33

Page 34: Jaws

A2,S, A0,S,Gb2,S, A0,S,Gb2,S, D1,S,E2,S, D1,S,E2,S, A0,S,D2,S, A0,S,

Gb2,S, D1,S, A0,S,A2,SS,A2,S, A0,S,Gb2,S, A0,S,Gb2,S, B0,S,E2,S, B0,S,D2,S, D1,S,

Gb2,S, A0,S, D1,S,A2,SS,A2,S, D1,S,Gb2,S, D1,S,Gb2,S, A0,S,E2,S, A0,S,E2,S, D1,S,D2,S, D1,S,

Gb2,S, A0,S, D1,S,A2,SS,A2,S, D1,S,Gb2,S, D1,S,Gb2,S, A0,S,E2,S, B0,S,D2,S, D1,S,

B2,S, B0,S, B2,S, Gb1,S,D3,S, B0,S, D3,S, Gb1,S,Db3,S, B0,S,A2,S, Gb1,S,B2,S, B0,S,D3,S, Gb1,S,Db3,S, B0,S,A2,S, Gb1,S,B2,S, B0,S,

G2,S, E1,S, G2,S, B1,S,B2,S, E1,S, B2,S, B1,S,A2,S, E1,S,Gb2,S, B1,S,G2,S, E1,S,B2,S, B1,S,A2,S, E1,S,

34

Page 35: Jaws

Gb2,S, B1,S,G2,S, E1,S,

E2,S, C1,S, E2,S, G1,S,G2,S, C1,S, G2,S, G1,S,Gb2,S, C1,S,D2,S, G1,S,E2,S, C1,S,G2,S, G1,S,Gb2,S, C1,S,D2,S, G1,S,E2,S, C1,S,

A1,S, A0,S, A1,S, E1,S,A1,S, A0,S, A1,S, E1,S,A1,S,END

};

printinf.h

extern char buffer[7];extern char state;extern void print_ir_max_dir(int);extern void print_front_sens();extern void print_state();extern void print_floor_sens();

printinf.c

#include "lib\sprint.h"#include "lib\lcd.h"#include "lib\ir_comm.h"#include "sensors.h"

#define DELAY 2

char state;bank1 char buffer[7];

void print_ir_max_dir(int thing) {int ir_max;int ir_nmax;if (thing == PUCK) {

ir_max = irpmax;ir_nmax = irpnmax;

}

35

Page 36: Jaws

if (thing == OFF_GOAL) {ir_max = irgmax;ir_nmax = irgnmax;

}

sprint16(buffer, ir_max);lcd_print1("m:", 0);lcd_print_at_cursor(buffer);sprint16(buffer, ir_nmax);lcd_print2("n:", 0);lcd_print_at_cursor(buffer);sprint16(buffer, ir_value(ir_max, thing));if (ir_value(ir_max, thing) < 10)

lcd_print1(" ", 4);else if (ir_value(ir_max, thing) < 100)

lcd_print1(" ", 4);else if (ir_value(ir_max, thing) < 1000)

lcd_print1(" ", 4);else

lcd_print1("", 4);lcd_print_at_cursor(buffer);sprint16(buffer, ir_value(ir_nmax, thing));if (ir_value(ir_nmax, thing) < 10)

lcd_print2(" ", 4);else if (ir_value(ir_nmax, thing) < 100)

lcd_print2(" ", 4);else if (ir_value(ir_nmax, thing) < 1000)

lcd_print2(" ", 4);else

lcd_print2("", 4);lcd_print_at_cursor(buffer);

if (thing == PUCK)lcd_print2("P", 14);

elselcd_print2("G", 14);

}

void print_front_sens() {sprint16(buffer, ir_value(4, PUCK));if (ir_value(4, PUCK) < 10)

lcd_print1("f: ", 9);else if (ir_value(4, PUCK) < 100)

lcd_print1("f: ", 9);else if (ir_value(4, PUCK) < 1000)

lcd_print1("f: ", 9);else

lcd_print1("f:", 9);lcd_print_at_cursor(buffer);

36

Page 37: Jaws

}

void print_state() {sprint16(buffer, state);lcd_print2("s:", 9);lcd_print_at_cursor(buffer);lcd_print_at_cursor(" ");

}

void print_floor_sens() {sprint16(buffer, floor[0]);lcd_print1("", 0);lcd_print_at_cursor(buffer);lcd_print_at_cursor(" ");sprint16(buffer, floor[1]);lcd_print2("", 0);lcd_print_at_cursor(buffer);lcd_print_at_cursor(" ");sprint16(buffer, floor[2]);lcd_print1("", 5);lcd_print_at_cursor(buffer);lcd_print_at_cursor(" ");

}

sensors.h

/* New definition of ir_value(x,y) to make it point to* our copy of the read values.*/

#define ir_value(x,y) ir_values[(x)][(y)]

/* max and nmax are indexes of the maximum and second to maximum* ir sensores on p = puck and g = goal*/

extern unsigned int irgmax, irgnmax, irpmax, irpnmax;/* Floor sensors */extern char floor[3];/* Used for reading movement */extern char floor_old;/* Safe copies of ir readings */extern bank2 int ir_values[5][2];

extern void init_floor_sens();extern void read_floor_sens();extern void update_ir_max_dir();

37

Page 38: Jaws

sensors.c

#include <pic.h>#include "lib\adc.h"#include "lib\ir_comm.h"#include "lib\lcd.h"

#define ir_value(x,y) ir_values[(x)][(y)]

unsigned int iter, irgmax, irgnmax, irpmax, irpnmax;char floor[3];char floor_old;int bank2 ir_values[5][2];

void update_ir_max_dir() {ir_wait();for (iter = 0; iter < 5; ++iter) {

di(); /* Entering critical section */ir_values[iter][PUCK] = ir_value_cs(iter, PUCK);ir_values[iter][OFF_GOAL] = ir_value_cs(iter, OFF_GOAL);ei(); /* Critical section end */

}

// Find sensor with the largest value: irXmaxirpmax = 0;for (iter = 1; iter < 4; ++iter) {

if (ir_value(iter, PUCK) > ir_value(irpmax, PUCK)) {irpmax = iter;

}}irgmax = 0;for (iter = 1; iter < 4; ++iter) {

if (ir_value(iter, OFF_GOAL) > ir_value(irgmax, OFF_GOAL)) {irgmax = iter;

}}

// Find sensor with the second largest value: irXnmaxirpnmax = (irpmax == 0 ? 1 : 0);for (iter = irpnmax+1; iter < 4; ++iter) {

if (iter != irpmax && ir_value(iter, PUCK) >ir_value(irpnmax, PUCK)) {

irpnmax = iter;}

}irgnmax = (irgmax == 0 ? 1 : 0);for (iter = irgnmax+1; iter < 4; ++iter) {

if (iter != irgmax && ir_value(iter, OFF_GOAL) >ir_value(irgnmax, OFF_GOAL)) {

38

Page 39: Jaws

irgnmax = iter;}

}}

void init_floor_sens() {//use only three (of five) A/D channel (AN0) (see adc.h)ADCON1 = 0b10000010;TRISA0 = TRISA1 = TRISA2 = 1;

}

void read_floor_sens() {floor_old = floor[1];floor[0] = sample_ad_channel(0);floor[1] = sample_ad_channel(1);floor[2] = sample_ad_channel(2);

}

club.h

/** Functions to control rotation of club rubber band*/

/** Initiate use of club motor by setting data direction on* the control pins of the pic.*/

extern void init_club();

extern void rot_club_in();extern void rot_club_out();extern void rot_club_stop();

club.c

#include <pic.h>

#define CLUB_MOTOR RB7#define CLUB_MOTOR_DIR RB6

/** Initiate use of club motor by setting data direction on* the control pins of the pic.

39

Page 40: Jaws

*/void init_club() {

TRISB6 = TRISB7 = 0;}

void rot_club_in() {CLUB_MOTOR_DIR = 1;CLUB_MOTOR = 1;

}

void rot_club_out() {CLUB_MOTOR_DIR = 0;CLUB_MOTOR = 1;

}

void rot_club_stop() {CLUB_MOTOR = 0;

}

inter.c

// ***************************** intr.c

#include <pic.h>#include "ir_comm.h"#include "pwm.h"#include "defines.h"

/** New end of soung set to largest value of an unsigned int*/

#define SOUND_END 0xffff

//pins for controlling the speaker driver (use 6V motor driver IC)//connect sound pin to dir and sound enbl pin to enbl//with these settings connect://// pin8 RE0 <---> fifth motor control pin// pin9 RE1 <---> sixth motor control pin//// Then connect speaker with series resistance to motor terminal 3

#define SOUND_PIN RE1#define SOUND_PIN_TRIS TRISE1#define SOUND_ENBL_PIN RE0#define SOUND_ENBL_PIN_TRIS TRISE0// note that the use of port E pins as digital I/O requires// ADCON1 to be properly set

40

Page 41: Jaws

int soft_wdt;

//constant vector to give right frequencies for all notesconst char wave_per_add[16]={0,14,28,41,53,64,75,85,95,104,112,

120,128,135,142,148};

const char * notes;/** sound_index declared as unsigned int to be able to play tunes* longer than 127 notes*/

unsigned int sound_index=SOUND_END;unsigned int note_time;

bit has_passed;unsigned int soft_tmr;unsigned int soft_tmr_copy;

//initialise tone generatorvoid init_sound() {

SOUND_PIN_TRIS=0;SOUND_ENBL_PIN_TRIS=0;

//init TIMER0T0CS=0; //internal clockPSA=0; //prescaler assigned to WDTT0IF=0;T0IE=1;

}

//start playing a tune//(non-blocking)void play_tune(const char* tune){

sound_index=0;if(tune[sound_index]==0&&tune[sound_index+1]==0)

sound_index=SOUND_END;else {

notes=tune;//copy two lowest bytes of soft_tmrnote_time=soft_tmr;

}}

//Variable def to access both 8-bit regs of TIMER1 together as an intvolatile unsigned int TMR1 @ 0x0E;

41

Page 42: Jaws

// initialise the soft timer// uses TIMER1void init_soft_tmr() {

//0xFFFF-4999 will overflow (reach beyond 0xFFFF) in 1 msTMR1=60536;//TMR1 on in internal clock (timer) mode without prescalerT1CON=0b00000001;TMR1IE=1;

}

void interrupt service_routine(void) {

char note;char prescale;

//calling functions from the interrupt routine should be//avoided, so we include the code we need right here instead.//That way we can still use separate files.//First some declarations in *.irh files (interrupt routine headers)

#include "ir_comm.irh"//#include "serialio.irh"//then the code itself in *.irc files (interrupt routine C source)

#include "ir_comm.irc"

// update soft timer if appropriateif(TMR1IF){

/** Software watchdog timer*/if (++soft_wdt > 200) {

PCLATH = 0;PCL = 0;

}

TMR1IF=0;soft_tmr++;TMR1ON=0;TMR1+=60532;TMR1ON=1;

}

// handle sound generationif(T0IF) {

T0IF=0;if(sound_index!=SOUND_END) {

// a tune is playing

// check if it is time for the next note

42

Page 43: Jaws

if(((unsigned int)soft_tmr- (note_time+((unsigned int)notes[sound_index+1]<<3)))<0x8000) {

//time is up; next notesound_index+=2;//check end of tuneif(notes[sound_index]==0&&notes[sound_index+1]==0) {

sound_index=SOUND_END;SOUND_ENBL_PIN=0;// max prescaling to avoid unnecessarily many irrelevant interrPS0=PS1=PS2=1;

}note_time=soft_tmr;

}if(sound_index!=SOUND_END) {

// tune is still playing// continue to play notenote=notes[sound_index];// if this is a pause (quiet note)if((note&0xF0)!=0xF0) {

// not a pause

// set prescaler depending on octave 0, 1, 2, or 3prescale=0b100-((note&0x30)>>4);OPTION|=prescale;OPTION&=(prescale|0b11111000);// set timer 0 to overflow when sound pin needs// to be toggled next time (new TMR0 interrupt then)TMR0+=wave_per_add[note&0x0F];// toggle sound pin and make sure enable pin is highSOUND_PIN=!SOUND_PIN;SOUND_ENBL_PIN=1;

} else SOUND_PIN=SOUND_ENBL_PIN=0; //pause}

}}

}

43

Page 44: Jaws

D Extra pictures

44

Page 45: Jaws

45