· web viewthe motors are controlled by an arduino due microcontroller which receives its data on...

38
Trash2D2 David Mercado April 22, 2014 University of Florida Department of Electrical and Computer Engineering EEL 4665 - IMDL - Final Written Report

Upload: nguyenlien

Post on 29-Aug-2018

213 views

Category:

Documents


0 download

TRANSCRIPT

Trash2D2David MercadoApril 22, 2014

University of FloridaDepartment of Electrical and Computer Engineering

EEL 4665 - IMDL - Final Written ReportInstructors: A. Antonio Arroyo, Eric M. Schwartz

TAs: Josh Weaver, Andy Gray, Nick Cox, Dan Frank

Table of ContentsAbstract .......................................................................................................................................... 3

Introduction .................................................................................................................................... 3

Integrated System ........................................................................................................................... 3

Mobile Platform ............................................................................................................................. 4

Actuation ........................................................................................................................................ 5

Sensors ........................................................................................................................................... 6

Behaviors ....................................................................................................................................... 9

Experimental Layout and Results ................................................................................................ 10

Conclusion ................................................................................................................................... 15

Documentation ............................................................................................................................. 16

Appendices ................................................................................................................................... 17

2

AbstractTrash2D2 is a mobile, intelligent garbage can robot that automatically opens its lid when the user wants to dispose of trash, signals the user when the bag is full, and roams throughout the room in order to collect trash from persons at various locations. Additionally, this robot detects a high frequency sound emission and move towards its location of origin, much like a homing station.

To accomplish these tasks, Trash2D2 is composed of a cylindrical can, one foot in diameter and height, equipped with motors for its two driving wheels and lid. The motors are controlled by an Arduino Due microcontroller which receives its data on the surroundings from five infrared sensors, two bumper sensors, and two filtered, amplified microphones.

IntroductionDuring meetings and parties where food and drinks are being served, people will often have all sorts of trash that they would like to dispose of. More often than not, there is no trash can in the vicinity of each person and group of people, leading to many attendants disposing of their trash on top of the furniture or on the floor. This robot corrects, or at least minimizes, this problem by providing a trash can throughout the meeting room during the duration of the event. Specifically, Trash2D2 is an intelligent trash can on a mobile platform that moves throughout the room randomly, collecting trash from the attendants.

Additionally, Trash2D2 is equipped with a sound recognition system that detects a call signal at a particular frequency, commanding the robot to then travel to the origin of the call signal. The signal can be placed by the door and programmed to set off on garbage collection day. This way, Trash2D2 will conveniently be waiting at the door at these times of the week for the user to dispose of the garbage.

Finally, Trash2D2 can detect when the current garbage bag is full and needs to be replaced. The robot then visually indicates this to the user by maintaining its lid open and remaining still.

Integrated SystemThe robot is controlled using an Arduino Due microcontroller. No communication is needed with another board or external computer. The following types of connections are established with the Arduino board:

Analog Inputs: Two (2) Electret Microphones (Filtered & Amplified) Digital Inputs: Four (4) Infrared Sensors, Two (2) Bumper Sensors Digital Outputs: Various LEDs, Four (4) Motors (some with encoders and/or requiring

PWM capabilities).

These sensors provide data to the microprocessor about the surroundings of the robot so that it can determine the appropriate action to take. The board itself is programmed to perform actions based on a priority hierarchy and system of conditions that need to be met. This code is included

3

in the appendix of this report to allow for further inspection. The actions dictated by the microprocessor and the order of priority can be seen in the following flowchart:

Mobile PlatformAlthough the trash can itself will serve as the human interface of the robot, the central circuitry of the robot, including the microcontroller, is attached to a separate balsa wood platform. This platform, lying beneath the trash can, is where the connections are made with the motors and sensors. The motors that power the mobile platform are attached to the bottom of the balsa wood platform, connecting with two driving wheels placed at either side of the outside cylinder. Two caster wheels are also attached to the bottom of the wooden platform to provide additional support.

4

The two-wheel-drive system enables the robot to rotate about a point near its center of mass, clearing itself of obstacles and granting greater flexibility. The mobile platform is what allows the Trash2D2 to engage in roaming behavior, obstacle avoidance, corner stationing, and retreat towards the sound call signal emission.

