Created
January 2, 2016 11:40
-
-
Save shirish47/e48284eb0c6ff5593935 to your computer and use it in GitHub Desktop.
trying the sleep or standby current measurment of nrf24l01+ modules
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright (C) 2011 J. Coliz <[email protected]> | |
This program is free software; you can redistribute it and/or | |
modify it under the terms of the GNU General Public License | |
version 2 as published by the Free Software Foundation. | |
TMRh20 2014 - Updates to the library allow sleeping both in TX and RX modes: | |
TX Mode: The radio can be powered down (.9uA current) and the Arduino slept using the watchdog timer | |
RX Mode: The radio can be left in standby mode (22uA current) and the Arduino slept using an interrupt pin | |
*/ | |
/** | |
* Example RF Radio Ping Pair which Sleeps between Sends | |
* | |
* This is an example of how to use the RF24 class to create a battery- | |
* efficient system. It is just like the GettingStarted_CallResponse example, but the | |
* ping node powers down the radio and sleeps the MCU after every | |
* ping/pong cycle, and the receiver sleeps between payloads. | |
* | |
* Write this sketch to two different nodes, | |
* connect the role_pin to ground on one. The ping node sends the current | |
* time to the pong node, which responds by sending the value back. The ping | |
* node can then see how long the whole cycle took. | |
*/ | |
#include <SPI.h> | |
#include <avr/sleep.h> | |
#include <avr/power.h> | |
#include "nRF24L01.h" | |
#include "RF24.h" | |
#include "printf.h" | |
// Set up nRF24L01 radio on SPI bus plus pins 7 & 8 | |
RF24 radio(5,6); | |
// sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver | |
// Leave open to be the 'ping' transmitter | |
//const int role_pin = 5; | |
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; // Radio pipe addresses for the 2 nodes to communicate. | |
// Role management | |
// Set up role. This sketch uses the same software for all the nodes | |
// in this system. Doing so greatly simplifies testing. The hardware itself specifies | |
// which node it is. | |
// The various roles supported by this sketch | |
typedef enum { role_ping_out = 1, role_pong_back } role_e; | |
// The debug-friendly names of those roles | |
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"}; | |
// The role of the current running sketch | |
role_e role; | |
// Sleep declarations | |
typedef enum { wdt_16ms = 0, wdt_32ms, wdt_64ms, wdt_128ms, wdt_250ms, wdt_500ms, wdt_1s, wdt_2s, wdt_4s, wdt_8s } wdt_prescalar_e; | |
void setup_watchdog(uint8_t prescalar); | |
void do_sleep(void); | |
const short sleep_cycles_per_transmission = 4; | |
volatile short sleep_cycles_remaining = sleep_cycles_per_transmission; | |
void setup(){ | |
// set up the role pin | |
pinMode(4, OUTPUT); | |
digitalWrite(4,LOW); | |
delay(20); // Just to get a solid reading on the role pin | |
// read the address pin, establish our role | |
// if ( digitalRead(role_pin) ) | |
// role = role_ping_out; | |
// else | |
role = role_pong_back; | |
Serial.begin(115200); | |
printf_begin(); | |
Serial.print(F("\n\rRF24/examples/pingpair_sleepy/\n\rROLE: ")); | |
Serial.println(role_friendly_name[role]); | |
// Prepare sleep parameters | |
// Only the ping out role uses WDT. Wake up every 4s to send a ping | |
//if ( role == role_ping_out ) | |
setup_watchdog(wdt_4s); | |
// Setup and configure rf radio | |
radio.begin(); | |
// Open pipes to other nodes for communication | |
// This simple sketch opens two pipes for these two nodes to communicate | |
// back and forth. | |
// Open 'our' pipe for writing | |
// Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading) | |
if ( role == role_ping_out ) { | |
radio.openWritingPipe(pipes[0]); | |
radio.openReadingPipe(1,pipes[1]); | |
} else { | |
radio.openWritingPipe(pipes[1]); | |
radio.openReadingPipe(1,pipes[0]); | |
} | |
// Start listening | |
radio.startListening(); | |
// Dump the configuration of the rf unit for debugging | |
//radio.printDetails(); | |
} | |
void loop(){ | |
if (role == role_ping_out) { // Ping out role. Repeatedly send the current time | |
radio.powerUp(); // Power up the radio after sleeping | |
radio.stopListening(); // First, stop listening so we can talk. | |
unsigned long time = millis(); // Take the time, and send it. | |
Serial.print(F("Now sending... ")); | |
Serial.println(time); | |
radio.write( &time, sizeof(unsigned long) ); | |
radio.startListening(); // Now, continue listening | |
unsigned long started_waiting_at = millis(); // Wait here until we get a response, or timeout (250ms) | |
bool timeout = false; | |
while ( ! radio.available() ){ | |
if (millis() - started_waiting_at > 250 ){ // Break out of the while loop if nothing available | |
timeout = true; | |
break; | |
} | |
} | |
if ( timeout ) { // Describe the results | |
Serial.println(F("Failed, response timed out.")); | |
} else { | |
unsigned long got_time; // Grab the response, compare, and send to debugging spew | |
radio.read( &got_time, sizeof(unsigned long) ); | |
printf("Got response %lu, round-trip delay: %lu\n\r",got_time,millis()-got_time); | |
} | |
// Shut down the system | |
delay(500); // Experiment with some delay here to see if it has an effect | |
// Power down the radio. | |
radio.powerDown(); // NOTE: The radio MUST be powered back up again manually | |
// Sleep the MCU. | |
do_sleep(); | |
} | |
// Pong back role. Receive each packet, dump it out, and send it back | |
if ( role == role_pong_back ) { | |
if ( radio.available() ) { // if there is data ready | |
unsigned long got_time; | |
while (radio.available()) { // Dump the payloads until we've gotten everything | |
radio.read( &got_time, sizeof(unsigned long) ); // Get the payload, and see if this was the last one. | |
// Spew it. Include our time, because the ping_out millis counter is unreliable | |
printf("Got payload %lu @ %lu...",got_time,millis()); // due to it sleeping | |
} | |
radio.stopListening(); // First, stop listening so we can talk | |
radio.write( &got_time, sizeof(unsigned long) ); // Send the final one back. | |
Serial.println(F("Sent response.")); | |
radio.startListening(); // Now, resume listening so we catch the next packets. | |
} else { | |
Serial.println(F("Sleeping")); | |
delay(50); // Delay so the serial data can print out | |
do_sleep(); | |
} | |
} | |
} | |
void wakeUp(){ | |
sleep_disable(); | |
} | |
// Sleep helpers | |
//Prescaler values | |
// 0=16ms, 1=32ms,2=64ms,3=125ms,4=250ms,5=500ms | |
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec | |
void setup_watchdog(uint8_t prescalar){ | |
uint8_t wdtcsr = prescalar & 7; | |
if ( prescalar & 8 ) | |
wdtcsr |= _BV(WDP3); | |
MCUSR &= ~_BV(WDRF); // Clear the WD System Reset Flag | |
WDTCSR = _BV(WDCE) | _BV(WDE); // Write the WD Change enable bit to enable changing the prescaler and enable system reset | |
WDTCSR = _BV(WDCE) | wdtcsr | _BV(WDIE); // Write the prescalar bits (how long to sleep, enable the interrupt to wake the MCU | |
} | |
ISR(WDT_vect) | |
{ | |
//--sleep_cycles_remaining; | |
Serial.println(F("WDT")); | |
} | |
void do_sleep(void) | |
{ | |
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here | |
sleep_enable(); | |
attachInterrupt(1,wakeUp,LOW); | |
WDTCSR |= _BV(WDIE); | |
sleep_mode(); // System sleeps here | |
// The WDT_vect interrupt wakes the MCU from here | |
sleep_disable(); // System continues execution here when watchdog timed out | |
detachInterrupt(1); | |
WDTCSR &= ~_BV(WDIE); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment