一款语音控制的墨水屏桌面助手
具备时间显示、倒计时事件显示、累积事件显示、语音控制功能
一款动动嘴就能交互的极简风桌面摆件!
组成: 墨水屏、stm32、vc02语音模块、实时时钟
使用软件: cubeide1.16.1、lceda专业版、solidworks2024、keyshot13
完整资料: 已上传github-Xiaotian_Epaper,oshwhub-电路设计
更新日志:
- 2025.1.18:更新bom表中黑白红墨水屏器件链接,更新程序,添加二次开发教程
- 2025.1.5:添加pcb焊接建议,bom表中增加了我使用的下载器购买链接
- 2024.12.28:添加黑白红墨水屏供选择,版本v0.0.2
- 2024.12.13:首次上传,版本v0.0.1
序号 | 文件名 | 描述 |
---|---|---|
1 | Hardware | 硬件设计 |
2 | Firmware | 固件文件 |
3 | Software | 软件程序 |
4 | CAD_Model | 模型文件 |
5 | Docs | 文档 |
6 | Tools | 附带工具 |
7 | img | 输出图片 |
8 | REDME.assets | REDME中的图片 |
语音控制指令集
命令词 | 回复语 | 备注 |
---|---|---|
请介绍你自己 | 你好我叫小天 我是一个桌面助手 你可以通过语音和我进行交互 你可以说浇过花了 浇过水了 更改时间 更换图片 有什么需要尽管给我说 |
需唤醒 |
你好小天|小天小天 | 随时待命 | 唤醒词 |
写完日记了 | 记录每一天 | 免唤醒 |
看完书了 | 日拱一卒功不唐捐 | 免唤醒 |
加过水了 | 下次早点浇 | 免唤醒 |
坛子加过水了 | 美味需要时间酝酿 | 免唤醒 |
吃了海底捞 | 发工资了吗又吃海底捞 | 免唤醒 |
更改时间 | 想要调整时间你可以说时间年加一或者时间年减一 | 需唤醒 |
时间年加一 | 需唤醒 | |
时间年减一 | 需唤醒 | |
时间月加一 | 需唤醒 | |
时间月减一 | 需唤醒 | |
时间日加一 | 需唤醒 | |
时间日减一 | 需唤醒 | |
时间时加一 | 需唤醒 | |
时间时减一 | 需唤醒 | |
时间分加一 | 需唤醒 | |
时间分减一 | 需唤醒 | |
更换图片 | 已经更换照片 | 免唤醒 |
墨水屏Epaper:
分辨率296x128像素 、2.9寸、黑白
刷新方式:全屏刷新/局部刷新(4灰阶不支持局刷)
刷新时间:全刷3秒,局刷0.6秒
据说无故障刷新次数为100w次,我设置每分钟刷新一次,那这样算,能够用两年,想想也还有点短
stm32f103cbt6
72M主频,基本外设丰富,特别的是128k flash,对于当前所选墨水屏分辨率来说
一张全屏照片大小=296x128/8=4.7k,即使考虑到用上freeRTOS也可以无压力存20来张图像,并且往往无需全屏图像,对于个人开发来说完全够用了
vc02语音模块
一款低成本纯离线语音识别模组,简单说就是写好对答语句,说特定语句执行特定功能,这里使用时,说出特定语句发送串口指令到主控进行任务控制。支持150条本地指令离线识别,支持RTOS轻量级系统,具有丰富的外围接口,以及简单友好的客制化工具,该项目放弃了按键交互,完全使用语音模块进行交互,想干嘛动动嘴就行,君子动口不动手!
DS1302
一款时钟芯片,用于离线时间记录,确保断电后设备仍然能保持时间
使用cubeide经过初步封装后的freeRTOS,建立了四个任务init、show、run、read,分别执行初始化、显示、主要运行计算、读取任务
为了降低不同任务抢夺共享资源,用了两个无限时间等待的信号量确保run任务正常运行,用了两个事件组分别控制时钟芯片的数据读写和墨水屏的刷新显示
列出硬件组成中模块的电气连接及数据流向
xiaotian结构设计如下,pcb固定采用内嵌螺母设计,在3D打印时需要注意设置一个暂停层,把螺母放进去再继续打印;
巧妙地外壳和屏幕壳体设计,使用Bambu的0.12mm打印刚好将屏幕壳体嵌入到外壳中,在底部使用两颗平头螺丝固定,表面外壳看不出什么安装的痕迹,对于审美的一点点强迫症,舒适了!
电容电阻使用的0603封装,需要用到加热台和烙铁,焊接不当需要拆除的话也需要用到热风枪,这里给一些手工焊接的建议,如果采用SMT焊接可以不用看
- 手工焊接建议开钢网,当然想纯白嫖也可以不开,我没开也焊接成功了,就是难度稍微高一点
- 首先用加热台焊接元器件最多的一面,但注意不要一开始就把引脚密集的typeC和stm32主控芯片贴上去,因为引脚过于密集,但凡锡膏多加一点就会短接,后续用烙铁不好分开,有的同学可能说用助焊剂容易分开,但我以前用的时候发现助焊剂加热时间久了会导电短路,有点恐怖。我实际发现比较好的方法是在加热台上等锡膏都融化了,用镊子把粘连的锡抚顺了,然后再放上typeC和stm32主控,成功率提高很多!
- 焊接好了可以先连接typeC测试串口,能检测到串口一般说明最难的主控和typeC焊接没什么问题,有问题的话先检查用的线是不是只能充电没有信号线,确定是焊接问题,就需要用热风枪吹热拆下来然后再焊接了
焊接成品如下,手工抹的锡膏,表面会有一些锡球不那么美观。
文件路径:"Xiaotian_Epaper\3.Software\Xiaotian_Epaper\Libraries\include\EPAPER.h"
//选择屏幕类型,共适配了两种类型的显示屏,bom表中有列出链接,可以根据自己选择来做选择
#define black_white_red //使用黑白红墨水屏
//#define black_white //使用黑白墨水屏
1.定义场景名称,路径:"Xiaotian_Epaper\3.Software\Xiaotian_Epaper\Libraries\include\myfreertos.h"
// 可以参考定义自己的场景
#define scene1 //显示场景1
//#define scene2 //显示场景2
2.在**init_show()**函数中初始化场景,路径"Xiaotian_Epaper\3.Software\Xiaotian_Epaper\Libraries\mytasks\task_show.c"
void init_show(){
//****
#ifdef scene1
#ifdef black_white_red
EPD_WhiteScreen_Black();
#else
EPD_WhiteScreen_White();
#endif
EPD_W21_Init();
//white
EPD_Dis_Part(0, 0, gImage1_white, 296, 128, NEG);
//right
EPD_Dis_string(186, 0, time, 32, NEG);
EPD_Dis_string(200, 32, date, 16, NEG);
EPD_Dis_Part(210, 48, gImage_love, 32, 32, POS);
EPD_Dis_string(210 + 32, 56, itoa(date_diff(Time_start, Time_now),temp_itoa,10), 16, NEG);
EPD_Dis_Part(210, 80, gImage_haidi, 32, 32, NEG);
EPD_Dis_string(210 + 32, 88, itoa(date_diff(Time_haidilao, Time_now),temp_itoa,10), 16, NEG);
//middle
EPD_Dis_Part(85, 0, photo1, 110, 128, POS);
// left
EPD_Dis_power(0, 0, (date_diff(event_power[0], Time_now)>4)?0:4-date_diff(event_power[0], Time_now));
EPD_Dis_power(0, 32, (date_diff(event_power[1], Time_now)>4)?0:4-date_diff(event_power[1], Time_now));
EPD_Dis_power(0, 64, (date_diff(event_power[2], Time_now)>4)?0:4-date_diff(event_power[2], Time_now));
EPD_Dis_power(0, 96, (date_diff(event_power[3], Time_now)>4)?0:4-date_diff(event_power[3], Time_now));
EPD_Dis_Part(60, 0, gImage_riji, 32, 32, NEG);
EPD_Dis_Part(60, 32, gImage_dushu, 32, 32, POS);
EPD_Dis_Part(60, 64, gImage_tanzi, 32, 32, POS);
EPD_Dis_Part(60, 96, gImage_jiaoshui, 32, 32, POS);
#endif
//****
}
3.在update_show()函数中定义更新逻辑,路径"Xiaotian_Epaper\3.Software\Xiaotian_Epaper\Libraries\mytasks\task_show.c"
void update_show()
{
//****
#ifdef scene1
//white
EPD_Dis_Part(0, 0, gImage1_white, 296, 128, NEG);
//right
EPD_Dis_string(186, 0, time, 32, NEG);
EPD_Dis_string(200, 32, date, 16, NEG);
EPD_Dis_Part(210, 48, gImage_love, 32, 32, POS);
EPD_Dis_string(210 + 32, 56, itoa(date_diff(Time_start, Time_now),temp_itoa,10), 16, NEG);
EPD_Dis_Part(210, 80, gImage_haidi, 32, 32, NEG);
EPD_Dis_string(210 + 32, 88, itoa(date_diff(Time_haidilao, Time_now),temp_itoa,10), 16, NEG);
//middle
EPD_Dis_Part(85, 0, photo1, 110, 128, POS);
// left
EPD_Dis_power(0, 0, (date_diff(event_power[0], Time_now)>4)?0:4-date_diff(event_power[0], Time_now));
EPD_Dis_power(0, 32, (date_diff(event_power[1], Time_now)>4)?0:4-date_diff(event_power[1], Time_now));
EPD_Dis_power(0, 64, (date_diff(event_power[2], Time_now)>4)?0:4-date_diff(event_power[2], Time_now));
EPD_Dis_power(0, 96, (date_diff(event_power[3], Time_now)>4)?0:4-date_diff(event_power[3], Time_now));
EPD_Dis_Part(60, 0, gImage_riji, 32, 32, NEG);
EPD_Dis_Part(60, 32, gImage_dushu, 32, 32, POS);
EPD_Dis_Part(60, 64, gImage_tanzi, 32, 32, POS);
EPD_Dis_Part(60, 96, gImage_jiaoshui, 32, 32, POS);
#endif
//****
}
考虑到嵌入式设备的flash容量有限,对保存的ASCII字模进行一定压缩处理,大大缩减了字模数组所占存储
取模软件取到的字模如下,在进行存储时,黑色区域存储为0x00,那么字模中就有大片的0x00存在,那么你一定能想到一种简单的思路对字模进行压缩。
如“0000000000”=”10个0“,这个思路叫做游程编码,其核心思想是通过减少重复数据的存储来实现压缩。在数据序列中,连续出现的相同元素组成的一段被称为一个“游程”。编码时,每个游程被替换为一个表示游程长度和游程值的二元组。例如,在字符串“AAAABBBCCDAA”中,“AAAA”是一个游程,长度为4,可以表示为(4, 'A')。
1.num-char压缩方式
“AAAABBBCCDAA” =》 (4, 'A')(3, 'B')(2, 'C')(1, 'D')(2, 'A')
这种方式的压缩率大概是81.89%
2.只压缩0x00的方式
“00000AAAABBBCCDAA” =》 (5, 0x00)"AAAABBBCCDAA"
这种方式压缩率达到51.19%,不过对应的编码和解码就麻烦一点,这里自己写了一个xiaotian_Epaper\6.Tools\ed_codem.m
文件进行处理,项目也采用该方式进行字模压缩
字模制作过程:
先在字模工具中制作完成->生成.c文件用vscode打开->正则表达式进行替换,删除不必要的注释内容,替换成可输入到matlab中的形式->拷贝到ed_codem.m文件中进行运算->拷贝到c程序中
字模数据处理所用正则表达式:
/\*.*?\*/ 搜索所有/* */括起来的内容
,(?![^,]*,) 选中所有行最后一个逗号
\n{2} 选中连续的两个换行符
取模软件
工具路径:xiaotian_Epaper\6.Tools\CharacterMatrix 3.0.2.3.exe
vc02烧录工具:教程参考
工具路径:xiaotian_Epaper\6.Tools\hummingbird-m-production-tool\UniOneDownloadTool.exe
固件路径:xiaotian_Epaper\2.Firmware\uni_app_release.bin
难度不是很高的一个项目,想锻炼一下贴片焊接、学习stm32设计开发、freeRTOS的同学都可以来试试,我会持续完善更新,期待大家交作业!