分页: 1 / 1

空气炸锅增加液晶显示与温度、时间调节

发表于 : 周四 9月 29, 2022 16:11
5661890
看见某宝里圆形液晶屏在出售价格也低廉,于是就想到了家里的空气炸锅是否可以改造成液晶屏的呢。于是上网查询圆形液晶屏尺寸与资料,再对比控制炸锅的那两个圆形的旋钮大小,经测量尺寸差不多,于是就购买ESP8266 modemcu开发板,旋钮编码器,1.28寸圆形GA9A01芯片驱动的液晶品,以及继电器控制板,若干导线。使用Arduino编程,目前已完成温度显示、定时功能,温度控制在等待MAX31865模块到手在添加代码。因为是新手代码不是很精简希望有大神可以帮忙精简。下面是购买的配件、显示图片及代码,成品尚未完成,完成后再继续更新。

代码: 全选

/************************************************************************************************************/
#include "Button2.h"; //按钮控制库https://github.com/LennartHennigs/Button2 按钮控制库
#include "Rotary.h";  //编码器库 https://github.com/skathir38/Rotary
#include "TickTwo.h"  //定时库 https://github.com/sstaub/TickTwo
#include <Arduino_GFX_Library.h> //液晶屏驱动库
Arduino_DataBus *bus = new Arduino_ESP8266SPI(4 /* DC */, 15 /* CS */);  //液晶屏控制芯片的选择与引脚的设置
Arduino_GFX *gfx = new Arduino_GC9A01(bus, 2 /* RST */, 0 /* rotation */, true /* IPS */);//屏幕型号的选择
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
ESP8266WebServer server(80);  //建立WEB服务器端口80
#include <WiFiManager.h> 

/***********************************************************************************************************/

#define ROTARY_PIN1 D1 //定义ESP8266接旋转编码器的输入引脚与名称
#define ROTARY_PIN2 D6 //定义ESP8266接旋转编码器的输入引脚与名称
#define BUTTON_PIN  D3 //定义ESP8266接旋转编码器按钮的输入引脚与名称
#define Relay_PIN   D0 //定义ESP8266接继电器的输出引脚与名称

#define CLICKS_PER_STEP 4   //定义旋转编码器时钟数及名称(这个数字取决于您的旋转编码器)
#define MIN_POS        -90  //定义旋转编码器最小值及名称
#define MAX_POS        270  //定义旋转编码器最大值及名称
#define START_POS       -90 //定义旋转编码器起始值及名称
#define INCREMENT       6   //定义旋转编码器每一步的增量

/************************************************************************************************************/

Rotary r;    //声明Rotary对象
Button2 b;    // 声明Button2对象
WiFiManager wifiManager;
void blink();
TickTwo timer1(blink, 60000); //声明TickTwo对象

/************************************************************************************************************/

byte cx=120, cy=120, outerR=110, innerR=100;          //定义实心圆弧起始坐标X、Y、外圆半径、内圆半径变量名称 
uint16_t color_1, color_2=BLACK,color_3;               //定义颜色变量名称
int originate=-90, ultimate=-90, originate_1;         //定义实心圆弧开始角度、结束角度、反向擦除圆弧起始角度变量名称
int Temperature=0,set_time_valu=0, Numerical_value, Clear_value=0;//定义温度、定时、显示数值、清除数值变量名称
byte x, y, x_1, y_1, x_2, y_2, Size, Size_1;          //定义显示坐标、文字大小变量名称
byte x_temp, x_var, x_time=114;                       //定义坐标转换值变量名称
int  Tem_switch, get_value, value;                           //定义整数型变量名称
String word_1;                                        //定义字符串变量名称

/************************************************************************************************************/

void setup()
{
  Serial.begin(9600); 
  gfx->begin();                                            //运行液晶屏库
  setup_wifi();                                            //WIFI初始化
  Start_Display();                                         //初始化液晶屏显示
  
  //开启按钮程序并设定按钮为输入
  b.begin(BUTTON_PIN); 
  b.setClickHandler(handler);                             //设置点击一次处理程序
  b.setLongClickHandler(handler);                         //设置长按处理程序
  b.setDoubleClickHandler(handler);                       //设置点击两次处理程序
  b.setTripleClickHandler(handler);                       //设置点击三次处理程序
  
  //开启旋转编码器程序并设定变量名称
  r.begin(ROTARY_PIN1, ROTARY_PIN2, CLICKS_PER_STEP, MIN_POS, MAX_POS, START_POS, INCREMENT);
  r.setChangedHandler(temperature);                       //温度设置的处理程序
  r.setLeftRotationHandler(set_time);                     //设置左旋转处理程序
  r.setRightRotationHandler(set_time);                    //设置右旋转处理程序
    
  timer1.start();                                         //开启定时程序
  pinMode(Relay_PIN, OUTPUT);                             //设置D0脚为输出型
  digitalWrite(Relay_PIN, HIGH);                          //写入D0脚高电平
                                           
  timing_run();                                           //定时运行
  Temperature_adjust();                                   //远程温度调整
  Time_adjust();                                          //远程时间调整
  Wifi_rest();                                            //wifi账号与密码删除
  Stop();                                                 //停止运行
}

