Multiple timer problem and code crash

I am working on a project with pushbuttons that need to switch a relay and turn it off after a few seconds. After that, it should not be possible to press the button for x number of seconds.

However I want to connect 4 buttons to one Arduino, it seems to me that this should just be able to run synchronously with separate timers running alongside each other. Unfortunately I am not getting this to work as intended.

Even though the timer variables all have different names (see code example). As soon as you press one button the program is activated and the button is triggered.
You should still be able to press the other 3 buttons but when I do that nothing happens until the number of seconds has passed.

Also, sometimes when I press a certain button the program crashes completely. The relay then turns on but does not turn off after that. Pressing the buttons does not change the situation.

Unfortunately I can't manage to find the problem, I have the idea that all the code is just fine. Hopefully someone here has an idea what the problem is.

My code:

int SensorPin1 = 3;
int SensorPin2 = 4;
int SensorPin3 = 5;
int SensorPin4 = 6;

int ValvePin1 = 7;
int ValvePin2 = 8;
int ValvePin3 = 9;
int ValvePin4 = 10;
int ValvePin5 = 11;
int ValvePin6 = 12;

unsigned long lastActive2;
unsigned long lastActive3;
unsigned long lastActive4;
unsigned long lastActive5;
unsigned long lastActive6;

int buttonState1 = 0;
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;

int delayTime = 20000;
int timeoutTime = 7000;

unsigned long currentTime1;
unsigned long currentTime2;
unsigned long currentTime3;
unsigned long currentTime4;

void setup() {
  pinMode(SensorPin1, INPUT_PULLUP);
  pinMode(SensorPin2, INPUT_PULLUP);
  pinMode(SensorPin3, INPUT_PULLUP);
  pinMode(SensorPin4, INPUT_PULLUP);

  pinMode(ValvePin1, OUTPUT);
  pinMode(ValvePin2, OUTPUT);
  pinMode(ValvePin3, OUTPUT);
  pinMode(ValvePin4, OUTPUT);
  pinMode(ValvePin5, OUTPUT);
  pinMode(ValvePin6, OUTPUT);

  digitalWrite (ValvePin1, HIGH); 
  digitalWrite (ValvePin2, HIGH); 
  digitalWrite (ValvePin3, HIGH); 
  digitalWrite (ValvePin4, HIGH); 
  digitalWrite (ValvePin5, HIGH); 
  digitalWrite (ValvePin6, HIGH); 
}

void loop() {
  currentTime1 = millis();

  // Sensor 2
  buttonState1 = digitalRead(SensorPin1);

  if (buttonState1 == LOW) {
    if ((currentTime1 - lastActive2) > delayTime) {
      digitalWrite (ValvePin2, LOW); 
      lastActive2 = millis();
    }
  }

  if ((currentTime1 - lastActive2) > timeoutTime) {
    digitalWrite (ValvePin2, HIGH); 
  }

  currentTime2 = millis();

  // Sensor 3
  buttonState2 = digitalRead(SensorPin2);

  if (buttonState2 == LOW) {
    if ((currentTime2 - lastActive3) > delayTime) {
    digitalWrite (ValvePin3, LOW); 
    lastActive3 = millis();
    }
  }

  if ((currentTime2 - lastActive3) > timeoutTime) {
    digitalWrite (ValvePin3, HIGH); 
  }

  currentTime3 = millis();
  
  // Sensor 4
  buttonState3 = digitalRead(SensorPin3);

  if (buttonState3 == LOW) {
    if ((currentTime3 - lastActive4) > delayTime) {
    digitalWrite (ValvePin4, LOW); 
    lastActive4 = millis();
    }
  }

  if ((currentTime3 - lastActive4) > timeoutTime) {
    digitalWrite (ValvePin4, HIGH); 
  }

  currentTime4 = millis();

  // Sensor 5
  buttonState4 = digitalRead(SensorPin4);

  if (buttonState4 == LOW) {
    if ((currentTime4 - lastActive5) > delayTime) {
    digitalWrite (ValvePin5, LOW); 
    digitalWrite (ValvePin6, LOW); 
    lastActive5 = millis();
    }
  }

  if ((currentTime4 - lastActive5) > timeoutTime) {
    digitalWrite (ValvePin5, HIGH); 
    digitalWrite (ValvePin6, HIGH); 
  }
}

It looks plausible.

The loop looks to be free running, so you could use just one currentTime for all four timers. Taking once the value of miilis() at the top of a free running loop is often seen.

