C. Andrew Davis Final Report SATYAGRAHA December 10, 2002 University of Florida Department of Electrical and Computer Engineering EEL 5666 Intelligent Machines Design Laboratory 1 Table of Contents 1. Abstract 3 2. Executive Summary 4 3. Introduction 5 4. Integrated System 6 5. Mobile Platform 7 6. Actuation 10 7. Sensors 11 8. Behaviors 18 9. Experimental Layout and Results 19 10. Conclusion 22 11. Documentation 23 12. Appendix A: Sources for Parts 24 13. Appendix B: Programming Code 25 2 1. ABSTRACT SATYAGRAHA is a multiple robot project inspired by the teachings of Mohandas Gandhi. He describes Satyagraha as civil resistance without any intentional injury to other parties. Gandhi himself called these actions “experiments in truth.” Project SATYAGRAHA consists of two belligerent robots engaged in a battle. A third robot, GANDHI, acts as a Satyagrahi (a participant in Satyagraha) and intervenes in the battle to peacefully end the violence between its robotic brethren. In a sense, this project is an experiment in truth. 3 2. EXECUTIVE SUMMARY SATYAGRAHA consists of two types of robots—a peaceful robot (GANDHI) and two belligerent robots (WARRIOR’s). All robots are equipped with IR collision avoidance and bump detection, but each type of robot serves a different purpose. GANDHI roams around looking for WARRIOR’s by tracing their 56.5 kHz IR signal through IR detectors. Once a WARRIOR is detected, GANDHI will drives towards the WARRIOR and bump into it. Next, GANDHI will continue seeking out other WARRIOR’s. The WARRIOR’s are equipped with 56.5 kHz IR to broadcast their position. A WARRIOR will wander about and periodically stop. If another WARRIOR’s IR beacon is detected, it will turn around to avoid facing it. Once found and bumped into by GANDHI, two parallel wires on the WARRIOR’s bump skirt are shorted together, signaling that a hit by GANDHI has been made. This causes the WARRIOR to become pacified. The WARRIOR turns off its IR beacons and displays a “smile” on its seven segment LED’s instead of a “frown”. The WARRIOR will then proceed to wander around and periodically “dance” by rotating in place. 4 3. INTRODUCTION SATYAGRAHA originated from my desire to study multiple-robot interaction and to create an artificial model of the natural world. SATYAGRAHA aims to serve as a simplistic model of human interactions pertaining to strife and conflict. The project also acts as an exercise in studying communication and behavior amongst a multitude of autonomous agents. The system presented consists of three robots. Two of these robots are belligerent warrior robots. Each WARRIOR exhibits its anger via a face created on 7-segment LED’s. The third robot, GANDHI, seeks out the warrior robots and then proceeds to pacify the WARRIOR by convincing it to stop fighting and become peaceful. This paper outlines the entire SATYAGRAHA system by analyzing each subsystem. The paper covers the robots’ platform design, actuation, sensor construction, behaviors, and experiments leading to an effective system. 5 4. INTEGRATED SYSTEM Each agent in the SATYAGRAHA system uses a Progressive AT-Mega163 development board as a means of control. The figure below shows the behaviors that each robot will exhibit. Figure 1 Collision Avoidance is implemented using 40 kHz modulated IR, operated though analog-todigital (A/D) ports, and bump detection is operated through digital input ports. Belligerent agent seeking is accomplished through hacked 56.5 kHz modulated IR detectors that are read through A/D ports as well. Anger and happiness are displayed by WARRIOR’s on 7-segment LED’s controlled through digital output ports. Hacked servos are used for locomotion and are controlled using pulse width modulation (PWM) implemented through the AT-Mega board. 56.5 kHz modulated IR LED beacons allow belligerent agents to be tracked. The beacons are controlled through PWM outputs on the microcontroller. 6 5. MOBILE PLATFORM The platforms are modified versions of the standard TJ design. The platforms are made of wood, designed in AutoCAD and cut using the T-Tech machine. The platform is designed to hold for the microcontroller, battery pack, protoboard, and two servos. The platform is customized to allow cables and sensors to be attached to the exterior. Below are Figures 2 and 3 of the platform. Figure 2: Platform base 7 Figure 3: Platform top Figure 4 shows the completed platform with hardware mounted Figure 4: Complete platform The original platform had a bump skirt that was too thin. It broke while the platform was being constructed. The servo ports had to be filed down extensively for the servos to fit. On successive platform cut-outs, the bump skirt was thickened and the radius of the platform top was increased to allow more room for attaching sensors. It was discovered that the bottom portion of the platform was too small to accommodate for all the wires and cables. The cables were often 8 smashed together against the protoboard. The result was that the microcontroller had to be placed on top of the platform. A caster for the platform to slide on consisted of a small disk designed for furniture, purchased for a nominal price. The platform was adhered together using standard wood glue and sensors were attached using screws, hot glue, vecro, or electrical tape. 9 6. ACTUATION Each robot has dual hacked servos fo r locomotion. Servos are attached to the left and right sides of the platform and have plastic molded wheels attached to them. The servos are hacked to allow for continuous motion. This provides a simpler system since motor drivers are not needed. Pulse width modulated signals are produced by the microcontroller. MX-400 standard servos were chosen due to their cheap cost and sufficient speed and torque. This application does not required significant amounts of torque or speed. 10 7. SENSORS Project SATYAGRAHI requires several dynamic sensor systems. All three robots include IR collision avoidance and bump sensors. Additionally, infrared is needed to allow GANDHI to seek out belligerent robots equipped with infrared emitters. A contact detection system is required to determine when GANDHI has made physical contact with another robot. INFRARED SENSOR SYSTEMS Infrared sensing is utilized in two separate systems in two completely different ways. This section discusses each sensor system separately. IR Short Range Collision Avoidance Each robot is equipped with two Sharp GP2D12 Distance Measuring Sensors. The GP2D12’s include an IR emitter and sensor in one package, modulating at a frequency of 40 kHz. They require a 5V power signal and ground and output consists of a analog voltage output within the range of 0V to 3V. The sensors are attached to the front of the robot body at a difference angle of 45 degrees. Figure 5 below shows the layout. Figure 5: IR Collision Avoidance Layout The analog output on each of the two Sharp sensors is fed into ADC ports PA0 and PA1, respectively, on the Mega-AVR microcontroller. Software then interprets the digital signal produced by the ADC for collision avoidance functions. IR Beacon Emitter and Detector System 11 In order for GANDHI to exhibit the behavior of “finding” a warrior robot, an IR beacon is attached to each warrior robot. Three Detectors on GANDHI allow it to sense these beacons and move towards a warrior robot. As to not interfere with the IR in place for collision avoidance, 56.5 kHz modulated IR is used. A warrior robot is equipped with five IR LED’s producing the required 56.5 kHz signal. Figure 6 shows the circuit driving the LED’s. Figure 6: IR LED circuit It was decided to place all of the IR LED’s towards the front rim of the robot. This will allow GANDHI to determine orientation and path information of warrior robots. Figure 7 shows the placement of the IR LED’s. 12 Figure 7: IR LED Layout To read the IR beacons, GANDHI is equipped with hacked LiteOn digital IR sensors. The sensors were hacked following Michael Hattermann’s instruction given in his Spring 2002 final report. Figure 8 is a copy of his instruction on how to hack the LiteOn sensor. Figure 8: Michael Hatterman’s hack The hacked LiteOn sensors provide analog signals of the measured intensity of 56.5 kHz modulated IR detected. Three of these sensors were place on GANDHI, underneath the top platform. All three are along the front rim and are aimed forward. One sensor was placed on each WARRIOR so that it can sense the general direction of other WARRIORS. Originally, Sharp 13 GP1UM267XK sensors were purchased but it was realized that there is no feasible way to hack them. BUMP SENSOR SYSTEM All SATYAGRAHI robots are equipped with four bump switches for detecting collisions. When open, the switch leads are at a very high impedance. When closed, the switch is close to a short circuit. The switches are wired to individual digital input ports on Port B of the AT-Mega microcontroller. The switches are attached to Port B, pin 0 through 3. Three of the bump switches are aligned along the front of the platform while the fourth is on the rear. Figure 9 shows the layout of the bump sensors. Figure 9: Bump Sensor Layout CONTACT DETECTION SYSTEM The contact detection system is used when GANDHI collides with a warrior robot. It is necessary to distinguish a bump with another robot from a bump with any other object. The sensor consists of parallel, stripped, wirewrap gauge wires affixed to the circumference of the WARRIO R’s bump skirt. GANDHI’s bump skirt is covered with a foil tape. WARRIOR robots monitor the voltage on their bump skirts through a digital port to detect deviations. When two 14 WARRIOR robots collide, the bump skirt wires are not shorted and the robots react as if they have hit any ordinary object. When a WARRIOR collides with GANDHI, the bump skirt wires are shorted together. This brings the input pin down to ground and ultimately leads to behavior changes in the WARRIOR robot. This is modified from a similar sensor developed by Jason Plew. His original design used a voltage divider circuit to detect robot collisions. A wire pulled up to 5 V would be attached to GANDHI and a wire pulled down to ground would be attached to a WARRIOR. In theory, a collision results in a voltage divider leaving a voltage of approximately 2.5 V. In actuality, this does not work without a common ground wire attached to each robot. Since GANDHI does not require feedback when a robot collision is made, the modification I have presented is more suitable for my design. Figure 10 shows the sensor as it appears on GANDHI (top) and a WARRIOR (bottom). Figure 110: Robot Contact Sensor System CONCLUSION Infrared sensors modulated at 40 kHz allow the robots to avoid collisions. Once objects are within 18 inches, suitable action can be taken to evade obstacles. Additionally, infrared sensors 15 modulated at 56.5 kHz allow GANDHI to track warrior robots. The intensity of the IR detected allows GANDHI to determine a general direction and proximity of a WARRIOR. The bump sensors send discrete voltages to the microcontroller to signify where a robot has collided with something. Software can then interpret this voltage to take corrective measures. The contact sensor works in conjunction with the bump sensors to determine when a collision occurs between GANDHI and a warrior. This important distinction allows for changes in robot behavior. PARTS LIST Infrared Emitter/Detector Sharp GP2D12 Distance Measuring Sensor Mark III Robot Store http://www.junun.org/MarkIII/Store.jsp $8.25/unit (6) Emitter IR LED IMDL Lab $0/unit (10) Detector LiteON 56.5kHz Digital IR Detector Jameco Electronics 1355 Shoreway Road Belmont, CA 94002 1-800-536-4316 Part # 176541 $1.95/unit (10) Bump Switch Switch IMDL Lab $0/unit (5) Robot Contact System 16 Wirewrap wire Wirewrap wire stripper Each robot includes a similar sensor package and all sensors are implemented via a Progressive Mega-AVR development board. 17 8. BEHAVIORS All of the robots must be able to avoid obstacles and retreat when it collides with an obstacle. IR sensing and bump detection are used to assume these behaviors. Additionally, all robots must be capable of detecting a belligerent robot. BEHAVIORS: GANDHI GANDHI continuously searches for 56.5 kHz modulate IR signals. Once GANDHI detects one, it will track the emitter and collide with the target emitter. Once this is done, GANDHI will back off and continue searching. GANDHI is equipped with two 7-segment LED’s that display a smile face to exhibit his peacefulness. BEHAVIORS: WARRIOR WARRIOR’s exhibit belligerence by displaying a frown face on three 7-segment LED’s. A WARRIOR’s motion is random roaming with intermittent periods of rest. This is to allow GANDHI to catch up to a WARRIOR it is chasing. If an enemy robot’s IR is detected while at rest, the WARRIOR will turn to face away from the enemy. The WARRIOR becomes pacified when GANDHI runs into it. This causes the frown face on the 7-segment LED’s to change to a smile face. The WARRIOR’s IR beacons are turned off, and it spins in circles. The WARRIOR will randomly roam and periodically begin “dancing” by spinning in place. 18 EXPERIMENTAL LAYOUT AND RESULTS Test 1: Sharp GP2D12 To test functionality, a Sharp GP2D12 sensor was connected to a breadboard, powered, and a mulitmeter attached to the output. A white piece of cardboard was placed at varying distances from the sensor and the voltage output was recorded. Table 1 shows the data collected. Distance Voltage Distance Voltage (in.) (in.) 1 0.94 16 0.70 2 1.85 17 0.67 3 2.67 18 0.64 3.5 2.71 19 0.61 4 2.46 20 0.60 5 2.05 21 0.60 6 1.70 22 0.56 7 1.42 23 0.52 8 1.25 24 0.50 9 1.12 26 0.48 10 1.03 28 0.45 11 0.96 30 0.41 12 0.88 32 0.20 13 0.83 34 0.02 14 0.77 36 0.02 Table 1: GP2D12 Signal Characteristics It was determined that 3.5 inches is the critical distance at which the sensor fails to provide consistent data. It was observed that as the object approaches the sensor, the output voltage increases. Once within 3.5 inches however, this voltage begins to decrease. The GP2D12 sensor is most suitable for measuring distances up to 18 inches away. Figure 11 is a graph of the experimental data collected. Code appears in the appendix detailing the testing procedures for the GP2D12 when interfaced with the Mega-AVR microcontroller. 19 3 Output (V) 2.5 2 1.5 1 0.5 0 2.45 2.45 2.52 2.44 2.31 2.12 2.02 1.93 1.8 1.74 1.73 1.53 2 4 6 8 10 12 14 16 18 20 22 24 Distance (in.) Figure 11: Sharp GP2D12 Data Plot Test 2: Hacked LiteOn 56.5 kHz IR detector To test functionality, a hacked LiteOn sensor was connected to a breadboard, powered, and a mulitmeter attached to the output. A IR LED modulated at 56 kHz was placed at varying distances from the sensor and the voltage output on the detector was recorded. Table 2 shows the data collected. Distance (in.) Output (V) 2 2.45 4 2.45 6 2.52 8 2.44 10 2.31 12 2.12 Distance Output (in.) (V) 14 2.02 16 1.93 18 1.8 20 1.74 22 1.73 24 1.53 Table 2: LiteOn Sensor Data It was determined that 8 inches is the critical distance at which the sensor fails to provide consistent data. It was observed that as the object approaches the sensor, the output voltage increases. Once within 8 inches however, this voltage begins to decrease. The LiteOn sensor is most suitable for measuring distances up to 30 inches away. Figure 12 is a graph of the 20 experimental data collected. Code appears in the appendix detailing the testing procedures for the LiteOn IR detector when interfaced with the Mega-AVR microcontroller. 3 Output (V) 2.5 2 1.5 1 0.5 0 2.45 2.45 2.52 2.44 2.31 2.12 2.02 1.93 1.8 1.74 1.73 1.53 2 4 6 8 10 12 14 16 18 20 22 24 Distance (in.) Figure 12: LiteOn Sensor Data Plot 21 10. CONCLUSION Overall, I accomplished most of the goals set forth in my proposal. A multiple robot system exhibiting human behaviors was the intention and the result. My original proposal included plans to have the WARRIOR robots fight by firing projectiles at each other. I decided against this idea based on the TA’s advice. Solenoids are costly and greatly increase weight of each robot due to the added battery power. I originally specified that I would make three to five robots. I met this goal by completing three robots. Five robots would make for a more attractive demonstration but the increased costs and time made this non- feasible. Future work may include building additional WARRIOR’s. No major problems occurred while designing and testing the robots. The delay in getting my original microcontroller of choice (manufactured by Futurlec) put me behind schedule towards the beginning of the semester. I finally decided to use the Progressive AT-Mega boards and I am very satisfied with them. The documentation and support software are excellent. A good rule of thumb when designing robots is to always have plenty of male and female headers. I constantly found myself running short on female headers for making cables. Additionally, it is good to check that all of your batteries are charged if a robot begins acting strangely. I noticed my servos would act in unpredictable ways but I could not determine the origin. Finally, I tested the batteries and realized the servos were not getting a high enough voltage. 22 11. Documentation Thanks to Jason Plew for his theoretical robot collision detection system Source for LiteOn 56.5 kHz IR detector hack: Michael Hattermann (IMDL Spring 2002) - Schematic located at: http://mil.ufl.edu/imdl/papers/IMDL_Report_Spring_02/michael_hatterman/hacked_ir.pdf 23 12. Appendix A: Sources for Parts Microcontroller: Progressive AT-Mega163 http://www.prllc.com Servos: MX-400 – Acroname http://www.acroname.com Plastic Molded Wheels: Mark III http://www.junun.org/MarkIII/Store.jsp 40 kHz modulated IR detectors: Sharp GP2D12 – Mark III 56 kHz modulated IR detectors: LiteOn LTM-9034 – Jameco http://www.jameco.com Batteries: Ni-MH Rechargeable – Hosfelt Electronics http://www.hosfelt.com 24 13.Appendix B: Programming Code // IR Test // Reads IR data in from PA0. The ADC converts the voltage // into a digial value that is then displayed on the // LED array. #include <io.h> #include <interrupt.h> #include <sig-avr.h> #define AVR_MEGA 0 typedef unsigned char u08; u08 analog(u08 channel) { u08 sample_L, sample_H; outp(channel, ADMUX); sbi(ADCSR, ADSC); /* begin conversion */ loop_until_bit_is_set(ADCSR, ADIF); sample_L = inp(ADCL); /* get low 8 bits */ sample_H = inp(ADCH);/* get high bits */ sbi(ADCSR, ADIF); /* clear ADC interrupt flag */ return sample_H; } int main(void) { outp(0xCE,ADCSR); outp(0x20,ADMUX); outp(0xff,DDRC); for (;;) { register u08 led = analog(0x20); outp(led,PORTC); } } 25 //Servo Testing Code #include <io.h> #include <sig-avr.h> #define AVR_MEGA 0 int main(void) { outp(0xFF,DDRD); outp(0xA1,TCCR1A); outp(0x04,TCCR1B); outp(0x00,TCNT1H); outp(0x00,TCNT1L); outp(0x00,OCR1AH); outp(0x14,OCR1AL); outp(0x00,OCR1BH); outp(0x14,OCR1BL); for (;;) {} } 26 //Collision Avoidance Testing Code #include <io.h> #include <interrupt.h> #include <sig-avr.h> #define AVR_MEGA 0 #define close 0x30 #define very_close 0x4B #define stop 0x12 #define error 0x96 #define l_max 0x14 #define l_half 0x13 #define l_maxr 0x10 #define l_halfr 0x11 #define r_max 0x10 #define r_half 0x11 #define r_maxr 0x14 #define r_halfr 0x13 #define l_motor 0x00 #define r_motor 0x01 #define zero 0x00 typedef unsigned char u08; u08 ir_left=0; u08 ir_right=0; u08 analog(u08 channel) { u08 sample_val_L, sample_val_H; outp(channel, ADMUX); sbi(ADCSR, ADSC); /* begin conversion */ loop_until_bit_is_set(ADCSR, ADIF); sample_val_L = inp(ADCL); /* get low 8 bits */ sample_val_H = inp(ADCH);/* high 2 bits, not used */ sbi(ADCSR, ADIF); /* clear ADC interrupt flag */ return sample_val_H; } 27 void Wait_opt(int time) { volatile int a, b, c, d; for (a = 0; a < time; ++a) { for (b = 0; b < 10; ++b) { for (c = 0; c < 66; ++c) { d = a + 1; } } } return; } int main(void) { // Set up servos outp(0xFF,DDRD); outp(0xA1,TCCR1A); outp(0x04,TCCR1B); outp(0x00,TCNT1H); outp(0x00,TCNT1L); outp(0x00,OCR1AH); outp(0x12,OCR1AL); outp(0x00,OCR1BH); outp(0x12,OCR1BL); // Set up A/D outp(0xCE,ADCSR); outp(0x20,ADMUX); outp(0xff,DDRC); for (;;) { ir_left=analog(0x20); ir_right=analog(0x21); Wait_opt(50); if (ir_left>error || ir_right>error) { Wait_opt(10); } else if (ir_left>very_close) { outp(l_max,OCR1AL); 28 outp(r_maxr,OCR1BL); Wait_opt(100); } else if (ir_left<very_close && ir_right>very_close) { outp(l_maxr,OCR1AL); outp(r_max,OCR1BL); } else if (ir_left>close && ir_right>close) { outp(l_max,OCR1AL); outp(stop,OCR1BL); } else if (ir_left>close && ir_right<close) { outp(l_max,OCR1AL); outp(r_half,OCR1BL); } else if (ir_left<close && ir_right>close) { outp(l_half,OCR1AL); outp(r_max,OCR1BL); } else if (ir_left<close && ir_right<close) { outp(l_max,OCR1AL); outp(r_max,OCR1BL); } } } 29 // Main program code for GANDHI #include <io.h> #include <sig-avr.h> #define AVR_MEGA 0 #define close 0x30 #define very_close 0x4B #define stop 0x12 #define error 0x96 #define l_max 0x14 #define l_half 0x13 #define l_maxr 0x10 #define l_halfr 0x11 #define r_max 0x10 #define r_half 0x11 #define r_maxr 0x14 #define r_halfr 0x13 #define l_motor 0x00 #define r_motor 0x01 #define zero 0x00 #define thresh 0x57 #define svery_close typedef unsigned char u08; u08 ir_left=0; u08 ir_right=0; u08 seek_left=0; u08 seek_center=0; u08 seek_right=0; u08 tracking=0; u08 analog(u08 channel) { u08 sample_val_L, sample_val_H; outp(channel, ADMUX); sbi(ADCSR, ADSC); /* begin conversion */ loop_until_bit_is_set(ADCSR, ADIF); 30 sample_val_L = inp(ADCL); /* get low 8 bits */ sample_val_H = inp(ADCH);/* high 2 bits, not used */ sbi(ADCSR, ADIF); /* clear ADC interrupt flag */ return sample_val_H; } void Wait_opt(int time) { volatile int a, b, c, d; for (a = 0; a < time; ++a) { for (b = 0; b < 10; ++b) { for (c = 0; c < 66; ++c) { d = a + 1; } } } return; } int main(void) { //Turn on beacons outp(0xFF,DDRD); outp(0x19,TCCR2); outp(0x35,OCR2); // Set up servos outp(0xFF,DDRD); outp(0xA1,TCCR1A); outp(0x04,TCCR1B); outp(0x00,TCNT1H); outp(0x00,TCNT1L); outp(0x00,OCR1AH); outp(0x12,OCR1AL); outp(0x00,OCR1BH); outp(0x12,OCR1BL); // Set up A/D outp(0xCE,ADCSR); outp(0x20,ADMUX); outp(0xff,DDRC); 31 // Set up Port B outp(0x00,DDRB); outp(0x1F,PORTB); // Turn on LED's outp(0xFF,DDRC); // Main program code for (;;) { register u08 LED = inp(PINB); register u08 bump = inp(PINB)&0x1F; register u08 b_back = bump&0x01; register u08 b_left = bump&0x02; register u08 b_center = bump&0x04; register u08 b_right = bump&0x08; outp(LED,PORTC); if (bump<0x1F) { // Bump detection outp(stop,OCR1AL); outp(stop,OCR1BL); Wait_opt(100); if (b_back==0) { outp(l_max,OCR1AL); outp(r_max,OCR1BL); } else if (b_left==0 || b_center==0) { outp(l_halfr,OCR1AL); outp(r_maxr,OCR1BL); } else if (b_right==0) { outp(l_maxr,OCR1AL); outp(r_halfr,OCR1BL); } Wait_opt(500); } // IR Beacon Detection seek_left = analog(0x22); 32 seek_center = analog(0x23); seek_right = analog(0x24); if (seek_left>error || seek_center>error || seek_right>error) { Wait_opt(5); } else if (seek_left>thresh || seek_center>thresh || seek_right>thresh) { tracking = 1; if (seek_center>seek_left && seek_center>seek_right) { outp(l_max,OCR1AL); outp(r_max,OCR1BL); } else if (seek_left>seek_center && seek_left>seek_right) { outp(l_half,OCR1AL); outp(r_max,OCR1BL); } else if (seek_right>seek_left && seek_right>seek_center) { outp(l_max,OCR1AL); outp(r_half,OCR1BL); } } else { tracking=0; } // Collision Avoidance ir_left=analog(0x20); ir_right=analog(0x21); if (ir_left>error || ir_right>error) { Wait_opt(5); } else if (tracking == 1) { Wait_opt(5); } else if (ir_left>very_close) { outp(l_max,OCR1AL); outp(r_maxr,OCR1BL); Wait_opt(100); } 33 else if (ir_left<very_close && ir_right>very_close) { outp(l_maxr,OCR1AL); outp(r_max,OCR1BL); } else if (ir_left>close && ir_right>close) { outp(l_max,OCR1AL); outp(stop,OCR1BL); } else if (ir_left>close && ir_right<close) { outp(l_max,OCR1AL); outp(r_half,OCR1BL); } else if (ir_left<close && ir_right>close) { outp(l_half,OCR1AL); outp(r_max,OCR1BL); } else if (ir_left<close && ir_right<close) { outp(l_max,OCR1AL); outp(r_max,OCR1BL); } } } 34 // Main program code for WARRIOR #include <io.h> #include <sig-avr.h> #define AVR_MEGA 0 #define close 0x30 #define very_close 0x4B #define stop 0x12 #define error 0x96 #define l_max 0x14 #define l_half 0x13 #define l_maxr 0x10 #define l_halfr 0x11 #define r_max 0x10 #define r_half 0x11 #define r_maxr 0x14 #define r_halfr 0x13 #define l_motor 0x00 #define r_motor 0x01 #define zero 0x00 #define awhile 20000 #define thresh 0x57 typedef unsigned char u08; u08 ir_left=0; u08 ir_right=0; int timeout=awhile; u08 rest=0; u08 peace=0; u08 enemy=0; u08 analog(u08 channel) { u08 sample_val_L, sample_val_H; outp(channel, ADMUX); sbi(ADCSR, ADSC); /* begin conversion */ loop_until_bit_is_set(ADCSR, ADIF); sample_val_L = inp(ADCL); /* get low 8 bits */ 35 sample_val_H = inp(ADCH);/* high 2 bits, not used */ sbi(ADCSR, ADIF); /* clear ADC interrupt flag */ return sample_val_H; } void Wait_opt(int time) { volatile int a, b, c, d; for (a = 0; a < time; ++a) { for (b = 0; b < 10; ++b) { for (c = 0; c < 66; ++c) { d = a + 1; } } } return; } int main(void) { //Turn on beacons outp(0xFF,DDRD); outp(0x19,TCCR2); outp(0x35,OCR2); // Set up servos outp(0xFF,DDRD); outp(0xA1,TCCR1A); outp(0x04,TCCR1B); outp(0x00,TCNT1H); outp(0x00,TCNT1L); outp(0x00,OCR1AH); outp(0x12,OCR1AL); outp(0x00,OCR1BH); outp(0x12,OCR1BL); // Set up A/D outp(0xCE,ADCSR); outp(0x20,ADMUX); outp(0xff,DDRC); 36 // Set up Port B outp(0x80,DDRB); outp(0x9F,PORTB); // Turn on LED's outp(0xFF,DDRC); // Main program code for (;;) { timeout--; if (timeout==0 ) { timeout=awhile; if (rest==0) { rest=1; if (peace==1) { outp(l_max,OCR1AL); outp(r_maxr,OCR1BL); } else if (peace==0) { outp(stop,OCR1AL); outp(stop,OCR1BL); } } else { rest = 0; outp(l_max,OCR1AL); outp(r_max,OCR1BL); } } // Collision Avoidance ir_left=analog(0x20); ir_right=analog(0x21); if (ir_left<error && ir_right<error && rest==0) { if (ir_left>very_close) { outp(l_max,OCR1AL); outp(r_maxr,OCR1BL); Wait_opt(150); } 37 else if (ir_left<very_close && ir_right>very_close) { outp(l_maxr,OCR1AL); outp(r_max,OCR1BL); } else if (ir_left>close && ir_right>close) { outp(l_max,OCR1AL); outp(stop,OCR1BL); } else if (ir_left>close && ir_right<close) { outp(l_max,OCR1AL); outp(r_half,OCR1BL); } else if (ir_left<close && ir_right>close) { outp(l_half,OCR1AL); outp(r_max,OCR1BL); } else if (ir_left<close && ir_right<close) { outp(l_max,OCR1AL); outp(r_max,OCR1BL); } } // Bump Detection register u08 LED = inp(PINB); register u08 bump = inp(PINB)&0x1F; register u08 b_back = bump&0x01; register u08 b_left = bump&0x02; register u08 b_center = bump&0x04; register u08 b_right = bump&0x08; register u08 b_gandhi = bump&0x10; outp(LED,PORTC); if (b_gandhi==0 || (bump<0x1F && rest==1)) { outp(0x00,TCCR2); peace=1; outp(0x1F,PORTB); outp(stop,OCR1AL); outp(stop,OCR1BL); Wait_opt(100); timeout=1; rest=0; 38 } if (bump<0x1F) { outp(stop,OCR1AL); outp(stop,OCR1BL); Wait_opt(50); if (b_back==0) { outp(l_max,OCR1AL); outp(r_max,OCR1BL); } else if (b_left==0 || b_center==0) { outp(l_halfr,OCR1AL); outp(r_maxr,OCR1BL); } else if (b_right==0) { outp(l_maxr,OCR1AL); outp(r_halfr,OCR1BL); } Wait_opt(200); } // Enemy IR Detection enemy=analog(0x22); while ((enemy>thresh) && (rest==1) && (peace==0)) { outp(l_max,OCR1AL); outp(r_maxr,OCR1BL); Wait_opt(10); outp(stop,OCR1AL); outp(stop,OCR1BL); } } } 39