controlling a machine

Hi there,

I want to control a machine at home but i am struggling with the simpletimer library, the time used is not constant when the machine must restart after an alarm has been resolved.
How can I retrigger a timer so that it starts from zero or doe i have too use something else.
These are my first steps in the wiring language and i still cant get this fixed after 3 days :-[thanks in advance.

#include <SimpleTimer.h>
#include <SimpleTimer.ccp>
// There must be one global SimpleTimer object.
// More SimpleTimer objects can be created and run,
// although there is little point in doing so.
SimpleTimer timer;

boolean hpOk= 2;      //high pressure ok
boolean lpOk= 3;      //low pressure ok
boolean clockOk= 4;   //its time to start
boolean thermOk= 5;   //heat wanted
boolean startOk;     //ready to go
int startCase = 0;   //startchoices
int alarmCase = 0;   //alarm choices
int T1 = 0;


void RepeatTask(){
 digitalWrite(13, HIGH); //timer set pin 13
}

void setup(){
  
  pinMode(hpOk, INPUT);    //hp
  pinMode(lpOk, INPUT);    //lp
  pinMode(clockOk, INPUT);    //clock
  pinMode(thermOk, INPUT);    //therm
  pinMode(9, OUTPUT);   //alarm signal hp
  pinMode(10, OUTPUT);  //alarm signal lp
  //pinMode(11, OUTPUT);
  // pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);    //start
  
 timer.setInterval(50000, RepeatTask); 
 
}
  

void alarm(){
  
   if (hpOk == LOW && lpOk == HIGH && clockOk == HIGH && thermOk == HIGH) {alarmCase = 1;}
   if (hpOk == HIGH && lpOk == LOW && clockOk == HIGH && thermOk == HIGH) {alarmCase = 2;} 
   if (hpOk == LOW && lpOk == LOW && clockOk == HIGH && thermOk == HIGH) {alarmCase = 3;}
   if (hpOk == HIGH && lpOk == HIGH && clockOk == LOW && thermOk == HIGH) {alarmCase = 4;}
   if (hpOk == HIGH && lpOk == HIGH && clockOk == HIGH && thermOk == LOW) {alarmCase = 5;}
   if (hpOk == HIGH && lpOk == HIGH && clockOk == LOW && thermOk == LOW) {alarmCase = 6;}
  
     switch(alarmCase){
       case 1:
        T1 = 100;
       break;
       case 2:
        T1 = 200;
       break;
       case 3:
        T1 = 400;
       break;
       case 4:
        T1 = 1000;
       break;
       case 5:
        T1 = 1000;
       break;
       case 6:
        T1 = 2000;
       break;
  } 
          digitalWrite(10, HIGH);
            delay(T1);
           digitalWrite(10, LOW);
          delay(T1);
}

void loop(){ 
  
   hpOk=digitalRead(2);
   lpOk=digitalRead(3);
   clockOk=digitalRead(4);
   thermOk=digitalRead(5);
  
 if (hpOk==HIGH && lpOk==HIGH && clockOk==HIGH && thermOk==HIGH){startOk=HIGH;}
    else{startOk=LOW;}
    
    if (startOk==0){startCase = 1;}
    if (startOk==1){startCase = 2;}
  
    switch(startCase){
      case 1:
        digitalWrite(13, LOW);
        alarm();
        break;
      case 2:
        timer.run();
        break;
    }
        
}

The code above works except the time.

greetings,
Chris

This

boolean hpOk=2;      //high pressure ok
boolean lpOk=3;      //low pressure ok
boolean clockOk=4;   //its time to start
boolean thermOk=5;   //heat wanted

isn't your problem, but you're confusing pin numbers with the values read back from them.

Most of these probably don't need to be global, either.

The code above works except the time.

So...it doesn't work.

What do you think performs as you expect (aka "works"), and what doesn't perform as you expect...and what do you expect?

Hi AWOL,

I don't understand First of all this piece of code

boolean hpOk=2;      //high pressure ok
boolean lpOk=3;      //low pressure ok
boolean clockOk=4;   //its time to start
boolean thermOk=5;   //heat wanted

these are all physical contacts from the machine to the arduino I have a high and low pressure switch, and also a external clock with thermostat. This code isn't finished yet, i need this at other locations(i think) :-?

I updated the code with the latest version

greetings, Chris

these are all physical contacts from the machine to the arduino

It's odd that the values you're assigning to the 'boolean's (we'll come back to that later) appear to match the pin numbers you use later in the corresponding "digitalRead"s.

'boolean' normally implies 'true' or 'false'. These are normally represented by the values 1 and 0 respectively.

boolean hpOk= 2;      //high pressure ok
...
  pinMode(hpOk, INPUT);    //hp
... 
   if (hpOk == LOW && lpOk == HIGH && clockOk == HIGH && thermOk == HIGH) {alarmCase = 1;}
...
   hpOk=digitalRead(2);

Confusing, isn't it?

(also confusing is going back and editing code people have already commented on)

(also confusing is going back and editing code people have already commented on)

You are right, I Will never do that again

The good news is, i have been reading about timer interrupts and copy/pasted an examlpe in my program and it works now
I also adjusted the booleans, i hope it is better now :slight_smile:

#include <avr/interrupt.h>
//#include <SimpleTimer.h>
//#include <SimpleTimer.ccp>
// There must be one global SimpleTimer object.
// More SimpleTimer objects can be created and run,
// although there is little point in doing so.
//SimpleTimer timer;

boolean hpOk;      //high pressure ok
boolean lpOk;      //low pressure ok
boolean clockOk;   //its time to start
boolean thermOk;   //heat wanted
boolean waterOk;
boolean startOk;     //ready to go
boolean startOk2;    //start compressor
int startCase = 0;   //startchoices
int alarmCase = 0;   //alarm choices
int T1 = 0;
int int_counter = 0;
volatile int second = 0;
int oldSecond = 0;
float value;

// Interrupt routine
ISR(TIMER2_OVF_vect) {                  // Interrupt Service routine: called when timer is overflowed (turns from 0xff to 0x00)                  
  int_counter += 1;
  TCNT2 = 0;                            // Initial count of timer (could be changed in range 1-254)
  if (int_counter == 61) {              // after one second change value of variable of second
    second+=1;
    int_counter = 0;
  }
};


//void RepeatTask(){
 //digitalWrite(13, HIGH); //timer set pin 13
//}

void setup(){
  
  pinMode(2, INPUT);    //hp
  pinMode(3, INPUT);    //lp
  pinMode(4, INPUT);    //clock
  pinMode(5, INPUT);    //therm
  //pinMode(6, INPUT);   //water ok
  
  pinMode(9, OUTPUT);   //alarm signal hp
  pinMode(10, OUTPUT);  //alarm signal lp
  pinMode(11, OUTPUT);
  // pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);    //start
    
  
// timer.setInterval(50000, RepeatTask);

  TCCR2A =0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20; 
  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= (1 << TOIE2);
  // Initial count of timer (could be changed in range 1-254)
  TCNT2 = 0;                                
  // turn interrupt on
  sei();
 
}
  

void alarm(){
  
   if (hpOk == LOW && lpOk == HIGH && clockOk == HIGH && thermOk == HIGH) {alarmCase = 1;}
   if (hpOk == HIGH && lpOk == LOW && clockOk == HIGH && thermOk == HIGH) {alarmCase = 2;} 
   if (hpOk == LOW && lpOk == LOW && clockOk == HIGH && thermOk == HIGH) {alarmCase = 3;}
   if (hpOk == HIGH && lpOk == HIGH && clockOk == LOW && thermOk == HIGH) {alarmCase = 4;}
   if (hpOk == HIGH && lpOk == HIGH && clockOk == HIGH && thermOk == LOW) {alarmCase = 5;}
   if (hpOk == HIGH && lpOk == HIGH && clockOk == LOW && thermOk == LOW) {alarmCase = 6;}
  
     switch(alarmCase){
       case 1:
        T1 = 100;
       break;
       case 2:
        T1 = 200;
       break;
       case 3:
        T1 = 400;
       break;
       case 4:
        T1 = 1000;
       break;
       case 5:
        T1 = 1000;
       break;
       case 6:
        T1 = 2000;
       break;
  } 
          digitalWrite(10, HIGH);
            delay(T1);
           digitalWrite(10, LOW);
          delay(T1);
          second=0;
}

void loop(){ 
  
   hpOk=digitalRead(2);
   lpOk=digitalRead(3);
   clockOk=digitalRead(4);
   thermOk=digitalRead(5);
   //waterOk=digitalRead(6);
  
 if (hpOk==HIGH && lpOk==HIGH && clockOk==HIGH && thermOk==HIGH){startOk=HIGH;}
    else{startOk=LOW;}
    
    if (startOk==0){startCase = 1;}
    if (startOk==1){startCase = 2;}
  
    switch(startCase){
      case 1:
        digitalWrite(13, LOW);
        digitalWrite(9, LOW);
        alarm();
        break;
      case 2:
     
          if (second==5) {
            digitalWrite(13, HIGH);
          }
           if (second==10){
           digitalWrite(9, HIGH);}
           
        break;
    
    }     
}

I also adjusted the booleans, i hope it is better now

No, it's not.

The boolean type is capable of holding values other than TRUE or FALSE, but it is meant to hold only those two values.

A byte is the same size as a boolean. If you are going to store other than true or false in the variables, you should use the correct type.

While you can get away with using boolean on the Arduino the way that you are, if you were to try to port the code to some system that used a smaller size for boolean, or enforced the true/false values in the variables, your code would no longer work.

It is better to develop good habits early (using the correct variable type based on its expected values (expected by others, if not the compiler)) than it is to try to unlearn bad habits later.

Hi Paul,

How can I learn more about these things, are there websites with a readable explanation for a newbie?

I renewed the code again

#include <avr/interrupt.h>
//#include <SimpleTimer.h>
//#include <SimpleTimer.ccp>
// There must be one global SimpleTimer object.
// More SimpleTimer objects can be created and run,
// although there is little point in doing so.
//SimpleTimer timer;

boolean hpOk;      //high pressure ok
boolean lpOk;      //low pressure ok
boolean clockOk;   //its time to start
boolean thermOk;   //heat wanted
boolean waterOk;
boolean startOk;     //ready to go
boolean startOk2;    //start compressor
int startCase = 0;   //startchoices
int alarmCase = 0;   //alarm choices
int T1 = 0;
int int_counter = 0;
volatile int second = 0;
int oldSecond = 0;
float value;

// Interrupt routine
ISR(TIMER2_OVF_vect) {                  // Interrupt Service routine: called when timer is overflowed (turns from 0xff to 0x00)                  
  int_counter += 1;
  TCNT2 = 0;                            // Initial count of timer (could be changed in range 1-254)
  if (int_counter == 61) {              // after one second change value of variable of second
    second+=1;
    int_counter = 0;
  }
};


//void RepeatTask(){
 //digitalWrite(13, HIGH); //timer set pin 13
//}

void setup(){
  
  pinMode(2, INPUT);    //hp
  pinMode(3, INPUT);    //lp
  pinMode(4, INPUT);    //clock
  pinMode(5, INPUT);    //therm
  //pinMode(6, INPUT);   //water ok
  
  pinMode(9, OUTPUT);   //alarm signal hp
  pinMode(10, OUTPUT);  //alarm signal lp
  pinMode(11, OUTPUT);
  // pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);    //start
    
  
// timer.setInterval(50000, RepeatTask);

  TCCR2A =0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;
  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= (1 << TOIE2);
  // Initial count of timer (could be changed in range 1-254)
  TCNT2 = 0;                                
  // turn interrupt on
  sei();

}
  

void alarm(){
  
   if (hpOk == false && lpOk == true && clockOk == true && thermOk == true) {alarmCase = 1;}
   if (hpOk == true && lpOk == false && clockOk == true && thermOk == true) {alarmCase = 2;}
   if (hpOk == false && lpOk == false && clockOk == true && thermOk == true) {alarmCase = 3;}
   if (hpOk == true && lpOk == true && clockOk == false && thermOk == true) {alarmCase = 4;}
   if (hpOk == true && lpOk == true && clockOk == true && thermOk == false) {alarmCase = 5;}
   if (hpOk == true && lpOk == true && clockOk == false && thermOk == false) {alarmCase = 6;}
  
     switch(alarmCase){
       case 1:
        T1 = 100;
       break;
       case 2:
        T1 = 200;
       break;
       case 3:
        T1 = 400;
       break;
       case 4:
        T1 = 1000;
       break;
       case 5:
        T1 = 1000;
       break;
       case 6:
        T1 = 2000;
       break;
  }
          digitalWrite(10, HIGH);
            delay(T1);
           digitalWrite(10, LOW);
            delay(T1);
            second=0;
}

void loop(){
  
   hpOk=digitalRead(2);
   lpOk=digitalRead(3);
   clockOk=digitalRead(4);
   thermOk=digitalRead(5);
   //waterOk=digitalRead(6);
  
 if (hpOk==true && lpOk==true && clockOk==true && thermOk==true){startOk=true;}
    else{startOk=false;}
    
    if (startOk==false){startCase = 1;}
    if (startOk==true){startCase = 2;}
  
    switch(startCase){
      case 1:
        digitalWrite(13, LOW);
        digitalWrite(9, LOW);
        alarm();
        break;
      case 2:
    
          if (second==5) {
            digitalWrite(13, HIGH);
          }
           if (second==10){
           digitalWrite(9, HIGH);}
          
        break;
    
    }    
}
hpOk == false

This test can be much shorter:

!hpOK
lpOk == true

This test can be much shorter:

lpOK

So:

   if (hpOk == false && lpOk == true && clockOk == true && thermOk == true) {alarmCase = 1;}

becomes

   if (!hpOk && lpOk && clockOk && thermOk) {alarmCase = 1;}

P.S. The { and } are not needed when there is only one statement in the block.

But it is a good habit to get into to always include them, as you’ll find you’ll add a new line and wonder why it always executes.
Best to put the conditional code on a new line (this isn’t BASIC, you know), properly indented.

Upon further review, scratch all that.

You missed the point I was making. The output from digitalRead is NOT boolean. It is integer. From wiring.h:

int digitalRead(uint8_t);

You should be using a variable of the right type to store the output of a function.

Today, the output of digitalRead is HIGH or LOW, which are defined as 1 and 0, which are equivalent to true and false.

But, in the future, that could change. HIGH might be assigned a value of 32000 and LOW might be assigned a value of -16000.

Then, your code would fail, because those values are outside the range that can be stored in a boolean, which is defined in wiring.h, too:

typedef uint8_t boolean;

I started the programming all over again

what about this (it is just the begin of the program)

#include <avr/interrupt.h>

int switch_hp = 2;  //switch high pressure connected to pin 2
int switch_lp = 3;  //switch low pressure connected to pin 3
int switch_therm = 4;  //switch thermostat connected to pin 4
int switch_clock = 5;  //switch clock connected to pin 5
int switch_water = 6;  //switch water connected to pin 6
int pump_rel = 9;   //pump relay connected to pin 9
int ledpin_alarm_press = 10;  //pressure alarm led connected to pin 10
int ledpin_alarm_water = 11;  //alarm led no waterflow
int ledpin_mach_status = 12;  //machine status
int compressor = 13;  //compressor relay connected to pin 13

int startOk;  //start the cycle at 22u00
int securityOk; //all switches ready to go
int hpOk;
int lpOk;
int thermOk;
int clockOk;
int waterOk;

int startCase = 0;   //startchoices
int alarmCase = 0;   //alarm choices
int T1 = 0;

int int_counter = 0;
volatile int second = 0;
int oldSecond = 0;
float value;

// Interrupt routine
ISR(TIMER2_OVF_vect) {                  // Interrupt Service routine: called when timer is overflowed (turns from 0xff to 0x00)                  
  int_counter += 1;
  TCNT2 = 0;                            // Initial count of timer (could be changed in range 1-254)
  if (int_counter == 61) {              // after one second change value of variable of second
    second+=1;
    int_counter = 0;
  }
};

void setup(){
  
  pinMode(switch_hp, INPUT);    //hp ok
  pinMode(switch_lp, INPUT);    //lp ok
  pinMode(switch_therm, INPUT);    //clock ok 
  pinMode(switch_clock, INPUT);    //therm ok
  pinMode(switch_water, INPUT);   //water ok
  
  pinMode(pump_rel, OUTPUT);   //alarm signal hp
  pinMode(ledpin_alarm_press, OUTPUT);  //alarm signal lp, hp
  pinMode(ledpin_alarm_water, OUTPUT);  //alarm signal no waterflow
  pinMode(ledpin_mach_status, OUTPUT);  //machinestatus
  pinMode(compressor, OUTPUT);    //start compressor
  
  TCCR2A =0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;
  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= (1 << TOIE2);
  // Initial count of timer (could be changed in range 1-254)
  TCNT2 = 0;                                
  // turn interrupt on
  sei();
}

void loop(){
  
  hpOk = digitalRead(switch_hp);
  lpOk = digitalRead(switch_lp);
  thermOk = digitalRead(switch_therm);
  clockOk = digitalRead(switch_clock);
  waterOk = digitalRead(switch_water);
  
    if (hpOk){startOk=1;}
      else{startOk=0;}
        digitalWrite(pump_rel, startOk);
      
      
}

This is better, except that now hpok is not a boolean, so the test needs to explicitly involve HIGH and LOW.

if(hopk == HIGH)

While not strictly true, it will make your code much easier to read in the future, and does not rely on the fact that HIGH and true are the same value.