3

First post and I am at a dead end with this problem.

(some background) I have a raspberry PiZero which I am developing a weather station with, so far it logs temp, humidity and pressure as well as sending the data to the windy.com API. Recently I added a tipping bucket rain gauge. This has 2 wires which connect to the GPIO, when the bucket tips it momentarily competes the circuit, essentially a button press!

The goal here is to count the tips every hour, then reset. before resetting, send this data to log file + Windy API. This is the part I am struggling with.

I am pretty good with python but I am at a true writers block moment, here is a small program I cobbled together from snippets which counts the tips for testing

/usr/bin/python3
import requests
from gpiozero import Button
import time

rain_sensor = Button(27)
bucket_size = 0.2794
count = 0

    def bucket_tipped():
    global count
    count = count + 1
    print(count * bucket_size)

def reset_rainfall():
    global count
    count = 0


#display and log results
def timed_loop():
reset_rainfall
timeout = time.monotonic() + 3600   # 1 hour from now
while True:
    if time.monotonic() > timeout:  # break if timeout time is reached
        rain_sensor.when_pressed = bucket_tipped
        time.sleep(1)          # Short sleep so loop can be interupted
        continue
print count


  # close the log file and exit nicely
 GPIO.cleanup()
DanF
  • 47
  • 6
  • Your code is only logging/printing once every 5 seconds. The GPI add_event_detect may be incrementing, but you only log once per 5 seconds. The one thing I'm not sure about is how the "button press" is working. It might be that you are listening for an event that never happens. If the add_event_detect callback never happens then you will just log 0 every 5 seconds. – justengel Oct 12 '20 at 11:25
  • Thanks, if I manually operate the bucket whilst t's running I receive a value. However it's then resetting back to 0. How do I accumulate this over a specific person THEN reset? – DanF Oct 12 '20 at 12:31
  • I recommend to not pre calculate hourly sums or stuff like that. I would reccomend to store the raw data and derive rain rate from that data. You can use pandas with groupby to count hourly tips. – dl.meteo Oct 14 '20 at 07:33

1 Answers1

1

It looks like you are continuously setting your rain to 0 in your while True: loop.

Edit: Try something like this for your loop.

def timed_loop():
    rain = 0
    timeout = time.monotonic() + 3600   # 1 hour from now
    while True:
        if time.monotonic() > timeout:  # break if timeout time is reached
            # You place your code here that you want to run every hour. 
            # After that the loop restarts
            rain = 1  
            time.sleep(1)          # Short sleep so loop can be interupted
            continue

Edit 3:

With the following code you can record button presses over a specified amount of time.

import time

def bucket_tip_counter():
    recording_time_timeout = 3600  # Amount of seconds you want to have the timer run
    recording_time = time.monotonic() + recording_time_timeout
    button_timeout = 1  # This timeout is here so the button doesnt trigger the count more then once for each trigger
                        # You have to modify this to your needs. If the button stays activated for a few seconds you need to set the timer accordingly.
    count = 0           # Sets the counter to 0 at the start
    button = 0          # Here you need to replace the 0 with the GPIO pin that returns True if the button is pressed
    while True:         # starts the loop

        if button:         # if button gets pressed/bucket tipped
            count += 1     # up count by one
            time.sleep(button_timeout)  # wait specified timeout to make sure button isnt pressed anymore

        if time.monotonic() > recording_time:  # If the recording_time is reached the loop triggers this if condition
            print(count)   # print count
                           # Here you can also place code that you want to run when the hour is over
                           # Note that the counter wont start back up until that code is finished.

            count = 0      # set count back to 0
            recording_time = time.monotonic() + recording_time_timeout  # Set a new timer so the hour can start anew
            continue   # restart the loop

        time.sleep(1)  # small sleep to stop CPU hogging.
FrozenAra
  • 487
  • 1
  • 12
  • Thanks, is there a way to reset this outside the loop. For example, after 1 hour break the loop reset and go again? – DanF Oct 12 '20 at 12:29
  • perfect, that looks about what I'm after. so run my code block after > timeout: so right before timed_loop() send data to log then it will re-run? – DanF Oct 12 '20 at 13:04
  • Yes exactly. Everything in that if condition runs after the set time, In this case once every hour, and then starts anew. – FrozenAra Oct 12 '20 at 13:06
  • 1
    Thanks, I will give this a go and report back. – DanF Oct 12 '20 at 13:23
  • so far i have this, which so far just seems to break out the loop immediately and not time it. `def timed_loop(): reset_rainfall timeout = time.monotonic() + 3600 # 1 hour from now while True: if time.monotonic() > timeout: # break if timeout time is reached rain_sensor.when_pressed = bucket_tipped time.sleep(1) # Short sleep so loop can be interupted continue print count` – DanF Oct 12 '20 at 13:49
  • Hi, thanks for the update I'll try to break it down explain what i need. essentially the program needs to Count a button press from the rain gauge. and count these button presses over a certain time period (1 hour) Once we have our count we know the amount of rain that fell in that hour. send this data to Windy, Reset and start again. sorry I wasn't very clear, also thanks for the update i'll give this a shot – DanF Oct 13 '20 at 08:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/222948/discussion-between-danf-and-frozenara). – DanF Oct 13 '20 at 08:59