//主循环程序
void loop() 
{ 
  b.loop();
  r.loop();
  if(set_time_valu>0){
     timer1.update();
     }       
  reset_Position();
  server.handleClient(); 
}

/************************************************************************************************************/

// 温度设定调整
void temperature(Rotary& r) 
{   
  if(Tem_switch==0)
    {              
   if(r.getDirection()==1)                         //判断r.getDirection()的取值等于1时执行Temperature自加否则自减
     {
       Temperature++;
     }
   else{
       Temperature--;
       }
    Temperature_Display();                         //数值显示程序
  }
}

// 设置定时时间并画圆弧
void set_time(Rotary& r) {  
  if(Tem_switch==1){      
    if(r.getDirection()==1){                       //判断编码器增加侧执行下列程序
            Time_plus();
       }else{                                      //判断编码器如果没有增加侧执行下列程序
            Time_sub();
            }   
      Time_Display();
  }
}

/**********************************************************************************************************
功能选择,按钮一次Tem_switch=2定时开始运行,按钮两次Tem_switch=1时间调节且停止,长按按钮Tem_switch=0调节温度且停止
连续按钮三次WIFI设置,wifi设置时其他功能均不可使用,需等待WIFI联网后方能恢复
**********************************************************************************************************/
void handler(Button2& btn) {
   switch (btn.getType()) {
        case single_click:
        if(set_time_valu>0){
            SET_RUN();
           }
            break;
        case double_click:
            SET_time();
            break;
        case triple_click:
            //setup_wifi();
            break;
        case long_click:
            SET_TEMP_STOP();
            break;
    }
}

//定时运行程序
void blink() 
{
  if(Tem_switch==2)            
    {
      if(set_time_valu>0){
       set_time_valu--;              
       ultimate = constrain(ultimate, -90, 270);                           //将ultimate数值限制-90与270之间
       originate_1 = ultimate-INCREMENT;
       gfx->fillArc(cx, cy, outerR, innerR, originate_1, ultimate, BLUE);  //反画实心圆弧
       ultimate = ultimate-INCREMENT;
       get_value = set_time_valu;
       coordinate();
       x=x_var, x_time=x_var, y=140, Size=3, color_1=WHITE, Numerical_value=set_time_valu;
       Display();                                                          //显示后退数值      
       }
    if(set_time_valu==0){
       SET_TEMP_STOP();
       }
    }     
}

//旋转编码器自动归零
void reset_Position()
{
  if(r.getPosition()==MAX_POS || r.getPosition()==MIN_POS )
    {
      r.resetPosition();
    }   
}

//纯数值显示,无擦除原显示功能
void Value_Display()
{
 gfx->setCursor(x, y);//设置光标坐标    
 gfx->setTextColor(color_1);//设置文字颜色
 gfx->setTextSize(Size);//设置文字大小
 gfx->println(value);//输出值
}

//温度与时间调整时数值显示
void Display()
{
     gfx->setCursor(x_1, y_1);//设置光标坐标    
     gfx->setTextColor(color_2);//设置文字颜色
     gfx->setTextSize(Size);//设置文字大小
     gfx->println(Clear_value);//输出文字E    
     gfx->setCursor(x, y);//设置光标坐标
     gfx->setTextColor(color_1);//设置文字颜色
     gfx->setTextSize(Size);//设置文字大小
     gfx->println(Numerical_value);//输出文字
     Clear_value = Numerical_value;
     x_1=x;
     y_1=y;
     
}

//字符串文字显示
void Word_Display()
{
 gfx->setCursor(x_2, y_2);//设置光标坐标    
 gfx->setTextColor(color_3);//设置文字颜色
 gfx->setTextSize(Size_1);//设置文字大小
 gfx->println(word_1);//输出文字  
}

//根据Temperature的数值调整tx坐标值始温度值显示在屏幕中间
void coordinate()
{
   if(get_value<10)                           
     {
       x_var = 114;
     }
   else{
         if(get_value<100 &&get_value>9)
           {
            x_var = 106;
           }
         else{
               x_var = 96;
             }
       }
}

//按钮温度选择
void SET_TEMP_STOP()
{
         x_1 = x_temp, y_1=70, Clear_value = Temperature;
         Tem_switch=0;    
         x_2=94, y_2=176, Size_1=3, color_3=BLACK, word_1="RUN";
         Word_Display();
         x_2=50, y_2=142, Size_1=2, color_3=BLACK, word_1="SET";
         Word_Display();
         x_2=50, y_2=72, Size_1=2, color_3=BLUE, word_1="SET";
         Word_Display();
         x_2=90, y_2=176, Size_1=3, color_3=RED, word_1="STOP";
         Word_Display();          
         digitalWrite(Relay_PIN, HIGH); 
 }

//按钮时间选择
void SET_time()
{
         x_1 = x_time, y_1=140,Clear_value = set_time_valu;
         Tem_switch=1;        
         x_2=94, y_2=176, Size_1=3, color_3=BLACK, word_1="RUN";
         Word_Display();
         x_2=50, y_2=72, Size_1=2, color_3=BLACK, word_1="SET";
         Word_Display();
         x_2=50, y_2=142, Size_1=2, color_3=RED, word_1="SET";
         Word_Display();
         x_2=90, y_2=176, Size_1=3, color_3=RED, word_1="STOP";
         Word_Display();
         digitalWrite(Relay_PIN, HIGH);    
 }

//按钮控制运行
void SET_RUN()
{
         x_1 = x_time, y_1=140, Clear_value = set_time_valu;
         Tem_switch=2;         
         x_2=50, y_2=142, Size_1=2, color_3=BLACK, word_1="SET";
         Word_Display();
         x_2=50, y_2=72, Size_1=2, color_3=BLACK, word_1="SET";
         Word_Display();
         x_2=90, y_2=176, Size_1=3, color_3=BLACK, word_1="STOP";
         Word_Display();
         x_2=94, y_2=176, Size_1=3, color_3=GREEN, word_1="RUN";
         Word_Display();
         digitalWrite(Relay_PIN, LOW);  
 }

//WIFI启动与设置
void setup_wifi() { 
  gfx->fillScreen(color_2);                                              //给屏幕充满黑色
  wifiManager.setConfigPortalTimeout(120);                                //WIFI没有连接自动跳出
 
  x_2=45, y_2=70, Size_1=2, color_3=WHITE, word_1="Please connect";  
  Word_Display();
  x_2=15, y_2=100, Size_1=2, color_3=WHITE, word_1="SSID:AutoConnectAP";  
  Word_Display();
  x_2=40, y_2=130, Size_1=2, color_3=RED, word_1="IP:192.168.4.1";  
  Word_Display();
  x_2=50, y_2=160, Size_1=2, color_3=WHITE, word_1="Wait two Min";  
  Word_Display();  
  wifiManager.autoConnect("AutoConnectAP");                              //自动连接WIFI
  server.onNotFound(handleNotFound); 
  server.begin();                                                        //开启web服务器

  gfx->fillScreen(color_2);
  x_2=50, y_2=70, Size_1=2, color_3=WHITE, word_1="Connected to:";  
  Word_Display(); 
  x_2=80, y_2=100, Size_1=2, color_3=WHITE, word_1=WiFi.SSID();  
  Word_Display(); 
  x_2=30, y_2=130, Size_1=2, color_3=WHITE, word_1="IP ";  
  Word_Display();
  gfx->setCursor(60, 130);//设置光标坐标    
  gfx->setTextColor(WHITE);//设置文字颜色
  gfx->setTextSize(2);//设置文字大小
  gfx->println(WiFi.localIP());//输出值                                
  delay(10000);
  //Start_Display();
  //SET_TEMP_STOP();
    Serial.print("ESP8266 Connected to ");
    Serial.println(WiFi.SSID());              // WiFi名称
    Serial.print("IP address:\t");
    Serial.println(WiFi.localIP());           // IP
}

//温度显示
void Temperature_Display() 
{    
    Temperature = constrain(Temperature, 0, 220);                                    //将数值限制在0与220之间
    get_value = Temperature;
    coordinate();                                                                    //坐标调整函数
    x=x_var, x_temp=x_var, y=70, Size=3, color_1=WHITE, Numerical_value=Temperature; //给显示程序变量赋值
    Display();                                                                       //数值显示函数
}

//时间显示
void Time_Display()
{
    set_time_valu = constrain(set_time_valu, 0, 60);                                    //将数值限制在0与60之间
    get_value = set_time_valu;
    coordinate();                                                                       //坐标调整程序
    x=x_var, x_time=x_var, y=140, Size=3, color_1=WHITE, Numerical_value=set_time_valu; //给显示程序变量赋值
    Display();                                                                          //函数
  }
  
//时间加
void Time_plus()
{
   ultimate = constrain(ultimate, -90, 270);                             //将ultimate数值限制-90与270之间
   ultimate = ultimate+INCREMENT;                                        //每次加INCREMENT值给ultimate
   set_time_valu++;                                                      //set_time_valu自加
   gfx->fillArc(cx, cy, outerR, innerR, originate, ultimate,  WHITE);    //画实心圆弧白色
  }

//时间减
void Time_sub()
{
  ultimate = constrain(ultimate, -90, 270);                              //将ultimate数值限制-90与270之间
  set_time_valu--;
  originate_1 = ultimate-INCREMENT;
  gfx->fillArc(cx, cy, outerR, innerR, originate_1, ultimate, BLUE);     //画实心圆弧
  ultimate = ultimate-INCREMENT;
  }
  
//远程温度调节
void Temperature_adjust()
{
  server.on("/Temp_plus", []() {    
    server.send(200, "text/plain", "Temp plus");
     if(Tem_switch==0){
               Temperature++;
               Temperature_Display();
              }else{
                SET_TEMP_STOP();
                Temperature++;
                Temperature_Display();                                
                }               
  });

    server.on("/Temp_sub", []() {    
    server.send(200, "text/plain", "Temp sub");
     if(Tem_switch==0){
               Temperature--;
               Temperature_Display();
              }else{
                SET_TEMP_STOP();
                Temperature--;
                Temperature_Display();                                
                }
  });
}

