欢迎访问 pinpong python库教程文档!¶
pinpong库是一套控制开源硬件主控板的Python库,基于Firmata协议并兼容MicroPython语法,5分钟即可让你上手使用Python控制开源硬件。
借助于pinpong库,直接用Python代码就能给各种常见的开源硬件编程。其原理是给开源硬件烧录一个特定的固件,使开源硬件可以通过串口与电脑通讯,执行各种命令。
pinpong库的名称由“Pin”和“Pong”组成,“Pin”指引脚,“PinPong”为“乒乓球”的谐音,指信号的往复。
pinpong库的设计,是为了让开发者在开发过程中不用被繁杂的硬件型号束缚,而将重点转移到软件的实现。哪怕程序编写初期用Arduino开发,部署时改成了掌控板,只要修改一下硬件的参数就能正常运行,实现了“一次编写处处运行”。
注意
当前PinPong库正在快速更新中,已支持Arduino系列uno、leonardo、mega2560,ESP32系列掌控板(handpy),micro:bit(microbit),行空板(unihiker),传感器支持50+,其他主控板及更多扩展库将逐步支持。
本文档推荐阅读流程:
- 查看安装教程进行准备
- 查看示例快速上手测试
- 查看教程进行系统学习
点击观看pinpong入门视频互动教程:https://www.bilibili.com/video/BV17K4y1T7MF

简介¶
PinPong库是一套控制开源硬件主控板的Pyhton库,基于Firmata协议并兼容MicroPython语法,5分钟即可让你上手使用Python控制开源硬件。
借助于PinPong库,直接用Python代码就能给各种常见的开源硬件编程。其原理是给开源硬件烧录一个特定的固件,使开源硬件可以通过串口与电脑通讯,执行各种命令。
PinPong库的名称由“Pin”和“Pong”组成,“Pin”指引脚,“PinPong”为“乒乓球”的谐音,指信号的往复。
pinpong库的设计,是为了让开发者在开发过程中不用被繁杂的硬件型号束缚,而将重点转移到软件的实现。哪怕程序编写初期用Arduino开发,部署时改成了掌控板,只要修改一下硬件的参数就能正常运行,实现了“一次编写处处运行”。
注意
当前PinPong库正在快速更新中,已支持Arduino系列uno、leonardo、mega2560,ESP32系列掌控板(handpy),micro:bit(microbit),行空板(unihiker),传感器支持50+,其他主控板及更多扩展库将逐步支持。
本文档推荐阅读流程:
- 查看安装教程进行准备
- 查看示例快速上手测试
- 查看教程进行系统学习
安装教程¶
Windows平台安装¶
- 安装Python3。pinpong库依赖Python,因此请确保电脑安装了Python3,如果已经安装,此步可以略过。
- 如果没有安装Python3,则需要进行安装, Python下载地址: 点击打开

- Windows平台对应点击Windows,然后选择最新版本下载(也可选择其他版本)


- 下载完成后根据引导进行安装,注意安装最后一步勾选add to path,将python加入到环境变量。

- 打开命令提示窗。win+R快捷键,输入cmd

- 安装pinpong库。小黑窗中输入pip install pinpong ,等待片刻即可安装完成。
注意
如果网络较慢安装不成功,可以指定国内源进行安装: pip install pinpong -i http://mirrors.aliyun.com/pypi/simple/

- 帮助命令。在小黑窗中输入pinpong ,即可输出当前版本信息、官方文档网址、库列表查看、端口号。

开始第一个程序¶
- 连接arudino uno板至电脑;
- 打开IDLE编辑器,新建文件(New File);
- 从本文档“PINPONG示例”复制“blink”示例程序的代码到IDLE中,点击“运行(RUN) > Run Module”或按键盘上F5键即可运行代码;
- Python Shell窗口即会显示PinPong的logo和运行状况,Uno板载LED开始闪烁,运行成功,按键盘上的Ctrl+C组合键即可停止代码运行。
- 接下来请查看其他教程或运行其他示例程序进一步学习吧。


Linux 平台安装¶
终端中输入sudo pip install pinpong即可安装。
$ sudo pip install pinpong

帮助命令。在小黑窗中输入pinpong ,即可输出当前版本信息、官方文档网址、库列表查看、端口号。
开始第一个程序¶
- 连接arudino uno板至电脑;
- 从本文档“PINPONG示例”复制“blink”示例程序的代码到Python编辑器中,运行代码;
- 接下来请查看其他教程或运行其他示例程序进一步学习吧。

