#define key_start     5                  //开始按键
#define key_add       6                  //增加按键
#define key_less      7                  //减少按键
#include <U8g2lib.h>
#include <Wire.h>
#include <PID_v1.h>
#include <OneWire.h>
#include <DallasTemperature.h>           //库

//字体:华文黑体  字号:16px  显示文字:阈值:
/*
  ------------------------------------------------------------------------------------------------
  |    0                                   0         0                                           |
  |      0   0 0 0 0 0 0 0 0 0             0         0                                           |
  |                0         0             0 0 0 0 0 0 0 0 0 0                                   |
  |  0             0   0     0           0           0                                           |
  |  0             0     0   0           0           0                                           |
  |  0   0 0 0 0 0 0 0 0 0   0         0 0     0 0 0 0 0 0 0                                     |
  |  0             0         0         0 0     0           0                                     |
  |  0     0 0 0   0   0     0       0   0     0 0 0 0 0 0 0                                     |
  |  0     0   0   0   0     0     0     0     0           0                                     |
  |  0     0 0 0   0   0     0           0     0 0 0 0 0 0 0           0 0                       |
  |  0             0 0       0           0     0           0           0 0                       |
  |  0       0 0     0   0   0           0     0 0 0 0 0 0 0                                     |
  |  0   0 0       0   0 0   0           0     0           0           0 0                       |
  |  0           0       0   0           0     0           0           0 0                       |
  |  0         0             0           0 0 0 0 0 0 0 0 0 0 0 0                                 |
  |  0                     0 0           0                                                       |
  ------------------------------------------------------------------------------------------------
*/
static const unsigned char PROGMEM yuzhi[96] = {0x04, 0x00, 0x10, 0x02, 0x00, 0x00, 0xE8, 0x3F, 0x10, 0x02, 0x00, 0x00, 0x00, 0x21, 0xF0, 0x3F, 0x00, 0x00, 0x02, 0x25, 0x08, 0x02, 0x00, 0x00, 0x02, 0x29, 0x08, 0x02, 0x00, 0x00, 0xFA, 0x2F, 0xCC, 0x1F, 0x00, 0x00, 0x02, 0x21, 0x4C, 0x10, 0x00, 0x00, 0x72, 0x25, 0xCA, 0x1F, 0x00, 0x00, 0x52, 0x25, 0x49, 0x10, 0x00, 0x00, 0x72, 0x25, 0xC8, 0x1F, 0x0C, 0x00, 0x02, 0x23, 0x48, 0x10, 0x0C, 0x00, 0x62, 0x2A, 0xC8, 0x1F, 0x00, 0x00, 0x1A, 0x2D, 0x48, 0x10, 0x0C, 0x00, 0x82, 0x28, 0x48, 0x10, 0x0C, 0x00, 0x42, 0x20, 0xF8, 0x7F, 0x00, 0x00, 0x02, 0x30, 0x08, 0x00, 0x00, 0x00};
//字体:华文黑体  字号:16px  显示文字:温度:
/*
  ------------------------------------------------------------------------------------------------
  |                                              0                                               |
  |    0       0 0 0 0 0 0 0                       0                                             |
  |      0     0           0           0 0 0 0 0 0 0 0 0 0 0 0 0                                 |
  |      0     0           0           0       0       0                                         |
  |0           0 0 0 0 0 0 0           0       0       0                                         |
  |  0         0           0           0 0 0 0 0 0 0 0 0 0 0 0                                   |
  |  0         0           0           0       0       0                                         |
  |      0     0 0 0 0 0 0 0           0       0       0                                         |
  |      0                             0       0 0 0 0 0                                         |
  |    0     0 0 0 0 0 0 0 0 0         0                               0 0                       |
  |0 0 0     0     0   0     0         0   0 0 0 0 0 0 0 0             0 0                       |
  |    0     0     0   0     0         0     0           0                                       |
  |    0     0     0   0     0       0         0       0               0 0                       |
  |    0     0     0   0     0       0           0 0 0                 0 0                       |
  |    0   0 0 0 0 0 0 0 0 0 0 0   0         0 0       0 0                                       |
  |                                    0 0 0               0 0 0                                 |
  ------------------------------------------------------------------------------------------------
*/
static const unsigned char PROGMEM wendu[96] = {0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xC4, 0x1F, 0x00, 0x01, 0x00, 0x00, 0x48, 0x10, 0xFC, 0x7F, 0x00, 0x00, 0x48, 0x10, 0x44, 0x04, 0x00, 0x00, 0xC1, 0x1F, 0x44, 0x04, 0x00, 0x00, 0x42, 0x10, 0xFC, 0x3F, 0x00, 0x00, 0x42, 0x10, 0x44, 0x04, 0x00, 0x00, 0xC8, 0x1F, 0x44, 0x04, 0x00, 0x00, 0x08, 0x00, 0xC4, 0x07, 0x00, 0x00, 0xE4, 0x3F, 0x04, 0x00, 0x0C, 0x00, 0x27, 0x25, 0xF4, 0x0F, 0x0C, 0x00, 0x24, 0x25, 0x24, 0x08, 0x00, 0x00, 0x24, 0x25, 0x42, 0x04, 0x0C, 0x00, 0x24, 0x25, 0x82, 0x03, 0x0C, 0x00, 0xF4, 0x7F, 0x61, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x70, 0x00, 0x00};
//字体:华文黑体  字号:16px  显示文字:℃
/*
  --------------------------------
  |                              |
  |                              |
  |                              |
  |  0 0 0 0         0 0 0 0 0 0 |
  |  0     0 0     0 0       0 0 |
  |0 0     0 0   0 0           0 |
  |  0     0 0 0 0 0             |
  |  0 0 0 0   0 0 0             |
  |            0 0 0             |
  |            0 0 0             |
  |            0 0 0             |
  |              0 0             |
  |              0 0 0         0 |
  |                  0 0 0 0 0   |
  |                              |
  |                              |
  --------------------------------
*/
static const unsigned char PROGMEM du[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xFE, 0x32, 0xE3, 0xB3, 0xC1, 0xF2, 0x81, 0xDE, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x81, 0x80, 0xC3, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00};
volatile double Input;             //输入值
volatile double Output;            //输出的pwm
volatile double Setpoint;          //目标值
volatile int tem;                  //温度
volatile int tem_test;             //温度阈值
volatile boolean run_state;        //运行状态
U8G2_SSD1306_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
PID myPID(&Input, &Output, &Setpoint, 2, 5, 1, DIRECT);
OneWire oneWire_4(4);
DallasTemperature sensors_4(&oneWire_4);
DeviceAddress insideThermometer;

//获取温度
float ds18b20_4_getTemp(int w) {
  sensors_4.requestTemperatures();
  if (w == 0) {
    return sensors_4.getTempC(insideThermometer);
  }
  else {
    return sensors_4.getTempF(insideThermometer);
  }
}

//OLED 屏幕显示
void page1() {
  u8g2.setFont(u8g2_font_timR14_tf);
  u8g2.setFontPosTop();
  u8g2.drawXBMP(0, 5, 48, 16, yuzhi);         //显示中文
  u8g2.setCursor(43, 5);                      //坐标
  u8g2.print(tem_test);                       //显示阈值
  u8g2.drawXBMP(65, 5, 16, 16, du);
  u8g2.drawXBMP(0, 20, 48, 16, wendu);
  u8g2.setCursor(43, 20);
  u8g2.print(tem);
  u8g2.drawXBMP(65, 20, 16, 16, du);
}

void setup() {
  Input = 0;
  Output = 0;
  Setpoint = 70;
  tem = 0;
  tem_test = 70;                             //初始值
  run_state = false;
  Serial.begin(9600);
  u8g2.setI2CAddress(0x3C * 2);              //屏幕地址
  u8g2.begin();
  pinMode(2, OUTPUT);
  myPID.SetMode(AUTOMATIC);
  digitalWrite(2, LOW);
  pinMode(key_start, INPUT_PULLUP);
  pinMode(key_add, INPUT_PULLUP);
  pinMode(key_less, INPUT_PULLUP);
  sensors_4.getAddress(insideThermometer, 0);
  sensors_4.setResolution(insideThermometer, 9);
  u8g2.enableUTF8Print();

}

void loop() {
  if (true == run_state) {                           //如果是运行模式
    tem = ds18b20_4_getTemp(0);                      //获取温度
    Input = tem;                                     //赋值给输入值
    myPID.Compute();                                 //进行pwm算法
    analogWrite(3, Output);                          //输出pwm
    Serial.println(Output);
    if (0 == digitalRead(key_add)) {                 //如果增加按键按下
      tem_test = constrain(tem_test + 1, 1, 100);    //阈值加1
      Setpoint = tem_test;         //赋值给目标值
      while (0 == digitalRead(key_add)) {
        delay(1);
      }
      delay(10);

    }
    if (0 == digitalRead(key_less)) {                //减少按键
      tem_test = constrain(tem_test - 1, 1, 100);
      Setpoint = tem_test;
      while (0 == digitalRead(key_less)) {
        delay(1);
      }
      delay(10);

    }
    u8g2.firstPage();                               //刷新屏幕
    do
    {
      page1();
    } while (u8g2.nextPage());
    if (80 < tem) {                                //如果温度超过设定的最大值
      analogWrite(3, 0);                           //关闭输出
      u8g2.clearDisplay();                         //清空屏幕
      run_state = false;                           //停止运行

    }

  }
  if (0 == digitalRead(key_start)) {              //如果开始按键按下
    delay(10);
    while (0 == digitalRead(key_start)) {
      delay(1);
    }
    delay(10);
    run_state = !run_state;                       //运行模式取反

  }

}