Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Simple demo for feeding some random data to Pachube.
- // Based on pachube.pde 2011-07-08 <jcw@equi4.com> http://opensource.org/licenses/mit-license.php
- // Created by <maniacbug@ymail.com>
- // This has been tested with EtherCard rev 7752
- // Get it from http://jeelabs.net/projects/11/wiki/EtherCard
- #include <EtherCard.h>
- #include <CmdMessenger.h>
- #include <Base64.h>
- #include <Streaming.h>
- // change these settings to match your own setup
- #define FEED "34843"
- #define APIKEY "VKL3ii3Zhdhgcgjkif66Fh4fxdfgGGfIyap"
- // On Nanode, this will get the MAC from the 11AA02E48 chip
- byte mymac[6];
- // Static IP configuration to use if no DHCP found
- // Change these to match your site setup
- static byte static_ip[] = { 192,168,1,91 };
- static byte static_gw[] = { 192,168,1,1 };
- static byte static_dns[] = { 192,168,1,99 };
- char website[] PROGMEM = "api.pachube.com";
- char field_separator = ',';
- char command_separator = ';';
- int mcount, tvalue, sd1, sd1a, sd2, sd2a;
- double sd6, sd7;
- float sd3, sd4, sd5, sd8=0.0; //floats because data is to ? decimal places
- int tol=5; //update frequency tolerance, either up or down 5 Watts triggers an update
- //------------------------------------------------------------
- // Timing Variables
- //------------------------------------------------------------
- unsigned long timerDelay=840000UL; // Maximum Pachube update time to prevent freezing - 14 minutes
- unsigned long LEDDelay=500; //Sets the period which LED blinks when data is uploaded to Pachube
- unsigned long prevMillis=0UL;
- byte Ethernet::buffer[512];
- uint32_t timer;
- Stash stash;
- void printf_begin(void);
- void read_MAC(byte*);
- //------------Command Messenger------------------//
- // Attach a new CmdMessenger object to the default Serial port
- CmdMessenger cmdMessenger = CmdMessenger(Serial, field_separator, command_separator);
- enum
- {
- kCOMM_ERROR = 000, // Lets Arduino report serial port comm error back to the PC (only works for some comm errors)
- kACK = 001, // Arduino acknowledges cmd was received
- kARDUINO_READY = 002, // After opening the comm port, send this cmd 02 from PC to check arduino is ready
- kERR = 003, // Arduino reports badly formatted cmd, or cmd not recognised
- kSEND_CMDS_END, // Mustnt delete this line
- };
- messengerCallbackFunction messengerCallbacks[] =
- {
- Arduino_msg, // 004 in this example
- NULL
- };
- void Arduino_msg()
- {
- cmdMessenger.sendCmd(kACK,"command recieved");
- mcount = 0;
- while ( cmdMessenger.available() )
- {
- char buf[350] = { '\0' };
- cmdMessenger.copyString(buf, 350);
- mcount = mcount+1 ;
- tvalue = atoi(buf);
- if (mcount == 1) {
- sd1 = (tvalue); }
- else if (mcount == 2) {
- sd2 = (tvalue); }
- else if (mcount == 3) {
- sd3 = (tvalue); }
- else if (mcount == 4) {
- sd4 = (tvalue); }
- else if (mcount == 5) {
- sd5 = (tvalue); }
- else if (mcount == 6) {
- sd6 = (tvalue); }
- else if (mcount == 7) {
- sd7 = (tvalue); }
- else if (mcount == 8) {
- sd8 = (tvalue); }
- if(buf[0])
- cmdMessenger.sendCmd(kACK, buf);
- }
- }
- void arduino_ready()
- {
- // In response to ping. We just send a throw-away Acknowledgement to say "im alive"
- cmdMessenger.sendCmd(kACK,"Arduino ready");
- }
- void unknownCmd()
- {
- // Default response for unknown commands and corrupt messages
- cmdMessenger.sendCmd(kERR,"Unknown command");
- }
- void attach_callbacks(messengerCallbackFunction* callbacks)
- {
- int i = 0;
- int offset = kSEND_CMDS_END;
- while(callbacks[i])
- {
- cmdMessenger.attach(offset+i, callbacks[i]);
- i++;
- }
- }
- //end of CmdMessenger code
- void setup () {
- pinMode(6, OUTPUT); //Onboard LED
- Serial.begin(9600);
- printf_begin();
- printf_P(PSTR("\nEtherCard/examples/nanode_pachube\n\r"));
- // Fetch the MAC address -- Nanode-specific
- read_MAC(mymac);
- printf_P(PSTR("MAC: %02x:%02x:%02x:%02x:%02x:%02x\n\r"),
- mymac[0],
- mymac[1],
- mymac[2],
- mymac[3],
- mymac[4],
- mymac[5]
- );
- if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
- printf_P(PSTR( "Failed to access Ethernet controller\n\r"));
- if (!ether.dhcpSetup())
- {
- printf_P(PSTR("DHCP failed, using static configuration\n\r"));
- ether.staticSetup(static_ip, static_gw);
- ether.copyIp(ether.dnsip, static_dns);
- }
- ether.printIp("IP: ", ether.myip);
- ether.printIp("GW: ", ether.gwip);
- ether.printIp("DNS: ", ether.dnsip);
- if (!ether.dnsLookup(website))
- printf_P(PSTR("DNS failed\n\r"));
- ether.printIp("SRV: ", ether.hisip);
- //----------Start of CmdMessenger----------//
- cmdMessenger.print_LF_CR(); // Make output more readable whilst debugging in Arduino Serial Monitor
- cmdMessenger.attach(kARDUINO_READY, arduino_ready);
- cmdMessenger.attach(unknownCmd);
- attach_callbacks(messengerCallbacks);
- arduino_ready();
- //----------End of CmdMessenger----------//
- }
- void loop () {
- //check if timer has reset (after 49 days...)
- if (prevMillis > millis()) {
- prevMillis = 0; }
- cmdMessenger.feedinSerialData(); //CmdMessenger
- ether.packetLoop(ether.packetReceive());
- //------------------------------
- // SEND DATA TO PACHUBE
- //------------------------------
- // blink onboard LED to show IF statement is true (Pin 6 on Nanode)
- if ((millis() - prevMillis) > (LEDDelay)) {
- digitalWrite(6, HIGH); } // turns LED off
- // check if new data has arrived...
- if ((sd1 >(sd1a + tol)) || (sd1 <(sd1a - tol)) || (sd2 >(sd2a + tol)) || (sd2 <(sd2a - tol)) || ((millis() - prevMillis) > (timerDelay))) {
- digitalWrite(6, LOW); //turns onboard LED on if IF statement true
- // reset the indicators to current values
- sd1a = sd1;
- sd2a = sd2;
- prevMillis=millis();
- printf_P(PSTR("Sending...\n\r"));
- byte sd = stash.create();
- stash.print("sd1,");
- stash.println((word) sd1);
- stash.print("sd2,");
- stash.println((word) sd2);
- stash.print("sd3,");
- stash.println((word) sd3 / 1000.0, 3);
- stash.print("sd4,");
- stash.println((word) sd4 / 1000.0, 3);
- stash.print("sd5,");
- stash.println((word) sd5 / 1000.0, 3);
- stash.print("sd6,");
- stash.println((word) sd6);
- stash.print("sd7,");
- stash.println((word) sd7);
- stash.print("sd8,");
- stash.println((sd8 / 100.0) - 50.0);
- //stash.println((word) sd8);
- stash.save();
- // generate the header with payload - note that the stash size is used,
- // and that a "stash descriptor" is passed in as argument using "$H"
- Stash::prepare(PSTR("PUT http://$F/v2/feeds/$F.csv HTTP/1.0" "\r\n"
- "Host: $F" "\r\n"
- "X-PachubeApiKey: $F" "\r\n"
- "Content-Length: $D" "\r\n"
- "\r\n"
- "$H"),
- website, PSTR(FEED), website, PSTR(APIKEY), stash.size(), sd);
- // send the packet - this also releases all stash buffers once done
- ether.tcpSend();
- }
- }
- int serial_putc( char c, FILE * )
- {
- Serial.write( c );
- return c;
- }
- void printf_begin(void)
- {
- fdevopen( &serial_putc, 0 );
- }
- // Nanode_MAC
- // Rufus Cable, June 2011 (threebytesfull)
- // Sample code to read the MAC address from the 11AA02E48 on the
- // back of the Nanode V5 board.
- // This code is hacky and basic - it doesn't check for bus errors
- // and will probably fail horribly if it's interrupted. It's best
- // run in setup() - fetch the MAC address once and keep it. After
- // the address is fetched, it puts the chip back in standby mode
- // in which it apparently only consumes 1uA.
- // Feel free to reuse this code - suggestions for improvement are
- // welcome! :)
- // http://ww1.microchip.com/downloads/en/DeviceDoc/DS-22067H.pdf
- // http://ww1.microchip.com/downloads/en/devicedoc/22122a.pdf
- // Nanode has UNI/O SCIO on PD7
- #define D7_ON _BV(7)
- #define D7_OFF (~D7_ON)
- #define SCIO_HIGH PORTD |= D7_ON
- #define SCIO_LOW PORTD &= D7_OFF
- #define SCIO_OUTPUT DDRD |= D7_ON
- #define SCIO_INPUT DDRD &= D7_OFF
- #define SCIO_READ ((PIND & D7_ON) != 0)
- #define WAIT_QUARTER_BIT delayMicroseconds(9);
- #define WAIT_HALF_BIT delayMicroseconds(20);
- #define NOP PORTD &= 0xff
- // Fixed Timings
- // standby pulse time (600us+)
- #define UNIO_TSTBY_US 600
- // start header setup time (10us+)
- #define UNIO_TSS_US 10
- // start header low pulse (5us+)
- #define UNIO_THDR_US 6
- // SCIO Manipulation macros
- #define BIT0 SCIO_HIGH;WAIT_HALF_BIT;SCIO_LOW;WAIT_HALF_BIT;
- #define BIT1 SCIO_LOW;WAIT_HALF_BIT;SCIO_HIGH;WAIT_HALF_BIT;
- // 11AA02E48 defines
- #define DEVICE_ADDRESS 0xA0
- #define READ_INSTRUCTION 0x03
- // Where on the chip is the MAC address located?
- #define CHIP_ADDRESS 0xFA
- inline bool unio_readBit()
- {
- SCIO_INPUT;
- WAIT_QUARTER_BIT;
- bool value1 = SCIO_READ;
- WAIT_HALF_BIT;
- bool value2 = SCIO_READ;
- WAIT_QUARTER_BIT;
- return (value2 && !value1);
- }
- void unio_standby() {
- SCIO_OUTPUT;
- SCIO_HIGH;
- delayMicroseconds(UNIO_TSTBY_US);
- }
- void unio_sendByte(byte data) {
- SCIO_OUTPUT;
- for (int i=0; i<8; i++) {
- if (data & 0x80) {
- BIT1;
- } else {
- BIT0;
- }
- data <<= 1;
- }
- // MAK
- BIT1;
- // SAK?
- /*bool sak =*/ unio_readBit();
- }
- void unio_readBytes(byte *addr, int length) {
- for (int i=0; i<length; i++) {
- byte data = 0;
- for (int b=0; b<8; b++) {
- data = (data << 1) | (unio_readBit() ? 1 : 0);
- }
- SCIO_OUTPUT;
- if (i==length-1) {
- BIT0; // NoMAK
- } else {
- BIT1; // MAK
- }
- /*bool sak =*/ unio_readBit();
- addr[i] = data;
- }
- }
- void unio_start_header() {
- SCIO_LOW;
- delayMicroseconds(UNIO_THDR_US);
- unio_sendByte(B01010101);
- }
- void read_MAC(byte* mac_address) {
- // no interrupts!
- cli();
- // standby
- unio_standby();
- // start header
- unio_start_header();
- unio_sendByte(DEVICE_ADDRESS);
- unio_sendByte(READ_INSTRUCTION);
- unio_sendByte(CHIP_ADDRESS >> 8);
- unio_sendByte(CHIP_ADDRESS & 0xff);
- // read 6 bytes
- unio_readBytes(mac_address, 6);
- // back to standby
- unio_standby();
- // interrupts ok now
- sei();
- }
- // vim:ai:cin:sts=2 sw=2 ft=cpp
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement