一、利用阿里云服务器实现树莓派外网访问(SSH 反向代理)
1. 树莓派端配置
步骤 1:安装 SSH 服务(若未安装)
sudo apt-get install openssh-server
步骤 2:创建反向代理连接
-p 22
:指定阿里云服务器的 SSH 端口
-qngfN
:静默模式、后台运行、不分配伪终端
-R
:反向代理参数
2222
:阿里云服务器用于映射的端口(需自行定义未被占用的端口)
username
:阿里云服务器登录用户名
步骤 3:设置开机自启动
将反向代理命令添加到~/.bashrc
或创建启动脚本:
echo "ssh -p 22 -qngfNTR 2222:localhost:22 username@114.55.126.125" >> ~/.bashrc
2. 阿里云服务器端配置
步骤 1:检查端口监听状态
ss -ntl | grep 2222
若输出类似LISTEN 0 128 :::2222 :::*
,说明端口已成功绑定。
步骤 2:配置防火墙(若使用安全组)
在阿里云控制台的安全组规则中添加入方向规则,允许 TCP 协议访问 2222 端口。
3. 外网访问树莓派
# 格式: ssh -p [服务器映射端口] [树莓派用户名]@[服务器IP]
ssh -p 2222 pi@114.55.126.125
二、树莓派 PWM LED 呼吸灯(含多线程实现)
1. 单线程顺序呼吸灯
import RPi.GPIO as GPIO
import time# 设置GPIO模式为BOARD编号
GPIO.setmode(GPIO.BOARD)# 定义LED引脚(可修改为实际连接的引脚)
YELLOW_LED = 11 # 黄灯
GREEN_LED = 16 # 绿灯# 初始化引脚
GPIO.setup(YELLOW_LED, GPIO.OUT)
GPIO.setup(GREEN_LED, GPIO.OUT)# 创建PWM对象(频率60Hz)
pwm_yellow = GPIO.PWM(YELLOW_LED, 60)
pwm_green = GPIO.PWM(GREEN_LED, 60)# 启动PWM(初始占空比0)
pwm_yellow.start(0)
pwm_green.start(0)try:# 循环3次呼吸效果for _ in range(3):# 黄灯呼吸for dc in range(0, 101, 5):pwm_yellow.ChangeDutyCycle(dc)time.sleep(0.05)for dc in range(100, -1, -5):pwm_yellow.ChangeDutyCycle(dc)time.sleep(0.05)# 绿灯呼吸for dc in range(0, 101, 5):pwm_green.ChangeDutyCycle(dc)time.sleep(0.05)for dc in range(100, -1, -5):pwm_green.ChangeDutyCycle(dc)time.sleep(0.05)finally:# 停止PWM并清理资源pwm_yellow.stop()pwm_green.stop()GPIO.cleanup()
2. 多线程同时呼吸灯实现
import RPi.GPIO as GPIO
import time
import threading# 设置GPIO模式
GPIO.setmode(GPIO.BOARD)# 定义LED引脚
YELLOW_LED = 11
GREEN_LED = 16# 初始化引脚
GPIO.setup(YELLOW_LED, GPIO.OUT)
GPIO.setup(GREEN_LED, GPIO.OUT)# 创建PWM对象
pwm_yellow = GPIO.PWM(YELLOW_LED, 60)
pwm_green = GPIO.PWM(GREEN_LED, 60)# 启动PWM
pwm_yellow.start(0)
pwm_green.start(0)def yellow_breath():"""黄灯呼吸函数"""for _ in range(3):for dc in range(0, 101, 5):pwm_yellow.ChangeDutyCycle(dc)time.sleep(0.05)for dc in range(100, -1, -5):pwm_yellow.ChangeDutyCycle(dc)time.sleep(0.05)def green_breath():"""绿灯呼吸函数"""for _ in range(3):for dc in range(0, 101, 5):pwm_green.ChangeDutyCycle(dc)time.sleep(0.05)for dc in range(100, -1, -5):pwm_green.ChangeDutyCycle(dc)time.sleep(0.05)try:# 创建并启动线程t1 = threading.Thread(target=yellow_breath)t2 = threading.Thread(target=green_breath)t1.start()t2.start()# 等待线程结束t1.join()t2.join()finally:# 清理资源pwm_yellow.stop()pwm_green.stop()GPIO.cleanup()
三、树莓派超声波测距程序
1. 硬件连接
超声波模块 Trig 引脚 → 树莓派 GPIO23(BCM 编号)
超声波模块 Echo 引脚 → 树莓派 GPIO24(BCM 编号)
模块 VCC → 树莓派 5V
模块 GND → 树莓派 GND
2. 完整代码
import RPi.GPIO as GPIO
import time# 设置GPIO模式为BCM
GPIO.setmode(GPIO.BCM)# 定义引脚
TRIG_PIN = 23
ECHO_PIN = 24# 初始化引脚
GPIO.setup(TRIG_PIN, GPIO.OUT)
GPIO.setup(ECHO_PIN, GPIO.IN)def measure_distance():"""测量距离函数"""# 发送触发信号GPIO.output(TRIG_PIN, True)time.sleep(0.00001) # 10微秒GPIO.output(TRIG_PIN, False)# 记录发送和接收时间start_time = time.time()stop_time = time.time()# 等待Echo变为高电平(发送超声波)while GPIO.input(ECHO_PIN) == 0:start_time = time.time()# 等待Echo变为低电平(接收超声波)while GPIO.input(ECHO_PIN) == 1:stop_time = time.time()# 计算距离(声速343m/s,转换为cm)time_elapsed = stop_time - start_timedistance = (time_elapsed * 34300) / 2return distancetry:print("超声波测距程序启动,按Ctrl+C停止")while True:dist = measure_distance()print(f"距离: {dist:.2f} cm")time.sleep(1) # 每秒测量一次except KeyboardInterrupt:print("程序停止")
finally:GPIO.cleanup()
四、Linux 驱动程序控制 PWM(含编译与测试)
1. 准备编译环境
# 安装内核头文件(树莓派专用)
sudo apt-get install raspberrypi-kernel-headers
2. 驱动程序代码
pwmled.h 文件
#define PWMLED_MAX_BRIGHTNESS 1000typedef enum {PWMLED_CMD_SET_BRIGHTNESS = 0x1,PWMLED_CMD_GET_BRIGHTNESS,
} pwmled_cmd_t;
pwmled.c 文件
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/pwm.h>
#include "pwmled.h"MODULE_LICENSE("Dual MIT/GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("PWM LED Driver");#define PWM_PERIOD_NS 1000000 // 1ms周期(1000000纳秒)static struct {struct pwm_device *pwm;unsigned int brightness;
} pwmled;// IOCTL处理函数
long pwmled_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {switch (cmd) {case PWMLED_CMD_SET_BRIGHTNESS:// 限制亮度范围0~1000pwmled.brightness = arg > PWMLED_MAX_BRIGHTNESS ? PWMLED_MAX_BRIGHTNESS : arg;// 计算占空比(亮度*1000纳秒)int duty_ns = pwmled.brightness * 1000;// 配置PWMpwm_config(pwmled.pwm, duty_ns, PWM_PERIOD_NS);// 启用或禁用PWMif (pwmled.brightness > 0) {pwm_enable(pwmled.pwm);} else {pwm_disable(pwmled.pwm);}break;case PWMLED_CMD_GET_BRIGHTNESS:return pwmled.brightness;default:return -EINVAL;}return 0;
}// 文件操作结构体
static struct file_operations fops = {.owner = THIS_MODULE,.unlocked_ioctl = pwmled_ioctl,
};// 杂项设备结构体
static struct miscdevice pwmled_misc = {.minor = MISC_DYNAMIC_MINOR,.name = "pwmled",.fops = &fops,
};// 模块初始化函数
int __init pwmled_init(void) {int ret;// 请求PWM通道0(根据实际硬件修改通道号)pwmled.pwm = pwm_request(0, "pwmled");if (IS_ERR(pwmled.pwm)) {ret = PTR_ERR(pwmled.pwm);printk(KERN_ERR "Failed to request PWM channel\n");return ret;}// 初始化亮度为0pwmled.brightness = 0;// 注册杂项设备ret = misc_register(&pwmled_misc);if (ret < 0) {printk(KERN_ERR "Failed to register misc device\n");pwm_free(pwmled.pwm);return ret;}printk(KERN_INFO "PWM LED driver initialized\n");return 0;
}// 模块退出函数
void __exit pwmled_exit(void) {// 禁用PWMpwm_disable(pwmled.pwm);// 释放PWM资源pwm_free(pwmled.pwm);// 注销杂项设备misc_deregister(&pwmled_misc);printk(KERN_INFO "PWM LED driver unloaded\n");
}module_init(pwmled_init);
module_exit(pwmled_exit);
3. 编译驱动(Makefile)
obj-m += pwmled.oall:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
4. 加载驱动与测试
步骤 1:编译并加载驱动
# 编译驱动
make
# 加载驱动
sudo insmod pwmled.ko
步骤 2:查看设备节点
ls /dev/pwmled
步骤 3:编写测试程序
import os
import fcntl# 定义IOCTL命令
PWMLED_CMD_SET_BRIGHTNESS = 0x1
PWMLED_CMD_GET_BRIGHTNESS = 0x2# 打开设备文件
fd = os.open("/dev/pwmled", os.O_RDWR)
if fd < 0:print("Failed to open /dev/pwmled")exit(1)try:# 设置亮度(0~1000)brightness = 500print(f"设置亮度为: {brightness}")fcntl.ioctl(fd, PWMLED_CMD_SET_BRIGHTNESS, brightness)# 等待5秒time.sleep(5)# 获取当前亮度current_brightness = fcntl.ioctl(fd, PWMLED_CMD_GET_BRIGHTNESS)print(f"当前亮度: {current_brightness}")finally:# 关闭设备文件os.close(fd)
步骤 4:卸载驱动
sudo rmmod pwmled