esp32+1.3寸屏幕语音交互

简介: esp32+1.3寸屏幕语音交互

先上视频:

image.png

esp32+1.3寸屏幕语音交互

资料提供

百度网盘

链接:https://pan.baidu.com/s/14NO9VFD0rBgw6YYv1eYk3w?pwd=psbn 

提取码:psbn

准备材料:

nodemcu开发板一个

1.3寸IPS模块一个

继电器一个

舵机俩个+舵机云台

LU-ASR01鹿小班智能语音识别模块 离线识别  

购买需要选择带喇叭的

杜邦线  一样买点  都会用得到

温湿度模块  DHT11

12V小灯泡

连接方式:

esp32S           屏幕

GND             GND

3.3V             VCC

14             SCL

15             SDA        

33               RES        

27               DC

   

esp32S        语音模块  

 

16              IO8

P17             IO7

继电器          语音模块

信号线        IO1

舵机信号线          语音模块

舵机1        I02

舵机2        IO3

温湿度DHT11      语音模块

信号线             DHT

具体实物图连接方式如下:

语音交互表情制作

制作链接:http://tomeko.net/online_tools/file_to_hex.php?lang=en

将240x240大小的图片添加进去,会生成一个数组文件,将数组文件添加到esp266+1.3寸屏幕语音交互\语音模块与1.3寸屏幕交互\esp32_101\img\face.h文件里面

注意这里的数组名需要在语音模块和esp32中对应位置同时进行修改

 

ESP32代码部分

1.主函数

 
// UDP时间服务初始化
void UDPTimeInit(){
  Serial.println("Starting UDP");                 //连接时间服务器
  Udp.begin(localPort);
  Serial.print("Local port: ");
//  Serial.println(Udp.localPort());
  Serial.println("waiting for sync");
  setSyncProvider(getNtpTime);
  setSyncInterval(300); //时间校准间隔
}
 
 
time_t getNtpTime()                               //获取NTP时间
{
  IPAddress ntpServerIP;                          //NTP服务器的IP地址
 
  while (Udp.parsePacket() > 0) ;                 //之前的数据没有处理的话一直等待 discard any previously received packets
  WiFi.hostByName(ntpServerName, ntpServerIP);    //从网站名获取IP地址
  
  sendNTPpacket(ntpServerIP);                     //发送数据包
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();                 //接收数据
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);    //从缓冲区读取数据
      
      unsigned long secsSince1900;
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0;                                       //没获取到数据的话返回0
}
 
void sendNTPpacket(IPAddress &address)            //发送数据包到NTP服务器
{
  memset(packetBuffer, 0, NTP_PACKET_SIZE);       //缓冲区清零
 
  packetBuffer[0] = 0b11100011;                   //LI, Version, Mode   填充缓冲区数据
  packetBuffer[1] = 0;                            //Stratum, or type of clock
  packetBuffer[2] = 6;                            //Polling Interval
  packetBuffer[3] = 0xEC;                         //Peer Clock Precision
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;
 
  Udp.beginPacket(address, 123);                  //NTP服务器端口123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);       //发送udp数据
  Udp.endPacket();                                //发送结束
}
 
 
String week()                                     //星期
{
  String wk[7] = {"日","一","二","三","四","五","六"};
  String s = "周" + wk[weekday()-1];
  return s;
}
 
String monthDay()                                 //月日
{
  String s = String(month());
  s = s + "月" + day() + "日";
  return s;
}
 
String hourMinute()                               //时分
{
  String s = num2str(hour());
  s = s + ":" + num2str(minute());
  return s;
}
 
String num2str(int digits)                        //数字转换成字符串,保持2位显示
{
  String s = "";
  if (digits < 10)
    s = s + "0";
  s = s + digits;
  return s;
}
 
void printDigits(int digits)                      //打印时间数据
{
  Serial.print(":");
  if (digits < 10)                                //打印两位数字
    Serial.print('0');
  Serial.print(digits);
}

2.太空人时钟esp32_101

 
#include "main.h"
#define  VERSION   "V101"
 
void setup()
{
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);                           //初始化串口
  Serial.println();                               //打印回车换行
 
  TFTDisplayInit();                               //初始化TFT
  connect_wifi();                                 //联网处理
  UDPTimeInit();                                  //初始化时间服务
  
  MainView();                                     //太空表主结构
  
//  getCityCode();                                  //通过IP地址获取城市代码
 
  CityWeaterShow();                           //获取天气信息
  weatherOldTime = millis();
}
 
void loop()
{
  SoftSerialRx();
  if(dhStatus != 0){
    runImg(dhStatus);                          
  }else{
    //时钟动画
    taikongren();
  }
                           
}
 
//太空人业务
void taikongren(){
  //主界面动画
  if (now() != oldTime){                    //如果本次数据和上次不一样的话,刷新
    oldTime = now();
    TimeUpdateShow();
  }
  if(millis() - weatherUpdateTime > 600000){              //10分钟更新一次天气
    weatherUpdateTime = millis();
    CityWeaterShow();
  }
  weatherShow();                                 //天气数据滚动显示
  jpgSlideShow();   
}

3.配网与时钟布局

 
void connect_wifi()                               //联网
{
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);           //用固定的账号密码连接网络
 
  while (WiFi.status() != WL_CONNECTED) {         //未连接上的话
    for (uint8_t n = 0; n < 10; n++){             //每500毫秒检测一次状态
      PowerOn_Loading(50);
    }
  }
  while(loadNum < 194){                           //让动画走完
    PowerOn_Loading(1);
  }
  
  Serial.print("\nWiFi connected to: ");
  Serial.println(WIFI_SSID);
  Serial.print("IP:   ");
  Serial.println(WiFi.localIP());                 //得到IP地址
}
 
void PowerOn_Loading(uint8_t delayTime)           //开机联网显示的进度条,输入延时时间
{
  clk.setColorDepth(8);
  clk.createSprite(200, 50);                      //创建Sprite
  clk.fillSprite(0x0000);                         //填充颜色
 
  clk.drawRoundRect(0,0,200,16,8,0xFFFF);         //画一个圆角矩形
  clk.fillRoundRect(3,3,loadNum,10,5,0xFFFF);     //画一个填充的圆角矩形
  clk.setTextDatum(CC_DATUM);                     //显示对齐方式
  clk.setTextColor(TFT_GREEN, 0x0000);            //文本的前景色和背景色
  clk.drawString("Connecting to WiFi",100,40,2);  //显示文本
  clk.pushSprite(20,110);                         //Sprite中内容一次推向屏幕
  clk.deleteSprite();                             //删除Sprite
  loadNum += 1;                                   //进度条位置变化,直到加载完成
  if(loadNum>=194){
    loadNum = 194;
  }
  delay(delayTime);
}
 
void TimeUpdateShow()                        //时间显示
{
  clk.setColorDepth(8); 
 
  //--------------------中间时间区显示开始--------------------
  //时分
  clk.createSprite(140, 48);                      //创建Sprite,先在Sprite内存中画点,然后将内存中的点一次推向屏幕,这样刷新比较快
  clk.fillSprite(bgColor);                        //背景色
  //clk.loadFont(FxLED_48);
  clk.setTextDatum(CC_DATUM);                     //显示对齐方式
  clk.setTextColor(TFT_BLACK, bgColor);           //文本的前景色和背景色
  clk.drawString(hourMinute(),70,24,7);           //绘制时和分
  //clk.unloadFont();
  clk.pushSprite(28,40);                          //Sprite中内容一次推向屏幕
  clk.deleteSprite();                             //删除Sprite
  
  //秒
  clk.createSprite(40, 32);
  clk.fillSprite(bgColor);
  clk.loadFont(FxLED_32);                         //加载字体
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_BLACK, bgColor); 
  clk.drawString(num2str(second()),20,16);
  clk.unloadFont();                               //卸载字体
  clk.pushSprite(170,60);
  clk.deleteSprite();
  //--------------------中间时间区显示结束--------------------
 
  //--------------------底部时间区显示开始--------------------
  clk.loadFont(ZdyLwFont_20);                     //加载汉字字体
  
  //星期
  clk.createSprite(58, 32);
  clk.fillSprite(bgColor);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_BLACK, bgColor);
  clk.drawString(week(),29,16);                   //周几
  clk.pushSprite(1,168);
  clk.deleteSprite();
  
  //月日
  clk.createSprite(98, 32);
  clk.fillSprite(bgColor);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_BLACK, bgColor);  
  clk.drawString(monthDay(),49,16);               //几月几日
  clk.pushSprite(61,168);
  clk.deleteSprite();
 
  clk.unloadFont();                               //卸载字体
  //--------------------底部时间区显示结束--------------------
}
 
 
 
 
 
void getCityCode()                                //发送HTTP请求并且将服务器响应通过串口输出
{
  String URL = "http://wgeo.weather.com.cn/ip/?_="+String(now());
 
  httpClient.begin(Client,URL);                          //配置请求地址。此处也可以不使用端口号和PATH而单纯的
  httpClient.setUserAgent("esp8266");             //用户代理版本,其实没什么用 最重要是后端服务器支持
  //httpClient.setUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1");//设置请求头中的User-Agent
  httpClient.addHeader("Referer", "http://www.weather.com.cn/");
 
  int httpCode = httpClient.GET();                //启动连接并发送HTTP请求
  Serial.print("Send GET request to URL: ");
  Serial.println(URL);
  
  if (httpCode == HTTP_CODE_OK) {                 //如果服务器响应OK则从服务器获取响应体信息并通过串口输出
    String str = httpClient.getString();
    int aa = str.indexOf("id=");
    if (aa > -1){                                 //应答包里找到ID了
       cityCode = str.substring(aa+4,aa+4+9);     //9位长度
       Serial.println(cityCode); 
       CityWeaterShow();                           //显示天气信息
       weatherOldTime = millis();
    }
    else{                                         //没有找到ID
      Serial.println("获取城市代码失败");  
    }
  } 
  else{
    Serial.println("请求城市代码错误:");
    Serial.println(httpCode);
  }
 
  httpClient.end();                               //关闭与服务器连接
}
 
void CityWeaterShow()                              //获取城市天气
{
  String URL = "http://d1.weather.com.cn/weather_index/" + cityCode + ".html?_="+String(now());
 
  httpClient.begin(Client,URL);                          //配置请求地址。
  httpClient.setUserAgent("esp8266");             //用户代理版本,其实没什么用 最重要是后端服务器支持
  //httpClient.setUserAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1");//设置请求头中的User-Agent
  httpClient.addHeader("Referer", "http://www.weather.com.cn/");
 
  int httpCode = httpClient.GET();                //启动连接并发送HTTP请求
  Serial.print("Send GET request to URL: ");
  Serial.println(URL);
  
  if (httpCode == HTTP_CODE_OK) {                 //如果服务器响应OK则从服务器获取响应体信息并通过串口输出
    String str = httpClient.getString();
    int indexStart = str.indexOf("weatherinfo\":");//寻找起始和结束位置
    int indexEnd = str.indexOf("};var alarmDZ");
 
    String jsonCityDZ = str.substring(indexStart+13,indexEnd);//复制字符串
    Serial.println(jsonCityDZ);
 
    indexStart = str.indexOf("dataSK =");         //寻找起始和结束位置
    indexEnd = str.indexOf(";var dataZS");
    String jsonDataSK = str.substring(indexStart+8,indexEnd);//复制字符串
    Serial.println(jsonDataSK);
 
    indexStart = str.indexOf("\"f\":[");          //寻找起始和结束位置
    indexEnd = str.indexOf(",{\"fa");
    String jsonFC = str.substring(indexStart+5,indexEnd);//复制字符串
    Serial.println(jsonFC);
    
    weaterData(&jsonCityDZ,&jsonDataSK,&jsonFC);  //显示天气信息
    Serial.println("获取成功");
    
  } 
  else {
    Serial.println("请求城市天气错误:");
    Serial.print(httpCode);
  }
 
  httpClient.end();                               //关闭与服务器连接
}
 
void weaterData(String *cityDZ,String *dataSK,String *dataFC)//天气信息写到屏幕上
{
  DynamicJsonDocument doc(512);
  deserializeJson(doc, *dataSK);
  JsonObject sk = doc.as<JsonObject>();
 
  clk.setColorDepth(8);
  clk.loadFont(ZdyLwFont_20);                     //加载汉字字体
  
  //温度显示
  clk.createSprite(54, 32);                       //创建Sprite
  clk.fillSprite(bgColor);                        //填充颜色
  clk.setTextDatum(CC_DATUM);                     //显示对齐方式
  clk.setTextColor(TFT_BLACK, bgColor);           //文本的前景色和背景色 
  clk.drawString(sk["temp"].as<String>()+"℃",27,16);//显示文本
  clk.pushSprite(185,168);                        //Sprite中内容一次推向屏幕
  clk.deleteSprite();                             //删除Sprite
 
  //城市名称显示
  clk.createSprite(88, 32); 
  clk.fillSprite(bgColor);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_BLACK, bgColor); 
  clk.drawString(sk["cityname"].as<String>(),44,16);
  clk.pushSprite(151,1);
  clk.deleteSprite();
  
  //PM2.5空气指数显示
  uint16_t pm25BgColor = tft.color565(156,202,127);//优
  String aqiTxt = "优";
  int pm25V = sk["aqi"];
  if (pm25V > 200){
    pm25BgColor = tft.color565(136,11,32);        //重度,显示颜色和空气质量程度
    aqiTxt = "重度";
  }
  else if (pm25V > 150){
    pm25BgColor = tft.color565(186,55,121);       //中度
    aqiTxt = "中度";
  }
  else if (pm25V > 100){
    pm25BgColor = tft.color565(242,159,57);       //轻
    aqiTxt = "轻度";
  }
  else if (pm25V > 50){
    pm25BgColor = tft.color565(247,219,100);      //良
    aqiTxt = "良";
  }
  clk.createSprite(50, 24); 
  clk.fillSprite(bgColor);
  clk.fillRoundRect(0,0,50,24,4,pm25BgColor);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(0xFFFF); 
  clk.drawString(aqiTxt,25,13);
  clk.pushSprite(5,130);
  clk.deleteSprite();
 
  //湿度显示
  clk.createSprite(56, 24); 
  clk.fillSprite(bgColor);
  clk.setTextDatum(CC_DATUM);
  clk.setTextColor(TFT_BLACK, bgColor); 
  clk.drawString(sk["SD"].as<String>(),28,13);
  //clk.drawString("100%",28,13);
  clk.pushSprite(180,130);
  clk.deleteSprite();
 
  scrollText[0] = "实时天气 " + sk["weather"].as<String>();//滚动显示的数据缓冲区
  scrollText[1] = "空气质量 " + aqiTxt;
  scrollText[2] = "风向 " + sk["WD"].as<String>()+sk["WS"].as<String>();
  
  //左上角滚动字幕
  deserializeJson(doc, *cityDZ);
  JsonObject dz = doc.as<JsonObject>();
  //Serial.println(sk["ws"].as<String>());
  //String aa = "今日天气:" + dz["weather"].as<String>() + ",温度:最低" + dz["tempn"].as<String>() + ",最高" + dz["temp"].as<String>() + " 空气质量:" + aqiTxt + ",风向:" + dz["wd"].as<String>() + dz["ws"].as<String>();
  //Serial.println(aa);
  scrollText[3] = "今日" + dz["weather"].as<String>();
  
  deserializeJson(doc, *dataFC);
  JsonObject fc = doc.as<JsonObject>();
  scrollText[4] = "最低温度"+fc["fd"].as<String>()+"℃";
  scrollText[5] = "最高温度"+fc["fc"].as<String>()+"℃";
  
  clk.unloadFont();                               //卸载字体
}
 
void weatherShow()                               //天气滚动条显示
{
  
  if(millis() - weatherOldTime > 2500){                    //2.5秒切换一次显示内容
    if(scrollText[Dis_Count]){                    //如果滚动显示缓冲区有数据
      clkb.setColorDepth(8);
      clkb.loadFont(ZdyLwFont_20);                //加载汉字字体
      
//      for(int pos = 24; pos>0; pos--){            //24点,每次移动一个点,从下往上移
//        Dis_Scroll(pos);
//      }
 
      //滚动显示修改为静态显示,滚动的时候太空人会卡顿
      clkb.createSprite(148, 24);                 //创建Sprite,先在Sprite内存中画点,然后将内存中的点一次推向屏幕,这样刷新比较快
      clkb.fillSprite(bgColor);                   //背景色
      clkb.setTextWrap(false);
      clkb.setTextDatum(CC_DATUM);                //显示对齐方式
      clkb.setTextColor(TFT_BLACK, bgColor);      //文本的前景色和背景色
      clkb.drawString(scrollText[Dis_Count],74,12);//打显示内容
      clkb.pushSprite(2,4);                       //Sprite中内容一次推向屏幕
      clkb.deleteSprite();                        //删除Sprite
  
      
      //clkb.deleteSprite();                      //删除Sprite,这个我移动到Dis_Scroll函数里了
      clkb.unloadFont();                          //卸载字体
  
      if (Dis_Count >= 5){                        //总共显示五条信息
        Dis_Count = 0;                            //回第一个
      }
      else{
        Dis_Count += 1;                           //准备切换到下一个  
      }
      //Serial.println(Dis_Count);
    }
    weatherOldTime = millis();
  }
}
 
void Dis_Scroll(int pos){                         //字体滚动
  clkb.createSprite(148, 24);                     //创建Sprite,先在Sprite内存中画点,然后将内存中的点一次推向屏幕,这样刷新比较快
  clkb.fillSprite(bgColor);                       //背景色
  clkb.setTextWrap(false);
  clkb.setTextDatum(CC_DATUM);                    //显示对齐方式
  clkb.setTextColor(TFT_BLACK, bgColor);          //文本的前景色和背景色
  clkb.drawString(scrollText[Dis_Count],74,pos+12);//打显示内容
  clkb.pushSprite(2,4);                           //Sprite中内容一次推向屏幕
  clkb.deleteSprite();                            //删除Sprite
}
 
void SoftSerialRx(){
  String revData;
  
  if(mySoftwareSerial.available()){
    revData = mySoftwareSerial.readStringUntil('\n');
    String val = "kaixin";
    revData.trim();
    Serial.println(revData);
    Serial.println(revData.length());
    Serial.println(val.length());
    
//    if( val=="kaixin"){
//      dhStatus =1;
//    }
    if( revData=="kaixin"){
      dhStatus =1;
    }
    if(revData== "chongbai"){
      dhStatus =2;
    }
    if(revData== "shuaku"){
      dhStatus =3;
    }
    if(revData== "tiaopi"){
      dhStatus = 4;
    }
 
    if(revData== "zhangsan"){
      dhStatus = 5;
    }
 
    if(revData== "kongtiao"){
      dhStatus = 6;
    }
  }
}
 
//开心表情
void kaixindh(){
  TJpgDec.drawJpg(0,0,kaixin, sizeof(kaixin));//
  delay(450);
  TJpgDec.drawJpg(0,0,kaixin2, sizeof(kaixin2));//
  delay(900);
 
}
 
//耍酷 表情
void shuakudh(){
  TJpgDec.drawJpg(0,0,shuaku, sizeof(shuaku));//
  delay(450);
  TJpgDec.drawJpg(0,0,kaixin2, sizeof(kaixin2));//
  delay(900);
}
 
//调皮 表情
void tiaopidh(){
  TJpgDec.drawJpg(0,0,tiaopi, sizeof(tiaopi));//
  delay(450);
  TJpgDec.drawJpg(0,0,kaixin2, sizeof(kaixin2));//
  delay(900);
}
 
//自定义 表情
void zidingyidh(){
  TJpgDec.drawJpg(0,0,tiaopi, sizeof(tiaopi));//
  delay(450);
  TJpgDec.drawJpg(0,0,kaixin2, sizeof(kaixin2));//
  delay(900);
}
 
 
 
//崇拜 表情
void chongbaidh(){
  TJpgDec.drawJpg(0,0,chongbai, sizeof(chongbai));//
  delay(450);
  TJpgDec.drawJpg(0,0,kaixin2, sizeof(kaixin2));//
  delay(900);
 
}
 
void runImg(int index){
  tft.resetViewport();
  if(index == 1){
    tft.fillScreen(0xFFFF);
    kaixindh();
  }
 
  if(index == 2){
    tft.fillScreen(0xFFFF);
    chongbaidh();
  }
 
  if(index == 3){
    tft.fillScreen(0xFFFF);
    shuakudh();
  }
 
  if(index == 4){
    tft.fillScreen(0xFFFF);
    tiaopidh();
  }
 
  if(index == 5){
    tft.fillScreen(0xFFFF);
    zidingyidh();
  }
 
  if(index == 6){
    tft.fillScreen(0xFFFF);
    tiaopidh();
  }
  tft.resetViewport();
  CityWeaterShow();
  dhStatus = 0;
  MainView();
}

4.与语音模块通信

 
//初始化TFT
void TFTDisplayInit(){
  tft.init();                                     //TFT初始化
  tft.setRotation(0);                             //旋转角度0-3
  tft.fillScreen(0x0000);                         //清屏tft.color565(255,6,31  
  tft.setTextColor(TFT_BLACK, bgColor);           //设置字体颜色
 
  //设置  TJpgDec
  TJpgDec.setJpgScale(1);                         //设置放大倍数
  TJpgDec.setSwapBytes(true);                     //交换字节
  TJpgDec.setCallback(tft_output);                //回调函数tft_output()
}
 
//显示回调函数
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
  if (y >= tft.height()) return 0;
  tft.pushImage(x, y, w, h, bitmap);
  return 1;
}
 
// 太空表主结构
void MainView(){
    TJpgDec.drawJpg(0,0,watchtop, sizeof(watchtop));//显示顶部图标 240*20
    TJpgDec.drawJpg(0,220,watchbottom, sizeof(watchbottom));//显示底部图标 240*20
 
  //绘制一个窗口
  tft.setViewport(0, 20, 240, 200);               //中间的显示区域大小
  tft.fillScreen(0x0000);                         //清屏
  tft.fillRoundRect(0,0,240,200,5,bgColor);       //实心圆角矩形
  //tft.resetViewport();
 
  //绘制线框
  //  drawFastHLine 画横线
  //  drawFastVLine 画竖线  
  tft.drawFastHLine(0,34,240,TFT_BLACK);          //这些坐标都是窗体内部坐标
  tft.drawFastVLine(150,0,34,TFT_BLACK);
  tft.drawFastHLine(0,166,240,TFT_BLACK);
  tft.drawFastVLine(60,166,34,TFT_BLACK);
  tft.drawFastVLine(160,166,34,TFT_BLACK);
 
  TJpgDec.drawJpg(161,171,temperature, sizeof(temperature));//温度图标
  TJpgDec.drawJpg(159,130,humidity, sizeof(humidity));  //湿度图标
 
 
}
 
 
void jpgSlideShow(){
  int x=80,y=94,dt=30;                            //dt图片播放间隔时长
  TJpgDec.drawJpg(x,y,i0, sizeof(i0));            
  delay(dt);
  TJpgDec.drawJpg(x,y,i1, sizeof(i1));
  delay(dt);
  TJpgDec.drawJpg(x,y,i2, sizeof(i2));
  delay(dt);
  TJpgDec.drawJpg(x,y,i3, sizeof(i3));
  delay(dt);  
  TJpgDec.drawJpg(x,y,i4, sizeof(i4));
  delay(dt);  
  TJpgDec.drawJpg(x,y,i5, sizeof(i5));
  delay(dt);  
  TJpgDec.drawJpg(x,y,i6, sizeof(i6));
  delay(dt);  
  TJpgDec.drawJpg(x,y,i7, sizeof(i7));
  delay(dt);  
  TJpgDec.drawJpg(x,y,i8, sizeof(i8));
  delay(dt);  
  TJpgDec.drawJpg(x,y,i9, sizeof(i9));
  delay(dt);  
}

5.初始化时钟时间

 
// UDP时间服务初始化
void UDPTimeInit(){
  Serial.println("Starting UDP");                 //连接时间服务器
  Udp.begin(localPort);
  Serial.print("Local port: ");
//  Serial.println(Udp.localPort());
  Serial.println("waiting for sync");
  setSyncProvider(getNtpTime);
  setSyncInterval(300); //时间校准间隔
}
 
 
time_t getNtpTime()                               //获取NTP时间
{
  IPAddress ntpServerIP;                          //NTP服务器的IP地址
 
  while (Udp.parsePacket() > 0) ;                 //之前的数据没有处理的话一直等待 discard any previously received packets
  WiFi.hostByName(ntpServerName, ntpServerIP);    //从网站名获取IP地址
  
  sendNTPpacket(ntpServerIP);                     //发送数据包
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500) {
    int size = Udp.parsePacket();                 //接收数据
    if (size >= NTP_PACKET_SIZE) {
      Serial.println("Receive NTP Response");
      Udp.read(packetBuffer, NTP_PACKET_SIZE);    //从缓冲区读取数据
      
      unsigned long secsSince1900;
      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-(");
  return 0;                                       //没获取到数据的话返回0
}
 
void sendNTPpacket(IPAddress &address)            //发送数据包到NTP服务器
{
  memset(packetBuffer, 0, NTP_PACKET_SIZE);       //缓冲区清零
 
  packetBuffer[0] = 0b11100011;                   //LI, Version, Mode   填充缓冲区数据
  packetBuffer[1] = 0;                            //Stratum, or type of clock
  packetBuffer[2] = 6;                            //Polling Interval
  packetBuffer[3] = 0xEC;                         //Peer Clock Precision
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;
 
  Udp.beginPacket(address, 123);                  //NTP服务器端口123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);       //发送udp数据
  Udp.endPacket();                                //发送结束
}
 
 
String week()                                     //星期
{
  String wk[7] = {"日","一","二","三","四","五","六"};
  String s = "周" + wk[weekday()-1];
  return s;
}
 
String monthDay()                                 //月日
{
  String s = String(month());
  s = s + "月" + day() + "日";
  return s;
}
 
String hourMinute()                               //时分
{
  String s = num2str(hour());
  s = s + ":" + num2str(minute());
  return s;
}
 
String num2str(int digits)                        //数字转换成字符串,保持2位显示
{
  String s = "";
  if (digits < 10)
    s = s + "0";
  s = s + digits;
  return s;
}
 
void printDigits(int digits)                      //打印时间数据
{
  Serial.print(":");
  if (digits < 10)                                //打印两位数字
    Serial.print('0');
  Serial.print(digits);
}

LU-ASR01模块代码

#include "asr.h"
#include "setup.h"
#include "myLib/asr_event.h"
#include "SoftwareSerial.h"
#include "myLib/luxiaoban.h"
 
uint32_t snid;
SoftwareSerial mySerial1(6,7);
DHTxx _component(9);
QueueHandle_t play = xQueueCreate(5,4);
float temp = 255;
uint8_t hum = 255;
uint32_t var = 0;
uint32_t ser_rec = 0;
Servo servo1;
Servo servo2;
 
//{ID:250,keyword:"命令词",ASR:"最大音量",ASRTO:"音量调整到最大"}
//{ID:251,keyword:"命令词",ASR:"中等音量",ASRTO:"音量调整到中等"}
//{ID:252,keyword:"命令词",ASR:"最小音量",ASRTO:"音量调整到最小"}
void audio_play(){
  while (1) {
    if(xQueueReceive(play,&ser_rec,0)){
      if(ser_rec == 1)
      {
        temp = _component.read_temperature();
        luxiaoban_speech(temp, 255);
      }else if(ser_rec == 2){
        temp = _component.read_temperature();
        hum = _component.readHumidity();
        luxiaoban_speech(temp, hum);
      }
    }
    delay(10);
  }
  vTaskDelete(NULL);
}
//{ID:1,keyword:"命令词",ASR:"我是一",ASRTO:"一"}
//{ID:2,keyword:"命令词",ASR:"我是二",ASRTO:"二"}
//{ID:3,keyword:"命令词",ASR:"我是三",ASRTO:"三"}
//{ID:4,keyword:"命令词",ASR:"我是四",ASRTO:"四"}
//{ID:5,keyword:"命令词",ASR:"我是五",ASRTO:"五"}
//{ID:6,keyword:"命令词",ASR:"我是六",ASRTO:"六"}
//{ID:7,keyword:"命令词",ASR:"我是七",ASRTO:"七"}
//{ID:8,keyword:"命令词",ASR:"我是八",ASRTO:"八"}
//{ID:9,keyword:"命令词",ASR:"我是九",ASRTO:"九"}
//{ID:10,keyword:"命令词",ASR:"我是十",ASRTO:"十"}
//{ID:11,keyword:"命令词",ASR:"我是百",ASRTO:"百"}
//{ID:12,keyword:"命令词",ASR:"我是千",ASRTO:"千"}
//{ID:13,keyword:"命令词",ASR:"我是摄氏度",ASRTO:"摄氏度"}
//{ID:24,keyword:"命令词",ASR:"我是点",ASRTO:"点"}
//{ID:25,keyword:"命令词",ASR:"当前温度唯",ASRTO:"温度唯"}
//{ID:26,keyword:"命令词",ASR:"湿度百分之",ASRTO:"湿度百分之"}
//{ID:27,keyword:"命令词",ASR:"我是零",ASRTO:"零"}
//{ID:28,keyword:"命令词",ASR:"当前温度唯零下",ASRTO:"温度唯零下"}
void ASR_CODE()
{
  //{ID:500,keyword:"唤醒词",ASR:"小电小电",ASRTO:"小电在呢,有什么需要帮助吗?"}
  if(snid == 500){
    mySerial1.println("kaixin");
  }
  //{ID:501,keyword:"唤醒词",ASR:"你好小电",ASRTO:"主人我在"}
  if(snid == 501){
    mySerial1.println("zhangsan");
  }
  //{ID:502,keyword:"命令词",ASR:"打开灯光",ASRTO:"好的,灯光已打开"}
  if(snid == 502){
    luxiaoban_digital_write(0,0);
    mySerial1.println("shuaku");
  }
  //{ID:503,keyword:"命令词",ASR:"关闭灯光",ASRTO:"好的,灯光已关闭"}
  if(snid == 503){
    luxiaoban_digital_write(0,1);
    mySerial1.println("tiaopi");
    delay(3000);
  }
  //{ID:504,keyword:"命令词",ASR:"灯光向前",ASRTO:"灯光位置已调节"}
  if(snid == 504){
    mySerial1.println("kongtiao");
    servo1.write(90);
    delay(1000);
  }
  //{ID:505,keyword:"命令词",ASR:"盒子在哪",ASRTO:"盒子在书桌里"}
  if(snid == 505){
    mySerial1.println("chongbai");
    luxiaoban_digital_write(2,1);
    delay(3000);
    luxiaoban_digital_write(2,0);
  }
  //{ID:506,keyword:"命令词",ASR:"灯光向右",ASRTO:"灯光位置已调节"}
  if(snid == 506){
    mySerial1.println("kongtiao");
    servo1.write(180);
    delay(1000);
  }
  //{ID:507,keyword:"命令词",ASR:"灯光向下",ASRTO:"灯光位置已调节"}
  if(snid == 507){
    mySerial1.println("kongtiao");
    servo2.write(170);
    delay(1000);
  }
  //{ID:508,keyword:"命令词",ASR:"灯光向左",ASRTO:"灯光位置已调节"}
  if(snid == 508){
    mySerial1.println("kongtiao");
    servo1.write(0);
    delay(1000);
  }
  //{ID:509,keyword:"命令词",ASR:"灯光向上",ASRTO:"灯光位置已调节"}
  if(snid == 509){
    mySerial1.println("kongtiao");
    servo2.write(20);
    delay(1000);
  }
  //{ID:510,keyword:"命令词",ASR:"房间温湿度",ASRTO:"当前"}
  if(snid == 510){
    ser_rec = 2;
    xQueueSend(play,&ser_rec,0);
  }
}
 
void setup()
{
  mySerial1.begin(9600);
  Serial.begin((9600));
  //输入代码
  //code here
  //esp32     语音模块开发板
  //P16       IO8
  //P17       IO7
  //{speak:橙子-甜美客服,vol:20,speed:10,platform:haohaodada}
  //{playid:10001,voice:欢迎使用小电,用小电小电唤醒我}
  //{playid:10002,voice:我退下了,用小电小电唤醒我}
  _component.init();
  xTaskCreate(audio_play,"audio_play",256,NULL,4,NULL);
  servo1.attach(1);
  servo2.attach(2);
}


相关实践学习
达摩院智能语音交互 - 声纹识别技术
声纹识别是基于每个发音人的发音器官构造不同,识别当前发音人的身份。按照任务具体分为两种: 声纹辨认:从说话人集合中判别出测试语音所属的说话人,为多选一的问题 声纹确认:判断测试语音是否由目标说话人所说,是二选一的问题(是或者不是) 按照应用具体分为两种: 文本相关:要求使用者重复指定的话语,通常包含与训练信息相同的文本(精度较高,适合当前应用模式) 文本无关:对使用者发音内容和语言没有要求,受信道环境影响比较大,精度不高 本课程主要介绍声纹识别的原型技术、系统架构及应用案例等。 讲师介绍: 郑斯奇,达摩院算法专家,毕业于美国哈佛大学,研究方向包括声纹识别、性别、年龄、语种识别等。致力于推动端侧声纹与个性化技术的研究和大规模应用。
目录
相关文章
|
25天前
|
JSON 安全 IDE
基于ESP8266网络天气时钟的OLED显示
【8月更文挑战第25天】基于ESP8266的网络天气时钟通过OLED显示屏提供直观的时间与天气信息。硬件包括ESP8266开发板、OLED显示屏及其他元件。软件实现涉及Wi-Fi连接、天气API数据获取、NTP时间同步及OLED显示控制。显示内容设计包括清晰的时间格式与详细的天气描述,支持图标展示。项目支持自动更新机制、低功耗模式,并可扩展闹钟等功能。开发者需根据具体环境调整优化,确保系统稳定可靠。
|
10月前
|
数据处理 开发工具 Android开发
由于真机的音频输入设备没有被正确识别导致的
由于真机的音频输入设备没有被正确识别导致的
53 1
|
4月前
|
内存技术
基于Micropython利用ESP32-C3驱动墨水屏显示图片
基于Micropython利用ESP32-C3驱动墨水屏显示图片
288 0
|
4月前
|
芯片
基于Micropython利用ESP32-C3墨水屏电子时钟方法
基于Micropython利用ESP32-C3墨水屏电子时钟方法
279 0
|
传感器 Ubuntu Java
ESP-IDF 蓝牙开发实战 — 传感器数据上传及手机控制开发板
ESP32-C3 蓝牙部分我们学习了GATT,本文博主手把手带领大家使用 ESP32-C3的蓝牙做一个简单的小应用。
1161 0
ESP-IDF 蓝牙开发实战 — 传感器数据上传及手机控制开发板
|
存储 IDE 物联网
Blinker 语音控制 51单片机 点灯
Blinker 语音控制 51单片机 点灯
271 0
|
传感器 监控 网络协议
Python + ESP32 DIY自动感应智能皂液器 避免触摸更安全
Python + ESP32 DIY自动感应智能皂液器 避免触摸更安全
184 0
|
缓存 编解码 API
ZYNQ-使用HDMI显示器进行VDMA彩条显示测试
ZYNQ-使用HDMI显示器进行VDMA彩条显示测试
290 0
ZYNQ-使用HDMI显示器进行VDMA彩条显示测试
|
Java Android开发 C++
如何利用vga接口的显示器做笔记本的副屏
如何利用vga接口的显示器做笔记本的副屏
如何利用vga接口的显示器做笔记本的副屏