Hey, running into a problem which probably has a simple solution.
I'm attempting to create a queue using switches which will then be displayed on a webpage for public perusal. IE switch #1 is on, a message will appear that states "switch 1 has been on and waiting for (blah blah hours:minutes:seconds)"
Sending the information is already a headache to me, but what I can't even get past is the storing of this switch and a timer to count how long the switch has been active.
I have something along the lines of:
if (switchpress == 0)
println(desknum " has been waiting for " timervalue)
however, I have no idea how to establish a timer, let alone a timer that would reset itself once that switch is turned off. The reset would be to prevent the issue of having the switch re-engaged and then saying they've been waiting this new amount + whatever time they had been waiting the previous time the switch was activated.
If this is too in depth of a question for me to ask here, let me know and I can try to look elsewhere for the information but so far I'm stumped.
When the switch becomes on save the value of millis() and set a boolean to true.
When it becomes off set the boolean to false. If the boolean is true calculate the on period by subtracting the start time from the current value of millis()
An array of structs to hold the start values, booleans and input pin numbers and polling the input pins will make the code shorter and neater
if (switchpress == HIGH) { //this is because the switch is going to a pin designated as an output
unsigned long timer = millis()
println(desknum "has been waiting for "(currenttime - timer))
}
You need to detect when the the switch becomes closed, not when it is closed
I don't understand your comment about the switch going to a pin designated as an output. More detail please. However it is wired it must be in a known state at all times and not floating at an unknown voltage. This means using a pullup or pulldown resistor, wiring the switch appropriately and having the code logic match the wiring.
I suggested using a boolean to prevent the continued calculation and reporting of elapsed time when the switch us turned off
Did you note my suggestion to use an array to hold the data for the switches ?
Gonna be honest with you sir, a lot of this is flying over my head. Arrays in particular.
I have a pin going to a switch with the other side going to my + rail. So the pinMode is actually INPUT not OUTPUT, my bad.
I assume that when that switch comes through, it will read as HIGH. If it doesn't then I guess I need to create a separate bool value to do "BeginTimer = digitalRead(switchpressed);" and then use that "BeginTimer" variable to activate my timer.
arduino boards allready have a built it timer that always runs. it just count up milliseconds from when the board powers ups.
you don't really need to code out a timer. you just need to record the current time when the switch turns on. then subtract that recorded time from the current time when the switch goes off.
Here is the code for one switch written as I suggested
const byte switchPin = A3;
void setup()
{
Serial.begin(115200);
while (!Serial);
pinMode(switchPin, INPUT_PULLUP); //use internal pullup resistor
Serial.println("Starting");
}
void loop()
{
unsigned long currentTime = millis(); //get the current time
static unsigned long onTime; //local variables to hold data
static unsigned long onPeriod = 0; //static enables them to retain data between calls
static byte previousState = HIGH;
static boolean isOn = false;
byte currentState = digitalRead(switchPin);
if (currentState != previousState) //test if input has changed state
{
if (currentState == LOW) //switch has become closed
{
isOn = true; //flag that the switch is on
onTime = currentTime; //save the time it came on
}
else //switch has become open
{
isOn = false; //flag that the switch is off
}
previousState = currentState; //save the current input state for the next time it is checked
}
if (isOn == true) //if the switch is on
{
onPeriod = currentTime - onTime; //calculate how long it has been on
Serial.println(onPeriod); //print the period in milliseconds
}
}
It can be made shorter by eliminating the boolean but by having it the code is easier to read.
More importantly the program can be made to work for any number of inputs with the addition of only a few lines of code
const byte SwitchPins[] = {2, 4, 3, 5, 9};
const int SwitchCount = sizeof SwitchPins / sizeof SwitchPins[0];
const char *SwitchNames[SwitchCount] = {"Desk 1", "Desk 2", "Front Desk", "Help Desk", "Desk 3"};
unsigned long SwitchCloseTime[SwitchCount]; // Defaults to 0
void setup()
{
Serial.begin(115200);
for (int i = 0; i < SwitchCount; i++)
{
pinMode(SwitchPins[i], INPUT_PULLUP); // Connect switch between pin and Ground. Goes LOW when closed.
}
}
void loop()
{
unsigned long currentMillis = millis();
for (int i = 0; i < SwitchCount; i++)
{
if (digitalRead(SwitchPins[i]) == LOW) // Switch closed
{
if (SwitchCloseTime[i] == 0) // If the timer for this switch is not already running
SwitchCloseTime[i] = currentMillis; // Start the run timer for this switch
}
else // Switch not closed
{
SwitchCloseTime[i] = 0; // Stop the timer for this switch
}
}
// For testing, show the queue every 5 seconds
static unsigned long showTime = 0;
if (currentMillis - showTime > 5000)
{
ShowQueue(&Serial); // For HTTP this would be '&client'
Serial.println("------------------");
showTime = currentMillis;
}
}
void ShowQueue(Stream *stream)
{
unsigned long currentMillis = millis();
for (int i = 0; i < SwitchCount; i++)
{
if (SwitchCloseTime[i] != 0) // Timer is running for this switch
{
unsigned long elapsedTime = currentMillis - SwitchCloseTime[i];
long int elapsedSeconds = elapsedTime / 1000; // 'long' needed for times over about 9 hours
int elapsedMinutes = elapsedSeconds / 60;
int elapsedHours = elapsedMinutes / 60;
elapsedMinutes %= 60; // Truncate to 0-59 range
elapsedSeconds %= 60; // Truncate to 0-59 range
stream->print(SwitchNames[i]);
stream->print(" has been waiting ");
// Show time as h:mm:ss
stream->print(elapsedHours);
stream->print(':');
if (elapsedMinutes < 10)
stream->print('0');
stream->print(elapsedMinutes);
stream->print(':');
if (elapsedSeconds < 10)
stream->print('0');
stream->println(elapsedSeconds);
}
}
}