LowPowerLab Forum

Hardware support => Moteino => Topic started by: jbeale on October 19, 2013, 02:10:20 AM

Title: Moteino v2 sleep mode: is 0.17 mA at 3.3 Vin about right?
Post by: jbeale on October 19, 2013, 02:10:20 AM
I am trying out low-power sleep mode, for battery operation.  I tried the code below on a Arduino Pro Mini, and also the Moteino R2 (RFM12B module, plus 4Mbit flash), both at 3.3 V.  The Moteino ran at 0.17 mA in sleep mode, is that about right?  That current is low enough for my project, but I'm just checking in case I can lower it further.  Maybe by removing the regulator? Does the 4Mbit flash draw much when not active?  At first I was seeing about 4 mA in sleep, but then I realized I had not put the RFM12B into sleep mode, which makes a difference!

// Sketch for testing low-power sleep mode with wake up on WDT.
// 5V Arduino Pro Mini at 3.3 V:  0.27 mA (only POWER LED on), 3.15 mA (POWER + Pin13 LED on)
// Moteino at 3.3 V: 0.17 mA with Pin9 LED off, 1.11 mA with LED on
// from http://donalmorrissey.blogspot.com/2010/04/sleeping-arduino-part-5-wake-up-via.html

#include <RFM12B.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>

#define NODEID        2  // RFM12b network ID used for this unit
#define NETWORKID    99  // RFM12b network ID we are on

//#define LED_PIN (13) // Arduino LED pin
#define LED_PIN (9) // Moteino LED pin

RFM12B radio;        // MOTEINO RFM12B radio object
volatile int f_wdt=1;  // watchdog timeout flag

/***************************************************
*  Name: Watchdog Interrupt Service (runs at WD timeout)
***************************************************/
ISR(WDT_vect)
{
  if(f_wdt == 0) f_wdt=1;
  else Serial.println("WDT Overrun!!!");
}

/***************************************************
*  Description: Enters the arduino into sleep mode.
***************************************************/
void enterSleep(void)
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   /* EDIT: could also use SLEEP_MODE_PWR_DOWN for lowest power consumption. */
  sleep_enable();
  sleep_mode();  // all halt until WDT interrupt
 
  /* The program will continue from here after the WDT timeout*/
  sleep_disable(); /* First thing to do is disable sleep. */ 
  power_all_enable();  // re-enable all peripherals
}

void setup()
{
  Serial.begin(115200);
  Serial.println("Initialising...");
  delay(100); //Allow for serial print to complete.
 
  // set unused pins to be outputs, avoiding current from floating input pins
  DDRB = 0xef;   // Port B bit 4 is SPI MISO
  PORTB = 0x00;
  DDRC = 0xff;
  PORTC = 0x00;
  DDRD = 0xfe;  // Port D bit 0 is Serial RX (RxD)
  PORTD = 0x00;
 
  pinMode(LED_PIN,OUTPUT);  // enable LED pin as output
 
  radio.Initialize(NODEID, RF12_915MHZ, NETWORKID); // MOTEINO: initialize RFM12B
  radio.Sleep(); // MOTEINO: sleep right away to save power

  MCUSR &= ~(1<<WDRF); // clear reset flag
 
  // In order to change WDE or the prescaler, we need to
  // set WDCE (This will allow updates for 4 clock cycles).
  WDTCSR |= (1<<WDCE) | (1<<WDE);

  /* set new watchdog timeout prescaler value */
  WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */
//  WDTCSR = 1<<WDP1 | 1<<WDP2; /* 1.0 seconds */
//  WDTCSR = 1<<WDP0 | 1<<WDP2; /* 0.5 seconds */
 
  WDTCSR |= _BV(WDIE);   // Enable the WD interrupt (note no reset).
 
  Serial.println("Initialisation complete.");
  delay(100); //Allow for serial print to complete.
}

void loop()
{
  if(f_wdt == 1)
  {
    digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // toggle LED
   
    f_wdt = 0;   // Don't forget to clear the flag.     
    enterSleep();  // (re) enter sleep mode
  }
} // end loop() (main)
Title: Re: Moteino v2 sleep mode: is 0.17 mA at 3.3 Vin about right?
Post by: Felix on October 19, 2013, 11:57:05 AM
If you sleep everything (atmega, radio, flash, and any other peripherals) you should be in the few micro amp range.
0.17ma is still a LOT.
If you don't sleep the FLASH chip (sleep() and wakeup() functions) it will not draw a lot, a few microamps, but sleeping it will make it draw something in the sub micro amp range, see datasheet for exact numbers (i think something like 0.1uA).

