Hi All, firstly thankyou to so many of you who have examples and tutorials for the Arduino. I am still very new but learning every single day, reading and researching. I have searched google for a few days now trying to find an answer to this question.
I have created a simple code to watch for input changes from a button, and count the time between inputs. In the example below, I have the first button activating the timer on its first press. The Second press stops the timer, and if the time elapsed is shorter than a certain number, it triggers an LED. A second button turns the LED off. My issue is, if the first button is pressed once, and starts the timer, I need to have a maximum I can set, for the timer to stop counting and reset, so its ready to start again on another press of the first button.
I am drawing a complete blank how to go about this. Whenever I do a search on google, i get information on timer interrupts, and after alot of reading, I cant see how this works for my application.
As a second question, my goal is to have multiple inputs and counters on the same Uno board, basically duplicates of the current setup. My question is, I am reading that the Uno has 3 timers. Am I right in assuming I can only have 3 of these counters working successfully? Yes, there could be more than three timers running at once. It is a slim chance of that happening but its still possible. Thankyou!
LC_2_LANES_25-05.ino (4.3 KB)
OP's code realigned:
/* AJs Lane Changer Test using push buttons and a LED as a solenoid
May 25 2017
First attempt at multiple LC control from one Arduino
*/
// Statements for LC A
const int solePin1 = 5; // LED connected to solenoid pin 5 OUTPUT!!!! - This is the trigger to power the Solenoid to hold LC open
#define buttonPin1 2 // sensor 1 button on pin 2 - First lane sensor, at a distance prior to lanechanger.
#define buttonPin2 3 // sensor 2 button on pin 3 - This is the Sensor. Goes HIGH when car passes sensor 2 in passing lane - Beyond the lane changer!
int buttonState1; // variable to store button state
int buttonState2 = 0; // variable for reading the reset pushbutton status
int lastButtonStateA; // variable to store last button state
int timingA; // condition for blinking - timer is timing - BLINKING
long startTimeA; // start time for stop watch
long elapsedTimeA; // elapsed time for stop watch
void setup()
{
Serial.begin(9600);
pinMode(buttonPin1, INPUT); // Sensor 1 as an input
digitalWrite(buttonPin1, HIGH); // turn on pullup resistors. Wire button so that press shorts pin to ground. - Question this, when wiring in Sensor 1!
pinMode(buttonPin2, INPUT_PULLUP); //Sensor 2 input - Ditto, check wiring when
pinMode(solePin1, OUTPUT); //solenoid output
}
void loop()
{
int button;
buttonState1 = digitalRead(buttonPin1); // read the button state and store
buttonState2 = digitalRead(buttonPin2); // read the state of the pushbutton value:\
if (buttonState1 == LOW && lastButtonStateA == HIGH && timingA == false) // check for a high to low transition
// if true then found a new button press while clock is not running - start the clock
{
startTimeA = millis(); // store the start time
timingA = true; // turn on timing
delay(5); // short delay to debounce switch
lastButtonStateA = buttonState1; // store buttonState in lastButtonState, to compare next time
}
else if (buttonState1 == LOW && lastButtonStateA == HIGH && timingA == true) // check for a high to low transition
// if true then found a new button press while clock is running - stop the clock and report
{
elapsedTimeA = millis() - startTimeA; // store elapsed time
timingA = false; // turn off timing
lastButtonStateA = buttonState1; // store buttonState in lastButtonState, to compare next time
// routine to report elapsed time
Serial.println( (int)(elapsedTimeA)); // divide by 1000 to convert to seconds - then cast to an int to print
{
if (elapsedTimeA < 600)
{
digitalWrite(solePin1, HIGH); // if time between buttons is 200 or lower - fire solenoid
} // check if the pushbutton is pressed. if it is, the buttonState is HIGH:
else
{
digitalWrite(solePin1, LOW); // turn off LED when not blinking
}
}
}
else
{
lastButtonStateA = buttonState1; // store buttonState in lastButtonState, to compare next time
}
// Reset Routine - when car in passing lane passes sensor, to turn OFF the solenoid power
if (digitalRead (buttonPin2) == HIGH) // pin has been pulled to Gnd, act on it
{ // whatever the code does for an active input, such as
digitalWrite(solePin1, LOW);
}
else { // do something else - We dont want it to do anything. All it does it switch off the solenoid.
}
}
Not sure if I have understood you correctly, but is this something like what you want:
if (buttonState1 == LOW && lastButtonStateA == HIGH && timingA == false) // check for a high to low transition
// if true then found a new button press while clock is not running - start the clock
{
startTimeA = millis(); // store the start time
timingA = true; // turn on timing
delay(5); // short delay to debounce switch
}
else if (buttonState1 == LOW && lastButtonStateA == HIGH && timingA == true) // check for a high to low transition
// if true then found a new button press while clock is running - stop the clock and report
{
elapsedTimeA = millis() - startTimeA; // store elapsed time
timingA = false; // turn off timing
// routine to report elapsed time
Serial.println( (int)(elapsedTimeA)); // divide by 1000 to convert to seconds - then cast to an int to print
{
if (elapsedTimeA < 600)
{
digitalWrite(solePin1, HIGH); // if time between buttons is 200 or lower - fire solenoid
} // check if the pushbutton is pressed. if it is, the buttonState is HIGH:
else
{
digitalWrite(solePin1, LOW); // turn off LED when not blinking
}
}
}
else if (timingA == true)
{
if (millis() - startTimeA > TIMEOUT_TIME) {
timingA = false;
Serial.println("timingA timeout");
}
}
lastButtonStateA = buttonState1; // store buttonState in lastButtonState, to compare next time
BTW:
You are overdoing it with the comments: you don't need a comment on each line. Choose good variable and function names and let the code speak for itself. Save end-of-line comments for really important stuff - and make sure they are correct !?!
Keep variables consistent; why startTimeA, lastButtonStateA but buttonState1?
Am I right in assuming I can only have 3 of these counters working successfully?
You don't seem to be using any counters explicitly at the moment - just using millis().
Here's an example that has a "ready" led when the sketch is ready for the first press, and a "winner" led when the second press was fast enough.
enum State {
READY, RUNNING, DISPLAYING_RESULT
}
state = READY;
const byte Apin, Bpin, readyLedPin, winnerLedPin; // set these to your pins
const uint32_t WINNER_ms = 3000; // must press within 3 seconds to win
const uint32_t TIMEOUT_ms = 5000; // 5 second timeout before returning to 'READY' state
byte A;
byte B;
uint32_t startMs;
void setup() {
pinMode(Apin, INPUT_PULLUP);
pinMode(Bpin, INPUT_PULLUP);
pinMode(readyLedPin, OUTPUT);
pinMode(winnerLedPin, OUTPUT);
digitalWrite(readyLedPin, HIGH);
digitalWrite(winnerLedPin, LOW);
}
void loop() {
// read all inputs at the top of loop()
prevA = A;
A = digitalRead(Apin);
prevB = B;
B = digitalRead(Bpin);
swtch(state) {
case READY:
if(prevA == HIGH && A == LOW) {
// buttton A pressed
digitalWrite(readyLedPin, LOW);
startMs = millis();
state = RUNNING;
}
break;
case RUNNING:
uint32_t elapsedTime = millis() - startMs;
if(prevA == HIGH && A == LOW) {
// button A pressed
if(elapsedTime < WINNER_ms) {
digitalWrite(winnerLedPin, HIGH);
state = DISPLAYING_RESULT;
}
else {
digitalWrite(readyLedPin, HIGH);
state = READY; // or should this be DISPLAYING_RESULT ?
}
}
else if(elapsedTime > TIMEOUT_ms) {
// timeout
digitalWrite(readyLedPin, HIGH);
state = READY;
}
break;
case DISPLAYING_RESULT:
if(prevB == HIGH && B == LOW) {
// button B pressed
digitalWrite(winnerLedPin, LOW);
digitalWrite(readyLedPin, HIGH);
state = READY;
}
break;
}
}