Archives For June 2013

xMail

I will not print it until I have tested it for some weeks. I added access to some D and A pins so I can reuse the PCB or test new functionality on 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

image

App created with Google Cloud Messaging support.