Pages

Friday 9 May 2014

Practice - Light Based Alarm (Sunset Project)

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
The value that we are going to find at the point of interest is:


Once we know how the photoresistor works and how we must take benefit of it, we can build the circuit that will turn on a LED depending on the ambient light received on the sensor’s side. The following picture shows the connections that have to be done for this part:

Figure 2: Sunset connections [2]
Before implementing the code we have to configure the Xbee modules by following these steps:

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

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