基础库示例¶
示例程序可帮助你快速验证模块的使用,复制粘贴代码到python编辑器中,并修改Board初始化版型为你使用的板子型号即可
- 常用库示例中的模块通过board库导入
1-01-blink:数字输出¶
# -*- coding: UTF-8 -*-
#实验效果:控制arduino UNO板载LED灯一秒闪烁一次
#接线:使用windows或linux电脑连接一块arduino主控板
import time
from pinpong.board import Board,Pin
Board("uno").begin() #初始化,选择板型(uno、microbit、RPi、handpy)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
led = Pin(Pin.D13, Pin.OUT) #引脚初始化为电平输出
while True:
#led.value(1) #输出高电平 方法1
led.write_digital(1) #输出高电平 方法2
print("1") #终端打印信息
time.sleep(1) #等待1秒 保持状态
#led.value(0) #输出低电平 方法1
led.write_digital(0) #输出低电平 方法2
print("0") #终端打印信息
time.sleep(1) #等待1秒 保持状态
1-02-button:数字输入¶
# -*- coding: UTF-8 -*-
#实验效果:使用按钮控制arduino UNO板载亮灭
#接线:使用windows或linux电脑连接一块arduino主控板,主控板D8接一个按钮模块
import time
from pinpong.board import Board,Pin
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
btn = Pin(Pin.D8, Pin.IN) #引脚初始化为电平输入
led = Pin(Pin.D13, Pin.OUT)
while True:
#v = btn.value() #读取引脚电平方法1
v = btn.read_digital() #读取引脚电平方法2
print(v) #终端打印读取的电平状态
#led.value(v) #将按钮状态设置给led灯引脚 输出电平方法1
led.write_digital(v) #将按钮状态设置给led灯引脚 输出电平方法2
time.sleep(0.1)
1-03-adc:模拟输入¶
# -*- coding: UTF-8 -*-
#实验效果:打印UNO板A0口模拟值
#接线:使用windows或linux电脑连接一块arduino主控板,主控板A0接一个旋钮模块
import time
from pinpong.board import Board,Pin
Board("uno").begin() #初始化,选择板型(unomicrobit、RPi、handpy)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
#adc0 = ADC(Pin(Pin.A0)) #将Pin传入ADC中实现模拟输入 模拟输入方法1
adc0 = Pin(Pin.A0, Pin.ANALOG) #引脚初始化为电平输出 模拟输入方法2
while True:
#v = adc0.read() #读取A0口模拟信号数值 模拟输入方法1
v = adc0.read_analog() #读取A0口模拟信号数值 模拟输入方法2
print("A0=", v)
time.sleep(0.5)
1-04-PWM:模拟输出¶
# -*- coding: UTF-8 -*-
#实验效果: PWM输出实验,控制LED灯亮度变化
#接线:使用windows或linux电脑连接一块arduino主板,LED灯接到D6引脚上
import time
from pinpong.board import Board,Pin
Board("uno").begin() #初始化,选择板型(uno、microbit、RPi、handpy)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
#pwm0 = PWM(Pin(board,Pin.D6)) #将引脚传入PWM初始化 模拟输出方法1
pwm0 = Pin(Pin.D6, Pin.PWM) #初始化引脚为PWM模式 模拟输出方法2
while True:
for i in range(255):
print(i)
#pwm0.duty(i) #PWM输出 方法1
pwm0.write_analog(i) #PWM输出 方法2
time.sleep(0.05)
1-05-irq:引脚中断¶
# -*- coding: UTF-8 -*-
#实验效果:引脚模拟中断功能测试
#接线:使用windows或linux电脑连接一块arduino主控板,主控板D8接一个按钮模块
import time
from pinpong.board import Board,Pin
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
btn = Pin(Pin.D8, Pin.IN)
def btn_rising_handler(pin):#中断事件回调函数
print("\n--rising---")
print("pin = ", pin)
def btn_falling_handler(pin):#中断事件回调函数
print("\n--falling---")
print("pin = ", pin)
def btn_both_handler(pin):#中断事件回调函数
print("\n--both---")
print("pin = ", pin)
btn.irq(trigger=Pin.IRQ_FALLING, handler=btn_falling_handler) #设置中断模式为下降沿触发
#btn.irq(trigger=Pin.IRQ_RISING, handler=btn_rising_handler) #设置中断模式为上升沿触发,及回调函数
#btn.irq(trigger=Pin.IRQ_RISING+Pin.IRQ_FALLING, handler=btn_both_handler) #设置中断模式为电平变化时触发
while True:
time.sleep(1) #保持程序持续运行
常用库示例¶
- 常用库示例中的模块通过board库导入
2-02-servo:舵机¶
# -*- coding: UTF-8 -*-
#实验效果:舵机控制
#接线:使用windows或linux电脑连接一块arduino主控板,D4连接一个舵机
import time
from pinpong.board import Board,Pin,Servo #导入Servo库
Board("uno").begin() #初始化,选择板型(uno、microbit、RPi、handpy)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
s1 = Servo(Pin(Pin.D4)) #将Pin传入Servo中初始化舵机引脚
while True:
#s1.angle(0) #控制舵机转到0度位置 方法1
s1.write_angle(0) #控制舵机转到0度位置 方法2
print("0")
time.sleep(1)
#s1.angle(90) #控制舵机转到90度位置
s1.write_angle(90) #控制舵机转到90度位置 方法2
print("90")
time.sleep(1)
#s1.angle(180) #控制舵机转到180度位置
s1.write_angle(180) #控制舵机转到180度位置 方法2
print("180")
time.sleep(1)
#s1.angle(90) #控制舵机转到90度位置
s1.write_angle(90) #控制舵机转到90度位置 方法2
print("90")
time.sleep(1)
2-01-tone:蜂鸣器¶
# -*- coding: UTF-8 -*-
#实验效果:控制蜂鸣器发声
#接线:使用windows或linux电脑连接一块arduino主控板,主控板D8接一个蜂鸣器模块
import time
from pinpong.board import Board,Pin,Tone #导入Tone类实现控制蜂鸣器
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
tone = Tone(Pin(Pin.D8)) #将Pin传入Tone中实现模拟输出
tone.freq(200) #按照设置的频率播放
'''
while True:
tone.tone(200,500) #按照设置的频率和时间播放直到完成
time.sleep(1)
'''
while True:
print("freq=",tone.freq()) #读取频率并打印
tone.on() #打开蜂鸣器
time.sleep(1)
tone.off() #关闭蜂鸣器
time.sleep(1)
tone.freq(tone.freq()+100) #按照设置的频率播放
2-03-sr04_urm10:超声波传感器¶
# -*- coding: UTF-8 -*-
#实验效果:读取超声波
#接线:使用windows或linux电脑连接一块arduino主控板,使用SR04或URM10超声波,Trig接D7,Echo接D8
import time
from pinpong.board import Board,Pin,SR04_URM10 #中导入SR04_URM10
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
TRIGER_PIN = Pin(Pin.D7)
ECHO_PIN = Pin(Pin.D8)
sonar = SR04_URM10(TRIGER_PIN,ECHO_PIN)
while True:
dis = sonar.distance_cm() #获取距离,单位厘米(cm)
print("distance = %d cm"%dis)
time.sleep(0.1)
2-04-dht:温湿度传感器¶
# -*- coding: UTF-8 -*-
#实验效果:读取dht温湿度传感器
#接线:使用windows或linux电脑连接一块arduino主控板,dht11连接D6,dht22连接D7
import time
from pinpong.board import Board,Pin,DHT11,DHT22 #导入dht库
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
dht11 = DHT11(Pin(Pin.D6))
dht22 = DHT22(Pin(Pin.D7))
while True:
temp = dht11.temp_c() #读取摄氏温度
humi = dht11.humidity() #读取湿度
print("dht11 temperature=",temp," humidity=",humi)
temp = dht22.temp_c() #读取摄氏温度
humi = dht22.humidity() #读取湿度
print("dht22 temperature=",temp," humidity=",humi)
time.sleep(1)
2-07-neopixel:WS2812灯带¶
# -*- coding: UTF-8 -*-
#实验效果:控制WS2812单线RGB LED灯
#接线:使用windows或linux电脑连接一块arduino主控板,ws2812灯接到D9口
import time
from pinpong.board import Board,Pin,NeoPixel #导入neopixel类
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
NEOPIXEL_PIN = Pin(Pin.D9)
PIXELS_NUM = 4 #灯数
np = NeoPixel(NEOPIXEL_PIN,PIXELS_NUM)
while True:
np[0] = (0, 255 ,0) #设置第一个灯RGB亮度
np[1] = (255, 0, 0) #设置第二个灯RGB亮度
np[2] = (0, 0, 255) #设置第三个灯RGB亮度
np[3] = (255, 0, 255) #设置第四个灯RGB亮度
print("color 1")
time.sleep(1)
np[1] = (0, 255, 0)
np[2] = (255, 0, 0)
np[3] = (255, 255, 0)
np[0] = (0, 0, 255)
print("color 2")
time.sleep(1)
扩展库示例¶
- 扩展库示例中的模块通过libs库导入,
- 可通过终端输入pinpong查询支持列表和使用方法
- 从安装目录下的examples文件夹中可以找到所有示例程序代码
2-05-lcd1602:1602显示屏¶
# -*- coding: UTF-8 -*-
#实验效果:I2C LCD1602控制
#接线:使用windows或linux电脑连接一块arduino主控板,LCD1602显示屏接到I2C口SCL及SDA
import time
from pinpong.board import Board
from pinpong.libs.lcd1602 import LCD1602_I2C #从libs中导入lcd1602_i2c库
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
lcd = LCD1602_I2C(i2c_addr=0x20) #初始化LCD的I2C地址
print("I2C LCD1602 TEST...")
lcd.backlight(True) #打开背光
lcd.clear() #清屏
lcd.set_cursor(0,0) #设置光标位置
lcd.print("Hello World") #显示 "Hello World",1602屏像素点少,不能显示汉字
lcd.set_cursor(1,1) #设置光标位置
lcd.print(1234) #显示数字1234
while True:
time.sleep(1)
lcd.scroll_left() #滚动显示
2-06-oled12864:oled显示屏¶
# -*- coding: UTF-8 -*-
#实验效果:I2C OLED2864屏控制
#接线:使用windows或linux电脑连接一块arduino主控板,OLED2864显示屏接到I2C口SCL及SDA
import time
from pinpong.board import Board
from pinpong.libs.dfrobot_ssd1306 import SSD1306_I2C #导入ssd1306库
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
oled=SSD1306_I2C(width=128, height=64) #初始化屏幕,传入屏幕像素点数
while True:
oled.fill(1) #全部填充显示
oled.show() #显示生效
print("1")
time.sleep(1)
oled.fill(0) #全部填充熄灭,清屏
oled.show() #显示生效
print("0")
time.sleep(1)
oled.text("0") #显示数字
oled.text("Hello PinPong",8,8) #指定位置显示文字
oled.show() #显示生效
time.sleep(2)
3-01-tcs34725:颜色识别¶
# -*- coding: UTF-8 -*-
#实验效果:读取I2C TCS34725颜色传感器数值
#接线:使用windows或linux电脑连接一块arduino主控板,TCS34725颜色传感器接到I2C口SCL SDA
import time
from pinpong.board import Board
from pinpong.libs.dfrobot_tcs34725 import TCS34725 #从libs导入tcs34725库
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
tcs = TCS34725() #传感器初始化
print("Color View Test!");
while True:
if tcs.begin(): #查找传感器,读取到则返回True
print("Found sensor")
break #找到 跳出循环
else:
print("No TCS34725 found ... check your connections")
time.sleep(1)
while True:
r,g,b,c = tcs.get_rgbc() #获取rgbc数据
print(r,g,b,c)
print("C=%d\tR=%d\tG=%d\tB=%d\t"%(c,r,g,b))
'''
#数据转换
r /= c
g /= c
b /= c
r *= 256
g *= 256
b *= 256;
print("------C=%d\tR=%d\tG=%d\tB=%d\t"%(c,r,g,b))
'''
time.sleep(1)
3-02-urm09:I2C超声波¶
# -*- coding: UTF-8 -*-
#实验效果:读取I2C 超声波传感器(URM09)数值
#接线:使用windows或linux电脑连接一块arduino主控板,URM09传感器接到I2C口SCL SDA
import time
from pinpong.board import Board
from pinpong.libs.dfrobot_urm09 import URM09 #从libs中导入URM09库
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
urm = URM09(i2c_addr=0x11) #初始化传感器,设置I2C地址
urm.set_mode_range(urm._MEASURE_MODE_AUTOMATIC ,urm._MEASURE_RANG_500) #设置URM09模式为自动检测,最大测量距离500cm
while True:
dist = urm.distance_cm() #读取距离数据,单位厘米(cm)
temp = urm.temp_c() #读取传感器温度,单位摄氏度(℃)
print("Distance is %d cm "%dist)
print("Temperature is %.2f .c "%temp)
time.sleep(0.5)
3-03-rgb1602:彩色1602屏¶
# -*- coding: UTF-8 -*-
#实验效果:控制I2C RGB彩色LCD1602液晶屏幕
#接线:使用windows或linux电脑连接一块arduino主控板,LCD1602接到I2C口SCL SDA
import time
from pinpong.board import Board
from pinpong.libs.rgb1602 import RGB1602 #从libs导入rgb1602库
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
lcd = RGB1602()
print("I2C RGB1602 TEST...")
lcd.set_rgb(0,50,0); #设置RGB值
lcd.set_cursor(0,0) #设置光标到原点
lcd.print("PinPong") #显示 "PinPong"
lcd.set_cursor(1,1) #设置光标位置
lcd.print(1234) #显示数字
while True:
time.sleep(1)
lcd.scroll_left() #滚动显示
3-04-mlx90614:红外测温¶
# -*- coding: UTF-8 -*-
#实验效果:读取I2C MLX90614远红外测温传感器
#接线:使用windows或linux电脑连接一块arduino主控板,红外测温传感器接到I2C口SCL SDA
import time
from pinpong.board import Board
from pinpong.libs.dfrobot_mlx90614 import MLX90614 #从libs导入mlx90614库
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
irt=MLX90614()
while True:
print("Object %s *C"% irt.obj_temp_c()) #读取物体温度 摄氏度(℃)
print("Object %s *F"% irt.obj_temp_f()) #读取物体温度 华氏度(℉)
print("Ambient %s *C"% irt.env_temp_c()) #读取环境温度 摄氏度(℃)
print("Ambient %s *F"% irt.env_temp_f()) #读取环境温度 华氏度(℉)
print() #空行
time.sleep(1)
3-05-PN532:NFC近场通讯模块¶
# -*- coding: utf-8 -*-
#实验效果:NFC近场通讯模块 IIC读取卡片信息
#接线:使用windows或linux电脑连接一块arduino主控板,NFC近场通讯模块接到I2C口SCL SDA
import time
from pinpong.board import Board
from pinpong.libs.dfrobot_pn532 import PN532
Board("uno").begin() #初始化,选择板型和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
nfc = PN532()
while not nfc.begin():
print("initial failure")
time.sleep(1)
print("Please place the info card/tag on module..... ")
while True:
if nfc.scan():
info = nfc.get_information()
if info != None:
print("----------------NFC card/tag information-------------------")
print("UID Lenght: %d"%info.lenght)
print("UID: %x %x %x %x"%(info.uid[0],info.uid[1],info.uid[2],info.uid[3] ))
print("AQTA: %x %x"%(info.AQTA[0], info.AQTA[0]))
print("SAK: 0x%x"%(info.sak))
print("Type: %s"%(info.types))
print("Manu facturer: %s"%(info.manu))
print("RF Technology: %s"%(info.RF))
print("Memory Size: %d bytes(total)/%d bytes(available)"%(info.size_total, info.size_available))
print("Block/Page Size: %d bytes"%(info.block))
print("Number of Blocks/pages: %d"%(info.num_block))
time.sleep(1)
# -*- coding: utf-8 -*-
#实验效果:NFC近场通讯模块 IIC读取卡片内信息
#接线:使用windows或linux电脑连接一块arduino主控板,NFC近场通讯模块接到I2C口SCL SDA
import time
from pinpong.board import Board
from pinpong.libs.dfrobot_pn532 import PN532
Board("uno").begin() #初始化,选择板型和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
nfc = PN532()
def print_data(block):
value = nfc.read_data(block)
if value != None:
for i in value:
print("0x%x "%(i), end="")
print("")
else:
print_data(block)
while not nfc.begin():
print("initial failure")
time.sleep(1)
print("Waiting for a card......")
while True:
if nfc.scan():
NFC = nfc.get_information()
if NFC != None:
if NFC.lenght == 0x02 or NFC.lenght == 0x04:
print("----------------Here is the card information to read-------------------")
for i in range(NFC.num_block):
if i == 0:
print("Block %d:UID0-UID3/MANUFACTURER--------->"%(i), end="")
print_data(i);
elif (i+1)%4==0 and i < 128:
print("Block %d:KEYA/ACCESS/KEYB--------------->"%(i), end="")
print_data(i)
elif (i+1)%16==0 and i > 127:
print("Block %d:KEYA/ACCESS/KEYB--------------->"%(i), end="")
print_data(i)
else:
print("Block %d:DATA ------------------------>"%(i), end="")
print_data(i)
else:
print("The card type is not mifareclassic...")
time.sleep(3)
# -*- coding: utf-8 -*-
#实验效果:NFC近场通讯模块 IIC读写卡片信息
#接线:使用windows或linux电脑连接一块arduino主控板,NFC近场通讯模块接到I2C口SCL SDA
import time
from pinpong.board import Board
from pinpong.libs.dfrobot_pn532 import PN532
Board("uno").begin() #初始化,选择板型和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
nfc = PN532()
write_data = "DFRobot NFC"
#write_data = [1, 2, 3, 4, 5, 6, 7, 8, 9]
#write_data = (10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
block_num = 2
while not nfc.begin():
print("initial failure")
time.sleep(1)
print("Waiting for a card......")
def parse_data(read_data):
if read_data != None:
print("read success! data is ", end=" ")
print(read_data)
else:
print("read failure!")
while True:
if nfc.scan():
info = nfc.get_information()
if info != None:
if info.lenght == 0x02 or info.lenght == 0x04:
if not nfc.write_data(block_num, write_data):
print("write failure!")
else:
print("write success! data is", end=" ")
print(write_data)
read_data= nfc.read_data(block_num)
parse_data(read_data)
else:
print("The card type is not mifareclassic...")
time.sleep(2)
行空板示例¶
- 行空板是一个运行Linux的开发板,板载GD32协处理器,因此可以使用pinpong库控制板载或外接硬件。
行空板官方文档中提供了大量pinpong库案例,因此基础教程请打开行空板官方教程查看:https://wiki.unihiker.com/pinpong_python_lib

掌控板示例¶
- 以下部分为掌控板板载特殊元件控制示例
- 非板载特殊器件(例如IO、外接传感器等)操作方法同其他所有主控板基础及扩展示例
掌控板示例-屏幕控制¶
# -*- coding: UTF-8 -*-
#实验效果:控制掌控板屏幕显示功能
#接线:使用windows或linux电脑连接一块掌控板主控板
import time
from pinpong.board import Board
from pinpong.extension.handpy import *
Board("handpy").begin()#初始化,选择板型和端口号,不输入端口号则进行自动识别
#Board("handpy","COM36").begin() #windows下指定端口初始化
#Board("handpy","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("handpy","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
oled.DispChar('你好世界', 38, 0) #先写入缓存区,在(38,0)处显示'你好世界'
oled.DispChar('hello,world', 32, 16) #先写入缓存区,在(32,16)处显示'hello,world'
oled.DispChar('안녕하세요', 35, 32) #先写入缓存区,在(35,32)处显示'안녕하세요'
oled.DispChar('こんにちは世界', 24, 48) #先写入缓存区,在(24,48)处显示'こんにちは世界'
oled.show() #显示画面
'''其他屏幕控制的方法'''
#oled.DispChar("PinPong库",1) #屏幕显示"pinpong库"在第一行
#oled.DispChar("pinpong库", 42, 22) #屏幕显示"pinpong库"在x,y坐标处,x:0-127,y:0-63
#oled.Bitmap(0,0,50,50,"E:\\PinPong\\default.png") #依次是显示的坐标X,Y, 显示的宽和高,图片路径
#oled.chear(1) #屏幕清除第一行的内容,参数1,2,3,4
#oled.fill(0) #清屏黑色填0,白色填1
#oled.rotation(0) #屏幕旋转0°或者180°
#oled.pixel(0,0) #在坐标x,y画点
#oled.set_line_width(1) #设置线宽范围 1 - 128
#oled.line(0,0,127,63) #划线,依次是起点坐标x1,y1和终点坐标x2,y2
#oled.circle(63, 31, 20) #画圆,依次是坐标x, y和 半径, 不填充
#oled.fill_circle(63, 31, 20) #画圆,依次是坐标x, y和 半径, 填充
#oled.rect(0,0, 63, 31) #画矩形,依次是起点坐标x, y, 宽,高, 不填充
#oled.fill_rect(0,0, 63, 31) #画矩形,依次是起点坐标x, y, 宽,高, 填充
#oled.show() #显示生效,所有屏幕操作执行完成后调用show才会执行
掌控板示例-读取传感器¶
# -*- coding: UTF-8 -*-
#实验效果:读取掌控板板载传感器功能,通过终端窗口查看数据
#接线:使用windows或linux电脑连接一块掌控板主控板
import time
from pinpong.board import Board
from pinpong.extension.handpy import *
Board("handpy").begin()#初始化,选择板型和端口号,不输入端口号则进行自动识别
#Board("handpy","COM36").begin() #windows下指定端口初始化
#Board("handpy","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("handpy","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
while True:
print(button_a.value()) #按键A是否按下
print(button_b.value()) #按键B是否按下
print(button_ab.value()) #按键AB是否按下
# print(touchPad_P.is_touched()) #是否触摸P
# print(touchPad_Y.is_touched()) #是否触摸Y
# print(touchPad_T.is_touched()) #是否触摸T
# print(touchPad_H.is_touched()) #是否触摸H
# print(touchPad_O.is_touched()) #是否触摸O
# print(touchPad_N.is_touched()) #是否触摸N
# touch_threshold("all",60) #设置按键P/Y/T/H/O/N的触摸阈值,all代表全部
# print(touchPad_P.read()) #读取按键P的触摸值
# print(touchPad_Y.read()) #读取按键Y的触摸值
# print(touchPad_T.read()) #读取按键T的触摸值
# print(touchPad_H.read()) #读取按键H的触摸值
# print(touchPad_O.read()) #读取按键O的触摸值
# print(touchPad_N.read()) #读取按键N的触摸值
print(sound.read()) #读取麦克风强度
print(light.read()) #读取环境光强度
# print(accelerometer.get_x()) #读取加速度X的值
# print(accelerometer.get_y()) #读取加速度Y的值
# print(accelerometer.get_z()) #读取加速度Z的值
# print(accelerometer.get_strength()) #读取加速度的强度
print("------------------")
time.sleep(0.4)
掌控板示例-RGB灯控制¶
# -*- coding: UTF-8 -*-
#实验效果:控制掌控板板载RGB灯
#接线:使用windows或linux电脑连接一块掌控板主控板
import time
from pinpong.board import Board
from pinpong.extension.handpy import *
Board("handpy").begin()#初始化,选择板型和端口号,不输入端口号则进行自动识别
#Board("handpy","COM36").begin() #windows下指定端口初始化
#Board("handpy","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("handpy","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
rgb[0] = (255, 0, 0) # 设置为红色,全亮度
rgb[1] = (0, 128, 0) # 设定为绿色,一半亮度
rgb[2] = (0, 0, 64) # 设置为蓝色,四分之一亮度
rgb.write()
掌控板示例-音乐播放¶
# -*- coding: UTF-8 -*-
#实验效果:控制掌控板蜂鸣器播放音调
#接线:使用windows或linux电脑连接一块掌控板主控板
import time
from pinpong.board import Board
from pinpong.extension.handpy import *
Board("handpy").begin()#初始化,选择板型和端口号,不输入端口号则进行自动识别
#Board("handpy","COM36").begin() #windows下指定端口初始化
#Board("handpy","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("handpy","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
tune = ["C4:4", "D4:4", "E4:4", "C4:4", "C4:4", "D4:4", "E4:4", "C4:4",
"E4:4", "F4:4", "G4:8", "E4:4", "F4:4", "G4:8"]
music.play(tune) #播放自编乐谱
更多示例¶
pinpong库安装目录下有更多示例程序,可以通过如下方法找到.
- 进入Python终端,然后依次输入如下代码即可查看Python库所在的目录(site-packages)
import pinpong
print(pinpong.__path__)

- 打开对应路径的文件夹,其中examples文件夹下即为所有内置的示例程序
注意
内置examples文件夹下的案例仅供参考使用,不排除后续会变更,最终以本文档网页中列出的示例为准。

进阶教程¶
项目前置知识¶
概述¶
本系列教程是基于win10操作系统下,使用Python3通过pinpong库来控制Arduino UNO板来实现项目功能,在本节中我们将了解以下内容:
一、 什么是Arduino?
二、 什么是Python?
三、 如何编辑Python代码?
四、 什么是pinpong库?
一、什么是Arduino?¶
Arduino是一个开放源码电子原型平台,拥有灵活、易用的硬件和软件。Arduino专为设计师,工艺美术人员,业余 爱好者,以及对开发互动装置或互动式开发环境感兴趣的人而设的。
Arduino可以接收来自各种传感器的输入信号从而检测出运行环境,并通过控制光源,电机以及其他驱动器来影响 其周围环境。板上的微控制器编程使用Arduino编程语言(基于Wiring)和Arduino开发环境(以Processing为基 础)。Arduino可以独立运行,也可以与计算机上运行的软件(例如,Flash,Processing,MaxMSP)进行通信。Arduino开发 IDE 接口基于开放源代码,可以让您免费下载使用开发出更多令人惊艳的互动作品。
Arduino是人们连接各种任务的粘合剂。要给Arduino下一个最准确的定义,最好用一些实例来描述。
◆ 您想当咖啡煮好时,咖啡壶就发出“吱吱”声提醒您吗?
◆ 您想当邮箱有新邮件时,电话会发出警报通知您吗?
◆ 想要一件闪闪发光的绒毛玩具吗?
◆ 想要一款具备语音和酒水配送功能的X教授蒸汽朋克风格轮椅吗?
◆ 想要一套按下快捷键就可以进行实验测试蜂音器吗?
◆ 想为您的儿子自制一个《银河战士》手臂炮吗?
◆ 想自制一个心率监测器,将每次骑脚踏车的记录存进存储卡吗?
◆ 想过自制一个能在地面上绘图,能在雪中驰骋的机器人吗?
Arduino都可以为您实现。
1.1认识Arduino UNO¶
Arduino系列有众多的型号,其中最为经典的就是Arduino UNO了。在后续项目中我们也将以Arduino UNO为主。
先来简单的看下Arduino UNO。下图中有标识的部分为常用部分。图中标出的数字口和模拟口,即为常说的I/O。数字口有0~13,模拟口有0~5。
除了最重要的I/O口外,还有电源部分。UNO可以通过两种方式供电方式,一种通过USB供电,另一种是通过外接 6~12V的DC电源。除此之外,还有4个LED灯和复位按键,稍微说下4个LED。ON是电源指示灯,通电就会亮了。L是接在数字口13上的一个LED,在下节的项目中会进行教学的。TX、RX是串口通讯指示灯,比如我们在下载程序的过程中,这两个灯就会不停闪烁。

二、什么是Python?¶
Python是一种跨平台的计算机程序设计语言。是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越多被用于独立的、大型项目的开发。
Python是一种解释型脚本语言,可以应用于以下领域:
◆ Web 和 Internet开发
◆ 科学计算和统计
◆ 人工智能
◆ 桌面界面开发
◆ 软件开发
◆ 后端开发
◆ 网络爬虫
三、如何编辑Python代码?¶
可以用很多方法来编辑Python代码,甚至你可以使用文本编辑器编辑代码。在项目中我们将主要使用Python安装后自带的IDLE来编辑代码。
3.1如何安装Python¶
1、首先打开Python的下载链接( Python下载 )找到【Download Windows x86-64 executable installer】下载Python安装包,项目中使用到的Python版本为3.8.5。选择适合的版本下载安装即可。
2、安装Python,注意在安装时勾选add Python x.x to path,然后点击Install Now进行安装。(如果安装时未勾选,可以重新安装时勾选)

