|
| 1 | +/** |
| 2 | + * ENC28J60 Ethershield DHCP and Pachube demo - Pachube RGB |
| 3 | + * This reads a number of Pachube datastreams and |
| 4 | + * converts the output to colours on a RGB LED. |
| 5 | + * The original demo uses a Pachube app with 3 rotary controls |
| 6 | + * that select the value for each of the Red, Green and Blue colours. |
| 7 | + * The example uses DHCP to determin the local IP address, gateway, |
| 8 | + * and DNS server. |
| 9 | + * |
| 10 | + * As a debugging aid, the RGB LED initialy glows red. |
| 11 | + * Once the ENC28J60 has been initialised it changes to Orange |
| 12 | + * When the IP address has been allocated it changes to Green. |
| 13 | + * It then changes to the set colour once the values are being |
| 14 | + * read from the Pachube application. |
| 15 | + * |
| 16 | + * See http://blog.thiseldo.co.uk/?p=574 for details on how to set this up with Pachube dashboard |
| 17 | + * |
| 18 | + * Written By and (c) Andrew D Lindsay, May 2011 |
| 19 | + * http://blog.thiseldo.co.uk |
| 20 | + * Feel free to use this code, modify and redistribute. |
| 21 | + * |
| 22 | + */ |
| 23 | + |
| 24 | +// If using a Nanode (www.nanode.eu) instead of Arduino and ENC28J60 EtherShield or JeeNode and EtherCard then |
| 25 | +// use this define: |
| 26 | +#define NANODE |
| 27 | + |
| 28 | +#include <EtherCard.h> |
| 29 | +#ifdef NANODE |
| 30 | +#include <NanodeMAC.h> |
| 31 | +#endif |
| 32 | + |
| 33 | +#define DEBUG |
| 34 | + |
| 35 | +// If using a Common Anode RGB LED (i.e. has connection to +5V |
| 36 | +// Then leave this uncommented this |
| 37 | +//#define COMMON_ANODE |
| 38 | +// If using Common Cathode RGB LED (i.e. has common connection to GND) |
| 39 | +// then comment out the above line or change to: |
| 40 | +#undef COMMON_ANODE |
| 41 | + |
| 42 | +#ifdef COMMON_ANODE |
| 43 | +#define LOW_LIMIT 255 |
| 44 | +#define HIGH_LIMIT 0 |
| 45 | +#else |
| 46 | +#define LOW_LIMIT 0 |
| 47 | +#define HIGH_LIMIT 255 |
| 48 | +#endif |
| 49 | + |
| 50 | +// Define where the RGB LED is connected - this is a common cathode LED. |
| 51 | +#define BLUEPIN 3 // Blue LED, connected to digital pin 3 |
| 52 | +#define REDPIN 5 // Red LED, connected to digital pin 5 |
| 53 | +#define GREENPIN 6 // Green LED, connected to digital pin 6 |
| 54 | + |
| 55 | +// Please modify the following lines. mac and ip have to be unique |
| 56 | +// in your local area network. You can not have the same numbers in |
| 57 | +// two devices: |
| 58 | +// how did I get the mac addr? Translate the first 3 numbers into ascii is: TUX |
| 59 | +#ifdef NANODE |
| 60 | +static uint8_t mymac[6] = { 0,0,0,0,0,0 }; |
| 61 | +#else |
| 62 | +static uint8_t mymac[6] = { 0x54,0x55,0x58,0x12,0x34,0x56 }; |
| 63 | +#endif |
| 64 | + |
| 65 | +// IP and netmask allocated by DHCP |
| 66 | +static uint8_t myip[4] = { 0,0,0,0 }; |
| 67 | +static uint8_t mynetmask[4] = { 0,0,0,0 }; |
| 68 | +static uint8_t gwip[4] = { 0,0,0,0 }; |
| 69 | +static uint8_t dnsip[4] = { 0,0,0,0 }; |
| 70 | +static uint8_t dhcpsvrip[4] = { 0,0,0,0 }; |
| 71 | + |
| 72 | +// IP address of the host being queried to contact (IP of the first portion of the URL): |
| 73 | +static uint8_t websrvip[4] = { 0, 0, 0, 0}; |
| 74 | + |
| 75 | +int currentRed = 0; |
| 76 | +int currentGreen = 0; |
| 77 | +int currentBlue = 0; |
| 78 | + |
| 79 | +//============================================================================================================ |
| 80 | +// Pachube declarations |
| 81 | +//============================================================================================================ |
| 82 | +#define PORT 80 // HTTP |
| 83 | + |
| 84 | +// the EtherCard library does not really support sending additional info in a get request |
| 85 | +// here we fudge it in the host field to add the API key |
| 86 | +// Http header is |
| 87 | +// Host: <HOSTNAME> |
| 88 | +// X-PachubeApiKey: xxxxxxxx |
| 89 | +// User-Agent: Arduino/1.0 |
| 90 | +// Accept: text/html |
| 91 | +// Add your own API key |
| 92 | +#define PACHUBEAPIKEY "pachube.com\r\nX-PachubeApiKey: xxxxxxxxxxxxxxxxxx" |
| 93 | +#define PACHUBE_VHOST "pachube.com" |
| 94 | +// This demo only works with v1 API URLs, A v2 url has 1 result per line |
| 95 | +// Add your own FEED ID |
| 96 | +#define PACHUBEAPIURL "/api/xxxxx.csv" |
| 97 | + |
| 98 | +static uint8_t resend=0; |
| 99 | + |
| 100 | +byte Ethernet::buffer[700]; |
| 101 | +#ifdef NANODE |
| 102 | +NanodeMAC mac( mymac ); |
| 103 | +#endif |
| 104 | + |
| 105 | +void browserresult_callback(uint8_t statuscode,uint16_t datapos, uint16_t dlen){ |
| 106 | +char headerEnd[2] = {'\r','\n' }; |
| 107 | +int contentLen = 0; |
| 108 | + |
| 109 | +#ifdef DEBUG |
| 110 | + Serial.print("Received data, status:"); |
| 111 | + Serial.println(statuscode,DEC); |
| 112 | +// Serial.println((char*)&Ethernet::buffer[datapos]); |
| 113 | +#endif |
| 114 | + |
| 115 | + if (datapos != 0) |
| 116 | + { |
| 117 | + // Scan headers looking for Content-Length: 5 |
| 118 | + // Start of a line, look for "Content-Length: " |
| 119 | + // now search for the csv data - it follows the first blank line |
| 120 | + uint16_t pos = datapos; |
| 121 | + while (Ethernet::buffer[pos]) // loop until end of buffer (or we break out having found what we wanted) |
| 122 | + { |
| 123 | + // Look for line with \r\n on its own |
| 124 | + if( strncmp ((char*)&Ethernet::buffer[pos],headerEnd, 2) == 0 ) { |
| 125 | + Serial.println("End of headers"); |
| 126 | + pos += 2; |
| 127 | + break; |
| 128 | + } |
| 129 | + |
| 130 | + if( strncmp ((char*)&Ethernet::buffer[pos], "Content-Length:", 15) == 0 ) { |
| 131 | + // Found Content-Length |
| 132 | + pos += 16; // Skip to value |
| 133 | + char ch = Ethernet::buffer[pos++]; |
| 134 | + contentLen = 0; |
| 135 | + while(ch >= '0' && ch <= '9' ) { // Only digits |
| 136 | + contentLen *= 10; |
| 137 | + contentLen += (ch - '0'); |
| 138 | + ch = Ethernet::buffer[pos++]; |
| 139 | + } |
| 140 | +#ifdef DEBUG |
| 141 | + Serial.print("Content Length: " ); |
| 142 | + Serial.println( contentLen, DEC ); |
| 143 | +#endif |
| 144 | + } |
| 145 | + // Scan to end of line |
| 146 | + while( Ethernet::buffer[pos++] != '\r' ) { } |
| 147 | + while( Ethernet::buffer[pos++] != '\n' ) { } |
| 148 | + |
| 149 | + if (Ethernet::buffer[pos] == 0) break; // run out of buffer?? |
| 150 | + } |
| 151 | + if (Ethernet::buffer[pos]) // we didn't run out of buffer |
| 152 | + { |
| 153 | + |
| 154 | + int red = 0; |
| 155 | + int green = 0; |
| 156 | + int blue = 0; |
| 157 | + int index = pos; |
| 158 | + char ch = Ethernet::buffer[index++]; |
| 159 | + while(ch >= '0' && ch <= '9' ) { |
| 160 | + red *= 10; |
| 161 | + red += (ch - '0'); |
| 162 | + ch = Ethernet::buffer[index++]; |
| 163 | + } |
| 164 | + ch = Ethernet::buffer[index++]; |
| 165 | + while(ch >= '0' && ch <= '9') { |
| 166 | + green *= 10; |
| 167 | + green += (ch - '0'); |
| 168 | + ch = Ethernet::buffer[index++]; |
| 169 | + } |
| 170 | + ch = Ethernet::buffer[index++]; |
| 171 | + while(ch >= '0' && ch <= '9' && index < (pos+contentLen+1)) { |
| 172 | + blue *= 10; |
| 173 | + blue += (ch - '0'); |
| 174 | + ch = Ethernet::buffer[index++]; |
| 175 | + } |
| 176 | + |
| 177 | +#ifdef DEBUG |
| 178 | + Serial.print( "Red: " ); |
| 179 | + Serial.println( red,DEC ); |
| 180 | + Serial.print( "Green: " ); |
| 181 | + Serial.println( green,DEC ); |
| 182 | + Serial.print( "Blue: " ); |
| 183 | + Serial.println( blue,DEC ); |
| 184 | +#endif |
| 185 | + |
| 186 | + // Set the RGB LEDS |
| 187 | +// solid( red, green, blue, 0 ); |
| 188 | + fadeTo( red, green, blue ); |
| 189 | + } |
| 190 | + } |
| 191 | +} |
| 192 | + |
| 193 | +//function fades existing values to new RGB values |
| 194 | +void fadeTo(int r, int g, int b) |
| 195 | +{ |
| 196 | + //map values |
| 197 | + r = map(r, 0, 255, LOW_LIMIT, HIGH_LIMIT); |
| 198 | + g = map(g, 0, 255, LOW_LIMIT, HIGH_LIMIT); |
| 199 | + b = map(b, 0, 255, LOW_LIMIT, HIGH_LIMIT); |
| 200 | + |
| 201 | + //output |
| 202 | + fadeToColour( REDPIN, currentRed, r ); |
| 203 | + fadeToColour( GREENPIN, currentGreen, g ); |
| 204 | + fadeToColour( BLUEPIN, currentBlue, b ); |
| 205 | + |
| 206 | + currentRed = r; |
| 207 | + currentGreen = g; |
| 208 | + currentBlue = b; |
| 209 | +} |
| 210 | + |
| 211 | +// Fade a single colour |
| 212 | +void fadeToColour( int pin, int fromValue, int toValue ) { |
| 213 | + int increment = (fromValue > toValue ? -1 : 1 ); |
| 214 | + int startValue = (fromValue > toValue ? : 1 ); |
| 215 | + |
| 216 | + if( fromValue == toValue ) |
| 217 | + return; // Nothing to do! |
| 218 | + |
| 219 | + if( fromValue > toValue ) { |
| 220 | + // Fade down |
| 221 | + for( int i = fromValue; i >= toValue; i += increment ) { |
| 222 | + analogWrite( pin, i ); |
| 223 | + delay(10); |
| 224 | + } |
| 225 | + } else { |
| 226 | + // Fade up |
| 227 | + for( int i = fromValue; i <= toValue; i += increment ) { |
| 228 | + analogWrite( pin, i ); |
| 229 | + delay(10); |
| 230 | + } |
| 231 | + } |
| 232 | +} |
| 233 | + |
| 234 | + |
| 235 | +//function holds RGB values for time t milliseconds, mainly for demo |
| 236 | +void solid(int r, int g, int b, int t) |
| 237 | +{ |
| 238 | + //map values |
| 239 | + r = map(r, 0, 255, LOW_LIMIT, HIGH_LIMIT); |
| 240 | + g = map(g, 0, 255, LOW_LIMIT, HIGH_LIMIT); |
| 241 | + b = map(b, 0, 255, LOW_LIMIT, HIGH_LIMIT); |
| 242 | + |
| 243 | + //output |
| 244 | + analogWrite(REDPIN,r); |
| 245 | + analogWrite(GREENPIN,g); |
| 246 | + analogWrite(BLUEPIN,b); |
| 247 | + |
| 248 | + currentRed = r; |
| 249 | + currentGreen = g; |
| 250 | + currentBlue = b; |
| 251 | + |
| 252 | + //hold at this colour set for t ms |
| 253 | + if( delay > 0 ) |
| 254 | + delay(t); |
| 255 | +} |
| 256 | + |
| 257 | +void setup(){ |
| 258 | +#ifdef DEBUG |
| 259 | + Serial.begin(19200); |
| 260 | + Serial.println("EtherCard Pachube RGB"); |
| 261 | +#endif |
| 262 | + |
| 263 | + pinMode(REDPIN, OUTPUT); // sets the pins as output |
| 264 | + pinMode(GREENPIN, OUTPUT); |
| 265 | + pinMode(BLUEPIN, OUTPUT); |
| 266 | + // Set the RGB LEDs off |
| 267 | + solid(255, 0, 0, 0 ); |
| 268 | + |
| 269 | + uint8_t rev = ether.begin(sizeof Ethernet::buffer, mymac); |
| 270 | + Serial.print("ENC28J60 Revision " ); |
| 271 | + Serial.println( rev, DEC ); |
| 272 | + if ( rev == 0) |
| 273 | + Serial.println( "Failed to access Ethernet controller"); |
| 274 | + |
| 275 | + Serial.println("Setting up DHCP"); |
| 276 | + if (!ether.dhcpSetup()) |
| 277 | + Serial.println( "DHCP failed"); |
| 278 | + |
| 279 | + ether.printIp("My IP: ", ether.myip); |
| 280 | + ether.printIp("Netmask: ", ether.mymask); |
| 281 | + ether.printIp("GW IP: ", ether.gwip); |
| 282 | + ether.printIp("DNS IP: ", ether.dnsip); |
| 283 | + |
| 284 | + if (!ether.dnsLookup(PSTR( PACHUBE_VHOST ))) |
| 285 | + Serial.println("DNS failed"); |
| 286 | + |
| 287 | + ether.printIp("SRV: ", ether.hisip); |
| 288 | + |
| 289 | + solid(255, 153, 51, 0 ); |
| 290 | + |
| 291 | +#ifdef DEBUG |
| 292 | +// Serial.print( "ENC28J60 version " ); |
| 293 | +// Serial.println( es.ES_enc28j60Revision(), HEX); |
| 294 | +// if( es.ES_enc28j60Revision() <= 0 ) { |
| 295 | +// Serial.println( "Failed to access ENC28J60"); |
| 296 | + |
| 297 | +// while(1); // Just loop here |
| 298 | +// } |
| 299 | +#endif |
| 300 | + |
| 301 | +/* |
| 302 | + for( int i=0; i<4; i++ ) { |
| 303 | + solid(255,0,0, 200 ); |
| 304 | + solid(0,255,0, 200 ); |
| 305 | + solid(0,0,255, 200 ); |
| 306 | + } |
| 307 | + |
| 308 | + // All off |
| 309 | + solid( 0, 0, 0, 0 ); |
| 310 | +*/ |
| 311 | +#ifdef DEBUG |
| 312 | + Serial.println("Ready"); |
| 313 | +#endif |
| 314 | +} |
| 315 | + |
| 316 | +#ifdef DEBUG2 |
| 317 | +// Output a ip address from buffer from startByte |
| 318 | +void printIP( uint8_t *buf ) { |
| 319 | + for( int i = 0; i < 4; i++ ) { |
| 320 | + Serial.print( buf[i], DEC ); |
| 321 | + if( i<3 ) |
| 322 | + Serial.print( "." ); |
| 323 | + } |
| 324 | +} |
| 325 | +#endif |
| 326 | + |
| 327 | + |
| 328 | +void loop() |
| 329 | +{ |
| 330 | + static uint32_t timetosend; |
| 331 | + uint16_t dat_p; |
| 332 | + int plen = 0; |
| 333 | + |
| 334 | + // Main processing loop now we have our addresses |
| 335 | +// while( es.ES_dhcp_state() == DHCP_STATE_OK ) { |
| 336 | + // Stays within this loop as long as DHCP state is ok |
| 337 | + // If it changes then it drops out and forces a renewal of details |
| 338 | + // handle ping and wait for a tcp packet - calling this routine powers the sending and receiving of data |
| 339 | + plen = ether.packetReceive(); |
| 340 | + dat_p=ether.packetLoop( plen ); |
| 341 | + if( plen > 0 ) { |
| 342 | + // We have a packet |
| 343 | + // Check if IP data |
| 344 | + if (dat_p == 0) { |
| 345 | +// if (es.ES_client_waiting_gw() ){ |
| 346 | + // No ARP received for gateway |
| 347 | +// continue; |
| 348 | +// } |
| 349 | + } |
| 350 | + } |
| 351 | + // If we have IP address for server and its time then request data |
| 352 | + |
| 353 | + if( millis() - timetosend > 3000) // every 3 seconds |
| 354 | + { |
| 355 | + timetosend = millis(); |
| 356 | +#ifdef DEBUG |
| 357 | + Serial.println("Sending request"); |
| 358 | +#endif |
| 359 | + // note the use of PSTR - this puts the string into code space and is compulsory in this call |
| 360 | + // second parameter is a variable string to append to HTTPPATH, this string is NOT a PSTR |
| 361 | + ether.browseUrl(PSTR(PACHUBEAPIURL), "", PSTR(PACHUBEAPIKEY), &browserresult_callback); |
| 362 | + } |
| 363 | +// } |
| 364 | +} |
| 365 | + |
0 commit comments