Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possibility to have gpio outputs inverted #13

Closed
joe-ave opened this issue Oct 7, 2022 · 12 comments
Closed

Possibility to have gpio outputs inverted #13

joe-ave opened this issue Oct 7, 2022 · 12 comments
Assignees
Labels
enhancement New feature or request

Comments

@joe-ave
Copy link

joe-ave commented Oct 7, 2022

Hello,
looking thru the schematics of many of the relayboards with optoisolaters available for arduino/esp/rpi etc. most of them need a low pulldown signal to activate the relay.
So maybe there should be an option of some kind that the output could be inverted?

//Jonas

@Olli69
Copy link
Contributor

Olli69 commented Oct 7, 2022

Tack för idén, Jonas!
I just try to figure out the case. Maybe you could give an example of a board model/setup, please? Maybe, at least in some cases, you could also invert the result by wiring? I mean if there are out both NO "normally open" and NC "normally closed" (which are reverse) in the relay, you just select the right terminal to get the correct result?

Inverting the output would of course be quite simple in the program logic. But additional parameters in the channel configuration would always make the user interface a bit more complex - something we try to avoid if easily possible.

Olli

@joe-ave
Copy link
Author

joe-ave commented Oct 7, 2022

Hi Olli!,

9277b82e552fc8d5b16d3de2996d1f47ef1d7272

Borrowed picture from https://forum.arduino.cc/t/4-channel-relay-board/268035/4

Most of them seem to have this type of setup, the channels have common vcc and to activate the relay the input needs to be pulled low.
And yes the easy way is to connect the function to to a NC contact instead but the failsafe position ( if the ESP is powered off for instance and the outputs will be sort of floating ) would be constant on and that might cause trouble dependent on what you are controlling.
Maybee you could just have a new output type, like "Relay inverted" the you do not need additional parameters and/or checkboxes.
//Jonas

@Olli69 Olli69 self-assigned this Oct 8, 2022
@Olli69
Copy link
Contributor

Olli69 commented Oct 8, 2022

