基于ESP32 WiFi 的完成的综合应用
驱动板载的Lcd,加速度传感器、摇杆,按钮,三色灯,温度采集,采用LVGL作为交互界面的设计,几乎完成的所有功能的尝试。
标签
嵌入式系统
ESP32
genvex
更新2023-03-27
507

    话说公元2023年二月的某天晚上,编程小能手看着自己优秀的代码久久不能入眠,但是但是当他把程序上传到一块正面引有硬禾学堂字样的开发板的时候,开发板上的屏幕居然没有像往常一样正常地点亮,经过几次数据线反复插拔,屏幕依然没有一点反应,编程小能手顿时慌了,距离要交作业的时间马上到了,怎么就失灵了呢,前面写得这么多代码不能能都废了吧,好歹你等我把作业交了才坏吧。。。。。

让我们把时间往前往前回拨一下。


Fiw_07k7fvoUc7yYnjPKRlBUSdfR

 


(1)摇杆的驱动 (项目1 内容)

      这个开发板的上的摇杆非常有创意,只用了一个引脚就可以实现了两个方向移动的信号的记录。 在管脚不足的情况下,是一个很好的解决办法。它的原理是在摇杆的水平和垂直方面的移动改变了对应引脚的pwm(plus width moduale)的频率(frequency)和占空比(duty),最后开给我们的任务就是如何精确的捕捉对应引脚的频率和占空比的变化,然后将这个变化范围映射到屏幕大小的空间上。下面提供一种解决方案,这方案经测试,效果非常稳定优良,甚至比采用两个引脚测量ADC 数值变化的硬件方案更好。

首先,我们先完成一段检测频率和占空比的程式。

volatile unsigned long raiseTime = 0; //前一次上升沿时间
volatile unsigned long fallTime = 0;  //前一次下降沿时间
volatile double duty = 0;  //占空比
volatile double fre = 0;   //频率

int pwmPin = 2;   //信号输入的管脚


portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;  //自旋锁

void changeISR()
{
  auto now = micros();
  if(digitalRead(pwmPin))  //现在是高
  {
    portENTER_CRITICAL_ISR(&mux);   //进入临界区
    auto total = now - raiseTime;
    fre = 1e6/(double)total;
    auto h = fallTime - raiseTime;
    duty = h/(double)total*1000;
    portEXIT_CRITICAL_ISR(&mux);   //离开临界区
    raiseTime = now;
  }
  else
  {
    fallTime = now;
  }
}

void setup() {
  lcd.init();  
  lcd.setTextSize(2);
  lcd.setCursor(0,10);
  lcd.print("freq: ");
  lcd.setCursor(0,60);
  lcd.print("duty: ");
  pinMode(pwmPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(pwmPin), changeISR, CHANGE);
}

void loop() {
  delay(10);

  portENTER_CRITICAL(&mux);
  double f = fre;
  double d = duty;
  portEXIT_CRITICAL(&mux);

  lcd.setCursor(50,10);
  lcd.print(f);
  lcd.setCursor(50,60);
  lcd.print(d);
}

 

      然后,我们只要将频率和占空比数值后,就可以跟lvgl的鼠标进行绑定了,LVGL方面内容不是本项目重点,具体理解请参考代码理解。

大家看到  Accl_data.x ,Accl_data.y 的时候注意一下,原来我是用姿态传感器来定位鼠标的,现在能直接用摇杆了,将就这用,多多包涵。

 

void pointer_map()

{

    portENTER_CRITICAL(&mux);

    double x = freq;

    double y = duty;

    portEXIT_CRITICAL(&mux);

    Accl_data.x = map(x, 227, 430, 0, 127);

    Accl_data.y = map(y, 357, 802, -1, 127);

}

(2)按键的驱动

     在本项目中只用到了一个按键,旋钮的功能没有用上,但是为了这个按钮也铆足了劲(差点没搞抑郁)。利用freeRTOS 给开了一个任务实施扫描按键的变化,又不影响主循环的进展。

 

int get_key(unsigned int input)
{
    int k;
    for (k = 0; k < NUM_KEYS; k++)
    {
        if (input < adc_key_val[k])
        { // 循环对比比较值,判断是否有键按下,有返回键号
            return k;
        }
    }
    return -1;
}

void key_scan(void *parm)
{
    uint32_t nextTime = 0;
    int analogValumeSum;
    while (true)
    {
        analogValumeSum = 0;
        for (int i = 0; i < 500; i++)
        {
            analogValumeSum += analogRead(1);
            // wait for next sample
            while (micros() < nextTime)
                ;
            nextTime = micros() + SAMPLING_TIME_US;
        }

        key = get_key(analogValumeSum / 500); // 调用判断按键程序
        // Serial.println(key);
        vTaskDelay(50);
    }
}

(3)屏幕驱动

    开始项目的首要工作是把屏幕给点亮,根据主办方提供的资料索引得知板载屏幕的IC是ST7735(ST7735s),是一片较为常见的IC。因为,编程环境选择Arduino,一个大众化的开发平台,可深可浅,可咸可甜,支持的图形库的选择有很多,例如TFT_eSPI,Adafruit GFX,LovyanGFX,ArduinoGFX等等,尝试过使用以上的图形库对屏幕进行驱动,均获得成功,所以可以大大方方地选择自己顺手的工具即可。这里我选择了通用且移植性能都较好的TFT_eSPI(比较通用)

  • LVGL移植

    LVGL图形库是基于基础图形库之上高级图形库,它提供了强大的绘图机制,可以帮助开发者快速构建令人惊叹的用户界面。即使资源紧缺的MCU上开发出,也能开发出最接近产品级别的用户交互界面(UI,user interface),然而只需要给LVGL提供简单的画点或者填充的函数即可完成升级。在LVGL图形库的帮助下,可以完成风格一致的用户界面,优化难度比传统的图形库会更简单。前面我们已经用基础图形库点亮了屏幕,移植LVGL也是顺水推舟的事情。 LVGL内容属于本项目的额外内容,但它却是本项目的灵魂主干,其他所有功能都依赖LVGL来体现,不能也将这些内容稍微的在各自功能实现的过程中稍微的展开一点。

主页上方是个时钟显示区域,需要通过网络获取时间,过程很复杂哈,然后这种有点仿苹果风的样式也需要点功夫慢慢调,有兴趣的同学可以掰开来仔细查看。

主页下半部分才是各种功能的主要实现区域,实现的任务是检测姿态传感器的数值变化和温度显示界面的切换。。


(4)姿态传感器的利用 (作业5)

     板载的MAA7660姿态传感器完成了,灯光的控制和检测静置状态。正常状态下,在屏幕左下方是姿态传感器数值显示区域,在屏幕右下是30秒倒计时的动画效果,在主程序中检测3个轴向加速度的变化,并将3个轴向的加速度值映射到3颗灯珠的亮度上,实现了使用姿态传感器控制灯光的效果。如果30秒内加速没有明显的变化,主页下半区将进入另外一个状态,使用板载温度传感器检测温度并绘制曲线,(附送按键读数数值的监测),而灯光进入自动循环的周期。这些都是主循环的核心代码,业务逻辑需要理一理。

FvM6Za4gWSExU6eA5SZ169Jmoxnt


(5)温度的检测

     使用短短的一个函数驱动了NTS112,读取了到加热器附近的变化。就为了这个传感器的数据读取,我们在群里讨论了几个晚上,使得查看驱动说明书也变得不是一件很苦的事情了,最后各位大神各显神通,我总结了他们的精华思想,用最少的代码高效地完成相应的功能。没有专门对这个传感器做完整功能的驱动,这种艰苦卓绝的战斗,留给有志之士了。

float readTemperature()

{

    unsigned char data[2];

    Wire.beginTransmission(NTS112_ADDRESS);

    Wire.write(0x00);

    Wire.endTransmission();

    Wire.requestFrom(NTS112_ADDRESS, 2);

    data[0] = Wire.read();

    data[1] = Wire.read();

   return (float)(data[0] + data[1] / 256.00);

}

(6)pid控温的探索

    项目到这已完成得差不多了,早点就想涉足pid控制的事情,在本项目中也不断地学习,有了较为“深刻”的理解,也还是在理论上的理解。如果把这方面的功能也加进来就太完美了,那下期我就没有新东西玩啦,哈哈,还是留点悬念好些。这里放张我跟chatGPT一起学习pid控制的过程,给大家参考(作为证据)。

 

FlrCY42rdBMR9MrTdXZTuQpxPf6Y

     是不是很简单呀?在生活助理(chatGPT)的帮助下,好像生活也没那么难了。


总结

     这个项目的复杂程度很高,涉及的板载所有硬件的功能,是前面所学到的知识一次小结,将LVGL的思想继续传扬,感受了硬件设计的精妙。项目完成得非常认真,非常有诚意,毕竟我们在过年前就拿到板子,所以过年期间都在研究这块板子,所以掌握得还是比较透彻的,但是感觉也有些不足之处,作业内容堆叠很多功能,程序的顶层设计思路还不够清晰,这是今后需要改进的地方。 不断的学习,不断地进步,今天积累,是明天通往成功的基石,虽然我们知道精神力量无法真正抗衡物理实力,生活还得继续,热爱自己的所爱。

 

    回到了故事的开头。因为本项目需要从网络读取时间,如果网络的账号和密码没有重设的话,是没有办法进入正常显示的。正好主人经常更换居住地点,这种情况就出现了,被吓得半死,所以各位如果要测试本项目代码,记得也把自己的网路信息修改了。

(具体在哪修改?找吧:)。

 

代码链接

链接:https://pan.baidu.com/s/1AQM51KEPybItZjer9P5kVg?pwd=ilw7 
提取码:ilw7

 

团队介绍
Ta和ta的团队
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2023 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号