Description
This time we are going to show you how we can interact with ambient light through sensors. As usually, we will propose you two main parts for this lab exercise: the first one shows how we implemented the WSN MOOC proposal, while the second part goes beyond that, so we will also show you how to activate a LED and a buzzer on the sensor side in order to prevent thefts.
The stuff we are using this time is showed below [1]:
- Breadboard (two better than one).
- Jumper wire Arduino UNO (and USB-A-to-B cable).
- 2 XBee.
- 2 XBee explorer (and at least one USB-to-mini-USB cable).
- Four LEDs (white, red, blue, green).
- A buzzer.
- A photoresistor (or Light Dependant Resistance).
- 10Kohm in the dark, 1Kohm in bright light 20Kohm resistor .
Remember you can download the code in the code section.
Part 1
The idea is to implement a voltage divider with a fixed resistance and a variable one in order to take the value between them. This will allow us to detect the voltage variations, which will let knowing the state of the ambient light. When the photoresistor detects bright light, its resistance value decreases, so the output voltage decreases. The opposite behavior happens when it detects a dark environment.
The following schema shows you the logical circuit that we are implementing:
Figure 1: Voltage divider |
1. The processing part must implement coordinator tasks, so we set a PAN ID (BFB7 in our case):
Figure 3: Coordinator node |
2. The sensor side is the router part, so we set the same PAN ID as for the coordinator and we enable the “JV Channel Verification” field:
Figure 4: Router Node 1 |
3. We also configure the I/O settings that allow us to convert the received values from the circuit into digital characters for transmission: ADC (Analog-Digital Conversion) option.
Figure 5: Router Node 2 |
4. The last step consists in changing the IO Sampling Rate into 255 ms (0xFF) in order to avoid some communication troubles:
Figure 6: Router Node 3 |
Circuit Photography
Processing Side Code (Part 1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | int LED_NIGHT = 10; int LED_SUNSET = 11; int LED_DAY = 12; int debugLED = 13; int analogValue = 0; // Upper boundaries int DAYup = 750; int SUNSETup = 950; void setup() { pinMode(LED_DAY,OUTPUT); pinMode(LED_SUNSET,OUTPUT); pinMode(LED_NIGHT,OUTPUT); pinMode(debugLED,OUTPUT); Serial.begin(9600); } void loop() { digitalWrite(LED_NIGHT, LOW); digitalWrite(LED_SUNSET, LOW); digitalWrite(LED_DAY, LOW); // make sure everything we need is in the buffer if (Serial.available() >= 21) { // look for the start byte if (Serial.read() == 0x7E) { //blink debug LED to indicate when data is received digitalWrite(debugLED, HIGH); delay(10); digitalWrite(debugLED, LOW); // read the variables that we're not using out of the buffer for (int i = 0; i<18; i++) { byte discard = Serial.read(); } int analogHigh = Serial.read(); int analogLow = Serial.read(); analogValue = analogLow + (analogHigh * 256); Serial.print("Analog value "); Serial.println(analogValue); } } // DAY TIME if (analogValue > 0 && analogValue <= DAYup) { digitalWrite(LED_DAY, HIGH); delay(10); digitalWrite(LED_DAY, LOW); } // SUNSET TIME if (analogValue > DAYup && analogValue <= SUNSETup) { digitalWrite(LED_SUNSET, HIGH); delay(10); digitalWrite(LED_SUNSET, LOW); } // NIGHT TIME if (analogValue > SUNSETup && analogValue <= 1023) { digitalWrite(LED_NIGHT, HIGH); delay(10); digitalWrite(LED_NIGHT, LOW); } } |
Part 2
To extend the practical exercise seen on this entry we have deployed a buzzer that makes sounds when the state of the sensor changes. It could be useful for detecting movement (detecting a shadow) and then displaying the alarm to frighten thieves.
So, the behavior of our circuit is going to be the same as shown before, but we are adding communication between the coordinator and the router, in order to transmit a command to activate the port D1 at the sensor side, that will make the buzzer sound.
For this purpose, we have to use the "setRemoteState" function, which sends information through the serial channel with the value (as input of the function) that enables or disables the specific port with we are dealing to.
In our case, we have implemented that the Programmer side checks every 10 seconds if the status of the photoreceptor has changed from day to night. If yes, we call the "setRemoteState" function to send "05". Otherwise, we send "04".
More information about XBee 802.15.4 digital input/output passing can be found on the following link: http://www.digi.com/support/kbase/kbaseresultdetl?id=2188
So, the behavior of our circuit is going to be the same as shown before, but we are adding communication between the coordinator and the router, in order to transmit a command to activate the port D1 at the sensor side, that will make the buzzer sound.
For this purpose, we have to use the "setRemoteState" function, which sends information through the serial channel with the value (as input of the function) that enables or disables the specific port with we are dealing to.
In our case, we have implemented that the Programmer side checks every 10 seconds if the status of the photoreceptor has changed from day to night. If yes, we call the "setRemoteState" function to send "05". Otherwise, we send "04".
More information about XBee 802.15.4 digital input/output passing can be found on the following link: http://www.digi.com/support/kbase/kbaseresultdetl?id=2188
Circuit Assembly
Circuit Photographies
Processing Side Code (Part 2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | int LED_NIGHT = 10; int LED_SUNSET = 11; int LED_DAY = 12; int debugLED = 13; int analogValue = 0; // Upper boundaries int DAYup = 750; int SUNSETup = 950; int remoteIndicator = false; // keeps track of the desired remote on/off state int lastRemoteIndicator = false; // record of prior remote state unsigned long lastSent = 0; // records last time the remote was re-set to keep it in sync void setup() { pinMode(LED_DAY,OUTPUT); pinMode(LED_SUNSET,OUTPUT); pinMode(LED_NIGHT,OUTPUT); pinMode(debugLED,OUTPUT); Serial.begin(9600); } void loop() { digitalWrite(LED_NIGHT, LOW); digitalWrite(LED_SUNSET, LOW); digitalWrite(LED_DAY, LOW); // make sure everything we need is in the buffer if (Serial.available() >= 23) { // look for the start byte if (Serial.read() == 0x7E) { //blink debug LED to indicate when data is received digitalWrite(debugLED, HIGH); delay(10); digitalWrite(debugLED, LOW); // read the variables that we're not using out of the buffer for (int i = 0; i<20; i++) { byte discard = Serial.read(); } int analogHigh = Serial.read(); int analogLow = Serial.read(); analogValue = analogLow + (analogHigh * 256); Serial.print("Analog value "); Serial.println(analogValue); } } // DAY TIME if (analogValue > 0 && analogValue <= DAYup) { digitalWrite(LED_DAY, HIGH); delay(10); digitalWrite(LED_DAY, LOW); remoteIndicator = false; } // SUNSET TIME if (analogValue > DAYup && analogValue <= SUNSETup) { digitalWrite(LED_SUNSET, HIGH); delay(10); digitalWrite(LED_SUNSET, LOW); remoteIndicator = false; } // NIGHT TIME if (analogValue > SUNSETup && analogValue <= 1023) { digitalWrite(LED_NIGHT, HIGH); delay(10); digitalWrite(LED_NIGHT, LOW); remoteIndicator = true; } // set the indicator immediately when there's a state change if (remoteIndicator != lastRemoteIndicator) { if (remoteIndicator==false) setRemoteState(0x4); if (remoteIndicator==true) setRemoteState(0x5); lastRemoteIndicator = remoteIndicator; } // re-set the indicator occasionally in case it's out of sync if (millis() - lastSent > 10000 ) { if (remoteIndicator==false) setRemoteState(0x4); if (remoteIndicator==true) setRemoteState(0x5); lastSent = millis(); } } void setRemoteState(int value) { Serial.write(0x7e);//Start byte Serial.write((byte)0x0);//Length Serial.write(0x10);//Length High Serial.write(0x17);//AT Command Request Serial.write((byte)0x0);//Frame ID Serial.write((byte)0x0);//Serial Number of Destination Serial.write((byte)0x0); Serial.write((byte)0x0); Serial.write((byte)0x0); Serial.write((byte)0x0); Serial.write((byte)0x0); Serial.write(0xFF); Serial.write(0xFF);//End of Serial Number of Destinition // 16 bit of recipient or 0xFFFE if unknown Serial.write(0xFF); Serial.write(0xFE); Serial.write(0x02);//Apply changes immediately //Command name in ASCII characters Serial.write('D'); Serial.write('1'); //command data in as many bytes after length bytes Serial.write(value); //checksum is all bytes after length bytes long sum = 0x17 + 0xFF+ 0xFF + 0xFF + 0xFE + 0x02 + 'D' + '1' + value; Serial.write (0xFF - ( sum & 0xFF) ); delay(10); // avoiding overwhelming } |
Buzzer Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | // Pin where the buzzer is connected const int BELL = 5; const int PIN_STATE = 2; // Light detector state int DETstate = 0; // Tone variables float sinVal; int toneVal; void setup() { pinMode(BELL, OUTPUT); Serial.begin(9600); } void loop() { DETstate = digitalRead(PIN_STATE); if (DETstate == HIGH){ for (int x=0; x<180; x++) { // convert degrees to radians then obtain sin value sinVal = (sin(x*(3.1412/180))); // generate a frequency from the sin value toneVal = 2000+(int(sinVal*1000)); tone(BELL, toneVal); } delay(10); noTone(BELL); //analogWrite(BELL, 0); } } |
Video
References
[1]
Material list retrieved from “WSN course guide”, chapter 11 (Sunset Sensor), made
by Jaume Barceló and Luis Sanabria
[2] Image
retrieved from “WSN course guide”, chapter 11 (Sunset Sensor), made by Jaume
Barceló and Luis Sanabria
No comments:
Post a Comment