Hello
I have a some logic Events that need to trigger a digital output. But I need a 500ms delay to allow some conditions to settle before setting the digital output to HIGH.
Also the output must follow the High to LOW transition at the end of the Event. Lastly If the Event duration is less than the delay time of 500ms there will not be a digital output to HIGH.
I have read posts on one-shot using millis() and I was thinking of && the Event and one-shot output to drive the digital output to HIGH. But I am having a problem with one-shot wanting to re-triggering while the Event is still HIGH. So I need a better way to isolate the triggering of the one-shot while the event is still HIGH.
I have attached a pdf, showing the desired results, and a section of one-shot code that I am playing with.
Thank you
David
//***************************
// Pin declarations
//***************************
const byte RelayControl = 13;
const byte Event = 12;
//***************************
// Global Variables
//***************************
byte BTB1_flag = 0; // Set flag to 0 one time
unsigned long RelayDelay = 500; // Interval in MS for delay
unsigned long BTB1Time = 0; // Set start time to 0
int BTB1 = 0; //BTB1 = BUS TIE BREAKER #1
void setup()
{
pinMode( RelayControl, OUTPUT );
pinMode( Event, INPUT_PULLUP );
}
void loop()
{ //START OF VOID LOOP DO NOT REMOVE
BTB1 = digitalRead( Event ); //READ EVENT TRIGGER
unsigned long t_now_ms = millis(); //SET CURRENT TIME EVERY LOOP
if( BTB1 == LOW ) //IF "BTB1" IS LOW
{
BTB1_flag = 1; // Set "BTB1_flag" Value to 1
BTB1Time = t_now_ms; //set current time to "BTB1Time"
}
if( BTB1_flag == 1 && ((t_now_ms - BTB1Time) >= RelayDelay))
{
BTB1_flag = 0;
}
digitalWrite( RelayControl, ( BTB1_flag == 0 ));
} //END OF VOID LOOP DO NOT REMOVE
Post a complete program. Unless it is too long (hopefully not), please include it in your post so we don't have to download. And please use the code button </> so your code looks like this and is easy to copy to a text editor
Maybe you need a variable to record whether your event has happened and been responded to so that it is not activated twice.
Maybe you could point me in the right direction, My last programming was in BASIC using punch cards in the late 1960's. So I have a lot to catch up on.
Didn't punch my first cards till 1975 Intro Fortran.
Instructions are in the comments up top. ANY explaining you need, I'll work with you but please, the forum notifications (at least for me) fail often (I get links to the wrong threads regularly) so don't hesitate to send me a PM if I don't respond, those I get!
This sketch uses a modular event-driven approach to achieve a kind of concurrent tasking.
Input, processing, and output all run independent all the time. Processing reads data from inputs and sets data that the outputs work from. Generally, loop() runs in a small fraction of a millisecond on 16MHz AVR's (like the UNO chip) and you get smooth operation with under 1ms reaction times.
This sketch barely scratches 1% of what that chip can do.
// All you need to do this example is an Arduino and a button on pin 2.
// Push the button once, led lights after delay. Again, led turns off.
// Button is debounced and wired directly to ground. The button can be a
// jumper from pin 2 grounded on USB connector. Tested with jumper.
// By GoForSmoke for free public use. Using Arduino 1.0.5-r2
const byte ledPin = 13; // this is the onboard led pin
const byte buttonPin = 2;
byte setLedPin = 0;
const unsigned long ledDelay = 1000UL; // blink interval
unsigned long ledDelayStart = 0U; // 16 bit blink (on or off) time ms
// button variables
byte buttonRead; // wired for pullup -- if down then LOW, if up then HIGH
byte lastButtonRead = HIGH; // so debounce knows previous read
byte checkDebounce = 0; // only checks decounce after every button pin change
byte lastButtonState = 0; // last stable button state
byte buttonState = 0; // stable button state
// 0 = button is up after debounce
// 1 = button is down after debounce
// button debounce timing variables
const unsigned long debounceDelayMs = 100UL;
unsigned long debounceStartMs;
unsigned long msNow;
byte processState = 0; // 1st press to start, 1st release, 2nd press to stop, 2nd release
void setup()
{
Serial.begin( 115200 );
pinMode( ledPin, OUTPUT ); // default is LOW
pinMode( buttonPin, INPUT_PULLUP ); // my button connects to ground, not 5V
// however that means that when the button is pressed the pin is LOW.
}
void loop() // make sure that loop() runs fast and stays in the "now".
{
// BUTTON CODE BLOCK, it handles debouncing.
// the task is to set the variable buttonState when a Stable Button State is reached.
// other sensor code could change the same variable if desired
// read the pin which may be changing fast and often as the button bounces
buttonRead = digitalRead( buttonPin ); // momentary state
msNow = millis();
if ( buttonRead != lastButtonRead )
{
debounceStartMs = msNow;
checkDebounce = 1;
}
else if ( checkDebounce )
{
if ( msNow - debounceStartMs >= debounceDelayMs ) // stable button state achieved
{
buttonState = !buttonRead; // mission accomplished, button is stable
// note that buttonState is opposite buttonRead
checkDebounce = 0; // stop debounce checking until pin change
}
}
lastButtonRead = buttonRead;
//
// End of the BUTTON CODE BLOCK
//==================================================================================
// CONTROL CODE BLOCK that uses buttonState and processState
if ( lastButtonState != buttonState )
{
lastButtonState = buttonState;
Serial.println( F( "============================================================" ));
Serial.print( F( "processState " ));
Serial.print( processState );
Serial.print( F( " buttonState " ));
Serial.println( buttonState );
Serial.print( F( " millis " ));
Serial.println( msNow );
Serial.println( F( "============================================================" ));
switch ( processState )
{
case 0: // waits for press without blocking
if ( buttonState == 1 ) // button is pressed
{
processState = 1;
setLedPin = 1; // start led blink task
ledDelayStart = millis(); // led blink control value set in the control block
}
break;
case 1: // waits for release without blocking
if ( buttonState == 0 ) // button is released
{
processState = 2;
}
break;
case 2: // waits for press without blocking
if ( buttonState == 1 ) // button is pressed
{
processState = 3;
setLedPin = 2; // led blink control value set in the control block
}
break;
case 3: // waits for release without blocking
if ( buttonState == 0 ) // button is released
{
processState = 0; // start over
}
break;
}
}
// End of the CONTROL CODE
//==================================================================================
// LED BLINK CODE BLOCK
if ( setLedPin == 1 )
{
if ( millis() - ledDelayStart >= ledDelay )
{
digitalWrite(ledPin, HIGH );
setLedPin = 0;
}
}
else if ( setLedPin == 2 )
{
digitalWrite(ledPin, LOW );
setLedPin = 0;
}
// End of the LED BLINK CODE
//==================================================================================
// Want to add serial commands and args input?
// this is a good spot. Serial is so slow it can usually go last.
}
AllenDC:
Maybe you could point me in the right direction,
Maybe this would work (not tested). It was easier to write my own code than to get my head around yours. I prefer meaningful variable names.
void loop() {
currentMillis = millis();
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) { // Low = button pressed
buttonMillis = currentMillis; // reset the clock
// turn relay off
relayDoneFlag = false; // so it can be triggered again with next button press
}
// next line will only be true if the button is kept pressed for longer than RelayDelay
if (currentMillis - buttonMillis > RelayDelay) {
if (relayDoneFlag == false) {
relayDoneFlag = true; // so it won't be turned on twice
// turn relay on
}
}
}
And I may have completely misunderstood your requirement
Sure, I need 8 versions of the Output follows Event, after a delay time, but the delay time was always 500ms
So here is a version:
unsigned long DelayTime = 500; // Interval in MS for delay
unsigned long GCB1currentMillis;
unsigned long GCB1ControlMillis;
int GCB1Control;
int GCB1RunOneTime;
int GCB1DoneFlag;
//ENGINE 1 GENERATOR CONTROL BREAKER 1 CONTROL START
GCB1currentMillis = millis(); //Update to current millis
if (GCB1Control == LOW)
{
GCB1ControlMillis = GCB1currentMillis; // reset the clock to current millis
GCB1 = 0; // Turn GCB1 to OFF
GCB1DoneFlag = false; // so it can be triggered again with next button press
}
// next line will only be true if the button is kept pressed for longer than Delay
if (GCB1currentMillis - GCB1ControlMillis > DelayTime)
{
if (GCB1DoneFlag == false)
{
GCB1DoneFlag = true; // so it won't be turned on twice
GCB1 = 1; // Turn GCB1 to ON
}
}
//ENGINE 1 GENERATOR CONTROL BREAKER 1 CONTROL END