Archives For arduino

Continuing with the description of the wireless mailbox sensor, I was missing the information on the coordinator: an arduino mega with an ethernet shield and an Xbee attached.

Originally I had two Regular Xbee Series 1. I chose series 1 because of the simplicity for non complex projects. I read in many sources they are easier to handle when starting out with Xbee and also they support multi-point communication. Weather to use a physical antenna or on-chip antenna I think doesn’t matter much. The problem I had was that the signal from the regular Xbees didn’t reach from my mailbox (which is downstairs outside my apartment) to the location of the coordinator inside my apartment. I finally had to buy a Xbee Series 1 Pro with a wire antenna. Pro and Regular Xbees are compatible with only few minor changes, more importantly the Pro version consumes more power given the larger reception range. The coordinator runs on a connected power source so I didn’t really mind this increase in power consumption.

The coordinator is always listening for upcoming Xbee transmissions, in case it receives something, it will check the source sensor the transmission is coming from and the message (mailbox opened, new letter received, etc). After “decoding” the message it will connect via the Ethernet Shield to a php script I have in my hosting that will handle the push notification using Google Cloud Messaging (GCM) for Android. I will write about the use of GCM and the android app in a separate post.

Here is the full code for the arduino handling the reception of messages:

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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <Xbee.h>
#include <Ilos.h>
 
// Xbee related stuff
XBee         xbee       = XBee();
XBeeResponse response   = XBeeResponse();
Rx16Response rx16       = Rx16Response();
Rx64Response rx64       = Rx64Response();
 
// Ethernet related stuff
boolean     lastConnected   = false;
byte        mac[]           = { 0x00, 0xAA, 0xBB, 0xCC, 0xDA, 0x02 };
IPAddress   ip(192,168,1,234);
char        server[]        = "www.adrova.com";
EthernetClient client;
 
// Input and outputs
int statusLED = 13;
 
void setup(){
 
    // Setup pin modes
    pinMode(statusLED, OUTPUT);
 
    // Setup serial interfaces for debugging
    Serial.begin(9600);
 
    // Setup serial interface for Xbee
    Serial1.begin(9600);
    xbee.setSerial(Serial1);
 
    // Start the Ethernet connection:
    if (Ethernet.begin(mac) == 0) {
        Serial.println("Failed to configure Ethernet using DHCP");
        Ethernet.begin(mac, ip);
    }
 
    // Give the Ethernet shield a second to initialize:
    delay(1000);
 
}
 
void loop(){
 
    // Consume data if available from the Ethernet client
    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();
    }
 
    xbee.readPacket();
 
    if (xbee.getResponse().isAvailable()) {
        // We've got something to read
 
        if (xbee.getResponse().getApiId() == RX_16_RESPONSE ) {
            // We've got a rx packet
 
            int sourceAddress;
 
            xbee.getResponse().getRx16Response(rx16);
 
            uint8_t option = rx16.getOption();
            sourceAddress  = rx16.getRemoteAddress16();
 
            //uint8_t analogHigh = rx16.getData(0);
            //uint8_t analogLow = rx16.getData(1);
 
            uint8_t message = rx16.getData(0);
 
            //int value = analogLow + (analogHigh * 256);
 
            Serial.println(message);
 
            // Flash led to indicate success
            flashLed(statusLED, 5, 50);
 
            if(sourceAddress == XMAIL_ADDRESS){
                switch(message){
                    case XMAIL_MSG_RESET_CODE:
                        sendNotification(XMAIL_NAME, XMAIL_MSG_RESET); break;
                    case XMAIL_MSG_NEW_LETTER_CODE:
                        sendNotification(XMAIL_NAME, XMAIL_MSG_NEW_LETTER); break;
                }
            } else if (sourceAddress == XWASH_ADDRESS){
                // TODO for the next sensor
            }
 
        } else {
            // Not something we were expecting
            flashLed(statusLED, 2, 1000);
        }
 
    } else if (xbee.getResponse().isError()) {
 
        //nss.print("Error reading packet.  Error code: ");
        //nss.println(xbee.getResponse().getErrorCode());
        flashLed(statusLED, 2, 1000);
    }
 
    // Store the state of the connection for next time through
    // the loop:
    lastConnected = client.connected();
 
}
 
// Function that will flash a led n times with a delay of wait between each flash
void flashLed(int pin, int times, int wait) {
 
    for (int i = 0; i < times; i++) {
        digitalWrite(pin, HIGH);
        delay(wait);
        digitalWrite(pin, LOW);
 
        if (i + 1 < times) {
            delay(wait);
        }
    }
}
 
// Function that will connect to the GCM service and send the notification
void sendNotification(const char* sensor, const char* message) {
 
//    Serial.println(sensor);
//    Serial.println(message);
//    Serial.println();
 
    if (client.connect(server, 80)) {
        // If there's a successful connection:
        Serial.println("Connecting...");
 
        char getURL[] = "GET /normandy/server/send.php?secret=XXXXXXXXXX&sensor=";
        strcat(getURL, sensor);
        strcat(getURL, "&message=");
        strcat(getURL, message);
        strcat(getURL, " HTTP/1.1");
 
        // Send the HTTP PUT request:
        client.println(getURL);
        client.println("Host: www.adrova.com");
        client.println("User-Agent: arduino-ethernet");
        client.println("Connection: close");
        client.println();
    } else {
        // if you couldn't make a connection:
        Serial.println("Connection failed.");
        Serial.println("Disconnecting.");
        client.stop();
    }
}

As you can see, I have the function sendNotification defined which loads the php script with the sensor and messaged passed in the query string. I don’t really need to handle the result (You could potentially handle errors or check if the server is down here to retry to send the notification later). I added a secret variable for “authorization” purposes since a notification is sent every time the page is loaded. The code itself is self-explanatory, just loading the website and that’s it.

Wireless mailbox sensor

June 27, 2013 — 2 Comments

I normally check my mailbox (snail mail) every day before entering my apartment. One day I thought “Wouldn’t it be nice if I know if I have new letters without having to check the mailbox?” That’s how I came up with the idea to install a wireless sensor that will notify me when somebody leaves something from me in the mailbox.

The idea itself it’s nothing new and it’s very common among Arduino enthusiasts. What I think is unique is the combination of tools I used (or at least I couldn’t find a similar solution to the setup I have).

In this posts I will just describe the wireless mailbox sensor. It’s basically one home-made Arduino (you can see this post on how you can build your own one) with an Xbee Series 1 transmitter and a couple of sensors: A DFRobot DFR0028 Tilt Sensor and a Snap-Action switch (similar to this one).

The sensors

This is the planned sensor setup

This is the planned sensor setup

The tilt sensor will detect when a new letter arrives and it’s placed in the small cover of the mailbox. It will trigger when the mailbox lid is lifted. Originally I thought of having a light sensor in there, but it was just easier to have an on-off sensor because I only need to recognize these two states. The snap-action switch will detect when I open the mailbox with the key (to reset the detection) and it’s placed right where the lock mechanism is resting. The snap-action switch is normally closed and when I use the key and rotate the lock mechanism, the switch will open, thus triggering the sensor. Every time a sensor is triggered, the Arduino will send a message to the coordinator (i.e. another Arduino I have in my apartment also with an Xbee attached).

The power source

I started my prototype based on this post from the adafruit forum. It also provided me with a solution to run the sensor on batteries. Originally I had no idea how to deal with that. The simple setup should not consume a lot of power, but the Xbee could, so the idea from this guy was to cut the Xbee power when it’s not sending anything, and only power it up when you need to send something (BTW, that implies one-way communication, which I don’t like since I want to be able to reset the mailbox not only with the key, but also remotely, but I will try to achieve this on a further version of the sensor). Another tip from that same post to save some power, was to put the processor to sleep when is not doing anything. Basically the atmega328 has the capability to be put to sleep, and be woken up by interrupts in two pins (2 and 3). More information about this here. This way, the Arduino will wake up every time a sensor triggers, the it will give some power to the Xbee and send the corresponding message, then cut the power again to the Xbee and finally it the will go back to sleep.

The Xbee communication

Because I’m thinking this sensor will be just a component of a bigger mesh of sensors, I wanted to avoid using broadcast messages and direct my messages to a particular Xbee (so called the coordinator). I’m using the xbee-arduino library for doing this. For using API mode (i.e. this library) you will need to configure manually the Xbees on your mesh. In windows you can use the X-CTU application Digi provides to configure and update Xbee firmware. For mac, you can use moltosenso iron which is free and provides the basic functionalities to configure your Xbees. I use DFRobot Basic Breakout to program my microcontrollers, and it is also useful to configure the Xbee. I also use the Sparkfun’s Xbee Explorer Regulated to manage the 5V to 3.3 Voltage conversion is needed to power the Xbees. It’s also handy to plug some headers into the board that fit for example a breadboard. If you want to configure the Xbee using this two boards, you just need to connect the VCC of the Basic Breakout to 5V of the Explorer, GND to GND, RX of the Breakout to DOUT (CAREFUL: RX in the DFROBOT Breakout is actually TX), and TX to DIN. Doing this, you would normally get access to the Xbee configuration.

Once you have access to the Xbee on your computer, you need to set up the following parameters in your Xbee (this information is for Series 1 which I use):

For the coordinator:

PAN: 965  -> This is you network id, the number you use here should be use in all Xbees in the network for communicate with each other.
MY: 1000 -> This will be the 16-bit address of this particular Xbee.
CH: C -> This is the newtork channel, this value will need also to be the same for all Xbees in the network.
CE: 1 -> This indicates this Xbee is a Coordinator.
AP: 2 -> This indicates this Xbee will use API mode.

For all other Xbees the configuration would be the same except for:

MY: 1001 -> This will be the 16-bit address of this particular Xbee.
CE: 0 -> This indicates this Xbee is NOT a Coordinator.

More information about this configuration and also configuration for Xbees Series 2 here: XBeeConfiguration.

The software

You can see the code for the mailbox sensor here:

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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <XBee.h>
#include <avr/sleep.h>
 
// Constant definitions
const uint8_t XMAIL_MSG_NEW_LETTER_CODE = 0;
const uint8_t XMAIL_MSG_RESET_CODE = 1;
 
// Pin definitions
int ledPin            = 10;
int xBeeTransistorPin = 13; // xBee Powered when HIGH
int newLetterPin      = 2;  // Mailbox opened (letter introduced)
int mailboxOpenedPin  = 3;  // Mailbox opened (with key)
 
// Control variables
boolean flag_error;
boolean flag_start;
 
// Store the message to send
uint8_t message[] = {0};
 
// Set up XBee configuration
XBee xbee = XBee();
 
void setup(){
 
    // Set up pin modes
    pinMode(newLetterPin, INPUT);
    pinMode(mailboxOpenedPin, INPUT);
    pinMode(xBeeTransistorPin, OUTPUT);
    pinMode(ledPin, OUTPUT);
 
    // Set up Serial XBee
    Serial.begin(9600);
    xbee.setSerial(Serial);
 
    // Set up initial values
    turnXBeeOff();
    digitalWrite(ledPin, LOW);
    flag_error = false;
    flag_start = true;
}
 
void loop() {
 
    // If the arduino was just powered up, do nothing
    if(flag_start){
        flag_start = false;
        SleepNow();
    }
 
    //payload[0] = message >> 8 & 0xff;
    //payload[1] = message & 0xff;
 
    // 16-bit addressing: Enter address of remote XBee, typically the coordinator
    Tx16Request tx = Tx16Request(0x1000, message, sizeof(message));
    // Prepare a response
    TxStatusResponse txStatus = TxStatusResponse();
    // Turn on XBee power
    turnXBeeOn();
    // Give it some time
    delay(2000);
    // Send signal...
    xbee.send(tx);
 
    // ... and wait for a response
    if (xbee.readPacket(3000)) {
        // Should be a znet tx status
        if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) {
 
            xbee.getResponse().getZBTxStatusResponse(txStatus);
            // get the delivery status, the fifth byte
 
            if (txStatus.isSuccess()) {
                // success.  time to celebrate
                flag_error = false;
            } else {
                // the remote XBee did not receive our packet. is it powered on?
                flag_error = true;
            }
        } else {
            // Not something we were expecting
        }
    } else if (xbee.getResponse().isError()) {
        //nss.print("Error reading packet.  Error code: ");
        //nss.println(xbee.getResponse().getErrorCode());
        flag_error = true;
    } else {
        // local XBee did not provide a timely TX Status Response.  
        // Radio is not configured properly or connected
        flag_error = true;
    }
 
    // Cut off power to XBee
    delay(3000);
    turnXBeeOff();
    delay(2000);
 
    // TODO Retry 3 times
    if(!flag_error){
 
        // Back to sleep
        SleepNow();
    }
 
}
 
void turnXBeeOn() {
    digitalWrite(xBeeTransistorPin, HIGH);
}
 
void turnXBeeOff() {
    digitalWrite(xBeeTransistorPin, LOW);
}
 
// Interrupt functions which will save from where the wake up was triggered
void aNewLetterArrived()
{
    sleep_disable();     // first thing after waking from sleep: disable sleep...
    detachInterrupt(0);  // disables both interrupt {0,1} so the wakeUpNow{0,1} code
    detachInterrupt(1);
    message[0] = XMAIL_MSG_NEW_LETTER_CODE;
}
 
void mailboxWasOpened()
{
    sleep_disable();     // first thing after waking from sleep: disable sleep...
    detachInterrupt(0);  // disables both interrupt {0,1} so the wakeUpNow{0,1} code
    detachInterrupt(1);
    message[0] = XMAIL_MSG_RESET_CODE;
}
 
// Function to put the Arduino to sleep
void SleepNow()
{
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
 
    sleep_enable();
 
    attachInterrupt(0, aNewLetterArrived, LOW);
    attachInterrupt(1, mailboxWasOpened, LOW);
 
    sleep_mode();
}
 
// Function to flash the status led
void flashLed(int times, int wait) {
 
    for (int i = 0; i < times; i++) {
        digitalWrite(ledPin, HIGH);
        delay(wait);
        digitalWrite(ledPin, LOW);
        delay(wait);
    }
}

I had some issues sending two bytes instead of only one. So at the end I opted for just sending a byte (uint8_t) of information with the Xbee, anyways this would allow for 256 of different encoded messages (I only needed two). I still have yet to deal with errors, so far I assume no communication problem occurred.

So far everything works fine. I’m trying to make a custom PCB to reduce some space… I’ll upload the schematics once I have them.

It's a bit hairy, but the next step after some weeks of testing will be to print a PCB

It’s a bit hairy, but the next step after some weeks of testing will be to print a PCB

Schematic

Arduino on a Breadboard

April 21, 2013 — 6 Comments

There are plenty of resources where you can get started with Arduino. A nice place to start would be the Arduino Getting Started page. There is also this free small guidebook one of my professors made last year. It is quite simple, but it’s a good approach when you know nothing about Arduino. I do have some experience with it and what I wanted to do is now try to make my own “arduino” by buying a atmega328 and the corresponding components to make it work. The benefits of doing this is that you can change components for specific requirements you might require for some applications, for example a lower power consumption or some size constrains.  At the end, building your own arduino gives you more flexibility on what you can do with it, of course this comes with an added complexity to the project.

I’m proud to say majored in electronics during my studies. Unfortunately, I never got to do hardware stuff in a professional way, and right know I more focused into software development. Is still remember a thing or two of my circuits lectures so this kinda helped me making the next step of building my own circuits. I still think that making these small projects does not require a lot of experience with electronics, but it sure helps and speeds up the process.

I mainly used two resources for making an Arduino from scratch: arduino.cc and this site from jameco.com. Both sites contain almost the same information with minor differences. I live in Germany, and most of the components I ordered them from lipoly.de and watterott.com. Good thing about both sites is that they are available in english as well. Building your own Arduino is not cheaper than buying it  from a seller. Hardware components are expensive when you buy only a few of them. When it’s your first project you need to invest some money in resistors, capacitors, and all this things you need to get you started which you will likely buy in packages (there no sense in buying 2 or 3 resistors). Once you have a full set of these basic elements, in future projects you will only have to focus on buying the special components (xbees, sensors, actuators, etc). I think the price of a custom made Arduino is around the same as a standard one after that initial investment.

I used an atmega328 with an Arduino Uno bootloader already burned in it. There are instructions on how to burn it yourself in the arduino.cc page mentioned before. You will also need a usb to serial for communication with the Arduino. I bought the FTDI Basic Breakout 3.3/5V which is handy because it comes with a jumper switch to change from 3.3V logic to 5V. Careful though: in this breakout board the TX/RX pins are wrongly labeled and I spent some time figuring this out. RX is actually TX and viceversa. Don’t forget to connect the DTR line of the serial board to the reset pin from the atmega328 when you program it.

Arduino on a breadboard

This is my final version of an arduino on a breadboard

In the next post I’ll write about my first experience building a sensor for mail detection and communicating via xbee.