我一直在從事一個項目,通過該項目我可以整理來自 MQ-135 空氣質量傳感器的空氣質量信息,以檢測我工作場所空氣質量惡化的情況。然而,MQ-135 空氣質量傳感器的位置在從傳感器收集原始信息時具有巨大的重要性。因此,我決定通過開發一個用戶友好的界面,通過選定的角度制作一個可移動的傳感器底座。為了實現這一目標并添加一些確鑿的功能(例如可調節背景光),我使用 Python 中的 guizero 模塊為我的 Raspberry Pi 開發了一個 GUI,名為 Air Quality Module。
通過空氣質量模塊,您可以通過選擇給定角度之一 - 0、30、45、90、135、180 - 來控制連接到迷你云臺套件的兩個伺服電機,并以 RGB 格式調整背景光 - 255, 255, 255. 而且,最重要的是,您可以監控 MQ-135 傳感器生成的當前空氣質量范圍:如果空氣質量惡化,GUI 會通過警告消息通知您。
本項目中提到的一些產品和組件:
樹莓派 3 板殼 3B
樹莓派 4B/3B+ SD 卡 32GB
補給品:
樹莓派 3 型號 B+× 1
DigitSpace Raspberry Pi 3 板殼× 1
SD 卡 32 GB× 1
DigitSpace Raspberry Pi 3B Micro-HDMI VGA 轉換線× 1
Adafruit MCP3008× 1
MQ-135 空氣質量傳感器× 1
Pimoroni Pan-Tilt 帽子× 1
SG90微型伺服電機 × 2
RGB擴散共陽極× 1
SparkFun 可焊接面包板 - 迷你× 2
電阻 220 歐姆 × 3
跳線(通用) × 1
在這個項目中,你將學到:
如何使用 Raspberry Pi 的角度控制伺服電機
如何使用 Raspberry Pi 調整 RGB LED 的顏色
如何使用 MCP3008 和 Raspberry Pi 讀取模擬傳感器
如何使用 guizero 模塊開發 GUI
如何編寫范圍函數來排列值,如 Arduino 中的 map 函數
第 1 步:使用 MCP3008 讀取模擬傳感器
與 Arduino 相比,Raspberry Pi 沒有內置的 ADC(模數轉換器),我們可以通過它輕松地從模擬傳感器收集信息。因此,我們需要在我們的電路中實現一個外部 ADC,以整理來自模擬傳感器(如 MQ-135 空氣質量傳感器)的數據。我使用了 MCP3008 8 通道 ADC,因為它效率高且使用簡單。
我使用 Raspberry Pi 上的 Adafruit CircuitPython MCP3xxx 庫來讀取帶有 MCP3008 的模擬傳感器。
但是,您需要安裝在 Python 中提供 CircuitPython 支持的 Adafruit_Blinka 庫才能使用上述庫。
sudo pip3 install adafruit-blinka
如果需要,您必須在執行命令之前在 Raspberry Pi Configuration Settings 上啟用 SPI。
完成后,從命令行運行以下命令來安裝 Adafruit CircuitPython MCP3xxx 庫。
sudo pip3 install adafruit-circuitpython-mcp3xxx
然后,按如下方式進行引腳連接。盡管在項目原理圖和代碼中對引腳連接進行了很好的解釋,但除此之外,我將保留 MCP3008 的以下引腳連接原理圖。
MCP3008 CLK 轉 Pi SCLK
MCP3008 DOUT 轉 Pi MISO
MCP3008 DIN 轉 Pi MOSI
MCP3008 CS 轉 Pi D5
MCP3008 VDD 至 Pi 3.3V
MCP3008 VREF 至 Pi 3.3V
MCP3008 AGND 到 Pi GND
MCP3008 DGND 到 Pi GND
MCP3008 CH0 到模擬傳感器的信號引腳
CH0 指的是 MCP3008 上的第一個輸入引腳 - 從 0 到 7。
第 2 步:開發 GUI(空氣質量模塊)和編程 Raspberry Pi
為了能夠在 Python 中創建 GUI,您需要在 Raspberry Pi 上安裝 guizero 模塊。然后,您可以使用模塊提供的所有小部件和事件。
從您的命令行運行以下命令來安裝 guizero 模塊。
sudo pip3 install guizero
導入所需的庫和模塊。
不要忘記包含所有 GUI 小部件 - App、Box、Text、TextBox、PushButton、ButtonGroup、MenuBar、info、yesno、warn。
創建 SPI 總線、cs(片選)和 mcp 對象。
創建連接到 MCP3008 輸入引腳的模擬輸入通道——我只使用了通道 0。
定義 GPIO 引腳設置 - GPIO.setmode(GPIO.BCM) 。
定義 RGB 引腳并設置 PWM 頻率 - 100。
在 100 - OFF 處啟動 RGB PWM 引腳。
定義伺服電機引腳并設置 PWM 頻率 - 50。
在 0 - OFF 處啟動伺服底座和臂銷。
定義菜單欄選項命令(功能):
在Tutorial()函數中,如果需要,打開一個 yesno 消息以轉到項目教程頁面。
在Components()函數中,打開一條信息消息以顯示組件。
在About()函數中,打開一條信息消息以顯示電梯間距。
定義小部件命令和功能:
在_range()函數中,復制 Arduino 映射函數以在 Python 中排列給定范圍內的值。
在evaluateSensorValue()函數中,從測試范圍內的 MQ-135 空氣質量中獲取空氣質量值 - 從 0-60000 到 0-1023。
測試您的模塊,然后在本例中定義 0 到 60000 之間的值范圍。
如果超過閾值 (300),則通過警告消息通知 - 空氣質量惡化 - 并將狀態更改為危險。
在adjust_color()函數中,通過使用ChangeDutyCycle()更改 PWM 頻率(在 0 到 100 之間)來調整 RGB LED 的顏色。將輸入的顏色值從 0-255 排列到 0-100。
在base_tilt_move()和arm_tilt_move()函數中,通過選擇的角度控制伺服電機 - 0, 30, 45, 90, 135, 180 - 運行ChangeDutyCycle(selected_angle) 。2 到 12 之間的循環值精確地適用于 0 到 180 之間的角度。
調整伺服電機位置后不要忘記執行以下行以關閉伺服 PWM 引腳。
改變工作周期(0)
創建名為 Air Quality Module 的 GUI 應用程序。
定義菜單欄選項 - 教程、組件、關于。
使用 box 小部件設計界面
RGB 顏色接口
使用布局網格對齊部件。
將相關命令(功能)分配給調整按鈕 - adjust_color。
空氣質量界面
定義傳感器和狀態文本變量。
使用repeat()函數每秒更新 MQ-135 空氣質量傳感器生成的傳感器值。
注意:在執行app.display()函數時,While 循環不起作用。
迷你云臺底座接口
在按鈕組小部件中定義角度 - 0、30、45、90、135、180。
分配相關命令(函數) - base_tilt_move。
迷你云臺臂接口
在按鈕組小部件中定義角度 - 0、30、45、90、135、180。
分配相關的命令(函數)——arm_tilt_move。
啟動循環 app.display() 。
特征
1) 改變儀器的背景顏色(RGB)。
2) 通過選擇中間角度 - 0、30、45、90、135、180 來調整迷你云臺套件上伺服電機的位置。
3) 當傳感器 (MQ-135) 檢測到空氣質量惡化時收到通知 - 狀態:危險。
在菜單欄上:
4) 進入教程頁面。
5) 檢查組件。
6) 顯示電梯間距。
連接
引腳連接在代碼和下面的項目示意圖中得到了很好的解釋。
將樹莓派連接到屏幕。
將 MCP3008 和 RGB LED 連接到迷你面包板上。在將 MCP3008 連接到 Raspberry Pi 之前,我使用了一個電位器來測試值范圍。
組裝迷你云臺套件并將 MQ-135 空氣質量傳感器粘在迷你云臺套件(臂)上。
總結
完成所有步驟后,我將所有部件固定在一個舊塑料盒上,并將設備放在我的桌子上,以收集空氣質量數據并使用樹莓派上的空氣質量模塊 (GUI) 調整其背景顏色
示意圖
代碼
# Raspberry Pi Adjustable Air Quality Detector Controlled via GUI
#
# Raspberry Pi 3B+
#
# By Kutluhan Aktar
#
# Learn how to develop a GUI, named Air Quality Module, to control a mini pan-tilt kit and get information from an MQ-135 Air Quality Sensor.
# Also, you can change the background light (RGB) via the GUI.
#
# Get more information on the project page:
# https://theamplituhedron.com/projects/Raspberry-Pi-Adjustable-Air-Quality-Detector-Controlled-via-GUI/
from guizero import App, Box, Text, TextBox, PushButton, ButtonGroup, MenuBar, info, yesno, warn
from time import sleep
from subprocess import call
import RPi.GPIO as GPIO
import busio
import digitalio
import board
import adafruit_mcp3xxx.mcp3008 as MCP
from adafruit_mcp3xxx.analog_in import AnalogIn
# Create the SPI bus
spi = busio.SPI(clock=board.SCK, MISO=board.MISO, MOSI=board.MOSI)
# Create the cs (chip select)
cs = digitalio.DigitalInOut(board.D5)
# Create the mcp object
mcp = MCP.MCP3008(spi, cs)
# Create analog inputs connected to the input pins on the MCP3008.
channel_0 = AnalogIn(mcp, MCP.P0)
# Define RGB pins settings and PWM frequencies
GPIO.setmode(GPIO.BCM)
red_pin = 2
green_pin = 3
blue_pin = 4
GPIO.setup(red_pin, GPIO.OUT)
GPIO.setup(green_pin, GPIO.OUT)
GPIO.setup(blue_pin, GPIO.OUT)
red_value = GPIO.PWM(red_pin, 100)
blue_value = GPIO.PWM(blue_pin, 100)
green_value = GPIO.PWM(green_pin, 100)
red_value.start(100)
blue_value.start(100)
green_value.start(100)
# Define servo motor pin settings and PWM frequencies
servo_base_pin = 20
servo_arm_pin = 21
GPIO.setup(servo_base_pin, GPIO.OUT)
GPIO.setup(servo_arm_pin, GPIO.OUT)
servo_base_value = GPIO.PWM(servo_base_pin, 50)
servo_arm_value = GPIO.PWM(servo_arm_pin, 50)
servo_base_value.start(0)
servo_arm_value.start(0)
# Define menu bar options' commands (functions).
def Tutorial():
# Open the project page if requested.
go_to_tutorial = yesno("Open Tutorial", "Get more information about the project!")
if go_to_tutorial == True:
command = "chromium-browser https://theamplituhedron.com/projects/"
call([command], shell=True)
print("Project Tutorial!")
else:
warn("Close", "Return to the application!")
def Components():
info("Components", "Raspberry Pi 3B+\nMQ-135 Sensor\nMini Pan-Tilt Kit\n2 x Servo Motor\nRGB LED\n2 x Mini Breadboard\nMCP3008")
def About():
info("About", "Develop a GUI, named Air Quality Module, to control a mini pan-tilt kit and get information from an MQ-135 Air Quality Sensor. Also, you can change the background light (RGB) on the GUI.")
# Define application commands and features:
def _range(x, in_min, in_max, out_min, out_max):
return int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)
def evaluateSensorValue():
# Test your module, then define the value range - in this case between 0 and 60000.
sensorValue = _range(channel_0.value, 0, 60000, 0, 1023)
sensor_value.value = sensorValue
# Threshold
if(sensorValue > 300):
status_text.value = "Status: DANGER"
status_text.text_color = "yellow"
warn("!!!DANGER!!!", "Air Quality Deteriorating!")
else:
status_text.value = "Status: OK"
status_text.text_color = "green"
def adjust_color():
red = _range(int(r_input.value), 0, 255, 1, 100)
green = _range(int(g_input.value), 0, 255, 1, 100)
blue = _range(int(b_input.value), 0, 255, 1, 100)
red_value.ChangeDutyCycle(101 - red)
blue_value.ChangeDutyCycle(101 - blue)
green_value.ChangeDutyCycle(101 - green)
def base_tilt_move():
# Cycle values between 2 and 12 are working precisely:
selected_angle = 2 + (int(base_angle.value) / 18)
servo_base_value.ChangeDutyCycle(selected_angle)
sleep(0.5)
servo_base_value.ChangeDutyCycle(0)
def arm_tilt_move():
selected_angle = 2 + (int(arm_angle.value) / 18)
servo_arm_value.ChangeDutyCycle(selected_angle)
sleep(0.5)
servo_arm_value.ChangeDutyCycle(0)
# Create the GUI application.
appWidth = 1200
appHeight = 500
app = App(title="Air Quality Module", bg="#eb2e00", width=appWidth, height=appHeight)
# Define menu bar options.
menubar = MenuBar(app, toplevel=["Tutorial", "Components", "About"],
options=[
[ ["View", Tutorial] ],
[ ["Inspect", Components ] ],
[ ["About", About] ]
])
# Design the interface using the box widget.
top = Box(app, width="fill", height=appHeight / 2, align="top")
bottom = Box(app, width="fill", height=appHeight / 2, align="bottom")
color_interface = Box(top, width=appWidth / 2, align="left", layout="grid", border=True)
quality_interface = Box(top, width=appWidth / 2, align="right")
base_interface = Box(bottom, width=appWidth / 2, align="left")
arm_interface = Box(bottom, width=appWidth / 2, align="right")
# RGB Color Interface
color_header = Text(color_interface, text="Adjust RGB Background Color", color="#002699", size=20, grid=[0,0])
r_label = Text(color_interface, text="R :", color="#1a53ff", size=15, grid=[0,1])
r_input = TextBox(color_interface, grid=[1,1])
r_input.bg = "#ff5c33"
r_input.text_color = "#1a53ff"
g_label = Text(color_interface, text="G :", color="#1a53ff", size=15, grid=[0,2])
g_input = TextBox(color_interface, grid=[1,2])
g_input.bg = "#ff5c33"
g_input.text_color = "#1a53ff"
b_label = Text(color_interface, text="B :", color="#1a53ff", size=15, grid=[0,3])
b_input = TextBox(color_interface, grid=[1,3])
b_input.bg = "#ff5c33"
b_input.text_color = "#1a53ff"
adjust_button = PushButton(color_interface, grid=[2,4], width="20", text="Adjust", command=adjust_color)
adjust_button.bg = "#002699"
adjust_button.text_color = "white"
# Air Quality Interface
quality_header = Text(quality_interface, text="Air Quality Sensor", color="#002699", size=20, align="top")
sensor_value = Text(quality_interface, text="TEST", color="#002699", size=120)
status_text = Text(quality_interface, text="Status: OK", color="green", size=15, align="bottom")
# Update the sensor value.
sensor_value.repeat(1000, evaluateSensorValue)
# Mini Pan-Tilt Base Interface
base_header = Text(base_interface, text="Pan-Tilt Base", color="#002699", size=20)
base_angle = ButtonGroup(base_interface, options=["0", "30", "45", "90", "135", "180"], selected="0", width=20, command=base_tilt_move)
base_angle.text_size = 15
base_angle.text_color = "white"
# Mini Pan-Tilt Arm Interface
arm_header = Text(arm_interface, text="Pan-Tilt Arm", color="#002699", size=20)
arm_angle = ButtonGroup(arm_interface, options=["0", "30", "45", "90", "135", "180"], selected="0", width=20, command=arm_tilt_move)
arm_angle.text_size = 15
arm_angle.text_color = "white"
# Start the loop.
app.display()
-
檢測器
+關注
關注
1文章
860瀏覽量
47654 -
GUI
+關注
關注
3文章
650瀏覽量
39553
發布評論請先 登錄
相關推薦
評論