How to use multiple timers?

How can I use a different timer in each interrupt?

I followed a tutorial on using the <TimerOne.h> library but i'm not able to add another timer. Should I be using a different library?
Im making an automated green house, this is what I have so far. With timer2 my goal is to turn the light on for 12 hours and off for 12 hours.
Im using an Arduino mega.

#include <TimerOne.h>
//Soil moisture sensor and pumps
const int dry = 455;
const int wet = 164;
int pump1 = 6;
int pump2 = 7;
int soilMoisturePercentage;
int soilMoisture = "OFF";
//light
int light = 2;
int lightOnOrOff = "OFF";
const int systemOn = "ON";

#define active_Low;

void setup() {
  Serial.begin(9600);
  pinMode(light, OUTPUT);
  pinMode(pump1, OUTPUT);
  pinMode(pump2, OUTPUT);
  Timer1.initialize(1000000);
  Timer1.attachInterrupt(checkSoil);
  Timer2.initialize();
  Timer2.attachInterrupt(checkLight);
}

void loop() {
  int sensorVal = analogRead(A0);
  int soilMoisturePercentage = map(sensorVal, wet, dry, 100, 0);
  Serial.print(soilMoisturePercentage);
  Serial.println("%");
  
  if(soilMoisturePercentage <=35){
  soilMoisture = "ON";
}

  
} 
void checkSoil(){
  if(soilMoisture == "ON"){
    digitalWrite(pump1, LOW);
    soilMoisture = "OFF";
    return;
  }
  if(soilMoisture == "OFF"){
    digitalWrite(pump1, HIGH);
    return;
  }

}


That is seriously misguided. Timers are not designed for such long intervals. Timer0 on the AVR is already used to clock the millis() and micros() functions, and those are what you should use for an application like that. Or even, an RTC, since if you lose power, you lose track of CPU time.

2 Likes

These statements are very odd. They will set the variables to integer-cast pointers to the strings,

You should use true/false, a code like 1 or 0, or define some constants like

const byte ON = 1;
const byte OFF = 0;

int lightOnOrOff = OFF;
const int systemOn = ON;

For multiple timers, look into Demonstration code for several things at the same time , https://docs.arduino.cc/built-in-examples/digital/BlinkWithoutDelay , Now for two at once | Multi-tasking the Arduino - Part 1 | Adafruit Learning System or Flashing multiple LEDs at the same time

You might try wrapping the stuff in your multiple timers, along with the contents of your loop in a rate-limiting millis() functions like:

int checkMoisture(void) {
  int retval = false; // for one-shot actions like if(checkDiurnal()){...}
  static unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  unsigned interval = 500;
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    int sensorVal = analogRead(A0);
    int soilMoisturePercentage = map(sensorVal, wet, dry, 100, 0);
    Serial.print(soilMoisturePercentage);
    Serial.println("%");

    if (soilMoisturePercentage <= 35) {
      soilMoisture = "ON";
    }
    return retval;
  }
}

// or 

int checkDiurnal(void) {
  int retval = false; // for one-shot actions like if(checkDiurnal()){...}
  static unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  unsigned interval = 1000UL * 3600 * 12; // 12 hours worth of milliseconds
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    retval = true;
    //checkMoisture();
    checkSoil();  // changes the pump appropriately
    // other stuff that needs doing every 12 hours
  }
  return retval;
}

... then your loop can quickly run through a checklist and does what needs doing:

void loop() {
  //  int sensorVal = analogRead(A0);
  //int soilMoisturePercentage = map(sensorVal, wet, dry, 100, 0);
  //  Serial.print(soilMoisturePercentage);
  //  Serial.println("%");

  //  if(soilMoisturePercentage <=35){
  //  soilMoisture = "ON";

  checkMoisture();  // replace the above with a rate-limited millis() function
  if(checkDiurnal()){
     Serial.print("Diurnal one-shot is happening");
     //... other stuff
  }
}

1 Like

I just watched this video, is this what your talking about?

What about pump2? I only want that to be on for a few seconds, would i still use Timer0, timer1, or Timer2?

I'm trying to get away from using the delay function in my code.

Yeah I got errors and thought those might fix it. It didn't.

Thank you for this information! Im going to need to do more reading to better understand but thank you for putting me on the right path

[quote="DaveX, post:3, topic:1108621"]

int checkMoisture(void) {
  int retval = false; // for one-shot actions like if(checkDiurnal()){...}
  static unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  unsigned interval = 500;
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    int sensorVal = analogRead(A0);
    int soilMoisturePercentage = map(sensorVal, wet, dry, 100, 0);
    Serial.print(soilMoisturePercentage);
    Serial.println("%");

    if (soilMoisturePercentage <= 35) {
      soilMoisture = "ON";
    }
    return retval;
  }
}

Why did you write " int checkDiurnal(void)" instead of " void checkDiurnal"?

That is another reason to not use timers. millis() and micros() have almost no limit of the number of things you can time using them. You could time 200 pumps if you like.

Please follow the links that @DaveX posted.

1 Like

Oops -- my intention was to set the return value to true, so that one could use the timer as a flag for a test whether the routine did anything or whether it did nothing because it was too soon.

int checkMoisture(void) {
  int retval = false; // for one-shot actions like if(checkDiurnal()){...}
  static unsigned long previousMillis = 0;
  unsigned long currentMillis = millis();
  unsigned interval = 500;
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    retval = true;
    int sensorVal = analogRead(A0);
    int soilMoisturePercentage = map(sensorVal, wet, dry, 100, 0);
    Serial.print(soilMoisturePercentage);
    Serial.println("%");

    if (soilMoisturePercentage <= 35) {
      soilMoisture = "ON";
    }
  }
  return retval;
}

so in loop you could count cycles or send a message, or whatever with:

void loop(){
   ...
   if(checkMoisture()){
      Serial.print("Moisture checked");
   }
   ...
}

Code like the Arduino PID_v1 uses that trick on it's PID::calculate() method so you can act on adjustments only when they update.

A simple 12 hour ON, 12 hour OFF millis() timer.

unsigned long  lightTimer,
               cycleTime = 86400000,  // 24 hours in milliseconds
               onInterval = 43200000; // 12 hours in milliseconds
const byte lightPin = 2; // output pin for light


void setup()
{
  //Serial.begin(9600);
  pinMode(lightPin,OUTPUT);
}

void loop()
{
  if(millis() - lightTimer >= cycleTime) // 24 hours
    lightTimer += cycleTime; // reset timer
  digitalWrite(lightPin,millis() - lightTimer < onInterval); //12 hours 

}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.