#if !defined(__AVR_ATmega328P__) #error "This sketch is designed for an Arduino Uno or Duemilenova. You are using a different processor. You can try removing this #error, but YMMV" #endif // Code by Paul MacDougal for triembed.org members // This code is released into the public domain for any and all uses // We expect a normally low signal on pin SW // We will count the number of rising edges (not debounced in any way in software) // and report that every once in a while. #include // Sleep Modes #include // Power management #include // Watchdog timer #include // Pin Change Interrupt //unsigned char WARstupidArduinoIssue; // tell the Arduino IDE that this is the beginning of code so that #if works below // Ideally, this is just the duration you want to sleep divided by 8s, but you might need to tune it per processor at temperature and voltage // must fit in a short (65k), so you need to sleep for less than 6.1 days or change change some variables from 'short' to 'long' #define ONE_HOUR 450 #define EIGHT_MINUTES 60 #define ONE_MINUTE 7 #define DURATION ONE_HOUR // Set the reporting duration here // If you are using an Ethernet Shield, you can report to a Sparkfun public data stream https://data.sparkfun.com/streams/AJgVGKqLN5hjGAgLEAAV #define USE_ETHERNET 1 #if USE_ETHERNET #include #include #define PUBLICKEY "AJgVGKqLN5hjGAgLEAAV" #define PRIVATEKEY "ask Paul for the key" #define HOST "follow the instructions in the comment" // change this to your initials and some trailing digits, e.g. pdm003 #endif #if USE_ETHERNET byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // physical mac address You can pick one :-) const byte LED = 3, SW = 2; // The ethernet shield uses pin 13, so you will need to put an LED w/ resistor to ground on pin LED #else const byte LED = 13, SW = 2; #endif // We use a trick to toggle the LED. The datasheet says "Writing a logic one to PINxn toggles the value of PORTxn" uint8_t bitn; // This is a byte with PINxn set volatile uint8_t *pinx; // This is a non-volatile pointer to a volatile PINx register //################# Interrupt Service Routines ###################### volatile unsigned long switchRising = 0; // this is a count of SW rising edges (not debounced in SW) void handleSW() { // ISR // We don't care if we were asleep or awake when the pin went high switchRising++; } // Count of watchdog timer interrupts volatile unsigned short eightSecondPeriods = 0; ISR(WDT_vect) { eightSecondPeriods++; *pinx = bitn; // toggle the LED } //##################################################################### // This routine puts the processor to sleep and handles waking up activities void sleepNow() { set_sleep_mode(SLEEP_MODE_PWR_DOWN); // this is the lowest level of sleep // you may be able to further reduce power consumption while asleep by turning off BrownOut Detection, A/D circuits, ... noInterrupts(); // make sure we don't get interrupted before we sleep sleep_enable(); // enables the sleep bit in the MCUCR register PCintPort::attachInterrupt(SW, handleSW, HIGH); // wake up on high level interrupts(); // interrupts allowed now, next instruction WILL be executed sleep_cpu(); // here the device is put to sleep // ... // we wake up here sleep_disable(); // first thing after waking from sleep PCintPort::attachInterrupt(SW, handleSW, RISING); } const uint8_t v1 = (1<