//远程时间调节
void Time_adjust()
{
  server.on("/Time_plus", []() {    
    server.send(200, "text/plain", "Time plus");
     if(Tem_switch==1){
               Time_plus();
               Time_Display();
              }else{
                SET_time();
                Time_plus();
                Time_Display();                                
                }               
  });

    server.on("/Time_sub", []() {    
    server.send(200, "text/plain", "Time sub");
     if(Tem_switch==1){
               Time_sub();
               Time_Display();
              }else{
                SET_time();
                Time_sub();
                Time_Display();                                
                }
  });
}

//WIFI账户与密码删除
void Wifi_rest()
{
    server.on("/REST", []() {
    server.send(200, "text/plain", "wifi rest");
    ESP.eraseConfig();     
    delay(5000);
    ESP.reset();

  });  
}

//远程定时控制
void timing_run()
{
  server.on("/timing_control", []() {
  server.send(200, "text/plain", "timing Start");
  if(set_time_valu>0){
            SET_RUN();
        }
  });
}

//远程停止控制
void Stop()
{
  server.on("/STOP", []() {
  server.send(200, "text/plain", "STOP");
  SET_TEMP_STOP();
  });
}

//开始显示界面
void Start_Display()
{
  gfx->fillScreen(color_2);                                                 //给屏幕充满蓝色
  gfx->fillArc(cx, cy, outerR, innerR, originate, 270, BLUE);               //画蓝色实心圆弧
  get_value = set_time_valu;
  coordinate();                                                             //坐标调整函数
  x=x_var, x_time=x_var, y=140, Size=3, color_1=WHITE, value=set_time_valu; //给显示程序变量赋值
  Value_Display();                                                          //数值显示函数
  gfx->fillArc(cx, cy, outerR, innerR, originate, ultimate,  WHITE);
  get_value = Temperature;
  coordinate();                                                             //坐标调整函数
  x=x_var, x_temp=x_var, y=70, Size=3, color_1=WHITE, value=Temperature;    //给显示程序变量赋值
  Value_Display();
   
   x_2=154, y_2=142, Size_1=2, color_3=DARKGREY, word_1="Min";              //屏幕上显示Min
   Word_Display();
   x_2=100, y_2=40, Size_1=2, color_3=DARKCYAN, word_1="TEMP";              //屏幕上显示TEMP
   Word_Display();
   x_2=100, y_2=110, Size_1=2, color_3=DARKCYAN, word_1="TIME";             //屏幕上显示TIME
   Word_Display();  
   x_2=50, y_2=72, Size_1=2, color_3=BLUE, word_1="SET";                    //屏幕上显示SET
   Word_Display();
   x_2=90, y_2=176, Size_1=3, color_3=RED, word_1="STOP";                   //屏幕上显示STOP
   Word_Display(); 
   x_2=166, y_2=70, Size_1=3, color_3=WHITE, word_1="C";                    //屏幕上显示C
   Word_Display(); 
   x_2=158, y_2=64, Size_1=1, color_3=WHITE, word_1="o";                    //屏幕上显示O
   Word_Display();                                                          //字符串显示函数
  }

//网页未发现反馈
void handleNotFound() {
  // run when no route is found
  String message = "File Not Found\n\n";
  message += "URI: ";
  // get request uri
  message += server.uri();
  message += "\nMethod: ";
  // get request method
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  // get request args
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  // send with 404 code
  server.send(404, "text/plain", message);
}

Re: 空气炸锅增加液晶显示与温度、时间调节

发表于 : 周二 10月 04, 2022 14:23
DT27
厉害啊 :o

Re: 空气炸锅增加液晶显示与温度、时间调节

发表于 : 周一 11月 21, 2022 16:44
5661890
继续温度控制部分的改造,原计划使用max31865模块采集温度的,但是因为esp8266引脚有限,只能改用PT100温度采集模块串口版,当然价格是原来的一半挺划算的。上几张改造图片,拆空气炸锅
IMG_20221108_201956.jpg
IMG_20221108_201956.jpg (2.4 MiB) 查看 21699 次
拿下面板上面一个圆形孔洞安装透明亚克力
IMG_20221111_072834.jpg
IMG_20221111_072834.jpg (2.97 MiB) 查看 21699 次
下面一个安装旋转编码器
IMG_20221112_114726.jpg
IMG_20221112_114726.jpg (3.56 MiB) 查看 21699 次
安装风扇与加热管控制继电器,温度采集模块及PT100,还有5V电源。
IMG_20221112_180142.jpg
IMG_20221112_180142.jpg (3.05 MiB) 查看 21699 次
最后再组装
IMG_20221121_175702.jpg
IMG_20221121_175702.jpg (2.98 MiB) 查看 21686 次
目前测试温度控制在上下4度,想用PID控制的但是温度调整误差有10度,还在揣摩PID程序中,暂时先这样用用。附上代码,此次定时代码有改动原定时程序不太准确。(但代码逻辑仍比较繁琐,希望有大神可以帮忙精简。)

代码: 全选

