Project

General

Profile

Resolved: Sleepy problem

Added by zooto68 over 4 years ago

I’ve got a problem using the Sleep functions. I have uploaded the following code to an Atmega328p and instead of it sleeping every 60000ms in between transmissions it transmits roughly every 5-6 seconds. Any idea what I may be doing wrong please?

// Sensor Node Transmitter - Mike McRoberts

#define RF69_COMPAT 1  
#include   //from jeelabs.org
#include 
#include "HTU21D.h"

ISR(WDT_vect) { Sleepy::watchdogEvent(); } // interrupt handler for JeeLabs Sleepy power saving

//Create an instance of the object
HTU21D myHumidity;

#define nodeID 1          //node ID of tx (range 0-30)
#define nodeGroup 100      //network group (can be in the range 1-250).
#define nodeFreq RF12_433MHZ     //Freq of RF12B can be RF12_433MHZ, RF12_868MHZ or RF12_915MHZ. Match freq to module
#define nodeURN 0xB6A3E25C

#define USE_ACK           // Enable ACKs, comment out to disable
#define RETRY_PERIOD 5    // How soon to retry (in seconds) if ACK didn't come in
#define RETRY_LIMIT 5     // Maximum number of times to retry
#define ACK_TIME 10       // Number of milliseconds to wait for an ack

// create structure - a neat way of packaging data for RF comms
typedef struct { 
  long URN; 
  long battery; 
  float temperature, humidity; 
} PacketTX;      
PacketTX dataPacket; 

// Wait a few milliseconds for proper ACK
 #ifdef USE_ACK
  static byte waitForAck() {
   MilliTimer ackTimer;
   while (!ackTimer.poll(ACK_TIME)) {
     if (rf12_recvDone() && rf12_crc == 0 &&
        rf12_hdr == (RF12_HDR_DST | RF12_HDR_CTL | nodeID))
        return 1;
     }
   return 0;
  }
 #endif

//--------------------------------------------------------------------------------------------------
// Send payload data via RF
//-------------------------------------------------------------------------------------------------
 static void rfwrite(){
  #ifdef USE_ACK
   for (byte i = 0; i <= RETRY_LIMIT; ++i) {  // tx and wait for ack up to RETRY_LIMIT times
     rf12_sleep(-1);              // Wake up RF module
      while (!rf12_canSend())
      rf12_recvDone();
      rf12_sendStart(RF12_HDR_ACK, &dataPacket, sizeof dataPacket); 
      rf12_sendWait(2);           // Wait for RF to finish sending while in standby mode
      byte acked = waitForAck();  // Wait for ACK
      rf12_sleep(0);              // Put RF module to sleep
      if (acked) { return; }      // Return if ACK received

   Sleepy::loseSomeTime(RETRY_PERIOD * 1000);     // If no ack received wait and try again
   }
  #else
     rf12_sleep(-1);              // Wake up RF module
     while (!rf12_canSend())
     rf12_recvDone();
     rf12_sendStart(0, &dataPacket, sizeof dataPacket); 
     rf12_sendWait(2);           // Wait for RF to finish sending while in standby mode
     rf12_sleep(0);              // Put RF module to sleep
     return;
  #endif
 }

//--------------------------------------------------------------------------------------------------
// Read current supply voltage
//--------------------------------------------------------------------------------------------------
 long readVcc() {
   bitClear(PRR, PRADC); ADCSRA |= bit(ADEN); // Enable the ADC
   long result;
   // Read 1.1V reference against Vcc
   #if defined(__AVR_ATtiny84__) 
    ADMUX = _BV(MUX5) | _BV(MUX0); // For ATtiny84
   #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);  // For ATmega328
   #endif 
   delay(2); // Wait for Vref to settle
   ADCSRA |= _BV(ADSC); // Convert
   while (bit_is_set(ADCSRA,ADSC));
   result = ADCL;
   result |= ADCH<<8;
   result = 1126400L / result; // Back-calculate Vcc in mV
   ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power
   return result;
} 


void setup() {
  rf12_config();
  rf12_sleep(0);      // Put the RFM12 to sleep
  myHumidity.begin();
  Serial.begin(19200);

  Serial.println("Sensor Node Transmit");

  PRR = bit(PRTIM1); // only keep timer 0 going

  ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power
}

void loop() {

  dataPacket.URN = nodeURN;
  dataPacket.humidity = myHumidity.readHumidity();
  dataPacket.temperature =  myHumidity.readTemperature();
  //Serial.print(dataPacket.temperature); Serial.println(" C");
  //Serial.print(dataPacket.humidity); Serial.println(" %");

  //Battery readings
  dataPacket.battery = readVcc(); // Get supply voltage

  //Serial.print("Transmitting.."); 

  rfwrite(); // Send data via RF 
  //Serial.println("Sent."); 

  Sleepy::loseSomeTime(60000); //JeeLabs power save function: enter low power mode for 60 seconds (valid range 16-65000 ms)

}

Thanks,

Mike


Replies (3)

RE: Sleepy problem - Added by martynj over 4 years ago

Perhaps check the loseSomeTime() return value in case some other interrupt is coming in?

// Spend some time in low-power mode, the timing is only approximate.
// @param msecs Number of milliseconds to sleep, in range 0..65535.
// @returns 1 if all went normally, or 0 if some other interrupt occurred

RE: Sleepy problem - Added by JohnO over 4 years ago

Is the code receiving the ACK ? If not then it resends every 5 seconds:

   Sleepy::loseSomeTime(RETRY_PERIOD * 1000);     // If no ack received wait and try again

RE: Sleepy problem - Added by zooto68 over 4 years ago

You were right. It wasn’t receiving the ACKs back. Fixed it now. Thanks.

    (1-3/3)