gw.sleep isn't very accurate on a Pro Mini 3.3V (8Mhz)


  • Contest Winner

    Last week a ran into my first 8Mhz problem (see http://forum.mysensors.org/topic/1894/pro-mini-is-giving-a-frequent-time-out-on-dth11-read-out). But thanx to the kind people on this forum that problem is solved.

    Now I have another question. I've noticed that my gw.sleep on that same Arduino (mini Pro 3.3V 8Mhz) is far from accurate. If I let the arduino sleep for 900000 milli seconds, I would expect 15 minutes, but it's usually around 16 or 17 minutes (I can monitor that on Domoticz). The longer I let my Arduino sleep the bigger the difference becomes. I have one Soil Moisture sensor that is battery powered (2 AA), that should sleep for 30 minutes. But it's more often 45 minutes or more.

    It might be a hardware problem, I'm not sure. But could it possible that gw.sleep uses 16Mhz timing, which could explain the incorrect sleeping time? Otherwise I have no clue what could be wrong. Here's the sketch that is currently running on a battery powered Pro Mini 3.3V.

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * 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.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Henrik EKblad
     * 
     * DESCRIPTION
     * This sketch provides an example how to implement a humidity/temperature
     * sensor using DHT11/DHT-22 
     * http://www.mysensors.org/build/humidity
     */
     
    /**
      * Include necessary libraries
      */
     
    #include <SPI.h>
    #include <MySensor.h>  
    #include <dht8mf.h>  
    
    /*
     * Define sketch constants
     */
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define DHT11_PIN 3
    #define BATTERY_MEASURE_CYCLE 48 // every 12 hours. Just for test purposes.
    #define BATTERY_SENSE_PIN  A2 // determine battery percentage an A2
    #define SENSOR_READING_DELAY  2000
    unsigned long SLEEP_TIME = 900000;  // check every 15 minutes angd go back to sleep.
    
    MySensor gw;
    dht8mf dht;
    double lastTemp;
    double lastHum;
    int oldBatteryPcnt = 0;
    int batteryCycleCounter = BATTERY_MEASURE_CYCLE; // Send the status at the first cycle
    
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    
    /**
     * Sketch initialization code
     */
    void setup()  { 
       // use the 1.1 V internal reference
    #if defined(__AVR_ATmega2560__)
       analogReference(INTERNAL1V1);
    #else
       analogReference(INTERNAL);
    #endif  
      gw.begin(); // Initialize MySensor for communication with gate way
    
      // Send the Sketch Version Information to the Gateway
      gw.sendSketchInfo("Basic roomsensor", "1.0");
    
      // Register all sensors to gw (they will be created as child devices)
      gw.present(CHILD_ID_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
    }
    
    /**
     * Read temperature and hummidity from sensor. Report values to gateway if the
     * differ from last reading.
     */
    void readDHT() {
      delay( SENSOR_READING_DELAY ); // Wait the minimum ammout off time, so that DHT will give good reading
      int dhtStatus = dht.read11( DHT11_PIN ); // Change the method to your sensor see dht.h file
      if ( dhtStatus == DHTLIB_OK ) { // Check if Sensor readings are okay
          if (dht.temperature != lastTemp) {
            lastTemp = dht.temperature;
            gw.send(msgTemp.set(dht.temperature, 1));
          }
          if (dht.humidity != lastHum) {
            lastHum = dht.humidity;
            gw.send(msgHum.set(dht.humidity, 1));
          }
      }
    }
    
    void checkBatteryLevel() {
      if ( batteryCycleCounter == BATTERY_MEASURE_CYCLE ) {
        delay(100); // wait a while so that the analog pins can stabelize before reading.
    
        // get the battery Voltage
        int sensorValue = analogRead( BATTERY_SENSE_PIN );
        int batteryPcnt = sensorValue / 10;
    
        if (oldBatteryPcnt != batteryPcnt) {
          gw.sendBatteryLevel(batteryPcnt);
          oldBatteryPcnt = batteryPcnt;
        }
        batteryCycleCounter = 1;
      }
      batteryCycleCounter++;
    }
    
    void loop() {
      readDHT();
      checkBatteryLevel();
      gw.sleep(SLEEP_TIME); //sleep a bit
    }
    

    Just to be sure that it's not the battery power causing the problem, I hooked up the arduino through fdti to my computer. But that gives the same result. The arduino is sleeping much longer than instructed to 🙂

    The <dht8mf.h> library is just the DHT library from the Arduino website. I refactored the name to DHT8Mhz Friendly.



  • I had a sensebender hooked up to a ftdi serial adapter and monitored the serial log for over a week (I was trying to capture rerouting issues). The sketch had the sensor gw.sleep for 60 seconds between readings and I noticed it actually took 62-63 seconds between readings. I assumed it was due to time to initialize the SI7021 and/or radio but that seems a little long for that.


  • Admin

    Sleeping is done in 8sec cycles. Not sure how much re-sleeping takes but during one minute it wakes up 7 times and goes back to sleep.

    3 seconds sounds like a big readout time. @tbowmo, could usage of the internal oscillator affect sleep-time on the sensebender?


  • Admin

    When sleeping, the internal watchdog timer is used to wakeup the MCU again. This runs off a 128Khz oscillator, which is highly dependent on both temperature and voltage.

    See page 605 in the datasheet for the atmega (Figure 35-36).

    Looking at the graph, 3V @25 degrees celcius, the oscillator runs at approximately 116Khz, which gives a sleep time of 9 seconds, instead of 8 seconds.

    sleep time calculated as follows:

    1/(116000/1048576) = 9,039 seconds. (1048576 = 1024 x 1024, which is the clock divider used when sleeping "8" seconds).


  • Admin

    Thanks for the explanation! Makes sense now.



  • I noticed the same issue. My programmed sleep-time is 5 min, but the sensors actually sleeps for about 5:25. First I thought it has to do with the 8s-cycle, but the explaination of @tbowmo seems to be the answer.
    Thank you!


  • Admin

    btw. This sleep time, is independent of the oscillator used to run the MCU (8Mhz / 1Mhz). As the watchdog has it's own oscillator.


Log in to reply
 

Suggested Topics

  • 3
  • 2
  • 4
  • 2
  • 15
  • 3

18
Online

11.2k
Users

11.1k
Topics

112.5k
Posts