在树莓派RaspberryPi上几种简单协议的实现

对自己的拖延症也真是恨铁不成钢,这又是一篇拖延得快要放弃的文章。快过年了,怎么也不能拖到年后,打起精神,清空列表!

想要自己打造一个小小家庭环境监控系统,各种Sensor不可或缺。看了下大部分人在树莓派上都用Python, 我也来凑个热闹。Python果然是一种很容易入门的语言,我只是稍微查了下资料,半天时间,就搞定了好几个Sensor,当然只是最简单的拿数据什么的,但相比之下,虽然自己对于用C写这些协议很熟,碰到问题我也宁可去看看Python的语法也不愿意换C……Python的优势倒不全是语法简洁,最重要的是有巨量的开发库可以用。像这些简单的协议,全是把库装好,直接拿来用就可以了,看看代码量,简直让人不忍再直视C的代码。对于不用追求速度的玩票项目,相当适合。
这一篇先介绍几种最常用的基本协议的实现,老规矩,先上源码传送门

GPIO

GPIO口很简单,要不输入,要不输出。先装一下开发库:
sudo apt-get install python-rpi.gpio
然后在代码里面引用:

import time
import RPi.GPIO as GPIO
# 定义引脚
gpio_pin=17
print("start gpio test for pin=bcm%d" %pin)
GPIO.setmode(GPIO.BCM)
# 设为Input,读取GPIO
GPIO.setup(pin, GPIO.IN)
value = GPIO.input(pin)
print("before set, pin=%d" %value)
# 改变GPIO输出
GPIO.setup(pin, GPIO.OUT)
GPIO.output(pin, value)
print("now pin=%d" %GPIO.input(pin))
GPIO.cleanup()

这里只是一个Demo,实际应用中不大有能让你随便拉高拉低还能保持住你设置的情况。一般像灯啊之类的,就是你拉高它就亮拉低它就黑;要不就是一些输入设备类似按键,或者更复杂的有Timing的输入。这里要注意两点:

  1. setmode用的是BCM模式,所用的Pin也要跟引脚图上相对应的BCM号码相同。你也可以设成物理管脚号,用setmode(GPIO.BOARD)
  2. input/output模式是相对于host也就是树莓派来说的接收数据/状态的时候是input,输出状态的时候是output

I2C

I2C是可以一条总线接n个设备的,只要设备的I2C地址不冲突,你尽可以用面包板扩展一下,接上好几个。首先依然是添加开发库,注意这个库貌似只在python2里用,如果我换python3就会报错找不到,可能我不太熟吧……
sudo apt-get -y install python-smbus
然后接好硬件,如果你需要确认一下硬件,可以用i2c的工具看看:

sudo apt-get -y install i2c-tools
sudo i2cdetect -y 1

参数1是指设备i2c-1,在rpi2上默认就是1,i2c0预留给E2PROM用了,没去折腾打开它。如果你看到一个类似下面的结果,说明硬件已经OK了。

上面的图表示有两个I2C设备接在总线上,它们的地址分别是0x48和0x77。如果你没看见有设备,检查硬件连接,还有记得在系统的config里面打开i2c。
然后依然是sample code:

import time
import smbus

addr=0x48
cmd=0xAB
# 打开 /dviev/i2c-1  
bus = smbus.SMBus(1)
# 读写数据,case 1
data = bus.read_byte(addr)
bus.write_byte(addr, data+1)
# 读写数据,case 2
data = bus.read_byte_data(addr, cmd)
bus.write_byte_data(addr, cmd, data+1)

大部分I2C设备的读写,除了需要i2c device地址以外,还要有一些固定cmd,所以读写接口是有两种,具体要看设备spec里面的要求,大同小异。

UART

串口UART通信主要有两种,一种是用来调试的命令行,一种是sensor的数据接口。总觉得串口调试是很久远的事情了,特别是在树莓派上,基本上都是网络ssh吧。看了些其他的例程,都是做串口调试,其实如果只是拿个数据没那么复杂。
首先当然还是装酷(库):
sudo apt-get -y install python-serial
然后多做一步:树莓派默认的console是UART输出的,改掉(记得用sudo改)。
打开/boot/cmdline.txt,里面的内容”dwc_otg.lpm_enable=0 console=ttyAMA0,115200console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline
fsck.repair=yes rootwait”,粗体字部分删掉,因为ttyAMA0就是我们要使用的设备。
在部分别的文章中见过还需要改一个地方,可能是上一代rpi用的,如果你的系统是最新的,不需要做。
测试代码部分:

import serial
import time

def showdata(arg):
    result = ''
    for i in arg:
        st = '%02X'%ord(i)
        result += st+' '
    print(result)

ser = serial.Serial('/dev/ttyAMA0', 9600, timeout=1)
# 获得接收缓冲区字符
#count = ser.inWaiting()
# 读取内容
data = ser.read(5)
showdata(data)
# 清空接收缓冲区
#ser.flushInput()
ser.close()

上面的code中,函数showdata()是我自己加的用来打印读取到的16进制数据的。因为我接的设备是一个sensor而不是字符设备,所以需要转换一下。同样的,被注释掉的inWaiting()和flushInput()函数,是给字符输入输出设备用的,我也没测过,在我的机子上,因为sensor会不停地报数据,简单的read就行了。
另外硬件连接方面很重要的一点:

树莓派的TX要连接从设备的RX,树莓派的RX要连接从设备的TX!!!

不要搞反了,不然是出不来数据的!

SPI-暂时没有

本来是买了个SPI的屏幕,谁知快递出问题没送到,好不容易收到了找卖家要资料也总是忘掉,所以只好欠奉了。快过年了,估计得过些日子再说吧!
话说,家里的NAS系统升级以后,居然admin也不是root权限了,好多隐藏的文件夹都打不开。我的BitSync出了点问题,想去看看配置文件,也是束手无策。看来Qnap是不打算给人玩了,认认真真做商业机。幸好有树莓派,以后玩点乱七八糟的东西,就只能靠它了。
另:我Github上的源码中,有几个传感器的demo,包括bmp180,dht11,pcf8591等,需要的话随意取用。

3 条关于 “在树莓派RaspberryPi上几种简单协议的实现”的评论

  1. 想问一下博主串口那个程序里的data到底是个什么类型的数据,16进制数还是什么,如果是16进制数,怎么判断它是不是我想要的数的代码怎么写,比如判断data是不是0x55

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

*