Go Down

Topic: Loop function after button pressed until timeout is reached (Read 296 times) previous topic - next topic

cleight

Hello I am looking for some assistance with a program I wrote that runs a random relay trigger within an If Statement based on a button press and timeout delay. I believe I might need to use a While instead of an IF statement and possibly a software debounce. I am however extremely new to arduino and my Google skills are failing me this evening.

My main issue in my code below is with function "void operateRelay8()"

Code: [Select]
int relay1 = 0; //Vibration
int relay2 = 1; //Sander
int relay3 = 2;
int relay4 = 3;
int relay5 = 4;
int relay6 = 5;
int relay7 = 6;
int relay8 = 7; //Edison Bulb
byte switchVal = LOW;
const int buttonPin = 12; //the number of the pushbutton
const int ledPin = 13;

#define RELAY_ON LOW
#define RELAY_OFF HIGH

unsigned long relayDuration = 10000;
unsigned long relaystartmillis = 0;
unsigned long relay8startmillis = 0;

long randOn = 0;                  // Initialize a variable for the ON time
long randOff = 0;                 // Initialize a variable for the OFF time

int relay1State = RELAY_OFF;
int relay2State = RELAY_OFF;
int relay3State = RELAY_OFF;
int relay4State = RELAY_OFF;
int relay5State = RELAY_OFF;
int relay6State = RELAY_OFF;
int relay7State = RELAY_OFF;
int relay8State = RELAY_ON;


