Latching Outputs??

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 :wink:

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 :smiley: )

void loop() {
  // get current time
  currenttime = millis();

  CheckInputs();

  statemachine01();

  // for the other light (?)
  statemachine02();
  
}