Yes, you do need separate variables for the others.

Nothing should make any odd behaviour, so post a schematic of your project, and check all wiring.

When I have a bigger window I look for copy/paste errors. And probably run your sketch.

When this works, soon, you'll want to stick around to hear us tell you about and recommend arrays for duplicating effort, much easier and safer than copy/paste/editing.

a7

Yes I thought so too.
I had one currentTime at first but since it didn't work I tried making separate currentTime variables to see if there was any difference but unfortunately there isn't.

Here is a summary of what happens and how the wiring is connected (I can't draw digitally so a schematic drawing is hard to do)

  1. There is a 12V button connected, this button engages a 12V relay as soon as you push the button.
  2. The 12V relay is connected to D3, D4, D5 and D6 and these are connected to ground as soon as the relay switches.
  3. After this, the 5V relay is activated e.g. on D7 for 7 sec.
  4. After this, the button may not be pressed for 20 sec, but of course the other buttons may because they should do the above count on their own.

I have checked the wiring several times and all 4 buttons work exactly as they should but not at the same time.
Or actually the strange thing is: As soon as I press one button I can activate the other buttons as well (as soon as I press during the timeout time, when the relay is still active). As soon as the timeout time is over and the relay goes off, I can't press any of the buttons, not even the ones I haven't pressed yet.

The strange thing is that sometimes the program crashes completely and the relay does not switch off and the buttons do not work anymore until I disconnect the power.

Okay, I ran your code and it seems to function. I had no problem activating the sensors 1, 2, 3 4 with immediate effect.

I did modify the delay time (life too short), and you must change the type of your constants used in time computations, viz:

unsigned long delayTime = 20000L;
unsigned long timeoutTime = 7000;

But I do neither see capricious or inexplicable behavoiur. I am not using relays...

So schematic.

In the meantime, if you replace the relays with print statements ("turining on relay 1" and so forth) or LEDs, see if the sketch starts to work better.

a7

Pencil and paper. Take a picture and post it.

Just show all the parts and how they are connected, with attention to sources of power and how that power gets to the things that need it.

A blocky diagram is a good start.

a7

look this over.

less code to maintain. easier to disable setting relays in order to rule them out as a cause. easier to disable specific relays. easier to disable specific cases

const int MaxOut = 2;

// define controller struct describing pins and ancillary variables
struct Ctl {
    const byte    PinBut;
    const byte    PinOut [MaxOut];
    const char   *desc;

    bool          active;
    unsigned long msec;
}
// statically specify values
ctl [] = {
    {   3, {  8 },     "A" },
    {   4, {  9 },     "B" },
    {   5, { 10 },     "C" },
    {   6, { 11, 12 }, "D" },
};
const int Nctl = sizeof(ctl)/sizeof(Ctl);

enum { Off = HIGH, On = LOW };

unsigned long MsecPeriod = 4000;

// -----------------------------------------------------------------------------
void
loop (void)
{
    unsigned long msec = millis ();

    for (int n = 0; n < Nctl; n++) {
        // if ctl active, check if timer expired
        if (ctl [n].active)  {
            if (msec - ctl [n].msec >= MsecPeriod)  {
                ctl [n].active = false;
                for (int i = 0; i < MaxOut; i++)
                    if (0 != ctl [n].PinOut [i])
                        digitalWrite (ctl [n].PinOut [i], Off);

                Serial.print   (ctl [n].desc);
                Serial.println (" controller off");
            }
        }

        // turn relay on if button pressed
        else if (LOW == digitalRead (ctl [n].PinBut))  {
            ctl [n].active = true;
            ctl [n].msec   = msec;
            for (int i = 0; i < MaxOut; i++)  {
                if (0 != ctl [n].PinOut [i])
                    digitalWrite (ctl [n].PinOut [i], On);
            }

            Serial.print   (ctl [n].desc);
            Serial.println (" controller on");
        }
    }
}

// -----------------------------------------------------------------------------
void
setup (void)
{
    Serial.begin (9600);
    for (int n = 0; n < Nctl; n++) {
        pinMode (ctl [n].PinBut, INPUT_PULLUP);
        for (int i = 0; i < MaxOut; i++)  {
            if (0 != ctl [n].PinOut [i])  {
                pinMode      (ctl [n].PinOut [i], OUTPUT);
                digitalWrite (ctl [n].PinOut [i], Off);
            }
        }
        Serial.print   (" controller ");
        Serial.println (ctl [n].desc);
    }
}
1 Like

What happens if you replace the relays with LEDs?
or
if you disconnect all relays an add a serial print at each place where a relay is switched on/off ?

Does it work then?

The behaviour of your device sounds like there is a hardware-problem

Too big current drawn by the relays
electromagnetic noise or maybe even electric transients causing the microcontroller to crash.

So it will be crucial to post a schematic.

Free hand-drawn with pen an paper an then taking a picture with your smartphone to get the "analog" drawing digital is totally sufficient.

2 Likes

Hello creativeking

Welcome to the best Arduino forum ever :slight_smile:

What is the task of your sketch in real life?

Thanks for the responses!

I have tried some things but it remains very strange....
I replaced the Arduino Nano for another arduino Nano and then the code worked fine! I could press the buttons independently and the timers rotated independently.

Then I had to take the power off several times, each time for a few minutes and now it doesn't work again....
Now it does even more strange things. The timers are running the same again, so when you press 1 time it turns on. Once it goes off you have to wait at all 4 buttons until the timer is over.

But now it also happens sometimes that when you press button 1, relay 1 turns on (as it should) but then suddenly relay 3 also turns on spontaneously, for example. This is nowhere in the code... I really do not understand how this is possible

Attached is the schematic drawing, hopefully it is somewhat clear. Additional info below:

  • There is a 12V transformer connected to the buttons. These are 12V buttons because there is a 12V LED in them.
  • Because of these 12V buttons, there are 12V relays between them because Arduino can't handle this.
  • So you press the button and the 12V relay comes on. (This always works perfectly)
  • From the Nano a cable goes from D3 - D6 to the 12V relay to the normal open contact. The Con is connected to the ground of the Nano and is looped through.
  • So the Arduino Nano makes a closed circuit as soon as the 12V relay turns on.
  • Then the Nano should see if the delay time is ahead and then the 5V relay should turn on
  • Once the 5V relay turns on, a 12V air pressure valve is activated which causes a pneumatic cylinder to open. and close again after the number of seconds set.

It's for a Halloween project.

We have a dark maze where we hang luminous buttons with a pneumatic cylinder nearby with body parts attached to it, for example.

Once you press the button the cylinder should slide forward as a scare effect. After a few seconds the cylinder where to slide in so it can happen again.
And that with 4 buttons and 4 cylinders separate from each other in other places in the maze.

So it seems to me that this should just be doable with 1 arduino but really weird things happen.

Hello creativeking

Post current sketch to see how we can help.

Post the datasheet of buttons used.

Your schematic is professional.

  • no fritzing picture
  • lines run only horizontal / vertical
  • includes connections to power-supplies

You have buttons named Button + LED 12V

Which have a signal output. What voltage do you have on this signal-output?
If this voltages exceeds 5V you are damaging your Arduinos.

How much current does your 5V-relay draw?

Are these five Relay_5V? because IO-pins D9, D10, D11, D12, D13 are connected to the box named "Relay 5V" ?

An arduino is NO powersupply!
You are supplying your Arduino-Nano from 12V
which means dissipated power in the voltage-regulator:
12V - 5V = 7V * amperage you draw

If you draw too much current the overheat-protection of the voltage-regulator makes the voltage-regulator shut-down.

How does your wiring look like?
It might be that electromagnetic noise disturbs your electronic

The 12V switches have 12V output on the switch wire. Therefore, it does not go to the Arduino but to the 12V relays.

The 12V relays are used to connect to D3 - D6 on the CON / NO side of the relays. So the 12V and 5V is completely separated from each other.

It is a 5 fold 5V relay indeed. So the arduino engages these 5V relays through D8 - D12 and they switch the 12V valves.

The arduino is not used as a power supply. There is a 12V transformer on the top left that powers the knobs and valves.
This also supplies the arduino with 12V input voltage.

Only the 5V relays on the right are powered from the Arduino but it seems to me that should still be possible?

This depends on the current these relays draw.

Again:
The onboard-voltage-regulator has to transform the voltagedrop Input-to-output * amperage to heat

Input: 12V
Output: 5V
Voltage-drop: 12V - 5V = 7V

let's estimate your relay draws 50 mA
You switch two of them = 100 mA
Arduino-Nano itself draws another 50 mA
7V * 0.15A = 1.05 Watt heat-generation
that must be dissipated by this small chip

1 W of heat would heat up this chip quickly an at a temperature of 125°C the chip will shut down