void setup() {
  // put your setup code here, to run once:
pinMode (0, OUTPUT);
pinMode (1, OUTPUT);
pinMode (2, OUTPUT);
pinMode (3, OUTPUT);
pinMode (4, OUTPUT);
pinMode (5, OUTPUT);
pinMode (6, OUTPUT);
pinMode (7, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
randomSeed (analogRead (0));    // randomize
}

void loop() {
  // put your main code here, to run repeatedly:

readPin();
operateRelay();
operateRelay8();
digitalWrite(relay4, RELAY_OFF);
digitalWrite(relay5, RELAY_OFF);
digitalWrite(relay6, RELAY_OFF);
digitalWrite(relay7, RELAY_OFF);
}

void readPin () {
  switchVal = digitalRead(buttonPin);
}

void operateRelay() {
  if (relay2State == RELAY_OFF) {
    if (switchVal == HIGH) {
      relaystartmillis = millis();
      digitalWrite(relay1, RELAY_ON);
      relay2State = RELAY_ON;
      digitalWrite(relay2, RELAY_ON);
      relay1State = RELAY_ON;
    }
  } else { //this happens if relayState2 == RELAY_ON
    if (millis() - relaystartmillis >= relayDuration) { //time has expired
      digitalWrite(relay2, RELAY_OFF);
      relay2State = RELAY_OFF;
      digitalWrite(relay1, RELAY_OFF);
      relay1State = RELAY_OFF;
    }
  }
}
void operateRelay8() {
  randOn = random (100, 1200);    // generate ON time between 0.1 and 1.2 seconds
  randOff = random (200, 900);    // generate OFF time between 0.2 and 0.9 seconds
  if (relay8State == RELAY_ON) {
  if (switchVal == HIGH) {
      relay8startmillis = millis();
      digitalWrite(relay8, RELAY_OFF);    // sets the LED off
      delay(randOff);               // waits for a random time while OFF
      digitalWrite(relay8, RELAY_ON);   // sets the LED on
      delay(randOn);                // waits for a random time while ON
  } else {
    if (millis() - relay8startmillis >= relayDuration) {
      digitalWrite(relay8, RELAY_ON);
    }
  }
 }
}

outsider

What is the issue with void operateRelay8()? Do you have a 10k pulldown resistor from pin 12 to GND?

sterretje

Making use of delay in code that makes use if millis() based timing does not make sense.

From your code, I can not determine what you exactly want to achieve. While the button is pressed, the relay8 must toggle with random delays and it stops when the button is released?

Just a note at the side:
unless randOn and randOff are used in other functions as well, they should not have global scope. They should have local scope to the operateRelay8 function (and probably be static).
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

cleight

Thank you both for your replies. What I am trying to accomplish is when the button is pressed, turn relay on/off at random times until I delayed amount of time becomes true, then leave the relay in the on position.

I have utilized the internal Pull Up resistor, which has fixed the sporadic issues I was getting, However the relay8 code doesn't loop until delayed time value is reached. It will only loop through the random sequence when the button is held down.

Blue Eyes

I think you want something like the following.  Since you are using delays while waiting for the time to pass, the actual duration will be greater than the variable relayDuration, adding to the randomness.

Code: [Select]


void operateRelay8() {

  // if relay is on
  if (relay8State == RELAY_ON) {

    // if switch was read high
    if (switchVal == HIGH) {

      // mark start
      relay8startmillis = millis();

      // while duration has not passed
      while (millis() - relay8startmillis <= relayDuration)
      {

        // get random on/off times
        randOn = random (100, 1200);    // generate ON time between 0.1 and 1.2 seconds
        randOff = random (200, 900);    // generate OFF time between 0.2 and 0.9 seconds

        // turn relay off and on
        digitalWrite(relay8, RELAY_OFF);    // sets the LED off
        delay(randOff);               // waits for a random time while OFF
        digitalWrite(relay8, RELAY_ON);   // sets the LED on
        delay(randOn);                // waits for a random time while ON

      }

    }
  }

}


sterretje

One problem I see is that you never change the relay8State in the function. The below code toggles the relay while the button iis pushed with variable durations and switches it on when the button is released.

Code: [Select]
void operateRelay8()
{
  // delay duration for on or off
  static unsigned long delayDuration;

  // if button pressed
  if (switchVal == HIGH)
  {
    // if delay not started yet
    if (relay8startmillis == 0)
    {
      // toggle relay state
      relay8State = !relay8State;
      // set delay start time
      relay8startmillis = millis();
      // set the delay depending on the relay state
      if (relay8State == RELAY_ON)
        delayDuration = random (100, 1200); // set on time
      else
        delayDuration = random (200, 900);  // set off time
      // set the relay according to the relay state
      digitalWrite(relay8, relay8State);
    }

    // if time lapsed
    if(millis() - relay8startmillis >= delayDuration)
    {
      // reset the start time
      relay8startmillis = 0;
    }
  }
  else
  {
    // set the relay state to on
    relay8State = RELAY_ON;
    // set the relay according to the relay state
    digitalWrite(relay8, relay8State);
    // indicate no delay in progress
    relay8startmillis = 0;
  }

}

It's non-blocking so you have to keep calling it from loop (as you already do).

Compiled, not tested.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

PaulMurrayCbr

Quote
Thank you both for your replies. What I am trying to accomplish is when the button is pressed, turn relay on/off at random times until I delayed amount of time becomes true, then leave the relay in the on position.
not sure how long you awnt to be turning the relay on and off for.

Code: [Select]

boolean doingTheRun;
uint32_t startTime,
uint32_t randomStartTime,
uint32_t randomDuration,
boolean isOn;


loop() {
  if(!doingTheRun) {
    if(button is down) {
      startTime = randomStartTome = millis();
      randomDuration = 0;
     isOn = false;
     doingTheRun = true;
       }
  }
  else {
    if(millis() - startTime >= 60L * 1000L) { // one minute
      turn relay on;
      doingTheRun = false;
    }
    else if(milis() - randomStartToime >= randomDuration) {
      isOn = !isOn;
      digitalout(relayPin, isOn);
      randomStartTime = millis();
      randomDuration = rand(whatevs);
      
    }
  }
}
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

cleight

I think you want something like the following.  Since you are using delays while waiting for the time to pass, the actual duration will be greater than the variable relayDuration, adding to the randomness.

Code: [Select]


void operateRelay8() {

  // if relay is on
  if (relay8State == RELAY_ON) {

    // if switch was read high
    if (switchVal == HIGH) {

      // mark start
      relay8startmillis = millis();

      // while duration has not passed
      while (millis() - relay8startmillis <= relayDuration)
      {

        // get random on/off times
        randOn = random (100, 1200);    // generate ON time between 0.1 and 1.2 seconds
        randOff = random (200, 900);    // generate OFF time between 0.2 and 0.9 seconds

        // turn relay off and on
        digitalWrite(relay8, RELAY_OFF);    // sets the LED off
        delay(randOff);               // waits for a random time while OFF
        digitalWrite(relay8, RELAY_ON);   // sets the LED on
        delay(randOn);                // waits for a random time while ON

      }

    }
  }

}


Thank you Blue Eyes your code worked exactly how I envisioned it when I started this project. Here is the final code incase anyone in the future needs something like this:

Code: [Select]

// Halloween Electric Chair Prop, Version 11.2
// Created by: Cleight, 2016

int relay1 = 0; //Vibration
int relay2 = 1; //Strobe
int relay3 = 2;
int relay4 = 3;
int relay5 = 4;
int relay6 = 5;
int relay7 = 6;
int relay8 = 7; //Edison Bulb
byte switchVal = HIGH;
const int buttonPin = 12; //the number of the pushbutton
const int ledPin = 13;

#define RELAY_ON LOW
#define RELAY_OFF HIGH

unsigned long relayDuration = 75000;
unsigned long relaystartmillis = 0;
unsigned long relay8startmillis = 0;

long randOn = 0;                  // Initialize a variable for the ON time
long randOff = 0;                 // Initialize a variable for the OFF time

int relay1State = RELAY_OFF;
int relay2State = RELAY_OFF;
int relay3State = RELAY_OFF;
int relay4State = RELAY_OFF;
int relay5State = RELAY_OFF;
int relay6State = RELAY_OFF;
int relay7State = RELAY_OFF;
int relay8State = RELAY_ON;


void setup() {
  // put your setup code here, to run once:
pinMode (0, OUTPUT);
pinMode (1, OUTPUT);
pinMode (2, OUTPUT);
pinMode (3, OUTPUT);
pinMode (4, OUTPUT);
pinMode (5, OUTPUT);
pinMode (6, OUTPUT);
pinMode (7, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
randomSeed (analogRead (0));    // randomize
}

void loop() {
  // put your main code here, to run repeatedly:

readPin();
operateRelay();
operateRelay8();
digitalWrite(relay3, RELAY_OFF);
digitalWrite(relay4, RELAY_OFF);
digitalWrite(relay5, RELAY_OFF);
digitalWrite(relay6, RELAY_OFF);
digitalWrite(relay7, RELAY_OFF);
}

void readPin () {
  switchVal = digitalRead(buttonPin);
}

void operateRelay() {
  if (relay2State == RELAY_OFF) {
    if (switchVal == LOW) {
      relaystartmillis = millis();
      digitalWrite(relay1, RELAY_ON);
      relay2State = RELAY_ON;
      digitalWrite(relay2, RELAY_ON);
      relay1State = RELAY_ON;
    }
  } else { //this happens if relayState2 == RELAY_ON
    if (millis() - relaystartmillis >= relayDuration) { //time has expired
      digitalWrite(relay2, RELAY_OFF);
      relay2State = RELAY_OFF;
      digitalWrite(relay1, RELAY_OFF);
      relay1State = RELAY_OFF;
    }
  }
}
void operateRelay8() {

  // if relay is on
  if (relay8State == RELAY_ON) {

    // if switch was read high
    if (switchVal == LOW) {

      // mark start
      relay8startmillis = millis();

      // while duration has not passed
      while (millis() - relay8startmillis <= relayDuration)
      {

        // get random on/off times
        randOn = random (100, 1000);    // generate ON time between 0.1 and 1.2 seconds
        randOff = random (200, 800);    // generate OFF time between 0.2 and 0.9 seconds

        // turn relay off and on
        digitalWrite(relay8, RELAY_OFF);    // sets the LED off
        delay(randOff);               // waits for a random time while OFF
        digitalWrite(relay8, RELAY_ON);   // sets the LED on
        delay(randOn);                // waits for a random time while ON

      }

    }
  }
}

Go Up