I use the RocketScream lowpower.h library, or the narcoleptic library to sleep the atmega, makes it very easy with 1 call where you specify how long you want to sleep. See the mailbox notifier sketch for how I do this:
https://github.com/LowPowerLab/MailboxNotifier/blob/master/MailboxNotifier.ino
Title: Re: Moteino v2 sleep mode: now about 6 uA with just WDT
Post by: jbeale on October 20, 2013, 01:21:11 AM
Thanks for the pointer to the LowPower library!  My test code below shows Moteino rev2 (RFM12B radio, and no SPI Flash chip) takes 6 uA in shutdown (with only watchdog timer on, for wake-from-sleep). Current draw was unchanged with Vin anywhere from 5 V down to 3.3 V.  I also tried a cheap Arduino Pro Mini clone, which took a bit more current: 20 uA @ Vin=4.0, 14 uA @ 3.3V (after I removed the always-on red power LED) and that despite the fact it had no RFM12B radio module. I suppose the difference is the LDO regulator used.  My Pro Mini is this one (http://www.ebay.com/itm/271251071444) (at $3.68 shipped, I didn't expect too much.)

By the way, is there a current schematic online for Moteino rev2, if I don't have Eagle installed (eg PDF or PNG format)? The one I found (http://lowpowerlab.com/wp-content/uploads/2012/12/Moteino_schematic.png) does not show the SPI Flash chip.

// Moteino Low-Power Sleep Mode example - J.Beale Oct. 19 2013

#include <SPIFlash.h>
#include <RFM12B.h>
#include <SPI.h>
#include <LowPower.h>

#define SERIAL_BAUD      115200
#define LED  9            // LED is D9 on Motetino
// #define LED  13        // LED is D13 on Arduino Pro Mini

#define NODEID        2  // RFM12b network ID used for this unit
#define NETWORKID    99  // RFM12b network ID we are on

RFM12B radio;        // MOTEINO RFM12B radio object

// Moteino: Flash SPI_CS = 8, ID = 0xEF30 (Winbond 4Mbit flash)
SPIFlash flash(8, 0xEF30); // flash(SPI_CS, MANUFACTURER_ID)

void setup()
{
  Serial.begin(SERIAL_BAUD);
  Serial.print("Start...");

  if (flash.initialize()) {
    Serial.println("Flash Init OK!");
    flash.sleep();          // put flash (if it exists) into low power mode
  } else {
    Serial.println("Flash Init FAIL!");
  }
 
  delay(100);          // wait for serial xmit
  pinMode(LED, OUTPUT);
  digitalWrite(LED,LOW);
 
  radio.Initialize(NODEID, RF12_915MHZ, NETWORKID); // MOTEINO: initialize RFM12B
  radio.Sleep(); // MOTEINO: sleep right away to save power
}

void loop()
{
// Enter power down state for 8 s with ADC and BOD module disabled
// Moteino (with RFM12B, no SPI Flash): 6 uA @ Vin = 5 V, 4 V, and 3.3 V
// with no red power LED, Arduino Pro Mini takes 20 uA @ Vin=4.0, 14 @ 3.3V

    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); 

    digitalWrite(LED,HIGH);    // flash LED for 1 msec (still quite visible)
    delay(1);
    digitalWrite(LED,LOW);
}
Title: Re: Moteino v2 sleep mode: is 0.17 mA at 3.3 Vin about right?
Post by: pko on October 20, 2013, 05:06:13 AM
I think Felix will not mind me posting the PDF for him.
Title: Re: Moteino v2 sleep mode: is 0.17 mA at 3.3 Vin about right?
Post by: jbeale on October 21, 2013, 06:11:54 PM
Thanks PKO, that was exactly what I was looking for. I built my own Moteino-alike using a RFM12B + Arduino Pro Mini. It does work using the Moteino "Send" sketch and a regular Moteino rev2 receiver, however it only works over very short ranges, like 15 feet (when I go any farther than that, I just get "CRC Error").  I may have damaged the RF module by powering from 5V instead of 3.3 V during programming of the Arduino.  I have the same length of antenna wire as the regular device and I assume there is nothing drastically wrong with my connections, or it wouldn't have worked at all.
Title: Re: Moteino v2 sleep mode: is 0.17 mA at 3.3 Vin about right?
Post by: Felix on October 22, 2013, 08:13:17 AM
I never tried to power it from more than 5V but that can't be good... I think the absolute max power in is 3.6V.