Raspberry Pi Pico W 智慧淹水偵測系統,結合 Google 試算表與 LINE 通訊軟體

前言

本篇文章要來介紹的是使用 Raspberry Pico W 和 RS485 溫溼度感測器的淹水偵測裝置,為了因應最近強降雨的情形,怕地下室淹水所製作的,現在這套設備正在 CAVEDU 地下室服役中。

Pico W淹水偵測裝置功能如下:

➡️每15分鐘會上傳資料點至Google Sheet雲端,以確保裝置運作中

➡️可定時(如:每日7:00PM把目前偵測到的溫溼度發送到 LINE 通訊軟體

➡️若濕度過高,則會立即通報LINE中。由於LINE可以把相關人員加入群組中,所以只要有人接到通報,就可以第一時間做處置。

撰寫/攝影 許鈺莨 (ChatGPT協作編輯)
時間 2 小時 材料表
難度 2(滿分5)

本文

智慧偵測淹水裝置接線圖

智慧偵測淹水裝置主要由下列元件所組成:

  • Raspberry Pi Pico W: 接收RS485感測器訊號,並上傳至雲端及LINE 訊息。
  • Raspberry Pi Pico W擴充板 : 擴充Raspberry Pi Pico W腳位,以方便將感測器腳位。
  • TTL轉RS485模組 : 可將RS485感測器訊號轉成TTL訊號,再讓Raspberry Pi Pico W接收
  • RS485溫溼度感測器:可以偵測室內的溫度及濕度。
  • LCD液晶螢幕: 主要顯示目前的溼度狀況與時間。
  1. Raspberry Pi Pico W擴充板與LCD 接線

  1. Raspberry Pi Pico W擴充板與TTL轉RS485模組接線

  1. TTL轉RS485模組接線與RS485溫濕度感測器接線

智慧偵測淹水裝置流程圖

系統流程圖如下 (點選看大圖)

 

智慧偵測淹水裝置匯入LCD函式庫

  1. 匯入 Raspberry Pi pico 函式庫的做法,請參考「使用 Raspberry Pi Pico W 和 MicroPython 開發物聯網應用
  2. 函式庫下載:https://reurl.cc/Dov54e
  1. 匯入檔案指令,匯入以上連結下載的 lcd_api.py 和 i2c_lcd.py
cd LCD_library
ampy --port COMX put lcd_api.py
ampy --port COMX put i2c_lcd.py
  1. 智慧偵測淹水裝置程式全貌

下列程式中需要 IFTTT 作為中介軟體來串接 pico W 與 LINE,相關IFTTT申請步驟,請參考 「LinkIt™ 7697空氣品質偵測並上傳Google表單(空氣盒子2.0)」。,並將申請到的 IFTTT 相關資訊填入以下 .py 檔之後上傳到 pi pico 開發板即可。

Alert_IFTTT_LINE_GOOGLE_settime_blog.py
import utime
import machine
import urequests
import ntptime
import network
from machine import I2C, Pin, RTC
from lcd_api import LcdApi
from i2c_lcd import I2cLcd

# IFTTT settings(需自行輸入IFTTT相關資訊)
IFTTT_GOOGLE_EVENT = "enter_your_google_event"
IFTTT_LINE_EVENT = "enter_your_line_event"
IFTTT_KEY= "enter_your_webhook_key"
IFTTT_URL_GOOGLE_SHEET ='https://maker.ifttt.com/trigger/'+IFTTT_GOOGLE_EVENT+'/with/key/'+IFTTT_KEY
IFTTT_URL_LINE ='https://maker.ifttt.com/trigger/'+IFTTT_LINE_EVENT+'/with/key/'+IFTTT_KEY

# WiFi settings(需自行輸入WIFI帳號和密碼)
wifi_ssid = "enter_your_wifi_ssid"
wifi_password = "enter_your_wifi_password"

# Initialize UART(初始化UART)
uart = machine.UART(1, baudrate=9600, tx=machine.Pin(8), rx=machine.Pin(9), timeout=1000)

uart.init(9600, bits=8, parity=None, stop=1)

# LCD initialization (LCD 初始化)
I2C_ADDR     = 0x3f
I2C_NUM_ROWS = 2
I2C_NUM_COLS = 16
i2c = I2C(0, sda=machine.Pin(0), scl=machine.Pin(1), freq=400000)
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)  

# Initialize RTC (RTC 初始化)
rtc = RTC()

# Connect to the WiFi (WIFI連線)
def connect_wifi(ssid, password):
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        wlan.connect(ssid, password)
        while not wlan.isconnected():
            pass

