ESP32学习,驱动LED点阵屏,时钟、日历、天气、新闻显示

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


ESP32学习,驱动LED点阵屏,时钟、日历、天气、新闻显示
—(一)

前言

提示:这里可以添加本文要记录的大概内容:
arduino学习了一段时间,虽然学的不精,也老想着弄点作品。拿到了ESP32这个模块,参考了好多文章资料,就学习着整个作品。跟单片机打交道,不外乎输入输出,屏幕输出是运行结果的显示,就先做个时钟显示吧

在这里插入图片描述

一、ESP32是什么?

esp32芯片是espressif乐鑫信息科技推出的一块wifi芯片,拥有40nm工艺、双核32位mcu、2.4ghz双模wifi和蓝牙芯片、主频高达230mhz。esp32芯片采用tensilica xtensa lx6微处理器,包括双核心和单核版本,内置天线开关,rf射频模块,功率放大器,低噪声接收放大器,滤波器和电源管理模块。
在这里插入图片描述
双列30P,方便连接接口,手工做个电路板吧。
在这里插入图片描述

还有空间,加了电源插针和按钮开关,方便后续开发。
刚开始写文章,错误之处还请指正。

二、简要模块和代码

1.引入能用到的库和HUB75接口

代码如下(示例):

#include <WiFi.h>
#include <WiFiUdp.h>
#include <TimeLib.h>
#include "time.h"
#include <HTTPClient.h>
#include <WebServer.h>
#include <DNSServer.h>
#include <esp_wifi.h>
#include <ESPmDNS.h>
#include <ArduinoJson.h>
//#include <BluetoothSerial.h> //后期可用到蓝牙,相互切换使用
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
#include <U8g2_for_Adafruit_GFX.h>
#include <Preferences.h> //esp32 nvs 存储
#include <Update.h>
#include "OneButton.h" //导入按键检测库
//HUB75对应esp32接口
/*--------------------- MATRIX GPIO CONFIG  -------------------------*/
#define R1_PIN 25
#define G1_PIN 26
#define B1_PIN 27
#define R2_PIN 14
#define G2_PIN 12
#define B2_PIN 13
#define A_PIN 23
#define B_PIN 19 // 
#define C_PIN 5
#define D_PIN 17
#define E_PIN 32 //-1  //32
#define LAT_PIN 4
#define OE_PIN 15
#define CLK_PIN 16

在这里插入图片描述

2.NVS数据读取保存

代码如下(示例):

Preferences prefs; //设定nvs存储名称
//读取nvs存储
void NvsPrefsRead(String Ckey,String mod){  //Ckey 读取键值 mod 读取模式 All 全部读取 待完善
    prefs.begin("mynamespace");
    if(mod!="All"){
        Serial.print("剩余空间: ");Serial.println(prefs.freeEntries());//查询剩余空间
        Serial.print("读取: mynamespace .showMode: ");
        //showMode 循环显示模式的读取
        showMode=(prefs.getString("showMode", "0")).toInt();
        flagColor=(prefs.getString("flagColor", "0")).toInt();
        Serial.print(showMode);Serial.print(" flagColor: ");Serial.println(flagColor);
    }
    prefs.end();
}
void NvsPrefsWrite(String Ckey,uint8_t index,String Str){ //Ckey 写入键值 Str 写入内容 
    prefs.begin("mynamespace");
    Serial.print("剩余空间: ");Serial.println(prefs.freeEntries());//查询剩余空间
    prefs.putString(Ckey.c_str(), Str);
    Serial.print("写入内容: ");Serial.print(Ckey);Serial.print(": "); Serial.println(Str);
    Str=prefs.getString(Ckey.c_str(), "默认");
    Serial.print("读取内容: ");Serial.print(Ckey);Serial.print(": "); Serial.println(Str);
    Serial.print("剩余空间: ");Serial.println(prefs.freeEntries());//查询剩余空间
    prefs.end();
}

3.MATRIX HUB75_I2S_CFG 定义和显示

代码如下(示例):

#define PANEL_RES_X 64      //定义矩阵宽度X
#define PANEL_RES_Y 64     // 定义矩阵高度Y
#define PANEL_CHAIN 2      // 数量 128*64 64*2 64
HUB75_I2S_CFG::i2s_pins _pins={R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN};
HUB75_I2S_CFG mxconfig(
						PANEL_RES_X,   // width
						PANEL_RES_Y,   // height
						PANEL_CHAIN,   // chain length
					 _pins,   // pin mapping
  HUB75_I2S_CFG::FM6126A      // driver chip
  //初始化LED屏
void init_LED() {
  dma_display = new MatrixPanel_I2S_DMA(mxconfig);
  dma_display->begin();
  dma_display->setBrightness8(15); //0-255亮度
  dma_display->fillScreen(myRED); //全红
  dma_display->clearScreen();
  dma_display->setCursor(x, y);//设定光标位置
  dma_display->setTextSize(1);//字符大小
  dma_display->setTextColor(dma_display->color565(255, 255, 0));//颜色
  dma_display->print(words);//输出
}
);

4.U8G2中文字库

代码如下(示例):

U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;//定义中文字库
  u8g2Fonts.begin(*dma_display);
  u8g2Fonts.setFontMode(1);
  u8g2Fonts.setFontDirection(0); 
  u8g2Fonts.setFont(u8g2_font_wqy16_t_gb2312); //16点阵字体
  int s= u8g2Fonts.getUTF8Width("木林森");//子串长度(点阵数)
  u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100), random(100)));
  u8g2Fonts.drawUTF8(80,61,"木林森");//根据点阵位置显示汉字

5.button库的应用

代码如下(示例):

OneButton button(buttonPin, true); 
OneButton button2(buttonPin2, true);
    //按键函数调用
    button.setDebounceMs(80); //设置消抖时长
    button.setClickMs(80);   //设置最短单击时长
    button.setPressMs(5000);  //长按最短时长
    button.setIdleMs(2000) ; //空闲有效时长

    button.attachClick(oneClickPrg);
    button.attachDoubleClick(oneClickPrg);
    button.attachMultiClick(oneClickPrg);
    button.attachLongPressStart(oneClickPrg);
    
    button2.attachClick(twoClickPrg);
    button2.attachDoubleClick(twoClickPrg);
    button2.attachLongPressStart(twoClickPrg);
	//下面代码需放在loop
    button.tick(); //按键函数持续关注
    button2.tick();

6.网络获取新闻条目

代码如下(示例):

//网络获取新闻条目
//链接示例:Url163="https://3g.163.com/touch/reconstruct/article/list/BAI67OGGwangning/1-1.html"; //163新闻条目 1-1;10-1;15-1 意思: 第15条 获取1条
void News163FromWifi(const char* Url163_){
    HTTPClient http;
    int httpCode;
    http.begin(Url163_);
    httpCode = http.GET();            //Make the request
    if (httpCode > 0) {         //Check for the returning code
        String payload = http.getString();
        //Serial.println(payload);
        StaticJsonDocument<1024>  doc;  //分配内存,静态
        /*
        artiList({"BAI67OGGwangning":[{"docid":"ISJ1PNU60514R9OJ",
        "source":"环球网资讯","title":"德国防长:德军内部对话在新加坡遭窃听 是\"个人失误\"",
        "priority":82,"hasImg":1,"url":"https://3g.163.com/news/article/ISJ1PNU60514R9OJ.html",
        "commentCount":282,"imgsrc3gtype":"1","stitle":"",
        "digest":"来源:环球时报【环球时报驻德国特约记者青木】俄媒近日曝光德国",
        "imgsrc":"http://dingyue.ws.126.net/2024/0306/7a2a5ef7j00s9wct0001ud000sg00izg.jpg",
        "ptime":"2024-03-06 10:10:18"}]})
        */
        int X1=payload.indexOf("[{");  //读取N@索引 序号
        Serial.print("X1: ");Serial.print(X1);
        int X2=payload.indexOf("}]");  //读取C@索引  内容
        Serial.print("  X2: ");Serial.println(X2);
        if(X1>1)  payload=payload.substring(X1+1,X2+1);
        //Serial.print("payload: ");Serial.println(payload);
        DeserializationError error = deserializeJson(doc, payload);

        if (error) {
            Serial.println("JSON parsing failed!");
            } else {
            String str=doc["title"].as<String>();
            Serial.println(str);
            ShowNewsMatrix(str);
            }
    }else{
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
    }
    http.end();
}

https://3g.163.com/touch/reconstruct/article/list/BAI67OGGwangning/1-1.html


7.时间、日历、农历、天气界面显示

代码如下(示例):

//表盘界面显示时间
void FaceClockTime(){
    initFaceClockTime();
    showHour(hou,myColor[flagColor]);
    if(minu==minuOld){}else{
        FillTab(16,10,24,22,myBLACK);//清屏
        if(minu<10){
            displayNumber(0,16,8,myColor[flagColor]);
            displayNumber(minu,28,8,myColor[flagColor]);
        }else{
            displayNumber(minu/10,16,8,myColor[flagColor]);
            displayNumber(minu%10,28,8,myColor[flagColor]);
        }
        minuOld=minu;
    }
        FillTab(22,33,14,8,myBLACK);//清屏
        if(sec<10){
            drawText("0",22,33);
            drawText(String(sec),30,33);
        }else{
            drawText(String(sec/10),22,33);
            drawText(String(sec%10),30,33);
        }
        dma_display->drawPixel(miaoZB[sec][0]+PianyiX,miaoZB[sec][1]+PianyiY,myWHITE);
        if(bigTimeFlag>=15){
            //可以加标志显示日期
            FillTab(56,0,72,50,myBLACK);//清屏
            displayNumbers2(year1,78,0,myColor[flagColor]);
            if(month1<10){
                displayNumbers2(0,91,0,myColor[flagColor]);
                displayNumbers2(month1,99,0,myColor[flagColor]);
            }else{
                displayNumbers2(month1,99,0,myColor[flagColor]);
            }
            if(day1<10){
                displayNumbers2(0,112,0,myColor[flagColor]);
                displayNumbers2(day1,120,0,myColor[flagColor]);
            }else{
                displayNumbers2(day1,120,0,myColor[flagColor]);
            }
            //显示农历
            u8g2Fonts.setFont(u8g2_font_wqy12_t_gb2312); 
            u8g2Fonts.setForegroundColor(myColor[rand()%9]);
            String nongli=china_animals+" "+china_monthday;
            u8g2Fonts.drawUTF8(60,28,nongli.c_str());
            //显示天气
            String tianqi=weekHZ[week]+ " "+Weather+" "+Temp+"℃";
            u8g2Fonts.drawUTF8(60,44,tianqi.c_str());
            bigTimeFlag=0;//计数重启
        }
        bigTimeFlag++;
}


8.天气、农历获取

代码如下(示例):

//网络获取天气信息
void WeitherFromWifi(){
    if(weather_getOK==1)return;
    String url_xinzhi =  "https://api.seniverse.com/v3/weather/now.json?key=";//心知天气API接口网址
    url_xinzhi += tqAPI;
    url_xinzhi += "&location=";
    url_xinzhi += CiTy;
    url_xinzhi += "&language=zh-Hans&unit=c";
    HTTPClient http;
    http.begin(url_xinzhi);
    Serial.println(url_xinzhi);
    int httpGet = http.GET();
    Serial.printf("HTTPGET is %d\n",httpGet);
    if(httpGet > 0){ 
        weather_getOK=1;
        String json = http.getString();
        Serial.println(json);
        StaticJsonDocument<1024>  doc;  //分配内存,静态
        deserializeJson(doc, json);
              /*{"results":[{"location":{"id":"WWHPMHEV4CS4","name":"临沂","country":"CN","path":"临沂,临沂,山东,中国",
                "timezone":"Asia/Shanghai","timezone_offset":"+08:00"},
                "now":{"text":"晴","code":"1","temperature":"14"},
                "last_update":"2024-02-12T17:50:13+08:00"}]}*/
            Weather = doc["results"][0]["now"]["text"].as<String>();               //天气
            Temp = doc["results"][0]["now"]["temperature"].as<String>();              // 实况温度
            Serial.print(" Weather: ");Serial.print(Weather);Serial.print(" Temp: ");Serial.print(Temp);Serial.println("");Serial.println("");
    }else
    {
      Serial.printf("Wrong code, error: %s\n", http.errorToString(httpGet).c_str());
    }
      http.end();
}

//网络获取农历换算
void NongliFromWifi(){
    if(china_getOK==1)return;
        String url_xinzhi =   "http://v.juhe.cn/calendar/day?date="; //聚合数据 //农历API接口网址
        //  http://v.juhe.cn/calendar/day?date=2023-10-23&key=自己的KEY
        url_xinzhi += String(year1);
        url_xinzhi += "-";
        url_xinzhi += String(month1);
        url_xinzhi += "-";
        url_xinzhi += String(day1);
        url_xinzhi += "&key="+nlAPI;
    HTTPClient http;
    http.begin(url_xinzhi);
    int httpGet = http.GET();
  Serial.printf("HTTPGET is %d\n",httpGet);
  if(httpGet > 0)
  { 
    china_getOK=1;
    String json = http.getString();
    Serial.println(json);
    StaticJsonDocument<1024>  doc;  //分配内存,静态
      /*
      //聚合数据内容
      {"reason":"Success","result":{"data":{"animalsYear":"兔","weekday":"星期一","lunarYear":"癸卯年","lunar":"九月初九","year-month":"2023-10","date":"2023-10-23","suit":"安葬.入殓.成服.除服.破土.迁坟","avoid":"馀事勿取","holiday":"重阳节","desc":""}},"error_code":0}
      */
      deserializeJson(doc, json);
       china_year = doc["result"]["data"]["lunarYear"].as<String>();               //农历 年
       china_monthday = doc["result"]["data"]["lunar"].as<String>();                  // 月
       china_animals = doc["result"]["data"]["animalsYear"].as<String>();              // 日
       china_holiday = doc["result"]["data"]["holiday"].as<String>(); 
        if(china_holiday=="null"){china_holiday="";}
      Serial.print(" 农历: ");Serial.print(china_year);Serial.print(" ");
      Serial.print(china_animals);Serial.print(" ");
      Serial.print(china_monthday);Serial.print(" ");
      Serial.print(china_holiday);Serial.println("");
    }else{
      Serial.printf("Wrong code, error: %s\n", http.errorToString(httpGet).c_str());
    }
  http.end();
}

总结

