1 项目目标
通过ESP32核心板的ADC监测IO板模拟输出管脚的变化,判断哪一个按键或编码器的旋转发生了变化,进而控制1.44寸LCD屏幕的菜单显示,要求实现主菜单和至少二级菜单。
2 完成的功能
旋转旋转编码器,可以在ADC管脚中监测到相应的模拟电压值,并以此来判断旋转编码器是在逆时针旋转还是顺时针旋转,又或是在按压旋钮。
LCD屏能够显示主菜单,并通过旋转编码器控制光标移动来实现菜单的功能。
3 实现思路
通过Arduino IDE的串口监视器,在ADC管脚对模拟输入进行采样。
将采样到的ADC量化值进行分类,从而实现判断旋转编码器输入指令。
每个菜单都设置一个结构来存放其目录以及进行下一操作后光标和菜单所在的目录。
每个菜单的函数都是其菜单的布局。
4 实现过程
代码流程图
利用Arduino IDE来读取ADC模块的ADC量化值。
void loop {
int sensorValue = analogRead(Aout);
}
建立菜单函数。
unsigned char funindex = 0;//当前所在菜单
unsigned char cursor = 1;//当前光标所在位置
void (*current)(void);
void menu0(void);
void menu1(void);
void menu2(void);
void menu11(void);
void menu21(void);
建立菜单结构。
typedef struct
{
unsigned char index;//当前目录
unsigned char left;//旋转编码器左转后的目录
unsigned char right;//旋转编码器右转的目录
unsigned char enter;//按压旋转编码器旋钮后的目录
void (*operation)(void);//所在目录菜单对应的函数
}KEY_TABLE;
KEY_TABLE table[5] =
{
{0,0,0,1,(*menu0)},
{1,1,2,3,(*menu1)},
{2,1,2,4,(*menu2)},
{3,3,3,0,(*menu11)},
{4,4,4,0,(*menu21)},
};
在显示菜单前,由于Arduino中TFT_eSPI的库中的字体较少,需要先自制字体头文件。
可直接将Windows系统中的字体文件复制出来,然后转换为hex数组
#include<pgmspace.h>
const uint8_t arial_12[] PROGMEM = {
0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x09,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01,
.
.
.
};//arial_12.h
将头文件放入工程文件夹,然后调用。
#include <SPI.h>
#include <TFT_eSPI.h>
#include "arial_12.h"
void displayString(String text, int16_t x, int16_t y, uint16_t color)//在(x,y)处显示对应颜色的文本
{
tft.setTextSize(7);
tft.setTextColor(color);
tft.loadFont(arial_12);//加载字体
tft.setCursor(x,y);
tft.println(text);
tft.unloadFont();//中止加载,释放内存
}
开始进行菜单的布局。
void menu0(void)//主菜单
{
tft.fillScreen(bgColor);
if(cursor==1)
displayString("blue", 5, 5, tgColor);
else
displayString("blue", 5, 5, fgColor);//光标在该位置时变色
if(cursor==2)
displayString("purple", 5, 55, tgColor);
else
displayString("purple", 5, 55, fgColor);
}
void menu1(void)//子菜单2
{
tft.fillScreen(TFT_BLUE);
if(cursor==3)
displayString("back", 5, 5, tgColor);
else
displayString("back", 5, 5, fgColor);
}
void menu2(void)//子菜单2
{
tft.fillScreen(TFT_GREENYELLOW);
if(cursor==4)
displayString("back", 5, 5, tgColor);
else
displayString("back", 5, 5, fgColor);
}
对旋转编码器各个操作对应的函数进行定义。
void Left(void)
{
cursor = table[cursor].left;//将下一步光标所在的索引传递给光标
current = table[funindex].operation;
(*current)();//每次操作都会刷新一次,执行当前目录下的菜单函数
delay(250);
}
void Right(void)
{
cursor = table[cursor].right;
current = table[funindex].operation;
(*current)();
delay(250);
}
void Enter(void)
{
funindex = table[cursor].index;
cursor = table[funindex].enter;
current = table[funindex].operation;
(*current)();
delay(250);
}
开始初始化,进入主菜单
void setup() {
// put your setup code here, to run once:
tft.init();
tft.fillScreen(bgColor);
menu0();
}
在循环函数中不断扫描ADC的ADC量化值,来进行判断
void loop() {
// put your main code here, to run repeatedly:
int sensorValue = analogRead(Aout);
if((sensorValue > 6690) && (sensorValue < 6740))
Left();
if((sensorValue > 7020) && (sensorValue < 7070))
Right();
if((sensorValue > 6040) && (sensorValue < 6090))
Enter();
//delay(1);
}
5 遇到的主要难题
在Arduino IDE中配置ESP32环境时,由于网络地域问题,导致不能直接通过官网的JSON文件访问github网站加载所需的环境。
因此需要通过修改JSON文件,将需要下载的网站转到镜像网站,从而使Arduino IDE能够顺利下载环境。为此利用宝塔等工具将修改好的json文件上传到服务器生成直链。
在使用TFT_eSPI库的过程中,使用其自带的字体,LCD屏中显示会过大,即便将字体调到最小,每行显示三个数字变是极限了。再加上该字库关于字母的显示还有些缺陷,部分字母无法在屏幕上得到显示,因此最后决定自己做字体库。
6 未来的计划建议
计划在这之后继续完成这个项目其他一些指标,并在这个过程中进一步的去了解ESP32的功能。由于是第一次接触这种项目,因此希望能在完成任务之后还能再通过这块开发板来学习更多的单片机知识,并用在自身的生活中。