3.2如何编辑Python代码?¶
1、打开Python IDLE窗口如图所示,我们可以看到窗口,这是python shell窗口。

前面我们已经在IDLE中运行过简单语句了,但是在实际开发中,通常不能只包含一行代码,当需要编写多行代码时,就需要单独创建一个文件保存这些代码,在全部编写完成后一起执行,这里就需要新建一个文档
2、在 IDLE 主窗口的菜单栏上,选择“File -> New File”菜单项,将打开一个新窗口,在该窗口中,可以直接编写 Python 代码。 在输入一行代码后再按下 <Enter> 键,将自动换到下一行,等待继续输入

3、在代码区输入代码,我们输入hello world的指令

4、保存代码,点击菜单“Run Module”或按键盘上的“F5”键运行程序。如果是带*号的未保存状态执行运行功能的话,软件也会提示你保存后才可以运行。

5、运行成功,运行结果还是会返回python shell窗口反馈结果。

IDLE的使用可以参考官方文档: 官方文档
四、什么是pinpong库?¶
PinPong库是一套控制开源硬件主控板的Pyhton库,基于Firmata协议并兼容MicroPython语法,5分钟即可让你上手使用Python控制Arduino。
借助于PinPong库,直接用Python代码就能给各种常见的开源硬件编程。其原理是给开源硬件烧录一个特定的固件,使开源硬件可以通过串口与电脑通讯,执行各种命令。
PinPong库的名称由“Pin”和“Pong”组成,“Pin”指引脚,“PinPong”为“乒乓球”的谐音,指信号的往复。
pinpong库的设计,是为了让开发者在开发过程中不用被繁杂的硬件型号束缚,而将重点转移到软件的实现。哪怕程序编写初期用Arduino开发,部署时改成了掌控板,只要修改一下硬件的参数就能正常运行,实现了“一次编写处处运行”。
使用pinpong库可以结合Python丰富的扩展库资源来驱动Arduino。
附:
如何安装pinpong库?
在windows系统上使用快捷键win+R输入cmd,在弹出的小黑窗中输入 pip install pinpong 即可完成安装。
在pinpong官方文档 点击打开 中可以查看详细安装教程。
项目1 LED闪烁¶
一、概述¶
Hello World是所有编程语言学习的第一课,但是在Arduino学习中,我们的Hello World叫做Blink。Blink是什么意思呢?闪烁。其实Blink就是点亮Arduino机上的板载LED灯,并让它闪烁的一个程序。

二、项目实施¶
(1)点亮板载LED灯¶
硬件准备:
主控:Arduino UNO
连接线:TypeAtoB方口USB连接线

软件准备:
本教程项目使用操作系统为Win10,Python版本为3.8.5,编译器使用Python自带IDLE编辑器,Arduino板使用pinpong库驱动。
1、打开pinpong官方文档,找到基础库示例中的“blink”,并用IDLE打开。
2、 blink.py示例程序,右键选择Edit with IDLE→Edit with IDLE3.8.5 即可使用IDLE打开Python程序编辑内容。

程序编写:
将Arduino Uno主板通过USB连接到电脑后,无需选择端口,在运行程序时会自动识别端口,如识别失败则可以采用“指定端口初始化”的形式手动指定COM口。
注:第一次使用pinpong库会自动给Arduino主板烧录Firmata固件。所以不需要专门给Arduino上传固件。
按下F5运行程序,会提示保存程序,点击确定保存即可。运行成功后会弹出一个新的窗口,等待程序运行如图所示即为成功。
查看效果。Arduino Uno上的板载LED会按照亮1秒,熄灭1秒的规律闪烁。(如果此步执行没有成功可以查看官方文档中的常见问题)

注意:在程序运行时不可以拔掉与Arduino连接的USB线,且不能关闭新弹出的运行窗口,如果拔线或者关闭运行窗口,程序功能就会停止执行。
运行效果

红圈中的LED灯会按照亮1秒,熄灭1秒的规律闪烁。
1、如果我们想要修改小灯闪烁的频率,应该怎么修改程序?只需要修改代码中延时部分的时长即可。如图所示修改后的效果为小灯点亮2秒,熄灭1秒。
#实验效果:控制arduino UNO板载LED灯一秒闪烁一次
#接线:使用windows或linux电脑连接一块arduino主控板
import time
from pinpong.board import Board,Pin
Board("uno").begin() #初始化,选择板型和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
led = Pin(Pin.D13, Pin.OUT) #引脚初始化为电平输出
while True:
led.write_digital(1) #输出高电平
time.sleep(2) #等待2秒 保持状态
led.write_digital(0) #输出低电平
time.sleep(1) #等待1秒 保持状态
(2)点亮外接LED灯¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:LED发光模块
连接线:TypeAtoB方口USB连接线
硬件连接图:

- 将扩展板接入Arduino Uno主控板上,组装时注意对准后在压入,以防压弯插针。
- 将LED模块接入10号数字引脚。
程序编写:
1、我们在接线的时候将外接LED接到了10号引脚,所以我们需要修改程序才可以点亮这颗外接的小灯,将led 对应的引脚修改为10。

2、如果想要小灯有一个呼吸灯的效果应该如何执行?找到示例程序中的PWM模拟输出功能,并用Python IDLE运行。
3、修改引脚号与端口号,然后运行程序,小灯就会循环执行LED灯渐渐变亮,到最亮时熄灭的命令。
示例程序
# -*- coding: utf-8 -*-
#实验效果:小灯会循环执行渐渐变亮,到最亮时熄灭的命令
#接线:使用windows或linux电脑连接一块arduino主控板,主控板D6接一个LED灯模块
import time
from pinpong.board import Board,Pin,PWM #导入PWM类实现模拟输出
Board("uno").begin() #初始化,选择板型和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
pwm0 = PWM(Pin(Pin.D6)) #将Pin传入PWM中实现模拟输出
while True:
for i in range(255): #从0到255循环
pwm0.duty(i) #设置模拟输出值
print(i)
time.sleep(0.05)
三、代码分析¶
数字信号与模拟信号
你知道什么是数字信号什么是模拟信号吗?让我们先看看数字信号与模拟信号的概念吧。
资料阅读:
数字信号:数字信号指自变量是离散的、因变量也是离散的信号,这种信号的自变量用整数表示,因变量用有限数字中的一个数字来表示。在计算机中,数字信号的大小常用有限位的二进制数表示。
![]()
模拟信号:模拟信号是指用连续变化的物理量表示的信息,其信号的幅度,或频率,或相位随时间作连续变化,或在一段连续的时间间隔内,其代表信息的特征量可以在任意瞬间呈现为任意数值的信号。
![]()
光看概念感觉特别抽象,那么我们用生活中的实例来理解,比如我们平时用到的用于开关灯的开关,开和关是两个状态,非开即关。那么对灯来说开和关就是数字信号。再想想家中如果有一个温度计的话,温度变化是一个连续变化的的数值,并不能用某个特殊的状态来表示,温度的变化就是模拟信号。
在理解了数字信号与模拟信号之后,思考一下,在本项目中控制LED灯亮灭的信号是数字信号还是模拟信号?
四、硬件分析¶
不知道同学们有没有注意到,我们在第二个呼吸灯案例的时候,LED灯是接在10号数字引脚上的,但是按照数字信号和模拟信号的概念来看,应该是模拟信号才能实现呼吸灯的效果。这里就需要我们了解一个新的知识点,PWM信号。
观察我们手中的Arduino UNO主控板的数字引脚上,是不是有些引脚号旁边有*标记(有些板子是波浪号~)这些引脚就是支持PWM信号输出的引脚。
PWM(Pulse width modulation,中文名脉冲宽度调制),脉冲宽度调制是一种模拟控制方式。在Arduino中pwm是不断的做高低电平切换模拟出一种近似模拟量的输出的效果来实现变化的。但是这里仅仅得到了近似模拟值输出的效果,如果要输出真正的模拟值,还需要在模拟引脚上执行。
项目2 神奇的按键¶
一、概述¶
按钮开关,也称作按键开关,早期也称作敏感型开关,广泛应用在灯,插座总开关,门铃,汽车中控台等。按键开关的出现给用电安全增加了一层保护膜,方便控制电器的同时也进一步保护了元器件。
在Arduino 的学习过程中,我们会接触各种各样的输入设备,其中,按键开关是最简单 也是应用最广泛的一种。这里我们将用 Arduino 控制 LED 灯,实现按键按下开,再按下关的效果。

二、项目实施¶
(1)使用按钮点亮小灯¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:LED发光模块、按钮模块
连接线:TypeAtoB方口USB连接线

- 将LED发光模块接入13号数字引脚,将按钮模块接入8号数字引脚
程序编写:
1、 打开pingpong库的官方文档,找到基础库示例中的“数字输入”,并用IDLE打开。

2、按下F5运行程序,查看效果。当按下按钮时板载的LED灯会亮起(并打印1),松开会熄灭(打印0)。

注意:在程序运行时不可以拔掉与Arduino连接的USB线,且不能关闭新弹出的Python shell运行窗口,如果拔线或者关闭运行窗口,程序功能就会停止执行。
(2)按钮开关灯¶
在上步完成的功能中,我们通过按键可以实现“按下按键-LED 亮”,“松开按键-LED 灭”,但实际运用的开关却是“首次按下打开,再次按下关闭”,我们将在本步中实现这个功能。
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:LED发光模块、按钮模块
连接线:TypeAtoB方口USB连接线

- 将LED发光模块接入13号数字引脚,将按钮模块接入8号数字引脚
程序编写:
import time
from pinpong.board import Board,Pin
board = Board("uno").begin() #初始化,选择板型和端口号,不输入端口号则进行自动识别
#board = Board("uno","COM36").begin() #windows下指定端口初始化
#board = Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#board = Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
btn = Pin(Pin.D8, Pin.IN) #引脚初始化为电平输入
led = Pin(Pin.D13, Pin.OUT)
i=0 #设置变量i=0
while True:
v = btn.read_digital() #读取引脚电平
#print(v) #终端打印读取的电平状态
if (v == 1):
if (i == 1):
i=0
led.write_digital(0) #将按钮状态设置给led灯引脚
print("LED off")
else:
i=1
led.write_digital(1) #将按钮状态设置给led灯引脚
print("LED on")
time.sleep(0.5)
运行代码,摁下按钮可以切换LED灯的亮灭。

三、代码分析¶
1、导入必要的包和初始化设置。
import time
from pinpong.board import Board,Pin
board = Board("uno").begin() #初始化,选择板型和端口号,不输入端口号则进行自动识别
#board = Board("uno","COM36").begin() #windows下指定端口初始化
#board = Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#board = Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
btn = Pin(Pin.D8, Pin.IN) #引脚初始化为电平输入
led = Pin(Pin.D13, Pin.OUT)#引脚初始化为电平输出
2、我们需要一个按键能够得到两个不同的结果,那么就需要设置一个中间值来实现切换状态的作用。所以首先我们要设置一个变量i=0。
i = 0 #设置变量i=0
3、接着加入判断,判断按钮摁下的状态。为了方便设置,定义变量v为按钮的状态。
while True:
v = btn.read_digital() #读取引脚电平
#print(v) #终端打印读取的电平状态
if (v == 1):
4、然后加入判断,借助i来区别状态,如逻辑图所示,每次摁下按钮时i的值会在0和1之间切换,借助i值的变化来确定LED灯的亮灭状态即可,根据逻辑完成代码。

if (i == 1):
i=0
led.write_digital(0) #将按钮状态设置给led灯引脚
print("LED off")
else:
i=1
led.write_digital(1) #将按钮状态设置给led灯引脚
print("LED on")
time.sleep(0.5)
什么是按键抖动?
我们想象的开关电路是“按下按键-立刻导通”“再次按下-立刻断开”,而实际上并非如此。
按键通常采用机械弹性开关,而机械弹性开关在机械触点断开闭合的瞬间(通常 10ms左右),会由于弹性作用产生一系列的抖动,造成按键开关在闭合时不会立刻稳定的接通电路,在断开时也不会瞬时彻底断开。

那又如何消除按键抖动呢?
常用除抖动方法有两种:软件方法和硬件方法。这里重点讲讲方便简单的软件方法。
我们已经知道弹性惯性产生的抖动时间为 10ms 左右,用延时命令推迟命令执行的时间就可以达到除抖动的效果。
所以我们在代码中加入了0.5秒的延时以实现按键防抖的功能。

项目3 调光台灯¶
一、概述¶
在前面的课程中我们学会了如何点亮并控制LED灯,那LED灯的亮度我们可以调节吗?如果输出的值不是数字量,而是模拟量,是不是就可以实现通过数值来精确控制灯光亮度了。
在上节课的设计中,我们使用的是按钮控制灯的亮灭,按钮只有两个状态,是没办法输出模拟值的,所以本项目我们就需要使用到旋钮来作为灯光亮度的输入。

二、项目实施¶
(1)渐变灯光¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:LED发光模块
连接线:TypeAtoB方口USB连接线

- 将LED发光模块接入6号数字引脚
程序编写:
- 打开pingpong库的官方文档,找到基础库示例中的“模拟输出”,并用IDLE打开。

- 摁下F5运行程序,查看效果。LED灯会逐渐变亮,当到最亮时熄灭再慢慢变亮,循环变化。

(2)旋钮调光¶
在上步完成的功能中,我们旋钮来精确的控制LED灯的亮度。
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:LED发光模块、旋钮模块
连接线:TypeAtoB方口USB连接线

- 将LED发光模块接入6号数字引脚,将旋钮模块接入A0模拟引脚
程序编写:
import time
from pinpong.board import Board,Pin
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
pwm0 = Pin(Pin.D6, Pin.PWM) #初始化引脚为PWM模式 模拟输出方法2
adc0 = Pin(Pin.A0, Pin.ANALOG) #引脚初始化为电平输出
while True:
v = adc0.read_analog() #读取A0口模拟信号数值
L = int(v*255/1024)
pwm0.write_analog(L) #PWM输出
print("A0=",L)
运行代码,旋转旋钮LED灯会慢慢亮起和熄灭。

三、代码分析¶
- 导入必要的包和初始化设置。
import time
from pinpong.board import Board,Pin
Board("uno").begin() #初始化,选择板型和端口号,不输入则留空进行自动识别
pwm0 = Pin(Pin.D6, Pin.PWM)
adc0 = Pin(Pin.A0, Pin.ANALOG) #将Pin传入ADC中实现模拟输入
- 我们需要将旋钮输出的模拟值转换为LED灯亮度的PWM值,为了得到整数这里用了整型功能int。
v = adc0.read_analog() #读取A0口模拟信号数值
L = int(v*255/1024)
- 接着让LED灯根据我们转换过的数值亮起。
pwm0.write_analog(L) #PWM输出
print("A0=",L)
数据类型-整数类型
在我们做运算的时候,传感器读取到的数值经过*180/1024运算的结果往往不会是一个整数,常常会带着长长的小数尾数。我们试着不加int整形得到的结果如下:

这样的数值我们是无法直接使用的,所以就需要使用到整形int将数据取整。
项目4 智能节能灯¶
二、项目实施¶
(1)通过光线亮度控制小灯¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:LED发光模块、光线传感器
连接线:TypeAtoB方口USB连接线

- 将LED模块接入D13引脚,光线传感器接入A2引脚
程序编写:
- 打开pingpong库的官方文档,找到基础库示例中的“模拟输入”,并用IDLE打开。

- 修改代码,当亮度低于100的时候,点亮LED灯。
import time
from pinpong.board import Board,Pin
Board("uno").begin()
Light = Pin(Pin.A2,Pin.ANALOG)
LED = Pin(Pin.D13, Pin.OUT)
while True:
vl=Light.read_analog()
print("Light=",vl)
if vl < 100:
LED.write_digital(1)
else:
LED.write_digital(0)
- 摁下F5运行程序,查看效果。当亮度低于100(遮住光线传感器)的时候LED灯会亮起,恢复后LED灯会熄灭。

(2)加入声音传感器检测¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:LED发光模块、光线传感器、声音传感器
连接线:TypeAtoB方口USB连接线

- 将LED模块接入D13引脚,光线传感器接到A2引脚,声音传感器接到A1引脚。
程序编写
import time
from pinpong.board import Board,Pin #导入必要的库函数
Board("uno").begin()#初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
Sound = Pin(Pin.A1,Pin.ANALOG) #初始化声音传感器引脚为A1,检测声音大小
Light = Pin(Pin.A2,Pin.ANALOG)#初始化光线传感器引脚为A2,检测光线强度
LED = Pin(Pin.D13, Pin.OUT) #初始化LED引脚为D13
while True:
vs=Sound.read_analog()#读取模拟声音信号数值
vl=Light.read_analog()#读取模拟灯光信号数值
print("Sound=",vs,"Light=",vl)#打印声音和光线数据
if vs>200 and vl < 100:#判断光线和声音大小
LED.write_digital(1)
time.sleep(3)
else:
LED.write_digital(0)
运行代码,当亮度值低于100且声音值大于200时(遮住光线传感器且发出声音时),LED灯会点亮,当没有声音或光线传感器没有被遮住的状态维持3秒以上时,LED灯会熄灭。

三、代码分析¶
- 设计程序逻辑图

- 导入必要的包和初始化设置。
import time
from pinpong.board import Board,Pin #导入必要的库函数
Board("uno").begin()#初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
Sound = Pin(Pin.A1,Pin.ANALOG) #初始化声音传感器引脚为A1,检测声音大小
Light = Pin(Pin.A2,Pin.ANALOG)#初始化光线传感器引脚为A2,检测光线强度
LED = Pin(Pin.D13, Pin.OUT) #初始化LED引脚为D13
- 加入判断
while True:
vs=Sound.read_analog()#读取模拟声音信号数值
vl=Light.read_analog()#读取模拟灯光信号数值
print("Sound=",vs,"Light=",vl)#打印声音和光线数据
if vs>200 and vl < 100:#判断光线和声音大小
LED.write_digital(1)
time.sleep(3)
else:
LED.write_digital(0)
如何进行多条件判断
在本项目中我们需要判断两个条件,在我们做逻辑判断的时候经常会需要进行多条件判断,有些时候是需要两个条件都要满足的,有些时候是两个条件满足任意一条就可以了。在这种情况下,我们应该如何编写程序呢?
两条条件都需要满足的情况下,我们可以这样写
if 条件A and 条件B
两条条件满足任一即可的情况下,我们可以这样写
if 条件A or 条件B
想要得到反向的结果,即当x为true,得到的结果为false,当x为false时,得到的结果为true,我们可以这样写 not 条件。
四、硬件分析¶
在项目中我们用到了两种传感器,光线传感器和声音传感器。
光线传感器是将光信号变成电信号的特殊电子元件,在光线传感器中起到主要作用的就是就是光敏二极管。光敏二极管是光敏电阻中的一种。光明电阻在黑暗环境中,具有非常高阻值的电阻。光线越强,电阻值反而越低。随着两端电阻值的减小,电压也就相应减小,所以从模拟口独到的值也就变小。我们读取的数据也是由此而来的。

声音传感器的作用相当于一个麦克风。它用来接收声波,反馈声音的振动图像。在声音传感器上起到主要作用的就是麦克风,声波使麦克风内的薄膜震动,导致内部电容的变化,而产生与之对应的电压变化,经过转换为可监测的电压值反馈而来。

项目5 近视警示器¶
一、概述¶
近视眼越来越多,抛开遗传因素,主要还是不良用眼习惯导致的。特别是弓腰驼背,埋头看书,但是知道归知道,真的坐下本来挺直的腰杆又不知不觉地趴在桌子上。
为了健康,为了保护视力,我们用蜂鸣器和超声波传感器做一个简易近视警示器。

二、项目实施¶
(1)使用超声波测距¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:超声波传感器
连接线:TypeAtoB方口USB连接线

- 接线引脚TRIG–D7 、ECHO–D8、 GND–GND 、+5v–VCC
程序编写:
- 打开pingpong库的官方文档,找到常用库示例中的“超声波传感器”,并用IDLE打开。

- 摁下F5运行程序,查看效果。在新弹出的窗口中会显示超声波传感器测得的距离。

(2)使用蜂鸣器模块¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:蜂鸣器模块
连接线:TypeAtoB方口USB连接线

- 蜂鸣器模块连接到D7引脚
程序编写:
- 打开pingpong库的官方文档,找到常用库示例中的“蜂鸣器”,并用IDLE打开,将程序中的D8改为D7。

- 摁下F5运行程序,查看效果。在新弹出的窗口中会显示蜂鸣器的声音频率,蜂鸣器会按音阶递进响起。

(3)完成近视警示器¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:蜂鸣器模块、超声波传感器
连接线:TypeAtoB方口USB连接线

- 接线引脚TRIG–D7 、ECHO–D8、 GND–GND 、+5v–VCC
- 将蜂鸣器模块接入D4引脚。
程序编写
import time
from pinpong.board import Board,Pin,SR04_URM10,Tone#导入必要的库函数
Board("uno").begin()#初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
tone = Tone(Pin(Pin.D4))#初始化蜂鸣器模块引脚为D4
TRIGER_PIN = Pin(Pin.D7)#初始化超声波传感器TRIG引脚为D7
ECHO_PIN = Pin(Pin.D8)#初始化超声波传感器ECHO引脚为D8
tone.freq(200) #初始化蜂鸣器频率
sonar = SR04_URM10(TRIGER_PIN,ECHO_PIN)#初始化超声波传感器
while True:
dis = sonar.distance_cm() #读取超声波传感器距离
print("distance = %d cm"%dis)
if dis < 50:
tone.on()
time.sleep(1)
else:
tone.off()
运行代码,当超声波传感器监测到距离小于50时,蜂鸣器会报警提示距离桌面太近。

三、代码分析¶
- 设计程序逻辑图

- 导入必要的包和初始化设置。
import time
from pinpong.board import Board,Pin,SR04_URM10,Tone#导入必要的库函数
Board("uno").begin()#初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
tone = Tone(Pin(Pin.D4))#初始化蜂鸣器模块引脚为D4
TRIGER_PIN = Pin(Pin.D7)#初始化超声波传感器TRIG引脚为D7
ECHO_PIN = Pin(Pin.D8)#初始化超声波传感器ECHO引脚为D8
tone.freq(200) #初始化蜂鸣器频率
sonar = SR04_URM10(TRIGER_PIN,ECHO_PIN)#初始化超声波传感器
- 加入判断
while True:
dis = sonar.distance_cm()#读取超声波传感器距离
print("distance = %d cm"%dis)
if dis < 50:
tone.on()
time.sleep(1)
else:
tone.off()
四、硬件分析¶
- 认识超声波传感器
目前主流的测距传感器有超声波测距传感器,红外线测距传感器,激光测距传感器和雷达传感器。其中,超声波传感器适用于大幅平面静止测距。普通超声波传感器测距范围约2cm~450cm。
我们可以很清楚的看到实物超声波传感器上有 4 个角:VCC—5V 电源脚, Trig—出发控制端,Echo—接收端,GND—地段。图片中双探头传感器中,一个用来发送超声波,一个用来接收超声波。中间的单头超声波传感器即可以发送也可以接收超声波。这个传感器是我们接触的第一个四个引脚的传感器,使用的接线也比较特殊,后面的硬件连接需要做特殊处理。
超声波传感器测量距离的过程,超声波发射器向某一方向发射超声波,同时开始计时;超声波在空气中传播,一旦碰到障碍物立即折返;超声波接收器接收到反射波,同时停止计时。那么距离就可以通过时间差来计算出来。

- 认识蜂鸣器
首先,我们对喇叭应该非常熟悉,常见的耳机就是两个小喇叭,还有收音机,MP3,PM4播放器,电视机音响的发生原件都是喇叭。喇叭也叫做扬声器,是电声转换期间,它可以把模拟电信号转换为声音信号,属于宽频率发声器件。
而蜂鸣器是一体化的电子讯响器,可以在不同驱动波形下发出单调的声音,属于窄频率发声器件。我们可以通过改变频率设置蜂鸣器发声音高。
从外在表现看,喇叭和蜂鸣器最大区别是喇叭可以发出各种声音,而蜂鸣器只能发出几种单调的声音。从内在发声原理来看,蜂鸣器是利用压电陶瓷将电信号转化为机械振动信号;扬声器是利用电磁铁将电信号转化为机械振动信号。

项目6 噪声检测仪¶
一、概述¶
在日常生活会有很多噪声的来源,当噪声大到一定程度,就会影响我们的身体健康。那你有想过制作一个噪声检测装置吗?在之前的项目中我们有使用过声音传感器,那如何将检测结果更直观的显示出来?请跟着本文完成项目吧。

二、项目实施¶
(1)驱动舵机¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:舵机
连接线:TypeAtoB方口USB连接线

- 将舵机接入4号数字引脚
程序编写:
- 打开pingpong库的官方文档,找到常用库示例中的“舵机”,并用IDLE打开。

- 摁下F5运行程序,察看效果。

运行效果
舵机会以0度转到90度转到180度,再转回90度转到0度循环。
注意:在程序运行时不可以拔掉与Arduino连接的USB线,且不能关闭新弹出的Python shell运行窗口,如果拔线或者关闭运行窗口,程序功能就会停止执行。
- 如果我们想要修改舵机旋转的角度或让舵机按一定速度慢慢旋转,那我们只需要修改角度即可。示例程序为舵机从0度慢慢旋转至120度。
import time
from pinpong.board import Board,Pin,Servo
Board("uno").begin()
s1 = Servo(Pin(Pin.D4))
while True:
for i in range(120):
s1.write_angle(i)
time.sleep(0.1)
(2)用舵机反馈声音数值¶
大家可能会好奇,舵机是如何实现反馈声音数值的功能。如图所示,我们可以将读取到的数值转换成舵机的角度值,然后用舵柄当作指针来反馈数值。

硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:舵机、声音传感器
连接线:TypeAtoB方口USB连接线

- 将舵机接入4号数字引脚,声音传感器接入A0模拟引脚。
程序编写
- 我们在之前的项目中使用过声音传感器,知道如何读取它的数值,但是声音传感器读出的数据是0~1023而我们使用的舵机的旋转角度是0~180度,所以我们需要在程序中对这个数值进行转换。
vs = Sound.read_analog()
servoTurn = int(vs*180/1024)
在这里加入int,将数值整形,转化为舵机旋转的角度。
- 在了解了如何将声音传感器读取的数值转换为舵机可旋转的角度值之后,修改程序,示例程序如下。
import time
from pinpong.board import Board,Pin,Servo
Board("uno").begin()
s1 = Servo(Pin(Pin.D4))
Sound = Pin(Pin.A0,Pin.ANALOG)
while True:
vs = Sound.read_analog()
servoTurn = int(vs*180/1024)
print(servoTurn)
s1.write_angle(servoTurn)
time.sleep(0.5)
三、代码分析¶
import time
from pinpong.board import Board,Pin,Servo
Board("uno").begin()
s1 = Servo(Pin(Pin.D4)) #初始化舵机在D4引脚
Sound = Pin(Pin.A0,Pin.ANALOG)#初始化声音传感器在A0引脚
while True:
vs = Sound.read_analog()
servoTurn = int(vs*180/1024)#转换声音数值为舵机角度
print(servoTurn)
s1.write_angle(servoTurn)
time.sleep(0.5)
思考
在实际使用时我们会发现舵机的转动角度基本不会超过90度,这里我们可以试着将读取到的声音值打印出来观察一下,看看究竟为什么舵机只会在一个较小的范围内转动。
四、硬件分析¶
什么是舵机?
舵机是一种可以指定控制位置(角度)的电机,可以通过程序来指定控制舵机旋转的角度。我们最常用的舵机大多最大旋转角度是0°~180°,也有90°或者其他角度的。也有比较特殊的360°舵机,但是360°舵机不能够控制其旋转到指定的角度。本项目中我们使用的是180°舵机。

项目7 模拟交通灯¶
二、项目实施¶
(1)驱动LCD显示屏¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:1602LCD显示屏
连接线:TypeAtoB方口USB连接线