Hi Jonas,
So let me know if I have understood it right:

  • The issue is limited to gpio relays and how they "behave" in the case of failure of the ESP32.
  • If you are controlling a device with an external relay/conductor, you can use failsafe wiring (connect to NC terminals on both gpio and external relays, see relay 2 in the diagram on the wiki article . This wiring is also resilient to ESP32 power supply failure (or intentional switching off the power).
  • But if you are connecting your device directly to the ESP32 relay (e.g. a potential free input of a heat pump) you cannot freely select the failsafe state of that interface.
  • Basically, you could inverse all channel rules in the channel configuration (e.g. UP<->DOWN), but that would make the rules very hard to understand and you could not use rule templates directly.
  • Potential new relay/channel type "GPIO user-defined, inverted" (or "GPIO user-defined, failsafe") would solve this issue. UI for that type would work as for type "GPIO user-defined".

State chart

# Description Channel state Normal NO Normal NC Inverted NO Inverted NC
1 ESP power off / failure ? open (a) closed (a) open (b) closed (b)
2 Channel down DOWN open (a) closed (a) closed open
3 Channel up UP closed open open (b) closed (b)

In case of ESP32 failure:

  • Normal relay type states (a) equal to channel state DOWN.
  • Inverted relay type states (b) equal to channel state UP.

@joe-ave
Copy link
Author

joe-ave commented Oct 8, 2022

Hello Olli,

the main thing is that I want the relay that I am controlling to be energized when the channel in Arska indicates up and is green, most external relayboards seem to use a low signal to energize the coil but some a high signal.

I tried "Target State" set to "DOWN" but then it seems like the channel allways indicates "Down" and never turns (high) on regardless of how the rules are set, tried with "P diff to avg 24h".

I think the "GPIO user-defined, inverted" is the way to go to solve this, you do however need to consider how you initialize the outputs so that they are set high (if inverted!) before they are set as outputs, in the Arduino enviroment I do something like this in setup:

#define Relay_1 38
void RelaySetup (){
digitalWrite (Relay_1, HIGH);
pinMode (Relay_1, OUTPUT);
}
This is to prevent the relay from going "click-click" at startup since outputs are set low by default when pinMode are set, otherwise they are low until the code a few ms later tells them to be high.
And instead of "HIGH" you could point to a bool that you previously read from eeprom (also in setup) that holds the "GPIO user-defined" type.
//Jonas

@Olli69
Copy link
Contributor

Olli69 commented Oct 9, 2022

Hi Jonas,
Thanks! Now I (finally, hopefully, 😃) got your point about external relay boards. I have been thinking about how to make setups failsafe (defined state if ESP32 or ESP32 power supply is down) in various cases. Generally, I'm focusing mainly on boards with integrated relays to keep the basic setup simple (no soldering, etc. needed in basic cases). But of cause, it is good to have a working solution for external relay boards too and it seems to be analog with potential-free/dry contact case as you mentioned.

About that "Target State set to DOWN" thing you mentioned, A few points about rule conditions - hopefully, these will explain the case - please let me know if not:

  • A channel is DOWN by default
  • Rules are matched in order (1,2,3) and after the first match (don't care about target state), the following rules are not tested. So, if e.g. rule 2 has a target state DOWN and is matched, rules 3 and 4 are not tested but the channel will be DOWN.
  • If you want to have a channel be UP by default (no other rule is matching), you should add a rule which always true with the target state UP to the end of the rule list. There is not currently dummy always/newer variables but eg. "mm, month">0 is always true.
  • There is some delay (max 60 secs) before channel states are recalculated and there is only one channel state change per round (60 secs). The user interface has also some delay. So it takes some time before channel states are updated.

I tested with ESP32/LilyGo with integrated optoisolated relay modules following code and pinMode did not seem (no "click") set output LOW (if set HIGH before restart). Could it be caused by a difference between Arduino/ESP32, individual board design/random, depends on gpio (settings)... . Requires some further investigation to avoid that "inversed click-click" after the boot/init (if it issue with ESP32). Maybe that extra digitalWrite (pin, HIGH); for inversed in the init. Currently up/down status is not updated to eeprom after channel state change (only after settings change), to avoid memory wear-out caused by frequent writes. So currently, Arska does not know gpio states just after a reboot.

  // testing pinMode in beginning of setup() 
  Serial.println("pinMode OUTPUT, sleep 10");
  pinMode(5, OUTPUT);
  delay(10000);
  Serial.println("digitalWrite HIGH, sleep 10");
  digitalWrite(5, HIGH);
  delay(10000);
  Serial.println("restart");
  ESP.restart();

@joe-ave
Copy link
Author

joe-ave commented Oct 9, 2022

Hello Olli,

thanks for the advice about "Target State set to DOWN"!, with that workaround the rules works during normal operation but it´s just a little confusing when you look at it as the channel will indicate down when rule 1 is fulfilled and the external relay will activate, and rule 2 will indicate up and the external relay is deactivated when rule 1 is not fulfilled.

However, if I the rules are set so that rule 2 is up that puts the gpio high to have the external relay deactivated and then restart the board with the reset button the external relay will go on/off after approx. 22 seconds, when the wifi has been connected, duration maybe 0,5 second.

It happens right after the wifi is connected, probably when this line is printed on the serial:
set_state, channel: 0, on: 0 , off: 1665320235, utilization: 0.000000

and the turns high and deactivates the external relay when this lines is printed 0,5 sec later:
channel_idx 0, condition_idx 1 matches, channel wanna_be_up: false
set_relays rise_count: 1, drop_count: 0
Switching ch 0 (16) from 0 .-> 1
set_state, channel: 0, on: 0 , off: 0, utilization: 0.000000
1665255436

You will probably not see this with the internal relayboards that use an active 1 to activate the relays.

//Jonas

@Olli69
Copy link
Contributor

Olli69 commented Oct 9, 2022

Hi Jonas,
Do you think the new type "GPIO inversed" would solve what you wrote in the comment? I have implemented the first versions of it, but haven't had yet time to test it.

Olli

@joe-ave
Copy link
Author

joe-ave commented Oct 9, 2022

Hello Olli,

it should solve the confusing down/up workaround, and if the inverted gpio’s are initialized high the ”click/click” behaviour should go away during startup.

//Jonas

@Olli69 Olli69 added the enhancement New feature or request label Oct 10, 2022
@joe-ave
Copy link
Author

joe-ave commented Oct 11, 2022

Hello Olli,

on my local version I did this:

high before initialized

and

inverse of output

, this solved the issues for me so the relays don´t go "click-click" during startup and the rules work normaly.
I needed to write to the output first before pinmode was set, otherwise the relay led would blink for a brief moment, not long enough to energize the relay though.

You could probably create a new "set_channel_relay_inv" and "set_gpio_pinmode_output_inv" that do this and is called instead if "GPIO inversed" is selected.
But you probably already did something like this in your test version?

//Jonas

@Olli69
Copy link
Contributor

Olli69 commented Oct 11, 2022

Hi Jonas,
I will still check that once more, but when I tested with the piece of code in my earlier comment, the line did stay HIGH after pinMode(x, OUTPUT). I just wonder if we do something differently or could there be differences between our boards?

Anyway, pinMode is needed only once per gpio, but now it is called before every digitalWrite. Maybe removing excessive calls to pinMode helps.

I just pushed latest version (not well tested) to devel branch. It makes pinMode call only in init.

Olli

@joe-ave
Copy link
Author

joe-ave commented Oct 12, 2022

Hello Olli,

I poked in your latest 0.92-RC3 from the install page and it seems to work!, you can however see a brief blink ( not enough to energize the relay ) a couple of seconds after powerup.
Besides that the logic rules seems to work when "GPIO, inversed" is tested with my setup!

//Jonas

Edit:
I found this also: https://community.particle.io/t/can-i-not-call-digitalwrite-before-pinmode/49920, maybe digitalwritefast should be used?

//Jonas

@Olli69
Copy link
Contributor

Olli69 commented Oct 15, 2022

Hi Jonas!
Sounds good! I moved relay init (setting to default channel down) to the beginning of setup(), so it goes to the failsafe mode even though there would be problems with the wifi - there you probably saw the blinks.

Thanks for the link. There seem to be ...fast versions for AVR environments but I couldn't find them for ESP32. I could not see blinks on my test board with test led and no change in the relay. Maybe the capacitance of the connected relays slows down the change - and normally there is some kind of relay connected. But let's see if this (blink) could cause problems in some future setups - then there is probably a possibility to fix it with software or hardware (capacitor?).

Olli

@Olli69 Olli69 closed this as completed Oct 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants