内容介绍
内容介绍
项目介绍:RP2350 无线绘图笔
该项目是一个基于 RP2350 微控制器和 nRF52840 蓝牙模块实现的无线数字绘图笔系统。它旨在提供一种直观、无拘无束的数字创作体验,将物理手势与数字画布无缝连接。用户可以通过倾斜和移动手中的笔,直接控制电脑屏幕上的光标进行绘画,并通过笔身上集成的多功能按键,在创作过程中不中断地调整画笔的颜色与粗细。
核心功能
- 无线连接: 采用两块 nRF52840 开发板构建稳定的低功耗蓝牙(BLE)串口通信链路,将绘图笔与电脑分离,彻底摆脱线缆束缚,提供更大的创作自由度。
- 体感控制: 内置 KXTJ3-1057 三轴惯性测量单元(IMU),实时捕捉笔身的倾斜角度,并将其精确转换为画布上光标的移动指令。
- 参数即时调节: 用户可通过笔身上的按键随时进入设置模式,轻松调整画笔的粗细、以及红 (R)、绿 (G)、蓝 (B) 三色通道的数值。
- 实时颜色预览: 笔头集成了两颗 WS2812B RGB LED 灯珠,能够实时显示当前选定或正在编辑的颜色,为用户提供最直观的视觉反馈。
- 配套桌面应用: 使用 Python 和 Tkinter 库开发了一款简洁的跨平台画布应用。该应用在 Linux 系统上运行,负责接收并解析来自画笔的指令,实时渲染用户的笔触,并清晰地展示画笔的各项状态。
技术栈
- 硬件:
- 绘图笔控制器: 基于 RP2350 开发板,集成 KXTJ3-1057 IMU、WS2812B LED 及控制按键。
- 无线发射端: 一块 nRF52840 开发板,烧录
bleuart
程序,通过引脚连接到 RP2350,作为蓝牙外设。 - 无线接收端: 另一块 nRF52840 开发板,烧录
central_bleuart
程序,作为蓝牙中心设备,通过 USB 连接到 Linux 系统的电脑。
- 软件:
- 固件:
-
RP2350_Draw_Controller.ino
: 运行在 RP2350 上,使用 Arduino (C/C++) 编写,负责传感器数据读取、按键逻辑处理和状态机管理。 -
bleuart.ino
/central_bleuart.ino
: 运行在 nRF52840 上,构建了 BLE 串口服务。
-
- 桌面应用: 使用 Python 编写,
Tkinter
库用于构建图形用户界面,PySerial
库用于与接收端进行串口通信。
- 通信协议:
- 笔内通信: RP2350 控制器与 nRF52840 发射端之间通过 UART 串口进行通信。
- 无线通信: 两块 nRF52840 开发板之间通过 BLE UART 服务进行无线数据传输。
- 有线通信: nRF52840 接收端与电脑上的 Python 应用之间通过 USB 虚拟串口进行 JSON 格式的数据交换。
通过这套系统,我们将传统的绘画姿态与现代数字技术相结合,创造出一款功能完整、交互自然且高度集成的无线绘图工具。
硬件介绍
- RP2350: 项目的核心控制器,负责处理来自 IMU 的运动数据和用户的按键输入,并控制 LED 灯珠的状态。其强大的处理能力确保了数据流的实时性和稳定性。
- nRF52840: 两块 nRF52840 开发板构成了无线通信的桥梁。一块作为发射端(Peripheral),与 RP2350 连接,将处理后的数据通过 BLE 发送出去;另一块作为接收端(Central),通过 USB 连接电脑,将接收到的 BLE 数据转发给 Python 应用。
- KXTJ3-1057: 一款高灵敏度的三轴加速度传感器(IMU),用于检测笔身的倾斜姿态,是实现体感控制光标的关键。
- WS2812B: 两颗可编程 RGB LED 灯珠,用于实时显示画笔颜色,为用户提供直观的视觉反馈。
方案框图和项目设计思路
系统方案框图
graph LR
subgraph "绘图笔 (Pen)"
RP2350["<b>RP2350</b><br/>- KXTJ3 IMU<br/>- Buttons<br/>- WS2812B LEDs"] -- UART --> NRF_P["<b>nRF52840 (Peripheral)</b><br/>bleuart"];
end
subgraph "接收端 (Receiver)"
NRF_C["<b>nRF52840 (Central)</b><br/>central_bleuart"];
end
subgraph "电脑 (Computer)"
PC["<b>PC (Linux)</b><br/>Python App"];
end
NRF_P -- BLE --> NRF_C;
NRF_C -- USB --> PC;
设计思路
本项目的核心设计思路是模块化和用户体验优先。
- 功能分离: 我们将核心的运动感应和逻辑处理(RP2350)与无线通信功能(nRF52840)分离开来。这种设计降低了单个微控制器的负担,使得代码逻辑更清晰,也便于未来对任一模块进行独立升级(例如,更换更强的无线模块或更精确的传感器)。
- 状态机管理: 笔刷的控制逻辑采用了有限状态机(Finite State Machine, FSM)。系统定义了“绘图”、“设置菜单”、“编辑数值”等多种状态。用户的按键操作(如长按、短按)会触发状态之间的切换。这种模式极大地简化了复杂的用户交互逻辑,避免了使用大量嵌套的
if-else
语句,使代码更易于维护和扩展。 - 标准化数据交换: 硬件与上位机之间采用 JSON 格式进行通信。这是一种轻量级、易于人类阅读和机器解析的数据格式。通过定义清晰的
action
和payload
字段,我们实现了可靠的指令传递,同时也保证了未来新增功能时,通信协议可以轻松扩展。
软件流程图和关键代码介绍
固件 (RP2350_Draw_Controller.ino)
软件流程图
graph TD
A[Start] --> B[Initialize<br/>- Serial<br/>- IMU, LEDs];
B --> C{Loop};
C --> D{currentState == STATE_DRAWING?};
D -- Yes --> E[handleIMU<br/>Read & Send Move Cmd];
D -- No --> F[handleSwitches<br/>Process Buttons via State Machine];
E --> F;
F --> G[updateStatusLEDs];
G --> C;
关键代码:状态机实现
handleSwitches()
函数是整个固件交互逻辑的核心。它通过一个 switch
语句实现了状态机,根据当前的 currentState
变量来决定如何响应用户的按键输入。
// file: RP2350_Draw_Controller.ino
void handleSwitches() {
// ... 读取按键 ...
switch (currentState) {
case STATE_DRAWING:
// 处理落笔、橡皮擦逻辑
// 检测长按“确认键”进入 STATE_SETTING_MENU
break;
case STATE_SETTING_MENU:
// 处理“+”/“-”在菜单项间导航
// 检测长按“确认键”进入对应的编辑状态 (e.g., STATE_EDITING_THICKNESS)
// 检测长按“取消键”返回 STATE_DRAWING
break;
case STATE_EDITING_THICKNESS:
case STATE_EDITING_COLOR_R: // ... and other editing states
// 处理“+”/“-”修改数值
// 在修改颜色时,调用 updateNeopixels() 实时预览
// 检测长按“确认键”保存修改,并返回 STATE_SETTING_MENU
// 检测长按“取消键”放弃修改,并返回 STATE_SETTING_MENU
break;
}
}
上位机 (canvas_app.py)
软件流程图
graph TD
subgraph Main Thread
A[Start] --> B[Initialize UI - Tkinter Window, Canvas, Labels];
B --> C[process_commands - runs every 100ms];
C --> D{Is queue empty?};
D -- No --> E[Get command from queue];
E --> F[Process action - move, set_color, set_device_state];
F --> G[update_status_bar];
G --> C;
D -- Yes --> C;
end
subgraph Background Thread
H[listen_for_serial] --> I{Serial Data Received?};
I -- Yes --> J[command_queue.put];
J --> I;
I -- No --> I;
end
关键代码:指令处理与状态更新
process_commands()
方法是上位机应用的核心。它以非阻塞的方式从队列中获取并处理来自硬件的 JSON 指令,并更新 UI 界面。
# file: canvas_app.py
def process_commands(self):
try:
while not self.command_queue.empty():
command = self.command_queue.get_nowait()
action = command.get("action")
payload = command.get("payload", {})
# ... (处理 move, set_color, set_thickness 等)
elif action == "set_device_state":
self.device_state = payload.get("state", "Unknown")
self.device_state_value = payload.get("value", "")
needs_status_update = True
if needs_status_update:
self.update_status_bar()
except queue.Empty:
pass
finally:
self.root.after(100, self.process_commands)
实物功能展示图及说明
硬件连线图:黑色:GND 红色:5V 绿色和黄色:分别连接RP2350B和NRF52840的TX和RX
切换颜色到紫色#7300a5,开发板上状态灯实时变为紫色;
切换画笔粗细到21,可见上位机端的画笔粗细有相应变化。
切换画笔颜色到青绿色#73f5a5,开发板状态灯同步变化。
- 绘图状态: 用户手持绘图笔,在空中倾斜。电脑屏幕上的 Python 画布程序中,一个十字光标会跟随笔的倾斜而移动。当用户按下“落笔”键时,光标走过的路径会留下由当前颜色和粗细决定的线条。此时,笔尖的 LED 灯珠显示着当前画笔的颜色(例如,红色)。Python 程序的状态栏显示
Device: Drawing
。 - 进入设置菜单: 用户长按“确认/修改”键后,进入设置模式。Python 程序的状态栏变为
Device: Thickness
,表示当前可以对“画笔粗细”进行调整。用户短按“+”或“-”键,状态栏会依次切换显示Device: Color R
、Device: Color G
等,用于选择要修改的项目。 - 编辑数值与实时预览: 当菜单停在
Color R
时,用户再次长按“确认/修改”键,进入编辑模式。状态栏显示Device: Red: 100
。用户每按一次“+”键,数值增加 5,状态栏同步更新为Device: Red: 105
。最关键的是,笔尖的 WS2812B 灯珠颜色会实时地根据临时的 R、G、B 值进行变化,直观地展示出正在调配的颜色。长按“确认”保存后,状态栏返回菜单模式,LED 灯珠保持新颜色。若长按“取消”,则状态栏返回菜单模式,LED 灯珠恢复到修改前的颜色。
项目中遇到的难题和解决方法
- 难题:复杂的按键逻辑管理
- 问题描述: 项目初期,需要处理“修改/确认”、“取消”、“+”、“-”四个按键的多种操作(长按、短按、重复触发),并根据当前是“绘图”还是“设置”状态做出不同响应。使用传统的
if-else
结构会导致代码逻辑极其混乱、难以维护。 - 解决方法: 引入了有限状态机(FSM) 的设计模式。通过将程序流程划分为明确的几个状态(
STATE_DRAWING
,STATE_SETTING_MENU
,STATE_EDITING_...
),并在每个状态下独立处理按键逻辑,极大地简化了代码结构。这使得添加新功能或修改现有逻辑变得清晰而高效。
- 问题描述: 项目初期,需要处理“修改/确认”、“取消”、“+”、“-”四个按键的多种操作(长按、短按、重复触发),并根据当前是“绘图”还是“设置”状态做出不同响应。使用传统的
- 难题:UI 布局与画布可用空间冲突
- 问题描述: 在 Python 的 Tkinter 应用中,底部的状态栏不断增加新的信息标签后,挤占了主画布的垂直空间,但画布的逻辑尺寸并未改变。这导致光标无法到达画布的下边缘区域,影响了使用体验。
- 解决方法: 调整了画布的初始尺寸。将分辨率从 800x600 更改为更宽的 1280x720 (720p)。这个简单的改动不仅为状态栏提供了充足的空间,也为用户提供了更舒适的绘图区域,解决了画布不可达的问题。
- 难题:颜色调节缺乏直观反馈
- 问题描述: 在最初的版本中,用户在编辑 R、G、B 值时,只有在按下“确认”键之后,笔尖的 LED 灯珠颜色才会更新。这使得颜色调节过程完全依赖于想象和猜测,非常不直观。
- 解决方法: 对固件逻辑进行了优化。在进入颜色编辑状态时,将当前的颜色值存入临时变量。在用户按“+”或“-”调节数值时,立即使用临时颜色值去更新 WS2812B 灯珠。如果用户最终选择取消,则用保存的原始颜色值恢复灯珠显示。这一改进提供了实时颜色预览功能,极大地提升了用户体验。
软硬件
元器件
软件
附件下载
RP2350_Draw.zip
团队介绍
null
团队成员
qqice
评论
0 / 100
查看更多
猜你喜欢
基于RP2350B制作体感小游戏该项目使用了兼容小脚丫FPGA板上功能及扩展生态的RP2350B核心板,实现了体感小游戏的设计,它的主要功能为:根据加速计判断开发板姿态,通过 ADC 获取按键输入,然后通过 USB 虚拟串口发送数据到 PC 端,实现游戏操作和切换。
学嵌入式的Momo
18
使用RP2350B实现基于PWM的音乐播放器该项目使用了RP2350B,实现了基于PWM的音乐播放器的设计,它的主要功能为:通过PWM(脉宽调制)技术控制蜂鸣器播放音乐,实现简易音乐播放器功能。用户可通过按键切换曲目,并支持文本形式存储音乐文件。项目旨在帮助初学者理解PWM原理、音频信号处理及嵌入式系统开发流程。支持按键控制播放状态(播放/停止、切歌)。。
鲜de芒果
5
基于RP2350B制作带有录制功能的电子琴该项目使用了RP2350B及电子琴拓展板,实现了带有录制功能的电子琴的设计,它的主要功能为:录制; 谐波发生器 ; 蜂鸣器; 喇叭。
墨非沧海
6