本文已参与「新人创作礼」活动,一起开启掘金创作之路。
一、简介
本文是对霍尔传感器使用的一次记录,内容上将会介绍如何通过霍尔传感器检测到磁场实现双色灯,以及如何通过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()
四、资料准备
为了快速记录,所以就没有详细介绍各个传感器的使用说明,想要进一步了解学习的朋友可以自行百度搜索,或者查看下方的相关文章: