Untitled

 avatar
unknown
plain_text
4 months ago
3.9 kB
2
Indexable
import time
import board
import busio
import adafruit_vl53l0x
from adafruit_tca9548a import TCA9548A
import statistics
import sys
import tty
import termios

# Initialize I2C bus
i2c = busio.I2C(board.SCL, board.SDA)
mux = TCA9548A(i2c)

# Create sensor objects on channels 1, 2, and 4-7
sensors = {
    1: adafruit_vl53l0x.VL53L0X(mux[1]),
    2: adafruit_vl53l0x.VL53L0X(mux[2]),
    4: adafruit_vl53l0x.VL53L0X(mux[4]),
    5: adafruit_vl53l0x.VL53L0X(mux[5]),
    6: adafruit_vl53l0x.VL53L0X(mux[6]),
    7: adafruit_vl53l0x.VL53L0X(mux[7])
}

# Constants
MAX_DISTANCE = 400
MIN_DISTANCE = 0
FULL_THRESHOLD = 50
SAMPLES_PER_SENSOR = 20  # Number of readings per sensor
SAMPLE_DELAY = 0.05      # 50ms between readings

def getch():
    """Get a single character from standard input"""
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(sys.stdin.fileno())
        ch = sys.stdin.read(1)
    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

def get_filtered_reading(sensor):
    """Get multiple readings from a sensor and filter out outliers"""
    readings = []
    for _ in range(SAMPLES_PER_SENSOR):
        try:
            reading = sensor.range
            readings.append(reading)
            time.sleep(SAMPLE_DELAY)
        except Exception:
            continue
    
    if not readings:
        return None
        
    # Remove outliers: readings outside 2 standard deviations
    if len(readings) >= 4:  # Need enough samples for statistical validity
        mean = statistics.mean(readings)
        stdev = statistics.stdev(readings)
        filtered_readings = [r for r in readings if (mean - 2 * stdev) <= r <= (mean + 2 * stdev)]
        if filtered_readings:
            return statistics.median(filtered_readings)
    
    return statistics.median(readings)

def get_fill_level():
    """Get readings from all sensors with statistical filtering"""
    all_readings = []
    closest_reading = float('inf')
    
    print("Taking precise measurements...")
    
    for sensor_id, sensor in sensors.items():
        reading = get_filtered_reading(sensor)
        if reading is not None:
            all_readings.append(reading)
            closest_reading = min(closest_reading, reading)
            print(f"Sensor {sensor_id}: {reading:.1f}mm")
    
    if not all_readings:
        return None, None
        
    median_distance = statistics.median(all_readings)
    percentage = ((MAX_DISTANCE - median_distance) / (MAX_DISTANCE - MIN_DISTANCE)) * 100
    percentage = max(0, min(100, percentage))  # Clamp between 0-100%
    
    return closest_reading, percentage

def main():
    # Give sensors time to initialize
    time.sleep(1)
    
    print("High-Precision Fill Level Measurement")
    print("Press any key to measure, 'q' to quit")
    
    while True:
        char = getch()
        if char.lower() == 'q':
            print("\nExiting...")
            break
            
        print("\nStarting new measurement cycle...")
        closest_reading, percentage = get_fill_level()
        
        if closest_reading is None:
            print("Error: Could not get valid readings from sensors")
            continue
            
        print("\nResults:")
        print(f"Closest distance: {closest_reading:.1f}mm")
        
        if closest_reading <= FULL_THRESHOLD:
            print("STATUS: BIN FULL")
        else:
            print(f"Fill level: {percentage:.1f}%")
            print(f"Available space: {(MAX_DISTANCE - closest_reading):.1f}mm")
        
        print("\nPress any key for new measurement, 'q' to quit")

if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        print(f"\nAn error occurred: {str(e)}")
Editor is loading...
Leave a Comment