User Tools

Site Tools


arduino:wireless_sensor_networks_2014

Wireless Sensor Networks

Getting Started with Arduino

Set-up and Test

To set up the Arduino to use with the computer an usb cable is attached to the computer while the other end is attached to the Arduino. The usb cable is used as the power source and the cable to send programs. Use the Arduino software to program a simple file called Blink to test and make sure that the components and computer work together. In the process of trying to run Blink, I learned that when running Mac OS X Mavericks a new usb driver was implemented by Apple that breaks communications between DMXIS/D-Pro and any Enttec USB-DMX interface. By Apple implementing this new usb driver it does not allow the Arduino software to communicate with the device to carry out operations. The way to fix this problem is to use a couple of commands in the terminal that allow communication with DXMIS/D-Pro and any Enttec USB-DMX interface. These commands are:

     cd /System/Library/Extensions/IOUSBFamily.kext/Contents/PlugIns 
     sudo mv AppleUSBFTDI.kext AppleUSBFTDI.disabled 
     sudo touch /System/Library/Extensions

After carrying out these commands the computer needs to be restarted. After the computer restarts you need to install the original FTDI Virtual Com Ports drivers, which are found at: http://www.ftdichip.com/Drivers/VCP.htm After the drivers have been installed then start the Arduino software and program the same as always. By doing this the Mac can be used to communicate with the Arduino hardware to carry out the program.

Here is the code for the program Blink:

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 
  This example code is in the public domain.
 */
 
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;
// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Click on this link to watch a video of the Arduino set-up and running of Blink: http://youtu.be/YOifqs5ezC4

PushButtonControl

The next step in working with the Arduino is to make a button that controls the light. I coded the light to go on and off by set milliseconds for the first program, and this time I will control the light by the use of a button. This time the parts that I am using is not just the Arduino board and the usb cable; I will be using 1 Solderless breadboard, 3 pre-cut jumper wire, 1 10k Ohm resistor, and 1 momentary tactile pushbutton. These are shown here:

img_0608.jpg

By connecting them to the appropriate places, writing the code, and uploading the code to the Arduino the light can be controlled by a person pressing the button to turn the light on and off by the button. This is shown in this video: http://youtu.be/srgs0cODatU

// Example 02: Turn on LED while the button is pressed

const int LED = 13;    // the pin for the LED
const int BUTTON = 7;  // the input pin where the
                       // pushbutton is connected
int val = 0;           // val will be used to store the state
                       // of the input pin


void setup() {
  pinMode(LED, OUTPUT);    // tell Anduino LED is an output
  pinMode(BUTTON, INPUT);  // and BUTTON is an input
}

void loop() {
  val = digitalRead(BUTTON);    // read input value and store it
  
  // check whether the input is HIGH (button pressed)
  if (val == HIGH) {
    digitalWrite(LED, HIGH);  // turn LED on
  } else {
    digitalWrite(LED, LOW);
  }
}

The next step in the procedure of setting up the Arduino is to program the Arduino so that when the button is pressed the light will stay on. Having to hold down the button for the light to be on is impractical for people to use. That would mean a person would have to always be holding down the button when using a light, which would take away most of the benefits of using a light. The Arduino for this process is set up the same as it was for the button to be pressed to turn on and off when the button was released. The only part that changes is the code that is written to carry out the operation of pressing the button and the light stays on. Here is the code:

// Example 03: Turn on LED when the button is pressed
// and keep in on after it is released

const int LED = 13;    // the pin for the LED
const int BUTTON = 7;  // the input pin where the
                       // pushbutton is connected
int val = 0;    // val will be used to store the state
                // of the input pin
int old_val = 0; // this variable stores the previous
                 // value of "val"
int state = 0;   // 0 = LED off and 1 = LED  on

void setup() {
  pinMode(LED, OUTPUT);    // tell Arduino LED is an output
  pinMode(BUTTON, INPUT);  // and BUTTON is an output
}

void loop() {
  val = digitalRead(BUTTON);  // read input value and store it
                              // yum, fresh
                              
  // Check if there was a transition
  if ((val == HIGH) && (old_val == LOW)) {
    state = 1 - state;
    delay(10);
  }
  
  old_val = val;   // is now old , let's store it
  
  if(state == 1) {
    digitalWrite(LED, HIGH); // turn on LED
  } else {
    digitalWrite(LED, LOW);
  }
}

Here is the video showing the button being pressed and released and the light remaining on: http://youtu.be/7kzMmHDUBDw

Arduino: A Quick-Start Guide

LedSwitch

Arduino does not always have to take commands from code already entered or a physical button that is attached to the Arduino. This brings up the idea of using the keyboard of the computer to enter information that will carry out certain operations on the Ardunio while the program is running on it. The program that is used to show this the LedSwitch program which allows a user to enter 1 or 2 to turn on and off the light. The program will also recognize an input that does not do anything and tell the user that there is an error. This is different compared to the previous programs because that was not an option. Before I ran the code successfully I learned that the Arduino software does not support BYTE, which is shown below and the solution.

byte_error.jpg

byte_error_fixed.jpg

The program LedSwitch allows the user to input data into what is called the Serial Terminal, which shows output that is told to the user about what is happening on the Arduino. For example, if the user enters 1 the light is turned on, and if 2 is entered the light turns off. Here is a video that shows how the user and the Arduino work together: http://youtu.be/tFB9NwzXM2Q

Here is the code for LedSwitch:

const unsigned int LED_PIN = 13;
const unsigned int BAUD_RATE = 9600;

void setup() {
  pinMode(LED_PIN, OUTPUT);
  Serial.begin(BAUD_RATE);
}

void loop() {
  if (Serial.available() > 0) {
    int command = Serial.read();
    if (command == '1') {
      digitalWrite(LED_PIN, HIGH);
      Serial.println("LED on");
    } else if (command == '2') {
      digitalWrite(LED_PIN, LOW);
      Serial.println("LED off");
    } else {
      Serial.print("Unknown command: ");
      Serial.println(command);
      Serial.println(command, DEC);
      Serial.println(command, HEX);
      Serial.println(command, OCT);
      Serial.println(command, BIN);
      //Serial.println(command, BYTE);
      Serial.write(command); // When BYTE is being used use Serial.write(...);
    }
  }
}

Another way to control the program other than using the terminal given by the Arduino program is to use the terminal. The way to do it is to use a command called screen. This allows the terminal to connect with the Arduino with a couple more steps. The commands are shown below. The name of your device will be different than mine, so make sure that you know the name of the device. The number at the end of the second line is the same as the number you set in your code for Serial.begin(…)

terminal_to_serial.jpg

This shows the terminal being used like in the Arduino software, but after the number is entered it does not show. It just shows the written output that comes from the input.

serial_terminal.jpg

BinaryDie

Version 1

A game that you can play with the Arduino is a rolling dice game. The first step in producing this game is starting out simple by using lights to determine what the roll is being. In the first version of the program the lights mean a certain number on the die. Also, in this version you have to press the reset button on the arduino each time for a roll. Here is a picture of the Arduino set up and one light lit, which means a 2 was rolled.

img_0613.jpg

The parts needed to create this set-up are: 1 breadboard, 3 lights, 3 10k ohms resisters, 3 1k resistors, and 4 wires.

Here is the code for this simple version of BinaryDice:

const unsigned int LED_BIT0 = 12;
const unsigned int LED_BIT1 = 11;
const unsigned int LED_BIT2 = 10;

void setup() {
  pinMode(LED_BIT0, OUTPUT);
  pinMode(LED_BIT1, OUTPUT);
  pinMode(LED_BIT2, OUTPUT);
  
  randomSeed(analogRead(A0));
  long result = random(1,7);
  output_result(result);
}

void loop() {
}

void output_result(const long result) {
  digitalWrite(LED_BIT0, result & B001);
  digitalWrite(LED_BIT1, result & B010);
  digitalWrite(LED_BIT2, result & B100);
}

DiceGame

The DiceGame is one of the first more complex programs to use on the Arduino. The Arduino is set up differently and contains many parts connected to it to allow it to carry out the operations needed. Here is a picture of the Arduino set up:

img_0616.jpg

To build this you need: 1 breadboard, 7 wires, 4 resistors, 5 small wires, 3 lights, and 2 buttons.

The DiceGame uses a more complex code to carry out the operation of guessing the number with the guess button and then checking for the real number. As I was coding I learned that the bounce2 is different than bounce and that is what the Arduino Company offers. To fix this problem the programmer must this changing the variable for his/her program:

Change the constructor from:
	Bounce bouncer = Bounce (inputPin, input)
To:
	Bounce bouncer = Bounce();

And in the setup method this must be done:
	pinMode(inputPin, input);
	DigitialWrite(inputPin, HIGH);
	Bouncer.attach(inputPin)
	Bouncer.interval(input);
This must be done for each bouncer that is created. 

Here is the code for DiceGame:

#include <Bounce2.h>

const unsigned int LED_BIT0 = 12;
const unsigned int LED_BIT1 = 11;
const unsigned int LED_BIT2 = 10;
const unsigned int START_BUTTON_PIN = 5;
const unsigned int GUESS_BUTTON_PIN = 7;
const unsigned int BAUD_RATE = 9600;
Bounce start_button = Bounce();
Bounce guess_button = Bounce();
const unsigned int DEBOUNCE_DELAY = 20;
int guess = 0;

void setup() {
  pinMode(LED_BIT0, OUTPUT);
  pinMode(LED_BIT1, OUTPUT);
  pinMode(LED_BIT2, OUTPUT);
  pinMode(START_BUTTON_PIN, INPUT);
  digitalWrite(START_BUTTON_PIN, HIGH);
  pinMode(GUESS_BUTTON_PIN, INPUT);
  digitalWrite(GUESS_BUTTON_PIN, HIGH);
  randomSeed(analogRead(A0));
  Serial.begin(BAUD_RATE);
  start_button.attach(START_BUTTON_PIN);
  start_button.interval(DEBOUNCE_DELAY);
  guess_button.attach(GUESS_BUTTON_PIN);
  guess_button.interval(DEBOUNCE_DELAY);
  
}

