672 lines
24 KiB
Markdown
672 lines
24 KiB
Markdown
# 树莓派 5 圆柱运动控制系统
|
||
|
||
> 本项目运行在 **Raspberry Pi 5**(树莓派 5)上,通过多种通信协议控制三个圆柱在水槽中的运动,并实时测量受力情况。
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
1. [项目简介](#1-项目简介)
|
||
2. [整体架构](#2-整体架构)
|
||
3. [什么是树莓派(Raspberry Pi)?](#3-什么是树莓派raspberry-pi)
|
||
4. [GPIO 概念](#4-gpio-概念)
|
||
5. [通信协议简介](#5-通信协议简介)
|
||
6. [Python 环境搭建](#6-python-环境搭建)
|
||
7. [项目文件结构](#7-项目文件结构)
|
||
8. [如何运行](#8-如何运行)
|
||
9. [三个驱动模块详解](#9-三个驱动模块详解)
|
||
10. [signal_features.json 说明](#10-signal_featuresjson-说明)
|
||
11. [常见问题 FAQ](#11-常见问题-faq)
|
||
12. [参考资料](#12-参考资料)
|
||
|
||
---
|
||
|
||
## 1. 项目简介
|
||
|
||
这是一个在 **Raspberry Pi 5** 上运行的控制系统,用于在水槽中控制三个圆柱的运动并测量受力。系统通过以下方式工作:
|
||
|
||
- 三个**空心杯电机**(带编码器反馈)控制圆柱的**旋转**
|
||
- 三个**步进电机**控制圆柱的**直线移动**
|
||
- 一个**高精度 ADC**(模数转换器)测量应变片传来的电压信号,从而算出受力大小
|
||
|
||
---
|
||
|
||
## 2. 整体架构
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────────┐
|
||
│ Raspberry Pi 5 │
|
||
│ │
|
||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
|
||
│ │ SPI 总线 │ │ I2C 总线 │ │ 硬件 PWM │ │
|
||
│ │ /dev/spidev0.0│ │ /dev/i2c-1 │ │ GPIO12 输出 │ │
|
||
│ └───────┬───────┘ └──────┬───────┘ └──────────┬───────────┘ │
|
||
│ │ │ │ │
|
||
└───────────┼───────────────────┼────────────────────────┼──────────────┘
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
||
│ ADS124S08 │ │ 4EncoderMotor │ │ StepMotor Driver │
|
||
│ ADC 芯片 │ │ 电机模块 (I2C) │ │ (I2C + PWM) │
|
||
│ (SPI 通信) │ │ 地址: 0x24 │ │ 地址: 0x27 │
|
||
└──────┬───────┘ └────────┬─────────┘ └────────┬─────────┘
|
||
│ │ │
|
||
▼ ▼ ▼
|
||
应变片信号 空心杯电机 (×4) 步进电机 (×3)
|
||
(电压测量) (控制圆柱旋转) (控制圆柱平移)
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 什么是树莓派(Raspberry Pi)?
|
||
|
||
树莓派是一台只有**信用卡大小**的 Linux 计算机。它虽然小,但具备普通电脑的所有功能——有 CPU、内存、USB 接口、HDMI 视频输出、网络接口等。树莓派最特别的地方是它有一排**GPIO 引脚**,可以通过这些引脚直接控制外部电子设备(比如电机、传感器、灯光等)。
|
||
|
||
### 本项目使用的型号:Raspberry Pi 5
|
||
|
||
### 树莓派引脚图
|
||
|
||
树莓派 5 的 40 针 GPIO 排针布局如下(从上方俯视,SD 卡槽朝上):
|
||
|
||
```
|
||
3.3V (1) (2) 5V
|
||
GPIO2 (SDA) (3) (4) 5V
|
||
GPIO3 (SCL) (5) (6) GND
|
||
GPIO4 (7) (8) GPIO14 (TXD)
|
||
GND (9) (10) GPIO15 (RXD)
|
||
GPIO17 (11)(12) GPIO18
|
||
GPIO27 (13)(14) GND
|
||
GPIO22 (15)(16) GPIO23
|
||
3.3V (17)(18) GPIO24
|
||
GPIO10(MOSI)(19)(20) GND
|
||
GPIO9(MISO)(21)(22) GPIO25
|
||
GPIO11(SCLK)(23)(24) GPIO8 (CS)
|
||
GND (25)(26) GPIO7 (CS1)
|
||
GPIO0(IDSD)(27)(28) GPIO1 (IDSC)
|
||
GPIO5 (29)(30) GND
|
||
GPIO6 (31)(32) GPIO12 (PWM)
|
||
GPIO13 (33)(34) GND
|
||
GPIO19 (35)(36) GPIO16
|
||
GPIO26 (37)(38) GPIO20
|
||
GND (39)(40) GPIO21
|
||
```
|
||
|
||
> 详细引脚功能说明请参考:[树莓派官方引脚文档](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html)
|
||
|
||
---
|
||
|
||
## 4. GPIO 概念
|
||
|
||
### 什么是 GPIO?
|
||
|
||
GPIO 是 **General Purpose Input Output**(通用输入输出引脚)的缩写。可以把 GPIO 引脚想象成树莓派身上伸出来的"小触手",每个触手可以:
|
||
|
||
- **输出高电平(3.3V)或低电平(0V)**:相当于开或关一个开关
|
||
- **检测外部电平是高还是低**:相当于感应外部有没有电信号
|
||
|
||
### 高电平和低电平
|
||
|
||
- **高电平(HIGH / 1 / 3.3V)**:引脚输出 3.3 伏特的电压,相当于"开"
|
||
- **低电平(LOW / 0 / 0V)**:引脚输出 0 伏特的电压,相当于"关"
|
||
|
||
简单来说,树莓派通过把 GPIO 引脚设置为高电平或低电平,来控制外部设备。比如把某个引脚设为高电平,就等于告诉连接的设备"开始工作"。
|
||
|
||
### 本项目中使用的 GPIO 引脚
|
||
|
||
| 引脚 (BCM) | 功能 | 连接设备 |
|
||
|---|---|---|
|
||
| GPIO12 | PWM 输出(产生步进脉冲) | StepMotor 模块 |
|
||
| GPIO5 | 步进电机 0 方向控制 | StepMotor 模块 |
|
||
| GPIO6 | 步进电机 1 方向控制 | StepMotor 模块 |
|
||
| GPIO16 | 步进电机 2 方向控制 | StepMotor 模块 |
|
||
| GPIO22 | 电源阶段 1 控制(先供电) | ADC (ADS124S08) |
|
||
| GPIO17 | 电源阶段 1 控制(先供电) | ADC |
|
||
| GPIO24 | 电源阶段 2 控制(后供电) | ADC |
|
||
| GPIO27 | 电源阶段 2 控制(后供电) | ADC |
|
||
| GPIO23 | 保持低电平(初始化期间) | ADC |
|
||
| GPIO18 | 保持低电平(初始化期间) | ADC |
|
||
| GPIO25 | DRDY 输入(检测ADC数据就绪) | ADC |
|
||
| GPIO10 | SPI MOSI(主出从入) | ADC |
|
||
| GPIO9 | SPI MISO(主入从出) | ADC |
|
||
| GPIO11 | SPI SCLK(时钟线) | ADC |
|
||
| GPIO8 | SPI CS(片选,低电平选中) | ADC |
|
||
| GPIO2 | I2C SDA(数据线) | 电机模块 |
|
||
| GPIO3 | I2C SCL(时钟线) | 电机模块 |
|
||
|
||
> BCM 编号是 Broadcom 芯片的 GPIO 编号方式,也是 Python 库(如 gpiozero)默认使用的编号方式。
|
||
|
||
---
|
||
|
||
## 5. 通信协议简介
|
||
|
||
### 5.1 SPI(Serial Peripheral Interface,串行外设接口)
|
||
|
||
#### 是什么
|
||
|
||
SPI 是一种**同步串行通信协议**,用 **4 根线**连接主设备(这里是树莓派)和从设备(这里是 ADC 芯片)。
|
||
|
||
#### 四根线的比喻
|
||
|
||
把 SPI 通信想象成老师和学生对话:
|
||
|
||
| 线名 | 全称 | 比喻 |
|
||
|---|---|---|
|
||
| **SCLK** | Serial Clock(串行时钟) | 老师用**节拍器**打拍子,所有人按这个节奏说话 |
|
||
| **MOSI** | Master Out Slave In(主出从入) | **老师对学生说话**的通道 |
|
||
| **MISO** | Master In Slave Out(主入从出) | **学生对老师说话**的通道 |
|
||
| **CS** | Chip Select(片选) | 老师**点名**:喊谁的名字(拉低电平),谁就说话 |
|
||
|
||
> **CS 低电平有效**:当 CS 线从高电平变为低电平时,表示"我要跟你说话了";当 CS 线回到高电平时,表示"对话结束"。
|
||
|
||
#### 为什么 ADC 用 SPI?
|
||
|
||
- **速度快**:SPI 时钟频率可达几十 MHz,适合高速数据读取
|
||
- **全双工**:可以同时发送和接收数据(就像两个人可以同时说话和听)
|
||
- 高精度 ADC(如 ADS124S08)需要快速、可靠地传输 24 位数据,SPI 非常适合
|
||
|
||
#### 本项目中的 SPI
|
||
|
||
- **主设备**:树莓派 5
|
||
- **从设备**:ADS124S08 ADC 芯片
|
||
- **总线路径**:`/dev/spidev0.0`(总线 0,设备 0)
|
||
- **时钟频率**:1 MHz(每秒传输 1,000,000 位数据)
|
||
- **SPI 模式**:模式 1(CPOL=0,CPHA=1)
|
||
|
||
---
|
||
|
||
### 5.2 I2C(Inter-Integrated Circuit,内部集成电路)
|
||
|
||
#### 是什么
|
||
|
||
I2C 是一种**同步串行通信协议**,只用 **2 根线**就可以连接多个设备。
|
||
|
||
#### 两根线的比喻
|
||
|
||
I2C 像学校的**广播系统**:
|
||
|
||
| 线名 | 全称 | 比喻 |
|
||
|---|---|---|
|
||
| **SDA** | Serial Data(串行数据线) | 广播的**话筒和喇叭**,说话和听话都用这一根 |
|
||
| **SCL** | Serial Clock(串行时钟线) | 广播的**节拍信号**,控制说话的节奏 |
|
||
|
||
所有设备都接在同一对线上,但每个设备都有一个唯一的**地址**(就像一个班每个学生有**学号**)。主机喊学号,对应学号的设备才应答;其他设备保持安静。
|
||
|
||
#### 为什么电机模块用 I2C?
|
||
|
||
- **接线简单**:只需要两根线,可以挂多个设备(每个设备用不同地址区分)
|
||
- **设备数量**:理论上一个 I2C 总线上最多可以连接 127 个设备
|
||
- 电机控制不需要极快的数据传输速度,I2C 完全够用
|
||
|
||
#### 本项目中的 I2C
|
||
|
||
| 设备 | I2C 地址 | 用途 |
|
||
|---|---|---|
|
||
| 4EncoderMotor 模块 | **0x24** | 控制空心杯电机旋转 |
|
||
| StepMotor Driver 模块 | **0x27** | 配置步进电机(使能/复位等) |
|
||
|
||
树莓派通过 `/dev/i2c-1`(I2C 总线 1)与这两个模块通信。
|
||
|
||
---
|
||
|
||
### 5.3 PWM(Pulse Width Modulation,脉冲宽度调制)
|
||
|
||
#### 是什么
|
||
|
||
PWM 是一种通过**快速开关信号**来模拟不同电压输出的技术。就像快速眨眼——如果你半睁半闭眼睛,看起来就像在"眯着眼";PWM 也是类似的道理。
|
||
|
||
#### 两个重要参数
|
||
|
||
| 参数 | 含义 | 比喻 |
|
||
|---|---|---|
|
||
| **频率 (Frequency)** | 每秒开关多少次,单位 Hz(赫兹) | 每秒眨眼的次数 |
|
||
| **占空比 (Duty Cycle)** | 高电平时间占一个周期的比例 | 每次眨眼时,眼睛闭着的时间比例——80% 闭着 = 20% 占空比 |
|
||
|
||
比如:频率 1000 Hz = 每秒开关 1000 次。占空比 50% = 一半时间通(高电平),一半时间断(低电平)。
|
||
|
||
#### 为什么步进电机用 PWM?
|
||
|
||
步进电机是一种特殊的电机,**每收到一个脉冲就走一步**。所以:
|
||
|
||
- PWM 的频率越高 → 脉冲来得越快 → 电机转速越快
|
||
- PWM 的频率越低 → 脉冲来得越慢 → 电机转速越慢
|
||
|
||
树莓派的**硬件 PWM**(由专用硬件产生,不受 CPU 负载影响)通过 GPIO12 引脚输出脉冲,经过 StepMotor 模块驱动步进电机。
|
||
|
||
---
|
||
|
||
## 6. Python 环境搭建
|
||
|
||
### 6.1 检查环境
|
||
|
||
树莓派 OS(操作系统)自带 Python 3。打开终端(Terminal),输入以下命令检查版本:
|
||
|
||
```bash
|
||
python3 --version
|
||
```
|
||
|
||
如果显示类似 `Python 3.11.x` 或更高版本,说明 Python 已安装。
|
||
|
||
### 6.2 创建虚拟环境(推荐)
|
||
|
||
虚拟环境可以把本项目的 Python 依赖与你电脑上的其他项目隔离开,避免版本冲突。
|
||
|
||
```bash
|
||
# 进入项目文件夹
|
||
cd pinball_exp_rp5
|
||
|
||
# 创建虚拟环境(在项目根目录下生成 venv 文件夹)
|
||
python3 -m venv venv
|
||
|
||
# 激活虚拟环境
|
||
source venv/bin/activate
|
||
|
||
# 激活后,终端提示符前面会出现 (venv) 字样
|
||
```
|
||
|
||
> 以后每次使用本项目,都先运行 `source venv/bin/activate` 来激活虚拟环境。
|
||
|
||
### 6.3 安装依赖
|
||
|
||
首先确保 `requirements.txt` 文件在项目根目录下,然后运行:
|
||
|
||
```bash
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
#### 各依赖库的作用
|
||
|
||
| 库名 | 作用 | 安装方式 |
|
||
|---|---|---|
|
||
| **spidev** | 操作 SPI 总线的 Python 库。树莓派通过它跟 ADC 芯片通信。 | `pip install spidev` |
|
||
| **smbus2** | 操作 I2C 总线的 Python 库。树莓派通过它跟电机模块通信。 | `pip install smbus2` |
|
||
| **RPi.GPIO** | 控制 GPIO 引脚的经典库(可选)。本项目中主要用 gpiozero 代替。 | `pip install RPi.GPIO` |
|
||
| **gpiozero** | 简化版的 GPIO 控制库。Raspberry Pi OS 自带,无需额外安装。 | 系统自带 |
|
||
| **rpi_hardware_pwm** | 控制树莓派硬件 PWM 输出的库,用于步进电机的脉冲产生。 | `pip install rpi_hardware_pwm` |
|
||
| **jupyter** | 运行 `.ipynb` 笔记本文件的环境,可以在浏览器中交互式运行代码。 | `pip install jupyter` |
|
||
| **matplotlib** | 绘图库,`test.ipynb` 中用它将 ADC 采集的数据画成图表。 | `pip install matplotlib` |
|
||
|
||
> **注意**:`rpi_hardware_pwm` 和 `matplotlib` 不在 `requirements.txt` 中,需要单独安装。
|
||
|
||
```bash
|
||
# 如果上面的安装命令执行完后还缺少某些库,可以手动补装:
|
||
pip install rpi_hardware_pwm matplotlib jupyter
|
||
```
|
||
|
||
---
|
||
|
||
## 7. 项目文件结构
|
||
|
||
```
|
||
pinball_exp_rp5/
|
||
│
|
||
├── README.md # 本文件 — 项目说明(你正在读的这份文档)
|
||
├── requirements.txt # Python 依赖列表(自动安装用)
|
||
│
|
||
├── drv_adc.py # ADC 驱动模块 — 采集电压信号(SPI 通信)
|
||
├── drv_encodermotor.py # 编码器电机驱动模块 — 控制圆柱旋转(I2C 通信)
|
||
├── drv_stepmotor.py # 步进电机驱动模块 — 控制圆柱平移(I2C + PWM)
|
||
│
|
||
├── test.ipynb # 教学演示 Notebook(Jupyter 笔记本)
|
||
└── signal_features.json # 实验信号参数(已脱敏处理)
|
||
```
|
||
|
||
---
|
||
|
||
## 8. 如何运行
|
||
|
||
```bash
|
||
# 1. 激活虚拟环境(如果之前创建了虚拟环境)
|
||
source venv/bin/activate
|
||
|
||
# 2. 启动 Jupyter Notebook
|
||
jupyter notebook
|
||
|
||
# 3. 终端会显示一个链接(类似 http://127.0.0.1:8888/),
|
||
# 用浏览器打开这个链接
|
||
|
||
# 4. 在浏览器中点击 test.ipynb 文件
|
||
|
||
# 5. 在 Notebook 中按顺序从上到下运行每个 Cell(代码单元格):
|
||
# - 点击一个 Cell 选中它
|
||
# - 按 Shift + Enter 运行当前 Cell 并自动跳转到下一个
|
||
# - 也可以点工具栏上的 "Run" 按钮
|
||
```
|
||
|
||
> **什么是 Jupyter Notebook?**
|
||
> Jupyter Notebook 是一种交互式的编程环境,把代码、运行结果、文字说明放在一个文件(`.ipynb`)中。每个代码块叫做一个"Cell",可以单独运行,非常适合教学和实验。
|
||
|
||
---
|
||
|
||
## 9. 三个驱动模块详解
|
||
|
||
### 9.1 ADC 模块(`drv_adc.py`)
|
||
|
||
#### 控制芯片
|
||
|
||
**TI ADS124S08** —— 这是一款 24 位高精度模数转换器(ADC)。
|
||
|
||
- **24 位**意味着它可以分辨非常微小的电压变化(最小可分辨约 0.3 微伏)
|
||
- 可以把连续的模拟电压信号转换成计算机可以处理的数字信号
|
||
- 本项目中用于读取应变片经放大后的电压信号,从而计算受力
|
||
|
||
#### 通信方式
|
||
|
||
SPI 总线,路径:`/dev/spidev0.0`
|
||
|
||
#### 为什么要分两步给 ADC 上电?
|
||
|
||
ADS124S08 芯片的模拟电路和数字电路需要按照特定顺序启动。如果同时上电,芯片内部状态可能不稳定。所以驱动程序先启动第一部分电源(Stage 1),等待 100ms 让电源稳定后,再启动第二部分电源(Stage 2)。
|
||
|
||
#### 典型调用流程
|
||
|
||
```python
|
||
from drv_adc import ADS124S08
|
||
|
||
# 1. 创建 ADC 对象(自动完成上电和初始化)
|
||
adc = ADS124S08()
|
||
|
||
# 2. 配置可编程增益放大器(PGA)
|
||
# pga_en=1: 启用放大 gain=5: 放大 32 倍
|
||
adc.set_pga(pga_en=1, gain=5)
|
||
|
||
# 3. 配置采样率
|
||
# dr=8: 200 SPS(每秒采样 200 次) mode=1: 单次转换模式
|
||
adc.set_datarate(dr=8, mode=1)
|
||
|
||
# 4. 选择要测量的输入通道(单端模式,以 AINCOM 为公共端)
|
||
# 这里选择通道 0(AIN0 引脚)
|
||
adc.set_input_mux(pos_channel=0)
|
||
|
||
# 5. 读取多个通道的电压原始值
|
||
values = adc.request_channels([0, 1, 2])
|
||
|
||
# 6. 清理(关闭 SPI 总线,关掉 GPIO 电源)
|
||
adc.close()
|
||
```
|
||
|
||
#### 几个重要的配置
|
||
|
||
**PGA 增益倍数对照表:**
|
||
|
||
| gain 编码 | 实际放大倍数 | 适用信号 |
|
||
|---|---|---|
|
||
| 0 | ×1 | 强信号(>1V) |
|
||
| 1 | ×2 | 中等信号 |
|
||
| 2 | ×4 | 中等信号 |
|
||
| 3 | ×8 | 较弱信号 |
|
||
| 4 | ×16 | 弱信号 |
|
||
| 5 | ×32 | 微弱信号(如应变片) |
|
||
| 6 | ×64 | 极微弱信号 |
|
||
| 7 | ×128 | 最微弱信号 |
|
||
|
||
**数据速率对照表:**
|
||
|
||
| dr 编码 | 实际速率(SPS) | 每次采样等待时间 |
|
||
|---|---|---|
|
||
| 0 | 2.5 | 400 ms |
|
||
| 4 | 20 | 50 ms |
|
||
| 8 | 200 | 5 ms |
|
||
| 13 | 4000 | 0.25 ms |
|
||
|
||
> **SPS** = Samples Per Second(每秒采样次数)。数值越大,采样越快,但噪声也越大。
|
||
|
||
---
|
||
|
||
### 9.2 编码器电机模块(`drv_encodermotor.py`)
|
||
|
||
#### 控制硬件
|
||
|
||
**M5Stack Module 4EncoderMotor** —— 一个可以同时控制 4 个空心杯电机的模块。每个电机都带有编码器(可以测量电机转了多少圈)。
|
||
|
||
#### 通信方式
|
||
|
||
**I2C** 总线,模块地址:**0x24**
|
||
|
||
#### 什么是编码器?
|
||
|
||
编码器是安装在电机轴上的传感器。电机每转一个角度,编码器就产生一个脉冲。通过统计脉冲数量,计算机就知道电机转了多少圈、转到了哪个位置。
|
||
|
||
#### 三种控制模式
|
||
|
||
| 模式 | 名称 | 说明 |
|
||
|---|---|---|
|
||
| `NORMAL_MODE` (0x00) | 普通模式 | 直接设置 PWM 占空比控制转速,没有闭环控制 |
|
||
| `POSITION_MODE` (0x01) | 位置模式 | 使用 PID 闭环控制,让电机转到指定位置并停住 |
|
||
| `SPEED_MODE` (0x02) | 速度模式 | 使用 PID 闭环控制,让电机保持指定的转速 |
|
||
|
||
#### 什么是 PID 控制?
|
||
|
||
PID 是比例(P)-积分(I)-微分(D)控制的简称,是一种自动调节技术。打个比方:
|
||
|
||
你想让水龙头流出的水稳定在每分钟 1 升:
|
||
|
||
- **P(比例)**:看当前流量跟目标差多少,差得多就多拧一点,差得少就少拧一点
|
||
- **I(积分)**:如果长时间有微小偏差(比如一直是 0.98 升),就慢慢增加拧开的幅度
|
||
- **D(微分)**:如果流量突然变化(有人碰了水管),就快速反向调整一下
|
||
|
||
三个参数配合,就能让电机精确地达到并保持目标速度或位置。
|
||
|
||
#### 典型调用流程
|
||
|
||
```python
|
||
from drv_encodermotor import EncoderMotorDriver, SPEED_MODE
|
||
|
||
# 使用 with 语句(自动打开和关闭 I2C 连接)
|
||
with EncoderMotorDriver(bus=1) as driver:
|
||
|
||
# 1. 设置电机 0 为速度模式
|
||
driver.set_mode(0, SPEED_MODE)
|
||
|
||
# 2. 设置速度模式的 PID 参数
|
||
driver.set_speed_pid(0, kp=1, ki=100, kd=1)
|
||
|
||
# 3. 设置线速度(单位:米/秒)
|
||
# 电机将以 0.01 米/秒的速度旋转
|
||
driver.set_linear_speed_m_s(0, 0.01)
|
||
```
|
||
|
||
> `with` 语句是 Python 的一种语法,确保无论代码是否出错,I2C 连接都会被正确关闭。等价于 `try: ... finally: driver.close()`。
|
||
|
||
---
|
||
|
||
### 9.3 步进电机模块(`drv_stepmotor.py`)
|
||
|
||
#### 控制硬件
|
||
|
||
**M5Stack StepMotor Driver** —— 一个可以驱动最多 3 个步进电机的模块。
|
||
|
||
#### 通信方式
|
||
|
||
- **I2C**(地址 0x27):用于模块配置(使能、复位等)
|
||
- **硬件 PWM**(GPIO12):用于产生步进脉冲(控制电机速度)
|
||
|
||
#### 什么是步进电机?
|
||
|
||
步进电机是一种特殊的电机,**每收到一个电脉冲就转动一个固定的角度**(称为"步距角")。本项目中电机的步距角是 1.8°(每圈 200 步),加上驱动器的微步进和减速器后,每圈需要 **89,600 个脉冲**。
|
||
|
||
#### 三个电机的关系
|
||
|
||
- 三个步进电机**共享同一路 PWM**(即同时以相同的频率步进)
|
||
- 但每个电机可以**独立控制方向**(通过独立的 GPIO 引脚)
|
||
- 这样三个圆柱可以同时移动,但方向可以不同
|
||
|
||
#### S 曲线加减速
|
||
|
||
电机突然启动或停止会产生机械冲击。本项目使用 **S 曲线加减速**来让电机平滑地加速和减速。名字来源于速度随时间变化的形状像字母 "S"。
|
||
|
||
具体做法是用**余弦函数**来计算每个时刻的速度:
|
||
|
||
- 启动时:速度从 0 慢慢增加(就像汽车起步)
|
||
- 中间阶段:加速变快
|
||
- 接近目标速度时:加速又变慢,最终平稳到达目标速度
|
||
|
||
减速时反过来,整个过程非常平滑,减少了机械冲击和电机失步的风险。
|
||
|
||
#### 典型调用流程
|
||
|
||
```python
|
||
from drv_stepmotor import StepMotorDriver
|
||
|
||
# 1. 创建步进电机驱动对象
|
||
drv = StepMotorDriver()
|
||
|
||
# 2. 使能电机(允许接收脉冲)
|
||
drv.enable_motor()
|
||
|
||
# 3. 设置方向(True = 正向)
|
||
drv.set_dir(True)
|
||
|
||
# 4. 启动电机并以 S 曲线加速到 0.01 米/秒
|
||
drv.start(0.01)
|
||
|
||
# 5. 在运行中改变速度
|
||
# drv.change_speed(0.02)
|
||
|
||
# 6. 以 S 曲线减速停止
|
||
drv.stop()
|
||
|
||
# 7. 清理资源
|
||
drv.close()
|
||
|
||
# 也支持 with 语句
|
||
# with StepMotorDriver() as drv:
|
||
# drv.enable_motor()
|
||
# drv.set_dir(True)
|
||
# drv.start(0.01)
|
||
# time.sleep(2)
|
||
# drv.stop()
|
||
```
|
||
|
||
---
|
||
|
||
## 10. `signal_features.json` 说明
|
||
|
||
这个文件存储了从 **LBM(格子玻尔兹曼方法)** 计算机仿真中提取的信号特征。LBM 是一种流体力学仿真方法,用于模拟水流绕过圆柱时的受力情况。
|
||
|
||
### 文件内容格式
|
||
|
||
```json
|
||
{
|
||
"signals": [
|
||
{
|
||
"name": "action1", // 第 1 个圆柱的信号
|
||
"mean": 0.00166, // 信号的直流分量(平均值)
|
||
"components": [ // 正弦波分量列表
|
||
{
|
||
"frequency": 0.135, // 频率 (Hz)
|
||
"amplitude": 0.00137, // 幅值
|
||
"phase": 0.187 // 相位 (弧度)
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
每个 action(对应一个圆柱)包含:
|
||
- **mean(均值)**:信号的直流偏置
|
||
- **多个正弦波分量**:每个分量有频率、幅值、相位
|
||
|
||
这些参数用于在主控制循环中合成周期运动信号,让圆柱按照仿真得出的最优方式运动。**数据已做脱敏处理**(数值做了随机偏移),仅供学习参考。
|
||
|
||
---
|
||
|
||
## 11. 常见问题 FAQ
|
||
|
||
#### Q: SPI 设备找不到
|
||
|
||
```bash
|
||
ls -l /dev/spidev*
|
||
```
|
||
如果显示 `No such file or directory`,说明 SPI 接口未启用。
|
||
|
||
**解决方法**:
|
||
```bash
|
||
sudo raspi-config
|
||
# 进入 Interface Options → SPI → Enable
|
||
# 重启树莓派
|
||
```
|
||
|
||
#### Q: I2C 设备找不到
|
||
|
||
```bash
|
||
i2cdetect -y 1
|
||
```
|
||
如果命令不存在或没有显示设备地址,说明 I2C 接口未启用。
|
||
|
||
**解决方法**:
|
||
```bash
|
||
sudo raspi-config
|
||
# 进入 Interface Options → I2C → Enable
|
||
# 重启树莓派
|
||
```
|
||
|
||
扫描到的设备地址应该显示为十六进制编号(如 `24` 和 `27`)。
|
||
|
||
#### Q: 电机不转
|
||
|
||
请按顺序检查:
|
||
|
||
1. **电源**:电机模块是否有外部电源供电?树莓派的 5V 引脚通常不足以驱动电机
|
||
2. **使能信号**:是否调用了 `enable_motor()`(步进电机)或设置了正确的模式(编码器电机)
|
||
3. **接线**:I2C 连线是否正确(SDA → GPIO2,SCL → GPIO3)
|
||
4. **地址**:I2C 地址是否匹配(编码器电机 0x24,步进电机 0x27)
|
||
|
||
#### Q: ADC 读数为 0
|
||
|
||
1. 检查 PGA 配置是否正确(增益是否设得太低,信号太弱读不出来)
|
||
2. 检查输入通道选择是否正确(是不是选对了 AIN 引脚)
|
||
3. 检查 SPI 接线
|
||
4. 用 `check_status()` 方法查看 ADC 状态寄存器
|
||
|
||
#### Q: ImportError: No module named xxx
|
||
|
||
运行以下命令安装缺失的库:
|
||
|
||
```bash
|
||
pip install xxx
|
||
```
|
||
|
||
常用的库安装命令:
|
||
|
||
```bash
|
||
pip install spidev smbus2 rpi_hardware_pwm matplotlib jupyter
|
||
```
|
||
|
||
#### Q: Permission denied(权限不足)
|
||
|
||
通常是因为当前用户没有访问 SPI 或 I2C 设备的权限。`pi` 用户默认有权限。如果使用其他用户,可以将用户加入相关组:
|
||
|
||
```bash
|
||
sudo usermod -a -G spi,i2c,gpio 用户名
|
||
# 然后注销并重新登录
|
||
```
|
||
|
||
---
|
||
|
||
## 12. 参考资料
|
||
|
||
- **ADS124S08 数据手册(TI 官方网站)**
|
||
https://www.ti.com/product/ADS124S08
|
||
|
||
- **M5Stack 4EncoderMotor 模块文档**
|
||
https://docs.m5stack.com/en/module/Module_4EncoderMotor_V1.1
|
||
|
||
- **M5Stack StepMotor Driver 模块文档**
|
||
https://docs.m5stack.com/en/module/Stepmotor%20Driver%20Module13.2%20v1.1
|
||
|
||
- **树莓派官方文档**
|
||
https://www.raspberrypi.com/documentation/
|
||
|
||
- **树莓派 GPIO 引脚说明**
|
||
https://www.raspberrypi.com/documentation/computers/raspberry-pi.html
|
||
|
||
- **spidev Python 库**
|
||
https://pypi.org/project/spidev/
|
||
|
||
- **smbus2 Python 库**
|
||
https://pypi.org/project/smbus2/
|
||
|
||
- **gpiozero Python 库**
|
||
https://gpiozero.readthedocs.io/
|