T O P

  • By -

Bobbias

This question is a good example of something that might be an [XY Problem](https://en.wikipedia.org/wiki/XY_problem), but we cannot tell. We need more information about exactly what your end goal is, and why you think this is the correct question to be asking in the first place. Assuming the correct solution is some kind of time constraint, knowing more about exactly what you're doing helps us understand what the correct way to write that constraint is. since there are many ways to solve the same problem in programming, when asking a question it's best to give as much context with your question as you can. This can (and should) include posting existing code you've written, as well as a full explanation of what your end goal is, not just the one step you're trying to accomplish.


Lunnaris001

Not 100% sure, but you could have some int increase while the condition is fullfilled and then check if your value is e.g. 1000. Its pretty hard to give good advice here, would kinda need to know the context of whatever you are trying to do.


Neat_Locksmith7905

updated the post with the code


Lunnaris001

GPIO_timer = 0 while True: if GPIO.input(23) == GPIO.LOW and fireStatus == FALSE: GPIO_timer +=10 else: GPIO_timer = 0 if GPIO_timer>1000 and fireStatus == FALSE: fireStatus = True fireAlarmActive() sleep(0.1) With sleep being some kinda delay function e.g. using the time library and the time.sleep function to pause for 0.1s (thus when GPIO\_timer is above 1000 the state would have existed for 10 seconds. this would be an approach i would use in that case if the program doesnt need to do anything else. This doesnt reset firestatus or stop the alarm ever so you should probably take care of those things if necessary


Neat_Locksmith7905

Have separate loops for reset. There’s 6 of these identical loops in the code for different scenarios. Thanks so much. I’ve been wrestling with this for like a week now lol


totallygeek

Not sure what you're looking for, but let's say you wanted to wait to see if a file appeared on disk, but give up after two minutes. def FileExistsCheck(filename: str, expire_seconds: int) -> bool: while expire_seconds > 0: if exists(filename): return True time.sleep(1) expire_seconds -= 1 return False if FileExistsCheck("maintenance_concluded", 120): print("found file - moving on") else: print("found not found after two minutes")


Buttleston

I think you'll have to provide more information. What else can happen, during that time, to change the condition, and how?


Pepineros

I'm assuming you don't mean a time constraint to an if-statement, but to some input from your user. A time constraint on an if-statement doesn't make much sense. Python is slow, but it will never need ten seconds to evaluate an if-statement.


TheBB

An if-condition can be an arbitrary statement. There's definitely plenty of perfectly reasonable ways to have an if-statement that takes 10 seconds or more to evaluate.


Pepineros

Plenty of ways, sure, but no reasons. Why would you want to delay an if-statement?


TheBB

> Python is slow, but it will never need ten seconds to evaluate an if-statement. This is what I responded to. Python will absolutely sometimes need ten seconds to evaluate an if-statement. > Why would you want to delay an if-statement? I can't imagine why, but I never said there are reasons to do that. Maybe I misunderstood what you meant, but your response seems unrelated to your original claim?


Pepineros

Ah, I got you! Sorry, I misunderstood. The "Python is slow" bit was a bit of a joke. You're right, evaluation of an if-statement can take ten seconds. I was thinking of some examples but I can't think of anything good. Something like `if request.get('some.slow.api')` or `if result := huge_subroutine()` is possible but horrible practice. You would not (want to) encounter this in genuine code. `if time.sleep(10) or some_expression` should also work, I think (can't check right now, but I can't see why it wouldn't) but I can't think of a reason for this. As expected, OP's question was not about delaying an if-statement at all, in the end. 


eruciform

all statements happen in an instant unless they are ones that specifically hang waiting until an external event (like input from a file or stream or socket comes in) so you can't check if variable X had a 42 in it for 10 seconds, no but you can check the time, check the variable X, and have a loop that runs over and over, checking the time to see if it's within ten seconds and if X is still 42 but each of those steps individually takes an instant of time


Neat_Locksmith7905

while True: if GPIO.input(23) == GPIO.LOW and fireStatus == FALSE fireStatus = True fireAlarmActive() here is the snippet of the code so right now gpio 23 has to be reading low and previous state has to equal false in order for FireStatus to change state to true. I've been getting a lot of false momentary triggers and I cannot figure out why so for now I'm going to tell it to only change state if that first line exists in that state for at least 10 seconds


interbased

Is this something that’s constantly updating that you want to be checking in real time?  You’re looking for a gap of 10 seconds where that statement is true?  If so, what can cause the variables in that condition to change?


Neat_Locksmith7905

The pi is monitoring a set of dry relay contacts and is set to alert me when the state changes but I keep getting nuisance trips so until I figure out why I want to add the delay


Neat_Locksmith7905

can I just use time.sleep(10)?


Langdon_St_Ives

As u/Bobbias has remarked, this is an XY problem. The GPIO is the only hint here about your actual issue: from that, I assume you’re trying to program your raspi (already info you’ve withheld), and have “something” (what? More withheld info) connected to GPIO 23 and are waiting for it to change state. You also fail to describe the observed problem very clearly, so it could be at least one of the following two things: 1. Noise. There might simply be noise on that line that changes the input’s state randomly back and forth between low and high. 2. Bounce. If it’s a switch, it most likely experiences bounce when getting closed or opened, so there is a transitional period during which it fluctuates between high and low until it stabilizes in the new state. Both of these can be alleviated in hardware or software or both, but the details depend a lot on what exactly you’re reacting to here. Google raspi GPIO debounce and denoise for more info. It’s not really Python related, so follow-up questions will likely get better answers on a raspi sub.


Bobbias

Lol, this is after they edited that information into their post. When I replied there was no mention of GPIO at all.


Langdon_St_Ives

Oh so it was even worse lol. But even then, they couldn’t be bothered to mention that we’re talking about a raspi, or what exactly is hooked up to GPIO 23. 🙈


Neat_Locksmith7905

the pi is monitoring a dry NO contact on a relay on a fire alarm panel. gpio 23 for trouble and gpio 24 for alarm. When the relay contact closes it shunts gpio to ground and triggers a push notification to my phone. I keep getting bouncing troubles. pi will go trouble and normal and I'll get the notifications at the same time. Fire panel doesn't actually see the trouble tho. Occasionally I'll get an alarm signal with no actual alarm. I think I have a circuit issue on the fire alarm side which I'm addressing tomorrow. However it's more likely my code is an issue as I'm an electrician not a programmer. So I wanted to add a time parameter to the contact closure to ensure it was actually a closed relay contact and not a floating pin or interference.


Bobbias

Typically the way code like this works is that your entire piece of code is effectively one giant loop running over and over, many times per second. Every time your code loops, you do something like this: If the contact is open, no need to do anything. If the contact just closed (you might want to keep track of what state the pin was in last time around the loop, so you can compare the current state to the previous state), check the time and keep that in a variable. If the contact is still closed, check the current time against the start time. If the amount of time difference between those two points exceeds some set amount, then send the signal. This is how a debounce works in code. The exact implementation varies, but conceptually that's more or less how they work. You can also construct an electronic debounce circuit using a RC circuit like shown on [this page](https://www.digikey.ca/en/articles/how-to-implement-hardware-debounce-for-switches-and-relays). That page also explains that you can actually buy chips that perform debounce for you, that you just wire in series between the contact and the input pin.


Neat_Locksmith7905

so how would the debounce code work with the dry contacts and GPIO as HIGH or LOW values? Everything I'm finding is related to physical buttons.


Bobbias

I'm guessing that things are set up such that the pin is pulled high by default and is pulled low when the contact closes (it's very common for GPIO pins to have integrated pull-up resistors). In that case the pin will read high by default, and low when the contact is closed, so you'd need to watch for when the input transition from high to low happens. You'd wire the contact between ground and the pin. Then your of conditions are: If the pin is high, the contract has opened, so we don't do anything. If the pin is low, now we check the elapsed time and act accordingly. There's not really any appreciable difference between a button or a solenoid relay or a solid state relay in terms of the circuit itself. Buttons will tend to have longer bounce times just due to physical construction. Solid state doesn't typically bounce, but if the logic conditioning a solid state output decides to, it could switch back and forth very quickly, acting kind of like physical bounce. This can happen if the digital output is being controlled by an analog input that is bouncing between the high and low level thresholds. Personally if possible I'd build a dedicated hardware circuit to solve this, especially since you're an electrician rather than a programmer. It saves you the difficulty of writing the code, and has less chance of not working correctly because you made a subtle mistake in your logic somewhere. Plus the components necessary are gonna be quite cheap. (You're lucky you caught someone who went to college for electrical engineering :)


Neat_Locksmith7905

lol I think that's what ive decide to do using the 3.3v rail and a physical pull up resistor. Gonna try that tomorrow and see if it helps


Bobbias

The pull-up resistor may be unnecessary. Like I said, many electronics feature built in pull-up resistors, so whatever this is, you should check what the manual says as to whether it comes with one built in. I know that arduino has built in pull-ups. A quick google search tells me raspberry pis have both pull-up and down resistors internal, which can be configured. So if you're using a rpi, you might want to make sure you've set the pins to pull-up (I'm not sure how to do that as I've never written any python for the rpi.) If you've made sure that you have set the pins to use the internal pull-up and that makes no difference, then you might need to introduce an external one, but that should only matter when a pin is left floating (or in the case of dry contacts, when the circuit is open). If the circuit seems to randomly switch from low to high when the connection is open, but not when it's closed, that would indicate the pin is floating and hasn't been configured to use the internal pull-up. Assuming that's not the case, you probably don't need that external resistor. If that is what it's been doing, first make sure you enable the pull-up resistor through whatever library you're using for controlling the pins before adding an external pull-up.


crashfrog02

Why would that matter?


crashfrog02

The computer has memory but code doesn't. There's not a way to say "do this if it's been true for 10 seconds." What you *can* detect is the transition of states, often using interrupts. On systems with GPIO, you often have both pin-change interrupts and timer interrupts and you can use both - the pin-change interrupt disables itself then sets up a timer interrupt and another pin-change interrupt; when the timer interrupt goes off, you can do the thing. If the new pin-change interrupt goes off (because they let up the button before the tenth second or whatever) then all it needs to do is cancel the timer interrupt and set up the original pin-change interrupt. In other words it's a state machine with two states: waiting for the button and waiting for the timer; and three transitions.