Problems with timer libraries and millis(). Can't find right solution.

Hello there, looks like i got problem, i am fighting with that whole day.. I am creating house heating system, controlling by Arduino. My problem is: i have to rule pin from HIGH to LOW, let's say 35 sec. HIGH, and after that 65 sec. LOW (that works if one of ds18b20 reach temperature which i need), i found Metro timer library, it looks fine and works okay,but.. if (kp>23) if (ledMetro.check() == 1) --> that sentence gets me problems, because if kp reaches 23 C i need to get HIGH on pin, but unfortunately i have to wait until ledMetro.check()==1, it's not good for me. Also i tried many other libraries without any luck. Hope you could help me, thank you guys in advance.

Post the code you have now.

#include <Metro.h>
#include <SimpleTimer.h>
#include <OneWire.h>
#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE
#include <DallasTemperature.h>
#include <Math.h>
#define ONE_WIRE_BUS 3
#define LED 13 // Define the led's pin
Metro ledMetro = Metro(75000); 
int state = LOW;


void setup()
{
  
  pinMode(A4, OUTPUT);
  pinMode(A1,OUTPUT);
  pinMode(LED,OUTPUT);
  digitalWrite(LED,state);
  sensors.begin();
  pinMode(13, OUTPUT); 
}  // setup()...




 void loop()
{

  kp = sensors.getTempC (kpp);
  kg = sensors.getTempC (kgg);
  sp = sensors.getTempC (spp);
  sg = sensors.getTempC (sgg);
  ap = sensors.getTempC (app);
  tl = sensors.getTempC (tll);
  sensors.requestTemperatures(); 
  timer.run();

 
 if (kp>21) {
    if (ledMetro.check() == 1) { // this place it's all my problem i guess, because it's starts only when is elapsed.
      if (state==LOW)  { 
        state=HIGH;
        ledMetro.interval (35000);       //
      } 
      else {
        state=LOW;
        ledMetro.interval(40000); // 
      }
      digitalWrite(LED,state);
    }
  }

http://www.arduino.cc/playground/Code/Metro

The Metro library facilitates the implementation of recurring timed events like:

It doesn’t look like this is the appropriate library for you.

It seems like you could use the Blink Without Delay example as the basis for your project. When the temperature exceeds a threshold, turn the pin HIGH, and record when that happened.

Separately, see if its time to turn the pin off (“now” minus “then” is greater than some interval). If so, turn the pin LOW. If the pin is LOW, and you set it LOW, nothing happens, so there is no need to worry about turning the pin off only if it is on.

Thank you, but i can't realize how to set LOW delay time ? Right now it takes the same time ON and the same time OFF for me, i need different times, e.g. 35 sec. HIGH, and 10 sec. LOW.

I did a small class to keep track of elapsed time:

http://www.gammon.com.au/forum/?id=11094

In your main loop you can use an instance of that to keep track of x seconds elapsing, and then a different lot of seconds (if you need) for the next thing you need to do. eg.

if ( heater_on && t1.intervalMs () > 35000L )
 {
  // do something (like turn the heater off)
  t1.reset ();
 }
else if ( !heater_on && t1.intervalMs () > 10000L )
  {
  // do something else (like turn the heater on)
  t1.reset ();
  }

I think i wasn't clear, sorry about that, but my logic of cycle is pulse and pause, eg.: if (temp>21) { digitalWrite (13,HIGH); // let's say high is going to be for 20 sec. and after that it goes LOW for 10sec. digitalWrite (13,LOW); // Pin is the same. } or maybe i didn't realized your option, sorry

Like this:

#include <Elapsed.h>

const unsigned long ON_PERIOD = 20000;  // 20 seconds
const unsigned long OFF_PERIOD = 10000;  // 10 seconds

const byte HEATER_PIN = 13;

void setup() 
{                
  pinMode (HEATER_PIN, OUTPUT);     
  digitalWrite (HEATER_PIN, LOW);  // turn off
}  // end of setup

static Elapsed t1;

int temp = 18;  // read from temperature sensor

void loop() {

  // read temperature here ...

  // now turn heater on if necessary

  if (temp < 21)
  {
    if (digitalRead (HEATER_PIN) == HIGH)  // if already on
    {
      // time up?
      if (t1.intervalMs () > ON_PERIOD)
      {
        digitalWrite (HEATER_PIN, LOW);  // turn off
        t1.reset ();  // reset timer  
      }  // if period up
    }
    else  // not on
    {
      // time up?
      if (t1.intervalMs () > OFF_PERIOD)
      {
        digitalWrite (HEATER_PIN, HIGH);  // turn off
        t1.reset ();  // reset timer  
      }  // if period up
    }

  }  // need to heat up

}  // end of loop

When you first run this the LED on pin 13 stays off (because it is doing the off period). After that it is on for 20 seconds and off for 10 seconds.

ignas: I think i wasn't clear, sorry about that, but my logic of cycle is pulse and pause, eg.: if (temp>21) { digitalWrite (13,HIGH); // let's say high is going to be for 20 sec. and after that it goes LOW for 10sec. digitalWrite (13,LOW); // Pin is the same. } or maybe i didn't realized your option, sorry

That is the wrong way to do it. You need to write your logic as a set of rules (or a state machine) that will always set the system into the proper state, each time it is executed. This means you probably need, at least, a value for when you last changed the high/low setting.

Something like this:

unsigned long lastChange = 0;
bool isHigh = false;
void loop() {
  unsigned long now = millis();
  bool shouldBeHigh = (value() > 23);
  if (shouldBeHigh == isHigh) {
    if (now - lastChange > 100000) {
      lastChange = now - 100000; // make sure to not wrap in error
    }
  }
  else if (shouldBeHigh) {
    if (now - lastChange > TIME_LOW) {
      setValueHigh();
      lastChange = now;
      isHigh = true;
    }
  }
  else {
    if (now - lastChange > TIME_HIGH) {
      setValueLow();
      lastChange = now;
      isHigh = false;
    }
  }
}

This code will make sure that, if the output is low, and the value greater than the threshold, and the output has been low for at least TIME_LOW milliseconds, then the value will be high. Also, if the output is high, and the value is smaller than the threshold, and the output has been high for at least TIME_HIGH milliseconds, then the value will be low.

Often, the problem in programming is not how to write the code, but how to analyze the requirements of the problem you're trying to solve, such that the problem can robustly be translated to code!

Thank you Gammon and other guys for a help, i really appreciate it, you helped me a lot ;)

On a similar note is there a way to play an mp3 off a music shield while blinking led lights at the same time?