前言
我一直梦想着能够做出一款自制的飞行器,然后带着它游历世界各地,拍摄各种好玩的照片。听说树莓派似乎可以将我的编程专业发挥出来,既然如此,那么就开干吧。
那么就从环境的搭建开始做起,并以此博客作为记录和总结,也方便各位树莓派以及飞行器爱好者参考和借鉴。此外,我写的代码都会公开出来,方便大家探讨。
当然,本人初学者更希望有各路大神指点指点。
树莓派(Raspberry Pi)是学习计算机知识、架设服务器的好工具,价格低廉,可玩性高。
本文根据我的亲身经验,介绍如何从零开始,搭建一个树莓派服务器,控制 LED 灯。你会看到,树莓派玩起来实在很容易。
一、型号
树莓派是一个迷你电脑,集成在一块电路板。目前,最新的型号有两个。
(1)Raspberry Pi 3代 B 型
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061502.jpg)
(2)Raspberry Pi zero (含 zero w)
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061503.jpg)
虽然后者便宜,但是少了许多接口(比如只有一个 USB 口),CPU 和内存都比较低,配件也少,因此推荐购买第3代的 B 型。以下都针对这个型号,但大部分内容对 zero 也适用。
二、配件
树莓派本身只是一个主机。要运行起来,必须有配件。
(1)电源
Micro USB 接口的手机充电器,就可以充当电源,但输出必须是 5V 电压、至少 2A 电流。充电宝当电源也没问题。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061504.jpg)
(2)Micro SD 卡
树莓派不带硬盘,Micro SD 卡就是硬盘。最小容量8G,推荐使用16G和32G的卡。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061506.jpg)
(3)显示器
树莓派有 HDMI 输出,显示器必须有该接口。如果有 HDMI 转 VGA 的转接线,那么 VGA 显示器也可以。我用的是一个 7 寸的液晶监视器。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061507.jpg)
不过,显示器只在安装系统时需要,后面可以 SSH登录 ,所以就不需要了。
(4)无线键鼠
树莓派内置蓝牙,USB 或蓝牙的无线键鼠都可以用。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061508.jpg)
就像显示器一样,如果树莓派已经装好系统,而且只当作服务器,无线键鼠也可以不配。
三、电子元件
除了配件,下面的实验还需要一些电子元件。
(1)面包板(一块)
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061509.jpg)
(2)连接线(若干)
注意,连接线必须一端是公头,一端是母头。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061510.jpg)
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061511.jpg)
另外,最好也备一些两端都是公头的连接线。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061512.jpg)
(3)LED 二极管(若干)
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061512.gif)
(4)270欧姆的电阻(若干)
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061513.jpg)
四、安装系统
如果商家已经装好系统,可以跳过这一步,否则需要自己安装操作系统。
官方提供的操作系统是 Raspbian,这是 Debian 系统的定制版。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061514.png)
官方还提供一个安装器 NOOBS,建议通过它来安装 Raspbian,相对简单一点。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061515.png)
下载 NOOBS。
格式化 Micro SD 卡为 FAT 格式(操作指导)。
解压NOOBS.zip到 Micro SD 卡根目录。
插入 Micro SD 卡到树莓派底部的卡槽,接通电源,启动系统。
正常情况下,按照屏幕上的提示,一路回车,就能装好系统。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061516.png)
五、SSH 登录
安装系统后,树莓派就可以上网了(Wifi 或者网线)。这时,你要看一下它的局域网 IP 地址,可以使用下面的命令。
$ sudo ifconfig
然后,更改系统设置,打开 SSH 登录(默认是禁止的)。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061521.png)
接着,从另一台电脑 SSH 登录树莓派。下面的命令是在局域网的另一台电脑上执行的。
$ ssh [email protected]
上面代码中,192.168.1.5
是我的树莓派的地址,你要换成你的地址。树莓派的默认用户是pi
。
树莓派会提示你输入密码。pi
的默认密码是raspberry
。正常情况下,这样就可以登录树莓派了。接着,就可以进行各种服务器操作了,比如修改密码。
$ passwd
后面的实验需要将用户加入gpio
用户组。
$ sudo adduser pi gpio
上面的代码表示将用户pi
加入gpio
用户组。
六、安装 Node
为了运行 Node 脚本,树莓派必须安装 Node,可以参考这篇文章。
$ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
$ sudo apt install nodejs
正常情况下,Node 8.x 版就已经安装成功了。
$ node -v
v8.1.0
七、点亮 LED
树莓派提供了一组对外的 IO 接口,称为 GPIO( 通用 IO 接口,General-purpose input/output)。
GPIO基本介绍
GPIO(General Purpose I/O Ports)意思为通用输入/输出端口,通俗地说,就是一些引脚,可以通过它们输出高低电平或者通过它们读入引脚的状态-是高电平或是低电平。GPIO是个比较重要的概念,用户可以通过GPIO口和硬件进行数据交互(如UART),控制硬件工作(如LED、蜂鸣器等),读取硬件的工作状态信号(如中断信号)等。GPIO口的使用非常广泛。掌握了GPIO,差不多相当于掌握了操作硬件的能力。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061518.jpg)
它的 40 个脚的定义如下图。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061519.png)
注意,左上角的第1针(3.3V)是一个方块,其他针脚都是圆的。将树莓派翻过来,背后可以看到 GPIO 有一个角是方的,通过这种方法就可以确认哪一个针眼是3.3V。
补充: 3.3v和5v代表着该针脚会输出3.3v和5v的电压,Ground代表着该针脚是接地的,GPIO0*则是一些待用户开发的针脚。每个针脚都可以使用程序进行控制操作。ground 代表 接地。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061516.jpg)
通过 GPIO ,树莓派可以与其他电子元件连接。下面根据 Jonathan Perkin 的文章,使用树莓派连接 LED 二极管。
这里需要用到面包板。本质上,面包板就是几根导线,上面开了许多可以连到导线的孔。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061519.jpg)
+
极和-
极是两根垂直的导线,标着1
、5
、10
这些数字的行,每一行都是一根水平的导线。导线与导线之间互不连接,另外,面包板的左右两半也是互不连接的。
然后,按照下面的图,将树莓派、面包板、LED 灯、电阻连起来。
![](https://www.huaijiujia.com/wp-content/uploads/2018/01/bg2017061520.jpg)
上图中,红色导线表示电流的正极,从 GPIO 的第1针(3.3V)连到面包板。黑色导线表示电流的负极,从 GPIO 第三排的第6针(ground)连到面包板。它们连到面包板的哪个眼并不重要,但必须保证能组成一个完整的电路(上图的箭头流向)。注意,LED 二极管也有正负极,长脚表示正极,短脚表示负极。电阻没有正负极。
连接完成后,打开树莓派的电源,LED 应该就会亮起来了。
八、LED 控制脚本
下面,我们使用 Node 脚本控制 LED。
首先,将正极的导线从1号针脚(3.3V)拔出,插到第6排的11号针脚(上图的 GPIO 17)。这个针脚的电流是脚本可以控制的。
然后,在树莓派上新建一个实验目录,并安装控制 GPIO 的 Node 模块rpio
。。
$ mkdir led-demo && cd led-demo
$ npm init -y
$ npm install -S rpio
接着,新建一个脚本led-on.js
。
// led-on.js
var rpio = require('rpio');
// 打开 11 号针脚(GPIO17) 作为输出
rpio.open(11, rpio.OUTPUT);
// 指定 11 号针脚输出电流(HIGH)
rpio.write(11, rpio.HIGH);
运行这个脚本,应该就会看到 LED 灯泡变亮了。
$ node led-on.js
再新建一个led-off.js
脚本,只要改一行就行。
var rpio = require('rpio');
// Configure pin 11 (GPIO17) for output (i.e. read/write).
// rpio.setOutput(11);
rpio.open(11, rpio.OUTPUT);
// 指定 11 号针脚停止输出电流(LOW)
// Turn GPIO17 off, also known as 'LOW'.
rpio.write(11, rpio.LOW);
运行这个脚本,LED 灯泡应该就会熄灭了。
$ node led-off.js
有了这两个脚本,让 LED 闪烁就轻而易举了。新建一个led-blink.js
脚本。
var rpio = require('rpio');
rpio.open(11, rpio.OUTPUT);
/*
* Blink the LED quickly (10 times per second). It is switched on every
* 100ms, and a timeout is set for 50ms later to switch it off, giving us
* the regular blink.
*/
setInterval(function blink() {
rpio.write(11, rpio.HIGH);
setTimeout(function ledoff() {
rpio.write(11, rpio.LOW);
}, 50);
}, 100);
上面的脚本让 LED 每秒闪烁10次。
$ node led-blink.js
九、HTTP 服务器
通过控制 LED 可以做很多事,比如架设一个 HTTP 服务器,每当有人访问,LED 就闪烁一下。
首先,在刚才的目录里面装一个服务器模块。
$ npm install -S server
然后,新建一个脚本server.js
。
var server = require('server');
var { get } = server.router;
var rpio = require('rpio');
rpio.open(11, rpio.OUTPUT);
function blink() {
rpio.write(11, rpio.HIGH);
setTimeout(function ledoff() {
rpio.write(11, rpio.LOW);
}, 50);
}
server({ port: 8080 }, [
get('/' , ctx => {
console.log('a request is coming...');
blink();
}),
]);
console.log('server starts on 8080 port');
运行这个脚本。
$ node server.js
然后,再打开一个命令行终端,访问8080端口,LED 就会闪一下。
$ curl http://localhost:8080
好了,今天的教程就到这里。接下来,你可以自己探索,做更多的尝试,比如写一个测试用例脚本,只要测试失败 LED 就会长亮,或者组装一个8位的加法器。
python控制GPIO(教程可能是树莓派2的引脚,自己注意一下)
想用python来控制GPIO,最便捷的办法就是使用一些python类库,比如树莓派系统本身集成的RPi.GPIO。本文详细介绍如何使用RPi.GPIO来控制GPIO。
导入RPi.GPIO模块
可以用下面的代码导入RPi.GPIO模块。
import RPi.GPIO as GPIO
引入之后,就可以使用GPIO模块的函数了。如果你想检查模块是否引入成功,也可以这样写:
try:
import RPi.GPIO as GPIO
except RuntimeError:
print("引入错误")
针脚编号
在RPi.GPIO中,同时支持树莓派上的两种GPIO引脚编号。第一种编号是BOARD编号,这和树莓派电路板上的物理引脚编号相对应。使用这种编号的好处是,你的硬件将是一直可以使用的,不用担心树莓派的版本问题。因此,在电路板升级后,你不需要重写连接器或代码。
第二种编号是BCM规则,是更底层的工作方式,它和Broadcom的片上系统中信道编号相对应。在使用一个引脚时,你需要查找信道号和物理引脚编号之间的对应规则。对于不同的树莓派版本,编写的脚本文件也可能是无法通用的。
你可以使用下列代码(强制的)指定一种编号规则:
GPIO.setmode(GPIO.BOARD)
# or
GPIO.setmode(GPIO.BCM)
下面代码将返回被设置的编号规则
mode = GPIO.getmode()
警告
如果RPi.GRIO检测到一个引脚已经被设置成了非默认值,那么你将看到一个警告信息。你可以通过下列代码禁用警告:
GPIO.setwarnings(False)
引脚设置
在使用一个引脚前,你需要设置这些引脚作为输入还是输出。配置一个引脚的代码如下:
# 将引脚设置为输入模式
GPIO.setup(channel, GPIO.IN)
# 将引脚设置为输出模式
GPIO.setup(channel, GPIO.OUT)
# 为输出的引脚设置默认值
GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH)
释放
一般来说,程序到达最后都需要释放资源,这个好习惯可以避免偶然损坏树莓派。释放脚本中的使用的引脚:
GPIO.cleanup()
注意,GPIO.cleanup()只会释放掉脚本中使用的GPIO引脚,并会清除设置的引脚编号规则。
输出
要想点亮一个LED灯,或者驱动某个设备,都需要给电流和电压他们,这个步骤也很简单,设置引脚的输出状态就可以了,代码如下:
GPIO.output(channel, state)
状态可以设置为0 / GPIO.LOW / False / 1 / GPIO.HIGH / True。如果编码规则为,GPIO.BOARD,那么channel就是对应引脚的数字。
如果想一次性设置多个引脚,可使用下面的代码:
chan_list = [11,12]
GPIO.output(chan_list, GPIO.LOW)
GPIO.output(chan_list, (GPIO.HIGH, GPIO.LOW))
你还可以使用Input()函数读取一个输出引脚的状态并将其作为输出值,例如:
GPIO.output(12, not GPIO.input(12))
读取
我们也常常需要读取引脚的输入状态,获取引脚输入状态如下代码:
GPIO.input(channel)
低电平返回0 / GPIO.LOW / False,高电平返回1 / GPIO.HIGH / True。
如果输入引脚处于悬空状态,引脚的值将是漂动的。换句话说,读取到的值是未知的,因为它并没有被连接到任何的信号上,直到按下一个按钮或开关。由于干扰的影响,输入的值可能会反复的变化。
使用如下代码可以解决问题:
GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# or
GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
需要注意的是,上面的读取代码只是获取当前一瞬间的引脚输入信号。
如果需要实时监控引脚的状态变化,可以有两种办法。最简单原始的方式是每隔一段时间检查输入的信号值,这种方式被称为轮询。如果你的程序读取的时机错误,则很可能会丢失输入信号。轮询是在循环中执行的,这种方式比较占用处理器资源。另一种响应GPIO输入的方式是使用中断(边缘检测),这里的边缘是指信号从高到低的变换(下降沿)或从低到高的变换(上升沿)。
轮询方式
while GPIO.input(channel) == GPIO.LOW:
time.sleep(0.01) # wait 10 ms to give CPU chance to do other things
边缘检测
边缘是指信号状态的改变,从低到高(上升沿)或从高到低(下降沿)。通常情况下,我们更关心于输入状态的该边而不是输入信号的值。这种状态的该边被称为事件。
先介绍两个函数:
- wait_for_edge() 函数。
wait_for_edge()被用于阻止程序的继续执行,直到检测到一个边沿。也就是说,上文中等待按钮按下的实例可以改写为
channel = GPIO.wait_for_edge(channel, GPIO_RISING, timeout=5000)
if channel is None:
print('Timeout occurred')
else:
print('Edge detected on channel', channel)
- add_event_detect() 函数
该函数对一个引脚进行监听,一旦引脚输入状态发生了改变,调用event_detected()函数会返回true,如下代码:
GPIO.add_event_detect(channel, GPIO.RISING) # add rising edge detection on a channel
do_something()
// 下面的代码放在一个线程循环执行。
if GPIO.event_detected(channel):
print('Button pressed')
上面的代码需要自己新建一个线程去循环检测event_detected()的值,还算是比较麻烦的。
不过可采用另一种办法轻松检测状态,这种方式是直接传入一个回调函数:
def my_callback(channel):
print('This is a edge event callback function!')
print('Edge detected on channel %s'%channel)
print('This is run in a different thread to your main program')
GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback)
如果你想设置多个回调函数,可以这样:
def my_callback_one(channel):
print('Callback one')
def my_callback_two(channel):
print('Callback two')
GPIO.add_event_detect(channel, GPIO.RISING)
GPIO.add_event_callback(channel, my_callback_one)
GPIO.add_event_callback(channel, my_callback_two)
注意:回调触发时,并不会同时执行回调函数,而是根据设置的顺序调用它们。
综合例子:点亮LED灯
好了,上面说明了一大堆函数库的用法,那么现在就应该来个简单的实验了。这个实验很简单,点亮一个LED灯。
- 编写代码之前,首先你需要将led灯的针脚通过杜邦线连接到树莓派的引脚上,比如你可以连接到11号引脚。
- 新建一个main.py文件,写入如下代码:
import RPi.GPIO as GPIO //引入函数库
import time
RPi.GPIO.setmode(GPIO.BOARD) //设置引脚编号规则
RPi.GPIO.setup(11, RPi.GPIO.OUT) //将11号引脚设置成输出模式
while True
GPIO.output(channel, 1) //将引脚的状态设置为高电平,此时LED亮了
time.sleep(1) //程序休眠1秒钟,让LED亮1秒
GPIO.output(channel, 0) //将引脚状态设置为低电平,此时LED灭了
time.sleep(1) //程序休眠1秒钟,让LED灭1秒
GPIO.cleanup() //程序的最后别忘记清除所有资源
- 保存,并退出文件。执行
python3 main.py
,即可观看效果。Ctrl+C
可以关闭程序。
- 此外,不妨也试试其它的函数吧,增强印象。
使用PWM
这个python函数库还支持PWM模式的输出,我们可以利用PWM来制作呼吸灯效果。详情看代码:
import time
import RPi.GPIO as GPIO //引入库
GPIO.setmode(GPIO.BOARD) //设置编号方式
GPIO.setup(12, GPIO.OUT) //设置12号引脚为输出模式
p = GPIO.PWM(12, 50) //将12号引脚初始化为PWM实例 ,频率为50Hz
p.start(0) //开始脉宽调制,参数范围为: (0.0 <= dc <= 100.0)
try:
while 1:
for dc in range(0, 101, 5):
p.ChangeDutyCycle(dc) //修改占空比 参数范围为: (0.0 <= dc <= 100.0)
time.sleep(0.1)
for dc in range(100, -1, -5):
p.ChangeDutyCycle(dc)
time.sleep(0.1)
except KeyboardInterrupt:
pass
p.stop() //停止输出PWM波
GPIO.cleanup() //清除
结语
在文中,主要讲解了GPIO的概念,以及如何使用python操作GPIO。如果有条件,建议大家多动动手,你会收获不少满足感。我也是初学者,如果你有任何问题,大家一起探讨学习。
本文参考文档:https://sourceforge.net/p/raspberry-gpio-python/wiki/
本文转载自:
http://www.ruanyifeng.com/blog/2017/06/raspberry-pi-tutorial.html
http://blog.hyesheng.com/2016-09-01-raspberry02/