Willie and I have decided on building a recycling can that can detect "shots" (when the paper you throw at it goes into the can), and provides audio feedback with sound effects from NBA Jams. The first step was to think about how we could detect these things going in. Infrared sensing made the most sense. We bought sensor and emitter pairs from Radio Shack which worked really well. We were also really surprised with how much stuff Radio Shack had to cater to the Arduino tinkerer. Definitely an under-rated resource.
Anyways, we got the IR pairs to detect and set off a normal LED. SWEET! Basically, we watched the Serial monitor for values, and then manually set a threshold.
Here's a photo:
Here's our code for the simple IR detections:
//
// IR_Sensors_2.ino -- play the current value of an IR Sensor on a 5v speaker, adjusting
// from a base pitch of C3 (220hz)
//
// Dervied from http://arduino.cc/forum/index.php?topic=94690.0
//
// Note: Detector is clear, emitter is dark
//
//
// Constants
const int IR_IN_ANALOG_PIN = 2; // analog input pin -- Detector (clear)
const int IR_OUTPUT_PIN = 2; // digital output pin -- Emitter/dark)
const int LEDsignalPin = 13; // signal pin setup
const String INTRO = "Starting...";
// IR level values
int irLevel = 0; // variable to store the value read from input pin
int minIRLevel = 1000;
int maxIRLevel = 0;
int lastIRLevel = 0;
int irTone = 0;
bool firstLoop = true;
bool debug = true; // Set false to turn off Serial tracing
bool newRange = false;
//
// setup
//
void setup() {
// Set up the output LED
pinMode( IR_OUTPUT_PIN, OUTPUT );
digitalWrite( IR_OUTPUT_PIN, HIGH ); // Turns on the emitter
pinMode( LEDsignalPin, OUTPUT ); //sets signal LED to off
// Turn on tracing
if ( debug ) {
Serial.begin( 9600 );
}
}
//
// loop -- show the current input to the detector. Sense and highlight changes to the observed
// min, max and avg values of the signal
//
void loop() {
// read value of analog input
irLevel = analogRead( IR_IN_ANALOG_PIN );
// Play its value
//irTone = NOTE_C3 + irLevel;
//tone( SPKR_PIN, irTone );
// print header & initial irLevel
if ( firstLoop == true ) {
if ( debug ) {
Serial.println( INTRO );
Serial.print( "initial irLevel = " );
Serial.println( irLevel );
}
firstLoop = false;
}
// Check if irLevel changed
newRange = false;
if ( irLevel < 60) {
digitalWrite (LEDsignalPin, HIGH);
delay(50);
digitalWrite (LEDsignalPin, LOW);
}
if ( irLevel != lastIRLevel ) {
// Trace the new IR level
if ( debug ) {
// Print the level
Serial.print( "irLevel = " );
Serial.print( irLevel );
// Print increase/decrease
if ( irLevel > lastIRLevel ) {
Serial.print( " +++" );
} else {
Serial.print( " ---" );
}
}
// Save new minimum
if ( irLevel < minIRLevel ) {
if ( debug ) {
Serial.print( " new MIN" );
}
newRange = true;
minIRLevel = irLevel;
}
// Save new maximum
if ( irLevel > maxIRLevel ) {
if ( debug ) {
Serial.print( " new MAX" );
}
newRange = true;
maxIRLevel = irLevel;
}
// Finish the trace line
if ( debug ) {
Serial.println( "" );
}
// Print new range
if ( newRange ) {
if ( debug ) {
Serial.print( "Range: [ " );
Serial.print( minIRLevel );
Serial.print( ", " );
Serial.print( maxIRLevel );
Serial.println( " ]" );
}
}
// Save the irLevel
lastIRLevel = irLevel;
// wait half a second
if ( debug ) {
delay( 5 );
}
}
}
We later added a calibration to the IR setup, so that it would calibrate itself to the surrounding IR levels, and then watch for those to be changed. This means we can turn it on in any situation and it will adjust to the ambient about of IR light. Here's the code for that:
// this is an LED blink sketch with calibration for just one Sensor
const int sensorOne = A0; // analog input pin -- Detector (clear)
const int sensorTwo = A1;
const int sensorThree = A2;
const int emitterPin = 2; // digital output pin -- Emitter/dark)
const int signalPin = 13; // signal pin setup
// variables:
int sensorValue = 0; // the sensor value
int sensorMin = 1023; // minimum sensor value
int sensorMax = 0; // maximum sensor value
void blink() {
digitalWrite(13, HIGH);
delay(300);
digitalWrite(13, LOW);
}
void setup() {
// turn on LED to signal the start of the calibration period:
pinMode(signalPin, OUTPUT);
digitalWrite(signalPin, HIGH);
pinMode( emitterPin, OUTPUT );
digitalWrite( emitterPin, HIGH ); // Turns on the emitter
// calibrate during the first three seconds
while (millis() < 3000) {
sensorValue = analogRead(sensorOne);
// record the maximum sensor value
if (sensorValue > sensorMax) {
sensorMax = sensorValue;
}
// record the minimum sensor value
if (sensorValue < sensorMin) {
sensorMin = sensorValue;
}
}
// signal the end of the calibration period
digitalWrite(signalPin, LOW);
Serial.begin(9600);
}
void loop() {
// read the sensor:
sensorValue = analogRead(sensorOne);
// apply the calibration to the sensor reading
sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 255);
// in case the sensor value is outside the range seen during calibration
sensorValue = constrain(sensorValue, 0, 255);
if(sensorValue <= (sensorMax - 8)){
digitalWrite(13, HIGH);
delay(300);
digitalWrite(13, LOW);
}
Serial.print("sensor value = ");
Serial.println(sensorValue);
delay(5);
}
No comments:
Post a Comment