Skip to content

Instantly share code, notes, and snippets.

@maniacbug
Created August 7, 2011 03:19
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save maniacbug/1130021 to your computer and use it in GitHub Desktop.
Save maniacbug/1130021 to your computer and use it in GitHub Desktop.
Example to use EtherCard on Nanode to upload data to Pachube
// 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>
//
// See blog post at http://maniacbug.wordpress.com/2011/08/07/nanode/
// This has been tested with EtherCard rev 7752
// Get it from http://jeelabs.net/projects/11/wiki/EtherCard
#include <EtherCard.h>
// change these settings to match your own setup
#define FEED "33735"
#define APIKEY "3U_mvycWRlzWw_0o2RrPUY8cRG-E1wmDTsqTTeR5DrM"
// 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";
byte Ethernet::buffer[500];
uint32_t timer;
Stash stash;
// number of requests which we will make. Free Pachube
// accounts are rate-limited to 5 per minute, so if we leave this
// sketch running, we won't get nag mails from Pachube
int requests_remaining = 5;
void printf_begin(void);
void read_MAC(byte*);
void setup () {
Serial.begin(57600);
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);
}
void loop () {
ether.packetLoop(ether.packetReceive());
if (millis() > timer && requests_remaining ) {
timer = millis() + 10000;
printf_P(PSTR("Sending...\n\r"));
// generate two fake values as payload - by using a separate stash,
// we can determine the size of the generated message ahead of time
byte sd = stash.create();
stash.print("1,");
stash.println((word) millis() / 123);
stash.print("2,");
stash.println((word) micros() / 456);
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();
if ( ! --requests_remaining )
printf_P(PSTR("Stopping.\n\r"));
}
}
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
@Scott216
Copy link

I got this working with Pachube, it was easy. Thanks! I'm new to C programming and I'm trying to figure out what stash is in your program. I did some Google searches and I'm having a hard time finding an explanation.

@maniacbug
Copy link
Author

maniacbug commented Jan 25, 2012 via email

@Scott216
Copy link

Scott216 commented Jan 25, 2012 via email

@maniacbug
Copy link
Author

maniacbug commented Jan 25, 2012 via email

@Scott216
Copy link

Scott216 commented Jan 25, 2012 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment