Use this forum to chat about hardware specific topics for the ESP8266 (peripherals, memory, clocks, JTAG, programming)

User avatar
By Petervdpol
#37304
martinayotte wrote:Personally, I prefer handling long delays with millis(), especially if I wish to do something else in the loop(), such as watching for incoming TCP connections. So, so you can trigger tasks with code similar to the following :

Code: Select allvoid loop() {
  if (millis() - previous_millis > 600000) { // trigger tasks every 10 mins
    previous_millis = millis();
    // do some task here, or trigger some flags, etc
  }
  else {
    // do something else here, such as checking for incoming connections
  }
}


Thank you for your time, but I am afraid this solution doesn't do the job:

ESP8266_DHT_sensor_MQTT.ino: In function 'void loop()':
ESP8266_DHT_sensor_MQTT:67: error: 'previous_millis' was not declared in this scope
ESP8266_DHT_sensor_MQTT.ino: At global scope:
ESP8266_DHT_sensor_MQTT:77: error: expected unqualified-id before '{' token
'previous_millis' was not declared in this scope
User avatar
By Petervdpol
#37306 Hi GenusKahn,

Thank you for your time, but I am afraid this is not working: when I upload the sketch the ESP doesn't do anything; I have tried three ESP's to make sure. There is no WIFI activity at all. There is a possibly intresting observation: when upload my original sketch the blue LED starts flashing brightly after uploading is ready, and when still connected to the USB-Serial plug, and when the ESP is then connected to the DHT it flashed brightly once on power-up; sending off one reading (I can see the reading coming in on the PI wirt MQTT.fx)

Any ideas?

GengusKahn wrote:Hi there, I have modified the sketch to add a loop timer for 15 Seconds and 15 Minutes these are easily adjusted from the declarations.......
Use one of the sleep modes for a time less than the timer value.....This is not verified in the IDE as I have a different setup.......
My complete sketch using this is on this forum......

Code: Select all#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <DHT.h>

const char* ssid = "Yggdrasil";
const char* password = "XXXXXXXXX";
char* topic_t = "openhab/esp8266-1/temp";
char* topic_h = "openhab/esp8266-1/vocht";
char* server = "192.168.X.X";
String clientName = "esp8266-1";

//time peter, idea taken from https://www.safaribooksonline.com/library/view/arduino-cookbook-2nd/9781449321185/ch12.html
const long oneSecond = 1000;  // a second is a thousand milliseconds
const long oneMinute = oneSecond * 60;
const long fiveMinutes = oneMinute * 5;
//time peter

// Timer ADDED......
// Set time compare to select post rather than delay.......
unsigned long ulMeasDelta_ms;  // Distance to Tweet Time Timer
unsigned long ulNextMeas_ms;   // Holder for the next Tweet Time Value
int loop_timer = 15;           // Set the delay in Seconds for Thingspeak
int tweet_timer = 60;          // The number of 15 second periods to wait before Tweeting
int tweet_count = 0;           // Loop to count thing posts
//............




#define DHTPIN 2 // what pin we're connected to
#define DHTTYPE DHT22 // DHT 11
DHT dht(DHTPIN, DHTTYPE,15);

WiFiClient wifiClient;
PubSubClient client(server, 1883, callback, wifiClient);

void callback(char* topic, byte* payload, unsigned int length) {
// handle message arrived
}

void setup() {
  //ADDED................

  ulMeasDelta_ms = ( (unsigned long) loop_timer * 1000);  // Sample Interval X in Seconds placed above in the declarations....
  ulNextMeas_ms = millis()+ulMeasDelta_ms;
 
  //...............
Serial.begin(115200);
delay(10);
dht.begin();
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

Serial.print("Connecting to ");
Serial.print(server);
Serial.print(" as ");
Serial.println(clientName);


if (client.connect((char*) clientName.c_str())) {
Serial.println("Connected to MQTT broker");
Serial.print("Topic is: ");
Serial.println(topic_t);
Serial.println(topic_h);

}
else {
Serial.println("MQTT connect failed");
Serial.println("Will reset and try again...");
abort();
}
}

void loop()

{
//  ADDED...............
  // Only progress when timer match occurs................
    if (millis()>=ulNextMeas_ms)
  {                                          // 15 Second loop from the declarations above
    ulNextMeas_ms = millis()+ulMeasDelta_ms;


   tweet_count++;
if (tweet_count==tweet_timer){               // 15 Minute loop from the declarations above
   tweet_count=0;
   

//.............


float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t)) {
Serial.println("Failed to read from DHT sensor!");
return;
}

static int counter = 0;
String payload ;
payload += t;
//payload += ":";
//payload += h;
String payloadh ;
payloadh += h;

if (client.connected()){
Serial.print("Sending payload: ");
Serial.println(payload);

if (client.publish(topic_t, (char*) payload.c_str()))
{
Serial.println("Publish ok");
}
else {
Serial.println("Publish failed");
}

//peter
if (client.connected()){
Serial.print("Sending payload: ");
Serial.println(payloadh);

if (client.publish(topic_h, (char*) payloadh.c_str()))
{
Serial.println("Publish ok");
}
else {
Serial.println("Publish failed");
}}
//peter


}
else {
if (client.connect((char*) clientName.c_str())) {
Serial.println("Connected to MQTT broker");
Serial.print("Topic is: ");
Serial.println(topic_t);
Serial.println(topic_h);

}
}
// delay (20000); //WORKS FINE
// delay(5*60*1000); //STOPS AFTER FIRST READING AT STARTUP
//delay(fiveMinutes); // STOPS AFTER FIRST READING AT STARTUP
    }// 15 Minute Loop Timer
  }//   15 Second Loop Timer
}


My sketch has been running for some time and only network issues force a reboot.....

https://twitter.com/ddtmonitor

This is some messing with home made MPU 10 DOF....
https://twitter.com/mcuautomation

Image
User avatar
By Petervdpol
#37308 Well, since I am a NOOB, you must be mighty... Can you give me a hint how to work your code in mine? Depending where I place it I get errors regarding a " { " (at the top) or at the bottom I get a remark that " MinuteDelay" was not declared in this scope...

DrG wrote:Hi Petervdpol,

Not sure that I am 'mighty' but I think that I might be able to suggest something to try. Take a look at the reference doc for the ArduinoIDE here https://github.com/esp8266/Arduino/blob ... and-delays. The basic idea that I get from the section on Timing and Delays is that there are a lot of functions on the chip (since it is a System On Chip [SoC]) that need to be addressed at variable times - especially when wireless and TCP are going on. When you sit in a delay loop, you can't get to the tasks and when the delay loop is too long, you crash. In your case, you are finding that out after about 24 seconds.

Try to break up a long delay into shorter delays. When leaving each of those short delays, housekeeping will have a chance to address some matters.

Take a look at this code and give it a try. I have created a function that delays for the number of minutes in the argument. You should have no problem getting delays of 20 min or more - BUT there is no WiFi going on in that fragment, it is just to illustrate the approach. This may help and you may need to adjust the "inside" delay to make it even shorter to keep everything running. I commented out the yield() command, you can put it back in if you want, it might help also.

Code: Select allvoid setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
}

void loop() {
   Serial.println();
   Serial.print("1 min delay ");
   MinuteDelay(1);
   Serial.println();
   Serial.print("5 min delay ");
   MinuteDelay(5);
   Serial.println();
   Serial.print("10 min delay ");
   MinuteDelay(10);
   Serial.println();
   Serial.print("20 min delay ");
   MinuteDelay(20);
   Serial.println();
}

void MinuteDelay(int number){
  for (int i = 0; i < number; ++i)
    {
     
      // use 6 10 second delays for each minute // with a yield before each
      for(int j=0; j<6 ;j++)
      {
        Serial.print("*");
        // yield();
        delay(10000);
       
      }
    }
  }


The best way of doing what you want, however, may be to put the ESP to sleep so that it uses very little power and then have it wake up after a delay. That is a little more complicated but if you search on this board and elsewhere you will see how this can be done.

Let us know how it turns out,

Cheers,

DrG
User avatar
By GengusKahn
#37315 Hi there, I did not remove the original text, just use the "added" sections for timing, and as suggested if a timer is used to "wake" from sleep, adjust the loop timing...

Here is the adjusted 20 Minute loop timer....no delays but will cope with delays etc elsewhere as the timer compare is >=......

Code: Select all
unsigned long ulMeasCount=0;                                        // values for counted loops
unsigned long ulMeasDelta_ms;                                       // ms value to next loop time
unsigned long ulNextMeas_ms;                                        // ms value next loop match time


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  ulMeasDelta_ms = ( (unsigned long) 60 * 1000);  // Sample Interval 60 Seconds, this can be placed above in the declarations....
  ulNextMeas_ms = millis()+ulMeasDelta_ms;
  Serial.println();
  Serial.println("20 min delay Starting..................");
}

void loop() {
  if (millis()>=ulNextMeas_ms)
  { 
   ulMeasCount++;
   ulNextMeas_ms = millis()+ulMeasDelta_ms;
   Serial.print(ulMeasCount);
   Serial.println(" min elapsed ");   
  if (ulMeasCount==1){
   Serial.println();
   Serial.print("1 min delay ");
  }else if (ulMeasCount==5){
   Serial.println();
   Serial.print("5 min delay ");
  }else if (ulMeasCount==10){
   Serial.println();
   Serial.print("10 min delay ");
  }else if(ulMeasCount==20){
   Serial.println();
   Serial.print("20 min delay Restting");
   Serial.println();
   ulMeasCount=0;  // this will reset the loop again to start the one minute timer
  }
 }
}