以上是刚学习esp32驱动Matrix LED屏的部分代码模块,也是网络学习总结的,还在逐步完善,后续再增加一些传感器,丰富功能。学习学习还是挺有意义的。等代码上传网盘就跟帖发布。

  • 24
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
一、主要的显示屏IC IC(1)74HC04的作用:是一个6位反相器。 第7脚GND,电源地。 第14脚VCC,电源正极。 信号由A端输入Y端反相输出, A1与Y1为一组,其它类推。例:A1=“1”则Y1=“0”、A1=“0”则Y1=“1”,其它组功能一样。IC(2)74HC138的作用:八位二进制译十进制译码器。 第8脚GND,电源地。 第15脚VCC,电源正极 第1~3脚A、B、C,二进制输入脚。 第4~6脚片选信号控制,只有在4、5脚为“0”6脚为“1”时,才会被选通,输出受A、B、C信号控制。其它任何组合方式将不被选通,且Y0~Y7输出全“1”。通过控制选通脚来级联,使之扩展到十六位。例:G2A=0,G2B=0,G1=1,A=1,B=0,C=0,则Y0为“0”Y1~Y7为“1”。 IC(3)4HC595的作用:LED驱动芯片,8位移位锁存器。 第8脚GND,电源地。 第16脚VCC,电源正极 第14脚DATA,串行数据输入口,显示数据由此进入,必须有时钟信号的配合才能移入。第13脚EN,使能口,当该引脚上为“1”时QA~QH口全部为“1”,为“0”时QA~QH的输出由输入的数据控制。 第12脚STB,锁存口,当输入的数据在传入寄存器后,只有供给一个锁存信号才能将移入的数据送QA~QH口输出。 第11脚CLK,时钟口,每一个时钟信号将移入一位数据到寄存器。 第10脚RESET,复位口,只要有复位信号,寄存器内移入的数据将清空,显示屏不用该脚,一般接VCC。 第9脚DOUT,串行数据输出端,将数据传到下一个。 第15、1~7脚,并行输出口也就是驱动输出口,驱动LED。 IC(4)953的作用:行驱动管,功率管。其内部是两个CMOS管,1、3脚VCC,2、4脚控制脚,2脚控制7、8脚的输出,4脚控制5、6脚的输出,只有当2、4脚为“0”时,7、8、5、6才会输出,否则输出为高阻状态。 IC(5)TB62726的作用:LED驱动芯片,16位移位锁存器。 第1脚GND,电源地。 第24脚VCC,电源正极 第2脚DATA,串行数据输入 第3脚CLK,时钟输入. 第4脚STB,锁存输入. 第23脚输出电流调整端,接电阻调整 第22脚DOUT,串行数据输出 第21脚EN,使能输入其它功能与74HC595相似,只是TB62726是16位移位锁存器,并带输出电流调整功能,但在并行输出口上不会出现高电平,只有高阻状态和低电平状态。74HC595并行输出口有高电平和低电平输出.。TB62726与5026的引脚功能一样,结构相似。 二、LED显示屏常见信号的了解 1、CLK时钟信号:提供给移位寄存器的移位脉冲,每一个脉冲将引起数据移入或移出一位。数据口上的数据必须与时钟信号协调才能正常传送数据,数据信号的频率必须是时钟信号的频率的1/2倍。在任何情况下,当时钟信号有异常时,会使整板显示杂乱无章。 2、STB锁存信号:将移位寄存器内的数据送到锁存器,并将其数据内容通过驱动电路点亮LED显示出来。但由于驱动电路受EN使能信号控制,其点亮的前提必须是使能为开启状态。锁存信号也须要与时钟信号协调才能显示出完整的图象。在任何情况下,当锁存信号有异常时,会使整板显示杂乱无章。 3、EN使能信号:整屏亮度控制信号,也用于显示屏消隐。只要调整它的占空比就可以控制亮度的变化。当使能信号出现异常时,整屏将会出现不亮、暗亮或拖尾等现象。数据信号:提供显示图象所需要的数据。必须与时钟信号协调才能将数据传送到任何一个显示点。一般在显示屏中红绿蓝的数据信号分离开来,若某数据信号短路到正极或负极时,则对应的该颜色将会出现全亮或不亮,当数据信号被悬空时对应的颜色显示情况不定。 4、ABCD行信号:只有在动态扫描显示时才存在,ABCD其实是二进制数,A是最低位,如果用二进制表示ABCD信号控制最大范围是16行(1111),1/4扫描中只要AB信号就可以了,因为AB信号的表示范围是4行(11)。当行控制信号出现异常时,将会出现显示错位、高亮或图像重叠等现象。 三、常见故障处理手段(工具:万用表、电烙铁、刀片、螺丝刀、镊子……等。) 四、LED电子显示屏的维修方法判断问题必须先主后次方式的处理,将明显的、严重的先处理,小问题后处理。短路应为最高优先级。 1、电阻检测法,将万用表调到电阻档,检测一块正常的电路板的某点的到地电阻值,再检测另一块相同的电路板的同一个点测试与正常的电阻值是否有不同,若不同则就确定了问题的范围。 2、电压检测法,将万用表调到电压档,检测怀疑有问题的电路的某个点的到地电压,比较是否与正常值相似,否则确定了问题的范围。 3、短路检测法,将万用表调到短路检测挡(有的是二极管压降档或是电阻档,一般具有报警功能),检测是否有短路的现象出现,发现短路后应优先解决,使之

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值