ActuationThree motors are used in the assembly of Trash2D2:

180 Degree Rotation Servo Motor (1)o Powers a lever that opens and closes the lid of the trash can.o Hi-Tech HS-485HB, 67 oz-in. stall torque at 4.8 Vo Powered by 5V output from Arduino

5

Brushed DC Motors w/ Encoders (2)o The DC motors, in conjunction with wheel hubs, power the rotation of the driving

wheels on the left and right sides of the mobile platform.o Motors come with a 75:1 metal gearbox, powered by 7.2 V battery at 2.2 A to

provide 85 oz-in torque.o Wheels are 8 cm in diameter in order to move between 1 ft/s and 2 ft/s and carry

around 8 lbs of weight.o Attached to mobile platform using mounting brackets.o Power distribution controlled using speed controllers.

SensorsIn order to have knowledge of its surroundings, the robot is equipped with three different types of sensors - IR, bumper, and sound detection. The signals from these sensors serve as inputs for the Trash2D2.

Sharp Infrared Proximity Sensors (4)o Sensor emits an infrared signal straight ahead and measures the amount of

infrared light that was reflected back at the sensor. In this manner, the sensor can measure its distance away from an object in the direction of the signal.

o Three IR sensors are placed at the front of the robot in order to detect objects at a distance that are in the path of motion of the trash can. Two sensors are placed at opposite ends from each other to detect the orientation of the obstacle present. In this manner, the robot can decide whether to avoid the object by turning right or left. The third sensor is placed at the center to avoid objects in the line of action.

o Another IR sensor is placed at the top of the trash can lid. This IR sensor detects when a person is waving their hand over the lid. This signifies to the trash can that a user is attempting to throw trash away, which would command the lid to open for 4 seconds.

6

o The last IR sensor is placed on the inside of the can lid, directed downwards. This sensor measures the height of the trash in the can. If the trash height crosses the set threshold, the garbage can is flagged as full. This causes the lid to open and the robot to stop moving permanently until the user replaces the bag and resets the robot.

o Analog output varies between 3.1 V at 10 cm to 0.4 V at 80 cm.

Bumper Sensors (2)o The bumper sensors are simply a switch attached to a lever. When the lever is

pushed down, the switch closes, sending a signal tied to vcc to the microcontroller. To ensure that the signal does not float, the signal is connected to a 1 kΩ resistor tied to ground, creating a pull-down resistor.

o The two bumper sensors are placed on the front of the robot in order to detect whether the robot ran into an obstacle. The robot then retreats and readjusts itself to avoid the obstacle.

7

Electret Microphones w/ Bandpass Filter (2)o Each of these systems is composed of a microphone and a bandpass filter circuit

with an amplifier composed of resistors, capacitors, and an op-amp. These systems detect a particular range of sound within the natural audible frequency, at approximately 6500 to 7500 kHz and send a corresponding analog voltage signal, amplified about 100x, to the microcontroller. The circuit diagram of the bandpass filter is shown below.

o The microphone and filter circuit are powered by 3.3 V and ground.o The two microphone systems are placed at either side of the front of the robot in

order to detect sound in the orientations directed at. When the whistle goes off, the robot orients itself towards the origin of the sound by rotating towards the microphone with the louder signal and then travels forward towards the source. The separation of the microphones with slight overlap allows the robot to determine the sound origin orientation.

8

o The sound waves coming into the electret microphones are amplified using conical Styrofoam bowl receptors that reflect the sound waves towards the microphone and block sound waves attempting to enter from the sides. The receptors are oriented away from each other in order to provide the signals with a directional sense and aid in the orientation towards the sound source.

BehaviorsThe robot is able to accomplish the following behaviors:

Roam around a room avoiding obstacles in its way. When objects are present in infrared view, the robot changes direction. If it comes into physical contact with an object, it retreats and changes direction.

Capture sound data using two microphones, filtered so that only sounds at approximately 7 kHz are detected. This allows the robot to only listen for the homing signals and ignore noise at different frequencies, including the human voice.

The robot detects the presence of the high frequency whistle from over 5 feet away and directs itself towards the origin of the sound. During this behavior, the robot continues to avoid obstacles that it collides with by temporarily moving away from the area of collision. This signal detection and orientation system is a type of homing device that commands the robot to go to the door on garbage collection days.

An automatic lid opens for 3 seconds when a hand or other object is waved above it. This allows the person to throw trash away before the lid automatically closes again. While the lid is open, the robot pauses its roaming trajectory.

The automatic lid opens and the robot ceases to run whenever the trash has passed a certain height level. This indicates that the trash bag needs to be replaced and that the robot must be reset upon doing so.

9

Experimental Layout and ResultsMultiple experiments were conducted to different extents in order to ensure that the robot performs at the optimum level. The qualitative and quantitative experiments that were conducted include the following:

The weight placed on the robot was successively increased in order to ensure that the wooden platform and wheels are able to withstand the minimum eight pounds of weight set as an objective that the robot should be able to carry.

The two DC brushless motors and wheels were powered to various velocities, including maximum power, to ensure that they can carry the 8 pound weight of the robot at 2 ft/sec; the speed and direction were changed according to the signal outputted by the Arduino board. The encoders did not need to actively guide the robot because the robot is able to drive forward in a straight line, with a very slight deviation towards the left. This meets the accuracy required from the robot when approaching the homing signal sound source.

The two caster wheels located between the drive wheels were positioned a few millimeters above the plane made by the drive wheels, keeping the platform horizontal. This keeps the caster wheels from contacting the ground at the same time, maintaining the weight on the drive wheels. Different heights were tested to ensure that the wheels are able to maintain balance to the mobile platform while the robot is driving, with little to no rocking when changing directions. Over time, the weight of the robot caused the support brackets for the motors to bend until both caster wheels made contact with the floor. The caster wheel height levels were then readjusted and the support brackets were reinforced to overcome this.

10

. The three infrared sensors placed on the mobile platform had voltage reading outputs that

were connected to ADC ports on the processor. All three sensors displayed similar readings on the serial port when an object was placed closer to and farther away from the emitters - if there was no object within two feet, the sensor reading was close to 0 while objects within 6 inches led to readings of over 300 bits. The maximum signal measured was under 900 bits at approximately an inch from the sensor, indicating that these were behaving appropriately. Multiple trial runs have shown that the robot is able to avoid obstacles by detecting their presence with the IR sensors.

Similarly to the IR sensors, the bumper switches sent a signal to the board whenever the paddle pressed down on the spring-loaded buttons. The reaction from the robot was consistently swift so that no damage was done to the motors or structure. Trial runs also showed that the paddles held in form when pressed against an object.

Two different programming logic approaches were used. Originally, delays were implemented into the main program in order to indicate to the motors driving the wheels the amount of time to rotate in a particular direction. This works adequately for obstacle avoidance, particularly since there is no delay when the robot is driving forward and obstacles are not encountered while the robot is rotating due to its round body. However, once the microphones were collecting data, the delays were impeding the board from collecting sound data while the robot was avoiding an obstacle. Additionally, using delays to time the actions the robot takes based on the special sensor readings caused the robot to get stuck in a loop because the volume was not able to update value due to the delays.

A second approach to the programming logic was taken using timers. This worked much more efficiently, such that data was continuously being collected and the robot did not get stuck in a loop of constant values. At one point, it was considered using loop iterations instead of clock timers, but this meant that the actions of the motors would be sensitive to the length of the code and the peripheral data-collecting activity. Timers allowed a much tighter control of the amount that the robot would rotate when avoiding obstacles and multiple trial runs supported this claim.

The special sensor system is centered around sound collection, so the raw data from the microphones were tested in order to make sure that the analog data coming reflected the volume of the physical sound present. The microphone input values fluctuated between 100 to 1023 bits during silence and a loud sound present next to the microphones, respectively. This was a satisfying indication that the microphones work, but the value remained low when the sound was emitted farther than two feet from the microphones. This made it clear that an amplifier was required or the sound needs to be made louder.

A non-inverting amplifier was attempted using a UA741CN op-amp chip, a 33 kΩ resistor across the negative input to the output, a 100 Ω resistor across the negative input to ground, the microphone voltage reading into the positive input terminal, and the output connect to the ADC port on the Arduino. It was expected that the signal would have an amplification of over 300, but instead the serial port indicated that the ADC port was not receiving a signal. These results remained despite the frequency and intensity of the sound measured and the wiring changes, so the analog amplifier was reassessed. After further research, it was noted that this op-amp cannot handle signals of high frequency, so an LT 1632 op-amp was eventually used instead.

11

An analog high-pass filter was created using a 33 nF capacitor and a 1000 Ω resistor in order to only allow frequencies above 5 kHz to be detected, falling within the preferred high-frequency range. The filtered worked as originally expected - signals at 2 kHz did not produce a strong voltage reading, but sounds at 7 kHz were converted into readings of up to 900 bits. The voltage signal lost strength from the filter and the readings were not consistent, despite the large sampling window. This behavior, along with the lack of response from the op-amp resulted in additional tests to inspect the signal.

When the raw voltage reading from the microphone breakout board was connected to the oscilloscope, the signal indicated waves of different frequencies and a sample wave measured was similar to the one shown on the left. However, the signal outputted from the high-pass filter looked more similar to the impulse delta functions shown on the right. It was clear then that voltage signal outputted by the breakout board that the microphones were assembled to was filtered. After an inspection of the data file of the microphone and breakout board, it was evident that a bandpass filter and op-amp were already used to amplify the sound signal by 100 and only sounds in the normal audible range were allowed. Attempting to implement multiple amplifying filter circuits would not result in adequate data and would require extensive analysis, so the breakout board was removed in order to allow a custom circuit to solely manage amplification and filtering of the raw signal.

12

The analog circuit ultimately implemented is a second-order bandpass filter, shown earlier in the report, that only allows signals at approximately 7 kHz to be amplified. The second order of high pass and low pass filters creates a sharp dropoff that keeps the range of the amplified frequencies to underneath 800 Hz. The specific resistor and capacitor values used in the circuit were iteratively tested using LT Spice. This program simulated the frequency response as a Bode plot, shown below, that shows the voltage gain experienced by signals at different frequencies. This circuit was built on a breadboard prior to permanent soldering to ensure that only this range of frequencies was amplified from the microphone by the circuit. These experiments were carried through using an Analog Discovery USB Oscilloscope that connected directly to the computer. Any changes to the resistor or capacitor values in the circuit resulted in a large fluctuation in the data collected by the oscilloscope.

Although the amplifier circuit increased the magnitude of the signal by over 100x, the sound needed to be amplified further through physical means, all the while maintaining the a specific range of direction from which the sound could be picked up. The Styrofoam bowls provided the best results in this regard since they were inexpensive, easy to adapt to the microphone, and provided decent reverb and reflection of the sound waves. Testing

13

with the oscilloscope confirmed that the bowls led to slightly higher voltage readings at a given distance, but more importantly, allowed the microphones to detect the high frequency sound from twice the angle range than they would without the Styrofoam bowls by redirecting sound waves towards the microphone. It was attempted to place the microphone at the focal point of the bowl, similar to a satellite dish, but the shape of the bowl did not lend to a particular focal point of higher wave amplitude. Additionally, different configurations and adhesive configurations were attempted, including multiple bowls joined by hot glue, but testing with the oscilloscope showed that stacking bowls did not significantly improve the reverb and the hot glue dampened the reflection of the sound waves not originally directed straight at the microphone, reducing the directional range. In the end, the best configuration involved a single bowl attached to the robot and microphone using tape, which allows the bowl to continue vibrating, and minimal hot glue to ensure the components remained attached.