- 将1602LCD显示屏接入IIC接口
程序编写:
- 打开示例程序lcd1602.py,运行程序。(关于1602的示例程序有两个,一个是lcd1602.py一个是rgb1602.py,本项目使用的是单色背光的1062模块,所以使用lcd1602.py。打开pingpong库的官方文档,找到扩展库示例中的“1602显示屏”,并用IDLE打开。


运行效果
显示屏上第一行显示hello world,第二行显示1234,在屏幕上滚动播放。
- 如果我们想要修改屏幕上的内容,还有文字显示的位置,我们可以根据内容进行调整。
# -*- coding: UTF-8 -*-
#实验效果:I2C LCD1602控制
#接线:使用windows或linux电脑连接一块arduino主控板,LCD1602显示屏接到I2C口SCL及SDA
import time
from pinpong.board import Board
from pinpong.libs.lcd1602 import LCD1602_I2C #从libs中导入lcd1602_i2c库
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
#Board("uno","COM36").begin() #windows下指定端口初始化
#Board("uno","/dev/ttyACM0").begin() #linux下指定端口初始化
#Board("uno","/dev/cu.usbmodem14101").begin() #mac下指定端口初始化
lcd = LCD1602_I2C(i2c_addr=0x20) #初始化LCD的I2C地址
print("I2C LCD1602 TEST...")
lcd.backlight(True) #打开背光
lcd.clear() #清屏
lcd.set_cursor(2,0) #设置光标位置
lcd.print("Hello PinPong") #显示 "Hello PinPong",1602屏像素点少,不能显示汉字
lcd.set_cursor(6,1) #设置光标位置
lcd.print(6666) #显示数字1234
while True:
time.sleep(1)
lcd.scroll_left() #滚动显示
(2)加入LED和倒计时¶
仔细回顾一下交通灯的灯光切换方式,在红灯时,倒计时结束会变为绿灯,当绿灯倒计时结束时会先切到黄灯几秒后再切换到红灯亮起,依据这个规律,我们让LCD显示倒计时秒数。
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:1602LCD显示屏、红色黄色绿色LED模块
连接线:TypeAtoB方口USB连接线

- 将1602LCD显示屏接入IIC接口
- 将红色LED灯模块接D13数字引脚、绿色LED灯模块接D11数字引脚、黄色LED灯模块接D7数字引脚
程序编写
import time
from pinpong.board import Board,Pin
from pinpong.libs.lcd1602 import LCD1602_I2C
Board("uno").begin()
ledR = Pin(Pin.D13,Pin.OUT)#初始化红灯引脚在D13
ledG = Pin(Pin.D11,Pin.OUT)#初始化绿灯引脚在D11
ledY = Pin(Pin.D7,Pin.OUT)#初始化黄灯引脚在D7
lcd = LCD1602_I2C(i2c_addr=0x20) #初始化LCD地址为0x20
lcd.backlight(True) #打开背光
lcd.clear() #清屏
while True:
for G in range(30,-1,-1): #设置倒计时数值
ledR.write_digital(0)
ledG.write_digital(1)
ledY.write_digital(0)
lcd.set_cursor(7,1) #设置光标位置
lcd.print(G) #让LCD显示倒计时数值
time.sleep(1)
lcd.clear()
for Y in range(5,-1,-1):
ledR.write_digital(0)
ledG.write_digital(0)
ledY.write_digital(1)
lcd.set_cursor(7,1)
lcd.print(Y)
time.sleep(1)
lcd.clear()
for R in range(30,-1,-1):
ledR.write_digital(1)
ledG.write_digital(0)
ledY.write_digital(0)
lcd.set_cursor(7,1)
lcd.print(R)
time.sleep(1)
lcd.clear()
三、代码分析¶
- 导入必要库和模块,参考之前使用过LED灯的案例加上本次使用的LCD屏所需的部分。
import time
from pinpong.board import Board,Pin
from pinpong.libs.lcd1602 import LCD1602_I2C
- 然后对需要用到的功能进行初始化设置。
Board("uno").begin()
ledR = Pin(Pin.D13,Pin.OUT)
ledG = Pin(Pin.D11,Pin.OUT)
ledY = Pin(Pin.D7,Pin.OUT)
lcd = LCD1602_I2C(i2c_addr=0x20)
lcd.backlight(True)
lcd.clear()
- 设置一段红灯的倒计时功能,另外两种灯用相同的方法设置。
for G in range(30,-1,-1):
ledR.write_digital(0)
ledG.write_digital(1)
ledY.write_digital(0)
lcd.set_cursor(7,1)
lcd.print(G)
time.sleep(1)
lcd.clear()
for i in range()的作用:
range()是一个函数,for i in range()就是给 i 赋值,比如:
for i in range(30):
就是把0~30依次赋值给i,在程序中加入的
for i in range(30,-1,-1):
是将0~30的数值顺序倒序,按30~0的顺序赋值给i。
四、硬件分析¶
什么LCD1602?
LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。1602的意思是显示屏一行最多可以显示16个字符,一共有2行。
我们使用的是已经集成了控制驱动电路的成品模,通过iic接口与主控板连接。

项目8 桌面气象站¶
二、项目实施¶
(1)读取温度传感器数据¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:LM35线性温度传感器
连接线:TypeAtoB方口USB连接线

- 将LM35线性温度传感器接入A0模拟接口
程序编写:
- LM35温度传感器需要通过读取模拟值经过一定的换算得到温度数据,那么首先就需要读取对应引脚的模拟值,回顾之前案例,打开pingpong库的官方文档,找到基础库示例中的“模拟输入”,并用IDLE打开。

- 修改程序,添加转换公式:温度= 读取到模拟值 * (5/10.24);这样就能顺利读取温度数据了。
import time
from pinpong.board import Board,Pin
Board("uno").begin()
adc0 = Pin(Pin.A0, Pin.ANALOG)
while True:
v = adc0.read_analog()
tem = round(v*(5/10.24),2)
print("temperature:", tem)
time.sleep(0.5)
(2)让屏幕显示温度数据¶
在上个项目中我们使用了LCD显示屏,为了方便查看温度的实时数据,我们将数据在屏幕上显示出来。
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:1602LCD显示屏、LM35线性温度传感器
连接线:TypeAtoB方口USB连接线

- 将1602LCD显示屏接入IIC接口
- 将LM35线性温度传感器接入A0模拟接口
程序编写
import time
from pinpong.board import Board,Pin
from pinpong.libs.lcd1602 import LCD1602_I2C
Board("uno").begin()#初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
adc0 = Pin(Pin.A0, Pin.ANALOG) #初始化温度读取引脚在A0
lcd = LCD1602_I2C(i2c_addr=0x20)#初始化LCD的I2C地址
lcd.backlight(True) #打开背光
lcd.clear()#清屏
lcd.set_cursor(2,0)#设置光标位置
lcd.print('temperature')#显示“temperature”
while True:
v = adc0.read_analog()#读取模拟量的值
tem = round(v*(5/10.24),2)#将读到的数值转化为温度数据
lcd.set_cursor(5,1)
lcd.print(str(tem))
lcd.print('C')
time.sleep(1)
三、代码分析¶
- 导入必要库和模块,参考之前使用过的LCD屏所需的部分和adc部分。
import time
from pinpong.board import Board,Pin
from pinpong.libs.lcd1602 import LCD1602_I2C
- 然后对需要用到的功能进行初始化设置。
Board("uno").begin()#初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
adc0 = Pin(Pin.A0, Pin.ANALOG) #初始化温度读取引脚在A0
lcd = LCD1602_I2C(i2c_addr=0x20)#初始化LCD的I2C地址
lcd.backlight(True) #打开背光
lcd.clear()#清屏
lcd.set_cursor(2,0)#设置光标位置
lcd.print('temperature')#显示“temperature”
- 让屏幕显示温度,每隔一秒钟刷新。
while True:
v = adc0.read_analog()#读取模拟量的值
tem = round(v*(5/10.24),2)#将读到的数值转化为温度数据
lcd.set_cursor(5,1)
lcd.print(str(tem))
lcd.print('C')
time.sleep(1)
round()的作用:
round()函数用来返回浮点数四舍五入后的值,例如round(35.543,2)返回的结果就是35.54,(35.543,2)中的2代表保留两位小数。
四、硬件分析¶
LM35线性温度传感器
基于LM35半导体的温度传感器,可以用来对环境温度进行定性的检测。LM35半导体温度传感器是美国国家半导体公司生产的线性温度传感器。其测温范围是-40℃到150℃,灵敏度为10mV/℃,输出电压与温度成正比。

项目9 游园人数统计¶
二、项目实施¶
(1)使用红外光电开关检测是否有人经过¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:红外光电开关
连接线:TypeAtoB方口USB连接线

- 将红外光电开关接入8号数字接口
程序编写:
- 红外光电开关是通过检测指定距离内(3~80cm,可以调节)是否有物体经过,当检测到有人通过的话,会输出低电平,当没人经过的时候会输出高电平。看起来功能和我们之前用过的按钮的功能类似,是数字输入,所以我们以官方文档基础库示例中的“数字输入”为基础进行修改。

- 原程序是摁下按键时L灯亮起,但是红外光电开关是触发时输出低电平,未触发时输出高电平,所以将条件置反,就可以当传感器触发时灯亮,未触发时灯灭的功能。
import time
from pinpong.board import Board,Pin
Board("uno").begin()
btn = Pin(Pin.D8, Pin.IN)
led = Pin(Pin.D13, Pin.OUT)
while True:
v = btn.read_digital()
print(v)
led.write_digital(not v)
time.sleep(0.1)
(2)让屏幕显示人数¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:1602LCD显示屏、红外光电开关
连接线:TypeAtoB方口USB连接线

- 将1602LCD显示屏接入IIC接口
- 将红外光电开关接入8号数字接口
程序编写
import time
from pinpong.board import Board,Pin
from pinpong.libs.lcd1602 import LCD1602_I2C
Board("uno").begin()#初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
sw = Pin(Pin.D8, Pin.IN) #初始化红外开关引脚在D8
lcd = LCD1602_I2C(i2c_addr=0x20)#初始化LCD的I2C地址
lcd.backlight(True) #打开背光
lcd.clear()#清屏
v=0
lcd.set_cursor(2,0)#设置光标位置
lcd.print('Visitors')#显示标题
while True:
if sw.read_digital() == 0:
v = v+1
led.write_digital(1)
time.sleep(0.5)
print(v)
lcd.set_cursor(7,1)#设置光标位置
lcd.print(v)#显示人数
三、代码分析¶
- 导入必要库和模块,参考之前使用过的LCD屏所需的部分和pin部分。
import time
from pinpong.board import Board,Pin
from pinpong.libs.lcd1602 import LCD1602_I2C
- 然后对需要用到的功能进行初始化设置。
Board("uno").begin()#初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
sw = Pin(Pin.D8, Pin.IN) #初始化红外开关引脚在D8
lcd = LCD1602_I2C(i2c_addr=0x20)#初始化LCD的I2C地址
lcd.backlight(True) #打开背光
lcd.clear()#清屏
v=0
lcd.set_cursor(2,0)#设置光标位置
lcd.print('Visitors')#显示标题
- 每当有人经过就将变量v增加1并用显示屏显示人数。
while True:
if sw.read_digital() == 0:
v = v+1
led.write_digital(1)
time.sleep(0.5)
print(v)
lcd.set_cursor(7,1)#设置光标位置
lcd.print(v)#显示人数
四、硬件分析¶
红外光电开关
红外接近开关是一种集发射与接收于一体的光电开关传感器。数字信号的输出伴随传感器后侧指示灯亮的亮灭,检测距离可以根据要求进行调节,可调范围3-80cm。该传感器具有探测距离远、受可见光干扰小、价格便宜、易于装配、使用方便等特点,可以广泛应用于机器人避障、互动媒体、工业自动化流水线等众多场合。
项目10 定时浇花装置¶
一、概述¶
相信大家的家中应该都会养有一些植物吧,想要植物生长的旺盛我们就需要定期给他们浇水,但是我们可能常常会忘记给家中的植物浇水,可能就会导致植株枯萎,为了避免出现这类问题,我们可以自己设计一个定时浇花装置。

二、项目实施¶
(1)驱动继电器¶
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:继电器模块
连接线:TypeAtoB方口USB连接线

- 将继电器接入13号数字接口
程序编写:
- 继电器是通过高低电平来控制开关的,所以我们可以参考官方文档基础库示例中的“数字输出”。运行这段程序会出现的效果是继电器随着L灯的闪烁会有“啪嗒”声,这就是继电器内的电磁开关在切换时发出的声音。

(2)用继电器控制水泵¶
要实现浇花的功能那么就会需要使用到水泵来帮我们实现,但是水泵的工作电压大多是12V的,但是我们使用的arduino uno的输出电压是5v,无法直接驱动水泵,这时我们就需要借助继电器来驱动水泵了。
硬件准备:
主控:Arduino UNO、IO 传感器扩展板 V7.1
模块:继电器模块、水泵、12V电源
连接线:TypeAtoB方口USB连接线

- 将继电器接入13号数字接口
- 水泵与继电器连接
程序编写
- 浇花需要每隔一定的时间再执行,那如何控制间隔时间呢?用之前项目中最常用的time.sleep()行不行?用延时功能来控制是可以实现功能的,但是无法精确的定位在指定的时间,限制非常多,每次重启程序延时的时间就会重新计算,影响浇水的效率。
- 这里我们将使用time函数的time.strftime()功能来定位时间,如示例中,在每天下午15点30分10秒的时候打印“浇花”。在实际使用中将继电器执行功能加进来就可以了。
import time
while True:
time_now = time.strftime("%H:%M:%S", time.localtime())
if time_now == "15:30:10":
print("浇花")
time.sleep(1)
- 加入继电器实现每天定时浇水功能。
import time
from pinpong.board import Board,Pin
Board("uno").begin()
led = Pin(Pin.D13, Pin.OUT)
while True:
time_set = time.strftime("%H:%M:%S",time.localtime())
print(time_set)
if time_set == "15:30:10":
led.write_digital(1)
print("浇花")
time.sleep(5)
else:
led.write_digital(0)
time.sleep(1)
三、代码分析¶
import time
from pinpong.board import Board,Pin
Board("uno").begin() #初始化,选择板型(uno、leonardo、xugu)和端口号,不输入端口号则进行自动识别
led = Pin(Pin.D13, Pin.OUT) #初始化继电器引脚在D13
while True:
time_set = time.strftime("%H:%M:%S",time.localtime())#刷新时间
print(time_set)
if time_set == "15:30:10": #设定每天15:30:10浇水
led.write_digital(1)#输出高电平,继电器吸合
print("浇花")#终端打印信息
time.sleep(5)#等待5秒 保持状态
else:
led.write_digital(0)#输出低电平
time.sleep(1)#等待1秒 保持状态
time库函数
time库在我们之前的案例中一直有使用到的一个库,但是我们大多数情况只用到了其中的延时的功能,其实还有很多功能,让我们来了解一下吧。
time库是python中处理时间的标准库
- time库的使用
时间获取-------time() ctime() localtime()
时间格式化-------strftime() strptime()
程序计时-------sleep() perf_counter()
- 时间获取函数
time()-------获取当前时间戳,浮点数形式
ctime()-------以可读的方式返回字符串时间
localtime()-------计算机可以处理的时间格式
- 时间格式化
strftime()-------将时间进行合理输出
strptime()-------自定义时间
- 程序计时
perf_counter()-------测量时间函数
sleep()-------产生时间函数,模拟休眠的时间,单位是秒,可以是浮点数
四、硬件分析¶
继电器
继电器(英文名称:relay)是一种电控制器件,是当输入量(激励量)的变化达到规定要求时,在电气输出电路中使被控量发生预定的阶跃变化的一种电器。它具有控制系统(又称输入回路)和被控制系统(又称输出回路)之间的互动关系。通常应用于自动化的控制电路中,它实际上是用小电流去控制大电流运作的一种“自动开关”。故在电路中起着自动调节、安全保护、转换电路等作用。
光看文字描述有点难以理解,下面看看图示帮助理解继电器的作用。继电器工作原理图:

这里有两个电源回路,一个是线圈部分的回路另一个是设备(灯珠)端的回路。我们把线圈铁芯这端理解成掌控板这端,设备(灯珠)端我们理解成水泵;线圈电源就是掌控板的输出电压5V,被控制端电源电压就是我们驱动水泵的12V电源。我们通过5V的电压控制线圈铁芯这个电磁铁,当继电器高电平时,线圈通电,将衔铁吸引,这样设备端的回路就接通了。

继电器的作用
继电器是具有隔离功能的自动开关元件,广泛应用于遥控、遥测、通讯、自动控制、机电一体化及电力电子设备中,是最重要的控制元件之一。
继电器一般都有能反映一定输入变量(如电流、电压、功率、阻抗、频率、温度、压力、速度、光等)的感应机构(输入部分);有能对被控电路实现“通”、“断”控制的执行机构(输出部分);在继电器的输入部分和输出部分之间,还有对输入量进行耦合隔离,功能处理和对输出部分进行驱动的中间机构(驱动部分)。
作为控制元件,概括起来,继电器有如下几种作用:
1)扩大控制范围:例如,多触点继电器控制信号达到某一定值时,可以按触点组的不同形式,同时换接、开断、接通多路电路。
2)放大:例如,灵敏型继电器、中间继电器等,用一个很微小的控制量,可以控制很大功率的电路。
3)综合信号:例如,当多个控制信号按规定的形式输入多绕组继电器时,经过比较综合,达到预定的控制效果。
4)自动、遥控、监测:例如,自动装置上的继电器与其他电器一起,可以组成程序控制线路,从而实现自动化运行。
PinPong类 Board class¶
构造器 constructor¶
创建和初始化一块板子。
board = PinPong(board_name,port)
- boardname: 板子的类型。
- port: 设置对应的端口号,如省略参数则自动识别选择一个端口。如何查询端口号,见安装及快速开始教程。对于基于linux的开发板, 例如树莓派,哪吒板,不需要这个参数
- 说明:board_name命名列表
- 规则:
- 简单短小好记忆
- 不区分大小写,样例中推荐全小写
- 长单词或需要区分版本的单词间使用下划线区分
板子名称 | board_name | 备注 |
---|---|---|
Arduino uno r3 | uno | |
Arduino leonardo | leonardo | |
Arduino nano | nano | 暂未支持 |
Arduino mega1280 | mega1280 | 暂未支持 |
Arduino mega2560 | mega2560 | 暂未支持 |
micro:bit | microbit | |
掌控板 | handpy | |
虚谷号 | xugu | 等效于uno |
树莓派 | rpi | |
Firebeetle ESP32 | firebeetle_esp32 | 暂未支持 |
Firebeetle ESP8266 | firebeetle_esp8266 | 暂未支持 |
LattePanda | lp | 等效于leonardo |
ESP32 | esp32 | 暂未支持 |
ESP8266 | esp8266 | 暂未支持 |
哪吒开发板 | nezha | |
行空板 | unihiker |
方法 method¶
board.begin()
连接arduino板,检测固件版本,若没有烧录固件或版本有误,会烧录最新固件。
Pin类 Pin class¶
常量 constants¶
构造器 constructor¶
创建和初始化一个引脚。
pin = Pin(board, vpin, mode)
- board: 通过pinpong类创建的板子的对象,只有一块板子时可以省略此参数。
- vpin: 板子上所用到的引脚号。(数字引脚1-Pin.D1, 模拟引脚1-Pin.A1)
- mode: 定义引脚的输入、输出。Pin.IN, Pin.OUT (定义模拟量引脚时省略,默认输入)
定义一个数字输入,比如按键,
button_pin = Pin(Pin.D8, Pin.IN)
定义一个模拟量传感器引脚,
Analog_pin = Pin(Pin.A0)
方法 method¶
pin.value()
调用value(),没有提供args时,为数字读取,返回0或1。
v = button_pin.value()//获取引脚button_pin的引脚状态
pin.value(x)
调用value(),提供args时,为数字写入。
pin.value(1) //引脚pin输出高电平
pin.on()
引脚pin设置为高电平, 同pin.value(1)
pin.off()
引脚pin设置为低电平, 同pin.value(0)
pin.irq(trigger,handler)
设置中断,
- trigger: 中断模式,rising - 上升沿, falling - 下降沿, low - 低电平, high - 高电平...
- handler:
ADC类 ADC class¶
构造器 constructor¶
创建和初始化一个ADC,获取模拟量数据。
adc = ADC(board,Pin(board, Pin.A0))
- board: 通过pinpong类创建的板子对象,只有一块板子时可以省略此参数。
- Pin: 通过pin类创建的引脚对象。
方法 method¶
adc.read()
读取adc的模拟量。比如,brightness = adc.read()
PWM类 PWM class¶
构造器 constructor¶
创建和初始化一个PWM, 来输出PWM信号。
pwm0 = PWM(board, Pin(board, Pin.D6))
- board: 通过pinpong类创建的板子对象,只有一块板子时可以省略此参数。
- Pin: 通过pin类创建的引脚对象。
方法 method¶
pwm0.freq()
freq(),没有提供args时,返回频率。
f = pwm0.freq()//获取PWM频率。
pwm0.freq(x)
freq(x),提供args时,设置PWM频率为x。
pwm0.freq(1000)//设置PWM频率为1000。
pwm0.duty()
duty(),没有提供args时,返回占空比。
f = pwm0.duty()//获取PWM占空比。
pwm0.duty(x)
duty(x),提供args时,设置PWM占空比,范围0-255。
pwm0.duty(127)//设置PWM占空比为50%。
pwm0.deinit()
开发计划¶
- 这里将记录一些正在开发或计划开发的内容,如果你有什么建议可至本文档的github留言
- micro:bit板载元件api调整为与microPython相同。
- arduino nano的支持。
- 其他更多扩展模块的支持。
更新记录¶
V0.4.2公测版 20210820¶
- 重构handpy板载传感器的调用接口为micropython语法
- 增加handpy、micro:bit对外接传感器模块的支持
- 增加哪吒板的支持
- 解决发现的bug
V0.3.5公测版 20210407¶
- 支持传感器12位DA转换模块
- 支持传感器bmi160 6轴传感器
- 支持RGB LED点阵表情包
- 支持实时时钟SD2405
- 支持TM1650四位数码管
- 支持SHT31数字温度传感器
- 支持臭氧传感器
- 电容式指纹识别传感器
- 解决发现的bug
V0.3.4公测版 20201231¶
- 解决uno、leonardo pwm问题
- 新增microbit板载资源支持
- 新增handpy板载资源支持
- 新增bme680支持(环境传感器)
- 新增max17043支持(3.7V锂电池电量计)
V0.3.3公测版 20201116¶
- 支持DS18B20(温度传感器)传感器
- 支持音频分析模块
- 支持HX711(重量传感器)传感器
- 支持TDS(测量水的TDS)传感器
- 支持心率传感器
- 支持BME280(环境传感器)传感器
- 支持VL53L0(激光测距)传感器
- 支持LIS2DH(三轴加速计)传感器
- 支持BMP388(气压传感器)传感器
- 支持INA219(数字功率计)传感器
- 支持CCS811(空气质量)传感器
- 支持ADS1115(16位AD转换模块)传感器
- 支持huskylens(哈士奇)
V0.3.2公测版 20200929¶
- 增加树莓派、掌控板(handpy)以及micro:bit板的支持(当前仅支持数字模拟读写及舵机控制功能)。
- 新增扩展库:BNO05510DOF绝对定向传感器、BMP280气压传感器、NFC模块、PAJ7620U2手势识别模块、DS1307实时时钟模块、RPI TLC_10bit_adc树莓派10位adc模块、PRI pca_9685树莓派16路pwm模块。
V0.3.0公测版 20200727¶
注意
重要版本:API重做最终版本,后续API将不再进行修改,可用于教程编写。
- PinPong类名替换为Board类名便于理解
- 初始化方式修改,使用Board及begin()函数
- 增加默认板,无需给所有函数输入board参数
- 将常用库放入Board中,导入更方便
V0.2.2公测版 20200715¶
- Pin类增加基础函数:
- read_digital()
- write_digital(v)
- read_analog()
- write_analog(v)
- 详细用法见“PinPong示例”。
V0.2.0公测版 20200625¶
- 语法及库名称规范完成
- 增加常见扩展硬件库的支持
- 增加自动识别串口功能
V0.1.x内测版¶
- ::
- 功能开发及内测版本,仅供测试,代码与V0.2.0可能存在不兼容.
常见问题¶
虚谷号上出现错误:ImportError: cannot import name ‘Pin’¶
- 尝试先重启虚谷号
- 重启后如果依然出现,则先尝试更新pinpong库,终端运行: pip install -U pinpong
- 如依然出现,则尝试卸载重装pinpong库,终端运行: pip uninstall pinpong ,然后重启虚谷号后重新安装: pip install pinpong
使用pinpong库控制的硬件可以脱离电脑运行吗?¶
- pinpong是一个Python库,主要实现硬件与Python的交互,因此只有能运行Python(注意: Python和microPython 不一样 )的设备才可以使用,因此如果要脱离PC,可以使用树莓派、LattePanda等便携式单板计算机。
- 使用实时通信的方式与Python交互运行,后续将考虑开发通过网络的方式进行通信以实现在电脑上运行pinpong(Python),通过网络实时控制带网络功能的硬件设备。
运行程序时出现SerialExcedption: could not open port ‘COM’: PermissionError(13,’拒绝访问。’,None,5 怎么办?¶
- 此错误说明有设备占用了串口,或上一次程序没有正常关闭,或当前识别的串口错误。
- 如果是以前可以正常使用而本地运行无法使用则一般为串口被占用了,则可以尝试关闭上一次的程序及其他占用串口的软件,或重新插拔USB口及重启电脑。
- 如果是第一次使用这个主控板,则可能为串口没有安装驱动,需要安装一次驱动(推荐使用Mind+内置的一键安装驱动功能),或打开设备管理器查看是否有端口(COM)。