Control two leds simultaneously

Hi!

I followed the docs and created two things, ledBack and ledFront.
I added both in my dashboard as a on/off switch.
Clicking the first switch will properly switch the state of the ledBack.
But clicking the second switch results in a very quick moment (barley noticeable) of turning the LED on, but directly toggling back to the off state. The switch in the dashboard will also go back to the off state.

What is actually causing the behaviour?

int ledBarBackPin = 8;
int ledBarFrontPin = 9;

void setup()
{
  pinMode(ledBarBackPin, OUTPUT);
  pinMode(ledBarFrontPin, OUTPUT);

  thing["ledBack"] << digitalPin(ledBarBackPin);
  thing["ledFront"] << [](pson& in){
    digitalWrite(ledBarFrontPin, in ? HIGH : LOW);
  };

}

(in the end I hope to by able to use the second function so I can switch two LED’s at once, using just one switch)

1 Like

Hi, this is a good question. I expect to be able to explain it properly.

The dashboards works in a way that when you open them, they query the associated resources to correctly print the correct state, i.e. the switch is on or off. In this way, when the dashboard is open, each associated resource is called, receiving empty data in the input, as there is no intention to control the resource (the pson input will be empty)

So, how the dashboards know what is the current state of an input resource? The resource must set its current state in the input parameter, if it is empty, or use the input value if there is one. This way we can obtain three different things: query the current resource state (without modifying it), modify the current resource state, and based in (1), obtain the expected input on the resource (this is how the API explorer on the device works).

If you look at the definition of digitalPin (that is the example in your code that actually works as expected), you will see something like the following:

void digital_pin(protoson::pson& in, int pin){
    if(in.is_empty()){
        in = (bool) digitalRead(pin);
    }
    else{
        digitalWrite(pin, in ? HIGH : LOW);
    }
}

That basically returns the current pin state if there is no input control, or use the incoming data to control the led.

So, when you switch a button in the dashboard, the resource is receiving a control, which modifies the current pint state, but when you query the resource in your definition, nothing is being set in the input to know the current resource state. So, the dashboard receive an empty state resource, which is translated to a false state in the dashboard.

So, if you want to correctly send feedback to the dashboards or the api explorer about the resource state, you must set the current state if the input to the resource is empy. Otherwise, consume the input to update the resource state.

Hope it is more or less clear!! Let me know if you need more details :slight_smile:

Regarding your use case, the code can be done in the following way:

thing["twoLeds"] << [](pson& in){
   // define a variable in this method to control the current state of both leds
   static bool currentState = LOW;
   // if input is empty, return the current control state
   if(in.is_empty()){
     in = currentState;
   }else{
     // update current resource state
     currentState = in;
     // control two digital pins
     digitalWrite(ledBarBackPin, currentState ? HIGH : LOW);
     digitalWrite(ledBarFrontPin, currentState ? HIGH : LOW);
  }
};

Hope it helps!

Hi @alvarolb!
Thanks for the very detailled response, that indeed really helps to understand what’s going on!
Thanks so much.

Quick thought tough: wouldn’t it be good to add this information to the docs as well? Right now the docs suggest that my initial try would be working…

Thanks for the suggestion @dhunink ! I will add this information in the documentation! :slight_smile:

Funny, I’ve rewritten the code like this:

 // control two digital pins
 digitalWrite(3, currentState ? HIGH : LOW);
 digitalWrite(4, currentState ? LOW : HIGH);

and I got two toggleable LEDs on D3 and D4. :slight_smile: