文章目錄
- 一、簡介
- 二、硬體準備
-
- 1、元器件清單
- 2、接線說明
- 三、軟體準備
-
- 1、打開I2C通信
- 2、樹莓派采集不發送至PC
- 3、将采集到的資料發送至PC,并存入資料庫
- 四、資料準備
一、簡介
本文是對霍爾傳感器使用的一次記錄,内容上将會介紹如何通過霍爾傳感器檢測到磁場實作雙色燈,以及如何通過socket将其采集到的資料存入PC端的資料庫。
二、硬體準備
1、元器件清單
名稱 | 數量 |
---|---|
Raspberry Pi 4B | 1 |
GPIO擴充闆套件 | 1 |
PCF8591模數轉換器 | 1 |
霍爾傳感器 | 1 |
雙色Led | 1 |
面包闆 | 1 |
2、接線說明
GPIO擴充闆 | PCF8591 |
---|---|
SDA | SDA |
SCL | SCL |
5V | VCC |
GND | GND |
GPIO擴充闆 | PCF8591 | 霍爾傳感器 |
---|---|---|
* | AIN0 | A0 |
G17 | * | D0 |
5V | VCC | VCC |
GND | GND | GND |
GPIO擴充闆 | 雙色Led |
---|---|
G18 | R |
G27 | G |
GND | GND |
三、軟體準備
因為pcf8591是通過I2C與樹莓派進行通信的,是以我們第一步首先就是打開I2C。
1、打開I2C通信
2、樹莓派采集不發送至PC
該代碼實作的是當霍爾傳感器檢測到磁場時,亮紅燈;沒有檢測到磁場時,亮綠燈。模拟信号輸出表示檢測到磁場時,列印檢測到磁場的資訊“Detected magnetic materials”。同時數字信号輸出表示檢測到磁場時,列印“Detected Magnet”。
- PCF8591.py:
#!/usr/bin/env python
#------------------------------------------------------
#
# 您可以使用下面語句将此腳本導入另一個腳本:
# “import PCF8591 as ADC”
#
# ADC.Setup(Address) # 查詢PCF8591的位址:“sudo i2cdetect -y 1”
# i2cdetect is a userspace program to scan an I2C bus for devices.
# It outputs a table with the list of detected devices on the specified bus.
# ADC.read(channal) # Channal範圍從0到3
# ADC.write(Value) # Value範圍從0到255
#
#------------------------------------------------------
#SMBus (System Management Bus,系統管理總線)
import smbus #在程式中導入“smbus”子產品
import time
# for RPI version 1, use "bus = smbus.SMBus(1)"
# 0 代表 /dev/i2c-0, 1 代表 /dev/i2c-1 ,具體看使用的樹莓派那個I2C來決定
bus = smbus.SMBus(1) #建立一個smbus執行個體
#在樹莓派上查詢PCF8591的位址:“sudo i2cdetect -y 1”
def setup(Addr):
global address
address = Addr
def read(chn): #channel
if chn == 0:
bus.write_byte(address,0x40) #發送一個控制位元組到裝置
if chn == 1:
bus.write_byte(address,0x41)
if chn == 2:
bus.write_byte(address,0x42)
if chn == 3:
bus.write_byte(address,0x43)
bus.read_byte(address) # 從裝置讀取單個位元組,而不指定裝置寄存器。
return bus.read_byte(address) #傳回某通道輸入的模拟值A/D轉換後的數字值
def write(val):
temp = val # 将字元串值移動到temp
temp = int(temp) # 将字元串改為整數類型
# print temp to see on terminal else comment out
bus.write_byte_data(address, 0x40, temp)
#寫入位元組資料,将數字值轉化成模拟值從AOUT輸出
if __name__ == "__main__":
setup(0x48)
#在樹莓派終端上使用指令“sudo i2cdetect -y 1”,查詢出PCF8591的位址為0x48
while True:
print '電位計 AIN0 = ', read(0) #電位計模拟信号轉化的數字值
print '光敏電阻 AIN1 = ', read(1) #光敏電阻模拟信号轉化的數字
print '熱敏電阻 AIN2 = ', read(2) #熱敏電阻模拟信号轉化的數字值
tmp = read(0)
tmp = tmp*(255-125)/255+125
# 125以下LED不會亮,是以将“0-255”轉換為“125-255”,調節亮度時燈不會熄滅
write(tmp)
time.sleep(2)
- Hall.py
#/usr/bin/env python
import RPi.GPIO as GPIO
import PCF8591 as ADC
import time
HallPin = 11
Gpin = 13
Rpin = 12
def setup():
ADC.setup(0x48)
GPIO.setmode(GPIO.BOARD) # Numbers GPIOs by physical location
GPIO.setup(Gpin, GPIO.OUT) # Set Green Led Pin mode to output
GPIO.setup(Rpin, GPIO.OUT) # Set Red Led Pin mode to output
GPIO.setup(HallPin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Set BtnPin's mode is input, and pull up to high level(3.3V)
GPIO.add_event_detect(HallPin, GPIO.BOTH, callback=detect, bouncetime=200)
# 檢測到磁場時,數字輸出低電平,即GPIO.input(HallPin)==0
#沒有檢測到磁場時,數字輸出高電平,即GPIO.input(HallPin)==1
def Led(x):
if x == 0: #檢測到磁場時,亮紅燈
GPIO.output(Rpin, 1)
GPIO.output(Gpin, 0)
if x == 1: #沒有檢測到磁場時,亮綠燈
GPIO.output(Rpin, 0)
GPIO.output(Gpin, 1)
def Print1(x):
if x == 0: #檢測到磁場時,數字輸出低電平,x==0
print ' ***********************************'
print ' * Detected magnetic materials *'
print ' ***********************************'
def detect(chn):
Led(GPIO.input(HallPin))
Print1(GPIO.input(HallPin))
def Print2(x):
if x == 1:
print ''
print '*************'
print '* No Magnet *'
print '*************'
print ''
if x == 0:
print ''
print '*************'
print '* Detected Magnet *'
print '*************'
print ''
def loop():
status = 0
while True:
res = ADC.read(0) #模拟輸出信号A/D轉換後的數字信号值
print 'Current intensity of magnetic field : ', res
if res < 10: #這裡的數字輸出ADC.read(0)隻有兩個值,0或255
tmp = 0 #ADC.read(0)為255時沒有檢測到磁場
#ADC.read(0)為 0 時檢測到磁場,但有少量誤差的其它值,比如1或254等值偶爾出現
if res > 200:
tmp = 1
if tmp != status:
Print2(tmp)
status = tmp
time.sleep(0.5)
def destroy():
GPIO.output(Gpin, GPIO.LOW) # Green led off
GPIO.output(Rpin, GPIO.LOW) # Red led off
GPIO.cleanup() # Release resource
if __name__ == '__main__':
setup()
try:
loop()
except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child program destroy() will be executed.
destroy()
3、将采集到的資料發送至PC,并存入資料庫
PCF8591.py代碼不變,在Hall.py添加socket通信。
- Hall.py
#/usr/bin/env python
import RPi.GPIO as GPIO
import PCF8591 as ADC
import socket
import time
HallPin = 11
Gpin = 13
Rpin = 12
print("用戶端開啟")
#套接字接口
mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
def setup():
ADC.setup(0x48)
GPIO.setmode(GPIO.BOARD) # Numbers GPIOs by physical location
GPIO.setup(Gpin, GPIO.OUT) # Set Green Led Pin mode to output
GPIO.setup(Rpin, GPIO.OUT) # Set Red Led Pin mode to output
GPIO.setup(HallPin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Set BtnPin's mode is input, and pull up to high level(3.3V)
GPIO.add_event_detect(HallPin, GPIO.BOTH, callback=detect, bouncetime=200)
# 檢測到磁場時,數字輸出低電平,即GPIO.input(HallPin)==0
#沒有檢測到磁場時,數字輸出高電平,即GPIO.input(HallPin)==1
def Led(x):
if x == 0: #檢測到磁場時,亮紅燈
GPIO.output(Rpin, 1)
GPIO.output(Gpin, 0)
if x == 1: #沒有檢測到磁場時,亮綠燈
GPIO.output(Rpin, 0)
GPIO.output(Gpin, 1)
def Print1(x):
if x == 0: #檢測到磁場時,數字輸出低電平,x==0
print (' ***********************************')
print (' * Detected magnetic materials *')
print (' ***********************************')
def detect(chn):
Led(GPIO.input(HallPin))
Print1(GPIO.input(HallPin))
def Print2(x):
if x == 1:
print ('')
print ('*************')
print ('* No Magnet *')
print ('*************')
print ('')
if x == 0:
print ('')
print ('*************')
print ('* Detected Magnet *')
print ('*************')
print ('')
def connect():
#設定ip和端口
host = 'XXX.XXX.XXX.XXX' ## ip位址
port = 2222
try:
mySocket.connect((host, port)) ##連接配接到伺服器
print("連接配接到伺服器")
except : ##連接配接不成功,運作最初的ip
print ('連接配接不成功')
def loop():
status = 0
while True:
res = ADC.read(0) #模拟輸出信号A/D轉換後的數字信号值
print ('Current intensity of magnetic field : ', res)
if res < 10: #這裡的數字輸出ADC.read(0)隻有兩個值,0或255
tmp = 0 #ADC.read(0)為255時沒有檢測到磁場
#ADC.read(0)為 0 時檢測到磁場,但有少量誤差的其它值,比如1或254等值偶爾出現
if res > 200:
tmp = 1
if tmp != status:
Print2(tmp)
status = tmp
#編碼發送
msg = str(res)
mySocket.send(msg.encode("utf-8"))
print("發送完成")
time.sleep(10)
if msg == "over":
mySocket.close()
print("通信結束\n")
exit()
def destroy():
GPIO.output(Gpin, GPIO.LOW) # Green led off
GPIO.output(Rpin, GPIO.LOW) # Red led off
GPIO.cleanup() # Release resource
print("程式結束\n")
if __name__ == '__main__':
setup()
connect()
try:
loop()
except KeyboardInterrupt: # When 'Ctrl+C' is pressed, the child program destroy() will be executed.
destroy()
- PC.py
import pymysql # 導入 pymysql
import socket
import time
print("服務端開啟")
# 套接字接口
mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設定IP和端口
host = 'xxx.xxx.xxx.xxx'
port = 2222
# bind綁定該端口
mySocket.bind((host, port))
mySocket.listen(10)
# 打開資料庫連接配接
db = pymysql.connect(
host='localhost',
port=3306,
user='root',
passwd='123456',
db='xxdb',
charset='utf8'
)
print("資料庫開啟")
# 使用 cursor() 方法建立一個遊标對象 cursor
cursor = db.cursor()
sqltime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
while True:
# 接收用戶端連接配接
print("等待連接配接....")
client, address = mySocket.accept()
print("新連接配接")
print("IP is %s" % address[0])
print("port is %d\n" % address[1])
while True:
# 讀取消息
msg = client.recv(1024)
# 把接收到的資料進行解碼
print(msg.decode("utf-8"))
print("讀取完成")
# SQL 插入語句
# sql = "INSERT INTO MAGNETISM(MTIME , MFLAG) VALUES ('%s','%s')" % (sqltime, msg.decode("utf-8"))
sql = "INSERT INTO MAGNETISM(MFLAG) VALUES ('%s')" % (msg.decode("utf-8"))
try:
# 執行sql語句
cursor.execute(sql)
# 送出到資料庫執行
db.commit()
except:
# 如果發生錯誤則復原
db.rollback()
time.sleep(10)
if msg == "over":
client.close()
mySocket.close()
# 關閉資料庫連接配接
db.close()
print("程式結束\n")
exit()
四、資料準備
為了快速記錄,是以就沒有詳細介紹各個傳感器的使用說明,想要進一步了解學習的朋友可以自行百度搜尋,或者檢視下方的相關文章:
- 樹莓派與PCF8591模數轉換器的那些事兒
- 樹莓派與雙色Led子產品的那些事兒
- 樹莓派使用Socket發送資料至PC并存入資料庫
- STC12C2052與LCD1602液晶顯示屏的那些事兒(2)