Reputation: 465
I have a program running on a Raspberry Pi, and I want to pull some data from a thermometer every 15 minutes at 0, 15, 30 and 45 minutes past the hour.
I have tried this using a while loop, I previously used time.sleep(900) effectively, but this sometimes drifted away from 0, 15, 30 and 45 minutes past the hour.
At the moment I currently have this;
from datetime import datetime
def run(condition):
while condition == True:
if (datetime.now().minute == (0 or 15 or 30 or 45)):
#perform some task
temperature_store()
For sake of simplicity I have not got into what temperature_store() does, but it reads the temperature from a sensor plugged into the Pi and then prints it.
I want temperature_store() to occur every 15 minutes, but currently, it is happening every second.
I am aware that it is probably because I have the logic/syntax of the while loop wrong, but I cannot figure it out. (Do not have much experience with python scripts and delays in time).
Upvotes: 6
Views: 15070
Reputation: 1218
There's two ways to do this: the 'easy' way, and the stable way.
The easy way is simply to do the following:
from datetime import datetime
from time import sleep
def run(condition):
while datetime.now().minute not in {0, 15, 30, 45}: # Wait 1 second until we are synced up with the 'every 15 minutes' clock
sleep(1)
def task():
# Your task goes here
# Functionised because we need to call it twice
temperature_store()
task()
while condition == True:
sleep(60*15) # Wait for 15 minutes
task()
This essentially waits until we are synced up with the correct minute, then executes it, and simply waits 15 minutes before looping. Use it if you wish, it's the simplest way in pure Python. The issues with this are countless, however:
The second method is to use cron-jobs
, as suggested in the comments. This is superior because:
So, to use, simply (assuming you're on Linux):
from crontab import CronTab
cron = CronTab(user='username') # Initialise a new CronTab instance
job = cron.new(command='python yourfile.py') # create a new task
job.minute.on(0, 15, 30, 45) # Define that it should be on every 0th, 15th, 30th and 45th minute
cron.write() # 'Start' the task (i.e trigger the cron-job, but through the Python library instead
(obviously, configure username
appropriately)
In yourfile.py
, in the same path, simply put your code for temperature_store()
.
I hope this helps. Obviously, go with the first methods or even the suggestions in the comments if you prefer, but I just felt that the entire loop structure was a bit too fragile, especially on a Raspberry Pi. This should hopefully be something more stable and scalable, should you want to hook up other IoT things to your Pi.
Upvotes: 8
Reputation: 465
I have come up with the following answer, using some of the logic from @geza-kerecsenyi 's answer
def run():
first = True
while first == True:
second = True
while second == True:
if datetime.now().minute == 0 or datetime.now().minute ==15 or datetime.now().minute ==30 or datetime.now().minute == 45:
action()
sleep(899)
I am not sure which of these is better in terms of CPU or which is more effective to run, but the logic seems sound on both.
[@geza-kerecsenyi will mark your answer as correct]
Upvotes: 0
Reputation: 161
I did the module test in case of the program that prints seconds every 15 seconds.
The below code does not contain sleep().
You can change second to minute in below code to do tasks every 15 minutes.
from datetime import datetime
while True:
a = datetime.now().second
if (a % 15) == 0: # every 15 seconds
print(a) # ---- To do something every 15 seconds ---- #
while True: # discard any milliseconds or duplicated 15 seconds
a = datetime.now().second
if (a % 15) is not 0:
break
But I think that cron or any other schduler modules are good choices.
Upvotes: 0