Advertisement
rossoreed

Ethernet - Pachube

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