diff --git a/installation_part2.sh b/installation_part2.sh index bf43cf0..c4475c0 100644 --- a/installation_part2.sh +++ b/installation_part2.sh @@ -84,7 +84,7 @@ info "Starting the service..." sudo systemctl start master_nebuleair.service -#2. Add master_nebuleair.service +#2. Add rtc_save_to_db.service SERVICE_FILE_2="/etc/systemd/system/rtc_save_to_db.service" info "Setting up systemd service for rtc_save_to_db..." diff --git a/master.py b/master.py index 24a94ce..96305b3 100755 --- a/master.py +++ b/master.py @@ -81,12 +81,13 @@ def run_script(script_name, interval, delay=0): # Define scripts and their execution intervals (seconds) SCRIPTS = [ - #("RTC/save_to_db.py", 1, 0), # SAVE RTC time every 1 second, no delay + #("RTC/save_to_db.py", 1, 0), # --> will run as a separated system service (rtc_save_to_db.service) ("NPM/get_data_modbus_v3.py", 10, 0), # Get NPM data (modbus 5 channels) every 10s, with 2s delay ("envea/read_value_v2.py", 10, 0), # Get NPM data (modbus 5 channels) every 10s, with 2s delay ("loop/SARA_send_data_v2.py", 60, 1), # Send data every 60 seconds, with 2s delay ("BME280/get_data_v2.py", 120, 0), # Get BME280 data every 120 seconds, no delay ("MPPT/read.py", 120, 0), # Get MPPT data every 120 seconds, no delay + #("windMeter/read.py", 60, 2), # --> will run as a separated system service () ("sqlite/flush_old_data.py", 86400, 0) # flush old data inside db every day () ] diff --git a/sqlite/read.py b/sqlite/read.py index f6109d9..e75713b 100755 --- a/sqlite/read.py +++ b/sqlite/read.py @@ -15,6 +15,7 @@ data_BME280 data_envea timestamp_table data_MPPT +data_WIND ''' diff --git a/windMeter/ads115.py b/windMeter/ads115.py new file mode 100644 index 0000000..a3f9c55 --- /dev/null +++ b/windMeter/ads115.py @@ -0,0 +1,27 @@ +''' +Script to test the abs115 an analog-to-digital converter +sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/windMeter/ads115.py + +''' +import time +import board +import busio +import adafruit_ads1x15.ads1115 as ADS +from adafruit_ads1x15.analog_in import AnalogIn + +i2c = busio.I2C(board.SCL, board.SDA) +ads = ADS.ADS1115(i2c) +channel = AnalogIn(ads, ADS.P0) + +print("Testing ADS1115 readings...") +readings = [] + +for i in range(5): + voltage = channel.voltage + readings.append(voltage) + print(f"Voltage: {voltage:.6f}V") + time.sleep(1) + +# Calculate and display the mean +mean_voltage = sum(readings) / len(readings) +print(f"\nMean voltage: {mean_voltage:.6f}V") \ No newline at end of file diff --git a/windMeter/read.py b/windMeter/read.py new file mode 100644 index 0000000..fe9143d --- /dev/null +++ b/windMeter/read.py @@ -0,0 +1,108 @@ +''' + __ _____ _ _ ____ + \ \ / /_ _| \ | | _ \ + \ \ /\ / / | || \| | | | | + \ V V / | || |\ | |_| | + \_/\_/ |___|_| \_|____/ + +Script to read wind speed from a Davis Anémomètre-girouette Vantage Pro (6410) +https://www.shapemaker.io/blog/wind-speed-measurements-with-anemometer-and-a-raspberry-pi + +Connexion: +black (wind speed ) -> gpio21 +green (wind direction) -> ADS1115 (module I2C) +Yellow -> 5v +RED -> GND + +Attention: The Raspberry Pi doesn't have analog inputs, so we need an analog-to-digital converter (ADC) to read the wind direction. + +sudo /usr/bin/python3 /var/www/nebuleair_pro_4g/windMeter/read.py + +''' +#!/usr/bin/python3 +import time +import sqlite3 +import board +import busio +import numpy as np +import threading +import adafruit_ads1x15.ads1115 as ADS +from adafruit_ads1x15.analog_in import AnalogIn +from gpiozero import Button +from datetime import datetime + +# Constants +DB_PATH = "/var/www/nebuleair_pro_4g/sqlite/sensors.db" + +# Initialize I2C & ADS1115 +i2c = busio.I2C(board.SCL, board.SDA) +ads = ADS.ADS1115(i2c) +channel = AnalogIn(ads, ADS.P0) # Connect to A0 on the ADS1115 + +# Wind speed sensor setup +wind_speed_sensor = Button(21) +wind_count = 0 +wind_lock = threading.Lock() + +def spin(): + global wind_count + with wind_lock: + wind_count += 1 + +def reset_wind(): + global wind_count + with wind_lock: + wind_count = 0 + +wind_speed_sensor.when_activated = spin # More reliable + +def calc_speed(spins, interval): + return spins * (2.25 / interval) * 1.60934 # Convert MPH to km/h + +def get_wind_direction(): + voltage = channel.voltage + return voltage + +def save_to_database(wind_speed, wind_direction, spin_count): + """Save wind data to SQLite database.""" + try: + conn = sqlite3.connect(DB_PATH) + cursor = conn.cursor() + + cursor.execute("SELECT * FROM timestamp_table LIMIT 1") + row = cursor.fetchone() + rtc_time_str = row[1] if row else datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + cursor.execute(''' + INSERT INTO data_wind (timestamp, wind_speed, wind_direction) + VALUES (?, ?, ?) + ''', (rtc_time_str, round(wind_speed, 2), round(wind_direction, 2))) + + conn.commit() + conn.close() + print(f"Saved: {rtc_time_str}, {wind_speed:.2f} km/h, {wind_direction:.2f}V, Spins: {spin_count}") + + except Exception as e: + print(f"Database error: {e}") + +def main(): + print("Wind monitoring started...") + + try: + while True: + reset_wind() + print("Measuring for 60 seconds...") + time.sleep(60) + + wind_speed_kmh = calc_speed(wind_count, 60) + wind_direction = get_wind_direction() + + save_to_database(wind_speed_kmh, wind_direction, wind_count) + + except KeyboardInterrupt: + print("\nMonitoring stopped.") + except Exception as e: + print(f"Error: {e}") + +if __name__ == "__main__": + main()