/*****************************************************************************************************/
#include <ESP8266WiFi.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>
#include "Button2.h"              //按钮控制库https://github.com/LennartHennigs/Button2
#include "Rotary.h"               //编码器库 https://github.com/skathir38/Rotary
#include "TickTwo.h"               //定时库 https://github.com/sstaub/TickTwo
#include <Arduino_GFX_Library.h>   //液晶屏驱动库 https://github.com/moononournation/Arduino_GFX 
/*****************************************************************************************************
ESP8266 various dev board   : CS: 15, DC:  4, RST:  2, BL:  5, SCK: 14, MOSI: 13, MISO: 12
液晶屏控制芯片的选择与引脚的设置和屏幕驱动芯片型号的选择
******************************************************************************************************/
Arduino_DataBus *bus = new Arduino_ESP8266SPI(2/* DC */, 15 /* CS */);
Arduino_GFX *gfx = new Arduino_GC9A01(bus, 4 /* RST */, 0 /* rotation */, true /* IPS */);
ESP8266WebServer server(80);  //建立WEB服务器端口80
/******************************************************************************************************/
#define ROTARY_PIN1 D1       //定义ESP8266接旋转编码器的输入引脚与名称
#define ROTARY_PIN2 D2       //定义ESP8266接旋转编码器的输入引脚与名称
#define BUTTON_PIN  D6       //定义ESP8266接旋转编码器按钮的输入引脚与名称
#define Relay_PIN   D0       //定义ESP8266接继电器的输出
#define Relay_PIN_1 D3       //定义ESP8266接继电器的输出

#define CLICKS_PER_STEP 4    //定义旋转编码器时钟数及名称(这个数字取决于您的旋转编码器)
#define MIN_POS        -90   //定义旋转编码器最小值及名称
#define MAX_POS        270   //定义旋转编码器最大值及名称
#define START_POS      -90   //定义旋转编码器起始值及名称
#define INCREMENT       6    //定义旋转编码器每一步的增量
/******************************************************************************************************
声明Rotary、Button2、TickTwo、wifiManager对象
*******************************************************************************************************/
Rotary r; 
Button2 b;    
WiFiManager wifiManager;
void blink();
TickTwo timer1(blink, 1000); 
/******************************************************************************************************/
byte x, y, x_1, y_1, x_2, y_2, Size, Size_1;            //定义显示坐标、文字大小变量名
byte x_temp, x_var, x_time=114;                         //定义坐标转换值变量名称
byte cx=120, cy=120, outerR=120, innerR=110;            //定义实心圆弧起始坐标X、Y、外圆半径、内圆半径变量名称 
int  originate=-90, ultimate=-90, originate_1,numdata=0;//定义实心圆弧开始、结束角度、反向擦除圆弧起始角度变量名
int  Temperature=0,set_time_valu=0, Numerical_value, Clear_value=0;//定义温度、定时、显示数值、清除数值变量名
int  Tem_switch, get_value, Clear_value_1, value;                                        //定义整数型变量名
String word_1,tmp;                                                        //定义字符串变量名
unsigned char hexdata[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};//定义串口发送变量
uint16_t color_1, color_2=BLACK,color_3;                                  //定义颜色变量名
/******************************************************************************************************/
void setup()
{
  Serial.begin(9600);                                      //启动串口
  while(Serial.read() >= 0){}                              //清理缓存 
  Serial.setTimeout(50);
  gfx->begin();                                            //运行液晶屏库
  setup_wifi();                                            //WIFI初始化
  Start_Display();                                         //初始化液晶屏显示
    
  b.begin(BUTTON_PIN);                                     //开启按钮程序并设定按钮为输入
  b.setClickHandler(handler);                              //设置点击一次处理程序
  b.setLongClickHandler(handler);                          //设置长按处理程序
  b.setDoubleClickHandler(handler);                        //设置点击两次处理程序
  b.setTripleClickHandler(handler);                        //设置点击三次处理程序
  
  //开启旋转编码器程序并设定变量名称
  r.begin(ROTARY_PIN1, ROTARY_PIN2, CLICKS_PER_STEP, MIN_POS, MAX_POS, START_POS, INCREMENT);
  r.setChangedHandler(temperature);                        //温度设置的处理程序
  r.setLeftRotationHandler(set_time);                      //设置左旋转处理程序
  r.setRightRotationHandler(set_time);                     //设置右旋转处理程序
    
  timer1.start();                                          //开启定时程序
  pinMode(Relay_PIN, OUTPUT);                              //设置D0脚为输出型(風扇)
  digitalWrite(Relay_PIN, HIGH);                           //写入D0脚高电平
  pinMode(Relay_PIN_1, OUTPUT);                            //设置D4脚为输出型(加熱管)
  digitalWrite(Relay_PIN_1, HIGH);                         //写入D4脚高电平
                                           
  timing_run();                                            //远程定时运行
  Temperature_adjust();                                    //远程温度调整
  Time_adjust();                                           //远程时间调整
  Wifi_rest();                                             //wifi账号与密码删除
  Stop();                                                  //停止运行
}
/******************************************************************************************************/
//主循环程序
void loop() 
{ 
  b.loop();
  r.loop();
  if(Tem_switch==2){
     timer1.update();
     }                                              //如果设定的时间大于0才可以运行定时函数
  Serial.write(hexdata, 9);
  reset_Position();
  server.handleClient();                             //网页客户端处理函数
}
/******************************************************************************************************/
// 温度设定调整
void temperature(Rotary& r) 
{  
  if(Tem_switch==0)
    {              
   if(r.getDirection()==1)                    //判断r.getDirection()的取值等于1时执行Temperature自加否则自减
     {
       Temperature++;
     }
   else{
       Temperature--;
       }
    Temperature_Display();                    //温度数值显示程序
  }
}
/******************************************************************************************************/
// 设置定时时间并画圆弧
void set_time(Rotary& r) 
{   
  if(Tem_switch==1){      
    if(r.getDirection()==1){                   //判断编码器增加侧执行下列程序
            Time_plus();
       }else{                                  //判断编码器如果没有增加侧执行下列程序
            Time_sub();
            }   
      Time_Display();                          //时间数值显示程序
  }
}
/******************************************************************************************************
功能选择,按钮一次Tem_switch=2定时开始运行,按钮两次Tem_switch=1时间调节且停止,长按按钮Tem_switch=0调节温度且停止
*******************************************************************************************************/
void handler(Button2& btn) 
{
   switch (btn.getType()) {
        case single_click:
        if(set_time_valu>0){
            SET_RUN();
           }
            break;
        case double_click:
            SET_time();
            break;
        case triple_click:
            break;
        case long_click:
            SET_TEMP_STOP();
            break;
    }
}
/******************************************************************************************************/
//定时运行程序
int i;                                                                     //計數
void blink() 
{
  if(Tem_switch==2&&set_time_valu>0)            
    {
      if(i==60){
       set_time_valu--;              
       ultimate = constrain(ultimate, -90, 270);                           //将ultimate数值限制-90与270之间
       originate_1 = ultimate-INCREMENT;
       gfx->fillArc(cx, cy, outerR, innerR, originate_1, ultimate, BLUE);  //反画实心圆弧
       ultimate = ultimate-INCREMENT;
       get_value = set_time_valu;
       coordinate();
       x=x_var, x_time=x_var, y=140, Size=3, color_1=WHITE, Numerical_value=set_time_valu;
       Display();                                                           //显示定时计时数值  
        i=0;
       }else{
        i++;                                                                //不等于60自加
            } 
       temperature_control();
    }       
  if(set_time_valu==0)
    {
       digitalWrite(Relay_PIN_1, HIGH);
       if(numdata<=50)
       {
       SET_TEMP_STOP();
       }
    }  
}
/******************************************************************************************************
因为旋转编码器库的程序没有无穷大数值,所以编译旋转编码器自动归零函数,在达到最大值与最下值时自动复位归零
*******************************************************************************************************/
void reset_Position()
{
  if(r.getPosition()==MAX_POS || r.getPosition()==MIN_POS )
    {
      r.resetPosition();
    }   
}
/******************************************************************************************************/
//纯数值显示,无擦除原显示功能
void Value_Display()
{
 gfx->setCursor(x, y);                 //设置光标坐标    
 gfx->setTextColor(color_1);           //设置文字颜色
 gfx->setTextSize(Size);               //设置文字大小
 gfx->println(value);                  //输出值
}
/******************************************************************************************************/
//温度与时间调整时数值显示
void Display()
{
     gfx->setCursor(x_1, y_1);         //设置光标坐标    
     gfx->setTextColor(color_2);       //设置文字颜色
     gfx->setTextSize(Size);           //设置文字大小
     gfx->println(Clear_value);        //输出文字E    
     gfx->setCursor(x, y);             //设置光标坐标
     gfx->setTextColor(color_1);       //设置文字颜色
     gfx->setTextSize(Size);           //设置文字大小
     gfx->println(Numerical_value);    //输出文字
     Clear_value = Numerical_value;    //给清除函数赋值
     x_1=x;
     y_1=y;    
}
/******************************************************************************************************/
//字符串文字显示
void Word_Display()
{
 gfx->setCursor(x_2, y_2);            //设置光标坐标    
 gfx->setTextColor(color_3);          //设置文字颜色
 gfx->setTextSize(Size_1);            //设置文字大小
 gfx->println(word_1);                //输出文字  
}
/******************************************************************************************************/
//根据Temperature的数值调整tx坐标值是使温度值显示在屏幕中间
void coordinate()
{
   if(get_value<10)                           
     {
       x_var = 114;
     }
   else{
         if(get_value<100 &&get_value>9)
           {
            x_var = 106;
           }
         else{
               x_var = 96;
             }
       }
}
/******************************************************************************************************/
//按钮温度选择同时具有停止功能
void SET_TEMP_STOP()
{
         x_1 = x_temp, y_1=70, Clear_value = Temperature;
         Tem_switch=0;    
         x_2=94, y_2=176, Size_1=3, color_3=BLACK, word_1="RUN";
         Word_Display();
         x_2=50, y_2=142, Size_1=2, color_3=BLACK, word_1="SET";
         Word_Display();
         x_2=50, y_2=72, Size_1=2, color_3=BLUE, word_1="SET";
         Word_Display();
         x_2=90, y_2=176, Size_1=3, color_3=RED, word_1="STOP";
         Word_Display(); 
         digitalWrite(Relay_PIN_1, HIGH);        
         digitalWrite(Relay_PIN, HIGH);
          
 }
/******************************************************************************************************/
//按钮时间选择
void SET_time()
{
         x_1 = x_time, y_1=140,Clear_value = set_time_valu;
         Tem_switch=1;        
         x_2=94, y_2=176, Size_1=3, color_3=BLACK, word_1="RUN";
         Word_Display();
         x_2=50, y_2=72, Size_1=2, color_3=BLACK, word_1="SET";
         Word_Display();
         x_2=50, y_2=142, Size_1=2, color_3=RED, word_1="SET";
         Word_Display();
         x_2=90, y_2=176, Size_1=3, color_3=RED, word_1="STOP";
         Word_Display();
         digitalWrite(Relay_PIN_1, HIGH);
         digitalWrite(Relay_PIN, HIGH);   
 }
/******************************************************************************************************/
//按钮控制运行
void SET_RUN()
{
         x_1 = x_time, y_1=140, Clear_value = set_time_valu;
         Tem_switch=2;         
         x_2=50, y_2=142, Size_1=2, color_3=BLACK, word_1="SET";
         Word_Display();
         x_2=50, y_2=72, Size_1=2, color_3=BLACK, word_1="SET";
         Word_Display();
         x_2=90, y_2=176, Size_1=3, color_3=BLACK, word_1="STOP";
         Word_Display();
         x_2=94, y_2=176, Size_1=3, color_3=GREEN, word_1="RUN";
         Word_Display();
         digitalWrite(Relay_PIN, LOW);  
 }
/******************************************************************************************************/
//WIFI启动与设置
void setup_wifi() { 
  gfx->fillScreen(color_2);                                              //给屏幕充满黑色
  wifiManager.setConfigPortalTimeout(60);                                //WIFI没有连接自动跳出
 
  x_2=45, y_2=70, Size_1=2, color_3=WHITE, word_1="Please connect";  
  Word_Display();
  x_2=15, y_2=100, Size_1=2, color_3=WHITE, word_1="SSID:AutoConnectAP";  
  Word_Display();
  x_2=40, y_2=130, Size_1=2, color_3=RED, word_1="IP:192.168.4.1";  
  Word_Display();
  x_2=50, y_2=160, Size_1=2, color_3=WHITE, word_1="Wait two Min";  
  Word_Display();  
  wifiManager.autoConnect("AutoConnectAP");                              //自动连接WIFI
  server.onNotFound(handleNotFound); 
  server.begin();                                                        //开启web服务器

  gfx->fillScreen(color_2);
  x_2=50, y_2=70, Size_1=2, color_3=WHITE, word_1="Connected to:";  
  Word_Display(); 
  x_2=80, y_2=100, Size_1=2, color_3=WHITE, word_1=WiFi.SSID();  
  Word_Display(); 
  x_2=30, y_2=130, Size_1=2, color_3=WHITE, word_1="IP ";  
  Word_Display();
  gfx->setCursor(60, 130);//设置光标坐标    
  gfx->setTextColor(WHITE);//设置文字颜色
  gfx->setTextSize(2);//设置文字大小
  gfx->println(WiFi.localIP());//输出值                                
  delay(10000);
}
/******************************************************************************************************/
//温度显示
void Temperature_Display() 
{    
    Temperature = constrain(Temperature, 0, 220);                                    //限制在0与220之间
    get_value = Temperature;
    coordinate();                                                                    //坐标调整函数
    x=x_var, x_temp=x_var, y=70, Size=3, color_1=WHITE, Numerical_value=Temperature; //给显示程序变量赋值
    Display();                                                                       //数值显示函数
}
/******************************************************************************************************/
//时间显示
void Time_Display()
{
    set_time_valu = constrain(set_time_valu, 0, 60);                                    //限制在0与60之间
    get_value = set_time_valu;
    coordinate();                                                                       //坐标调整程序
    x=x_var, x_time=x_var, y=140, Size=3, color_1=WHITE, Numerical_value=set_time_valu; //给显示程序变量赋值
    Display();                                                                          //数值显示函数
  }
/******************************************************************************************************/  
//时间加
void Time_plus()
{
   ultimate = constrain(ultimate, -90, 270);                             //将ultimate数值限制-90与270之间
   ultimate = ultimate+INCREMENT;                                        //每次加INCREMENT值给ultimate
   set_time_valu++;                                                      //set_time_valu自加
   gfx->fillArc(cx, cy, outerR, innerR, originate, ultimate,  WHITE);    //画实心圆弧白色
  }
/******************************************************************************************************/
//时间减
void Time_sub()
{
  ultimate = constrain(ultimate, -90, 270);                              //将ultimate数值限制-90与270之间
  set_time_valu--;
  originate_1 = ultimate-INCREMENT;
  gfx->fillArc(cx, cy, outerR, innerR, originate_1, ultimate, BLUE);     //画实心圆弧
  ultimate = ultimate-INCREMENT;
  }
/******************************************************************************************************/  
//远程温度调节
void Temperature_adjust()
{
  server.on("/Temp_plus", []() {    
    server.send(200, "text/plain", "Temp plus");
     if(Tem_switch==0){
               Temperature++;
               Temperature_Display();
              }else{
                SET_TEMP_STOP();
                Temperature++;
                Temperature_Display();                                
                }               
  });

    server.on("/Temp_sub", []() {    
    server.send(200, "text/plain", "Temp sub");
     if(Tem_switch==0){
               Temperature--;
               Temperature_Display();
              }else{
                SET_TEMP_STOP();
                Temperature--;
                Temperature_Display();                                
                }
  });
}
/******************************************************************************************************/
//远程时间调节
void Time_adjust()
{
  server.on("/Time_plus", []() {    
    server.send(200, "text/plain", "Time plus");
     if(Tem_switch==1){
               Time_plus();
               Time_Display();
              }else{
                SET_time();
                Time_plus();
                Time_Display();                                
                }               
  });

    server.on("/Time_sub", []() {    
    server.send(200, "text/plain", "Time sub");
     if(Tem_switch==1){
               Time_sub();
               Time_Display();
              }else{
                SET_time();
                Time_sub();
                Time_Display();                                
                }
  });
}
/******************************************************************************************************/
//WIFI账户与密码删除
void Wifi_rest()
{
    server.on("/REST", []() {
    server.send(200, "text/plain", "wifi rest");
    ESP.eraseConfig();     
    delay(5000);
    ESP.reset();

  });  
}
/******************************************************************************************************/
//远程定时控制
void timing_run()
{
  server.on("/timing_control", []() {
  server.send(200, "text/plain", "timing Start");
  if(set_time_valu>0){
            SET_RUN();
        }
  });
}
/******************************************************************************************************/
//远程停止控制
void Stop()
{
  server.on("/STOP", []() {
  server.send(200, "text/plain", "STOP");
  SET_TEMP_STOP();
  });
}
/******************************************************************************************************/
//开始显示界面
void Start_Display()
{
  gfx->fillScreen(color_2);                                                 //给屏幕充满黑色
  gfx->fillArc(cx, cy, outerR, innerR, originate, 270, BLUE);               //画蓝色实心圆弧
  get_value = set_time_valu;
  coordinate();                                                             //坐标调整函数
  x=x_var, x_time=x_var, y=140, Size=3, color_1=WHITE, value=set_time_valu; //给显示程序变量赋值
  Value_Display();                                                          //数值显示函数
  get_value = Temperature;
  coordinate();                                                             //坐标调整函数
  x=x_var, x_temp=x_var, y=70, Size=3, color_1=WHITE, value=Temperature;    //给显示程序变量赋值
  Value_Display();
   
   x_2=154, y_2=142, Size_1=2, color_3=DARKGREY, word_1="Min";              //屏幕上显示Min
   Word_Display();
   x_2=100, y_2=40, Size_1=2, color_3=DARKCYAN, word_1="TEMP";              //屏幕上显示TEMP
   Word_Display();
   x_2=100, y_2=110, Size_1=2, color_3=DARKCYAN, word_1="TIME";             //屏幕上显示TIME
   Word_Display();  
   x_2=50, y_2=72, Size_1=2, color_3=BLUE, word_1="SET";                    //屏幕上显示SET
   Word_Display();
   x_2=90, y_2=176, Size_1=3, color_3=RED, word_1="STOP";                   //屏幕上显示STOP
   Word_Display(); 
   x_2=166, y_2=70, Size_1=3, color_3=WHITE, word_1="C";                    //屏幕上显示C
   Word_Display(); 
   x_2=158, y_2=64, Size_1=1, color_3=WHITE, word_1="o";                    //屏幕上显示O
   Word_Display();                                                          //字符串显示函数
   x_2=20, y_2=110, Size_1=2, color_3=RED, word_1="PV";                     //屏幕上显示PV
   Word_Display();
   
  }
/******************************************************************************************************/
//网页未发现反馈
void handleNotFound() {
  // run when no route is found
  String message = "File Not Found\n\n";
  message += "URI: ";
  // get request uri
  message += server.uri();
  message += "\nMethod: ";
  // get request method
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  // get request args
  message += server.args();
  message += "\n";
  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  // send with 404 code
  server.send(404, "text/plain", message);
}
/******************************************************************************************************/
void temperature_control()
{
  if(numdata>=Temperature-4)
  { 
     digitalWrite(Relay_PIN_1, HIGH);
  }else{
         digitalWrite(Relay_PIN_1, LOW);
       }   
}
  
/**********************************************************************************************************/
void serialEvent(){
  while(Serial.available()>0){
   tmp = Serial.readString(); 
   numdata = tmp[3];
   while(Serial.read() >= 0){}
  }
  if(numdata){
     gfx->setCursor(50, 110);         //设置光标坐标    
     gfx->setTextColor(color_2);       //设置文字颜色
     gfx->setTextSize(2);           //设置文字大小
     gfx->println(Clear_value_1);        //输出文字E    
     gfx->setCursor(50, 110);             //设置光标坐标
     gfx->setTextColor(WHITE);       //设置文字颜色
     gfx->setTextSize(2);           //设置文字大小
     gfx->println(numdata);    //输出文字
     Clear_value_1 = numdata;    //给清除函数赋值 
  }
}
/**********************************************************************************************************/