├── .editorconfig ├── .gitignore ├── 01prepare ├── README.md ├── taobao.jpg └── web_share_demo.gif ├── 02blink ├── README.md ├── code │ ├── javascript │ │ ├── README.md │ │ ├── led.js │ │ └── package.json │ └── python │ │ └── led.py └── images │ ├── bread-board.jpg │ ├── circuit_bb.png │ ├── circuit_s.png │ ├── object.jpg │ ├── rpi-pins-40-0.png │ └── rpi.jpg ├── 03fading-led ├── README.md ├── code │ ├── javascript │ │ ├── README.md │ │ ├── breathing-light.js │ │ └── package.json │ └── python │ │ └── breathing-light.py └── images │ ├── duty-cycle.png │ └── object.gif ├── 04digital-1 ├── README.md ├── code │ └── digital-1.py └── images │ ├── 1.png │ ├── 5161BS.png │ ├── circuit_bb.png │ ├── circuit_s.png │ └── object.gif ├── 05digital-2 ├── README.md ├── code │ └── digital-2.py └── images │ ├── 2.png │ ├── 3261BS.png │ └── object.jpg ├── 06buzzer ├── circuit_bb.png └── circuit_s.png ├── 07temperature ├── README.md ├── circuit_bb.png ├── circuit_s.png ├── temperature.py ├── test.py └── util.py ├── 08light-sensor ├── README.md ├── light-sensor.png └── light-sensor.py ├── 09echo-location ├── IMG_0268.jpg ├── README.md ├── circuit_bb.png ├── circuit_s.png └── echo_location.py ├── README.md ├── camera └── camera.py └── smoke-sensor ├── README.md ├── smoke-sensor.py └── test.py /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | 9 | [*.py] 10 | indent_style = space 11 | indent_size = 2 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.fzz 3 | *.pyc 4 | -------------------------------------------------------------------------------- /01prepare/README.md: -------------------------------------------------------------------------------- 1 | # 准备工作 2 | 开始动手前,需要准备一块树莓派主板和相关的电子元件,这些东西都可以在某宝买到。 3 | 4 | ## 网购 5 | ### 树莓派最小配置 6 | * 树莓派 Raspberry Pi 3主板 7 | * Micaro SD 卡带 Raspbian 操作系统 8 | * Android 手机数据线 9 | * HDMI 连接线(各种电视盒子带的 HDMI 线均可) 10 | * 带 HDMI 接口的显示器或电视机 11 | * 鼠标键盘 12 | 13 | ### 树莓派可选配置 14 | * 充电宝 15 | * 树莓派主板散热片 16 | * 树莓派亚克力外壳 17 | 18 | ### 电子元件 19 | * 面包板 20 | * 杜邦线(公对母) 21 | * LED 灯 22 | * 蜂鸣器(5V 有源) 23 | * DHT11温湿度传感器 24 | * 0.56英寸一位共阳数码管 25 | * 0.36英寸双位共阳数码管 26 | * 电阻包 27 | * 4线光敏电阻传感器 mk134 28 | * HC-SR04 超声波模块 29 | * 5MM红外发射管+红外接收管 30 | 31 | ### 订单截图 32 | ![订单截图](taobao.jpg) 33 | 34 | 共计花费 ¥314.20 元 35 | 36 | ## 组装 37 | * [插 SD 卡]将sd卡插入树莓派3主板的sd插槽中,注意sd卡有字的一面朝外,将sd卡插入后推到底会自动卡住,如果要取出sd卡,只要再往里一推就会弹出来。 38 | * [连接显示器]将显示器和树莓派3主板用 HDMI 线连接起来,如果你连的是电视机,请将电视机的信号源切换为 HDMI。 39 | * [连接鼠标键盘]将鼠标、键盘插在 USB 接口上。 40 | * [供电]准备给树莓派供电,树莓派电源接口和 Android 手机的电源接口一样,插上充电器或者充电宝。树莓派没有开机按钮,一通电就开机了。 41 | * [登录系统]如果显示器连接正常的话,这时候应该看到开机画面了,如果出现登录界面,用户名输入 `pi`,密码输入 `raspberry`。 42 | * [加入网络]进入系统后,点击屏幕右上角的 Wi-Fi 图标,加入无线网。至此,配置完成,树莓派已经是你家局域网中的一台微型计算机了。如果你习惯远程登录,你直接使用ip(假设ip为192.168.1.6)就可以ssh登录到树莓派上了。 43 | ``` 44 | ssh pi@192.168.1.6 45 | ``` 46 | 47 | ## 相关课程目录 48 | 1. [准备工作](../01prepare) 49 | 1. [点亮LED](../02blink) 50 | 1. [呼吸灯](../03fading-led) 51 | 1. [用单位数码管显示数字倒计时](../04digital-1) 52 | 1. [用双位数码管显示CPU温度](../05digital-2) 53 | 1. 控制蜂鸣器发声 54 | 1. 用温湿度探头检测室内温度 55 | 1. 用光敏传感器检测光线强度 56 | 1. 超声波测距 57 | 1. 红外遥控器 58 | 1. 声控灯 59 | 1. 进步电机 60 | 1. 用液晶显示器显示文字 61 | 1. 继电器 62 | 1. 让摄像头工作 63 | -------------------------------------------------------------------------------- /01prepare/taobao.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/01prepare/taobao.jpg -------------------------------------------------------------------------------- /01prepare/web_share_demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/01prepare/web_share_demo.gif -------------------------------------------------------------------------------- /02blink/README.md: -------------------------------------------------------------------------------- 1 | # 点亮LED 2 | 3 | ## 概述 4 | 本教程目的是用程序将 LED 灯点亮,3秒钟后灯自动熄灭。在所有软件编程语言中,第一个程序都叫 `hello world`,而今天的点灯教程其实就是硬件编程的 hello world,例子非常简单。 5 | 6 | 通过本节课,我们能学习到: 7 | * 硬件编程初体验 8 | * 面包板的使用 9 | * LED 原理 10 | * 通过 `GPIO` 来控制硬件 11 | 12 | ## 所需硬件 13 | * 树莓派 x1 14 | * 面包板 x1 15 | * 杜邦线 x2 16 | * LED灯 x1 17 | 18 | ## 名称解释 19 | 下面对本实验中要涉及到的一些电子元件和专业名称做简单介绍: 20 | 21 | ### 面包板 22 | ![面包板](https://github.com/zhongzhi107/raspberry-pi-tutorials/edit/master/02blink/images/bread-board.jpg) 23 | 24 | 面包板是专为电子电路的无焊接实验设计制造的,板子上有很多小插孔,由于各种电子元器件可根据需要随意插入或拔出,免去了焊接,节省了电路的组装时间,而且元件可以重复使用,所以非常适合电子电路的组装、调试和训练。 25 | 26 | 由于最上一行和最下一行往往都是相通的,所以这两行往往用于连接电路的电源线和地线,而元器件之间的连接往往采用中的各列。中间部分每五列栅格为一组,这一组五个栅格是导通的,在最中间的位置有一条凹槽,用于隔断左右两部分。 27 | 28 | ### LED 灯 29 | LED 是英文 Light Emitting Diode(发光二极管)的缩写。它有2个脚,长脚是正极,短脚是负极。当有电流流过时,LED 就会亮起。 30 | 31 | ### GPIO 32 | GPIO(General Purpose I/O Ports)意思为通用输入/输出端口,通俗地说,就是一些引脚,可以通过它们输出高低电平或者通过它们读入引脚的状态-是高电平或是低电平。GPIO是个比较重要的概念,用户可以通过GPIO口和硬件进行数据交互(如UART),控制硬件工作(如LED、蜂鸣器等),读取硬件的工作状态信号(如中断信号)等。GPIO口的使用非常广泛,掌握了GPIO,差不多相当于掌握了操作硬件的能力。 33 | 34 | 现在,我们先看看树莓派上的GPIO是怎么样的,这是树莓派的正面图: 35 | ![树莓派](images/rpi.jpg) 36 | 37 | 上面有40根排针,这就是树莓派用于控制外部传感器的接口,称之为 `GPIO`。40根引脚如何进行编号呢?如果按照物理位置来编号,只要掌握一个规则就容易记住: 38 | 最靠近角上的那一根引脚为2号引脚。旁边的就是1号引脚,具体请看上图示意图。 39 | 40 | 那么这40根引脚具体的用途和定义是什么呢,请看下面的图: 41 | 42 | ![GPIO](images/rpi-pins-40-0.png) 43 | (这张图以后经常要用到,建议保存下来,方便以后使用) 44 | 45 | 这个图是一个比较全面的一个定义,主要是因为对于这40根引脚有不同的编号规则来定义 46 | 虽然不同的规则叫的名字不一样,但实际的用途是一致的 47 | 这里只学习一种编号规则,也就是物理位置编号,这样更容易进行物理连接。 48 | 49 | 比如:1号引脚,是输出1个3.3伏的电压,也就是如果用数字万用表去测量这根引脚的电压,会一直测出来是3.3伏。 50 | 51 | 比如:2号引脚,是输出1个5伏的电压,也就是如果用数字万用表去测量这根引脚的电压,会一直测出来是5伏。 52 | 53 | 比如:6号引脚,是一个`GND`,也就是接地,如果测量电压的话,就是0伏。 54 | 55 | 比如:11号引脚,是绿色图标,旁边写着`GPIO17`,其实这个接口就是普通的接口,可以输入也可以输出。如果设置为输出,则可以输出高电压或者低电压。输出高电压就是3.3伏,输出低电压就是0伏。可以通过程序来控制。GPIO17是另外一种编号方式而已,这里我们可以忽略。 56 | 57 | 假如需要一个恒定的电压输出到某个电路,则可以选择3.3v或者5v的相应接口。 58 | 59 | 假如需要一个变化的电压输出到某个电路,则可以选择绿色的GPIO接口,例如11号、12号、13号、15号等。 60 | 61 | ### python GPIO 62 | 该库更确切的名称为`raspberry-gpio-python`,树莓派官方资料中推荐且容易上手。python GPIO是一个小型的python库,可以帮助用户完成raspberry相关IO口操作。但是python GPIO库还没有支持SPI、I2C或者1-wire等总线接口。除了python GPIO之外,还有众多的python扩展库(例如webiopi),毫无疑问的说python非常适合树莓派,树莓派也非常适合python。 63 | 64 | ### rpio 65 | 这是一个 JavaScript 语言操作 GPIO 的库,方法名和参数和 python GPIO 非常接近,更多信息请浏览[官方网站](https://github.com/jperkin/node-rpio) 66 | 67 | ## 连线图 68 | 在开始连接硬件电路之前,首先要做的事是将树莓派电脑关机,并断开电源。因为如果树莓派主板带电的时候,进行插接电路可能会导致电子元器件的烧毁,所以一定要记住: 69 | > 连接电路的时候主板必须断电。 70 | 71 | ![连线图](images/circuit_bb.png) 72 | *图片使用 [Fritzing](http://www.fritzing.org/) 绘制,更多示例图片请到 [Fritzing官网](http://fritzing.org/projects/) 浏览。* 73 | 74 | ## 电路原理图 75 | ![连线图](images/circuit_s.png) 76 | 77 | ## 示例代码 78 | 连好线后,接下来的工作就是写代码。想用 python 来控制 GPIO,最便捷的办法就是使用一些 python 类库,比如树莓派系统本身集成的 `RPi.GPIO`。 79 | 80 | 本文详细介绍如何使用`RPi.GPIO`来控制 GPIO,当然,你可以用任何喜欢的语言来控制 GPIO。 81 | 82 | ### 导入RPi.GPIO模块 83 | 可以用下面的代码导入`RPi.GPIO`模块。 84 | 85 | ```python 86 | import RPi.GPIO as GPIO 87 | ``` 88 | 89 | 引入之后,就可以使用 GPIO 模块的函数了。如果你想检查模块是否引入成功,也可以这样写: 90 | 91 | ```python 92 | try: 93 | import RPi.GPIO as GPIO 94 | except RuntimeError: 95 | print("引入错误") 96 | ``` 97 | 98 | ### 针脚编号 99 | 在 RPi.GPIO 中,同时支持树莓派上的两种 GPIO 引脚编号。 100 | 101 | 第一种编号是`BOARD编号`,这和树莓派电路板上的物理引脚编号相对应。使用这种编号的好处是,你的硬件将是一直可以使用的,不用担心树莓派的版本问题。因此,在电路板升级后,你不需要重写连接器或代码。 102 | 103 | 第二种编号是`BCM规则`,是更底层的工作方式,它和Broadcom的片上系统中信道编号相对应。在使用一个引脚时,你需要查找信道号和物理引脚编号之间的对应规则。对于不同的树莓派版本,编写的脚本文件也可能是无法通用的。 104 | 105 | 你可以使用下列代码(强制的)指定一种编号规则: 106 | 107 | ```python 108 | GPIO.setmode(GPIO.BOARD) 109 | # or 110 | GPIO.setmode(GPIO.BCM) 111 | ``` 112 | 113 | 下面代码将返回被设置的编号规则 114 | 115 | ```python 116 | mode = GPIO.getmode() 117 | ``` 118 | 119 | ### 警告 120 | 如果`RPi.GRIO`检测到一个引脚已经被设置成了非默认值,那么你将看到一个警告信息。你可以通过下列代码禁用警告: 121 | 122 | ```python 123 | GPIO.setwarnings(False) 124 | ``` 125 | 126 | ### 引脚设置 127 | 在使用一个引脚前,你需要设置这些引脚作为输入还是输出。配置一个引脚的代码如下: 128 | 129 | ```python 130 | # 将引脚设置为输入模式 131 | GPIO.setup(channel, GPIO.IN) 132 | 133 | # 将引脚设置为输出模式 134 | GPIO.setup(channel, GPIO.OUT) 135 | 136 | # 为输出的引脚设置默认值 137 | GPIO.setup(channel, GPIO.OUT, initial=GPIO.HIGH) 138 | ``` 139 | 140 | ### 释放 141 | 一般来说,程序到达最后都需要释放资源,这个好习惯可以避免偶然损坏树莓派。释放脚本中使用的引脚: 142 | 143 | ```python 144 | GPIO.cleanup() 145 | ``` 146 | 147 | 注意,GPIO.cleanup()只会释放掉脚本中使用的GPIO引脚,并会清除设置的引脚编号规则。 148 | 149 | ### 输出 150 | 要想点亮一个 LED 灯或者驱动某个设备,都需要给它们电流和电压,这个步骤也很简单,设置引脚的输出状态就可以了,代码如下: 151 | 152 | ```python 153 | GPIO.output(channel, state) 154 | ``` 155 | 156 | 状态可以设置为0 / GPIO.LOW / False / 1 / GPIO.HIGH / True。如果编码规则为,GPIO.BOARD,那么channel就是对应引脚的数字。 157 | 158 | 如果想一次性设置多个引脚,可使用下面的代码: 159 | 160 | ```python 161 | chan_list = [11,12] 162 | GPIO.output(chan_list, GPIO.LOW) 163 | GPIO.output(chan_list, (GPIO.HIGH, GPIO.LOW)) 164 | ``` 165 | 166 | 你还可以使用Input()函数读取一个输出引脚的状态并将其作为输出值,例如: 167 | 168 | ```python 169 | GPIO.output(12, not GPIO.input(12)) 170 | ``` 171 | 172 | ### 读取 173 | 我们也常常需要读取引脚的输入状态,获取引脚输入状态如下代码: 174 | 175 | ```python 176 | GPIO.input(channel) 177 | ``` 178 | 179 | 低电平返回`0 / GPIO.LOW / False`,高电平返回`1 / GPIO.HIGH / True`。 180 | 181 | 如果输入引脚处于悬空状态,引脚的值将是漂动的。换句话说,读取到的值是未知的,因为它并没有被连接到任何的信号上,直到按下一个按钮或开关。由于干扰的影响,输入的值可能会反复的变化。 182 | 使用如下代码可以解决问题: 183 | 184 | ```python 185 | GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_UP) 186 | # or 187 | GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 188 | ``` 189 | 190 | 需要注意的是,上面的读取代码只是获取当前一瞬间的引脚输入信号。 191 | 192 | 如果需要实时监控引脚的状态变化,可以有两种办法。最简单原始的方式是每隔一段时间检查输入的信号值,这种方式被称为轮询。如果你的程序读取的时机错误,则很可能会丢失输入信号。轮询是在循环中执行的,这种方式比较占用处理器资源。另一种响应GPIO输入的方式是使用中断(边缘检测),这里的边缘是指信号从高到低的变换(下降沿)或从低到高的变换(上升沿)。 193 | 194 | ### 轮询方式 195 | ```python 196 | while GPIO.input(channel) == GPIO.LOW: 197 | time.sleep(0.01) # wait 10 ms to give CPU chance to do other things 198 | ``` 199 | 200 | ### 边缘检测 201 | 202 | 边缘是指信号状态的改变,从低到高(上升沿)或从高到低(下降沿)。通常情况下,我们更关心于输入状态的该边而不是输入信号的值。这种状态的该边被称为事件。 203 | 先介绍两个函数: 204 | 205 | * wait_for_edge() 函数 206 | wait_for_edge()被用于阻止程序的继续执行,直到检测到一个边沿。也就是说,上文中等待按钮按下的实例可以改写为: 207 | 208 | ```python 209 | channel = GPIO.wait_for_edge(channel, GPIO_RISING, timeout=5000) 210 | if channel is None: 211 | print('Timeout occurred') 212 | else: 213 | print('Edge detected on channel', channel) 214 | ``` 215 | 216 | * add_event_detect() 函数 217 | 该函数对一个引脚进行监听,一旦引脚输入状态发生了改变,调用event_detected()函数会返回true,如下代码: 218 | 219 | ```python 220 | GPIO.add_event_detect(channel, GPIO.RISING) # add rising edge detection on a channel 221 | do_something() 222 | # 下面的代码放在一个线程循环执行。 223 | if GPIO.event_detected(channel): 224 | print('Button pressed') 225 | ``` 226 | 227 | 上面的代码需要自己新建一个线程去循环检测event_detected()的值,还算是比较麻烦的。 228 | 229 | 不过可采用另一种办法轻松检测状态,这种方式是直接传入一个回调函数: 230 | 231 | ```python 232 | def my_callback(channel): 233 | print('This is a edge event callback function!') 234 | print('Edge detected on channel %s'%channel) 235 | print('This is run in a different thread to your main program') 236 | 237 | GPIO.add_event_detect(channel, GPIO.RISING, callback=my_callback) 238 | ``` 239 | 240 | 如果你想设置多个回调函数,可以这样: 241 | 242 | ```python 243 | def my_callback_one(channel): 244 | print('Callback one') 245 | 246 | def my_callback_two(channel): 247 | print('Callback two') 248 | 249 | GPIO.add_event_detect(channel, GPIO.RISING) 250 | GPIO.add_event_callback(channel, my_callback_one) 251 | GPIO.add_event_callback(channel, my_callback_two) 252 | ``` 253 | 254 | 注意:回调触发时,并不会同时执行回调函数,而是根据设置的顺序调用它们。 255 | 256 | 好了,上面说明了一大堆函数库的用法,那么现在就应该来个简单的实验了 257 | 258 | ```python 259 | #!/usr/bin/env python 260 | # encoding: utf-8 261 | 262 | # 导入模块RPI.GPIO,命名为别名为GPIO 263 | import RPi.GPIO as GPIO 264 | # 导入time模块 265 | import time 266 | 267 | # 声明 GPIO 使用物理编号方式,也就是11号口就是物理编号11号口 268 | GPIO.setmode(GPIO.BOARD) 269 | 270 | # 声明11号口是用于输出模式 271 | GPIO.setup(11, GPIO.OUT) 272 | 273 | # 设置11号口为高电压,也就是11号口变为3.3伏 274 | # 这行代码执行之后,11号口变为高电压, 275 | # 那么根据电路原理,led灯就会亮起来 276 | GPIO.output(11, GPIO.HIGH) 277 | 278 | # 程序休眠3秒钟,程序休眠期间,led灯会一直亮着 279 | time.sleep(3) 280 | 281 | # 设置11号口为低电压,也就是11号口变为0伏,和GND一样 282 | # 这行代码执行之后,11号口变为低电压,那么根据电路原理,led灯就会熄灭 283 | GPIO.output(11, GPIO.LOW) 284 | 285 | # 将所有的GPIO口状态恢复为初始化,一般代码结束都执行此代码,这是一个好习惯 286 | GPIO.cleanup() 287 | ``` 288 | 289 | 保存文件为`led.py`,并运行之,看看 LED 灯是否亮3秒后熄灭。 290 | ``` 291 | sudo python led.py 292 | ``` 293 | 294 | ## 最终效果 295 | ![最终效果](images/object.jpg) 296 | 297 | ## 相关课程目录 298 | 1. [准备工作](../01prepare) 299 | 1. [点亮LED](../02blink) 300 | 1. [呼吸灯](../03fading-led) 301 | 1. [用单位数码管显示数字倒计时](../04digital-1) 302 | 1. [用双位数码管显示CPU温度](../05digital-2) 303 | 1. 控制蜂鸣器发声 304 | 1. 用温湿度探头检测室内温度 305 | 1. 用光敏传感器检测光线强度 306 | 1. 超声波测距 307 | 1. 红外遥控器 308 | 1. 声控灯 309 | 1. 进步电机 310 | 1. 用液晶显示器显示文字 311 | 1. 继电器 312 | 1. 让摄像头工作 313 | -------------------------------------------------------------------------------- /02blink/code/javascript/README.md: -------------------------------------------------------------------------------- 1 | # LED 2 | 3 | ## 安装 4 | 5 | ``` 6 | npm i 7 | ``` 8 | 9 | ## 运行 10 | 11 | ``` 12 | npm start 13 | ``` 14 | -------------------------------------------------------------------------------- /02blink/code/javascript/led.js: -------------------------------------------------------------------------------- 1 | // 导入 rpio 包 2 | var GPIO = require('rpio'); 3 | 4 | // 声明11号口是用于输出模式 5 | GPIO.open(11, GPIO.OUTPUT, GPIO.LOW); 6 | 7 | // 设置11号口为高电压,也就是11号口变为3.3伏 8 | // 这行代码执行之后,11号口变为高电压, 9 | // 那么根据电路原理,led灯就会亮起来 10 | GPIO.write(11, GPIO.HIGH); 11 | 12 | // 程序休眠3秒钟,程序休眠期间,led灯会一直亮着 13 | GPIO.sleep(3); 14 | 15 | // 设置11号口为低电压,也就是11号口变为0伏,和GND一样 16 | // 这行代码执行之后,11号口变为低电压,那么根据电路原理,led灯就会熄灭 17 | GPIO.write(11, GPIO.LOW); 18 | -------------------------------------------------------------------------------- /02blink/code/javascript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "led", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "led.js", 6 | "dependencies": { 7 | "rpio": "^0.9.23" 8 | }, 9 | "devDependencies": {}, 10 | "scripts": { 11 | "start": "node led.js" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC" 16 | } 17 | -------------------------------------------------------------------------------- /02blink/code/python/led.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | # 导入模块RPI.GPIO,命名为别名为GPIO 5 | import RPi.GPIO as GPIO 6 | # 导入time模块 7 | import time 8 | 9 | # 声明 GPIO 使用物理编号方式,也就是11号口就是物理编号11号口 10 | GPIO.setmode(GPIO.BOARD) 11 | 12 | # 声明11号口是用于输出模式 13 | GPIO.setup(11, GPIO.OUT) 14 | 15 | # 设置11号口为高电压,也就是11号口变为3.3伏 16 | # 这行代码执行之后,11号口变为高电压, 17 | # 那么根据电路原理,led灯就会亮起来 18 | GPIO.output(11, GPIO.HIGH) 19 | 20 | # 程序休眠3秒钟,程序休眠期间,led灯会一直亮着 21 | time.sleep(3) 22 | 23 | # 设置11号口为低电压,也就是11号口变为0伏,和GND一样 24 | # 这行代码执行之后,11号口变为低电压,那么根据电路原理,led灯就会熄灭 25 | GPIO.output(11, GPIO.LOW) 26 | 27 | # 将所有的GPIO口状态恢复为初始化,一般代码结束都执行此代码,这是一个好习惯 28 | GPIO.cleanup() 29 | -------------------------------------------------------------------------------- /02blink/images/bread-board.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/02blink/images/bread-board.jpg -------------------------------------------------------------------------------- /02blink/images/circuit_bb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/02blink/images/circuit_bb.png -------------------------------------------------------------------------------- /02blink/images/circuit_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/02blink/images/circuit_s.png -------------------------------------------------------------------------------- /02blink/images/object.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/02blink/images/object.jpg -------------------------------------------------------------------------------- /02blink/images/rpi-pins-40-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/02blink/images/rpi-pins-40-0.png -------------------------------------------------------------------------------- /02blink/images/rpi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/02blink/images/rpi.jpg -------------------------------------------------------------------------------- /03fading-led/README.md: -------------------------------------------------------------------------------- 1 | # 呼吸灯 2 | 3 | ## 概述 4 | [上一篇](../02blink) 我们通过控制`GPIO`口输出高低电平来控制一只 LED 的亮灭。这次我们来控制 LED 的亮度,灯由暗渐渐变亮,再由亮渐渐边暗,反复循环,也就是呼吸灯的效果。按 `ctrl` + `c` 中断程序。 5 | 6 | 通过本节课,你能学习到: 7 | * 脉冲宽度调制技术 8 | 9 | ## 所需硬件 10 | * 树莓派 x1 11 | * 面包板 x1 12 | * 杜邦线 x2 13 | * LED灯 x1 14 | 15 | ## 名称解释 16 | 我们知道,通过LED的电流越大,LED越亮,电流越小,LED越暗。如果可以控制输出电流大小就可以控制LED的明暗了。但是树莓派的各引脚并没有直接调整输出电流大小的功能,要想别的办法。这里,我们需要了解以下2个名词: 17 | 18 | ### 脉宽调制(PWM) 19 | 脉冲宽度调制(PWM)是一种利用数字手段获得模拟结果的技术。数字控制用于创建方波,电平在高和低之间切换。简单的说,`PWM`技术就是不停的通断电路并控制通断持续的时间片段长度,从而控制用电器在单位时间内实际得到的电能。再简单点说,如果你的手足够快,打开电灯开关后马上关闭,如果这个时间间隔足够短,灯丝还没有全部亮起来就暗下去了。你再次打开电灯再关闭,再打开再关闭……如果你一直保持相同的频率,那么电灯应该会保持一个固定的亮度不变。理论上,你可以通过调整开灯持续的时间长度和关灯持续的时间长度的比例就能得到不同亮度了。 20 | 21 | “导通时间”的持续时间称为脉冲宽度。要获得不同的模拟值,可以更改该脉冲的宽度。 22 | 23 | ### 占空比 24 | 一个脉冲循环内通电时间所占的比例。 25 | 26 | ![占空比](images/duty-cycle.png) 27 | 28 | ## 连线图 29 | 在开始连接硬件电路之前,首先要做的事是将树莓派电脑关机,并断开电源。因为如果树莓派主板带电的时候,进行插接电路可能会导致电子元器件的烧毁,所以一定要记住: 30 | > 连接电路的时候主板必须断电。 31 | 32 | 本次的接线图和[上一篇](../02blink)的连线图完全一样 33 | 34 | ![连线图](../02blink/images/circuit_bb.png) 35 | *图片使用 [Fritzing](http://www.fritzing.org/) 绘制,更多示例图片请到 [Fritzing官网](http://fritzing.org/projects/) 浏览。* 36 | 37 | ## 电路原理图 38 | ![连线图](../02blink/images/circuit_s.png) 39 | 40 | ## 示例代码 41 | ```python 42 | #!/usr/bin/env python 43 | # encoding: utf-8 44 | 45 | import RPi.GPIO as GPIO 46 | import time 47 | 48 | # 定义引脚编号 49 | channel = 12 50 | 51 | GPIO.setmode(GPIO.BOARD) 52 | GPIO.setup(channel, GPIO.OUT) 53 | 54 | # 创建一个 PWM 实例,需要两个参数,第一个是GPIO端口号,这里我们用11号 55 | # 第二个是频率(Hz),频率越高LED看上去越不会闪烁,相应对CPU要求就越高,设置合适的值就可以 56 | pwm = GPIO.PWM(channel, 80) 57 | 58 | # 启用 PWM,参数是占空比,范围:0.0 <= 占空比 >= 100.0 59 | pwm.start(0) 60 | 61 | try: 62 | while True: 63 | # 电流从小到大,LED由暗到亮 64 | for i in xrange(0, 101, 2): 65 | pwm.ChangeDutyCycle(i) 66 | time.sleep(0.02) 67 | 68 | # 再让电流从大到小,LED由亮变暗 69 | for i in xrange(100, -1, -2): 70 | pwm.ChangeDutyCycle(i) 71 | time.sleep(0.02) 72 | 73 | # 最后一段是一个小技巧。这个程序如果不强制停止会不停地执行下去。 74 | # 而Ctrl+C强制终端程序的话,GPIO口又没有机会清理。 75 | # 加上一个try except 可以捕捉到Ctrl+C强制中断的动作, 76 | # 试图强制中断时,程序不会马上停止而是会先跳到这里来做一些你想做完的事情,比如清理GPIO口。 77 | except KeyboardInterrupt: 78 | pass 79 | 80 | # 停用 PWM 81 | pwm.stop() 82 | 83 | # 清理GPIO口 84 | GPIO.cleanup() 85 | ``` 86 | 87 | 保存文件为`breathing-light.py`,并运行之。 88 | ``` 89 | sudo python breathing-light.py 90 | ``` 91 | 92 | ## 最终效果 93 | ![最终效果](images/object.gif) 94 | 95 | ## 相关课程目录 96 | 1. [准备工作](../01prepare) 97 | 1. [点亮LED](../02blink) 98 | 1. [呼吸灯](../03fading-led) 99 | 1. [用单位数码管显示数字倒计时](../04digital-1) 100 | 1. [用双位数码管显示CPU温度](../05digital-2) 101 | 1. 控制蜂鸣器发声 102 | 1. 用温湿度探头检测室内温度 103 | 1. 用光敏传感器检测光线强度 104 | 1. 超声波测距 105 | 1. 红外遥控器 106 | 1. 声控灯 107 | 1. 进步电机 108 | 1. 用液晶显示器显示文字 109 | 1. 继电器 110 | 1. 让摄像头工作 111 | -------------------------------------------------------------------------------- /03fading-led/code/javascript/README.md: -------------------------------------------------------------------------------- 1 | # 03fading-led 2 | 3 | 该例子中用的引脚12。 4 | 5 | 注意,需要使用 `sudo` 用户执行脚本 6 | 7 | ## 安装 8 | 9 | ``` 10 | npm i 11 | ``` 12 | 13 | ## 运行 14 | 15 | ``` 16 | npm start 17 | ``` 18 | -------------------------------------------------------------------------------- /03fading-led/code/javascript/breathing-light.js: -------------------------------------------------------------------------------- 1 | var rpio = require('rpio'); 2 | 3 | /* 4 | * Pulse an LED attached to P12 / GPIO18 5 times. 5 | */ 6 | 7 | var pin = 12; /* P12/GPIO18 */ 8 | var range = 1024; /* LEDs can quickly hit max brightness, so only use */ 9 | var max = 128; /* the bottom 8th of a larger scale */ 10 | var clockdiv = 8; /* Clock divider (PWM refresh rate), 8 == 2.4MHz */ 11 | var interval = 5; /* setInterval timer, speed of pulses */ 12 | var times = 5; /* How many times to pulse before exiting */ 13 | 14 | /* 15 | * Enable PWM on the chosen pin and set the clock and range. 16 | */ 17 | rpio.open(pin, rpio.PWM); 18 | rpio.pwmSetClockDivider(clockdiv); 19 | rpio.pwmSetRange(pin, range); 20 | 21 | /* 22 | * Repeatedly pulse from low to high and back again until times runs out. 23 | */ 24 | var direction = 1; 25 | var data = 0; 26 | var pulse = setInterval(function() { 27 | rpio.pwmSetData(pin, data); 28 | if (data === 0) { 29 | direction = 1; 30 | if (times-- === 0) { 31 | clearInterval(pulse); 32 | rpio.open(pin, rpio.INPUT); 33 | return; 34 | } 35 | } else if (data === max) { 36 | direction = -1; 37 | } 38 | data += direction; 39 | }, interval); 40 | -------------------------------------------------------------------------------- /03fading-led/code/javascript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "03fading-led", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "led.js", 6 | "dependencies": { 7 | "rpio": "^0.9.23" 8 | }, 9 | "devDependencies": {}, 10 | "scripts": { 11 | "start": "sudo node breathing-light.js" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC" 16 | } 17 | -------------------------------------------------------------------------------- /03fading-led/code/python/breathing-light.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import RPi.GPIO as GPIO 5 | import time 6 | 7 | # 定义引脚编号 8 | channel = 11 9 | 10 | GPIO.setmode(GPIO.BOARD) 11 | GPIO.setup(channel, GPIO.OUT) 12 | 13 | # 创建一个 PWM 实例,需要两个参数,第一个是GPIO端口号,这里我们用11号 14 | # 第二个是频率(Hz),频率越高LED看上去越不会闪烁,相应对CPU要求就越高,设置合适的值就可以 15 | pwm = GPIO.PWM(channel, 80) 16 | 17 | # 启用 PWM,参数是占空比,范围:0.0 <= 占空比 >= 100.0 18 | pwm.start(0) 19 | 20 | try: 21 | while True: 22 | # 电流从小到大,LED由暗到亮 23 | for i in xrange(0, 101, 2): 24 | pwm.ChangeDutyCycle(i) 25 | time.sleep(0.02) 26 | 27 | # 再让电流从大到小,LED由亮变暗 28 | for i in xrange(100, -1, -2): 29 | pwm.ChangeDutyCycle(i) 30 | time.sleep(0.02) 31 | 32 | # 最后一段是一个小技巧。这个程序如果不强制停止会不停地执行下去。 33 | # 而Ctrl+C强制终端程序的话,GPIO口又没有机会清理。 34 | # 加上一个try except 可以捕捉到Ctrl+C强制中断的动作, 35 | # 试图强制中断时,程序不会马上停止而是会先跳到这里来做一些你想做完的事情,比如清理GPIO口。 36 | except KeyboardInterrupt: 37 | pass 38 | 39 | # 停用 PWM 40 | pwm.stop() 41 | 42 | # 清理GPIO口 43 | GPIO.cleanup() 44 | -------------------------------------------------------------------------------- /03fading-led/images/duty-cycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/03fading-led/images/duty-cycle.png -------------------------------------------------------------------------------- /03fading-led/images/object.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/03fading-led/images/object.gif -------------------------------------------------------------------------------- /04digital-1/README.md: -------------------------------------------------------------------------------- 1 | # 用1位数码管显示数字倒计时 2 | 3 | ## 概述 4 | 5 | ![1位数码管](images/1.png) 6 | 7 | [上一篇](../03fading-led) 我们学习了使用 PWM 来控制 LED 的亮度,这次我们学习使用1位数码管显示个位数字倒计时。 8 | 9 | 通过本节课,我们能学习到: 10 | * 1位数码管的显示原理 11 | 12 | ## 所需硬件 13 | * 树莓派 x1 14 | * 面包板 x1 15 | * 杜邦线 x9 16 | * 1位数码管 x1 17 | 18 | ## 名称解释 19 | 20 | ### 数码管 21 | 数码管也称 LED 数码管,不同行业人士对数码管的称呼不一样,其实都是同样的产品。 22 | 23 | 数码管按段数可分为七段数码管和八段数码管,八段数码管比七段数码管多一个发光二极管单元,也就是多一个小数点(DP)这个小数点可以更精确的表示数码管想要显示的内容;按能显示多少个(8)可分为1位、2位、3位、4位、5位、6位、7位等数码管。 24 | 25 | 按发光二极管单元连接方式可分为共阳极数码管和共阴极数码管。共阳数码管是指将所有发光二极管的阳极接到一起形成公共阳极(COM)的数码管,共阳数码管在应用时应将公共极COM接到+5V,当某一字段发光二极管的阴极为低电平时,相应字段就点亮,当某一字段的阴极为高电平时,相应字段就不亮。共阴数码管是指将所有发光二极管的阴极接到一起形成公共阴极(COM)的数码管,共阴数码管在应用时应将公共极COM接到地线GND上,当某一字段发光二极管的阳极为高电平时,相应字段就点亮,当某一字段的阳极为低电平时,相应字段就不亮。 26 | 27 | ### 1位共阳数码管电路图 28 | 我们今天使用的是 5161BS 型号的1位共阳数码管,先看看它的电路原理图: 29 | 30 | ![1位数码管电路图](images/5161BS.png) 31 | 32 | 左图是数码管的每个管子的定义,从最上面的 A 管依次到中间的 G 管,还有小数点的 DP 管。通过组合 A 管到 G 管的不同亮起来和熄灭,就可以显示出数字信息。比如,让ABCDG这5根管亮起来,就能显示数字3了。 33 | 34 | 左图还包含关于引脚的编号,从正面看过去,让小数点放在右下角,下面从左到右为1到5号引脚 35 | ,上面从右向左是6到10号引脚,这10个引脚的编号很重要,因为需要了解每个引脚的功能定义,才能决定如何通过引脚输入电压信号。 36 | 37 | 右图是电路原理图,上面一层是3号引脚或者8号引脚,这是公共正极,中间一层是 A 管到 DP 管,也就是数码管的8个管子,下面一层是10个引脚剩余的8个引脚。当中的 A 管到 DP 管,大家可以当作每个管都是一个 LED 灯一样的,有正极和负极,正极输入高电压,负极输入 GND,就可以让数码管的单个管子亮起来。比如3号引脚输入高电压,7号引脚输入低电压 GND,A 管的2端产生电压差,就可以让 A 管亮起来;但是如果7号引脚如果也输入高电压,A 管的2端没有电压差,A 管就会熄灭。 38 | 39 | ## 连线图 40 | 在开始连接硬件电路之前,首先要做的事是将树莓派电脑关机,并断开电源。因为如果树莓派主板带电的时候,进行插接电路可能会导致电子元器件的烧毁,所以一定要记住: 41 | > 连接电路的时候主板必须断电。 42 | 43 | ![连线图](images/circuit_bb.png) 44 | *图片使用 [Fritzing](http://www.fritzing.org/) 绘制,更多示例图片请到 [Fritzing官网](http://fritzing.org/projects/) 浏览。* 45 | 46 | ## 电路原理图 47 | ![连线图](images/circuit_s.png) 48 | 49 | ## 示例代码 50 | ```python 51 | #!/usr/bin/env python 52 | # encoding: utf-8 53 | 54 | ''' 55 | 该程序实现 9 --> 0 倒计时效果 56 | 接线图: 57 | RPi digital 58 | 7 <---> 3 59 | 11 <---> 7 60 | 13 <---> 6 61 | 15 <---> 4 62 | 29 <---> 2 63 | 31 <---> 1 64 | 33 <---> 9 65 | 35 <---> 10 66 | 37 <---> 5 67 | ''' 68 | 69 | import RPi.GPIO as GPIO 70 | import time 71 | 72 | # 正极使用的针脚 73 | LED_POWER = 7 74 | # A-G管分别使用的针脚 75 | LED_A = 11 76 | LED_B = 13 77 | LED_C = 15 78 | LED_D = 29 79 | LED_E = 31 80 | LED_F = 33 81 | LED_G = 35 82 | LED_DP = 37 83 | 84 | # 重置数码管,熄灭所有数字 85 | def reset(): 86 | GPIO.output(LED_POWER, GPIO.LOW) 87 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G, LED_DP), GPIO.HIGH) 88 | 89 | # 显示数字0 90 | def show0(): 91 | reset() 92 | GPIO.output(LED_POWER, GPIO.HIGH) 93 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F), GPIO.LOW) 94 | 95 | # 显示数字1 96 | def show1(): 97 | reset() 98 | GPIO.output(LED_POWER, GPIO.HIGH) 99 | GPIO.output((LED_B, LED_C), GPIO.LOW) 100 | 101 | # 显示数字2 102 | def show2(): 103 | reset() 104 | GPIO.output(LED_POWER, GPIO.HIGH) 105 | GPIO.output((LED_A, LED_B, LED_D, LED_E, LED_G), GPIO.LOW) 106 | 107 | # 显示数字3 108 | def show3(): 109 | reset() 110 | GPIO.output(LED_POWER, GPIO.HIGH) 111 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_G), GPIO.LOW) 112 | 113 | # 显示数字4 114 | def show4(): 115 | reset() 116 | GPIO.output(LED_POWER, GPIO.HIGH) 117 | GPIO.output((LED_B, LED_C, LED_F, LED_G), GPIO.LOW) 118 | 119 | # 显示数字5 120 | def show5(): 121 | reset() 122 | GPIO.output(LED_POWER, GPIO.HIGH) 123 | GPIO.output((LED_A, LED_C, LED_D, LED_F, LED_G), GPIO.LOW) 124 | 125 | # 显示数字6 126 | def show6(): 127 | reset() 128 | GPIO.output(LED_POWER, GPIO.HIGH) 129 | GPIO.output((LED_A, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.LOW) 130 | 131 | # 显示数字7 132 | def show7(): 133 | reset() 134 | GPIO.output(LED_POWER, GPIO.HIGH) 135 | GPIO.output((LED_A, LED_B, LED_C), GPIO.LOW) 136 | 137 | # 显示数字8 138 | def show8(): 139 | reset() 140 | GPIO.output(LED_POWER, GPIO.HIGH) 141 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.LOW) 142 | 143 | # 显示数字9 144 | def show9(): 145 | reset() 146 | GPIO.output(LED_POWER, GPIO.HIGH) 147 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_F, LED_G), GPIO.LOW) 148 | 149 | GPIO.setmode(GPIO.BOARD) 150 | 151 | # 初始化引脚输出模式 152 | GPIO.setup((LED_POWER, LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G, LED_DP), GPIO.OUT) 153 | 154 | # 倒计时程序 155 | function_directory = locals() 156 | for i in range(0, 10)[::-1]: 157 | function_directory['show%s'%(i)]() 158 | time.sleep(1) 159 | 160 | GPIO.cleanup() 161 | ``` 162 | 163 | 保存文件为`digital-1.py`,并运行之。 164 | ``` 165 | sudo python digital-1.py 166 | ``` 167 | 168 | ## 最终效果 169 | ![最终效果](images/object.gif) 170 | 171 | ## 相关课程目录 172 | 1. [准备工作](../01prepare) 173 | 1. [点亮LED](../02blink) 174 | 1. [呼吸灯](../03fading-led) 175 | 1. [用单位数码管显示数字倒计时](../04digital-1) 176 | 1. [用双位数码管显示CPU温度](../05digital-2) 177 | 1. 控制蜂鸣器发声 178 | 1. 用温湿度探头检测室内温度 179 | 1. 用光敏传感器检测光线强度 180 | 1. 超声波测距 181 | 1. 红外遥控器 182 | 1. 声控灯 183 | 1. 进步电机 184 | 1. 用液晶显示器显示文字 185 | 1. 继电器 186 | 1. 让摄像头工作 187 | -------------------------------------------------------------------------------- /04digital-1/code/digital-1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | ''' 5 | 该程序实现 9 --> 0 倒计时效果 6 | 接线图: 7 | RPi digital 8 | 7 <---> 3 9 | 11 <---> 7 10 | 13 <---> 6 11 | 15 <---> 4 12 | 29 <---> 2 13 | 31 <---> 1 14 | 33 <---> 9 15 | 35 <---> 10 16 | 37 <---> 5 17 | ''' 18 | 19 | import RPi.GPIO as GPIO 20 | import time 21 | 22 | # 正极使用的针脚 23 | LED_POWER = 7 24 | # A-G管分别使用的针脚 25 | LED_A = 11 26 | LED_B = 13 27 | LED_C = 15 28 | LED_D = 29 29 | LED_E = 31 30 | LED_F = 33 31 | LED_G = 35 32 | LED_DP = 37 33 | 34 | # 重置数码管,熄灭所有数字 35 | def reset(): 36 | GPIO.output(LED_POWER, GPIO.LOW) 37 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G, LED_DP), GPIO.HIGH) 38 | 39 | # 显示数字0 40 | def show0(): 41 | reset() 42 | GPIO.output(LED_POWER, GPIO.HIGH) 43 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F), GPIO.LOW) 44 | 45 | # 显示数字1 46 | def show1(): 47 | reset() 48 | GPIO.output(LED_POWER, GPIO.HIGH) 49 | GPIO.output((LED_B, LED_C), GPIO.LOW) 50 | 51 | # 显示数字2 52 | def show2(): 53 | reset() 54 | GPIO.output(LED_POWER, GPIO.HIGH) 55 | GPIO.output((LED_A, LED_B, LED_D, LED_E, LED_G), GPIO.LOW) 56 | 57 | # 显示数字3 58 | def show3(): 59 | reset() 60 | GPIO.output(LED_POWER, GPIO.HIGH) 61 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_G), GPIO.LOW) 62 | 63 | # 显示数字4 64 | def show4(): 65 | reset() 66 | GPIO.output(LED_POWER, GPIO.HIGH) 67 | GPIO.output((LED_B, LED_C, LED_F, LED_G), GPIO.LOW) 68 | 69 | # 显示数字5 70 | def show5(): 71 | reset() 72 | GPIO.output(LED_POWER, GPIO.HIGH) 73 | GPIO.output((LED_A, LED_C, LED_D, LED_F, LED_G), GPIO.LOW) 74 | 75 | # 显示数字6 76 | def show6(): 77 | reset() 78 | GPIO.output(LED_POWER, GPIO.HIGH) 79 | GPIO.output((LED_A, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.LOW) 80 | 81 | # 显示数字7 82 | def show7(): 83 | reset() 84 | GPIO.output(LED_POWER, GPIO.HIGH) 85 | GPIO.output((LED_A, LED_B, LED_C), GPIO.LOW) 86 | 87 | # 显示数字8 88 | def show8(): 89 | reset() 90 | GPIO.output(LED_POWER, GPIO.HIGH) 91 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.LOW) 92 | 93 | # 显示数字9 94 | def show9(): 95 | reset() 96 | GPIO.output(LED_POWER, GPIO.HIGH) 97 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_F, LED_G), GPIO.LOW) 98 | 99 | GPIO.setmode(GPIO.BOARD) 100 | 101 | # 初始化引脚输出模式 102 | GPIO.setup((LED_POWER, LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G, LED_DP), GPIO.OUT) 103 | 104 | # 倒计时程序 105 | function_directory = locals() 106 | for i in range(0, 10)[::-1]: 107 | function_directory['show%s'%(i)]() 108 | time.sleep(1) 109 | 110 | GPIO.cleanup() 111 | -------------------------------------------------------------------------------- /04digital-1/images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/04digital-1/images/1.png -------------------------------------------------------------------------------- /04digital-1/images/5161BS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/04digital-1/images/5161BS.png -------------------------------------------------------------------------------- /04digital-1/images/circuit_bb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/04digital-1/images/circuit_bb.png -------------------------------------------------------------------------------- /04digital-1/images/circuit_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/04digital-1/images/circuit_s.png -------------------------------------------------------------------------------- /04digital-1/images/object.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/04digital-1/images/object.gif -------------------------------------------------------------------------------- /05digital-2/README.md: -------------------------------------------------------------------------------- 1 | # 用2位数码管显示CPU温度 2 | 3 | ## 概述 4 | 5 | ![1位数码管](images/2.png) 6 | 7 | [上一篇](../04digital-1) 我们学习使用1位数码管显示个位数字倒计时,这次我们学习使用2位数码管显示CPU的温度。 8 | 9 | 通过本节课,我们能学习到: 10 | * 2位数码管的显示原理 11 | * 视觉暂留显示技巧 12 | 13 | ## 所需硬件 14 | * 树莓派 x1 15 | * 面包板 x1 16 | * 杜邦线 x9 17 | * 2位数码管 x1 18 | 19 | ## 原理说明 20 | 我们今天使用的是 3261BS 型号的2位共阳数码管,先看看它的电路原理图: 21 | 22 | ![1位数码管电路图](images/3261BS.png) 23 | 24 | 通过 [上一篇](../04digital-1) 的学习,我们能够看懂1位数码管的电路图了,而2位数码管可以简单的理解为2个1位数码管的组合。 25 | 26 | 我们看最下面的一张图,10号引脚和5号引脚,分别是数码管第一个数字和第二个数字的公共阳极。 27 | 28 | **目标一:让数码管1和数码管2的 A 管分别亮起来** 29 | 30 | 数码管|期望达到的效果|需要做的电路控制 31 | ---|---|--- 32 | 数码管1|A 管亮|10号引脚高电压,3号引脚低电压 33 | 数码管2|A 管亮|5 号引脚高电压,3号引脚低电压 34 | 35 | 这个和操作1位数码管是一样的,但再看看接下来的目标可能就比较麻烦了: 36 | 37 | **目标二:让数码管1的 A 管亮,同时让数码管2的 A 管不亮** 38 | 39 | 数码管|期望达到的效果|需要做的电路控制 40 | ---|---|--- 41 | 数码管1|A 管亮|10号引脚高电压,*3号引脚低电压* 42 | 数码管2|A 管不亮|5号引脚高电压,*3号引脚高电压* 43 | 44 | 问题出来了:因为3号引脚是共用的,所以这种电路控制无法实现。那怎么解决这个问题呢?为了解决这个问题,这里我们需要借助 `视觉暂留` 45 | 46 | ### 视觉暂留 47 | 这个原理最早源于电影制作。科学实验证明,人眼在某个视像消失后,仍可使该物像在视网膜上滞留0.1-0.4秒左右。电影胶片以每秒24格画面匀速转动,一系列静态画面就会因视觉暂留作用而造成一种连续的视觉印象,产生逼真的动感。家里常用的日光灯也是这个原理,日光灯并非一直亮着的,而是在以很快的频率进行亮灭亮灭,当闪烁的频率达到每秒25次以上的时候,人眼就认为是一直亮着的。 48 | 49 | 可以利用这个原理,只要在足够短的时间间隔里分别显示2个数码管的数字,在人的视觉上就会认为这2个数字是同时显示的。那我们在电路控制采用的办法就是对3号引脚进行分时分配:0.01秒用于数码管1的 A 管,接下来的0.01秒用于数码管2的 A 管,这样1秒钟之内可以刷新50次,确保数码管没有闪烁感。 50 | 51 | ## 连线图 52 | 在开始连接硬件电路之前,首先要做的事是将树莓派电脑关机,并断开电源。因为如果树莓派主板带电的时候,进行插接电路可能会导致电子元器件的烧毁,所以一定要记住: 53 | > 连接电路的时候主板必须断电。 54 | 55 | ![连线图](images/circuit_bb.png) 56 | *图片使用 [Fritzing](http://www.fritzing.org/) 绘制,更多示例图片请到 [Fritzing官网](http://fritzing.org/projects/) 浏览。* 57 | 58 | ## 电路原理图 59 | ![连线图](images/circuit_s.png) 60 | 61 | ## 示例代码 62 | ```python 63 | #!/usr/bin/env python 64 | # encoding: utf-8 65 | 66 | ''' 67 | 接线图: 68 | RPi digital 69 | 7 <---> 10 70 | 11 <---> 5 71 | 13 <---> 3 72 | 15 <---> 9 73 | 29 <---> 8 74 | 31 <---> 6 75 | 33 <---> 7 76 | 35 <---> 4 77 | 37 <---> 1 78 | 79 | ''' 80 | 81 | import RPi.GPIO as GPIO 82 | import time 83 | import os 84 | 85 | 86 | # 数码管1-2正极分别使用的针脚 87 | LED_POWER_1 = 7 88 | LED_POWER_2 = 11 89 | 90 | # A-G管分别使用的针脚 91 | LED_A = 13 92 | LED_B = 15 93 | LED_C = 29 94 | LED_D = 31 95 | LED_E = 33 96 | LED_F = 35 97 | LED_G = 37 98 | 99 | # 获取CPU温度 100 | def get_cpu_temperature(): 101 | return os.popen('vcgencmd measure_temp').read()[5:7] 102 | 103 | # 重置数码管,熄灭所有数字 104 | def reset(): 105 | GPIO.output((LED_POWER_1, LED_POWER_2), GPIO.LOW) 106 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.HIGH) 107 | 108 | # 设置第几个数码管亮起 109 | def set_position(position): 110 | if position == 1: 111 | GPIO.output(LED_POWER_1, GPIO.HIGH) 112 | else: 113 | GPIO.output(LED_POWER_2, GPIO.HIGH) 114 | 115 | # 显示数字0 116 | def show0(p): 117 | reset() 118 | set_position(p) 119 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F), GPIO.LOW) 120 | 121 | # 显示数字1 122 | def show1(p): 123 | reset() 124 | set_position(p) 125 | GPIO.output((LED_B, LED_C), GPIO.LOW) 126 | 127 | # 显示数字2 128 | def show2(p): 129 | reset() 130 | set_position(p) 131 | GPIO.output((LED_A, LED_B, LED_D, LED_E, LED_G), GPIO.LOW) 132 | 133 | # 显示数字3 134 | def show3(p): 135 | reset() 136 | set_position(p) 137 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_G), GPIO.LOW) 138 | 139 | # 显示数字4 140 | def show4(p): 141 | reset() 142 | set_position(p) 143 | GPIO.output((LED_B, LED_C, LED_F, LED_G), GPIO.LOW) 144 | 145 | # 显示数字5 146 | def show5(p): 147 | reset() 148 | set_position(p) 149 | GPIO.output((LED_A, LED_C, LED_D, LED_F, LED_G), GPIO.LOW) 150 | 151 | # 显示数字6 152 | def show6(p): 153 | reset() 154 | set_position(p) 155 | GPIO.output((LED_A, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.LOW) 156 | 157 | # 显示数字7 158 | def show7(p): 159 | reset() 160 | set_position(p) 161 | GPIO.output((LED_A, LED_B, LED_C), GPIO.LOW) 162 | 163 | # 显示数字8 164 | def show8(p): 165 | reset() 166 | set_position(p) 167 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.LOW) 168 | 169 | # 显示数字9 170 | def show9(p): 171 | reset() 172 | set_position(p) 173 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_F, LED_G), GPIO.LOW) 174 | 175 | GPIO.setmode(GPIO.BOARD) 176 | 177 | # 初始化引脚输出模式 178 | GPIO.setup((LED_POWER_1, LED_POWER_2, LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.OUT) 179 | 180 | function_directory = locals() 181 | 182 | try: 183 | while True: 184 | cpu_temperature = get_cpu_temperature() 185 | print 'CPU temperature = %s°C'%(cpu_temperature) 186 | 187 | loop = 0 188 | while loop < 200: 189 | loop += 1 190 | # 先显示高位 191 | position = 1 192 | for n in cpu_temperature: 193 | function_directory['show%s'%(n)](position) 194 | time.sleep(0.01) 195 | position += 1 196 | 197 | except KeyboardInterrupt: 198 | GPIO.cleanup() 199 | ``` 200 | 201 | 保存文件为`digital-2.py`,并运行之。 202 | ``` 203 | sudo python digital-2.py 204 | ``` 205 | 206 | ## 最终效果 207 | ![最终效果](images/object.jpg) 208 | 209 | ## 总结 210 | 我们使用视觉暂留的显示方式来驱动2位数码管显示数字,其它多位(如4位,8位)数码管的显示也和2位数码管的显示方式类似。 211 | 212 | ## 相关课程目录 213 | 1. [准备工作](../01prepare) 214 | 1. [点亮LED](../02blink) 215 | 1. [呼吸灯](../03fading-led) 216 | 1. [用单位数码管显示数字倒计时](../04digital-1) 217 | 1. [用双位数码管显示CPU温度](../05digital-2) 218 | 1. 控制蜂鸣器发声 219 | 1. 用温湿度探头检测室内温度 220 | 1. 用光敏传感器检测光线强度 221 | 1. 超声波测距 222 | 1. 红外遥控器 223 | 1. 声控灯 224 | 1. 进步电机 225 | 1. 用液晶显示器显示文字 226 | 1. 继电器 227 | 1. 让摄像头工作 228 | -------------------------------------------------------------------------------- /05digital-2/code/digital-2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | ''' 5 | 接线图: 6 | RPi digital 7 | 7 <---> 10 8 | 11 <---> 5 9 | 13 <---> 3 10 | 15 <---> 9 11 | 29 <---> 8 12 | 31 <---> 6 13 | 33 <---> 7 14 | 35 <---> 4 15 | 37 <---> 1 16 | 17 | ''' 18 | 19 | import RPi.GPIO as GPIO 20 | import time 21 | import os 22 | 23 | 24 | # 数码管1-2正极分别使用的针脚 25 | LED_POWER_1 = 7 26 | LED_POWER_2 = 11 27 | 28 | # A-G管分别使用的针脚 29 | LED_A = 13 30 | LED_B = 15 31 | LED_C = 29 32 | LED_D = 31 33 | LED_E = 33 34 | LED_F = 35 35 | LED_G = 37 36 | 37 | # 获取CPU温度 38 | def get_cpu_temperature(): 39 | return os.popen('vcgencmd measure_temp').read()[5:7] 40 | 41 | # 重置数码管,熄灭所有数字 42 | def reset(): 43 | GPIO.output((LED_POWER_1, LED_POWER_2), GPIO.LOW) 44 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.HIGH) 45 | 46 | # 设置第几个数码管亮起 47 | def set_position(position): 48 | if position == 1: 49 | GPIO.output(LED_POWER_1, GPIO.HIGH) 50 | else: 51 | GPIO.output(LED_POWER_2, GPIO.HIGH) 52 | 53 | # 显示数字0 54 | def show0(p): 55 | reset() 56 | set_position(p) 57 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F), GPIO.LOW) 58 | 59 | # 显示数字1 60 | def show1(p): 61 | reset() 62 | set_position(p) 63 | GPIO.output((LED_B, LED_C), GPIO.LOW) 64 | 65 | # 显示数字2 66 | def show2(p): 67 | reset() 68 | set_position(p) 69 | GPIO.output((LED_A, LED_B, LED_D, LED_E, LED_G), GPIO.LOW) 70 | 71 | # 显示数字3 72 | def show3(p): 73 | reset() 74 | set_position(p) 75 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_G), GPIO.LOW) 76 | 77 | # 显示数字4 78 | def show4(p): 79 | reset() 80 | set_position(p) 81 | GPIO.output((LED_B, LED_C, LED_F, LED_G), GPIO.LOW) 82 | 83 | # 显示数字5 84 | def show5(p): 85 | reset() 86 | set_position(p) 87 | GPIO.output((LED_A, LED_C, LED_D, LED_F, LED_G), GPIO.LOW) 88 | 89 | # 显示数字6 90 | def show6(p): 91 | reset() 92 | set_position(p) 93 | GPIO.output((LED_A, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.LOW) 94 | 95 | # 显示数字7 96 | def show7(p): 97 | reset() 98 | set_position(p) 99 | GPIO.output((LED_A, LED_B, LED_C), GPIO.LOW) 100 | 101 | # 显示数字8 102 | def show8(p): 103 | reset() 104 | set_position(p) 105 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.LOW) 106 | 107 | # 显示数字9 108 | def show9(p): 109 | reset() 110 | set_position(p) 111 | GPIO.output((LED_A, LED_B, LED_C, LED_D, LED_F, LED_G), GPIO.LOW) 112 | 113 | GPIO.setmode(GPIO.BOARD) 114 | 115 | # 初始化引脚输出模式 116 | GPIO.setup((LED_POWER_1, LED_POWER_2, LED_A, LED_B, LED_C, LED_D, LED_E, LED_F, LED_G), GPIO.OUT) 117 | 118 | function_directory = locals() 119 | 120 | try: 121 | while True: 122 | cpu_temperature = get_cpu_temperature() 123 | print 'CPU temperature = %s°C'%(cpu_temperature) 124 | 125 | loop = 0 126 | while loop < 200: 127 | loop += 1 128 | # 先显示高位 129 | position = 1 130 | for n in cpu_temperature: 131 | function_directory['show%s'%(n)](position) 132 | time.sleep(0.01) 133 | position += 1 134 | 135 | except KeyboardInterrupt: 136 | GPIO.cleanup() 137 | -------------------------------------------------------------------------------- /05digital-2/images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/05digital-2/images/2.png -------------------------------------------------------------------------------- /05digital-2/images/3261BS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/05digital-2/images/3261BS.png -------------------------------------------------------------------------------- /05digital-2/images/object.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/05digital-2/images/object.jpg -------------------------------------------------------------------------------- /06buzzer/circuit_bb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/06buzzer/circuit_bb.png -------------------------------------------------------------------------------- /06buzzer/circuit_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/06buzzer/circuit_s.png -------------------------------------------------------------------------------- /07temperature/README.md: -------------------------------------------------------------------------------- 1 | # 第一个程序 —— 点亮LED 2 | 3 | ## 概述 4 | ## 名称解释 5 | ## 零件 6 | ## 连线图 7 | ## 完成效果图 8 | ## 示例代码 9 | ## 10 | -------------------------------------------------------------------------------- /07temperature/circuit_bb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/07temperature/circuit_bb.png -------------------------------------------------------------------------------- /07temperature/circuit_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/07temperature/circuit_s.png -------------------------------------------------------------------------------- /07temperature/temperature.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | ''' 5 | 该程序通过传感器获取温度、湿度数据 6 | 接线图: 7 | RPi DHT11 8 | 1 <---> VCC 9 | 12 <---> DATA 10 | -- <---> N/A 11 | 6 <---> GND 12 | ''' 13 | 14 | import RPi.GPIO as GPIO 15 | import time 16 | from util import bin2dec 17 | 18 | CHANNEL = 12 19 | MAX_TIMES = 10 20 | 21 | # 通过传感器获取温度、湿度数据 22 | def get_data(): 23 | # 建议连接线长度短于 20 米时用 5K 上拉电阻 , 大于 20 米时根据实际情况使用合适的上拉电阻 24 | GPIO.setmode(GPIO.BOARD) 25 | # 要等待 1s 以越过不稳定状态,在此期间无需发送任何指令 26 | time.sleep(1) 27 | 28 | # 用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据.从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集.采集数据后转换到低速模式。 29 | GPIO.setup(CHANNEL, GPIO.OUT) 30 | 31 | # 总线空闲状态为高电平,主机把总线拉低等待DHT11响应, 32 | # 主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。 33 | GPIO.output(CHANNEL, GPIO.LOW) 34 | time.sleep(0.02) 35 | # 给一个高电平,启动温度测量 36 | GPIO.output(CHANNEL, GPIO.HIGH) 37 | 38 | GPIO.setup(CHANNEL, GPIO.IN) 39 | while GPIO.input(CHANNEL) == GPIO.LOW: 40 | continue 41 | while GPIO.input(CHANNEL) == GPIO.HIGH: 42 | continue 43 | 44 | ''' 45 | 一次完整的数据传输为40bit,高位先出。  46 | 数据格式: 47 | 8bit湿度整数数据 + 48 | 8bit湿度小数数据 + 49 | 8bi温度整数数据 + 50 | 8bit温度小数数据 + 51 | 8bit校验和 52 | ''' 53 | j = 0 54 | data = [] 55 | for j in range(0, 40): 56 | k = 0 57 | while GPIO.input(CHANNEL) == GPIO.LOW: 58 | continue 59 | while GPIO.input(CHANNEL) == GPIO.HIGH: 60 | # 每接收到一个高电压,计数器 +1 61 | k += 1 62 | # 持续高电压,表示当前字节信号传输完毕 63 | # 跳出计数,进入下一次信号接收等待中 64 | if k > 100: 65 | break 66 | 67 | # 不清楚这个地方数据转换为什么是以 8 为分界 68 | if k < 8: 69 | data.append(0) 70 | else: 71 | data.append(1) 72 | 73 | GPIO.cleanup() 74 | print 'Bit data: %s'%(data) 75 | 76 | # 数据组装 77 | values = [] 78 | for i in range(0, 5): 79 | values.append(int(bin2dec(''.join(str(i) for i in data[i*8:(i+1)*8])))) 80 | 81 | # 数据有效性检查 82 | if values[4] == sum(values[0:3]): 83 | return { 84 | 'success': True, 85 | 'data': values 86 | } 87 | else: 88 | return { 89 | 'success': False 90 | } 91 | 92 | 93 | success = False 94 | tried_times = 0 95 | 96 | 97 | start_time = time.time() 98 | # 启动程序,并在获取数据失败时重试 99 | while not success and tried_times < MAX_TIMES: 100 | returnValues = get_data() 101 | success = returnValues['success'] 102 | tried_times += 1 103 | time.sleep(0.5) 104 | 105 | print 'Tried times: %d'%(tried_times) 106 | print 'Use time: %d(s)'%(time.time() - start_time) 107 | 108 | if success: 109 | v = returnValues['data'] 110 | print 'Temperature: %d°C, Humidity: %d%%'%(v[2], v[0]) 111 | else: 112 | print 'Fail' 113 | -------------------------------------------------------------------------------- /07temperature/test.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | from util import bin2dec 4 | 5 | a = [0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0] 6 | 7 | values = [] 8 | for i in range(0, 5): 9 | values.append(int(bin2dec(''.join(str(i) for i in a[i*8:(i+1)*8])))) 10 | 11 | print len(a) > 1000 and 0 or 1 12 | 13 | if values[4] == sum(values[0:3]): 14 | print 'OK\ntemperature: %d°C, humidity: %d%%'%(values[2], values[0]) 15 | else: 16 | print 'Fail' 17 | -------------------------------------------------------------------------------- /07temperature/util.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 2/10/16 base trans. wrote by srcdog on 20th, April, 2009 4 | # ld elements in base 2, 10, 16. 5 | 6 | import os,sys 7 | 8 | # global definition 9 | # base = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F] 10 | base = [str(x) for x in range(10)] + [ chr(x) for x in range(ord('A'),ord('A')+6)] 11 | 12 | # bin2dec 13 | # 二进制 to 十进制: int(str,n=10) 14 | def bin2dec(string_num): 15 | return int(string_num, 2) 16 | 17 | # hex2dec 18 | # 十六进制 to 十进制 19 | def hex2dec(string_num): 20 | return str(int(string_num.upper(), 16)) 21 | 22 | # dec2bin 23 | # 十进制 to 二进制: bin() 24 | def dec2bin(string_num): 25 | num = int(string_num) 26 | mid = [] 27 | while True: 28 | if num == 0: break 29 | num,rem = divmod(num, 2) 30 | mid.append(base[rem]) 31 | 32 | return ''.join([str(x) for x in mid[::-1]]) 33 | 34 | # dec2hex 35 | # 十进制 to 八进制: oct() 36 | # 十进制 to 十六进制: hex() 37 | def dec2hex(string_num): 38 | num = int(string_num) 39 | mid = [] 40 | while True: 41 | if num == 0: break 42 | num,rem = divmod(num, 16) 43 | mid.append(base[rem]) 44 | 45 | return ''.join([str(x) for x in mid[::-1]]) 46 | 47 | # hex2tobin 48 | # 十六进制 to 二进制: bin(int(str,16)) 49 | def hex2bin(string_num): 50 | return dec2bin(hex2dec(string_num.upper())) 51 | 52 | # bin2hex 53 | # 二进制 to 十六进制: hex(int(str,2)) 54 | def bin2hex(string_num): 55 | return dec2hex(bin2dec(string_num)) 56 | -------------------------------------------------------------------------------- /08light-sensor/README.md: -------------------------------------------------------------------------------- 1 | # 用光敏传感器检测光线强度 2 | 3 | ## 概述 4 | ## 名称解释 5 | ## 零件 6 | ## 连线图 7 | ## 完成效果图 8 | ## 示例代码 9 | ## 10 | -------------------------------------------------------------------------------- /08light-sensor/light-sensor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/08light-sensor/light-sensor.png -------------------------------------------------------------------------------- /08light-sensor/light-sensor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | # http://www.cnblogs.com/wpf_gd/articles/4700789.html 5 | 6 | import RPi.GPIO as GPIO 7 | from time import sleep 8 | 9 | CHANNEL = 7 10 | 11 | GPIO.setmode(GPIO.BOARD) 12 | 13 | GPIO.setup(CHANNEL, GPIO.OUT) 14 | GPIO.output(CHANNEL, GPIO.LOW) 15 | sleep(0.5) 16 | GPIO.setup(CHANNEL, GPIO.IN) 17 | 18 | try: 19 | while True: 20 | print GPIO.input(CHANNEL) 21 | if GPIO.input(CHANNEL) == GPIO.HIGH: 22 | print '暗' 23 | else: 24 | print '亮' 25 | sleep(1) 26 | 27 | except KeyboardInterrupt: 28 | pass 29 | -------------------------------------------------------------------------------- /09echo-location/IMG_0268.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/09echo-location/IMG_0268.jpg -------------------------------------------------------------------------------- /09echo-location/README.md: -------------------------------------------------------------------------------- 1 | # 超声波测距 2 | 3 | ## 概述 4 | ## 名称解释 5 | ## 零件 6 | ## 连线图 7 | ## 完成效果图 8 | ## 示例代码 9 | ## 10 | -------------------------------------------------------------------------------- /09echo-location/circuit_bb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/09echo-location/circuit_bb.png -------------------------------------------------------------------------------- /09echo-location/circuit_s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhongzhi107/raspberry-pi-tutorials/95679c9c085a7e3905e93c4927bce4a406eba98e/09echo-location/circuit_s.png -------------------------------------------------------------------------------- /09echo-location/echo_location.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | ''' 5 | 该程序每3秒测试一次距离,用ctrl+c停止。 6 | 原文:http://bbs.elecfans.com/forum.php?mod=viewthread&tid=451330 7 | 8 | 接线图: 9 | Vcc <---> 2 #5V 10 | Trig <---> 14 11 | Echo <---> 16 12 | Gnd <---> 6 13 | ''' 14 | 15 | import RPi.GPIO as GPIO 16 | import time 17 | 18 | TRIG_CHANNEL = 14 19 | ECHO_CHANNEL = 16 20 | 21 | def detect_distance(): 22 | # 发出触发信号 23 | GPIO.output(TRIG_CHANNEL, GPIO.HIGH) 24 | # 保持10us以上 25 | time.sleep(0.000015) 26 | GPIO.output(TRIG_CHANNEL, GPIO.LOW) 27 | 28 | while GPIO.input(ECHO_CHANNEL) == GPIO.LOW: 29 | pass 30 | # 发现高电压时,开始计时 31 | t1 = time.time() 32 | while GPIO.input(ECHO_CHANNEL) == GPIO.HIGH: 33 | pass 34 | # 高电压结束,停止计时 35 | t2 = time.time() 36 | # 返回距离,单位为米 37 | return (t2-t1)*340/2 38 | 39 | GPIO.setmode(GPIO.BOARD) 40 | 41 | GPIO.setup(TRIG_CHANNEL, GPIO.OUT, initial=GPIO.LOW) 42 | GPIO.setup(ECHO_CHANNEL, GPIO.IN) 43 | 44 | time.sleep(2) 45 | 46 | try: 47 | while True: 48 | print 'Distance: %0.2fm'%(detect_distance()) 49 | time.sleep(1) 50 | 51 | except KeyboardInterrupt: 52 | GPIO.cleanup() 53 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 软件工程师学习树莓派开发教程 2 | 3 | ## 介绍 4 | 5 | 面向软件工程师的树莓派入门教程,适合以下读者: 6 | 7 | * 对物联网感兴趣 8 | * 有一定的软件开发基础 9 | * 熟悉 `Unix/Linux` 操作系统 10 | * 了解 `python` 或 `JavaScript` 11 | * 无电子基础 12 | * 无硬件开发基础 13 | 14 | 所有教程编程部分均有 `python版` 和 `JavaScript版`,代码在 `code` 目录中。如果你安装的是 Raspbian 系统的话,系统默认就安装了 python 和 python GPIO;如果你希望使用 JavaScript 作为编程语言,你需要检查系统是否安装了 nodejs 15 | ``` 16 | node -v 17 | ``` 18 | 如果系统安装了nodejs,有输出版本信息。另外,还需要安装 `rpio` 19 | ``` 20 | npm install rpio --save 21 | ``` 22 | 23 | 如果你觉得该项目不错,**请点击右上方的 `⭐️ Star` 加星支持。** 24 | 25 | ## 目录 26 | 1. [准备工作](01prepare) 27 | 1. [点亮LED](02blink) 28 | 1. [呼吸灯](03fading-led) 29 | 1. [用单位数码管显示数字倒计时](04digital-1) 30 | 1. [用双位数码管显示CPU温度](05digital-2) 31 | 1. 控制蜂鸣器发声 32 | 1. 用温湿度探头检测室内温度 33 | 1. 用光敏传感器检测光线强度 34 | 1. 超声波测距 35 | 1. 红外遥控器 36 | 1. 声控灯 37 | 1. 进步电机 38 | 1. 用液晶显示器显示文字 39 | 1. 继电器 40 | 1. 让摄像头工作 41 | -------------------------------------------------------------------------------- /camera/camera.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | ''' 5 | http://www.pyimagesearch.com/2015/03/30/accessing-the-raspberry-pi-camera-with-opencv-and-python/ 6 | ''' 7 | -------------------------------------------------------------------------------- /smoke-sensor/README.md: -------------------------------------------------------------------------------- 1 | # 第一个程序 —— 点亮LED 2 | 3 | ## 概述 4 | ## 名称解释 5 | ## 零件 6 | ## 连线图 7 | ## 完成效果图 8 | ## 示例代码 9 | ## 10 | -------------------------------------------------------------------------------- /smoke-sensor/smoke-sensor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | ''' 5 | 该程序每 1 秒测试一次空气污染,用ctrl+c停止。 6 | http://blog.csdn.net/ling3ye/article/details/51472533 7 | 8 | 接线图: 9 | VCC <---> 1 #3.5V 10 | GND <---> 6 11 | DO <---> 7 12 | ''' 13 | 14 | import RPi.GPIO as GPIO 15 | import time 16 | 17 | CHANNEL = 7 18 | 19 | GPIO.setmode(GPIO.BOARD) 20 | GPIO.setup(CHANNEL, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 21 | 22 | def action(pin): 23 | print 'Sensor detected action!' 24 | 25 | GPIO.add_event_detect(CHANNEL, GPIO.RISING) 26 | GPIO.add_event_callback(CHANNEL, action) 27 | 28 | try: 29 | while True: 30 | print 'alive' 31 | time.sleep(0.5) 32 | except KeyboardInterrupt: 33 | GPIO.cleanup() 34 | -------------------------------------------------------------------------------- /smoke-sensor/test.py: -------------------------------------------------------------------------------- 1 | import RPi.GPIO as GPIO 2 | import time 3 | 4 | CHANNEL = 7 5 | 6 | def action(pin): 7 | print 'Sensor detected action!' 8 | 9 | GPIO.setmode(GPIO.BOARD) 10 | 11 | # 设置下拉电阻 12 | GPIO.setup(CHANNEL, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 13 | GPIO.add_event_detect(CHANNEL, GPIO.RISING) 14 | GPIO.add_event_callback(CHANNEL, action) 15 | 16 | GPIO.setup(CHANNEL, GPIO.OUT, initial=GPIO.HIGH) 17 | time.sleep(0.02) 18 | GPIO.output(CHANNEL, GPIO.LOW) 19 | 20 | GPIO.cleanup() 21 | --------------------------------------------------------------------------------