上传文件至 /
This commit is contained in:
parent
6dc255fc2d
commit
4d14308da2
40
README.md
40
README.md
@ -306,7 +306,8 @@ pinball_exp_rp5/
|
|||||||
├── drv_encodermotor.py # 编码器电机驱动模块 — 控制圆柱旋转(I2C 通信)
|
├── drv_encodermotor.py # 编码器电机驱动模块 — 控制圆柱旋转(I2C 通信)
|
||||||
├── drv_stepmotor.py # 步进电机驱动模块 — 控制圆柱平移(I2C + PWM)
|
├── drv_stepmotor.py # 步进电机驱动模块 — 控制圆柱平移(I2C + PWM)
|
||||||
│
|
│
|
||||||
├── test.ipynb # 教学演示 Notebook(Jupyter 笔记本)
|
├── test.ipynb # 教学演示 Notebook(Jupyter 笔记本,可在 VS Code 中直接打开)
|
||||||
|
├── demo.py # 精简版演示脚本(一个文件涵盖所有模块,适合快速上手)
|
||||||
└── signal_features.json # 实验信号参数(已脱敏处理)
|
└── signal_features.json # 实验信号参数(已脱敏处理)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -314,26 +315,49 @@ pinball_exp_rp5/
|
|||||||
|
|
||||||
## 8. 如何运行
|
## 8. 如何运行
|
||||||
|
|
||||||
|
本项目提供了两种运行方式:
|
||||||
|
|
||||||
|
### 方式一:运行 `demo.py`(最简方式)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. 激活虚拟环境(如果之前创建了虚拟环境)
|
# 1. 激活虚拟环境(如果之前创建了虚拟环境)
|
||||||
source venv/bin/activate
|
source venv/bin/activate
|
||||||
|
|
||||||
# 2. 启动 Jupyter Notebook
|
# 2. 直接运行 demo.py
|
||||||
|
python3 demo.py
|
||||||
|
```
|
||||||
|
|
||||||
|
`demo.py` 是一个精简的演示脚本,把所有功能写在一个文件里,运行后会自动在终端打印每一步的说明。适合第一次接触本项目时快速了解全貌。
|
||||||
|
|
||||||
|
### 方式二:在 VS Code / Jupyter Notebook 中打开 `test.ipynb`
|
||||||
|
|
||||||
|
`test.ipynb` 是 Jupyter Notebook 格式的文件,把文字说明和代码分块组织在一起,更适合逐步学习。
|
||||||
|
|
||||||
|
**在 VS Code 中打开:**
|
||||||
|
|
||||||
|
如果你使用 VS Code(推荐),直接双击 `test.ipynb` 文件即可在 VS Code 中打开。VS Code 内置了对 `.ipynb` 文件的支持,无需额外安装 Jupyter 服务器。打开后:
|
||||||
|
|
||||||
|
- 每个代码块(Cell)左侧有一个 ▶ 播放按钮,点击即可运行
|
||||||
|
- 也可以按 `Shift + Enter` 运行当前 Cell 并跳转到下一个
|
||||||
|
- 运行结果会直接显示在 Cell 下方
|
||||||
|
|
||||||
|
**在浏览器中使用 Jupyter Notebook:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 激活虚拟环境(如果之前创建了虚拟环境)
|
||||||
|
source venv/bin/activate
|
||||||
|
|
||||||
|
# 2. 启动 Jupyter Notebook 服务器
|
||||||
jupyter notebook
|
jupyter notebook
|
||||||
|
|
||||||
# 3. 终端会显示一个链接(类似 http://127.0.0.1:8888/),
|
# 3. 终端会显示一个链接(类似 http://127.0.0.1:8888/),
|
||||||
# 用浏览器打开这个链接
|
# 用浏览器打开这个链接
|
||||||
|
|
||||||
# 4. 在浏览器中点击 test.ipynb 文件
|
# 4. 在浏览器中点击 test.ipynb 文件
|
||||||
|
|
||||||
# 5. 在 Notebook 中按顺序从上到下运行每个 Cell(代码单元格):
|
|
||||||
# - 点击一个 Cell 选中它
|
|
||||||
# - 按 Shift + Enter 运行当前 Cell 并自动跳转到下一个
|
|
||||||
# - 也可以点工具栏上的 "Run" 按钮
|
|
||||||
```
|
```
|
||||||
|
|
||||||
> **什么是 Jupyter Notebook?**
|
> **什么是 Jupyter Notebook?**
|
||||||
> Jupyter Notebook 是一种交互式的编程环境,把代码、运行结果、文字说明放在一个文件(`.ipynb`)中。每个代码块叫做一个"Cell",可以单独运行,非常适合教学和实验。
|
> Jupyter Notebook 是一种交互式的编程环境,把代码、运行结果、文字说明放在一个文件(`.ipynb`)中。每个代码块叫做一个"Cell",可以单独运行,非常适合教学和实验。VS Code 也支持直接打开 `.ipynb` 文件。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
244
demo.py
Normal file
244
demo.py
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
"""
|
||||||
|
============================================================================
|
||||||
|
圆柱水槽控制系统 — 精简演示脚本
|
||||||
|
============================================================================
|
||||||
|
|
||||||
|
本脚本演示三个驱动模块的基本用法,适合第一次接触本项目时快速了解全貌。
|
||||||
|
|
||||||
|
运行方式:
|
||||||
|
python3 demo.py
|
||||||
|
|
||||||
|
注意事项:
|
||||||
|
⚠️ 所有涉及真实硬件的操作都会打印 [需要硬件] 标记。
|
||||||
|
如果你没有连接实际硬件,可以阅读代码和打印输出来了解流程。
|
||||||
|
============================================================================
|
||||||
|
"""
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 第一步:导入依赖
|
||||||
|
# ============================================================
|
||||||
|
# 导入时间模块,用于延时和计时
|
||||||
|
import time
|
||||||
|
# 导入数学模块,用于数学计算(如正弦函数)
|
||||||
|
import math
|
||||||
|
|
||||||
|
# 导入三个驱动模块(请确保这些 .py 文件与本脚本在同一目录下)
|
||||||
|
# 编码器电机驱动 — 控制圆柱旋转
|
||||||
|
from drv_encodermotor import EncoderMotorDriver, SPEED_MODE
|
||||||
|
# 步进电机驱动 — 控制圆柱平移
|
||||||
|
from drv_stepmotor import StepMotorDriver
|
||||||
|
# ADC 驱动 — 采集应变片电压信号
|
||||||
|
from drv_adc import ADS124S08
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 第二步:EncoderMotor(编码器电机)演示 — 控制圆柱旋转
|
||||||
|
# ============================================================
|
||||||
|
def demo_encodermotor():
|
||||||
|
"""
|
||||||
|
演示编码器电机的速度控制流程。
|
||||||
|
通过 I2C 总线与 M5Stack 4EncoderMotor 模块通信。
|
||||||
|
"""
|
||||||
|
print("=" * 60)
|
||||||
|
print("【EncoderMotor】编码器电机演示 — 控制圆柱旋转")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# 使用 with 语句创建驱动实例,退出后自动释放 I2C 资源
|
||||||
|
# bus=1 表示使用树莓派的 I2C 总线 1(/dev/i2c-1)
|
||||||
|
with EncoderMotorDriver(bus=1) as driver:
|
||||||
|
|
||||||
|
# 1. 设置通道 0 为速度模式(SPEED_MODE)
|
||||||
|
# 速度模式下,电机会自动维持设定的目标转速
|
||||||
|
print(" [需要硬件] 设置通道 0 为速度模式...")
|
||||||
|
driver.set_mode(0, SPEED_MODE)
|
||||||
|
|
||||||
|
# 2. 配置速度 PID 参数
|
||||||
|
# kp(比例)、ki(积分)、kd(微分)配合使速度控制更精确
|
||||||
|
print(" [需要硬件] 配置 PID 参数 (kp=1, ki=100, kd=1)...")
|
||||||
|
driver.set_speed_pid(0, kp=1, ki=100, kd=1)
|
||||||
|
|
||||||
|
# 3. 启用软启停功能,让电机加减速更平滑
|
||||||
|
print(" [需要硬件] 启用软启停...")
|
||||||
|
driver.set_soft_start_and_stop(0, True)
|
||||||
|
|
||||||
|
# 4. 设置目标线速度(单位:米/秒)
|
||||||
|
# 正数 = 正转,负数 = 反转
|
||||||
|
print(" [需要硬件] 设定目标速度:0.02 m/s")
|
||||||
|
driver.set_linear_speed_m_s(0, 0.02)
|
||||||
|
|
||||||
|
# 等待 1 秒让电机跑起来
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# 5. 读取编码器数值(电机转过的脉冲数)
|
||||||
|
print(" [需要硬件] 读取编码器数值...")
|
||||||
|
encoder_val = driver.get_encoder_value(0)
|
||||||
|
print(f" 编码器数值:{encoder_val}")
|
||||||
|
|
||||||
|
# 6. 读取电机总电流
|
||||||
|
print(" [需要硬件] 读取电机电流...")
|
||||||
|
current = driver.get_motor_current()
|
||||||
|
print(f" 总电流:{current:.4f} A")
|
||||||
|
|
||||||
|
# 7. 速度归零,停止电机
|
||||||
|
print(" [需要硬件] 停止电机...")
|
||||||
|
driver.set_linear_speed_m_s(0, 0.0)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# 退出 with 语句块,I2C 连接自动关闭
|
||||||
|
print(" [完成] EncoderMotor 演示结束,资源已释放\n")
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 第三步:StepMotor(步进电机)演示 — 控制圆柱平移
|
||||||
|
# ============================================================
|
||||||
|
def demo_stepmotor():
|
||||||
|
"""
|
||||||
|
演示步进电机的控制流程。
|
||||||
|
通过 I2C + 硬件 PWM 与 M5Stack StepMotor Driver 模块通信。
|
||||||
|
三个步进电机共享同一路 PWM 脉冲,但方向可独立控制。
|
||||||
|
"""
|
||||||
|
print("=" * 60)
|
||||||
|
print("【StepMotor】步进电机演示 — 控制圆柱平移")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# 创建驱动实例(这里演示用 try/finally 手动释放资源)
|
||||||
|
drv = StepMotorDriver()
|
||||||
|
try:
|
||||||
|
# 1. 使能电机 — 让电机驱动芯片开始接收脉冲
|
||||||
|
print(" [需要硬件] 使能电机...")
|
||||||
|
drv.enable_motor()
|
||||||
|
|
||||||
|
# 2. 复位所有 3 个电机通道(恢复到初始状态)
|
||||||
|
print(" [需要硬件] 复位所有电机通道...")
|
||||||
|
for i in range(3):
|
||||||
|
drv.reset_motor(i, True)
|
||||||
|
|
||||||
|
# 3. 设置运动方向(True=正向,False=反向)
|
||||||
|
print(" [需要硬件] 设置方向为正向...")
|
||||||
|
drv.set_dir(True)
|
||||||
|
|
||||||
|
# 4. S 曲线加速启动(速度 0.02 m/s,用 0.1 秒加速到目标)
|
||||||
|
# 加速曲线用了余弦函数,非常平滑
|
||||||
|
drv.ramp_time = 0.1 # 为了演示,把加减速时间设短
|
||||||
|
print(" [需要硬件] S 曲线加速启动 (0.02 m/s)...")
|
||||||
|
drv.start(0.02)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# 5. 在运行中切换速度(0.04 m/s)
|
||||||
|
print(" [需要硬件] 切换速度 (0.04 m/s)...")
|
||||||
|
drv.change_speed(0.04)
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
# 6. S 曲线减速停止
|
||||||
|
print(" [需要硬件] S 曲线减速停止...")
|
||||||
|
drv.stop()
|
||||||
|
|
||||||
|
print(" [完成] StepMotor 演示结束\n")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# 释放资源(停止电机、关闭 I2C 和 PWM)
|
||||||
|
drv.close()
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 第四步:ADC(模数转换器)演示 — 采集电压信号
|
||||||
|
# ============================================================
|
||||||
|
def demo_adc():
|
||||||
|
"""
|
||||||
|
演示 ADC 的数据采集流程。
|
||||||
|
通过 SPI 总线与 ADS124S08 芯片通信,读取应变片电压信号。
|
||||||
|
"""
|
||||||
|
print("=" * 60)
|
||||||
|
print("【ADC】模数转换器演示 — 采集电压信号")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# 创建 ADC 实例(构造函数会自动完成上电和初始化)
|
||||||
|
adc = ADS124S08()
|
||||||
|
try:
|
||||||
|
# 1. 配置 PGA(可编程增益放大器)
|
||||||
|
# pga_en=1 启用放大,gain=5 对应 ×32 倍
|
||||||
|
print(" [需要硬件] 配置 PGA (×32 倍)...")
|
||||||
|
adc.set_pga(pga_en=1, gain=5)
|
||||||
|
|
||||||
|
# 2. 配置数据速率和转换模式
|
||||||
|
# dr=8 对应 200 SPS(每秒 200 次采样)
|
||||||
|
# mode=1 单次转换模式(每次触发转换一次)
|
||||||
|
print(" [需要硬件] 配置数据速率 (200 SPS, 单次模式)...")
|
||||||
|
adc.set_datarate(dr=8, mode=1)
|
||||||
|
|
||||||
|
# 3. 读取三个通道(0, 1, 2)的数据
|
||||||
|
# 返回 24 位有符号整数的列表
|
||||||
|
print(" [需要硬件] 读取通道 0/1/2...")
|
||||||
|
channels = [0, 1, 2]
|
||||||
|
raw_values = adc.request_channels(channels=channels)
|
||||||
|
print(f" 原始采样值:{raw_values}")
|
||||||
|
|
||||||
|
# 4. 将 ADC 原始值转换为电压
|
||||||
|
print(" 转换为电压值:")
|
||||||
|
for ch, raw in zip(channels, raw_values):
|
||||||
|
voltage = adc.convert_to_voltage(raw)
|
||||||
|
print(f" 通道 {ch}:{voltage:.6f} V")
|
||||||
|
|
||||||
|
print(" [完成] ADC 演示结束\n")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# 关闭 SPI 总线,释放 GPIO 引脚
|
||||||
|
adc.close()
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 第五步:信号生成演示(纯数学计算,无需硬件)
|
||||||
|
# ============================================================
|
||||||
|
def demo_signal_generation():
|
||||||
|
"""
|
||||||
|
演示如何根据频率分量合成周期运动信号。
|
||||||
|
这是控制循环中的核心算法,不需要硬件即可运行。
|
||||||
|
"""
|
||||||
|
print("=" * 60)
|
||||||
|
print("【信号合成】周期运动信号生成演示(纯软件,无需硬件)")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# 定义一组简化的信号特征(包含均值 + 两个正弦波分量)
|
||||||
|
signal_feature = {
|
||||||
|
"mean": 0.0, # 均值(直流分量)
|
||||||
|
"components": [ # 正弦波分量列表
|
||||||
|
(0.27, 0.005, -1.5), # (频率Hz, 幅值, 相位rad)
|
||||||
|
(0.81, 0.001, 2.8), # (频率Hz, 幅值, 相位rad)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
# 在 3 秒内每隔 0.5 秒生成一个信号值
|
||||||
|
print(" 时间(s) | 信号值(m/s) ")
|
||||||
|
print(" -------|-------------")
|
||||||
|
t = 0.0
|
||||||
|
while t <= 3.0:
|
||||||
|
# 合成信号:均值 + 各正弦分量之和
|
||||||
|
value = signal_feature["mean"]
|
||||||
|
for freq, amp, phase in signal_feature["components"]:
|
||||||
|
value += amp * math.cos(2 * math.pi * freq * t + phase)
|
||||||
|
print(f" {t:5.1f} | {value:+.6f}")
|
||||||
|
t += 0.5
|
||||||
|
|
||||||
|
print(" [完成] 信号合成演示结束\n")
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# 主程序入口
|
||||||
|
# ============================================================
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print()
|
||||||
|
print("⏺ 圆柱水槽控制系统 — 精简演示")
|
||||||
|
print("⏺ 本脚本将逐个演示三个驱动模块和信号生成功能")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# 逐个执行演示(按顺序注释掉可以单独运行某个演示)
|
||||||
|
demo_encodermotor()
|
||||||
|
demo_stepmotor()
|
||||||
|
demo_adc()
|
||||||
|
demo_signal_generation()
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print("所有演示已完成。")
|
||||||
|
print("提示:运行 test.ipynb 可以获得更详细的分步讲解。")
|
||||||
|
print("=" * 60)
|
||||||
|
print()
|
||||||
Loading…
Reference in New Issue
Block a user