Determining if RPI-GIO IN was triggered by change or from Startup/Initialization?

I have a project that is nearly complete and working well. The last piece to my project is to know if the RPI-GPIO IN was triggered by a change at the magnetic switch it is attached to, or if it was triggered because I have "Read State at Startup/Deploy"

When the RPI-GPIO IN is triggered, I send an SMS message that says "Opening" or "Closing"

I need to to send an SMS that says "Open" or "Closed" based on the state at startup.

If I new if the msg.payload was a result of the "Read State at Startup/Deploy", I would just generate different message.

Thanks for contemplating my issue and providing some hints! :slight_smile: :slightly_smiling_face:

JasGot

You probably know from Broadcom 2835 datasheet that some GPIO pins will start at LOW whereas others will default to HIGH at the initialization. So it is important to make sure that the initial state will not interfere or mislead your code.

w1

What I did in a similar case was to add a trigger node after the GPIO node. The trigger node has a status indicator that will tell you what is going on.

Here how it works for me. The GPIO node for the hall sensor is configured like below.

When the sensor is not activated the internall pullup will force the node output to HIGH. Because of the visual indicator in the trigger node I am sure that upon reload / flow deployment the trigger node is not being activated (even knowing that GPIO 21 goes low for a split second). I can visually see that the node output only goes LOW when the hall sensor is activated. Does this makes sense for you ?

Sorry, it does not. I will work through this as I understand your advice.

I have added a Trigger before my main logic starts, and I have attached both the Startup Inject and also my RPI-GPIO IN to it.

I'm not sure how to configure the Trigger

I deployed and got twice as many sms as I was expecting, so I know the trigger is working, I just need to configure it properly now.....

Any advice?

In my case I configured the switch node to send a zero and wait for 1 second. Whenever the trigger node receives something from the GPIO node it will display a small blue icon. This way I know if there is any signal transition right after the flow deployment (which is not happening). What is the GPIO pin you are using for your magnetic switch ? The switch outputs LOW or HIGH when activated ? Did you configure the pullup in the node ?

This won't tell me the current state of the Magnetic Switch. It will send a 0 and the nothing will happen until there is a change.

I need to know the state at start/deploy.

The trigger node will send a 0 whenever the GPIO node sends out a message. You want to capture transitions of the GPIO output, don´t you ? Normally GPIO 18 is pulled LOW at startup.

I don´t know how the underline libraries handle this short transitions. In my case triggering a low level at startup would mean to the flow "sensor activated" which would be troublesome. Fortunatelly this is not happening (and I dont know exactly why).

Anyway, this was just a suggestion to see if you can detect unwanted transitions. Perhaps not what you want.

I need to know the state at startup, and I also need to know if the msg.payload was sent as a result of startup or as a result of a change.

My RPI-GPIO In shows a "1" for Relay Closed and a "0" for Relay Open

I need to be able to send two different messages:

  1. If the state is open at startup I need to send an SMS that says "Door is Open".
  2. If the state changes to Open at some later time, I need to send SMS that says "Door is Opening"

So, my dilemma is this:
If my RPI-GPIO In is showing a "0" how to do I know if it just changed state from "1", or if it was in the "0" state at startup?

I see now. Our uses cases are in fact quite different and we are concerned about diffferent things. However you know the state at start/deploy because you checked the option "Read initial state of pin on deploy / restart" . What you don´t know is if there was some quick change after the deploy/restart that resulted in a state change. Also there is no way for you to know what happened while the restarting was taking place. Depending on your hardware it can take quite some time to reload. Maybe the state changed in between and you will never know. Oh my, I have no idea on how to get out of this trouble.

I assume that you always get an initial state at startup. In that case you know that the first state you receive is the startup state. So when you get the first message you can ignore it if it is 1 and send the "is open" message if it is zero. Then any subsequent 0 states should generate the "opening" message.

Yes. This would work!!!!

How do I determine if it is the first state or a subsequent state?

A function node after the input can hold context. So it can try to load the context value. If it fails then it’s the first time. So save a value in context. Next time the fetch will succeed

1 Like

Try as I might, I cannot turn your words into a node or a flow.

Can you look at this sample flow and tell me what I should put in the function? Thanks.

[{"id":"419e8a7f494d3e4a","type":"tab","label":"Flow 2","disabled":false,"info":"","env":[]},{"id":"2932b306144a1e8f","type":"rpi-gpio in","z":"419e8a7f494d3e4a","name":"Magnetic Switch","pin":"18","intype":"up","debounce":"250","read":true,"bcm":true,"x":175,"y":315,"wires":[["34bbb0599891a2ab"]],"info":"Magnetic Switch"},{"id":"34bbb0599891a2ab","type":"function","z":"419e8a7f494d3e4a","name":"function 6","func":"// Determine if the current state is the result of\n// Starting the Flow or a result of the door moving.\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":315,"wires":[["d513d9da6c6f4fe5"]]},{"id":"d513d9da6c6f4fe5","type":"switch","z":"419e8a7f494d3e4a","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"eq","v":"1","vt":"str"},{"t":"eq","v":"2","vt":"str"},{"t":"eq","v":"3","vt":"str"}],"checkall":"true","repair":false,"outputs":4,"x":565,"y":315,"wires":[[],[],[],[]]}]

How do I know it is the first message? and how do I know if it is a subsequent message?

The same way that you know yourself if something is the first time, by remembering that it has happened, and each time it happens then asking yourself if it has happened before. Something like this maybe

image

[{"id":"b456fa6c8611d688","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"0","payloadType":"num","x":130,"y":3400,"wires":[["04863fc8738c9a6e"]]},{"id":"f4340c78479e6781","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"num","x":130,"y":3440,"wires":[["04863fc8738c9a6e"]]},{"id":"04863fc8738c9a6e","type":"function","z":"bdd7be38.d3b55","name":"Determine door message","func":"// Get whether this is second or later from context, if not defined in context then set to false\nlet secondOrLaterMessage = context.get(\"secondOrLaterMessage\") || false\nif (msg.payload == 0) {\n    if (secondOrLaterMessage) {\n        msg.payload = \"Door is opening\"\n    } else {\n        msg.payload = \"Door is open\"\n    }\n} else {\n    // payload is 1 so ignore it and return nothing\n    msg = null\n}\n// remember that next message will be second or later\nsecondOrLaterMessage = true\ncontext.set(\"secondOrLaterMessage\", secondOrLaterMessage)\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":3420,"wires":[["d3b87771b9d48eb7"]]},{"id":"d3b87771b9d48eb7","type":"debug","z":"bdd7be38.d3b55","name":"debug 10","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":560,"y":3420,"wires":[]}]
1 Like

Thanks! That helped me make a lot of progress.

It is backwards in a couple of scenarios, so I am reversing the logic and hope to have it all working tonight.

I gave up. I installed Context Browser, and I found that the "Determine door message" "secondOrLaterMessage" context is always true. So I have no way to generate my startup status which will allow me to display "Open" instead of "Opening".

If you restart node red and click the 0 inject node in the flow I posted, what message do you get out?

"Door is Open"
But 0 means door is closed.

I may have it sorted now. A good night sleep was helpful!

1 Like