gw.sleep isn't very accurate on a Pro Mini 3.3V (8Mhz)
-
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.
-
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?
-
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).
-
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!
-
btw. This sleep time, is independent of the oscillator used to run the MCU (8Mhz / 1Mhz). As the watchdog has it's own oscillator.