void loop() {
  handle_guess_button();
  handle_start_button();
}

void handle_guess_button() {
  if (guess_button.update()) {
    if (guess_button.read() == HIGH) {
      guess = (guess % 6) + 1;
      output_result(guess);
      Serial.print("Guess: ");
      Serial.println(guess);
    }
  }
}

void handle_start_button() {
  if (start_button.update()) {
    if (start_button.read() == HIGH) {
      const int result = random(1, 7);
      output_result(result);
      Serial.print("Result: ");
      Serial.println(result);
      if (guess > 0) {
        if (result == guess) {
          Serial.println("You win!");
          hooray();
        } else {
          Serial.println("You lose!");
        }
      }
      delay(2000);
      guess = 0;
    }
  }
}

void output_result(const long result) {
  digitalWrite(LED_BIT0, result & B001);
  digitalWrite(LED_BIT1, result & B010);
  digitalWrite(LED_BIT2, result & B100);
}

void hooray() {
  for (int i = 0; i < 3; i++) {
    output_result(7);
    delay(500);
    output_result(0);
    delay(500);
  }
}

Here is a video of how the program prints the guess and results to the serial terminal and how a user would interact with the board: http://youtu.be/UxHOerazicQ

Temperature

The Arduino can also take information that gains through sensors around it and give that information back to the computer. The first program is called temperature where the Arduino finds the temperature around it and then sends it to the computer to be output to the user. Here is a picture of the Arduino set up:

img_0618.jpg

Here is the serial terminal showing the temperatures that are found by the Arduino:

serial_terminal_temperature.jpg

Here is the code for the program temperature:

const unsigned int TEMP_SENSOR_PIN = 0;
const float SUPPLY_VOLTAGE = 5.0;
const unsigned int BAUD_RATE = 9600;

void setup() {
  Serial.begin(BAUD_RATE);
}

void loop() {
  Serial.print(get_temperature());
  Serial.println(" C");
  delay(1000);
}

const float get_temperature() {
  const int sensor_voltage = analogRead(TEMP_SENSOR_PIN);
  const float voltage = sensor_voltage * SUPPLY_VOLTAGE / 1024;
  return (voltage * 1000 - 500) / 100;
}

Twitter Temperature

I created a Twitter account that is to be used to post to when the Arduino is attached, so when it is taking temperatures it can post on the page if it is hot. The link to the Twitter account is here: https://twitter.com/mccarpr0

To do this process you have to use Processing in place of the Arduino IDE to carry out these operations. Here is the link: http://www.processing.org/ You also need to download twitter4j. This allows Processing to use its abilities with Java to connect the Arduino through code to Twitter to post. The link to twitter4j is: http://twitter4j.org/en/index.html After it is downloaded unzip it and find the file twitter4j-core-4.0.1.jar Drag that file into a blank Processing sketch. This will allow the Arduino to communicate with Twitter. That is all you do and the computer makes a file called code. The next step is to give Processing the library from Arduino, being that you need to install them. To do this you need to go to the Arduino website, here is the link: http://playground.arduino.cc/Interfacing/Processing Download the info and follow the instructions on how to link the library to the Arduino library so that Processing can communicate with the Arduino.

There are a few lines in the code that need to be changed as well. Here they are:

arduino = new Arduino(this, Arduino.list()[0], 57600);
Here you are just changing the number in [0] to whatever corresponds with your device. 

import processing.serial.*;
import cc.arduino.*;
println(Arduino.list());
Carry out these commands to figure out which number your device is so that Processing knows where to send the code.

Here is the code that uploads the temperature if it is to hot:

import processing.serial.*;

final float MAX_WORKING_TEMP = 32.0;
final int LINE_FEED = 10;
final int BAUD_RATE = 9600;
final String CONSUMER_KEY = "<OY2AyrFXXMPnPLTwL7ilgW6Cp>";
final String CONSUMER_SECRET = "<fXsabFoWD4CUgToHinozAZestFYUaAmG6SFpnteKU20OXoCyNn>";
final String ACCESS_TOKEN = "<2482754341-5Z0IZGpD0g1hjgXAXElpgalLnrjIm2ZW425dNuy>";
final String ACCESS_TOKEN_SECRET = "<TK8gYmDGWxAldP56LCjQiAhTSKjq1BLh4TDaXTyd9lz9Z>";

Serial arduinoPort;

void setup() {
  println(Serial.list());
  arduinoPort = new Serial(this, Serial.list()[3], BAUD_RATE);
  arduinoPort.bufferUntil(LINE_FEED);
}

void draw() {}

void serialEvent(Serial port) {
  final String arduinoData = port.readStringUntil(LINE_FEED);
  
  if (arduinoData != null) {
    final String[] data = split(trim(arduinoData), ' ');
    if (data.length == 2 && (data[1].equals("C") || data[1].equals("F"))) {
      float temperature = float(data[0]);
      println(temperature);
      int sleepTime = 5 * 60 * 1000;
      if (temperature > MAX_WORKING_TEMP) {
        tweetAlarm();
        sleepTime = 120 * 60 * 1000;
      }
      try {
        Thread.sleep(sleepTime);
      }
      catch (InterruptedException ignoreMe) {}
    }
  }
}

void tweetAlarm() {
  TwitterFactory factory = new TwitterFactory();
  Twitter twitter = factory.getInstance();
  twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
  AccessToken accessToken = new AccessToken(ACCESS_TOKEN, ACCESS_TOKEN_SECRET);
  twitter.setOAuthAccessToken(accessToken);
  try {
    Status status = twitter.updateStatus("Someone, please, take me to the beach!");
    println("succesfully updated status to '" + status.getText() + "'.");
  }
  catch (TwitterException e) {
    e.printStackTrace();
  }
}

Time Server

The Arduino also does can communicate with the Internet like posting to Twitter without using the computer for its internet access. This is done by the use of an Ethernet shield, which connects by going on top of the Arduino. The Ethernet shield also contains an Ethernet port that allows the Arduino to connect to the Internet. This is shown in the picture below.

img_0621.jpg

To test and make sure that the connection when the Arduino will gain the information for the time you can use the terminal. The terminal commands and output are shown below.

timecheck_terminal.jpg

To turn the domain name of time.nist.gov into an IP address the computer needs to access the Domain Name System (DNS). The Arduino’s library does not support DNS, so the computer must find with the use of the terminal. The picture below shows the commands and output.

timeshown_terminal.jpg

It is good that the terminal can communicate with the Internet to get the date and time. The next step is to get the Arduino to communicate with the Internet to gain the information of the date and time. This is done through a program that is written and then displays the information in the serial terminal where a user can see the information and not to have to type anything into the terminal. Here is the code:

#include <SPI.h>
#include <Ethernet.h>

const unsigned int DAYTIME_PORT = 13; 
const unsigned int BAUD_RATE = 9600;
//...
byte mac[] = {0x90, 0xA2, 0xDA, 0x0D, 0x1E, 0xF9};
byte my_ip[] = {152, 97, 100, 99};
byte time_server[] = {216, 229, 0, 179}; // time.nist.gov

EthernetClient client;

void setup() {
  Ethernet.begin(mac, my_ip);
  Serial.begin(BAUD_RATE);
}

void loop() {
  delay(1000);
  Serial.print("Connecting...");
  
  if (!client.connect(time_server, DAYTIME_PORT)) {
    Serial.println("connection failed.");
  } else {
    Serial.println("connected.");
    delay(1000);
    
    while (client.available()) {
      char c = client.read();
      Serial.print(c);
    }
    
    Serial.println("Disconnecting.");
    client.stop();
  }
}

This code allows the Arduino to display the information that it gains in the serial terminal. The output is shown below.

timeserver_serialterminal.jpg

Sending Email

Sending an email from the command line, which allows you to find the address of an SMTP server that can be used. These directions are set for a gmail account and if another service is used the domain names need to be changed accordingly. Here are the commands that need to be entered in a terminal to gain all necessary information:

nslookup
set type=mx
gmail.com
output: which is shown in the image below.
exit

By inputting these commands into the terminal shows a list of all the Google Mail exchange servers (MX) available on your network. This is shown in the image of the terminal below.

mailexchange_terminal.jpg

After finishing these commands the next set of commands to send an email are below in the image.

mailmessage_terminal.jpg

Here is an image of the final product shown in the web browser version of gmail.

picture_of_email_on_web.jpg

Email

The Arduino can be used to send email alert as well. To check and make sure that everything works, I created a program that sends an email. To make this happen it took more than one file to carry out the operation. Here are the three files:

email.h

#ifndef __EMAIL__H_
#define __EMAIL__H_

class Email {
  String _from, _to, _subject, _body;
  
  public:
  
  Email(
    const String& from,
    const String& to,
    const String& subject,
    const String& body
  ) : _from(from), _to(to), _subject(subject), _body(body) {}

  const String& getFrom()    const { return _from; }
  const String& getTo()      const { return _to; }
  const String& getSubject() const { return _subject; }
  const String& getBody()    const { return _body; }
};

#endif

Email.pde

#include <SPI.h>
#include <Ethernet.h>
#include "smtp_service.h"

const unsigned int SMTP_PORT = 25;
const unsigned int BAUD_RATE = 9600;

byte mac[]   = { 0x90, 0xA2, 0xDA, 0x0D, 0x1E, 0xF9 };
byte my_ip[] = { 152, 97, 100, 99 };

 // Insert IP of your SMTP server below!
byte smtp_server[] = { 152, 97, 17, 16 };

SmtpService smtp_service(smtp_server, SMTP_PORT);

void setup() {
  Ethernet.begin(mac, my_ip);
  Serial.begin(BAUD_RATE);
  delay(1000);
  Email email( // <label id="code.ethernet.init_mail"/>
    "mccarpr0@sewanee.edu",
    "prmccar@gmail.com",
    "Yet another subject",
    "Yet another body"
  );
  smtp_service.send_email(email);
}

void loop() {}

smtp_service.h

#ifndef __SMTP_SERVICE__H_
#define __SMTP_SERVICE__H_

#include "email.h"

class SmtpService {
  byte*        _smtp_server;
  unsigned int _port;
 
  void read_response(Client& client) { // <label id="code.ethernet.read_response"/>
    delay(4000);
    while (client.available()) {
      const char c = client.read();
      Serial.print(c);
    }
  }

  void send_line(Client& client, String line) { // <label id="code.ethernet.send_line"/>
    const unsigned int MAX_LINE = 256;
    char buffer[MAX_LINE];
    line.toCharArray(buffer, MAX_LINE);
    Serial.println(buffer);
    client.println(buffer);
    read_response(client);
  }

  public:
  
  SmtpService( // <label id="code.ethernet.smtp_constructor"/>
    byte*              smtp_server,
    const unsigned int port) : _smtp_server(smtp_server), 
                               _port(port) {}
                               
  void send_email(const Email& email) { // <label id="code.ethernet.send_mail"/>
    EthernetClient client;
    client.connect(_smtp_server, _port);
    Serial.print("Connecting...");
  
    if (!client.connected()) {
      Serial.println("connection failed.");
    } else {
      Serial.println("connected.");
      read_response(client);
      send_line(client, String("helo"));
      send_line(
        client,
        String("mail from: <") + email.getFrom() + String(">")
      );
      send_line(
        client,
        String("rcpt to: <") + email.getTo() + String(">")
      );
      send_line(client, String("data"));
      send_line(client, String("from: ") + email.getFrom());
      send_line(client, String("to: ") + email.getTo());
      send_line(client, String("subject: ") + email.getSubject());
      send_line(client, String(""));
      send_line(client, email.getBody());
      send_line(client, String("."));    
      send_line(client, String("quit"));    
      client.println("Disconnecting.");
      client.stop();
    }
  }
};

#endif

To check and make sure that the program is working while carrying out this operation I have certain information be printed out to the serial terminal so I can watch what the program is doing and what steps it is taking. The picture below is the serial terminal after the program has completed running.

serial_terminal_email.jpg

To make sure that we know that the program worked completely I checked online for the email and a picture of the final product is below.

email_shown_on_web.jpg

Infrared Sensor

Infrared Sensor is a way to dectect motion in a room. These sensors are extremely common; the most prominent form is in light switches that turn on when a person walks into a room. I created a smaller version that detected movement in a room. Here is a picture of the Arduino set up.

img_0622.jpg

To check and make sure that the sensor is picking up the information I had the program print out information to the serial terminal. A picture of the serial terminal is below.

serial_terminal_motion.jpg

Here is the code:

const unsigned int PIR_INPUT_PIN = 2;
const unsigned int BAUD_RATE = 9600;

class PassiveInfraredSensor { // <label id="code.ethernet.pir_class"/>
  int _input_pin;

  public:

  PassiveInfraredSensor(const int input_pin) {
    _input_pin = input_pin;
    pinMode(_input_pin, INPUT);
  }
  
  const bool motion_detected() const {
    return digitalRead(_input_pin) == HIGH;
  }
};

PassiveInfraredSensor pir(PIR_INPUT_PIN);

void setup() {
  Serial.begin(BAUD_RATE);
}

void loop() {
  if (pir.motion_detected()) {
    Serial.println("Motion detected");
  } else {
    Serial.println("No motion detected");    
  }
  delay(200);
}

Burglar Alarm

Another common form of using an infrared sensor is to detect if someone is intruding a house. To create a burglary alarm is the same as the motion detector, but the code that is uploaded is more complicated. In the motion detector it only took one file, but in this program it takes four programs. The program also emails alerts if motion is detected. To check and make sure that the program is doing its operations and working I have information print to the serial terminal. Here is a picture of the serial terminal.

serial_terminal_burglar.jpg

Here is the code for the four programs that are needed.

burglar_alarm.h

#ifndef __BURGLAR_ALARM_H__
#define __BURGLAR_ALARM_H__

#include "pir_sensor.h"
#include "smtp_service.h"

class BurglarAlarm {
  PassiveInfraredSensor _pir_sensor;
  SmtpService           _smtp_service;

  void send_alarm() {
    Email email(
		"prmccar@gmail.com",
	    "arduion2014@gmail.com",
	    "Intruder Alert!",
	    "Someone's moving in your living room!"
    );
    _smtp_service.send_email(email);
  }
  
  public:
  
  BurglarAlarm( // <label id="code.ethernet.burglar_alarm_constructor"/>
    const PassiveInfraredSensor& pir_sensor,
    const SmtpService&           smtp_service) :
      _pir_sensor(pir_sensor),
      _smtp_service(smtp_service)
  {
  }
  
  void check() {
    Serial.println("Checking");
    if (_pir_sensor.motion_detected()) {
      Serial.println("Intruder detected!");
      send_alarm();
    }
  }
};

#endif

BurglarAlarm.pde

#include <SPI.h>
#include <Ethernet.h>
#include "burglar_alarm.h"

const unsigned int PIR_INPUT_PIN = 2;
const unsigned int SMTP_PORT = 25;
const unsigned int BAUD_RATE = 9600;

byte mac[]         = { 0x90, 0xA2, 0xDA, 0x0D, 0x1E, 0xF9 };
byte my_ip[]       = { 152, 97, 100, 99 };

