Slider Control values do not match actual state

I have found that slider values, as reported via the websocket sometimes do not match the actual state.

This is my relay control (main 24V on/off):

var power24v = 26
export var relay_status = digitalRead(power24v)
export function sliderRelay(x) {
  digitalWrite(power24v, (x > 0.5))
  relay_status = digitalRead(power24v)

So I can read the variable relay_status to tell if the relay is on or not, and use sliderRelay to turn it on and off.

The problem comes when I change the relay setting via websocket, the relay_status changes, but the UI does not, and neither does the sliderRelay value.

I get results like this:

[2021-05-14 14:52:46,388][ INFO](Pixelblaze.PixelblazeBase.Pixelblaze_79C309) publishing item: LED_Controller/pixelblaze/update: {"vars":{"relay_status":1,"masked":1,"r":0,"g":0,"b":0}}
[2021-05-14 14:52:46,484][ INFO](Pixelblaze.PixelblazeBase.Pixelblaze_79C309) publishing item: LED_Controller/pixelblaze/update: {"activeProgram":{"name":"Blank","activeProgramId":"ShzpfL53tXQDBLbRv","controls":{"sliderRelay":0}},"sequencerMode":0,"runSequencer":false}

If I change sliderRelay in the UI, the value changes, but not by sending
{'setControls': {'sliderRelay': 1}, 'save': False}

What I’m looking for is for the UI and value of controls to reflect the actual state of the control, when it is updated via the websocket. I have a feeling it’s to do with the 'save': False, because if I try with 'save': True it seems to work (ie the value changes, but the UI still does not). I don’t want to change the default every time I set the relay On/Off though.

So I think if you read the setting of controls, it’s not reporting the actual setting, but the saved setting - which for the UI is the same, but not if you change it via websocket (without save: True).

Not sure how to get the UI to update and reflect the actual setting either.

Any other suggestion for how to do this? otherwise the UI and websocket interface gets out of sync, and while it doesn’t really matter for speed etc, with Main Relay On/Off it’s kind of crucial to know what it actually is.


Hi @Nick_W ,
I recommend reading them via getVars so they are independent of the controls inputs, just like you have done with relay_status.

When a pattern is activated the controls values that are sent are the persisted values so that the UI can load the controls with values that match. I’m not storing the ephemeral controls values anywhere unless they are to be saved/persisted, they are only consumed via the control function handler.

The UI doesn’t currently receive notifications when state changes on the Pixelblaze for things like brightness or controls. That would be cool, and probably need some kind of pub/sub system to avoid flooding WS clients with too much spam, and a way for the UI to be smart about how it handles the echo of events for actions it requested.

An unrelated thing to be aware of, the input and output values for digital pins is not necessarily the same. Using digitalRead on an output pin will read the signal as interpreted by the input circuitry, rather than read the intended output driver level. A high load on an output pin may pull the signal below the input threshold and you can end up reading different values than you wrote. That could also happen with a capacitive load and a very short time period between writing and reading.

1 Like

@wizard ,

I hadn’t considered that reading an OUTPUT pin might not be valid.

Checking the ESP32 documentation, it says:

int gpio_get_level (gpio_num_t gpio_num )
If the pad is not configured for input (or input and output) the returned value is always 0.

And interestingly, a pin can be set for both input and output

esp_err_t gpio_set_direction (gpio_num_t gpio_num, gpio_mode_t mode )
GPIO set direction.
Configure GPIO direction,such as output_only,input_only,output_and_input

These are valid modes:

GPIO mode : output and input with open-drain mode

GPIO mode : output and input mode

So what mode do you set for a pin defined as OUTPUT? as I am reading back the value set by digitalWrite(), which implies the mode is INPUT_OUTPUT (or I would be reading 0).

It would be useful if you could include INPUT_OUTPUT as a mode, (or just make it the default for both INPUT and OUTPUT to avoid confusion).



Reading a pin gives you the apparent level seen by the input circuitry, not the output circuitry, and I don’t think that it is what you are after.

digitalRead reads from the input register, and does not use gpio_get_level().
pinMode(pin,OUTPUT) enables the output driver, pinMode(pin,INPUT) disables the output driver. The input circuitry is enabled in either case, and disabled only for pinMode(pin, ANALOG). It does not use gpio_set_direction.

So, if the input circuity is always enabled (assuming I don’t select ANALOG), and OUTPUT enables the output circuitry, then when I digitalRead() the pin, I will get the voltage level currently on the pin as set by digitalWrite() (given that they are the same pin).

That’s what I seem to get anyway, and that is what I am looking for, as my relay is connected to the pin (and I want to know what voltage level is being applied to the Relay, and hence the Relay state).

Is this correct? it does seem to work…