Implemented generic setup file and VL53L3CX Sensor

This commit is contained in:
Maximilian Giller 2023-11-24 18:27:05 +01:00
parent b85ee8ab25
commit 16ebe4a670
7 changed files with 105 additions and 55 deletions

View file

@ -1,12 +1,10 @@
from sensors.people_counter import PeopleCounter from sensors.people_counter import PeopleCounter
from sensors.vl53l1x_sensor import VL53L1XSensor
import logging import logging
from setup import sensor
counter = PeopleCounter(VL53L1XSensor()) counter = PeopleCounter(sensor)
peopleCount = 0 peopleCount = 0
logging.getLogger().setLevel(logging.INFO)
def countChange(change: int) -> None: def countChange(change: int) -> None:
global peopleCount global peopleCount

View file

@ -1,30 +1,26 @@
from sensors import Directions, VL53L1XSensor from sensors import Directions
from time import sleep from time import sleep
from setup import sensor
import logging import logging
DELAY_SECONDS = 1 DELAY_SECONDS = 1
logging.getLogger().setLevel(logging.INFO)
sensor = VL53L1XSensor()
sensor.open() sensor.open()
try: try:
while True: while True:
sensor.setDirection(Directions.INSIDE) sensor.setDirection(Directions.INSIDE)
distance_inside = sensor.getDistance() distance_inside = sensor.getDistance()
sensor.setDirection(Directions.OUTSIDE) sensor.setDirection(Directions.OUTSIDE)
distance_outside = sensor.getDistance() distance_outside = sensor.getDistance()
logging.info("----------") logging.info("----------")
logging.info(f"Inside: {distance_inside} cm") logging.info(f"Inside: {distance_inside} cm")
logging.info(f"Outside: {distance_outside} cm") logging.info(f"Outside: {distance_outside} cm")
sleep(DELAY_SECONDS) sleep(DELAY_SECONDS)
finally: finally:
sensor.close() sensor.close()

View file

@ -1,3 +1,4 @@
from sensors.vl53l1x_sensor import VL53L1XSensor from sensors.vl53l1x_sensor import VL53L1XSensor
from sensors.vl53l3cx_sensor import VL53L3CXSensor
from sensors.people_counter import PeopleCounter from sensors.people_counter import PeopleCounter
from sensors.tof_sensor import Directions from sensors.tof_sensor import Directions

View file

@ -0,0 +1,61 @@
from sensors.tof_sensor import Directions, ToFSensor
import VL53L1X
# Reference: https://github.com/pimoroni/vl53l1x-python
#
# Left, right, top and bottom are relative to the SPAD matrix coordinates,
# which will be mirrored in real scene coordinates.
# (or even rotated, depending on the VM53L1X element alignment on the board and on the board position)
#
# ROI in SPAD matrix coords:
#
# 15 top-left
# | X____
# | | |
# | |____X
# | bottom-right
# 0__________15
#
class VL53L3CXSensor(ToFSensor):
def __init__(self) -> None:
super().__init__()
def open(self, ranging_mode: int = 3) -> None:
self.sensor = VL53L1X.VL53L1X(i2c_bus=1, i2c_address=0x52)
self.sensor.open()
self.roi = VL53L1X.VL53L1xUserRoi()
# Optionally set an explicit timing budget
# These values are measurement time in microseconds,
# and inter-measurement time in milliseconds.
# If you uncomment the line below to set a budget you
# should use `tof.start_ranging(0)`
# tof.set_timing(66000, 70)
self.ranging = ranging_mode
# 0 = Unchanged
# 1 = Short Range
# 2 = Medium Range
# 3 = Long Range
def setDirection(self, direction: Directions) -> None:
"""Configure sensor to pick up the distance in a specific direction."""
direction_roi = {
Directions.INSIDE: VL53L1X.VL53L1xUserRoi(6, 3, 9, 0),
Directions.OUTSIDE: VL53L1X.VL53L1xUserRoi(6, 15, 9, 12),
}
self.roi = direction_roi[direction]
def getDistance(self) -> float:
"""Returns new distance in cm."""
self.sensor.set_user_roi(self.roi)
self.sensor.start_ranging(self.ranging)
distance = self.sensor.get_distance()
self.sensor.stop_ranging()
return distance / 10
def close(self) -> None:
self.sensor.close()

28
src/setup.py Normal file
View file

@ -0,0 +1,28 @@
from sensors import VL53L1XSensor, VL53L3CXSensor
from datetime import time
import logging
LOG_FILE_PATH = "log.txt" # Path for logs
logging.getLogger().setLevel(logging.INFO)
sensor = VL53L3CXSensor()
# Should lights already turn on where there is any kind of motion in the sensor
ENABLE_MOTION_TRIGGERED_LIGHT = True
# Should lights change when a certain time in the schedule is reached
ENABLE_SCHEDULE_TRIGGERS = (
False # Not working correctly at the moment, so turned off by default
)
# Schedule (Key is time after scene should be used. Value is scene name to be used.)
# Needs to be sorted chronologically
SCHEDULE: dict[time, str] = {}
# Philips Hue configuration
hue_conf = {
"bridge_ip": "",
"transition_time": 10, # seconds
"light_group": "",
# If file exists, application is considered 'registered' at the bridge
"registered_file": "smart_light_registered.bridge",
} # Custom configuration for philips hue

View file

@ -1,28 +1,15 @@
from datetime import datetime from datetime import datetime
from services.philips_hue import PhilipsHue from services.philips_hue import PhilipsHue
from sensors.people_counter import PeopleCounter from sensors.people_counter import PeopleCounter
from sensors.vl53l1x_sensor import VL53L1XSensor
import logging import logging
import json import json
from setup import sensor, hue_conf, LOG_FILE_PATH
LOG_FILE_PATH = "log.txt" # Path for logs
hue_conf = {
"bridge_ip": "",
"transition_time": 10, # seconds
# Light group to control
"light_group": "",
# If file exists, application is considered 'registered' at the bridge
"registered_file": "smart_light_registered.bridge",
} # Custom configuration for philips hue
hue: PhilipsHue = PhilipsHue(hue_conf) # Light interface hue: PhilipsHue = PhilipsHue(hue_conf) # Light interface
counter: PeopleCounter = PeopleCounter(VL53L1XSensor()) # Sensor object counter: PeopleCounter = PeopleCounter(sensor) # Sensor object
peopleCount: int = 0 # Global count of people on the inside peopleCount: int = 0 # Global count of people on the inside
logging.getLogger().setLevel(logging.INFO)
def change_cb(countChange: int, directionState: dict): def change_cb(countChange: int, directionState: dict):
"""Handles basic logging of event data for later analysis. """Handles basic logging of event data for later analysis.

View file

@ -1,36 +1,15 @@
from datetime import datetime, time, timedelta from datetime import datetime, time, timedelta
from typing import Optional
from services.philips_hue import PhilipsHue from services.philips_hue import PhilipsHue
from sensors import PeopleCounter, Directions, VL53L1XSensor from sensors import PeopleCounter, Directions, VL53L1XSensor
import logging import logging
import json import json
from timeloop import Timeloop from timeloop import Timeloop
from setup import sensor, hue_conf, LOG_FILE_PATH, SCHEDULE, ENABLE_SCHEDULE_TRIGGERS
# Should lights already turn on where there is any kind of motion in the sensor
ENABLE_MOTION_TRIGGERED_LIGHT = True
# Should lights change when a certain time in the schedule is reached
ENABLE_SCHEDULE_TRIGGERS = (
False # Not working correctly at the moment, so turned off by default
)
# Schedule (Key is time after scene should be used. Value is scene name to be used.)
# Needs to be sorted chronologically
SCHEDULE: dict[time, str] = {}
LOG_FILE_PATH = "log.txt" # Path for logs
hue_conf = {
"bridge_ip": "",
"transition_time": 10, # seconds
"light_group": "",
# If file exists, application is considered 'registered' at the bridge
"registered_file": "smart_light_registered.bridge",
} # Custom configuration for philips hue
hue: PhilipsHue = PhilipsHue(hue_conf) # Light interface hue: PhilipsHue = PhilipsHue(hue_conf) # Light interface
counter: PeopleCounter = PeopleCounter(VL53L1XSensor()) # Sensor object counter: PeopleCounter = PeopleCounter(sensor) # Sensor object
peopleCount: int = 0 # Global count of people on the inside peopleCount: int = 0 # Global count of people on the inside
motion_triggered_lights = False # Is light on because of any detected motion motion_triggered_lights = False # Is light on because of any detected motion
timeloop: Timeloop = Timeloop() # Used for time triggered schedule timeloop: Timeloop = Timeloop() # Used for time triggered schedule
@ -55,7 +34,7 @@ def time_minus_time(time_a: time, time_b: time) -> timedelta:
return dt_a - dt_b return dt_a - dt_b
def get_scene_for_time(time: time) -> str: def get_scene_for_time(time: time) -> Optional[str]:
"""Determines the correct scene to activate for a given time. """Determines the correct scene to activate for a given time.
Args: Args:
@ -185,7 +164,7 @@ def trigger_change(triggerState: dict):
motion_triggered_lights = target_light_state motion_triggered_lights = target_light_state
def set_light_scene(target_scene: str) -> bool: def set_light_scene(target_scene: str) -> None:
"""Sets the lights to the given scene, but only, if lights are already on. Does not correct count if lights are in an unexpected state. """Sets the lights to the given scene, but only, if lights are already on. Does not correct count if lights are in an unexpected state.
Args: Args: