【”效果展示“前的视频已重新录制】
一、项目需求与硬件介绍
在IO扩展板上有一个用X、Y二轴电位计制作的游戏摇杆,并且处理器芯片支持USB通信。要求实现一个基于ESP32-S2处理器的USB鼠标、键盘复合设备,拨动游戏摇杆实现鼠标的移动,一个按键实现左键点击,另一个按键按下实现键盘敲入一串字符"eetree.cn"。
ESP32-S2是一款高度集成、高性价比、低功耗、主打安全的单核 Wi-Fi SoC。本项目使用ESP32-S2-MINI-1模组,它支持2.4 GHz WiFi,内置 ESP32S2系列芯片以及4MB flash。核心板集成了USB TYPE -C接口,两个按键,一个电源指示灯,一个用户LED灯和2排10pin的排针,方便与扩展板连接。
二、设计思路
不断查询摇杆、按键的状态,然后分别作出鼠标移动、点击和键盘输入的动作。由于任务并不复杂,因此不需要使用中断,在主循环中顺序执行各项操作。具体操作如流程图所示(与MSP430F5529是一样的)。综合考虑程序编译速度和使用的难易程度,本项目使用Arduino平台进行编程。
三、技术细节
自然是面向例程的编程,省时省力又省心。USB-HID设备的实现,参照例程,针对IO扩展板上外设的特点进行补充修改,即可实现相关功能。Arduino开发平台生态环境良好,丰富的第三方库对于各种外设都有合适的例程供用户参考。
3.1 摇杆
经过示波器的测量,发现摇杆在x、y方向上的位置,被转化成输出波形的频率和占空比。用示波器测量了摇杆拨动到正前、正后、正左、正右,四个极限位置的输出波形。因为该波形的频率很低(具体测量结果我放在MSP430那篇报告里),同时不存在占空比极小或极大的情况,最初准备沿用MSP430上的采集手段:使用一个用while循环模拟的时钟,从第1个上升沿起,依次记录高电平和低电平所用的时钟周期数,到第2个上升沿停止计数。然而,在Arduino平台下,ESP32的IO操作函数被一层层地封装,导致函数的运行效率不高,该方法无法奏效。
因此,直接在Arduino平台下调用PulseIn函数测量一个周期下高电平和低电平的时间。接着,从中提取频率和占空比信息,映射到摇杆在x、y方向上的具体位置。
D1=0;D2=0;
D1 = pulseIn(pwmPin, HIGH);
D2 = pulseIn(pwmPin, LOW);
3.2 按键
根据IO扩展板的电路,读取模拟信号输入端口的电压后,与设定的阈值进行比较,然后判断按键的动作。特别的,在“鼠标左键”对应的按键按下后,执行“按下左键”的操作。然后在该按键松开前,需要不断检测摇杆位置。
sensorValue = analogRead(sensorPin);
3.3 键鼠操作
面向例程编程实现相关操作。使用ESP32TinyUSB的开源代码,实现HID复合设备。 将摇杆输出的频率和占空比数值线性映射到指针的移动量上。以左键按下时为例:
else if(sensorValue>2000 && sensorValue<2550){
delay(10);
//device.pressRight();
device.buttons(LEFT_BTN); //阅读源代码,在hidcomposite.cpp中pressLeft的实现
delay(2);
sensorValue = analogRead(sensorPin);
while(sensorValue>1800 && sensorValue<2750){
sensorValue = analogRead(sensorPin);
//让左键按下时指针依然正常工作,“按下”时继续检测摇杆位置
D1=0;D2=0;
D1 = pulseIn(pwmPin, HIGH);//检测高电平
D2 = pulseIn(pwmPin, LOW);
s=D1+D2;
m=(float)D1/D2;
dx=0;dy=0;
if(s<3650 && s>3160){
//水平方向不移动
}
else if(s>3650){
dx=-(s-3650.0)/(4580.0-3650.0)*15.0;
}
else if(s<3160){
dx=(3160.0-s)/(3160.0-2450.0)*15.0;
}
if(m<2.4 && m>1.0){
//垂直方向不移动
}
else if(m<1.0 && m>0.50){
dy=-(1.0-m)/(1.0-0.50)*15.0;
}
else if(m>2.4 && m<4.09){
dy=(m-2.4)/(4.09-2.4)*15.0;
}
device.move(dx, dy);
delay(2);
//Serial.print(",adc=");Serial.println(sensorValue);
}
device.buttons(0);
delay(10);
}
3.4 其他
使用Ucglib的开源代码,以软件SPI的方式驱动LCD屏幕,显示简单的图案。
四、实现功能
本项目使用到IO扩展板上的:按键、旋转编码器,摇杆,LCD屏幕和按键。本项目成功实现按键控制文字输入、鼠标点击;摇杆控制鼠标指针;另外使用LCD屏幕显示了简单的文字。
五、遇到的问题
5.1 USB调试
根据以前使用CH552G的经验,使用Bus Hound工具在Windows电脑上直接观察设备发出的HID数据。根据HID数据的内容,及其发送的频率,判断设备的工作是否符合预期。
5.2 烫手
IO扩展板上有4个加热电阻,如果不在程序里拉低加热功能的控制引脚,它们的温度会非常高。注意安全。
5.3 开发环境
Arduino的简单好用,不必多说。而IDF的功能更加丰富,可以对ESP32实现更深层次的控制。原先准备用IDF编程,但是它在Windows下的编译速度令人无法忍受。最终我使用编译相对较快的Arduino。
如果要解决IDF的编译速度问题,更换高性能的电脑不是最主要的解决方式。在Linux中,IDF的编译速度至少是Windows的2倍(我用完全相同的一份代码试过)。不妨采用Windows+VSCode+WSL+ESP-IDF的组合开发ESP32。在配置WSL上消耗的时间,总归能在之后一次次编译代码时赚回来的。下载程序时,相比于常用的115200,选择921600的波特率能够减少一些等待的时间。
5.4 调试
我不知道怎么调试啊……项目的需求简单,可以盲调。
六、未来计划
该项目已实现所要求的全部功能。首先,希望能找到硬件SPI驱动LCD屏幕的代码,从而实现丰富的动画效果。其次,希望能利用上旋转编码器,实现键盘/鼠标动作的自由切换。(摇杆向下拨到底好像程序出了小的bug,需要改下程序的阈值)
不过,仔细思考了下代码的整个流程,隐隐约约感觉用CH552也可以实现项目的要求。摇杆位置读取的算法在51单片机上自然能用,鼠标、键盘按键的功能我之前做过并取得成功,同时网上也有许多开源资料供参考。
某宝上CH552G的单价为1.85元。也可以发3个CH552G的核心板。或者考虑用ESP32-C3制作核心板,它比ESP-S2多了蓝牙功能。