// Insert IP of your SMTP server below!
byte smtp_server[] = { 152, 97, 17, 16 };

PassiveInfraredSensor pir_sensor(PIR_INPUT_PIN);
SmtpService           smtp_service(smtp_server, SMTP_PORT);
BurglarAlarm          burglar_alarm(pir_sensor, smtp_service);

void setup() {
  Ethernet.begin(mac, my_ip);
  Serial.begin(BAUD_RATE);
  delay(20 * 1000);
}

void loop() {
  burglar_alarm.check();
  delay(3000);
}

pir_sensor.h

#ifndef __PASSIVE__IR__SENSOR_
#define __PASSIVE__IR__SENSOR_

class PassiveInfraredSensor {
  int _input_pin;

  public:
  PassiveInfraredSensor(const int input_pin) {
    _input_pin = input_pin;
    pinMode(_input_pin, INPUT);
  }

  const bool motion_detected() {
    return digitalRead(_input_pin) == HIGH;
  }

};

#endif

smtp_serivce.h

#ifndef __SMTP_SERVICE__H_
#define __SMTP_SERVICE__H_

#include "email.h"

class SmtpService {
  byte*        _smtp_server;
  unsigned int _port;
 
  void read_response(Client& client) { // <label id="code.ethernet.read_response"/>
    delay(4000);
    while (client.available()) {
      const char c = client.read();
      Serial.print(c);
    }
  }

  void send_line(Client& client, String line) { // <label id="code.ethernet.send_line"/>
    const unsigned int MAX_LINE = 256;
    char buffer[MAX_LINE];
    line.toCharArray(buffer, MAX_LINE);
    Serial.println(buffer);
    client.println(buffer);
    read_response(client);
  }

  public:
  
  SmtpService( // <label id="code.ethernet.smtp_constructor"/>
    byte*              smtp_server,
    const unsigned int port) : _smtp_server(smtp_server), 
                               _port(port) {}
                               
  void send_email(const Email& email) { // <label id="code.ethernet.send_mail"/>
    EthernetClient client;
    client.connect(_smtp_server, _port);
    Serial.print("Connecting...");
  
    if (!client.connected()) {
      Serial.println("connection failed.");
    } else {
      Serial.println("connected.");
      read_response(client);
      send_line(client, String("helo"));
      send_line(
        client,
        String("mail from: <") + email.getFrom() + String(">")
      );
      send_line(
        client,
        String("rcpt to: <") + email.getTo() + String(">")
      );
      send_line(client, String("data"));
      send_line(client, String("from: ") + email.getFrom());
      send_line(client, String("to: ") + email.getTo());
      send_line(client, String("subject: ") + email.getSubject());
      send_line(client, String(""));
      send_line(client, email.getBody());
      send_line(client, String("."));    
      send_line(client, String("quit"));    
      client.println("Disconnecting.");
      client.stop();
    }
  }
};

#endif

Here is a picture of the final outcome.

email_confirmation.jpg

Environmental Monitoring with Arduino

Humidity, Temperature, and Dew Point

The Arduino can also be used to take information from its surrounding, like the Burglar Alarm and Temperature programs. This program does the same as the Temperature, but with more information being found by one sensor and being able to display the information on the web with graphs and not just in the Serial Terminal. This is done by the use of a DHT22 sensor. Which is shown below:

dht22.jpg

The system that the DHT22 sensor used to print its information is outdated and at the present moment I am trying to update the code so that the sensor will work and print its information so that it can be seen on a website. The website that is used to create the graphs to be read on the web is done by Xively. This is different from the website used before which was cosm, which was bought by LogMeIn. I have tested to make sure that my account works, which was done by the use of cell phone as a package tracker. This is simple, but it uses the location devices in the phone to locate the package and its orientation. Here is the web page from from Xively: https://xively.com/develop/AkDh-BLjNLHYXGkm5lpJ

The next step is to have the Arduino be able to communicate with Xively to post and create a graph for the data points to go on. Here is a picture of how the Arduino is set-up:

img_0635.jpg

To test and make sure that the DHT22 sensor was working correctly and picking up correct temperatures I wrote a simple program that printed the temperature and humidity to the serial terminal. Here is the code and the picture of the serial terminal:

#include "DHT.h"
#define DHTPIN 2     
#define DHTTYPE DHT22   
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  dht.begin();
Serial.begin(9600);
}

void loop()
{

float h = dht.readHumidity();
float t = dht.readTemperature();
float fun = dht.convertCtoF(t);

Serial.print("<T:");
Serial.print(fun); 
Serial.print(">");

delay(2000);

Serial.print("<H:");
Serial.print(h); 
Serial.println(">");

delay(2000);
}

temperature_serial.jpg

After I made sure that the sensor was working correctly and I had the Arduino set up correctly I moved forward into having the Arduino send the information to Xively. To do so the Arduino is set up the same as before. The part that changes in the code and it is much more complex than the simple code above. Here is the code:

/*
  Xively sensor client
 
 This sketch connects an analog sensor to Xively (http://www.xively.com)
 using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
 the Adafruit Ethernet shield, either one will work, as long as it's got
 a Wiznet Ethernet module on board.
 
 This example has been updated to use version 2.0 of the Xively.com API. 
 To make it work, create a feed with a datastream, and give it the ID
 sensor1. Or change the code below to match your feed.
 
 
 Circuit:
 * Analog sensor attached to analog in 0
 * Ethernet shield attached to pins 10, 11, 12, 13
 
 created 15 March 2010
 modified 9 Apr 2012
 by Tom Igoe with input from Usman Haque and Joe Saavedra
 
http://arduino.cc/en/Tutorial/XivelyClient
 This code is in the public domain.
 
 */

#include <SPI.h>
#include <Ethernet.h>
#include "DHT.h"

#define DHTPIN 2
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

#define APIKEY         " C4M3OCHDE9IjJdOPbDQ1dogiPsDa3wR617QeP7NqXMleHwV9" // replace your xively api key here
#define FEEDID         1206029305 // replace your feed ID
#define USERAGENT      "WeatherReadings" // user agent is the project name

// assign a MAC address for the ethernet controller.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
// fill in your address here:
byte mac[] = { 
  0x90, 0xA2, 0xDA, 0x0D, 0x1E, 0xF9};

// fill in an available IP address on your network here,
// for manual configuration:
//IPAddress ip(152, 97, 100, 99);
byte ip[] = {152, 97, 100, 99};
// initialize the library instance:
EthernetClient client;

// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(216,52,233,122);      // numeric IP for api.xively.com
char server[] = "api.xively.com";   // name address for xively API

unsigned long lastConnectionTime = 0;          // last time you connected to the server, in milliseconds
boolean lastConnected = false;                 // state of the connection last time through the main loop
const unsigned long postingInterval = 10*1000; //delay between updates to Xively.com

void setup() {
  dht.begin();
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


 // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // DHCP failed, so use a fixed IP address:
    Ethernet.begin(mac, ip);
  }
}

void loop() {
  // read the analog sensor:
  //int sensorReading = analogRead(A0); 
  int sensorReading = dht.readTemperature();  

  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if there's no net connection, but there was one last time
  // through the loop, then stop the client:
  if (!client.connected() && lastConnected) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }

  // if you're not connected, and ten seconds have passed since
  // your last connection, then connect again and send data:
  if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
    sendData(sensorReading);
  }
  // store the state of the connection for next time through
  // the loop:
  lastConnected = client.connected();
}

// this method makes a HTTP connection to the server:
void sendData(int thisData) {
  // if there's a successful connection:
  if (client.connect(server, 80)) {
    Serial.println("connecting...");
    // send the HTTP PUT request:
    client.print("PUT /v2/feeds/");
    client.print(FEEDID);
    client.println(".csv HTTP/1.1");
    client.println("Host: api.xively.com");
    client.print("X-ApiKey: ");
    client.println(APIKEY);
    client.print("User-Agent: ");
    client.println(USERAGENT);
    client.print("Content-Length: ");

    // calculate the length of the sensor reading in bytes:
    // 8 bytes for "sensor1," + number of digits of the data:
    int thisLength = 8 + getLength(thisData);
    client.println(thisLength);

    // last pieces of the HTTP PUT request:
    client.println("Content-Type: text/csv");
    client.println("Connection: close");
    client.println();

    // here's the actual content of the PUT request:
    client.print("sensor1,");
    client.println(thisData);
  
  } 
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
   // note the time that the connection was made or attempted:
  lastConnectionTime = millis();
}


// This method calculates the number of digits in the
// sensor reading.  Since each digit of the ASCII decimal
// representation is a byte, the number of digits equals
// the number of bytes:

int getLength(int someValue) {
  // there's at least one byte:
  int digits = 1;
  // continually divide the value by ten, 
  // adding one to the digit count for each
  // time you divide, until you're at 0:
  int dividend = someValue /10;
  while (dividend > 0) {
    dividend = dividend /10;
    digits++;
  }
  // return the number of digits:
  return digits;
}

Here is the picture of the serial terminal:

xlively_serial_terminal.jpg

The serial terminal is used in this case is a way to help debugging. It allows me to see if everything went correctly or there was a problem. Here is the link to the Xively page that shows the graphs: https://xively.com/develop/G3JsNRWzemUgrKbDGJNr

Building Wireless Sensor Networks

Chatting

Using the XBee radios a user is able to communicate with them between serial terminals on two different computers. To do this program you need to XBee radios, a usb to micro-usb cables, and two computers. These computers can be running mac or windows it does not matter. After connecting one XBee radio to the computer the XBee needs to formatted to work correctly in the network. This is done by the program called X-CTU, which will format one Xbee radio into a coordinator and the other into a router. The software can be downloaded here: http://www.digi.com/support/productdetail?pid=3352&osvid=57&type=utilities By them being different it allows each to understand how the network work among them. The next step after making them be formatted correctly is to input the correct information into them using a serial terminal. The serial terminal in this case is not given like it was with the Arduino software. This time the serial terminal needs to be a downloaded program or use the screen option in the terminal. I decided to download the serial terminal from the internet. I used CoolTerm for the mac and Tera Term for the pc. Here is the link for CoolTerm: http://freeware.the-meiers.org and here is the link for Tera Term: http://en.sourceforge.jp/projects/ttssh2/releases/ After the XBee's are formatted and connected to the computer a user uses the serial terminal program to set all necessary information on the XBee for communication, but for the serial terminal to work correctly there are certain settings that need to be set. Here they are:

