GPIOZERO Measure time of inactive/active state of digital input - python

I have a dust sensor, and I have to measure a sum of inactive time in 30 seconds cycles.
For DigitalInputDevice gpiozero provides cool functionality, I mean two properties, and two callbacks:
properties - active_time (return float if pin is active or None) and inactive_time
(return float if pin is inactive or None),
callbacks - when_activated and when_deactivated
I thought that inside those callbacks I would have access to the digit input in the previous state, which would allow me to grab active time when pin change state to inactive, and inactive time when pin change state to active, but I was wrong.
So my question is: There is any possibility in this library to grab a whole active time when pin turns to inactive and vice versa?
Thank you!
Clarification: what I want is described in the image below
image of chart my sensor docs: https://botland.com.pl/index.php?controller=attachment&id_attachment=1565
I do it now in this way:
from gpiozero import DigitalInputDevice
from datetime import timedelta
import time
sensor_one_micrometer = DigitalInputDevice(20)
while True:
active_time = 0
inactive_time = 0
sensor_one_micrometer.wait_for_active()
while active_time + inactive_time < 30:
watch_start = time.time()
sensor_one_micrometer.wait_for_inactive()
active_time += time.time() - watch_start
watch_start = time.time()
sensor_one_micrometer.wait_for_active()
inactive_time += time.time() - watch_start
percent = inactive_time/(active_time+inactive_time)
print("Active Time: ", active_time)
print("Inactive Time: ", inactive_time)
print(
inactive_time/(active_time+inactive_time)
)

Related

How to count time interval on raspberry pi 4?

How can I count the time interval on Raspberry Pi 4 ? I have connected a magnetic switch sensor to the Pi and a Piezo buzzer. The Piezo buzzer must turned ON if the magnetic switch sensor input value equal 1 for more than 2 minutes. otherwise the piezo buzzer must be turned off.
I have used the function millis() on Arduino to measure the time interval like this :
long previoustime = 0;
long interval = 30000; //5 minutes
long currenttime = millis();
if (i == 5){ // Password correct open the door
setLocked(false);
previoustime = currenttime;
}
if (currenttime - previoustime >= interval) {
if(ServoMotor.read()==90){
setLocked(true);
i=1;
}
}
But it's different for the Raspberry Pi I have tried several functions but nothing works. Here is my code (without the time interval counter ) :
import RPi.GPIO as GPIO
import time
PizeoPin = 31
MagneticSwitchPin = 12
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
#Set Magnetic contact switch sensor as an input
GPIO.setup(MagneticSwitchPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(PizeoPin, GPIO.OUT)
GPIO.output(PizeoPin,GPIO.LOW)
while True:
if GPIO.input(12):
print("opened")
GPIO.output(PizeoPin,GPIO.HIGH)
time.sleep(1)
if GPIO.input(12) == False:
print("closed")
GPIO.output(PizeoPin,GPIO.LOW)
Can anyone help me to correct it please ?
This should work as you wanted. It won't be exactly 2 minutes but should be close enough for your purposes.
from collections import deque
interval = 60 * 2 # 2 minutes to seconds
vals = deque([False]*interval, maxlen=interval)
buzzing = False
while True:
vals.append(GPIO.input(MagneticSwitchPin))
if not buzzing:
if all(vals):
print("opened")
GPIO.output(PizeoPin,GPIO.HIGH)
buzzing = True
if buzzing:
if not all(vals):
print("closed")
GPIO.output(PizeoPin,GPIO.LOW)
buzzing = False
time.sleep(1)

How to automate control of Wemo light switch based on iPhone GPS

I'm writing a program to toggle the lights at my house based on my iPhone's GPS coordinates. Below is what I have so far. However, I feel like there must be a better way to do this. Is there a way to get GPS data without pinging my phone every five minutes?
So far I've tried the following with no joy:
Using Shortcuts and Scriptable I tried to write some JavaScript that would trigger when I got close to home. However, I could not figure out how to use await require('wemo-client') using scriptablify. I kept getting an error, "ReferenceError: Can't find variable: require".
IFTTT does not have a variable timed trigger so the lights won't turn off after 15 minutes. Also, I plan on adding a motion sensor trigger that is unsupported.
Pythonista is $10. Yes, I am that cheap.
Apple HomeKit does not support the model I'm using, Wemo Smart Light Switch F7C030.
The code below works, but I hate that I have to ping my phone every five minutes. I'd rather save battery life by firing this code once or twice a day, as needed.
Any suggestions would be greatly appreciated.
Code:
import sys
import time
import datetime
import os
from pyicloud import PyiCloudService
import pywemo
APPLE_ID = os.getenv('APPLE_ID') # Apple ID username
APPLE_ID_PASSWORD = os.getenv('APPLE_ID_PASSWORD') # Apple ID password
API = PyiCloudService(APPLE_ID, APPLE_ID_PASSWORD)
IPHONE = API.devices[1]
LOCATION = IPHONE.location()
FIVE = 300 # 5 * 60 seconds
FIFTEEN = 900 # 15 * 60 seconds
ONEMILE = 0.01449275362318840579710144927536 # one mile is 1/69 degrees lat or long
HOMELAT = # my home's latitude
HOMELONG = # my home's longitude
WEMOS = pywemo.discover_devices()
LEN_WEMOS = range(len(WEMOS))
# Two factor authentication to retrieve iPhone data
if API.requires_2fa:
import click
print("Two-step authentication required. Your trusted devices are:")
DEVICES = API.devices
for i, device in enumerate(DEVICES):
print(" %s: %s" % (i, device.get('deviceName', "SMS to %s" % device.get('phoneNumber'))))
DEF_DEVICE = click.prompt('Which device would you like to use?', default=0)
DEVICE = DEVICES[DEF_DEVICE]
if not API.send_verification_code(DEVICE):
print("Failed to send verification code")
sys.exit(1)
CODE = click.prompt('Please enter validation code')
if not API.validate_verification_code(DEVICE, CODE):
print("Failed to verify verification code")
sys.exit(1)
# Turn off the lights when I leave
def leavehome():
timenow = datetime.datetime.now()
print("Left home on {}".format(timenow.strftime("%B %d, %Y at %H:%M:%S")))
for wemo in LEN_WEMOS:
WEMOS[wemo].off()
# Turn on the lights for 15 minutes when I get home
def arrivehome():
timenow = datetime.datetime.now()
print("Arrived home on {}".format(timenow.strftime("%B %d, %Y at %H:%M:%S")))
# Loop through all Wemo devices
for wemo in LEN_WEMOS:
WEMOS[wemo].on()
time.sleep(FIFTEEN)
for wemo in LEN_WEMOS:
WEMOS[wemo].off()
# Automatically turn off the lights after 15 minutes - save electricity
def timeoff():
time.sleep(FIFTEEN)
for wemo in LEN_WEMOS:
WEMOS[wemo].off()
# Ping my phone for GPS data
def pingphone(prev):
mylat = LOCATION["latitude"]
mylong = LOCATION["longitude"]
logic(prev, mylat, mylong)
time.sleep(FIVE)
# Perform logic to determine if I'm home, out, arriving, or leaving
def logic(prev, lat, long):
inrange = (HOMELAT+ONEMILE >= lat >= HOMELAT-ONEMILE and HOMELONG+ONEMILE >= long >= HOMELONG-ONEMILE)
current = bool(inrange)
previous = prev
if current and not previous:
arrivehome()
elif previous and not current:
leavehome()
else:
timeoff()
pingphone(current)
# Run the script
pingphone(False)

Python time between x and y run code. And no code if time between xy

Im gonna try and explain to the best of my efforts.
Script im running is below.
I want to include something that will make the pir sensor not do anything between the hours of 24:00 and 05:00. But the button should work at those times regardless.
Also i want to be able to send different colors at certain times of the day.
So that if its between 8pm and 11 pm it will give this code to the lights: {"on":true,"bri":255,"sat":80,"hue":357}
There will be 4 colors in total. I have tried defining the command called with command(): and the colors but im at a standstill here.
Can anyone help me with this? I do really hope i made myself clear here, but fire away if anything is unclear.
import sys
sys.path.append("/home/pi/.local/lib/python2.7/site-packages")
from phue import Bridge
import RPi.GPIO as GPIO
import time
import datetime
print 'Waiting for network...'
time.sleep(30)
print 'The wait is over. It\'s showtime!'
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.IN) #Read output from PIR motion sensor
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP) #Read output from button.
b=Bridge('192.168.1.47')
try:
b.connect()
except ImportError:
print "Import error occurred!"
print "Connected to Hue bridge!"
lightson=b.get_light(2, "on")
if lightson: print "Lights are already on."
print 'Entering infinite loop...'
light_on_delay = 15 # time in min for light to stay on when button pressed
button_pressed = 0
while True:
# check for button press
input_state = GPIO.input(18)
if input_state == False:
print('Button Pressed')
end = (light_on_delay * 1) + time.time()
button_pressed = 1
command = {"on" : True, "bri" : 255, "sat" : 0, "hue" : 0}
b.set_group(2, command)
lightson=True
print('Lights are on for 15 minutes')
# check if button has been pressed if it has check to see if time is up
if button_pressed == 1:
if time.time() > end:
button_pressed = 0
else:
i=GPIO.input(4)
timestamp=datetime.datetime.now().time()
if (timestamp < offstarttime and timestamp > offendtime):
if i==0: #When output from motion sensor is LOW
print ('No movement detected - Turning lights off')
b.set_group(2, 'on', False)
lightson=False
print ('Lights are off')
time.sleep(0.1)
else: #When output from motion sensor is HIGH
print ('Movement detected - Turning lights on')
command = {"on" : True, "bri" : 255, "sat" : 0, "hue" : 0}
b.set_group(2, command)
lightson=True
print ('Lights are on.')
time.sleep(5)
# added delay to prevent program using 100% cpu time.
time.sleep(0.5)
You can add a time check using datetime module at the start of each iteration to conditionally set your command dictionary and run your PIR code if between certain hours. The button logic code should be run outside of the if blocks to make sure it always works
from datetime import datetime
while True:
now = datetime.now()
# Check to see if it is 5am or later
if now.hour >= 5:
# PIR sensor code here
print("PIR sensor should work now")
# Check to see if between 8pm and 11pm
if now.hour >= 20 and now.hour <= 23:
# Configure command dictionary for specific hours
command = {"on": True,"bri": 255,"sat": 80,"hue": 357}
else:
# Configure command dictionary for regular hours
command = {"on": False}
# Rest of your code including button logic

Testing how long a user has been in a list

I'm using a bot for twitch and it tracks the time the user has spent in the channel. !time You have spent 10 seconds in the stream. However when multiple users use this command !time it doesn't have a seperate 'count' for each user. Ex:
Rustie: !time
Bot: Rustie, you have 20 seconds in the stream.
~1 minute later~
John: !time
Bot: John, you have 1 minute 20 seconds in the stream.
My current code:
usersForTime = []
if "time" in message:
if user in usersForTime:
endTime = time.time() # I already made startTime in the !start command (which starts the time tracker in the first place)
ellapsed = (endTime - startTime)
sendMessage(s, user + ", you have " + "%.2f" % round(ellapsed, 2) + " seconds in the stream.")
else:
sendMessage(s ,"You need to start tracking your time with the !start command.")
You'll want to store startTime associated with a specific user, something like
userStart = {}
if user in usersForTime:
...
ellapsed = (endTime - userStart[user])
which uses a dictionary to look up the individual's startTime.
To store it originally (in !start):
userStart[user] = time.time()

how to write an if statement in python comparing time to a value

I'm trying to write a simple code in python to turn on a led light during certain hours of the day, then turn it off for the rest of the time. I tried to indicate the time frames in the if statement but everytime I run this code, only the "else" portion of the if statement works. Am I not allowed to compare my time format of HHMM to a flat value of 0745? If not how can I get the led to stay on from midnight to 7:45 in the morning? Any help or direction would be greatly appreciated!
import time
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(3,GPIO.OUT)
print (time.strftime("%H%M"))
while True:
if time.strftime("%H%M") <= 0745:
GPIO.output(3,1)
else:
GPIO.output(3,0)
Try to use datetime.
import datetime
while True:
time = datetime.datetime.now()
morning = time.replace(hour=7, minute=45, second=0, microsecond=0)
if time <= morning:
print("turn on")
else:
print("turn off")
Python has a datetime module that provides data types to work with dates and times.
You could write the code from your question like this:
import datetime
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(3,GPIO.OUT)
while True:
if datetime.datetime.now() <= datetime.datetime.combine(
datetime.date.today(),
datetime.time(7, 45)
):
GPIO.output(3,1)
else:
GPIO.output(3,0)
However, this still has the problem that the program will constantly spin in the while loop and suck up as much CPU cycles as it can get.
You could do something like this instead:
import time
import datetime
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(3,GPIO.OUT)
schedule = [
(datetime.time(0, 0), 0),
(datetime.time(7, 45), 1),
(datetime.time(18, 0), 0)
]
def switchLight():
"""
Switch the light to the proper state according to the schedule.
Return the next time the light needs to be switched.
"""
today = datetime.date.today()
schedule_index = 0
while schedule_index < len(schedule) and \
datetime.datetime.now() > datetime.datetime.combine(today, schedule[schedule_index][0]):
schedule_index += 1
GPIO.output(3, schedule[schedule_index][1])
# calculate next switching time
schedule_index += 1
if schedule_index == len(schedule):
schedule_index = 0
today = today + datetime.timedelta(days=1)
return datetime.datetime.combine(today, schedule[schedule_index][0])
while True:
next_time = switchLight()
time.sleep((next_time - datetime.datetime.now()).seconds + 1)

Categories