After the code was written, multiple iterations were necessary in order to achieve an algorithm that most successfully allowed the robot to detect and orient itself towards the source of the sound. The signal from the bandpass amplifier was strong and without noise, and digital rectifier was implemented to determine the average volume from the sound detected. A filter was implemented that required a minimum amount of high volume measurements before performing actions. Both of these proved successful at avoiding false positives and allowing the robot to detect high frequency sounds from 5 feet ahead of it and 3 feet behind. To enable the robot to orient itself to the sound, the code that was most successful involved rotating the robot in a certain direction only in the specific moments when one microphone receives a strong signal but the other does not. This caused the robot to become agitated during the orientation, but proved to provide the most accurate and consistent results.

Further testing indicated that the robot sound detection works best in open areas, but it suffers from limitations when the walls are too close to each other, as in a narrow hallway, and when the walls are composed of cinder blocks or glass. These cases led to a heightened amount of sound reflection off the walls that led to strong enough signals to confuse the microphones as to the direction of the sound source. This issue could

14

potentially be avoided by approaching the orientation algorithm from a signal strength perspective.

Testing confirmed that the IR sensors on the lid worked properly and that the servo with a lever could lift the lid to the desired position with the electrical power provided.

ConclusionAt the end of the semester, Trash2D2 was able to accomplish all the objectives and behaviors set forth at the beginning of the class. Specifically, it became a trash can robot that could travel a room, avoiding obstacles in its way, have an automatic lid, detect when the trash is full, and orient itself and move towards the location of origin of a homing signal at a particular audio frequency. Various unforeseen problems were encountered during the building process, which caused the methods used to be reevaluated and in some cases resulted in minor adjustments to the features of the robot. However, most of the changes made, including the role of the encoders and lack of LEDs, did not result in significant losses to the overall performance and presentation of the robot.

Like most prototypes, though, there is improvement that could be made to the design. In particular, the overall structure of the code and the algorithm used to determine the sound orientation could be improved to work more consistently and efficiently. Additionally, higher quality microphones can be used to expand the range of the distance and orientation from which the robot can detect the high frequency homing signal. The homing signal itself could be changed to a frequency that is inaudible to humans. Improvements can be made to reinforce the mechanical structure of the robot, particularly the support structures, and the circuitry could be reinforced in certain connections. All things considered, Trash2D2 was a major success and it accomplished the proposed tasks with more reliability and greater success than was originally expected when the project began.

15

Documentation[1] J. Bulgarelli, "R2D2 / Thrash Can." Behance. Available at

http://www.behance.net/gallery/R2D2-Trash-Can/5624157

[2] No Author, "Infrared Proximity Sensor - Sharp." Sparkfun. Available at https://www.sparkfun.com/products/242

[3] No Author, "Breakout Board for Electret Microphones." Sparkfun. Available at https://www.sparkfun.com/products/9964

[4] No Author, "Dual MC33926 Motor Driver Carrier." Pololu Robotics & Elecronics. Available at http://www.pololu.com/product/1213

[5] No Author, "75:1 Metal Gearmotor 25Dx54L mm with 48 CPR Encoder." Pololu Robotics & Elecronics. Available at http://www.pololu.com/product/2286

16

AppendicesCode programmed into the Arduino as of 4/22/2013:

// David Mercado// Trash2D2 Code// IMDL 4/21/2013

// IR Sensor Variablesint sensor1 = A0; // right proximity sensor; ADC locationint sensor2 = A1; // left proximity sensorint sensor3 = A4; // center proximity sensorint sensor4 = A5; // bottom lid sensorint sensor5 = A6; // top lid sensorint sensorVal1 = 0; // corresponding input variablesint sensorVal2 = 0;int sensorVal3 = 0;int sensorVal4 = 0;int sensorVal5 = 0;int threshold = 400; // proximity triggers (right & left)int threshold1 = 100; // " (center)int threshold2 = 600; // " (bottom)int threshold3 = 500; // " (top)

#include <Servo.h>Servo myservo; // create servo object to control lid servo

// Microphone Data Input Variablesint mike1 = A2; // left microphone; ADC locationint mike2 = A3; // right microphone;int mikeVal1 = 0; // corresponding input variablesint mikeVal2 = 0;unsigned long timer; // timer used in sound detection loop iterationsint volume1 = 0; // average volume calculation variablesint volume2 = 0;int v = 0; // enable to maintain sound loop ongoingint ve = 0; // enable to initialize sound loopint i = 0; // for-loop variableint vol1[500]; // array for volume1 dataint vol2[500]; // array for volume2 dataunsigned long timer3; // timer to restart sound loop initialization enable

// Drive Wheel Motor Variables

17

int pwmleft = 2; // speed controlsint pwmright = 3;int dleft = 22; // enableint dright = 23; // enableint enable_m = 24; // enableint vdd_m = 25;int mr_in1 = 26; // directional controlsint mr_in2 = 27;int ml_in1 = 28;int ml_in2 = 29;

// Bumper Variables int bumper1 = 34; // bumper inputs (right)int bumper2 = 36; // " (left)int rightbump = 0; // corresponding input variablesint leftbump = 0;

// Enables to Maintain Sensor Loops Ongoingint rb = 0; // right bumperint lb = 0; // left bumperint sv1 = 0; // sensors 1 - 5int sv2 = 0;int sv3 = 0;int sv4 = 0;int sv5 = 0;

// Variables for working codeunsigned long timer2 = millis();int Action = 3; // switch-case variable for current action

void setup() // setup code here, runs once: Serial.begin(9600); // Initialize digital inputs & outputs pinMode(dleft, OUTPUT); pinMode(dright, OUTPUT); pinMode(enable_m, OUTPUT); pinMode(vdd_m, OUTPUT); pinMode(mr_in1, OUTPUT); pinMode(mr_in2, OUTPUT); pinMode(ml_in1, OUTPUT); pinMode(ml_in2, OUTPUT); pinMode(pwmleft, OUTPUT); pinMode(pwmright, OUTPUT); pinMode(bumper1, INPUT);

18

pinMode(bumper2, INPUT); // Initialize servo motor pin location and initial position myservo.attach(4); myservo.write(0); delay(2000); // Increase the clock speed to gather audio waveform data REG_ADC_MR = (REG_ADC_MR & 0xFFF0FFFF) | 0x00020000;

void loop() // main code here, runs repeatedly:

// enable motors digitalWrite(dleft, LOW); digitalWrite(dright, LOW); digitalWrite(enable_m, HIGH); digitalWrite(vdd_m, HIGH); // read bumper and IR sensors rightbump = digitalRead(bumper1); leftbump = digitalRead(bumper2); sensorVal1 = analogRead(sensor1); sensorVal2 = analogRead(sensor2); sensorVal3 = analogRead(sensor3); sensorVal4 = analogRead(sensor4); sensorVal5 = analogRead(sensor5);

// Gather filtered sound wave samples volume1 = 0; // initialize average volume variable volume2 = 0; // Left Microphone Data Collection for (i=0;i<500;i++) // 500 data points of sound input vol1[i]=analogRead(mike1) - 310; for (i=0;i<500;i++) if (vol1[i] < 0) // rectify wave for same polarity vol1[i] = -vol1[i]; volume1 = volume1 + vol1[i]; // add all rectified samples together volume1 = volume1/500; // find average left mike volume // Right Microphone Data Collection for (i=0;i<500;i++)

19

vol2[i]=analogRead(mike2) - 300; for (i=0;i<500;i++) if (vol2[i] < 0) vol2[i] = -vol2[i]; volume2 = volume2 + vol2[i]; volume2 = volume2/500;

// Commands if right bumper hit if(rightbump!=0 || rb==1) rb = 1; // enable to run loop through actions if(millis() - timer2 < 500) Action = 0; // retreat for .5 seconds else if(millis() - timer2 < 1500) Action = 1; // turn left for 1.5 sec else Action = 3; // forward (default) timer2 = millis(); // timer reset rb = 0; // right bumper reset // Commands if left bumper hit else if(leftbump!=0 || lb==1) lb = 1; // loop enable if(millis() - timer2 < 500) Action = 0; // retreat for .5 sec else if(millis() - timer2 < 1500) Action = 2; // turn right for 1.5 sec else Action = 3; // forward (default) timer2 = millis(); // timer reset lb = 0; // left bumper reset // Commands if bumpers not hit else if(lb==0 && rb==0) // Commands if high frequency sound detected (and no current actions) if((volume1 > 50 || volume2 > 50 || v==1) && sv5 == 0 && sv4 == 0) ve = ve + 1; // activation enable, keeps track of high volume instances // Actions once strong volume signals detected (after 5 positive iterations) if(ve > 4 || v == 1) if(v == 0) // first iteration actions

20

timer = millis(); // intialize sound loop timer v = 1; // set sound loop enable sv1 = 0; // reset proximity IR loop enables sv2 = 0; sv3 = 0; // Stop & flap lid to show high frequency detected if(millis() - timer < 1500) Action = 6; // stop for 1.5 seconds & open lid myservo.write(90); else if(millis() - timer < 3000) Action = 6; // stop for 1.5 sec & close lid myservo.write(0); else if(millis() - timer < 4500) Action = 6; // stop for 1.5 sec & open lid myservo.write(90); // Continuously compare signal from both microphones & align for 5.5 sec else if(millis() - timer < 10000) if(volume1 > 50 && volume2 < 40) Action = 4; // if left mic has stronger signal, turn left else if(volume1 < 50 && volume2 > 40) Action = 5; // if right mic has stronger signal, turn right else if(volume1 > 50 && volume2 > 40) Action = 6; // if both signals strong, hold still timer2 = 0; // reset main timer // Approach sound source for up to 20 seconds else if(millis() - timer < 30000) // Compare signal and align for 5 seconds if 5 seconds have passed if(millis() - timer < 20000 && millis() - timer > 15000) if(volume1 > 50 && volume2 < 40) Action = 4; // left signal stronger, turn left else if(volume1 < 50 && volume2 > 40) Action = 5; // right signal stronger, turn right else if(volume1 > 50 && volume2 > 40) Action = 6; // both signals strong, hold still timer2 = 0; // reset main timer

21

// Commands if right IR sensor triggered else if((sensorVal1 > threshold || sv1==1) && sv2==0 && sv3==0) sv1 = 1; // loop enable if(sensorVal2 > threshold) // left sensor confirms source found Action = 7; // stop "permanently" timer2 = millis(); // reset main timer timer = millis() - 40000; // run down sound loop timer sv1 = 0; // reset loop enable else if(millis() - timer2 < 1000) Action = 5; // turn right for up to 1 second to align else Action = 7; // stop "permanently" timer2 = millis(); // reset main timer timer = millis() - 40000; // run down sound loop timer sv1 = 0; // reset loop enable // Commands if left IR sensor triggered else if((sensorVal2 > threshold || sv2==1) && sv3==0) sv2 = 1; // loop enable if(sensorVal1 > threshold) // right sensor confirms source found Action = 7; // stop "permanently" timer2 = millis(); // reset main timer timer = millis() - 40000; // run down sound loop timer sv1 = 0; // reset loop enable else if(millis() - timer2 < 1000) Action = 4; // turn left for up to 1 second to align else Action = 7; // stop "permanently" timer2 = millis(); // reset main timer timer = millis() - 40000; // run down sound loop timer sv2 = 0; // reset loop enable // Commands if center IR sensor triggered else if((sensorVal3 > threshold1 || sv3==1) && sv4==0 && sv5==0) sv3 = 1; // loop enable Action = 7; // stop "permanently" timer2 = millis(); // reset main timer timer = millis() - 40000; // run down sound loop timer sv3 = 0; // reset loop enable else // if source location not found Action = 3; // drive forward (default) timer2 = millis(); // reset main timer

22

else // final special system actions myservo.write(0); // close lid (allow 1 sec) delay(1000); digitalWrite(mr_in1, LOW); // reverse (allow 0.5 sec) digitalWrite(mr_in2, HIGH); digitalWrite(ml_in1, LOW); digitalWrite(ml_in2, HIGH); analogWrite(pwmleft, 128); analogWrite(pwmright, 128); delay(500); timer = millis(); // reset sound loop timer v = 0; // reset sound loop enable

// Commands if right IR sensor triggered else if((sensorVal1 > threshold || sv1==1) && sv2==0 && sv3==0 && sv4==0 && sv5==0) sv1 = 1; // loop enable if(millis() - timer2 < 1500) Action = 1; // turn left for 1.5 sec else Action = 3; // forward (default) timer2 = millis(); // reset main timer & loop enable sv1 = 0; // Commands if left IR sensor triggered else if((sensorVal2 > threshold || sv2==1) && sv3==0 && sv4==0 && sv5==0) sv2 = 1; // loop enable if(millis() - timer2 < 1500) Action = 2; // turn right for 1.5 sec else Action = 3; // forward (default) timer2 = millis(); // reset main timer & loop enable sv2 = 0; // Commands if center IR sensor triggered else if((sensorVal3 > threshold1 || sv3==1) && sv4==0 && sv5==0) sv3 = 1; if(millis() - timer2 < 500) Action = 0; // retreat for 0.5 sec else if(millis() - timer2 < 1500) Action = 1; // turn left for 1 sec

23

else Action = 3; // forward (default) timer2 = millis(); // reset main timer & loop enable sv3 = 0;

// Commands if bottom IR sensor triggered else if((sensorVal4 > threshold2 || sv4==1) && sv5==0) sv4 = 1; // loop enable if(millis() - timer2 < 15000) Action = 6; // stop for 15 sec myservo.write(90); // open lid else if(millis() - timer2 < 18000) Action = 6; // stop for 3 sec myservo.write(0); // close lid else Action = 3; // forward (default) timer2 = millis(); // reset main timer & loop enable sv4 = 0;

// Commands if top IR sensor triggered else if(sensorVal5 > threshold3 || sv5==1) sv5 = 1; // loop enable if(millis() - timer2 < 3000) Action = 6; // stop for 3 sec myservo.write(90); // open lid else if(millis() - timer2 < 4500) Action = 6; // stop for 1.5 sec myservo.write(0); // close lid else Action = 3; // forward (default) timer2 = millis(); // reset main timer & loop enable sv5 = 0;

// Commands if no sensors triggered else if(sv1==0 && sv2==0 && sv3==0 && sv4==0 && sv5==0) Action = 3; // forward (default) timer2 = millis(); // reset main timer if(millis() - timer3 > 500) // reset sound loop initialization enable timer3 = millis(); // every 0.5 sec ve = 0;

24

// Driving Commands switch(Action) case 0: //reverse digitalWrite(mr_in1, LOW); digitalWrite(mr_in2, HIGH); digitalWrite(ml_in1, LOW); digitalWrite(ml_in2, HIGH); analogWrite(pwmleft, 128); analogWrite(pwmright, 128); break; case 1: //turn left digitalWrite(mr_in1, HIGH); digitalWrite(mr_in2, LOW); digitalWrite(ml_in1, LOW); digitalWrite(ml_in2, HIGH); analogWrite(pwmleft, 128); analogWrite(pwmright, 128); break; case 2: //turn right digitalWrite(mr_in1, LOW); digitalWrite(mr_in2, HIGH); digitalWrite(ml_in1, HIGH); digitalWrite(ml_in2, LOW); analogWrite(pwmleft, 128); analogWrite(pwmright, 128); break; case 3: //forward digitalWrite(mr_in1, HIGH); digitalWrite(mr_in2, LOW); digitalWrite(ml_in1, HIGH); digitalWrite(ml_in2, LOW); analogWrite(pwmleft, 200); analogWrite(pwmright, 200); break; case 4: //turn left slowly digitalWrite(mr_in1, HIGH); digitalWrite(mr_in2, LOW); digitalWrite(ml_in1, LOW); digitalWrite(ml_in2, HIGH); analogWrite(pwmleft, 128); analogWrite(pwmright, 128); break; case 5: //turn right slowly digitalWrite(mr_in1, LOW); digitalWrite(mr_in2, HIGH); digitalWrite(ml_in1, HIGH);

25

digitalWrite(ml_in2, LOW); analogWrite(pwmleft, 128); analogWrite(pwmright, 128); break; case 6: //stop analogWrite(pwmleft, 0); analogWrite(pwmright, 0); break; case 7: //stop "permanently" analogWrite(pwmleft, 0); analogWrite(pwmright, 0); delay(5000); break;

26