PageRenderTime 25ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/examples/EtherShield_PachubeRGB/EtherShield_PachubeRGB.pde

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