import math from time import sleep, time, localtime from machine import Pin, SoftI2C, ADC, Timer, PWM import BME280 from hcsr04 import HCSR04 import re import random hc_sensor = HCSR04(trigger_pin=32, echo_pin=14) # PWM pin for the gauge pwm_pin = PWM(Pin(5)) # Pin 5 controls the gauge pwm_pin.freq(1000) pwm_pin.duty(0) def random_bounce_gauge(): global last_bounce_time, bounce_interval current_time = time() if current_time - last_bounce_time > bounce_interval: # Check if the interval has passed # Add a random small bounce between -10 and 20 (scaled to the 0-100 range) bounce = random.uniform(-40, 40) current_duty = pwm_pin.duty() # Get current duty cycle (0-100 range) new_duty = min(max(0, current_duty + bounce), 100) # Ensure duty stays within 0-100 range pwm_pin.duty(int(new_duty)) # Apply the new duty cycle print(f"Gauge bounce! Duty cycle changed to {new_duty}") # Update last bounce time and set a new random interval last_bounce_time = current_time bounce_interval = random.randint(3, 7) # Bounce every 3 to 7 seconds # Function to map humidity to PWM duty cycle, limited to 0-100 range def update_gauge_with_humidity(humidity): humidity_with_variation = simulate_humidity_variation(humidity) # Scale the humidity (0-100%) to the PWM duty cycle range of 0-100 max_duty_cycle = 100 # Maximum duty cycle for your gauge duty_cycle = int((humidity_with_variation / 100) * max_duty_cycle) # Map humidity to 0-100 range pwm_pin.duty(duty_cycle) # Set the PWM duty cycle print(f"Humidity: {humidity_with_variation:.2f}% -> PWM Duty Cycle: {duty_cycle}") # Initialize sensors and devices battery_adc = ADC(Pin(35)) # GPIO 35 (A13) battery_adc.atten(ADC.ATTN_11DB) # Configure to read a wider range (up to 3.3V) buzzer = Pin(27, Pin.OUT) led_pins = [4, 12, 13, 25, 26] leds = [Pin(pin, Pin.OUT) for pin in led_pins] stop_button = Pin(21, Pin.IN, Pin.PULL_UP) # Initialize variables initial_temp = None initial_temp_time_str = None beep_interval = 1.0 beep_timer = Timer(0) last_bounce_time = 0 bounce_interval = random.randint(5, 15) # Function to format the time def formatted_time(): t = localtime() # Get current time tuple return f"{t[3]:02}:{t[4]:02}:{t[5]:02}" # Format as HH:MM:SS def light_up_leds(indices): # Turn off all LEDs first (optional) for led in leds: led.off() # Light up LEDs at specified indices for index in indices: if 0 <= index < len(leds): leds[index].on() else: print(f"Invalid LED index: {index}") def wave_pattern(): for i in range(len(leds)): leds[i].on() sleep(0.05) leds[i].off() for i in range(len(leds) - 2, -1, -1): leds[i].on() sleep(0.05) leds[i].off() # Function to extract numeric values from strings def extract_numeric(value): cleaned_value = ''.join(char for char in value if char.isdigit() or char == '.') return float(cleaned_value) if cleaned_value else 0.0 # Function to read battery voltage def read_battery_voltage(): raw_value = battery_adc.read() voltage = (raw_value / 4095.0) * 2 * 3.3 # Convert ADC reading to actual voltage return voltage # Function to calculate battery percentage based on voltage def calculate_battery_percentage(voltage): max_voltage = 4.2 # Voltage when the battery is fully charged min_voltage = 3.0 # Voltage when the battery is considered empty percentage = (voltage - min_voltage) / (max_voltage - min_voltage) * 100 return max(0, min(percentage, 100)) # Cap percentage between 0% and 100% battery_voltage = read_battery_voltage() battery_percentage = calculate_battery_percentage(battery_voltage) # Function to beep def beep(timer): buzzer.on() sleep(0.2) # Beep duration buzzer.off() # Function to simulate humidity fluctuation def simulate_humidity_variation(humidity): fluctuation = random.uniform(-20, 20) # Simulate a ±10% fluctuation return max(0, min(humidity + fluctuation, 100)) # Ensure it stays between 0 and 100% # Function to adjust beep interval based on temperature change def adjust_beep_interval(current_temp): global beep_interval, initial_temp, initial_temp_time_str global last_adjust_time # Track the last time the interval was adjusted if initial_temp is None: initial_temp = current_temp initial_temp_time_str = formatted_time() # Store the time as a string print(f"Initial temp set at: {initial_temp_time_str} with temp: {initial_temp:.2f}C") return temp_diff = current_temp - initial_temp time_since_last_adjustment = time() - last_adjust_time print(f"Temp diff: {temp_diff:.2f}C, Time since last adjustment: {time_since_last_adjustment:.2f}s") # Only adjust if the temperature difference is significant enough if abs(temp_diff) >= 2 and time_since_last_adjustment > 5: # Adjusting only if 2C difference or more and at least 5 seconds have passed print(f"Condition met - adjusting beep interval. Temp diff: {temp_diff:.2f}C") if temp_diff < 0: # Colder beep_interval = max(0.5, beep_interval / 2) # Ensure a minimum interval of 0.5 seconds else: # Warmer beep_interval = min(2.0, beep_interval * 2) initial_temp = current_temp initial_temp_time_str = formatted_time() # Update the capture time as a string last_adjust_time = time() print(f"Beep interval adjusted to {beep_interval:.2f} seconds at {initial_temp_time_str}") # Reinitialize timer with updated interval beep_timer.init(period=int(beep_interval * 1000), mode=Timer.PERIODIC, callback=beep) print(f"Timer reinitialized with new interval of {beep_interval:.2f} seconds.") pwm_pin.duty(80) wave_pattern() pwm_pin.duty(20) # Main function def main(): global initial_temp, beep_timer, beep_interval, last_adjust_time last_adjust_time = time() # Initialize temperature reading, display, etc. try: i2c = SoftI2C(scl=Pin(22), sda=Pin(23)) bme = BME280.BME280(i2c=i2c) temp = bme.temperature if isinstance(temp, str): temp = temp.strip().rstrip('C') current_temp = float(temp) except Exception as e: print(f"Error reading initial temperature: {e}") current_temp = 0.0 # Start the timer for beeping beep_timer.init(period=1000, mode=Timer.PERIODIC, callback=beep) print("Timer initialized for beeping.") while True: if stop_button.value() == 0: sleep(0.2) # Debouncing delay if stop_button.value() == 0: print("Stopping script...") beep_timer.deinit() break # Sensor readings try: bme = BME280.BME280(i2c=i2c) temp = bme.temperature if isinstance(temp, str): temp = temp.strip().rstrip('C') current_temp = float(temp) hum = bme.humidity pres = bme.pressure hum_float = extract_numeric(hum) pres_float = extract_numeric(pres) battery_voltage = read_battery_voltage() adjust_beep_interval(current_temp) update_gauge_with_humidity(hum_float) # LED pattern based on distance distance = hc_sensor.distance_cm() if distance < 10: light_up_leds([0, 1, 2, 3, 4]) elif 10 < distance < 25: light_up_leds([0, 1, 2, 3]) elif 25 < distance < 50: light_up_leds([0, 1, 2]) elif 100 < distance < 125: light_up_leds([0, 1]) elif 150 < distance < 200: light_up_leds([0]) except Exception as e: print(f"Error reading sensors: {e}") print(f"[{formatted_time()}] Current Temperature: {current_temp:.2f}C") if initial_temp_time_str is not None: print(f"[{initial_temp_time_str}] Captured/Saved Temperature: {initial_temp:.2f}C") else: print(f"[No Time Recorded] Captured/Saved Temperature: None") print(f"[{formatted_time()}] Humidity: {hum}") print(f"[{formatted_time()}] Pressure: {pres}") print(f"[{formatted_time()}] Battery Voltage: {battery_voltage:.2f}V") print(f"[{formatted_time()}] Distance: {distance} cm") print('-----------------------------------') random_bounce_gauge() sleep(0.2) # Run the main function main()