【RPi系列】树莓派与霍尔传感器的那些事儿

80 阅读6分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

一、简介

  本文是对霍尔传感器使用的一次记录,内容上将会介绍如何通过霍尔传感器检测到磁场实现双色灯,以及如何通过socket将其采集到的数据存入PC端的数据库。 在这里插入图片描述

二、硬件准备

1、元器件清单

名称数量
Raspberry Pi 4B1
GPIO扩展板套件1
PCF8591模数转换器1
霍尔传感器1
双色Led1
面包板1

2、接线说明

创乐博

GPIO扩展板PCF8591
SDASDA
SCLSCL
5VVCC
GNDGND
GPIO扩展板PCF8591霍尔传感器
*AIN0A0
G17*D0
5VVCCVCC
GNDGNDGND
GPIO扩展板双色Led
G18R
G27G
GNDGND

三、软件准备

  因为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()

在这里插入图片描述

四、资料准备

  为了快速记录,所以就没有详细介绍各个传感器的使用说明,想要进一步了解学习的朋友可以自行百度搜索,或者查看下方的相关文章: