rossoreed

Ethernet - Pachube

Oct 24th, 2011
189
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Simple demo for feeding some random data to Pachube.
  2. // Based on pachube.pde 2011-07-08 <jcw@equi4.com> http://opensource.org/licenses/mit-license.php
  3. // Created by <maniacbug@ymail.com>
  4.  
  5. // This has been tested with EtherCard rev 7752
  6. // Get it from http://jeelabs.net/projects/11/wiki/EtherCard
  7. #include <EtherCard.h>
  8. #include <CmdMessenger.h>
  9. #include <Base64.h>
  10. #include <Streaming.h>
  11.  
  12. // change these settings to match your own setup
  13. #define FEED    "34843"
  14. #define APIKEY  "VKL3ii3Zhdhgcgjkif66Fh4fxdfgGGfIyap"
  15.  
  16. // On Nanode, this will get the MAC from the 11AA02E48 chip
  17. byte mymac[6];
  18.  
  19. // Static IP configuration to use if no DHCP found
  20. // Change these to match your site setup
  21. static byte static_ip[] = { 192,168,1,91 };
  22. static byte static_gw[] = { 192,168,1,1 };
  23. static byte static_dns[] = { 192,168,1,99 };
  24.  
  25. char website[] PROGMEM = "api.pachube.com";
  26. char field_separator = ',';
  27. char command_separator = ';';
  28.  
  29. int mcount, tvalue, sd1, sd1a, sd2, sd2a;
  30. double sd6, sd7;
  31. float sd3, sd4, sd5, sd8=0.0;  //floats because data is to ? decimal places
  32. int tol=5;  //update frequency tolerance, either up or down 5 Watts triggers an update
  33. //------------------------------------------------------------
  34. // Timing Variables
  35. //------------------------------------------------------------
  36. unsigned long timerDelay=840000UL;  // Maximum Pachube update time to prevent freezing - 14 minutes
  37. unsigned long LEDDelay=500;    //Sets the period which LED blinks when data is uploaded to Pachube
  38. unsigned long prevMillis=0UL;
  39.  
  40. byte Ethernet::buffer[512];
  41. uint32_t timer;
  42. Stash stash;
  43.  
  44. void printf_begin(void);
  45. void read_MAC(byte*);
  46.  
  47. //------------Command Messenger------------------//
  48.  
  49. // Attach a new CmdMessenger object to the default Serial port
  50. CmdMessenger cmdMessenger = CmdMessenger(Serial, field_separator, command_separator);
  51.  
  52. enum
  53. {
  54.   kCOMM_ERROR    = 000, // Lets Arduino report serial port comm error back to the PC (only works for some comm errors)
  55.   kACK           = 001, // Arduino acknowledges cmd was received
  56.   kARDUINO_READY = 002, // After opening the comm port, send this cmd 02 from PC to check arduino is ready
  57.   kERR           = 003, // Arduino reports badly formatted cmd, or cmd not recognised
  58.  
  59.   kSEND_CMDS_END, // Mustnt delete this line
  60. };
  61.  
  62. messengerCallbackFunction messengerCallbacks[] =
  63. {
  64.   Arduino_msg,            // 004 in this example
  65.   NULL
  66. };
  67.  
  68. void Arduino_msg()
  69. {
  70.   cmdMessenger.sendCmd(kACK,"command recieved");
  71.   mcount = 0;
  72.   while ( cmdMessenger.available() )
  73.   {
  74.     char buf[350] = { '\0' };
  75.     cmdMessenger.copyString(buf, 350);
  76.  
  77.     mcount = mcount+1 ;
  78.     tvalue = atoi(buf);
  79.     if (mcount == 1) {
  80.      sd1 = (tvalue); }
  81.       else if (mcount == 2) {
  82.        sd2 = (tvalue); }
  83.         else if (mcount == 3) {
  84.          sd3 = (tvalue); }
  85.           else if (mcount == 4) {
  86.            sd4 = (tvalue); }
  87.             else if (mcount == 5) {
  88.              sd5 = (tvalue); }
  89.               else if (mcount == 6) {
  90.                sd6 = (tvalue); }
  91.                 else if (mcount == 7) {
  92.                  sd7 = (tvalue); }
  93.                   else if (mcount == 8) {
  94.                    sd8 = (tvalue); }
  95.     if(buf[0])
  96.       cmdMessenger.sendCmd(kACK, buf);
  97.    }
  98. }
  99.  
  100. void arduino_ready()
  101. {
  102.   // In response to ping. We just send a throw-away Acknowledgement to say "im alive"
  103.   cmdMessenger.sendCmd(kACK,"Arduino ready");
  104. }
  105.  
  106. void unknownCmd()
  107. {
  108.   // Default response for unknown commands and corrupt messages
  109.   cmdMessenger.sendCmd(kERR,"Unknown command");
  110. }
  111.  
  112. void attach_callbacks(messengerCallbackFunction* callbacks)
  113. {
  114.   int i = 0;
  115.   int offset = kSEND_CMDS_END;
  116.   while(callbacks[i])
  117.   {
  118.     cmdMessenger.attach(offset+i, callbacks[i]);
  119.     i++;
  120.   }
  121. }
  122. //end of CmdMessenger code
  123.  
  124. void setup () {
  125.   pinMode(6, OUTPUT);  //Onboard LED
  126.  
  127.   Serial.begin(9600);
  128.   printf_begin();
  129.   printf_P(PSTR("\nEtherCard/examples/nanode_pachube\n\r"));
  130.  
  131.   // Fetch the MAC address -- Nanode-specific
  132.   read_MAC(mymac);
  133.  
  134.   printf_P(PSTR("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n\r"),
  135.       mymac[0],
  136.       mymac[1],
  137.       mymac[2],
  138.       mymac[3],
  139.       mymac[4],
  140.       mymac[5]
  141.   );
  142.  
  143.   if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
  144.     printf_P(PSTR( "Failed to access Ethernet controller\n\r"));
  145.   if (!ether.dhcpSetup())
  146.   {
  147.     printf_P(PSTR("DHCP failed, using static configuration\n\r"));
  148.     ether.staticSetup(static_ip, static_gw);
  149.     ether.copyIp(ether.dnsip, static_dns);
  150.   }
  151.  
  152.   ether.printIp("IP:  ", ether.myip);
  153.   ether.printIp("GW:  ", ether.gwip);  
  154.   ether.printIp("DNS: ", ether.dnsip);  
  155.  
  156.   if (!ether.dnsLookup(website))
  157.     printf_P(PSTR("DNS failed\n\r"));
  158.    
  159.   ether.printIp("SRV: ", ether.hisip);
  160.  
  161.   //----------Start of CmdMessenger----------//
  162.   cmdMessenger.print_LF_CR();   // Make output more readable whilst debugging in Arduino Serial Monitor
  163.   cmdMessenger.attach(kARDUINO_READY, arduino_ready);
  164.   cmdMessenger.attach(unknownCmd);
  165.   attach_callbacks(messengerCallbacks);
  166.   arduino_ready();
  167.   //----------End of CmdMessenger----------//
  168. }
  169.  
  170. void loop () {  
  171.  
  172.   //check if timer has reset (after 49 days...)
  173.   if (prevMillis > millis()) {
  174.     prevMillis = 0;  }
  175.  
  176.   cmdMessenger.feedinSerialData(); //CmdMessenger
  177.  
  178.   ether.packetLoop(ether.packetReceive());
  179.  
  180.   //------------------------------
  181.   // SEND DATA TO PACHUBE  
  182.   //------------------------------
  183.  
  184.   // blink onboard LED to show IF statement is true (Pin 6 on Nanode)
  185.   if ((millis() - prevMillis) > (LEDDelay)) {
  186.     digitalWrite(6, HIGH); } // turns LED off
  187.  
  188.   // check if new data has arrived...
  189.     if ((sd1 >(sd1a + tol)) || (sd1 <(sd1a - tol)) || (sd2 >(sd2a + tol)) || (sd2 <(sd2a - tol)) || ((millis() - prevMillis) > (timerDelay)))  {
  190.      
  191.     digitalWrite(6, LOW); //turns onboard LED on if IF statement true
  192.      
  193.     // reset the indicators to current values
  194.     sd1a = sd1;
  195.     sd2a = sd2;
  196.     prevMillis=millis();
  197.        
  198.     printf_P(PSTR("Sending...\n\r"));
  199.  
  200.     byte sd = stash.create();
  201.     stash.print("sd1,");
  202.     stash.println((word) sd1);
  203.     stash.print("sd2,");
  204.     stash.println((word) sd2);
  205.     stash.print("sd3,");
  206.     stash.println((word) sd3 / 1000.0, 3);
  207.     stash.print("sd4,");
  208.     stash.println((word) sd4 / 1000.0, 3);
  209.     stash.print("sd5,");
  210.     stash.println((word) sd5 / 1000.0, 3);
  211.     stash.print("sd6,");
  212.     stash.println((word) sd6);
  213.     stash.print("sd7,");
  214.     stash.println((word) sd7);
  215.     stash.print("sd8,");
  216.     stash.println((sd8 / 100.0) - 50.0);
  217.     //stash.println((word) sd8);
  218.     stash.save();
  219.    
  220.     // generate the header with payload - note that the stash size is used,
  221.     // and that a "stash descriptor" is passed in as argument using "$H"
  222.     Stash::prepare(PSTR("PUT http://$F/v2/feeds/$F.csv HTTP/1.0" "\r\n"
  223.                         "Host: $F" "\r\n"
  224.                         "X-PachubeApiKey: $F" "\r\n"
  225.                         "Content-Length: $D" "\r\n"
  226.                         "\r\n"
  227.                         "$H"),
  228.             website, PSTR(FEED), website, PSTR(APIKEY), stash.size(), sd);
  229.  
  230.     // send the packet - this also releases all stash buffers once done
  231.     ether.tcpSend();
  232.   }
  233. }
  234.  
  235. int serial_putc( char c, FILE * )
  236. {
  237.   Serial.write( c );
  238.   return c;
  239. }
  240.  
  241. void printf_begin(void)
  242. {
  243.   fdevopen( &serial_putc, 0 );
  244. }
  245.  
  246. // Nanode_MAC
  247. // Rufus Cable, June 2011 (threebytesfull)
  248.  
  249. // Sample code to read the MAC address from the 11AA02E48 on the
  250. // back of the Nanode V5 board.
  251.  
  252. // This code is hacky and basic - it doesn't check for bus errors
  253. // and will probably fail horribly if it's interrupted. It's best
  254. // run in setup() - fetch the MAC address once and keep it. After
  255. // the address is fetched, it puts the chip back in standby mode
  256. // in which it apparently only consumes 1uA.
  257.  
  258. // Feel free to reuse this code - suggestions for improvement are
  259. // welcome! :)
  260.  
  261. // http://ww1.microchip.com/downloads/en/DeviceDoc/DS-22067H.pdf
  262. // http://ww1.microchip.com/downloads/en/devicedoc/22122a.pdf
  263.  
  264. // Nanode has UNI/O SCIO on PD7
  265.  
  266. #define D7_ON  _BV(7)
  267. #define D7_OFF (~D7_ON)
  268.  
  269. #define SCIO_HIGH PORTD |= D7_ON
  270. #define SCIO_LOW  PORTD &= D7_OFF
  271.  
  272. #define SCIO_OUTPUT DDRD |= D7_ON
  273. #define SCIO_INPUT  DDRD &= D7_OFF
  274.  
  275. #define SCIO_READ ((PIND & D7_ON) != 0)
  276.  
  277. #define WAIT_QUARTER_BIT delayMicroseconds(9);
  278. #define WAIT_HALF_BIT delayMicroseconds(20);
  279.  
  280. #define NOP PORTD &= 0xff
  281.  
  282. // Fixed Timings
  283. // standby pulse time (600us+)
  284. #define UNIO_TSTBY_US 600
  285. // start header setup time (10us+)
  286. #define UNIO_TSS_US 10
  287. // start header low pulse (5us+)
  288. #define UNIO_THDR_US 6
  289.  
  290. // SCIO Manipulation macros
  291. #define BIT0 SCIO_HIGH;WAIT_HALF_BIT;SCIO_LOW;WAIT_HALF_BIT;
  292. #define BIT1 SCIO_LOW;WAIT_HALF_BIT;SCIO_HIGH;WAIT_HALF_BIT;
  293.  
  294. // 11AA02E48 defines
  295. #define DEVICE_ADDRESS 0xA0
  296. #define READ_INSTRUCTION 0x03
  297.  
  298. // Where on the chip is the MAC address located?
  299. #define CHIP_ADDRESS 0xFA
  300.  
  301. inline bool unio_readBit()
  302. {
  303.   SCIO_INPUT;
  304.   WAIT_QUARTER_BIT;
  305.   bool value1 = SCIO_READ;
  306.   WAIT_HALF_BIT;
  307.   bool value2 = SCIO_READ;
  308.   WAIT_QUARTER_BIT;
  309.   return (value2 && !value1);
  310. }
  311.  
  312. void unio_standby() {
  313.  
  314.   SCIO_OUTPUT;
  315.   SCIO_HIGH;
  316.   delayMicroseconds(UNIO_TSTBY_US);
  317. }
  318.  
  319. void unio_sendByte(byte data) {
  320.  
  321.   SCIO_OUTPUT;
  322.   for (int i=0; i<8; i++) {
  323.     if (data & 0x80) {
  324.       BIT1;
  325.     } else {
  326.       BIT0;
  327.     }
  328.     data <<= 1;
  329.   }
  330.   // MAK
  331.   BIT1;
  332.   // SAK?
  333.   /*bool sak =*/ unio_readBit();
  334. }
  335.  
  336. void unio_readBytes(byte *addr, int length) {
  337.   for (int i=0; i<length; i++) {
  338.    
  339.     byte data = 0;
  340.     for (int b=0; b<8; b++) {
  341.       data = (data << 1) | (unio_readBit() ? 1 : 0);
  342.     }
  343.     SCIO_OUTPUT;
  344.     if (i==length-1) {
  345.       BIT0; // NoMAK
  346.     } else {
  347.       BIT1; // MAK
  348.     }
  349.     /*bool sak =*/ unio_readBit();
  350.     addr[i] = data;
  351.   }
  352. }
  353.  
  354. void unio_start_header() {
  355.   SCIO_LOW;
  356.   delayMicroseconds(UNIO_THDR_US);
  357.   unio_sendByte(B01010101);
  358. }
  359.  
  360. void read_MAC(byte* mac_address) {
  361.  
  362.   // no interrupts!
  363.   cli();
  364.  
  365.   // standby
  366.   unio_standby();
  367.  
  368.   // start header
  369.   unio_start_header();
  370.  
  371.   unio_sendByte(DEVICE_ADDRESS);
  372.   unio_sendByte(READ_INSTRUCTION);
  373.   unio_sendByte(CHIP_ADDRESS >> 8);
  374.   unio_sendByte(CHIP_ADDRESS & 0xff);
  375.  
  376.   // read 6 bytes
  377.   unio_readBytes(mac_address, 6);
  378.  
  379.   // back to standby
  380.   unio_standby();
  381.  
  382.   // interrupts ok now
  383.   sei();
  384. }
  385.  
  386. // vim:ai:cin:sts=2 sw=2 ft=cpp
RAW Paste Data