# Update the time from NTP server (更新時間)
def update_time():
    ntptime.host = 'pool.ntp.org'
    ntptime.settime()
    tm = utime.localtime(utime.mktime(utime.localtime()) + 28800)
    rtc.datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0))

# Get current time(取得目前時間)
def get_time():
    time = rtc.datetime()
    current_hour = time[4]
    current_minute = time[5]
    current_second = time[6]
    current_time = "{:02d}:{:02d}:{:02d}".format(current_hour, current_minute, current_second)
    return current_time, current_hour, current_minute

# Send data to IFTTT (傳資料到IFTTT)
def send_to_ifttt(url, soil_temp, soil_vwc, state):
    data = {'value1': str(soil_temp), 'value2': str(soil_vwc), 'value3': state}
    request_headers = {'Content-Type': 'application/json'}
    request = urequests.post(url, json=data, headers=request_headers)
    request.close()

# Sensor Access Function (RS485感測器回傳資料)
def Sensor_Access():
    Read_SOIL_TEMP_HUMI_Command = bytes([0x01, 0x03, 0x00, 0x06, 0x00, 0x02, 0x24, 0x0A])
    SOIL_buf = bytearray(11)
    Sensor_Delay_mS = 50
uart.write(Read_SOIL_TEMP_HUMI_Command)
    uart.readinto(SOIL_buf)
    utime.sleep_ms(Sensor_Delay_mS)

    SOIL_VWC_Data = (SOIL_buf[5] << 8) + SOIL_buf[6]
    SOIL_VWC_Value = int(SOIL_VWC_Data) / 1000
    SOIL_TEMP_Data = (SOIL_buf[3] << 8) + SOIL_buf[4]
    SOIL_TEMP_Value = int(SOIL_TEMP_Data) / 100
    return SOIL_TEMP_Value, SOIL_VWC_Value

# Print on LCD (顯示數值在LCD)
def lcd_print(current_time, soil_vwc):
    lcd.clear()
    lcd.putstr("TIME: {time}    VWC: {vwc:.1f}".format(time=current_time, vwc=soil_vwc))

def main():
    state = " Normal "
    connect_wifi(wifi_ssid, wifi_password)
    update_time() # update the time from NTP server at the start
    lcd.putstr("WIFI is connected!")

    # setting the initial time to a value that triggers the first send
    last_sent_hour = -1
    last_sent_minute = -1
   line_flag = False

    while True:
        current_time, current_hour, current_minute = get_time()
        # read sensor every 15 minutes  (每15分鐘上傳數值到Google Sheets)

        if current_minute % 15 == 0 and current_minute != last_sent_minute:
            soil_temp, soil_vwc = Sensor_Access()
        send_to_ifttt(IFTTT_URL_GOOGLE_SHEET, soil_temp, soil_vwc, state)

            last_sent_minute = current_minute

# send to LINE sheet once every day at 7:00pm (每晚七點上傳數值到LINE)
        if current_hour == 19 and current_minute == 0 and line_flag == False:
            soil_temp, soil_vwc = Sensor_Access()
          #send_to_ifttt(IFTTT_URL_GOOGLE_SHEET, soil_temp, soil_vwc, state)
            send_to_ifttt(IFTTT_URL_LINE, soil_temp, soil_vwc, state)
            line_flag = True

        # reset line_flag after 7:00pm (重置line_flag)

        if current_hour == 19 and current_minute > 0:

            line_flag = False

        # send to LINE when soil_vwc is between 0 and 10 (當淹水時會發緊報)

        soil_temp, soil_vwc = Sensor_Access()
        if 0 < soil_vwc <= 10:
            state = " ALERT!! "
            send_to_ifttt(IFTTT_URL_LINE, soil_temp, soil_vwc, state)
           send_to_ifttt(IFTTT_URL_GOOGLE_SHEET, soil_temp, soil_vwc, state)
        else:
            state = " Normal "

        # print on LCD every second (LCD每秒更新一次顯示畫面)
        lcd_print(current_time, soil_vwc)
        print(current_time, soil_vwc)
        utime.sleep(1)  # sleep for 1 second

# Run the main function (執行主程式)
main()
  1. 安裝位置

筆者將裝置設置在地下室容易淹水的地方,由於感測器很靈敏,所以使用海綿來吸水,到一定程度後感測器就會發出通報 (下圖左)。裝置運作時,可由外接 LCD 看到當下的時間和濕度。

6. 實際執行

執行影片如本文開頭,為了較快看到效果,筆者設計是每秒上傳一次資料到雲端,請根據實際狀況來修改這個更新頻率。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *