Archives For ethernet shield

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.