Baud: 9600
Data: 8 bit
Parity: None
Stop bits: 1
Flow Control: None
Line Feed: CR+LF or Auto Line Feed (In the two serial terminals that I used the option is CR+LF)
Local echo: ON

After these settings are set a user uses “at” commands, which is what the XBee radio uses to format itself. By using the “at” commands the XBee radios will be able to communicate with each other. The commands used are below:

For Coordinator:
+++
atid 2001
atdh 0013A200
atdl 40795F4E
atid
atdh
atwr

This will change for the router as well:

For Router:
atid 2001
atdh 0013A200
atdl 40795F42
atif
atdh
atwr

atid is the PAN ID, atdh is the destination address high, and atdl is the destination address low. Then I print them back out so that I know what I entered is correct. The last command atwr saves the information to the XBee. After the information is set into the XBee a user can type anything when the radios are in transparent mode. The two ways to get the radios in transparent mode are to wait 10 seconds after done typing or type the at command atcn. By doing that any text that is inputed on one computer's serial terminal will also show up the other computer's serial terminal. Here are the two pictures of one computer being on a windows and the other a mac. When the text was typed in the windows computer it appeared on the mac.

chat_serial_terminal.jpg

chat_serial_terminal_mac.jpg

DoorBell

The XBee can also be attached to the Arduino to use the coding capabilities to carry out more operations by the XBees. In this program both XBees are attached to the Arduino, which are then connected to the computer. Here are images of both:

img_0641.jpg

img_0642.jpg

The first picture shows the XBee attached to the Arduino through the use of a breadboard. This set-up also contains a push button, which allows the user to press to hear a buzz noise come the from other. The other Arduino contains a breadboard as well with a XBee attached. This set-up contains a buzzer which produces a noise when when the button is pressed. Here is the code for each set-up:

DoorBell Basic Button

/*
****** Doorbell Basic BUTTON ********
requires pre-paired XBee Radios
and the BELL program on the reciveving end
by Rob Faludi http://faludi.com
*/

#define VERSION "1.00a0"

int BUTTON = 2;

void setup() {
  pinMode(BUTTON, INPUT);
  Serial.begin(9600);
}

void loop() {
  // send a capital D over the serial port if the button is pressed
  if (digitalRead(BUTTON) == HIGH) {
    Serial.print('D');
    delay(10); // prevents overwhelming the serial port
  }
}

DoorBell Basic Bell

/*
********* Doorbell Basic Bell **********
requires pre-paired XBee Radios
and the BUTTON program on the recieving end
by Rob Faludi http://faludi.com
*/

#define VERSION = "1.00a0"

int BELL = 5;

void setup() {
  pinMode(BELL, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  // look for a capital D over the serial port and ring the bell if found
  if (Serial.available() > 0) {
    if (Serial.read() == 'D') {
      // ring the bell briefly
      digitalWrite(BELL, HIGH);
      delay(10);
      digitalWrite(BELL, LOW);
    }
  }
}

To remember that all steps that were done in the chatting program also need to be done in this program so that the XBee's can communicate with each other.

XBee Temperature

The XBee radio can also be used to transmit information that is gained from the environment around it. This cane be done by the use of the XBee being attached to a breadboard and being powered by a battery. This is shown below:

img_0650.jpg

This is the XBee that will be put somewhere to take temperature readings. The other XBee will be connected to the computer to take commands and code written by the user and transport the information to the other XBee. Then the XBee that is one its own will send the information that it gains from what the other XBee told it to do back and then the XBee will upload that information to the computer so that people can read and understand the information that the XBee found. The code in the book is old and the parts that they use to create the temperature sensor are not used anymore. To do a more updated version I found a website that gives new code and a picture of how the XBee is connected to the breadboard and powered by a battery: http://www.faludi.com/bwsn/tmp36-instructions-simple-sensor-network/

As I tried to work with the code and the XBee for some reason the program would never work. I believe that the reason that the XBee would not work is because the board that connects the XBee to the breadboard does not have good connection. Here is an image of that board:

xbee_connection_board.jpg

The pins from the XBee go into the outside holes while another set of pins go into the closer holes, which then connect to the breadboard. I checked to make sure that there was power going throughout the system and it did, but the XBee still did not seem to receive power. The XBee Radio does not have a light or any indicator on it that tells the user if it is getting power and is turned on. This is much different from the Arduino where there is a light that tells you if there is power and if it is receiving and sending information. The XBee radio is a much more complicated version of a wireless sensor network compared to an Arduino wireless sensor network.

5/05/2014: WL 124 key checked out to Peter McCarthy

arduino/wireless_sensor_networks_2014.txt · Last modified: 2014/06/17 13:50 by mccarpr0