I'm working on a project that is designed to light up a games console, when that console is selected on a HDMI switcher.
I'm using the indicator LED's on the switcher I cannibalised as inputs, and have a star LED module over each console to light it up.
When you change the input, I want the light over that console to switch on, wait 5 seconds, dim, and then remain on until the input is changed again, when another input is selected, the one that was previously on, should turn off.
It's probably very simple, but I can't figure out how to do it!
Any help would be much appreciated.
int HDMI01 = A0; //HDMI indicator light one.
int light01 = 3; //Light corresponding to the first console
void setup() {
pinMode(light01, OUTPUT);
}
void loop() {
int HDMI01val = analogRead(HDMI01);
if (HDMI01val < 100){ //if <100 that input is on. I'll duplicate this code for each input -5-
digitalWrite(light01, HIGH);//light comes on
delay(5000);
for (int brightness=255;brightness>=20;brightness--){//light dims
analogWrite(light01,brightness);
delay(5);
}
delay(5000);
}
else {
digitalWrite(light01, LOW);
}
}
You have not said in what way your code does not do what you want.
The second 'delay(5000)' is probably not necessary unless you want the dimmed light to stay on for a minimum of 5 seconds.
Using delay() for sequence timing means that the inputs can't be checked until your sequence is done. That means if you change the input a light will go through the full light/pause/dim down sequence (over 6 seconds) before the inputs are checked again. If you want the lights to be responsive to input changes you will have to change from a delay() model to a millis() model. You would need to keep track of the currently selected light, what phase of operation it is in, and the time when that phase started. Phases would be something like OFF, ON_FULL, DIMMING, and ON_DIM.
johnwasser:
You have not said in what way your code does not do what you want.
Ah, new i'd miss something.
At the moment, the light turns on when it is supposed to, then after 5 seconds, it dims. After another 5 seconds it goes back up to full brightness and repeats this.
I need it to remain dimmed until the input is changed. (so i need the program to loop normally, but not change the output to that pin until the input changes.
johnwasser:
the second 'delay(5000)' is probably not necessary unless you want the dimmed light to stay on for a minimum of 5 seconds.
Using delay() for sequence timing means that the inputs can't be checked until your sequence is done. That means if you change the input a light will go through the full light/pause/dim down sequence (over 6 seconds) before the inputs are checked again. If you want the lights to be responsive to input changes you will have to change from a delay() model to a millis() model. You would need to keep track of the currently selected light, what phase of operation it is in, and the time when that phase started. Phases would be something like OFF, ON_FULL, DIMMING, and ON_DIM.
hmm, ok, I really have no clue how to make that work (millis), would you have any examples of this in practice?
If you are looking for an input to change, you need to record what it was the last time you looked at it. If it was HIGH and it still is HIGH then it hasn't changed.
Look in your Arduino examples menu for blink-without-delay. That uses millis. There is also a great example online called "several things at once."
You're probaly looking at a statemachine/sequencer implementation.
State 1
Wait for input activation; once detected, execute state 2
State 2
Led on for 5 seconds; once completed, execute state 3
State 3
Dim led; once done, execute state 4
State 4
Led permanently on; once done, execute state 5
State 5
Wait for input de-activation; once detected, exevute state 1
It's often implemented using a switch / case in the line of
void loop()
{
static byte currentState = 1;
switch(currentState)
{
case 1:
check input for high
if high, currentState++
break;
case 2:
led on
delay
currentState++
break;
case 3:
dim
currentState++
break;
case 4:
led off
currentState++
break;
case 5:
check input for low
if low, currentState = 1
break;
}
}
Ill have a look into the state machine you mention.
I have attached the next code i tried (trying to use millis to wait to dim instead of delay)
This seems to make sense to me, though i'm very new to programming.
However, the code seems to do nothing at all.
What am i missing, and is this a better way to deal with the dimming?
int light01 = 3;
int light01on = 0;
int light01fade = 0;
int light02;
int in01;
int in02;
int currenttime;
void setup() {
pinMode(light01, OUTPUT);
}
void loop() {
RecordCurrentTime();
CheckInputs();
onifinputon01();
}
//==========
void onifinputon01(){
if (in01 < 100){
digitalWrite(light01, HIGH);
currenttime = light01on + 8000;
}
else{
digitalWrite(light01, LOW);
}
if (currenttime < light01on){
digitalWrite(light01, HIGH);
}
else if (currenttime > light01on){
for (int light01fade=255;light01fade>=20;light01fade--){
analogWrite(light01,light01fade);
delay(5);
}
}
else if (light01fade == 20){
analogWrite(light01, 20);
}
}
//==========
void RecordCurrentTime(){
int currenttime = millis();
}
//==========
void CheckInputs(){
int in01 = analogRead(A0);
int in02 = analogRead(A1);
}
You never assign a time to current time
You have a global variable currenttime, but you update a local variable (in RecordCurrentTime); these are different variables. I suggest that you get rid of the RecordCurrentTime function as it does not really serve any purpose. And next update currenttime in loop()
void loop() {
// get current time
currenttime = millis();
CheckInputs();
onifinputon01();
}
I did not look at your other functions.
With regards to the statemachine, you can have a look at the below that implements a part of your requirement
void statemachine01()
{
static STATES currentState = WAITSTART;
// start time for time measurements
static unsigned long startTime = 0;
// inital value for fading
static byte fadevalue = 255;
// get current time
currenttime = millis();
switch (currentState)
{
case WAITSTART:
// reset fadevalue
fadevalue = 255;
// check input
if (in01 < 100)
{
// goto next state
currentState = ONFIVESECONDS;
}
break;
case ONFIVESECONDS:
// if delay not started yet
if (startTime == 0)
{
// switch light on
digitalWrite(light01, HIGH);
// set start time to current time
startTime = currenttime;
}
// check if time has passed
if (currenttime - startTime >= 8000)
{
// reset start time for use in next timing
startTime = 0;
// goto next state
currentState = DIM;
}
break;
case DIM:
// if delay not started yet
if (startTime == 0)
{
// set intensity
analogWrite(light01, fadevalue);
startTime = currenttime;
}
// check if time has passed
if (currenttime - startTime >= 5)
{
// check if all steps were done
if (fadevalue == 0)
{
// goto next state
currentState = ON;
}
// next fadevalue
fadevalue--;
// reset start time for use in next timing
startTime = 0;
}
break;
case ON:
break;
case WAITEND:
break;
}
}
You can fill in the missing parts. Call it from loop().
If you don't understand it, ask. I tried to make the comments as descriptive as possible (without writing a book )
void loop() {
// get current time
currenttime = millis();
CheckInputs();
statemachine01();
// for the other light (?)
statemachine02();
}