├── Gerber_(板厚0.8mm)328P迷你PD烙铁(合并).zip ├── Gerber_0.91OLED屏幕.zip ├── Gerber_V1.1主控屏幕合并.zip ├── Gerber_V1.1合并无开槽.zip ├── Gerber_V1.1拨码开关.zip ├── Gerber_单主控板_328P迷你PD烙铁.zip ├── Gerber_支架_2021-02-27.zip ├── Gerber_触摸支架_2021-03-26.zip ├── Picture ├── 1.png ├── 10.jpg ├── 11.jpg ├── 2.jpg ├── 4.jpg ├── 5.jpg ├── 6.png ├── 7.png ├── 8.jpg └── 9.jpg ├── README.md ├── Schematic_328P迷你PD电烙铁.pdf ├── Schematic_328P迷你PD电烙铁V1.1.pdf ├── v1.03 ├── A_ReadMe.ino ├── Buzzer.ino ├── CurveFitting.ino ├── Display.ino ├── DisplayMain.ino ├── DisplaySet.ino ├── EEPROM.ino ├── InterruptKey.ino ├── MsTimer2.ino ├── PID.ino ├── Sleep.ino ├── WDT.ino ├── analogRead.ino └── v1.03.ino ├── v1.20.1 ├── A_ReadMe.ino ├── Buzzer.ino ├── CurveFitting.ino ├── Display.ino ├── DisplayMain.ino ├── DisplaySet.ino ├── EEPROM.ino ├── InterruptKey.ino ├── MsTimer2.ino ├── PID.ino ├── Sleep.ino ├── WDT.ino ├── analogRead.ino ├── font.c ├── v1.20.1.ino ├── v1.20.1.ino.eep ├── v1.20.1.ino.hex └── v1.20.1.ino.with_bootloader.hex ├── 主控板+屏幕V1.0版本iBOM.html ├── 主控板+屏幕V1.1版本iBOM.html └── 用到的库 ├── MsTimer2.zip └── U8g2-2020-11-15.7z /Gerber_(板厚0.8mm)328P迷你PD烙铁(合并).zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Gerber_(板厚0.8mm)328P迷你PD烙铁(合并).zip -------------------------------------------------------------------------------- /Gerber_0.91OLED屏幕.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Gerber_0.91OLED屏幕.zip -------------------------------------------------------------------------------- /Gerber_V1.1主控屏幕合并.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Gerber_V1.1主控屏幕合并.zip -------------------------------------------------------------------------------- /Gerber_V1.1合并无开槽.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Gerber_V1.1合并无开槽.zip -------------------------------------------------------------------------------- /Gerber_V1.1拨码开关.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Gerber_V1.1拨码开关.zip -------------------------------------------------------------------------------- /Gerber_单主控板_328P迷你PD烙铁.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Gerber_单主控板_328P迷你PD烙铁.zip -------------------------------------------------------------------------------- /Gerber_支架_2021-02-27.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Gerber_支架_2021-02-27.zip -------------------------------------------------------------------------------- /Gerber_触摸支架_2021-03-26.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Gerber_触摸支架_2021-03-26.zip -------------------------------------------------------------------------------- /Picture/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Picture/1.png -------------------------------------------------------------------------------- /Picture/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Picture/10.jpg -------------------------------------------------------------------------------- /Picture/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Picture/11.jpg -------------------------------------------------------------------------------- /Picture/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Picture/2.jpg -------------------------------------------------------------------------------- /Picture/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Picture/4.jpg -------------------------------------------------------------------------------- /Picture/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Picture/5.jpg -------------------------------------------------------------------------------- /Picture/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Picture/6.png -------------------------------------------------------------------------------- /Picture/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Picture/7.png -------------------------------------------------------------------------------- /Picture/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Picture/8.jpg -------------------------------------------------------------------------------- /Picture/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Picture/9.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 328P-MiNi-T12(所有文件打板不过审我不管!) 2 | - 所有文件不定期更新 3 | 4 | ## 更新历史 5 | - 2021.5.18 上传拨码开关版本PCB Gerber文件 6 | - 2021.4.5 上传已修改适配的甘草最新1.20版本程序 7 | - 2021.2.28 上传V1.1版本的iBOM以及原理图 8 | - 2021.3.26 更新触摸版本控制的支架(接线方法及所需元器件后期更新)打板不过审我不管 9 | - 2021.3.23 更新V1.1版本Gerber文件 10 | - 2021.2.27 上传支架Gerber文件 11 | - 2021.2.17 重新上传分开打板的文件并更新README.md 12 | - 2021.2.16 将主控板以及屏幕合并为同一打板文件并更新iBOM文件并更新README.md 13 | 14 | ## 注意事项 15 | - 屏幕主控在一起的板子没有打板过,不知道能不能过JLC审核(故保留分开打板的Gerber文件) 16 | - 合并的Gerber与分开的Gerber背面的焊点位置及丝印位置有些许差距,完全不影响 17 | - 屏幕和主控板暂时采用飞线连接 18 | 19 | ***支架板厚 1.0mm*** 20 | 21 | ***主控板及屏幕板厚 0.8mm*** 22 | 23 | ## 套件及成品开车QQ群:903440195(***不提供解决疑难杂症服务***) 24 | 25 | [B站视频地址①](https://www.bilibili.com/video/BV1q54y1p7Bn)              [B站视频地址②](https://www.bilibili.com/video/BV1bz4y1m7pS) 26 | 27 | 项目源码及原理图基于 https://github.com/jie326513988/mini-T12 修改 28 | 29 | 以下带亚克力管的支架为触摸控制的支架,文件后续更新上来 30 | 31 |
32 | 33 |
34 | 35 |

36 | *** 37 | ### 主控板成品照片 38 | 39 | V1.0版本 40 | 41 |
42 | 43 | V1.1版本 44 | 45 |

46 | *** 47 | ### 带有精美iBOM方便对照焊接 48 | 49 |
50 | -------------------------------------------------------------------------------- /Schematic_328P迷你PD电烙铁.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Schematic_328P迷你PD电烙铁.pdf -------------------------------------------------------------------------------- /Schematic_328P迷你PD电烙铁V1.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/Schematic_328P迷你PD电烙铁V1.1.pdf -------------------------------------------------------------------------------- /v1.03/A_ReadMe.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 校准温度曲线的方法 3 | 1.准备好能测量0 - 500摄氏度的设备,探头建议使用裸装,以免外壳热传导导致热量损失测量不准 4 | 2.将探头紧压住烙铁头发热前段(上锡部分再下来一点),一定要紧紧压住,不然也会测量不准 5 | 3.放置好烙铁头以免校准时烫伤手或物品! 6 | 4.接上电源,从控制板进入‘校准’界面,将空心选框移动至第1段温度处(即对应的ADC 10下面) 7 | 5.按下确认键,此时空心选框变成实心选框,烙铁头开始加热,等待最下方的‘Now ADC’值稳定在一定的范围,与第一行相应的ADC值差不多即可(此时是ADC 10) 8 | 6.使用测量设备测量烙铁头的温度,将第1段温度调至测量得到的温度(实心选框状态可旋转旋钮调节数值) 9 | 7.依次测量剩下的第2段、第3段、第4段温度并输入至控制器 10 | 8.测量完4段温度后将光标移至Save,按下确认键,等待程序计时温度曲线 11 | 9.计算完会显示P系数界面,,再按下确认键即可退出校准界面 12 | 10.在主界面准备进行二次校准 13 | 11.在主界面开启加热至第二段校准的温度,如265,则加热至260度,若显示温度比实际高的话就到校准界面调高第二段温度,低则调低 14 | 12.依次加热至第三第四段温度并校准,直至自己满意为止 15 | 13.进入到“烙铁”选项,将冷端补偿温度改为此时主界面所显示的环境温度值(屏幕右上角),完毕。 16 | */ 17 | 18 | /* 19 | 长按操作(5下短音最后1下长音) 20 | 主界面,进入设置界面 21 | 其他界面,退出至主界面 22 | 双击操作(2下短音) 23 | 主界面,加热或停止状态切换 24 | 其他界面,无 25 | 单击(1下短音) 26 | 主界面,无 27 | 设置界面,进入二级菜单 28 | 二级菜单,切换数值更改选中状态,或确认更改数值,无选框状态则退出至一级菜单 29 | */ 30 | -------------------------------------------------------------------------------- /v1.03/Buzzer.ino: -------------------------------------------------------------------------------- 1 | //********** 控制蜂鸣器发声的频率和时间,系统延时法,占用系统速度大 ********** 2 | uint32_t error_buzzer_db_time = 0; 3 | void buzzer_run() 4 | { 5 | if (buzzer_state == 1) 6 | { 7 | for (uint16_t i = 0; i < buzzer_count; i++) 8 | { 9 | digitalWrite(buzzer_pin, 1); 10 | delayMicroseconds(buzzer_time); 11 | digitalWrite(buzzer_pin, 0); 12 | if (i < buzzer_count - 1) delayMicroseconds(buzzer_time); //最后一次不需要延时 13 | } 14 | buzzer_state = 0; 15 | } 16 | //错误提示报警音 17 | if (vin_error == 1 || t12_adc_error == 1) 18 | { 19 | if (millis() - error_buzzer_db_time > 1000) 20 | { 21 | buzzer(120, 300); 22 | error_buzzer_db_time = millis(); 23 | } 24 | } 25 | 26 | if (buzzer_szjm_state == 1) //进入设置界面时发出声音提示一下 27 | { 28 | buzzer(150, 720); 29 | buzzer_szjm_state = 0; 30 | } 31 | else if (buzzer_zjm_state == 1) //退出至主界面时发出声音提示一下 32 | { 33 | buzzer(150, 720); 34 | buzzer_zjm_state = 0; 35 | } 36 | } 37 | 38 | void buzzer(uint16_t time, uint16_t count) 39 | { 40 | buzzer_state = 1; //准备好蜂鸣器 41 | buzzer_time = time; //设置时间 42 | buzzer_count = count; //设置次数 43 | } 44 | //********************************************************* 45 | 46 | //****** 控制蜂鸣器发声的频率和时间,内部中断法,占用系统速度小 ****** 47 | 48 | /*void buzzer(uint16_t time, uint16_t count) //时间单位ms 49 | { 50 | if (buzzer_state == 0 && digitalRead(buzzer_pin) == 0) //蜂鸣器停止状态才能设置定时器 51 | { 52 | buzzer_count = count; //设置次数 53 | Timer1.initialize(time); //设置时间 54 | Timer1.attachInterrupt(buzzer_isr); //设置定时器中断函数 55 | Timer1.start(); //启动定时器 56 | } 57 | } 58 | void buzzer_isr() 59 | { 60 | buzzer_isr_count++; 61 | bitWrite(PINB, 0, 1); //设置pin8为输出 PINX写1翻转状态 62 | buzzer_state = 1; //标识蜂鸣器正在工作 63 | if (buzzer_isr_count >= buzzer_count) 64 | { 65 | buzzer_isr_count = 0; // 清除计数 66 | buzzer_state = 0; //标识蜂鸣器已停止 67 | digitalWrite(buzzer_pin, 0); //关闭蜂鸣器 68 | Timer1.stop(); //停止中断 69 | } 70 | }*/ 71 | //********************************************************* 72 | uint8_t get_num_digit(uint32_t num)//获取数字的位数 73 | { 74 | uint8_t count = 0; 75 | if (num == 0) count = 1; 76 | while (num != 0) 77 | { 78 | // n = n/10 79 | num /= 10; 80 | ++count; 81 | } 82 | return count; 83 | } 84 | -------------------------------------------------------------------------------- /v1.03/CurveFitting.ino: -------------------------------------------------------------------------------- 1 | //********** 曲线拟合程序 ********** 2 | //曲线拟合算法来至https://blog.csdn.net/m0_37362454/article/details/82456616 by欧阳小俊 3 | void qxnh_run() //曲线拟合运行 4 | { 5 | int16_t i, sizenum; 6 | float P[4]; 7 | int8_t dimension = 3; //3次多项式拟合 8 | // 要拟合的数据 9 | int xx[] = {sz_adc0, sz_adc1, sz_adc2, sz_adc3}; //t12 adc 10 | //int yy[] = {45, 219, 366, 435}; //测量设备的温度 11 | 12 | sizenum = sizeof(xx) / sizeof(xx[0]); //拟合数据的维数 13 | polyfit(sizenum, xx, sz_temp, dimension, P); 14 | 15 | sz_p[0] = P[0]; 16 | sz_p[1] = P[1]; 17 | sz_p[2] = P[2]; 18 | sz_p[3] = P[3]; 19 | /* 20 | 得出系数:P[0],P[1],P[2] 21 | 曲线公式:y = P[3]*X*X*X+P[2]*X*X + P[1]*X + P[0] 22 | 曲线公式:t12_temp =P[3]* t12_ad * t12_ad* t12_ad + P[2] * t12_ad * t12_ad + P[1] * t12_ad + P[0]; 23 | */ 24 | } 25 | 26 | /*==================polyfit(n,x,y,poly_n,a)===================*/ 27 | /*=======拟合y=a0+a1*x+a2*x^2+……+apoly_n*x^poly_n========*/ 28 | /*=====n是数据个数 xy是数据值 poly_n是多项式的项数======*/ 29 | /*===返回a0,a1,a2,……a[poly_n],系数比项数多一(常数项)=====*/ 30 | void polyfit(int n, int x[], int y[], int poly_n, float p[]) 31 | { 32 | int i, j; 33 | float *tempx, *tempy, *sumxx, *sumxy, *ata; 34 | 35 | tempx = (float *)calloc(n , sizeof(float)); 36 | sumxx = (float *)calloc((poly_n * 2 + 1) , sizeof(float)); 37 | tempy = (float *)calloc(n , sizeof(float)); 38 | sumxy = (float *)calloc((poly_n + 1) , sizeof(float)); 39 | ata = (float *)calloc( (poly_n + 1) * (poly_n + 1) , sizeof(float) ); 40 | for (i = 0; i < n; i++) 41 | { 42 | tempx[i] = 1; 43 | tempy[i] = y[i]; 44 | } 45 | for (i = 0; i < 2 * poly_n + 1; i++) 46 | { 47 | for (sumxx[i] = 0, j = 0; j < n; j++) 48 | { 49 | sumxx[i] += tempx[j]; 50 | tempx[j] *= x[j]; 51 | } 52 | } 53 | for (i = 0; i < poly_n + 1; i++) 54 | { 55 | for (sumxy[i] = 0, j = 0; j < n; j++) 56 | { 57 | sumxy[i] += tempy[j]; 58 | tempy[j] *= x[j]; 59 | } 60 | } 61 | for (i = 0; i < poly_n + 1; i++) 62 | { 63 | for (j = 0; j < poly_n + 1; j++) 64 | { 65 | ata[i * (poly_n + 1) + j] = sumxx[i + j]; 66 | } 67 | } 68 | gauss_solve(poly_n + 1, ata, p, sumxy); 69 | 70 | free(tempx); 71 | free(sumxx); 72 | free(tempy); 73 | free(sumxy); 74 | free(ata); 75 | } 76 | /*============================================================ 77 | 高斯消元法计算得到 n 次多项式的系数 78 | n: 系数的个数 79 | ata: 线性矩阵 80 | sumxy: 线性方程组的Y值 81 | p: 返回拟合的结果 82 | ============================================================*/ 83 | void gauss_solve(int n, float A[], float x[], float b[]) 84 | { 85 | int i, j, k, r; 86 | float max; 87 | for (k = 0; k < n - 1; k++) 88 | { 89 | max = fabs(A[k * n + k]); // find maxmum 90 | r = k; 91 | for (i = k + 1; i < n - 1; i++) 92 | { 93 | if (max < fabs(A[i * n + i])) 94 | { 95 | max = fabs(A[i * n + i]); 96 | r = i; 97 | } 98 | } 99 | if (r != k) 100 | { 101 | for (i = 0; i < n; i++) //change array:A[k]&A[r] 102 | { 103 | max = A[k * n + i]; 104 | A[k * n + i] = A[r * n + i]; 105 | A[r * n + i] = max; 106 | } 107 | max = b[k]; //change array:b[k]&b[r] 108 | b[k] = b[r]; 109 | b[r] = max; 110 | } 111 | 112 | for (i = k + 1; i < n; i++) 113 | { 114 | for (j = k + 1; j < n; j++) 115 | A[i * n + j] -= A[i * n + k] * A[k * n + j] / A[k * n + k]; 116 | b[i] -= A[i * n + k] * b[k] / A[k * n + k]; 117 | } 118 | } 119 | 120 | for (i = n - 1; i >= 0; x[i] /= A[i * n + i], i--) 121 | { 122 | for (j = i + 1, x[i] = b[i]; j < n; j++) 123 | x[i] -= A[i * n + j] * x[j]; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /v1.03/Display.ino: -------------------------------------------------------------------------------- 1 | //********** 显示决策 ********** 2 | uint32_t system_sleep_db_time = 0; //系统进入睡眠对比时间 3 | void display() 4 | { 5 | if (xp_state == 0) //正常显示 6 | { 7 | if (display_count == ZJM) zjm(); 8 | else if (display_count == SZJM) szjm(); 9 | else if (display_count == SZJM_PID) szjm_pid(); 10 | else if (display_count == SZJM_SLEEP) szjm_sleep(); 11 | else if (display_count == SZJM_OLED) szjm_oled(); 12 | else if (display_count == SZJM_POWER) szjm_power(); 13 | else if (display_count == SZJM_LAOTIE) szjm_laotie(); 14 | else if (display_count == SZJM_JIAOZHUN) szjm_jiaozhun(); 15 | } 16 | else xpjm(); //显示息屏界面 17 | } 18 | 19 | void draw_page(void) 20 | { 21 | static uint8_t is_next_page = 0; 22 | // 调用第一页,如果需要 23 | if ( is_next_page == 0 ) 24 | { 25 | u8g2.firstPage(); 26 | is_next_page = 1; 27 | } 28 | // 画我们的屏幕 29 | display(); 30 | // 调用下一页 31 | if ( u8g2.nextPage() == 0 ) 32 | { 33 | is_next_page = 0; // 确保调用了第一个页面 34 | } 35 | } 36 | 37 | void display_hfccsz() //恢复出厂设置进度显示界面 38 | { 39 | uint16_t x_old = 0; 40 | for (int i = 0 ; i < EEPROM.length() ; i++) 41 | { 42 | __asm__ __volatile__ ("wdr"); //防止没清除完因看门狗没喂狗导致重启 43 | uint16_t x_new = map(i, 0, EEPROM.length(), 0, 100); 44 | if (x_new - x_old >= 5) 45 | { 46 | u8g2.firstPage(); 47 | do { 48 | u8g2.setCursor(50, 16); 49 | u8g2.print(x_new); 50 | u8g2.setCursor(75, 16); 51 | u8g2.print("%"); 52 | x_old = x_new; 53 | } while ( u8g2.nextPage() ); 54 | } 55 | EEPROM.write(i, 0); //清除所有EEPROM 56 | } 57 | set_wdt_mod(1, 0); //利用看门狗实现软重启 58 | } 59 | 60 | void kj_display() //开机显示版本号 61 | { 62 | u8g2.firstPage(); 63 | do { 64 | u8g2.setFont(chinese15); 65 | u8g2.setCursor(50, 21); 66 | u8g2.print(version); 67 | } while ( u8g2.nextPage() ); 68 | } 69 | 70 | void xpjm() //息屏界面 71 | { 72 | if (xp_x - xp_x_old > 0) 73 | { 74 | if (xp_x_old != xp_x) xp_x_old++; 75 | } 76 | else if (xp_x - xp_x_old < 0 ) 77 | { 78 | if (xp_x_old != xp_x) xp_x_old--; 79 | } 80 | 81 | if (xp_y - xp_y_old > 0) 82 | { 83 | if (xp_y_old != xp_y) xp_y_old++; 84 | } 85 | else if (xp_y - xp_y_old < 0 ) 86 | { 87 | if (xp_y_old != xp_y) xp_y_old--; 88 | } 89 | 90 | u8g2.setFont(chinese15); 91 | u8g2.setCursor(xp_x_old, xp_y_old); 92 | u8g2.print(tc1047_temp, 1); 93 | u8g2.setCursor(xp_x_old + 27, xp_y_old - 1); 94 | u8g2.print("℃"); 95 | } 96 | 97 | /*u8g2.firstPage(); 98 | do { 99 | u8g2.setFont(chinese15); 100 | u8g2.setCursor(xp_x, xp_y); 101 | u8g2.print(tc1047_temp, 1); 102 | u8g2.setCursor(xp_x + 27, xp_y - 1); 103 | u8g2.print("℃"); 104 | } while ( u8g2.nextPage() );*/ 105 | -------------------------------------------------------------------------------- /v1.03/DisplayMain.ino: -------------------------------------------------------------------------------- 1 | //********** 画主界面 ********** 2 | uint8_t zjm_x1 = 0; 3 | uint8_t zjm_x2 = 100; 4 | #define zjm_x3 75 5 | #define zjm_x4 zjm_x3+4 6 | 7 | #define zjm_y1 7 8 | #define zjm_y2 19 9 | #define zjm_y3 32 10 | #define zjm_y4 14 11 | boolean zjm_dh_run = 0; //主界面动画状态 0-不允许 1-允许 12 | uint32_t zjm_dh_time1 = 0; //动画1运转对比时间 13 | uint32_t zjm_dh_time2 = 0; //动画2运转对比时间 14 | //热、停切换动画变量 15 | uint8_t zjm_dh_x1 = 0; 16 | uint8_t zjm_dh_y1 = 0; 17 | uint8_t zjm_dh_r1 = 1; 18 | //pwm动效动画 19 | uint8_t zjm_dh_l[14]; 20 | //开机过度动画y增量 21 | int8_t zjm_dh_y = 32; 22 | void zjm() 23 | { 24 | //****** 画当前温度及烙铁错误提示 25 | if (t12_error == 0 && t12_adc_error == 0) //正常画面 26 | { 27 | u8g2.setFont(u8g2_font_bubble_tn); 28 | if (t12_temp >= 99)u8g2.setCursor(0, zjm_dh_y + 18); 29 | else u8g2.setCursor(10, zjm_dh_y + 18); 30 | if (t12_switch == 1 && (thisError_average <= 4 && thisError_average >= -4)) u8g2.print(t12_temp_average); 31 | else u8g2.print(t12_temp); 32 | } 33 | else if (t12_adc_error == 1) zjm_error2(); //T12ADC超出测量范围画面 34 | else if (t12_error == 1) zjm_error3(); //手柄未接显示画面 35 | //****** 画设置温度进度条 36 | u8g2.setFont(u8g2_font_saikyosansbold8_8n); 37 | //自动获取设置温度的范围 38 | set_temp_max = ((sz_temp[3]) / 10 ) * 10; 39 | set_temp_min = ((sz_temp[0]) / 10) * 10; 40 | zjm_x1 = map(set_temp, set_temp_min, set_temp_max, 3, 57); 41 | u8g2.drawDisc(zjm_x1, zjm_dh_y + 28, 2);//画实心圆 42 | u8g2.drawBox(0, zjm_dh_y + 30, 61, 2); //画实心框 43 | if (set_temp <= 260)u8g2.setCursor(zjm_x1 + 4, zjm_dh_y + 29); //画设置温度 44 | else u8g2.setCursor(zjm_x1 - 26, zjm_dh_y + 29); //画设置温度 45 | u8g2.print(set_temp); 46 | 47 | //****** 画加热提示及切换动画 48 | u8g2.setFont(chinese15); 49 | if (zjm_dh_y != 0) //开机过渡动画变量变化 50 | { 51 | zjm_dh_y --; 52 | u8g2.setCursor(50, zjm_dh_y - 11); 53 | u8g2.print(version); 54 | } 55 | if (/*millis() - zjm_dh_time1 > 30 &&*/ zjm_dh_run == 1) 56 | { 57 | if (zjm_dh_x1 < 7) 58 | { 59 | zjm_dh_x1++; 60 | zjm_dh_y1++; 61 | if (zjm_dh_x1 == 7) 62 | { 63 | zjm_dh_r1 = 0; 64 | if (t12_switch == 1 && zjm_sleep_ts == 0) EEPROM.put(set_temp_eeprom, set_temp); //停止时保存当前的设置温度 65 | t12_switch = !t12_switch; //动画播放完,切换T12工作状态 66 | MsTimer2::stop(); //停止一次 然后在MsTimer2_rw1()里自动切换定时的中断任务 67 | } 68 | zjm_dh_time1 = millis(); 69 | } 70 | else if (zjm_dh_x1 >= 7 && millis() - zjm_dh_time1 > 300) 71 | { 72 | zjm_dh_x1 = 0; 73 | zjm_dh_y1 = 0; 74 | zjm_dh_r1 = 1; 75 | zjm_dh_run = 0; //关闭动画 76 | } 77 | } 78 | u8g2.drawRFrame(zjm_x3 - 3, zjm_dh_y + zjm_y4 - 14, 18, 18, 3); //空心圆角方形 79 | u8g2.setCursor(zjm_x3, zjm_dh_y + zjm_y4); 80 | if (t12_switch == 1 && zjm_sleep_ts == 0) u8g2.print("热"); 81 | else if (t12_switch == 1 && zjm_sleep_ts == 1) u8g2.print("休"); 82 | else u8g2.print("停"); 83 | if (zjm_dh_x1 == 7)u8g2.setDrawColor(2); 84 | u8g2.drawRBox(80 - zjm_dh_x1, zjm_dh_y + 8 - zjm_dh_y1, 2 + zjm_dh_x1 * 2, 2 + zjm_dh_y1 * 2, zjm_dh_r1); //实心圆角方形 85 | if (zjm_dh_x1 == 7)u8g2.setDrawColor(1); 86 | 87 | //****** 画PWM输出比例动画 88 | if (t12_switch == 1) 89 | { 90 | uint16_t zjm_pwmdh_time = map(pid_out, pwm_min, pwm_max, 450, 150); //输出比例决定刷新时间 91 | uint8_t zjm_pwmdh_l = map(pid_out, pwm_min, pwm_max, 3, 12); //输出比例决定L的最大值 92 | if (millis() - zjm_dh_time2 > zjm_pwmdh_time) 93 | { 94 | for (uint8_t i = 0; i < 14; i++) 95 | { 96 | zjm_dh_l[i] = random(1, zjm_pwmdh_l); 97 | } 98 | zjm_dh_time2 = millis(); 99 | } 100 | 101 | for (uint8_t i = 0; i < 14; i++) 102 | { 103 | u8g2.drawLine(74 + i, zjm_dh_y + 32, 74 + i, zjm_dh_y + 32 - zjm_dh_l[i]); //绘制垂直线,X,Y,长度 104 | //delay(100); 105 | } 106 | } 107 | else u8g2.drawHLine(74, zjm_dh_y + 31, 14); 108 | 109 | //****** 画室温-电压-电流-工作状态 110 | if (vin_error == 1) zjm_error1(); //电压电流有一个报警就显示 报警提示画面 111 | else zjm_vin_ec_temp_state(); //显示正常画面 112 | 113 | //****** 调试信息显示 114 | //u8g2.setCursor(75, 32); 115 | //u8g2.print(zjm_ca_count); 116 | } 117 | 118 | 119 | void zjm_vin_ec_temp_state() //画室温-电压-电流-工作状态 120 | { 121 | //画室温-电压 122 | u8g2.setFont(u8g2_font_lucasfont_alternate_tr); 123 | u8g2.setCursor(zjm_x2, zjm_dh_y + zjm_y1); 124 | u8g2.print(tc1047_temp, 1); 125 | u8g2.drawCircle(zjm_x2 + 21, zjm_dh_y + zjm_y1 - 6, 1, U8G2_DRAW_ALL); //画空心圆 126 | u8g2.setCursor(zjm_x2 + 23, zjm_dh_y + zjm_y1); 127 | u8g2.print("C"); 128 | 129 | u8g2.setCursor(zjm_x2, zjm_dh_y + zjm_y2); 130 | u8g2.print(vin, 1); 131 | u8g2.setCursor(zjm_x2 + 22, zjm_dh_y + zjm_y2); 132 | u8g2.print("V"); 133 | 134 | u8g2.setCursor(zjm_x2, zjm_dh_y + zjm_y3); 135 | u8g2.print(pid_out_bfb); 136 | u8g2.setCursor(zjm_x2 + 20, zjm_dh_y + zjm_y3); 137 | u8g2.print("%"); 138 | 139 | //u8g2.setCursor(70, 27); 140 | //u8g2.print(t12_ad,0); 141 | 142 | //u8g2.setCursor(45, 27); 143 | //u8g2.print(sleep_count); 144 | //u8g2.setCursor(65, 27); 145 | //u8g2.print(xp_time_count); 146 | 147 | /*u8g2.setCursor(55, 13); 148 | u8g2.print(sleep_MsTimer2_state);*/ 149 | 150 | //u8g2.setCursor(50, 27); 151 | //u8g2.print(pid_out); 152 | 153 | //u8g2.setCursor(0, 29); 154 | //u8g2.print(t12_temp_read_time); 155 | 156 | //u8g2.setCursor(0, 29); 157 | //u8g2.print(analogRead(tc1047_pin)); 158 | } 159 | void zjm_error1() //主界面 电压电流报警 提示 160 | { 161 | u8g2.setFont(chinese15); 162 | if (vin_error == 1) 163 | { 164 | u8g2.setCursor(95, zjm_dh_y + 13); 165 | u8g2.print("电 压"); 166 | u8g2.setCursor(95, zjm_dh_y + 29); 167 | u8g2.print("过 低"); 168 | } 169 | u8g2.setDrawColor(2); 170 | u8g2.drawBox(95 - 2, zjm_dh_y + 0, 40, 32); //实心方形 171 | u8g2.setDrawColor(1); 172 | } 173 | void zjm_error2() //主界面 温度超出测量范围 错误提示 174 | { 175 | u8g2.setFont(u8g2_font_lucasfont_alternate_tr); 176 | u8g2.setCursor(12, zjm_dh_y + 8); 177 | u8g2.print("T12 ADC"); 178 | u8g2.setCursor(23, zjm_dh_y + 17); 179 | u8g2.print("HIGH"); 180 | u8g2.setDrawColor(2); 181 | u8g2.drawBox(0, zjm_dh_y + 0, 61, 18); //实心方形 182 | u8g2.setDrawColor(1); 183 | } 184 | void zjm_error3() //主界面 手柄未接显示界面 错误提示 185 | { 186 | u8g2.setFont(chinese15); 187 | u8g2.setCursor(5, zjm_dh_y + 14); 188 | u8g2.print("手柄未接"); 189 | 190 | u8g2.setDrawColor(2); 191 | u8g2.drawBox(0, zjm_dh_y + 0, 61, 18); //实心方形 192 | u8g2.setDrawColor(1); 193 | } 194 | -------------------------------------------------------------------------------- /v1.03/DisplaySet.ino: -------------------------------------------------------------------------------- 1 | //********** 画设置主界面及其他界面 ********** 2 | #define szjm_y1 21 3 | int16_t szjm_dh_x[6] = {0, 50, 100, 150, 200, 250}; 4 | int16_t szjm_dh_x_count = 0; //设置界面动画x增量记录 5 | 6 | #define szjm_dh_bc 5 //变化步长,只能为5的倍数 7 | void szjm() 8 | { 9 | //画十字坐标 10 | //u8g2.drawHLine(0, 15, 128); 11 | //u8g2.drawVLine(63, 0, 32); 12 | //********** 线性滚动动画 13 | if (szjm_kxxk_L == 1) //顺时针滚动 14 | { 15 | szjm_dh_x_count += szjm_dh_bc; //记录变化次数 16 | for (uint8_t i = 0; i < 6; i++) //开始变化 17 | { 18 | szjm_dh_x[i] += szjm_dh_bc; //步长5 19 | } 20 | for (uint8_t i = 0; i < 6; i++) //数值限制 21 | { 22 | if (szjm_dh_x[i] > 250)szjm_dh_x[i] = -45; 23 | } 24 | if (szjm_dh_x_count >= 50) //变化完毕 25 | { 26 | szjm_kxxk_L = 0; //释放状态 27 | szjm_dh_x_count = 0; //变化次数清零 28 | if (szjm_kxxk_count >= 6) szjm_kxxk_count = 0; //数值限制 29 | } 30 | } 31 | else if (szjm_kxxk_R == 1) //逆时针滚动 32 | { 33 | szjm_dh_x_count -= szjm_dh_bc; //记录变化次数 34 | for (uint8_t i = 0; i < 6; i++) //开始变化 35 | { 36 | szjm_dh_x[i] -= szjm_dh_bc; //步长5 37 | } 38 | for (uint8_t i = 0; i < 6; i++) //数值限制 39 | { 40 | if (szjm_dh_x[i] < -150)szjm_dh_x[i] = 145; 41 | } 42 | if (szjm_dh_x_count <= -50) //变化完毕 43 | { 44 | szjm_kxxk_R = 0; //释放状态 45 | szjm_dh_x_count = 0; //变化次数清零 46 | if (szjm_kxxk_count <= -6) szjm_kxxk_count = 0; //数值限制 47 | } 48 | } 49 | //************************************************** 50 | //********** 画文字和框框 51 | //调试信息显示 52 | //u8g2.setFont(u8g2_font_lucasfont_alternate_tr); 53 | //u8g2.setCursor(0, 31); 54 | //u8g2.print(szjm_dh_x_count); 55 | //u8g2.setCursor(100, 31); 56 | //u8g2.print(szjm_kxxk_count); 57 | //u8g2.setCursor(50, 31); 58 | //u8g2.print(szjm_dh_x[0]); 59 | 60 | u8g2.setFont(chinese15); 61 | if (szjm_dh_x[0] >= -50 && szjm_dh_x[0] <= 150) 62 | { 63 | u8g2.setCursor(szjm_dh_x[0], szjm_y1); 64 | u8g2.print("PID"); 65 | } 66 | if (szjm_dh_x[1] >= -50 && szjm_dh_x[1] <= 150) 67 | { 68 | u8g2.setCursor(szjm_dh_x[1], szjm_y1); 69 | u8g2.print("休眠"); 70 | } 71 | if (szjm_dh_x[2] >= -50 && szjm_dh_x[2] <= 150) 72 | { 73 | u8g2.setCursor(szjm_dh_x[2], szjm_y1); 74 | u8g2.print("屏幕"); 75 | } 76 | if (szjm_dh_x[3] >= -50 && szjm_dh_x[3] <= 150) 77 | { 78 | u8g2.setCursor(szjm_dh_x[3], szjm_y1); 79 | u8g2.print("电源"); 80 | } 81 | if (szjm_dh_x[4] >= -50 && szjm_dh_x[4] <= 150) 82 | { 83 | u8g2.setCursor(szjm_dh_x[4], szjm_y1); 84 | u8g2.print("校准"); 85 | } 86 | if (szjm_dh_x[5] >= -50 && szjm_dh_x[5] <= 150) 87 | { 88 | u8g2.setCursor(szjm_dh_x[5], szjm_y1); 89 | u8g2.print("烙铁"); 90 | } 91 | u8g2.setDrawColor(2); 92 | u8g2.drawRBox(43, 6, 40, 20, 1); //空心圆角方形 93 | u8g2.setDrawColor(1); 94 | } 95 | 96 | //********** PID设置界面 ********** 97 | #define szjm_pid_x1 2 98 | #define szjm_pid_x2 14 99 | 100 | #define szjm_pid_x3 82 101 | #define szjm_pid_x4 94 102 | 103 | #define szjm_pid_y1 14 104 | #define szjm_pid_y2 29 105 | void szjm_pid() 106 | { 107 | u8g2.setCursor(szjm_pid_x1, szjm_pid_y1); 108 | u8g2.print("P"); 109 | u8g2.setCursor(szjm_pid_x2, szjm_pid_y1); 110 | u8g2.print(p, 1); 111 | 112 | u8g2.setCursor(szjm_pid_x3, szjm_pid_y1); 113 | u8g2.print("I"); 114 | u8g2.setCursor(szjm_pid_x4, szjm_pid_y1); 115 | u8g2.print(i, 1); 116 | 117 | u8g2.setCursor(szjm_pid_x1, szjm_pid_y2); 118 | u8g2.print("D"); 119 | u8g2.setCursor(szjm_pid_x2, szjm_pid_y2); 120 | u8g2.print(d, 1); 121 | 122 | //画选框 123 | switch (szjm_pid_kxxk_count) //空心选框的位置 124 | { 125 | case 1: //p 126 | if (szjm_pid_sxxk_count == szjm_pid_kxxk_count) 127 | { 128 | u8g2.setDrawColor(2); 129 | u8g2.drawBox(szjm_pid_x1 - 2, szjm_pid_y1 - 13, 48, 16); //实心方形 130 | //画水平线,标识进入小数点模式 131 | if (dec_state == 1) u8g2.drawHLine(szjm_pid_x2 + 4 + (get_num_digit(p) * 6), szjm_pid_y1 + 1, 10); 132 | u8g2.setDrawColor(1); 133 | } 134 | else u8g2.drawFrame(szjm_pid_x1 - 2, szjm_pid_y1 - 13, 48, 16); //空心方形 135 | break; 136 | case 2: //i 137 | if (szjm_pid_sxxk_count == szjm_pid_kxxk_count) 138 | { 139 | u8g2.setDrawColor(2); 140 | u8g2.drawBox(szjm_pid_x3 - 2, szjm_pid_y1 - 13, 48, 16); //实心方形 141 | //画水平线,标识进入小数点模式 142 | if (dec_state == 1) u8g2.drawHLine(szjm_pid_x4 + 4 + (get_num_digit(i) * 6), szjm_pid_y1 + 1, 10); 143 | u8g2.setDrawColor(1); 144 | } 145 | else u8g2.drawFrame(szjm_pid_x3 - 2, szjm_pid_y1 - 13, 48, 16); //空心方形 146 | break; 147 | case 3: //d 148 | if (szjm_pid_sxxk_count == szjm_pid_kxxk_count) 149 | { 150 | u8g2.setDrawColor(2); 151 | u8g2.drawBox(szjm_pid_x1 - 2, szjm_pid_y2 - 13, 48, 16); //实心方形 152 | //画水平线,标识进入小数点模式 153 | if (dec_state == 1) u8g2.drawHLine(szjm_pid_x2 + 4 + (get_num_digit(d) * 6), szjm_pid_y2 + 1, 10); 154 | u8g2.setDrawColor(1); 155 | } 156 | else u8g2.drawFrame(szjm_pid_x1 - 2, szjm_pid_y2 - 13, 48, 16); //空心方形 157 | break; 158 | } 159 | } 160 | 161 | //********** 休眠设置界面 ********** 162 | #define szjm_sleep_x1 2 163 | #define szjm_sleep_x2 105 164 | #define szjm_sleep_y1 14 165 | #define szjm_sleep_y2 29 166 | void szjm_sleep() 167 | { 168 | u8g2.setCursor(szjm_sleep_x1, szjm_sleep_y1); 169 | u8g2.print("休眠时间(S)"); 170 | u8g2.setCursor(szjm_sleep_x2, szjm_sleep_y1); 171 | u8g2.print(sleep_time); 172 | 173 | u8g2.setCursor(szjm_sleep_x1, szjm_sleep_y2); 174 | u8g2.print("休眠温度(℃)"); 175 | u8g2.setCursor(szjm_sleep_x2, szjm_sleep_y2); 176 | u8g2.print(sleep_temp); 177 | 178 | //画选框 179 | switch (szjm_sleep_kxxk_count) //空心选框的位置 180 | { 181 | case 1: //设置温度 182 | if (szjm_sleep_sxxk_count == szjm_sleep_kxxk_count) 183 | { 184 | u8g2.setDrawColor(2); 185 | u8g2.drawBox(szjm_sleep_x1 - 2, szjm_sleep_y1 - 13, 128, 16); //实心方形 186 | u8g2.setDrawColor(1); 187 | } 188 | else u8g2.drawFrame(szjm_sleep_x1 - 2, szjm_sleep_y1 - 13, 128, 16); //空心方形 189 | break; 190 | case 2: //设置温度 191 | if (szjm_sleep_sxxk_count == szjm_sleep_kxxk_count) 192 | { 193 | u8g2.setDrawColor(2); 194 | u8g2.drawBox(szjm_sleep_x1 - 2, szjm_sleep_y2 - 13, 128, 16); //实心方形 195 | u8g2.setDrawColor(1); 196 | } 197 | else u8g2.drawFrame(szjm_sleep_x1 - 2, szjm_sleep_y2 - 13, 128, 16); //空心方形 198 | break; 199 | } 200 | } 201 | 202 | //********** OLED亮度设置界面 ********** 203 | #define szjm_oled_x1 2 204 | #define szjm_oled_x2 106 205 | #define szjm_oled_x3 86 206 | #define szjm_oled_y1 14 207 | #define szjm_oled_y2 29 208 | void szjm_oled() 209 | { 210 | if (szjm_oled_kxxk_count == 3) //第2页 211 | { 212 | u8g2.setCursor(szjm_oled_x1, szjm_oled_y1); 213 | u8g2.print("旋转方向"); 214 | u8g2.setCursor(szjm_oled_x3, szjm_oled_y1); 215 | if (xzbmq_fx == 0) u8g2.print("顺+逆-"); 216 | else u8g2.print("顺-逆+"); 217 | } 218 | else //第1页 219 | { 220 | u8g2.setCursor(szjm_oled_x1, szjm_oled_y1); 221 | u8g2.print("屏幕亮度"); 222 | u8g2.setCursor(szjm_oled_x2, szjm_oled_y1); 223 | u8g2.print(oled_ld); 224 | 225 | u8g2.setCursor(szjm_oled_x1, szjm_oled_y2); 226 | u8g2.print("屏幕方向"); 227 | u8g2.setCursor(szjm_oled_x2, szjm_oled_y2); 228 | if (oled_fx == 0) u8g2.print("0"); 229 | else u8g2.print("180"); 230 | } 231 | //画选框 232 | switch (szjm_oled_kxxk_count) //空心选框的位置 233 | { 234 | case 1: //OLED亮度 235 | if (szjm_oled_sxxk_count == szjm_oled_kxxk_count) 236 | { 237 | u8g2.setDrawColor(2); 238 | u8g2.drawBox(szjm_oled_x1 - 2, szjm_oled_y1 - 13, 128, 16); //实心方形 239 | u8g2.setDrawColor(1); 240 | } 241 | else u8g2.drawFrame(szjm_oled_x1 - 2, szjm_oled_y1 - 13, 128, 16); //空心方形 242 | break; 243 | case 2: //OLED方向 244 | if (szjm_oled_sxxk_count == szjm_oled_kxxk_count) 245 | { 246 | u8g2.setDrawColor(2); 247 | u8g2.drawBox(szjm_oled_x1 - 2, szjm_oled_y2 - 13, 128, 16); //实心方形 248 | u8g2.setDrawColor(1); 249 | } 250 | else u8g2.drawFrame(szjm_oled_x1 - 2, szjm_oled_y2 - 13, 128, 16); //空心方形 251 | break; 252 | case 3: //旋转方向 253 | if (szjm_oled_sxxk_count == szjm_oled_kxxk_count) 254 | { 255 | u8g2.setDrawColor(2); 256 | u8g2.drawBox(szjm_oled_x1 - 2, szjm_oled_y1 - 13, 128, 16); //实心方形 257 | u8g2.setDrawColor(1); 258 | } 259 | else u8g2.drawFrame(szjm_oled_x1 - 2, szjm_oled_y1 - 13, 128, 16); //空心方形 260 | break; 261 | } 262 | } 263 | 264 | //********** 电源设置界面 ********** 265 | #define szjm_power_x1 2 266 | #define szjm_power_x2 100 267 | #define szjm_power_y1 14 268 | #define szjm_power_y2 29 269 | void szjm_power() 270 | { 271 | if (szjm_power_kxxk_count == 3) //第2页 272 | { 273 | u8g2.setCursor(szjm_power_x1, szjm_power_y1); 274 | u8g2.print("低压报警(V)"); 275 | u8g2.setCursor(szjm_power_x2, szjm_power_y1); 276 | if (vin_low >= 3.3) u8g2.print(vin_low, 1); 277 | else if (vin_low < 3.3) u8g2.print("关"); 278 | } 279 | else //第1页 280 | { 281 | u8g2.setCursor(szjm_power_x1, szjm_power_y1); 282 | u8g2.print("基准电压(V)"); 283 | u8g2.setCursor(szjm_power_x2, szjm_power_y1); 284 | u8g2.print(vcc_refer); 285 | u8g2.setCursor(szjm_power_x1, szjm_power_y2); 286 | u8g2.print("电源电压(V)"); 287 | if (vin_refer >= 0) 288 | { 289 | u8g2.setCursor(szjm_power_x2 - 8, szjm_power_y2); 290 | u8g2.print("+"); 291 | u8g2.setCursor(szjm_power_x2, szjm_power_y2); 292 | u8g2.print(vin_refer); 293 | } 294 | else 295 | { 296 | u8g2.setCursor(szjm_power_x2 - 6, szjm_power_y2); 297 | u8g2.print(vin_refer); 298 | } 299 | } 300 | //画选框 301 | switch (szjm_power_kxxk_count) //空心选框的位置 302 | { 303 | case 1: //基准电压(V) 304 | if (szjm_power_sxxk_count == szjm_power_kxxk_count) 305 | { 306 | u8g2.setDrawColor(2); 307 | u8g2.drawBox(szjm_power_x1 - 2, szjm_power_y1 - 13, 128, 16); //实心方形 308 | u8g2.setDrawColor(1); 309 | } 310 | else u8g2.drawFrame(szjm_power_x1 - 2, szjm_power_y1 - 13, 128, 16); //空心方形 311 | break; 312 | case 2: //基准电压(V) 313 | if (szjm_power_sxxk_count == szjm_power_kxxk_count) 314 | { 315 | u8g2.setDrawColor(2); 316 | u8g2.drawBox(szjm_power_x1 - 2, szjm_power_y2 - 13, 128, 16); //实心方形 317 | u8g2.setDrawColor(1); 318 | } 319 | else u8g2.drawFrame(szjm_power_x1 - 2, szjm_power_y2 - 13, 128, 16); //空心方形 320 | break; 321 | case 3: //电源电压(V) 322 | if (szjm_power_sxxk_count == szjm_power_kxxk_count) 323 | { 324 | u8g2.setDrawColor(2); 325 | u8g2.drawBox(szjm_power_x1 - 2, szjm_power_y1 - 13, 128, 16); //实心方形 326 | u8g2.setDrawColor(1); 327 | } 328 | else u8g2.drawFrame(szjm_power_x1 - 2, szjm_power_y1 - 13, 128, 16); //空心方形 329 | break; 330 | } 331 | } 332 | //********** 烙铁设置界面 ********** 333 | #define szjm_laotie_x1 2 334 | #define szjm_laotie_x4 105 335 | 336 | #define szjm_laotie_y1 14 337 | #define szjm_laotie_y2 29 338 | 339 | void szjm_laotie() 340 | { 341 | 342 | if (szjm_laotie_kxxk_count == 3) //第2页 343 | { 344 | u8g2.setCursor(szjm_laotie_x1, szjm_laotie_y1); 345 | u8g2.print("重置"); 346 | u8g2.setCursor(szjm_laotie_x4, szjm_laotie_y1); 347 | if (hfccsz_state == 1) u8g2.print("YES"); 348 | else u8g2.print("NO"); 349 | } 350 | else //第1页 351 | { 352 | u8g2.setCursor(szjm_laotie_x1, szjm_laotie_y1); 353 | u8g2.print("冷端补偿(℃)"); 354 | if (tc1047_refer <= -10) u8g2.setCursor(szjm_laotie_x4, szjm_laotie_y1); 355 | else u8g2.setCursor(szjm_laotie_x4, szjm_laotie_y1); 356 | u8g2.print(tc1047_refer); 357 | 358 | u8g2.setCursor(szjm_laotie_x1, szjm_laotie_y2); 359 | u8g2.print("开机加热"); 360 | u8g2.setCursor(szjm_laotie_x4, szjm_laotie_y2); 361 | if (t12_kj_jr == 1) u8g2.print("YES"); 362 | else u8g2.print("NO"); 363 | } 364 | 365 | //画选框 366 | switch (szjm_laotie_kxxk_count) //空心选框的位置 367 | { 368 | case 1: //冷端补偿 369 | if (szjm_laotie_sxxk_count == szjm_laotie_kxxk_count) 370 | { 371 | u8g2.setDrawColor(2); 372 | u8g2.drawBox(szjm_laotie_x1 - 2, szjm_laotie_y1 - 13, 128, 16); //实心方形 373 | u8g2.setDrawColor(1); 374 | } 375 | else u8g2.drawFrame(szjm_laotie_x1 - 2, szjm_laotie_y1 - 13, 128, 16); //空心方形 376 | break; 377 | case 2: //开机加热? 378 | if (szjm_laotie_sxxk_count == szjm_laotie_kxxk_count) 379 | { 380 | u8g2.setDrawColor(2); 381 | u8g2.drawBox(szjm_laotie_x1 - 2, szjm_laotie_y2 - 13, 128, 16); //实心方形 382 | u8g2.setDrawColor(1); 383 | } 384 | else u8g2.drawFrame(szjm_laotie_x1 - 2, szjm_laotie_y2 - 13, 128, 16); //空心方形 385 | break; 386 | case 3: //恢复出厂设置 387 | if (szjm_laotie_sxxk_count == szjm_laotie_kxxk_count) 388 | { 389 | u8g2.setDrawColor(2); 390 | u8g2.drawBox(szjm_laotie_x1 - 2, szjm_laotie_y1 - 13, 128, 16); //实心方形 391 | u8g2.setDrawColor(1); 392 | } 393 | else u8g2.drawFrame(szjm_laotie_x1 - 2, szjm_laotie_y1 - 13, 128, 16); //空心方形 394 | break; 395 | } 396 | } 397 | //********** 校准设置界面 ********** 398 | #define szjm_jiaozhun_x1 0 399 | 400 | #define szjm_jiaozhun_x2 30 401 | #define szjm_jiaozhun_x3 54 402 | #define szjm_jiaozhun_x4 80 403 | #define szjm_jiaozhun_x5 106 404 | 405 | #define szjm_jiaozhun_x6 102 406 | 407 | #define szjm_jiaozhun_y1 7 408 | #define szjm_jiaozhun_y2 18 409 | #define szjm_jiaozhun_y3 31 410 | void szjm_jiaozhun() 411 | { 412 | u8g2.setFont(u8g2_font_lucasfont_alternate_tr); 413 | if (szjm_jiaozhun_kxxk_count == 6) 414 | { 415 | u8g2.setCursor(0, 7); 416 | u8g2.print("P0:"); 417 | u8g2.setCursor(25, 7); 418 | u8g2.print(sz_p[0], 10); 419 | 420 | u8g2.setCursor(0, 15); 421 | u8g2.print("P1:"); 422 | u8g2.setCursor(25, 15); 423 | u8g2.print(sz_p[1], 10); 424 | 425 | u8g2.setCursor(0, 24); 426 | u8g2.print("P2:"); 427 | u8g2.setCursor(25, 24); 428 | u8g2.print(sz_p[2], 10); 429 | 430 | u8g2.setCursor(0, 32); 431 | u8g2.print("P3:"); 432 | u8g2.setCursor(25, 32); 433 | u8g2.print(sz_p[3], 10); 434 | } 435 | else 436 | { 437 | u8g2.setCursor(szjm_jiaozhun_x1, szjm_jiaozhun_y1); 438 | u8g2.print("ADC 10 350 650 940"); 439 | u8g2.setCursor(szjm_jiaozhun_x1, szjm_jiaozhun_y2); 440 | u8g2.print("Temp"); 441 | u8g2.setCursor(szjm_jiaozhun_x2, szjm_jiaozhun_y2); 442 | u8g2.print(sz_temp[0]); 443 | u8g2.setCursor(szjm_jiaozhun_x3, szjm_jiaozhun_y2); 444 | u8g2.print(sz_temp[1]); 445 | u8g2.setCursor(szjm_jiaozhun_x4, szjm_jiaozhun_y2); 446 | u8g2.print(sz_temp[2]); 447 | u8g2.setCursor(szjm_jiaozhun_x5, szjm_jiaozhun_y2); 448 | u8g2.print(sz_temp[3]); 449 | 450 | u8g2.drawHLine(0, 22, 128); 451 | 452 | u8g2.setCursor(szjm_jiaozhun_x1, szjm_jiaozhun_y3); 453 | u8g2.print("Now ADC:"); 454 | u8g2.setCursor(48, szjm_jiaozhun_y3); 455 | u8g2.print(t12_ad, 0); 456 | 457 | u8g2.setCursor(szjm_jiaozhun_x6, szjm_jiaozhun_y3); 458 | u8g2.print("Save"); 459 | } 460 | //画选框 461 | switch (szjm_jiaozhun_kxxk_count) //空心选框的位置 462 | { 463 | case 1: //深圳头1段温度 464 | if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 465 | { 466 | u8g2.setDrawColor(2); 467 | u8g2.drawBox(szjm_jiaozhun_x2 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //实心方形 468 | u8g2.setDrawColor(1); 469 | } 470 | else u8g2.drawFrame(szjm_jiaozhun_x2 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //空心方形 471 | break; 472 | case 2: //深圳头2段温度 473 | if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 474 | { 475 | u8g2.setDrawColor(2); 476 | u8g2.drawBox(szjm_jiaozhun_x3 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //实心方形 477 | u8g2.setDrawColor(1); 478 | } 479 | else u8g2.drawFrame(szjm_jiaozhun_x3 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //空心方形 480 | break; 481 | case 3: //深圳头3段温度 482 | if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 483 | { 484 | u8g2.setDrawColor(2); 485 | u8g2.drawBox(szjm_jiaozhun_x4 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //实心方形 486 | u8g2.setDrawColor(1); 487 | } 488 | else u8g2.drawFrame(szjm_jiaozhun_x4 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //空心方形 489 | break; 490 | case 4: //深圳头4段温度 491 | if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 492 | { 493 | u8g2.setDrawColor(2); 494 | u8g2.drawBox(szjm_jiaozhun_x5 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //实心方形 495 | u8g2.setDrawColor(1); 496 | } 497 | else u8g2.drawFrame(szjm_jiaozhun_x5 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //空心方形 498 | break; 499 | case 5: //保存 500 | u8g2.setDrawColor(2); 501 | u8g2.drawBox(szjm_jiaozhun_x6 - 2, szjm_jiaozhun_y3 - 8, 28, 9); //实心方形 502 | u8g2.setDrawColor(1); 503 | break; 504 | } 505 | } 506 | -------------------------------------------------------------------------------- /v1.03/EEPROM.ino: -------------------------------------------------------------------------------- 1 | //******************* 自动刷写eeprom ******************* 2 | void eerpom_auto() 3 | { 4 | EEPROM.get(auto_get_eeprom, auto_get); //获取自动刷写的状态 5 | if (auto_get > 1) auto_get = 0; //防止eeprom第0位不为0 6 | if (auto_get == 0) //状态为0开启刷写 7 | { 8 | EEPROM.put(p_eeprom, p); //pid-p 9 | EEPROM.put(i_eeprom, i); //pid-i 10 | EEPROM.put(d_eeprom, d); //pid-d 11 | EEPROM.put(sleep_time_eeprom, sleep_time); //休眠时间 12 | EEPROM.put(sleep_temp_eeprom, sleep_temp); //休眠温度 13 | EEPROM.put(oled_ld_eeprom, oled_ld); //OLED亮度 14 | EEPROM.put(vcc_refer_eeprom, vcc_refer); //基准电压 15 | EEPROM.put(vin_refer_eeprom, vin_refer); //电源电压校准值 16 | EEPROM.put(t12_kj_jr_eeprom, t12_kj_jr); //是否开机就加热 17 | EEPROM.put(vin_low_eeprom, vin_low); //输入电压过底报警阈值 18 | EEPROM.put(tc1047_refer_eeprom, tc1047_refer); //T12环境参考温度校准值 19 | EEPROM.put(oled_fx_eeprom, oled_fx); //OLED方向 20 | EEPROM.put(xzbmq_fx_eeprom, xzbmq_fx); //旋转编码器方向 21 | //写入曲线的4段温度 22 | EEPROM.put(sz_temp0_eeprom, sz_temp[0]); 23 | EEPROM.put(sz_temp1_eeprom, sz_temp[1]); 24 | EEPROM.put(sz_temp2_eeprom, sz_temp[2]); 25 | EEPROM.put(sz_temp3_eeprom, sz_temp[3]); 26 | //写入设置温度 27 | EEPROM.put(set_temp_eeprom, set_temp); 28 | //刷写完,记录auto_get的状态,防止下次开机再次刷写 29 | EEPROM.put(auto_get_eeprom, 1); 30 | auto_get = 1; 31 | } 32 | if (auto_get == 1)//状态为1只读取 33 | { 34 | EEPROM.get(p_eeprom, p); //pid-p 35 | EEPROM.get(i_eeprom, i); //pid-i 36 | EEPROM.get(d_eeprom, d); //pid-d 37 | EEPROM.get(sleep_time_eeprom, sleep_time); //休眠时间 38 | EEPROM.get(sleep_temp_eeprom, sleep_temp); //休眠温度 39 | EEPROM.get(oled_ld_eeprom, oled_ld); //OLED亮度 40 | EEPROM.get(vcc_refer_eeprom, vcc_refer); //基准电压 41 | EEPROM.get(vin_refer_eeprom, vin_refer); //电源电压校准值 42 | EEPROM.get(t12_kj_jr_eeprom, t12_kj_jr); //是否开机就加热 43 | EEPROM.get(vin_low_eeprom, vin_low); //输入电压过底报警阈值 44 | EEPROM.get(tc1047_refer_eeprom, tc1047_refer); //T12环境参考温度校准值 45 | EEPROM.get(oled_fx_eeprom, oled_fx); //OLED方向 46 | EEPROM.get(xzbmq_fx_eeprom, xzbmq_fx); //旋转编码器方向 47 | //获取曲线的4段温度 48 | EEPROM.get(sz_temp0_eeprom, sz_temp[0]); 49 | EEPROM.get(sz_temp1_eeprom, sz_temp[1]); 50 | EEPROM.get(sz_temp2_eeprom, sz_temp[2]); 51 | EEPROM.get(sz_temp3_eeprom, sz_temp[3]); 52 | //获取设置温度 53 | EEPROM.get(set_temp_eeprom, set_temp); 54 | } 55 | } 56 | //****************************************************** 57 | -------------------------------------------------------------------------------- /v1.03/InterruptKey.ino: -------------------------------------------------------------------------------- 1 | //********** 编码器按键决策 ********** 2 | #define xklv_time 120 //切换选框的滤波时间 3 | #define szlv_time 20 //切换选框的滤波时间 4 | #define szjm_qrcs 2; 5 | 6 | void xuan_zhaun() //旋转中断 选框决策 7 | { 8 | 9 | /*Serial.print("DT "); Serial.print(digitalRead(DT)); 10 | Serial.print(" | "); 11 | Serial.print("CLK "); Serial.print(digitalRead(CLK)); 12 | Serial.print(" | "); 13 | Serial.print("SW "); Serial.print(digitalRead(SW)); 14 | Serial.println(" ");*/ 15 | if ((millis() - xzbmq_time) < szlv_time) return; 16 | buzzer(100, 70); //时间,次数 17 | if (display_count == ZJM) 18 | { 19 | zjm_xz_key(); 20 | buzzer_temp_average_state = 0; //准备好到达温度提示声 21 | sleep_count = 0; //休眠计数归零 22 | zjm_sleep_ts = 0; //提示主界面退出显示休眠状态 23 | t12_adc_error = 0; //清除温度超出测量范围提示 24 | xp_state = 0; //结束息屏 25 | xp_time_count = 0; //清除息屏计数 26 | xp_time_count_old = 0; //清除息屏计数旧 27 | } 28 | else if (display_count == SZJM) szjm_xz_key(); 29 | else if (display_count == SZJM_PID) pid_xz_key(); 30 | else if (display_count == SZJM_SLEEP) sleep_xz_key(); 31 | else if (display_count == SZJM_OLED) oled_xz_key(); 32 | else if (display_count == SZJM_POWER) power_xz_key(); 33 | else if (display_count == SZJM_LAOTIE) laotie_xz_key(); 34 | else if (display_count == SZJM_JIAOZHUN) jiaozhun_xz_key(); 35 | xzbmq_time = millis(); 36 | } 37 | 38 | void an_xia() 39 | { 40 | if ((millis() - xzbmq_time) < 160) return; 41 | qj_sw_key(); //全局长按进入设置界面 或 退出至主界面 42 | } 43 | //************************ 全局长按进入设置界面 或 退出至主界面 ************************ 44 | void qj_sw_key() 45 | { 46 | //长按计数增加 47 | if (digitalRead(SW) == 0) 48 | { 49 | qj_ca_count++; //计数加一 50 | buzzer(80, 150); //时间,次数 51 | 52 | if (display_count == ZJM) t12_adc_error = 0; //清除温度超出测量范围提示 53 | xp_state = 0; //结束息屏 54 | xp_time_count = 0; //清除息屏计数 55 | xp_time_count_old = 0; //清除息屏计数旧 56 | 57 | xzbmq_time = millis(); 58 | } 59 | //判断按了几次 该做些什么 60 | if (qj_ca_count >= 5) //进入设置界面 61 | { 62 | if (display_count == ZJM) 63 | { 64 | display_count = SZJM; //在主界面时进入设置界面 65 | buzzer_szjm_state = 1; 66 | } 67 | else if (display_count != SZJM_JIAOZHUN) 68 | { 69 | display_count = ZJM; //在其他界面是退出至主界面 70 | buzzer_zjm_state = 1; 71 | } 72 | qj_ca_count = 0; //计数清零 73 | } 74 | else if ((millis() - xzbmq_time) > 260) //等待一段时间,确定松手了 75 | { 76 | //在主界面的按下决策 77 | if (display_count == ZJM) zjm_sw_key(); 78 | //在设置界面的按下决策 79 | else if (display_count == SZJM) szjm_sw_key(); 80 | //在PID界面的按下决策 81 | else if (display_count == SZJM_PID) pid_sw_key(); 82 | //在休眠界面的按下决策 83 | else if (display_count == SZJM_SLEEP) sleep_sw_key(); 84 | //在OLED亮度界面的按下决策 85 | else if (display_count == SZJM_OLED) oled_sw_key(); 86 | //在电源校准界面的按下决策 87 | else if (display_count == SZJM_POWER) power_sw_key(); 88 | //在烙铁界面的按下决策 89 | else if (display_count == SZJM_LAOTIE) laotie_sw_key(); 90 | //在校准界面的按下决策 91 | else if (display_count == SZJM_JIAOZHUN) jiaozhun_sw_key(); 92 | qj_ca_count = 0;//计数清零 93 | } 94 | } 95 | //************************ 主界面 ************************ 96 | void zjm_sw_key() 97 | { 98 | if (qj_ca_count == 2 && vin_error == 0 && t12_error == 0) // 启动或停止加热 99 | { 100 | zjm_dh_run = 1; //允许播放动画 ,动画播放完在DisplayMain里切换T12工作状态 101 | zjm_sleep_ts = 0; //提示主界面退出显示休眠状态 102 | buzzer_temp_average_state = 0; //准备好到达温度提示声 103 | } 104 | } 105 | void zjm_xz_key() //主界面 旋转 106 | { 107 | if (digitalRead(DT) == xzbmq_fx) set_temp += 10; 108 | else if (digitalRead(CLK) == xzbmq_fx) set_temp -= 10; 109 | //自动获取设置温度的范围 110 | set_temp_max = ((sz_temp[3]) / 10 ) * 10; 111 | set_temp_min = ((sz_temp[0]) / 10) * 10; 112 | if (set_temp > set_temp_max) set_temp = set_temp_min; 113 | else if (set_temp < set_temp_min) set_temp = set_temp_max; 114 | } 115 | //************************ 设置界面 ************************ 116 | void szjm_sw_key() //设置界面 按下 117 | { 118 | if (qj_ca_count == 1) //进入二级菜单 119 | { 120 | if (szjm_kxxk_count == 0) display_count = SZJM_SLEEP; //进入休眠设置菜单 121 | else if (szjm_kxxk_count == -5 || szjm_kxxk_count == 1) display_count = SZJM_PID; //进入PID设置菜单 122 | else if (szjm_kxxk_count == -1 || szjm_kxxk_count == 5) display_count = SZJM_OLED; //进入OELD亮度设置菜单 123 | else if (szjm_kxxk_count == -2 || szjm_kxxk_count == 4) display_count = SZJM_POWER; //进入电源设置菜单 124 | else if (szjm_kxxk_count == -4 || szjm_kxxk_count == 2) display_count = SZJM_LAOTIE;//进入烙铁设置菜单 125 | else if (szjm_kxxk_count == -3 || szjm_kxxk_count == 3) 126 | { 127 | //使用比较柔和的pid参数,退出校准界面时记得恢复正常的PID策略 128 | p = p_jz; //比例系数 129 | i = i_jz; //积分系数 130 | d = d_jz; //微分系数 131 | display_count = SZJM_JIAOZHUN;//进入烙铁设置菜单 132 | } 133 | } 134 | } 135 | void szjm_xz_key() //设置界面 旋转 136 | { 137 | if (digitalRead(DT) == xzbmq_fx) 138 | { 139 | if (szjm_kxxk_L == 0 && szjm_kxxk_R == 0) //顺时针 140 | { 141 | szjm_kxxk_L = 1; //允许播放动画 142 | szjm_kxxk_count++; //下一项 143 | } 144 | } 145 | else if (digitalRead(CLK) == xzbmq_fx) 146 | { 147 | if (szjm_kxxk_L == 0 && szjm_kxxk_R == 0) //逆时针 148 | { 149 | szjm_kxxk_R = 1; //允许播放动画 150 | szjm_kxxk_count--; //上一项 151 | } 152 | } 153 | } 154 | //************************ PID设置界面 ************************ 155 | void pid_sw_key() //设置界面 按下 156 | { 157 | if (qj_ca_count == 1) //返回或进入调节框 158 | { 159 | switch (szjm_pid_kxxk_count) 160 | { 161 | case 0: //返回至设置界面 162 | display_count = SZJM; 163 | break; 164 | case 1: //p 存储 165 | if (szjm_pid_sxxk_count == 0) szjm_pid_sxxk_count = szjm_pid_kxxk_count; 166 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 0) dec_state = 1; 167 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 1) 168 | { 169 | EEPROM.put(p_eeprom, p); 170 | dec_state = 0; 171 | szjm_pid_sxxk_count = 0; 172 | } 173 | break; 174 | case 2: //i 存储 175 | if (szjm_pid_sxxk_count == 0) szjm_pid_sxxk_count = szjm_pid_kxxk_count; 176 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 0) dec_state = 1; 177 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 1) 178 | { 179 | EEPROM.put(i_eeprom, i); 180 | dec_state = 0; 181 | szjm_pid_sxxk_count = 0; 182 | } 183 | break; 184 | case 3: //d 存储 185 | if (szjm_pid_sxxk_count == 0) szjm_pid_sxxk_count = szjm_pid_kxxk_count; 186 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 0) dec_state = 1; 187 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 1) 188 | { 189 | EEPROM.put(d_eeprom, d); 190 | dec_state = 0; 191 | szjm_pid_sxxk_count = 0; 192 | } 193 | break; 194 | } 195 | } 196 | } 197 | void pid_xz_key() //设置界面 旋转 198 | { 199 | if (szjm_pid_sxxk_count == 0) //选框移动 200 | { 201 | if (digitalRead(DT) == xzbmq_fx) szjm_pid_kxxk_count++; 202 | else if (digitalRead(CLK) == xzbmq_fx) szjm_pid_kxxk_count--; 203 | } 204 | else if (szjm_pid_sxxk_count == 1) //p加减 205 | { 206 | if (digitalRead(DT) == xzbmq_fx && dec_state == 0) p += 1; 207 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 0) p -= 1; 208 | else if (digitalRead(DT) == xzbmq_fx && dec_state == 1) p += 0.1; 209 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 1) p -= 0.1; 210 | } 211 | else if (szjm_pid_sxxk_count == 2) //i加减 212 | { 213 | if (digitalRead(DT) == xzbmq_fx && dec_state == 0) i += 1; 214 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 0) i -= 1; 215 | else if (digitalRead(DT) == xzbmq_fx && dec_state == 1) i += 0.1; 216 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 1) i -= 0.1; 217 | } 218 | else if (szjm_pid_sxxk_count == 3) //d加减 219 | { 220 | if (digitalRead(DT) == xzbmq_fx && dec_state == 0) d += 1; 221 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 0) d -= 1; 222 | else if (digitalRead(DT) == xzbmq_fx && dec_state == 1) d += 0.1; 223 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 1) d -= 0.1; 224 | } 225 | if (szjm_pid_kxxk_count > 3) szjm_pid_kxxk_count = 0; 226 | else if (szjm_pid_kxxk_count < 0) szjm_pid_kxxk_count = 3; 227 | } 228 | //************************ 休眠设置界面 ************************ 229 | void sleep_sw_key() //设置界面 按下 230 | { 231 | if (qj_ca_count == 1) //返回或进入调节框 232 | { 233 | switch (szjm_sleep_kxxk_count) 234 | { 235 | case 0: //返回至设置界面 236 | display_count = SZJM; 237 | break; 238 | case 1: //休眠时间 存储 239 | if (szjm_sleep_sxxk_count == 0) szjm_sleep_sxxk_count = szjm_sleep_kxxk_count; 240 | else if (szjm_sleep_sxxk_count == szjm_sleep_kxxk_count) 241 | { 242 | EEPROM.put(sleep_time_eeprom, sleep_time); //休眠时间 243 | szjm_sleep_sxxk_count = 0; 244 | } 245 | break; 246 | case 2: //休眠温度 存储 247 | if (szjm_sleep_sxxk_count == 0) szjm_sleep_sxxk_count = szjm_sleep_kxxk_count; 248 | else if (szjm_sleep_sxxk_count == szjm_sleep_kxxk_count) 249 | { 250 | EEPROM.put(sleep_temp_eeprom, sleep_temp); //休眠温度 251 | szjm_sleep_sxxk_count = 0; 252 | } 253 | break; 254 | } 255 | } 256 | } 257 | void sleep_xz_key() //设置界面 旋转 258 | { 259 | if (szjm_sleep_sxxk_count == 0) //选框移动 260 | { 261 | if (digitalRead(DT) == xzbmq_fx) szjm_sleep_kxxk_count++; 262 | else if (digitalRead(CLK) == xzbmq_fx) szjm_sleep_kxxk_count--; 263 | } 264 | else if (szjm_sleep_sxxk_count == 1) //休眠时间加减 265 | { 266 | if (digitalRead(DT) == xzbmq_fx) sleep_time += 1; 267 | else if (digitalRead(CLK) == xzbmq_fx) sleep_time -= 1; 268 | } 269 | else if (szjm_sleep_sxxk_count == 2) //休眠温度加减 270 | { 271 | if (digitalRead(DT) == xzbmq_fx) sleep_temp += 1; 272 | else if (digitalRead(CLK) == xzbmq_fx) sleep_temp -= 1; 273 | } 274 | if (szjm_sleep_kxxk_count > 2) szjm_sleep_kxxk_count = 0; 275 | else if (szjm_sleep_kxxk_count < 0) szjm_sleep_kxxk_count = 2; 276 | else if (sleep_time > 999) sleep_time = 10; 277 | else if (sleep_time < 10) sleep_time = 999; 278 | } 279 | //************************ OLED亮度设置界面 ************************ 280 | void oled_sw_key() //设置界面 按下 281 | { 282 | if (qj_ca_count == 1) //返回或进入调节框 283 | { 284 | switch (szjm_oled_kxxk_count) 285 | { 286 | case 0: //返回至设置界面 287 | display_count = SZJM; 288 | break; 289 | case 1: //OLED亮度 存储 290 | if (szjm_oled_sxxk_count == 0) szjm_oled_sxxk_count = szjm_oled_kxxk_count; 291 | else if (szjm_oled_sxxk_count == szjm_oled_kxxk_count) 292 | { 293 | EEPROM.put(oled_ld_eeprom, oled_ld); //OLED亮度 294 | szjm_oled_sxxk_count = 0; 295 | } 296 | break; 297 | case 2: //OLED亮度 存储 298 | if (szjm_oled_sxxk_count == 0) szjm_oled_sxxk_count = szjm_oled_kxxk_count; 299 | else if (szjm_oled_sxxk_count == szjm_oled_kxxk_count) 300 | { 301 | EEPROM.put(oled_fx_eeprom, oled_fx); //OLED方向 302 | if (oled_fx == 1)u8g2.setDisplayRotation(U8G2_R2); //旋转180度 303 | else u8g2.setDisplayRotation(U8G2_R0); //0度,默认方向 304 | szjm_oled_sxxk_count = 0; 305 | } 306 | break; 307 | case 3: //旋转编码器方向 存储 308 | if (szjm_oled_sxxk_count == 0) szjm_oled_sxxk_count = szjm_oled_kxxk_count; 309 | else if (szjm_oled_sxxk_count == szjm_oled_kxxk_count) 310 | { 311 | EEPROM.put(xzbmq_fx_eeprom, xzbmq_fx); //OLED方向 312 | EEPROM.get(xzbmq_fx_eeprom, xzbmq_fx); //OLED方向 313 | szjm_oled_sxxk_count = 0; 314 | } 315 | break; 316 | } 317 | } 318 | } 319 | 320 | void oled_xz_key() //设置界面 旋转 321 | { 322 | if (szjm_oled_sxxk_count == 0) //选框移动 323 | { 324 | if (digitalRead(DT) == xzbmq_fx) szjm_oled_kxxk_count++; 325 | else if (digitalRead(CLK) == xzbmq_fx) szjm_oled_kxxk_count--; 326 | if (szjm_oled_kxxk_count > 3) szjm_oled_kxxk_count = 0; 327 | else if (szjm_oled_kxxk_count < 0) szjm_oled_kxxk_count = 3; 328 | } 329 | else if (szjm_oled_sxxk_count == 1) //OLED亮度 加减 330 | { 331 | if (digitalRead(DT) == xzbmq_fx) oled_ld += 5; 332 | else if (digitalRead(CLK) == xzbmq_fx) oled_ld -= 5; 333 | if (oled_ld > 1 && oled_ld < 5) oled_ld = 5; 334 | else if (oled_ld == 0)oled_ld = 255; 335 | } 336 | else if (szjm_oled_sxxk_count == 2) //OLED方向 状态切换 337 | { 338 | if (digitalRead(DT) == xzbmq_fx) oled_fx = !oled_fx; 339 | else if (digitalRead(CLK) == xzbmq_fx) oled_fx = !oled_fx; 340 | } 341 | else if (szjm_oled_sxxk_count == 3) //旋转编码器方向 状态切换 342 | { 343 | if (digitalRead(DT) == xzbmq_fx) xzbmq_fx = !xzbmq_fx; 344 | else if (digitalRead(CLK) == xzbmq_fx) xzbmq_fx = !xzbmq_fx; 345 | } 346 | } 347 | //************************ 电源校准界面 ************************ 348 | void power_sw_key() //设置界面 按下 349 | { 350 | if (qj_ca_count == 1) //返回或进入调节框 351 | { 352 | switch (szjm_power_kxxk_count) 353 | { 354 | case 0: //返回至设置界面 355 | display_count = SZJM; 356 | break; 357 | case 1: //基准电压 存储 358 | if (szjm_power_sxxk_count == 0) szjm_power_sxxk_count = szjm_power_kxxk_count; 359 | else if (szjm_power_sxxk_count == szjm_power_kxxk_count) 360 | { 361 | EEPROM.put(vcc_refer_eeprom, vcc_refer); 362 | szjm_power_sxxk_count = 0; 363 | } 364 | break; 365 | case 2: //电源电压校准值 存储 366 | if (szjm_power_sxxk_count == 0) szjm_power_sxxk_count = szjm_power_kxxk_count; 367 | else if (szjm_power_sxxk_count == szjm_power_kxxk_count) 368 | { 369 | EEPROM.put(vin_refer_eeprom, vin_refer); 370 | szjm_power_sxxk_count = 0; 371 | } 372 | break; 373 | case 3: //低压报警阈值 存储 374 | if (szjm_power_sxxk_count == 0) szjm_power_sxxk_count = szjm_power_kxxk_count; 375 | else if (szjm_power_sxxk_count == szjm_power_kxxk_count) 376 | { 377 | EEPROM.put(vin_low_eeprom, vin_low); 378 | szjm_power_sxxk_count = 0; 379 | } 380 | break; 381 | } 382 | } 383 | } 384 | 385 | void power_xz_key() //设置界面 旋转 386 | { 387 | if (szjm_power_sxxk_count == 0) //选框移动 388 | { 389 | if (digitalRead(DT) == xzbmq_fx) szjm_power_kxxk_count++; 390 | else if (digitalRead(CLK) == xzbmq_fx) szjm_power_kxxk_count--; 391 | if (szjm_power_kxxk_count > 3) szjm_power_kxxk_count = 0; 392 | else if (szjm_power_kxxk_count < 0) szjm_power_kxxk_count = 3; 393 | } 394 | else if (szjm_power_sxxk_count == 1) //基准电压 加减 395 | { 396 | if (digitalRead(DT) == xzbmq_fx) vcc_refer += 0.01; 397 | else if (digitalRead(CLK) == xzbmq_fx) vcc_refer -= 0.01; 398 | } 399 | else if (szjm_power_sxxk_count == 2) //电源电压校准值 加减 400 | { 401 | if (digitalRead(DT) == xzbmq_fx) vin_refer += 0.1; 402 | else if (digitalRead(CLK) == xzbmq_fx) vin_refer -= 0.1; 403 | } 404 | else if (szjm_power_sxxk_count == 3) //低压报警阈值 加减 405 | { 406 | if (digitalRead(DT) == xzbmq_fx) vin_low += 0.1; 407 | else if (digitalRead(CLK) == xzbmq_fx) vin_low -= 0.1; 408 | if (vin_low > 30)vin_low = 3.2; 409 | else if (vin_low < 3.2)vin_low = 30; 410 | } 411 | } 412 | 413 | //************************ 烙铁界面 ************************ 414 | void laotie_sw_key() //设置界面 按下 415 | { 416 | if (qj_ca_count == 1) //返回或进入调节框 417 | { 418 | switch (szjm_laotie_kxxk_count) 419 | { 420 | case 0: //返回至设置界面 421 | display_count = SZJM; 422 | break; 423 | case 1: //冷端补偿 存储 424 | if (szjm_laotie_sxxk_count == 0) szjm_laotie_sxxk_count = szjm_laotie_kxxk_count; 425 | else if (szjm_laotie_sxxk_count == szjm_laotie_kxxk_count) 426 | { 427 | EEPROM.put(tc1047_refer_eeprom, tc1047_refer); 428 | szjm_laotie_sxxk_count = 0; 429 | } 430 | break; 431 | case 2: //开机加热 存储 432 | if (szjm_laotie_sxxk_count == 0) 433 | { 434 | t12_kj_jr = !t12_kj_jr; 435 | EEPROM.put(t12_kj_jr_eeprom, t12_kj_jr); 436 | } 437 | break; 438 | case 3: //恢复出厂设置 存储 439 | if (szjm_laotie_sxxk_count == 0) szjm_laotie_sxxk_count = szjm_laotie_kxxk_count; 440 | else if (szjm_laotie_sxxk_count == szjm_laotie_kxxk_count) 441 | { 442 | if (hfccsz_state == 1) display_hfccsz(); 443 | szjm_laotie_sxxk_count = 0; 444 | } 445 | break; 446 | } 447 | } 448 | } 449 | void laotie_xz_key() //设置界面 旋转 450 | { 451 | if (szjm_laotie_sxxk_count == 0) //选框移动 452 | { 453 | if (digitalRead(DT) == xzbmq_fx) szjm_laotie_kxxk_count++; 454 | else if (digitalRead(CLK) == xzbmq_fx) szjm_laotie_kxxk_count--; 455 | if (szjm_laotie_kxxk_count > 3) szjm_laotie_kxxk_count = 0; 456 | else if (szjm_laotie_kxxk_count < 0) szjm_laotie_kxxk_count = 3; 457 | } 458 | else if (szjm_laotie_sxxk_count == 1) //冷端补偿校准值 加减 459 | { 460 | if (digitalRead(DT) == xzbmq_fx) tc1047_refer += 1; 461 | else if (digitalRead(CLK) == xzbmq_fx) tc1047_refer -= 1; 462 | if (tc1047_refer > 99)tc1047_refer = 0; 463 | else if (tc1047_refer < -99) tc1047_refer = 0; 464 | } 465 | else if (szjm_laotie_sxxk_count == 3) //恢复出厂设置 状态切换 466 | { 467 | if (digitalRead(DT) == xzbmq_fx) hfccsz_state = !hfccsz_state; 468 | else if (digitalRead(CLK) == xzbmq_fx) hfccsz_state = !hfccsz_state; 469 | } 470 | } 471 | //************************ 校准界面 ************************ 472 | void jiaozhun_sw_key() //设置界面 按下 473 | { 474 | if (qj_ca_count == 1) //返回或进入调节框 475 | { 476 | switch (szjm_jiaozhun_kxxk_count) 477 | { 478 | case 0: //返回至设置界面,并恢复正常PID参数 479 | display_count = SZJM; 480 | szjm_jiaozhun_kxxk_count = 0; 481 | EEPROM.get(p_eeprom, p); //pid-p 482 | EEPROM.get(i_eeprom, i); //pid-i 483 | EEPROM.get(d_eeprom, d); //pid-d 484 | break; 485 | case 1: //深圳校准温度1段 存储 486 | if (szjm_jiaozhun_sxxk_count == 0) 487 | { 488 | szjm_jiaozhun_sxxk_count = szjm_jiaozhun_kxxk_count; 489 | t12_switch = 1; //打开加热 490 | } 491 | else if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 492 | { 493 | EEPROM.put(sz_temp0_eeprom, sz_temp[0]); 494 | szjm_jiaozhun_sxxk_count = 0; 495 | t12_switch = 0; //关闭加热 496 | } 497 | break; 498 | case 2: //深圳校准温度2段 存储 499 | if (szjm_jiaozhun_sxxk_count == 0) 500 | { 501 | szjm_jiaozhun_sxxk_count = szjm_jiaozhun_kxxk_count; 502 | t12_switch = 1; //打开加热 503 | } 504 | else if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 505 | { 506 | EEPROM.put(sz_temp1_eeprom, sz_temp[1]); 507 | szjm_jiaozhun_sxxk_count = 0; 508 | t12_switch = 0; //关闭加热 509 | } 510 | break; 511 | case 3: //深圳校准温度3段 存储 512 | if (szjm_jiaozhun_sxxk_count == 0) 513 | { 514 | szjm_jiaozhun_sxxk_count = szjm_jiaozhun_kxxk_count; 515 | t12_switch = 1; //打开加热 516 | } 517 | else if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 518 | { 519 | EEPROM.put(sz_temp2_eeprom, sz_temp[2]); 520 | szjm_jiaozhun_sxxk_count = 0; 521 | t12_switch = 0; //关闭加热 522 | } 523 | break; 524 | case 4: //深圳校准温度4段 存储 525 | if (szjm_jiaozhun_sxxk_count == 0) 526 | { 527 | szjm_jiaozhun_sxxk_count = szjm_jiaozhun_kxxk_count; 528 | t12_switch = 1; //打开加热 529 | } 530 | else if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 531 | { 532 | EEPROM.put(sz_temp3_eeprom, sz_temp[3]); 533 | szjm_jiaozhun_sxxk_count = 0; 534 | t12_switch = 0; //关闭加热 535 | } 536 | break; 537 | case 5: //开始曲线拟合系数计算 538 | qxnh_run(); //计算曲线拟合系数 539 | szjm_jiaozhun_kxxk_count = 6; 540 | break; 541 | case 6: //返回至设置界面,并恢复正常PID参数 542 | display_count = SZJM; 543 | szjm_jiaozhun_kxxk_count = 0; 544 | EEPROM.get(p_eeprom, p); //pid-p 545 | EEPROM.get(i_eeprom, i); //pid-i 546 | EEPROM.get(d_eeprom, d); //pid-d 547 | break; 548 | } 549 | } 550 | } 551 | void jiaozhun_xz_key() //设置界面 旋转 552 | { 553 | if (szjm_jiaozhun_sxxk_count == 0) //选框移动 554 | { 555 | if (digitalRead(DT) == xzbmq_fx) szjm_jiaozhun_kxxk_count++; 556 | else if (digitalRead(CLK) == xzbmq_fx) szjm_jiaozhun_kxxk_count--; 557 | if (szjm_jiaozhun_kxxk_count > 6) szjm_jiaozhun_kxxk_count = 0; 558 | else if (szjm_jiaozhun_kxxk_count < 0) szjm_jiaozhun_kxxk_count = 6; 559 | } 560 | else if (szjm_jiaozhun_sxxk_count == 1) //选框移动 561 | { 562 | if (digitalRead(DT) == xzbmq_fx) sz_temp[0] += 1; 563 | else if (digitalRead(CLK) == xzbmq_fx) sz_temp[0] -= 1; 564 | } 565 | else if (szjm_jiaozhun_sxxk_count == 2) //选框移动 566 | { 567 | if (digitalRead(DT) == xzbmq_fx) sz_temp[1] += 1; 568 | else if (digitalRead(CLK) == xzbmq_fx) sz_temp[1] -= 1; 569 | } 570 | else if (szjm_jiaozhun_sxxk_count == 3) //选框移动 571 | { 572 | if (digitalRead(DT) == xzbmq_fx) sz_temp[2] += 1; 573 | else if (digitalRead(CLK) == xzbmq_fx) sz_temp[2] -= 1; 574 | } 575 | else if (szjm_jiaozhun_sxxk_count == 4) //选框移动 576 | { 577 | if (digitalRead(DT) == xzbmq_fx) sz_temp[3] += 1; 578 | else if (digitalRead(CLK) == xzbmq_fx) sz_temp[3] -= 1; 579 | } 580 | } 581 | -------------------------------------------------------------------------------- /v1.03/MsTimer2.ino: -------------------------------------------------------------------------------- 1 | //定时器2 2 | uint32_t t12_sleep_old_time = 0; 3 | void MsTimer2_rw1() 4 | { 5 | if (t12_switch == 1) //烙铁启动,打开休眠判断决策 6 | { 7 | if (bitRead(TIMSK2, TOIE2) == 0) 8 | { 9 | sleep_count = 0; 10 | xp_time_count = 0; 11 | MsTimer2::set(1000, sleep_timing); // 1000ms 运行一次 12 | MsTimer2::start(); //打开定时器2计数 13 | } 14 | if (millis() - t12_sleep_old_time > 700) 15 | { 16 | t12_sleep(); //T12休眠决策 17 | t12_sleep_old_time = millis(); 18 | } 19 | } 20 | else if (t12_switch == 0) 21 | { 22 | if (bitRead(TIMSK2, TOIE2) == 0) 23 | { 24 | sleep_count = 0; 25 | xp_time_count = 0; 26 | MsTimer2::set(1000, xp_timing); // 1000ms 运行一次 27 | MsTimer2::start(); //打开定时器2计数 28 | } 29 | system_sleep(); //系统休眠决策 30 | } 31 | } 32 | 33 | void sleep_timing() //休眠定时任务 34 | { 35 | sleep_count++; //烙铁没动,计数增加 36 | } 37 | 38 | void xp_timing() //息屏定时任务,校准界面不息屏 39 | { 40 | if (display_count != SZJM_JIAOZHUN) xp_time_count++; //烙铁没动,计数增加 41 | } 42 | -------------------------------------------------------------------------------- /v1.03/PID.ino: -------------------------------------------------------------------------------- 1 | //********** PID算法 ********** 2 | //算法来至https://blog.csdn.net/foxclever/article/details/105006205 By foxclever 3 | void pid() 4 | { 5 | if (t12_switch == 1 && vin_error == 0 && t12_error == 0) //加热开关开启 6 | { 7 | //计算设定值与平均温度的差值 8 | int16_t ek_average = set_temp - t12_temp_average; 9 | //平均差值小于3,发出声音提示一下 10 | if (ek_average >= -3 && ek_average <= 3 && buzzer_temp_average_state == 0) 11 | { 12 | buzzer(120, 300); 13 | buzzer_temp_average_state = 1; 14 | } 15 | if (display_count == SZJM_JIAOZHUN) 16 | PIDRegulator(t12_ad); //在校准界面时使用T12的ADC作为PID的目标值 17 | else 18 | PIDRegulator(t12_temp); //在其他界面时使用T12的温度值作为PID的目标值 19 | } 20 | else 21 | { 22 | pid_out = 0; 23 | lasterror = 0; 24 | preerror = 0; 25 | t12_temp_read_time = 450; 26 | } 27 | pwm_1b(pid_out); 28 | pid_out_bfb = (pid_out / (pwm_max - pwm_min)) * 100; 29 | } 30 | 31 | void PIDRegulator(float PV) 32 | { 33 | float factor = 0.0; //变积分系数 34 | float increment = 0.0; 35 | float pError = 0.0, dError = 0.0, iError = 0.0; 36 | if (display_count == SZJM_JIAOZHUN) //在校准界面时使用T12的ADC作为PID的目标值 ,计算偏差 37 | { 38 | if (szjm_jiaozhun_sxxk_count == 1) thisError = sz_adc0 - PV; 39 | else if (szjm_jiaozhun_sxxk_count == 2) thisError = sz_adc1 - PV; 40 | else if (szjm_jiaozhun_sxxk_count == 3) thisError = sz_adc2 - PV; 41 | else if (szjm_jiaozhun_sxxk_count == 4) thisError = sz_adc3 - PV; 42 | } 43 | else //在其他界面时使用T12的温度值作为PID的目标值 ,计算偏差 44 | { 45 | thisError = set_temp - PV; //得到偏差值 46 | thisError_average = set_temp - t12_temp_average; //得到平均值的偏差值 47 | } 48 | //规定采样时间 49 | if (thisError < -5) t12_temp_read_time = 150; 50 | else if (thisError >= -5 && thisError <= 10) t12_temp_read_time = 400; 51 | else if (thisError > 10 && thisError <= 30) t12_temp_read_time = 500; 52 | else t12_temp_read_time = 800; 53 | if (thisError <= 30 && thisError > -15) 54 | { 55 | if (fabs(thisError) > deadband) 56 | { 57 | pError = thisError - lasterror; 58 | iError = float((thisError + lasterror)) / 2.0; 59 | dError = thisError - 2 * (lasterror) + preerror; 60 | 61 | //变积分系数获取 62 | factor = get_factor(thisError, errorabsmax, errorabsmin); 63 | 64 | //计算微分项增量带不完全微分 65 | deltadiff = d * (1 - alpha) * dError + alpha * deltadiff; 66 | 67 | increment = p * pError + i * factor * iError + deltadiff; //增量计算 68 | } 69 | else 70 | { 71 | if ((fabs(set_temp - pwm_min) < deadband) && (fabs(PV - pwm_min) < deadband)) 72 | { 73 | pid_out = pwm_min; 74 | } 75 | increment = 0.0; 76 | } 77 | 78 | pid_out = pid_out + increment; 79 | 80 | /*对输出限值,避免超调和积分饱和问题*/ 81 | if (pid_out >= pwm_max) 82 | { 83 | if (thisError <= 0) pid_out = pwm_min; 84 | else pid_out = pwm_max; 85 | } 86 | else if (pid_out <= pwm_min) pid_out = pwm_min; 87 | 88 | } 89 | else if (thisError > 30) pid_out = pwm_max; 90 | else if (thisError < -15) pid_out = pwm_min; 91 | preerror = lasterror; //存放偏差用于下次运算 92 | lasterror = thisError; 93 | } 94 | 95 | float get_factor(float ek0, float absmax, float absmin) //变积分系数获取 96 | { 97 | float factor1 = 0.0; 98 | factor1 = map(ek0, absmax, absmin, 0.0, 1.0); 99 | if (abs(ek0) >= absmax) factor1 = 0.0; 100 | else if (abs(ek0) <= absmin) factor1 = 1.0; 101 | return factor1; 102 | } 103 | 104 | void pwm_1b(uint16_t val)//自定义PWM,使用相位和频率校正模式,2048级控温 105 | { 106 | //输出通道B 占空比: (OCR1B+1) / (OCR1A+1) 107 | //占空比不能大于OCR1A 108 | 109 | if (val >= pwm_max) digitalWrite(t12_pwm_pin, 1); 110 | else if (val <= pwm_min) digitalWrite(t12_pwm_pin, 0); 111 | else 112 | { 113 | //pinMode(10, OUTPUT); //pin10连接至B通道 114 | //bitWrite(DDRB, 2, 1); //设置pin10为输出 115 | //相位和频率校正PWM,分频比64,频率: 16000000/2*256*(OCR1A+1) = 15HZ 116 | TCCR1A = B00100001; 117 | TCCR1B = B00010100; 118 | OCR1A = pwm_max; //从0开始数到0CR1A,0-65535,设置周期和频率 119 | OCR1B = val; //用来设置比较器,占空比 120 | } 121 | //ec_read(); //读取电流 122 | } 123 | /*时钟输出 | Arduino输出Pin | 芯片Pin | Pin 名字 124 | OC0A 6 12 PD6 125 | OC0B 5 11 PD5 126 | OC1A 9 15 PB1 127 | OC1B 10 16 PB2 128 | OC2A 11 17 PB3 129 | OC2B 3 5 PD3 130 | 131 | 脉冲生成模式控制位(WGM):用来设置PWM的模式或CTC模式 132 | 时钟选择位(CS):设置时钟的预分频 133 | 输出模式控制位(COMnA和COMnB):使能/禁用/反相 输出A和输出B 134 | 输出比较器(OCRnA和OCRnB):当计数器等于这两个值时,输出值根据不同的模式进行变化 135 | 136 | 快速PWM(0-255 0-255 数完归零) 137 | 相位修正PWM(0-255 255-0 数完倒数) 138 | 139 | 8位(定时器0/2) 140 | CSn0 001 = 1 141 | CSn1 010 = 8 142 | CSn2 011= 32 143 | CSn3 100= 64 144 | CSn4 101= 128 145 | CSn5 110= 256 146 | CSn6 111= 1024 147 | 16位(定时器1) 148 | CSn0 001 = 1 149 | CSn1 010 = 8 150 | CSn2 011= 64 151 | CSn3 100= 256 152 | CSn4 101= 1024 153 | 154 | COMnA1 COMnB1 = 占空比AB都可控 155 | 从0数到2047 0时输出高电平 156 | OCRnA 当数到OCRnA,输出低电平,即A的占空比=OCRnA的值 157 | OCRnB 当数到OCRnB,输出低电平,即B的占空比=OCRnB的值 158 | 159 | COMnA0 COMnB1 = A当数到头是反相 占空比A50% B可控 160 | OCRnA 从0数到OCRnA 0时输出高电平 161 | OCRnB 当OCRnA=OCRnB,输出低电平 162 | 输出通道B 占空比: (OCR1B+1) / (OCR1A+1) 163 | 占空比不能大于OCR1A 164 | pinMode(10, OUTPUT); //B 165 | bitWrite(DDRB, 2, 1); //设置pin10为输出 166 | 快速PWM,分频比64,频率: 16000000/64*(OCR1A+1) = 976HZ 167 | TCCR1A = B00100011; 168 | TCCR1B = B00011011; 169 | 相位和频率校正PWM,分频比8,频率: 16000,000/2*8*(OCR1A+1) = 488HZ 170 | TCCR1A = B00100001; 171 | TCCR1B = B00010010; 172 | 相位校正PWM,分频比256,频率: 16000000/2*256*(OCR1A+1) = 61HZ 173 | TCCR1A = B00100011; 174 | TCCR1B = B00010100; 175 | OCR1A = 2047; //从0开始数到0CR1A,0-65535,设置周期和频率 176 | OCR1B = val; //用来设置比较器,占空比*/ 177 | -------------------------------------------------------------------------------- /v1.03/Sleep.ino: -------------------------------------------------------------------------------- 1 | //********** T12休眠判断决策 ********** 2 | void t12_sleep() 3 | { 4 | if (sleep_state != digitalRead(t12_sleep_pin))//烙铁动了,计数清零 5 | { 6 | sleep_state = !sleep_state; //状态取反 7 | sleep_count = 0; //计数清零 8 | if (zjm_sleep_ts == 1) 9 | { 10 | zjm_sleep_ts = 0; //提示主界面退出显示休眠状态 11 | set_temp = sleep_temp_cache; 12 | sleep_temp_cache = 0; 13 | buzzer_temp_average_state = 0; //准备好到达温度提示声 14 | buzzer(150, 300); //提示一下 15 | } 16 | } 17 | if (sleep_count == sleep_time && zjm_sleep_ts == 0) //达到休眠的阈值,进入休眠 18 | { 19 | EEPROM.put(set_temp_eeprom, set_temp); //自动保存当前设置温度 20 | zjm_sleep_ts = 1; //提示主界面显示休眠中 21 | buzzer(150, 300); //提示一下 22 | 23 | if (set_temp > sleep_temp) //大于设置的休眠温度 24 | { 25 | sleep_temp_cache = set_temp; //休眠前将温度记录下来,记录和调温 26 | set_temp = sleep_temp; //将温度调至休眠温度 27 | } 28 | else if (set_temp <= sleep_temp) //小于等于设置的休眠温度,只记录不调温 29 | sleep_temp_cache = set_temp; //休眠前将温度记录下来 30 | } 31 | else if (sleep_count > 1800) //半小时没操作,关闭加热 32 | { 33 | MsTimer2::stop(); 34 | set_temp = sleep_temp_cache; 35 | sleep_temp_cache = 0; 36 | t12_switch = 0; 37 | sleep_count = 0; 38 | zjm_sleep_ts = 0; //提示主界面退出休眠 39 | buzzer(150, 1000); //提示一下 40 | } 41 | } 42 | 43 | //********** 系统休眠判断决策 ********** 44 | void system_sleep() 45 | { 46 | if (xp_time_count >= 180) //无加热无操作超过180秒就显示息屏界面 47 | { 48 | if (xp_time_count - xp_time_count_old > 3) //每隔3秒刷新一次位置 49 | { 50 | display_count = ZJM;//退出至主界面 51 | xp_state = 1; //标记息屏状态 52 | xp_x = random(0, 90); 53 | xp_y = random(11, 31); 54 | xp_time_count_old = xp_time_count; 55 | } 56 | else if (xp_time_count >= 65530) //防止数值溢出 57 | { 58 | xp_time_count = 180; 59 | xp_time_count_old = 0; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /v1.03/WDT.ino: -------------------------------------------------------------------------------- 1 | //********** 看门狗函数 ********** 2 | void set_wdt_mod(uint8_t mod, uint8_t ii) //模式,超时时间 3 | { 4 | /* 5 | WDCE 6 | 该位在定时序列中用于更改WDE和预分频器位 7 | 要清除WDE位或更改预分频器位,必须将WDCE置1。 8 | 一旦写入1,硬件将在四个时钟周期后清除WDCE。 9 | 0=16ms,1=32ms,2=64ms,3=128ms,4=250ms 10 | 5=500ms,6=1s,7=2s,8=4s,9=8s 11 | */ 12 | if (ii > 9 ) ii = 9; 13 | byte bb; 14 | bb = ii & 7; 15 | if (ii > 7) bb |= (1 << 5); 16 | bb |= (1 << WDCE); 17 | 18 | switch (mod) { 19 | case 0: //关闭看门狗 20 | __asm__ __volatile__ ("wdr"); //看门狗复位 21 | MCUSR = 0x00; //看门狗复位标志清零 22 | WDTCSR = (1 << WDCE) | (1 << WDE); //打开允许修改使能,并WDE置1 23 | WDTCSR = 0x00; //清除所有预分频位 24 | break; 25 | 26 | case 1: //打开看门狗,设置复位模式 27 | __asm__ __volatile__ ("wdr"); //看门狗复位 28 | MCUSR &= ~(1 << WDRF); //MUUSR中的WDRF清零,清除复位标志 29 | WDTCSR |= (1 << WDCE) | (1 << WDE); //打开允许修改使能,并WDE置1 30 | //设置新的看门狗超时值bb 31 | WDTCSR = bb; //8秒时bb=0011 0001 32 | WDTCSR |= _BV(WDE); //设置复位模式 33 | break; 34 | 35 | case 2: //打开看门狗,设置中断模式 36 | __asm__ __volatile__ ("wdr"); //看门狗复位 37 | MCUSR &= ~(1 << WDRF); //MUUSR中的WDRF清零,清除复位标志 38 | WDTCSR |= (1 << WDCE) | (1 << WDE); //打开允许修改使能,并WDE置1 39 | //设置新的看门狗超时值bb 40 | WDTCSR = bb; //8秒时bb=0011 0001 41 | WDTCSR |= _BV(WDIE); //设置中断模式 42 | break; 43 | 44 | case 3: //打开看门狗,设置中断+复位模式 45 | __asm__ __volatile__ ("wdr"); //看门狗复位 46 | MCUSR &= ~(1 << WDRF); //MUUSR中的WDRF清零,清除复位标志 47 | WDTCSR |= (1 << WDCE) | (1 << WDE); //打开允许修改使能,并WDE置1 48 | //设置新的看门狗超时值bb 49 | WDTCSR = bb; //8秒时bb=0011 0001 50 | WDTCSR |= _BV(WDIE); //设置中断模式 51 | WDTCSR |= _BV(WDE); //设置复位模式 52 | break; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /v1.03/analogRead.ino: -------------------------------------------------------------------------------- 1 | //********** 读取电压、电流、温度 ********** 2 | float vin_cache = 0.0; 3 | uint8_t vin_cache_count = 0; 4 | 5 | float tc1047_cache = 0.0; 6 | uint8_t tc1047_cache_count = 0; 7 | 8 | #define cycs 10 //时间平均滤波的采样次数 采样周期 = 采样次数*定时执行任务的时间 9 | uint8_t t12_adc_error_count = 0; //t12ADC超出检测范围错误计数 10 | void read_timing() //定时读取电源电压和机内温度 11 | { 12 | if (millis() - vin_read_time > t12_temp_read_time) 13 | { 14 | read_t12_temp(); 15 | vin_read_time = millis(); 16 | } 17 | } 18 | void read_timing2() 19 | { 20 | vin_read(); //读取电压 21 | tc1047_temp_read(); //读取室温 22 | if (szjm_oled_sxxk_count == 1) u8g2.setContrast(oled_ld); //改变亮度 23 | } 24 | void read_t12_temp() //定时读取T12的温度 25 | { 26 | float t12_ad_nwe = 0.0; //临时AD 27 | digitalWrite(t12_pwm_pin, 0); 28 | read_timing2(); 29 | delay(1); 30 | t12_ad_nwe = denoiseAnalog(t12_temp_pin); //读取即时AD 31 | //t12_ad_nwe = analogRead(t12_temp_pin); //读取即时AD 32 | t12_ad += (t12_ad_nwe - t12_ad) * 0.7; //平滑滤波 33 | //if (digitalRead(t12_sleep_pin) == 1) t12_ad += 2; //补偿上拉噪声干扰 34 | //计算温度,温度曲线由校准程序自动计算 35 | t12_temp = sz_p[3] * t12_ad * t12_ad * t12_ad + sz_p[2] * t12_ad * t12_ad + sz_p[1] * t12_ad + sz_p[0]; 36 | t12_temp += (tc1047_temp - tc1047_refer); //环境温度补偿 37 | 38 | //记录平均温度 39 | t12_temp_average_cache += t12_temp; 40 | t12_temp_average_count++; 41 | if (t12_temp_average_count == 8) 42 | { 43 | t12_temp_average = t12_temp_average_cache >> 3; 44 | t12_temp_average_cache = 0; //累计缓存温度清零 45 | t12_temp_average_count = 0; //计数清零 46 | } 47 | //运行PID 48 | pid(); 49 | 50 | //手柄检测及超出测量范围检测 51 | if (t12_switch == 0 && t12_ad >= 1020) //无手柄 52 | { 53 | t12_error = 1; 54 | t12_switch = 0; 55 | } 56 | else if (t12_switch == 1 && t12_ad >= 1020) //超出测量范围检测,延时检测 57 | { 58 | t12_adc_error_count++; 59 | if (t12_adc_error_count >= 8) 60 | { 61 | MsTimer2::stop(); //停止一次 然后在MsTimer2_rw1()里自动切换定时的中断任务 62 | t12_adc_error_count = 0; //清除计数 63 | t12_adc_error = 1; 64 | t12_switch = 0; 65 | } 66 | } 67 | else if (t12_switch == 1 && t12_ad < 1020) 68 | { 69 | t12_adc_error = 0; 70 | t12_adc_error_count = 0; //清除计数 71 | } 72 | else t12_error = 0; 73 | } 74 | 75 | void vin_read() 76 | { 77 | /* 78 | 串联电阻的中点电压计算公式 79 | Eout 中点电压 80 | Vcc 输入电压(两端施加电压) 81 | R1、R2 两个串联的分压电阻 82 | Eout = Vcc * R2/(R1+R2) R1靠近电源 R2靠近地 83 | */ 84 | /*vin = (denoiseAnalog(vin_pin) / 0.1282) * vcc_refer_fl; //计算电源电压 10/68+10=0.1282 85 | 板子实际R2是62k,所以是10/(62+10)=0.1389 86 | if (vin < vin_low && vin_low >= 3.3) //电压过低提示 87 | { 88 | vin_error = 1; 89 | t12_switch = 0; 90 | }*/ 91 | 92 | vin_cache += (denoiseAnalog(vin_pin) / 0.1389) * vcc_refer_fl; 93 | vin_cache_count++; 94 | if (vin_cache_count >= cycs) 95 | { 96 | vin = vin_cache / cycs + vin_refer; 97 | vin_cache_count = 0; 98 | vin_cache = 0; 99 | //电压过低提示 100 | if (vin < vin_low && vin_low >= 3.3) 101 | { 102 | vin_error = 1; 103 | t12_switch = 0; 104 | } 105 | else vin_error = 0; 106 | } 107 | } 108 | 109 | void tc1047_temp_read() //读取tc1047温度 110 | { 111 | //tc1047_temp = ((denoiseAnalog(tc1047_pin) * vcc_refer_fl) - 0.5) * 100; 112 | 113 | tc1047_cache += ((denoiseAnalog(tc1047_pin) * vcc_refer_fl) - 0.5) * 100; 114 | tc1047_cache_count++; 115 | if (tc1047_cache_count >= cycs) 116 | { 117 | tc1047_temp = tc1047_cache / cycs; 118 | tc1047_cache_count = 0; 119 | tc1047_cache = 0; 120 | } 121 | } 122 | 123 | /*uint16_t denoiseAnalog(uint8_t pin) 124 | { 125 | uint8_t low, high; 126 | if (pin >= A0) pin -= A0; //设置端口 127 | ADMUX = (0x0F & pin) | bit(REFS0); //设置基准电压为5V,设置端口 128 | ADCSRA |= bit (ADEN) | bit (ADIF); //启用ADC,关闭任何挂起的中断 129 | set_sleep_mode (SLEEP_MODE_ADC); //在取样时进行睡眠以降低噪音,需要开启ADC中断进行唤醒 130 | sleep_mode(); //进入休眠自动启动转换 131 | //bitSet(ADCSRA, ADSC); //ADSC 写1启动AD转换 132 | while (bitRead(ADCSRA, ADSC)); //等待转换结束 133 | low = ADCL; 134 | high = ADCH; 135 | bitClear (ADCSRA, ADEN); // 禁用ADC 136 | return (high << 8) | low; //返回数值 137 | }*/ 138 | uint16_t denoiseAnalog (byte port) 139 | { 140 | uint16_t result = 0; 141 | if (port >= A0) port -= A0; //设置端口 142 | ADMUX = (0x0F & port) | bit(REFS0); //设置基准电压为5V,设置端口 143 | ADCSRA |= bit (ADEN) | bit (ADIF); //启用ADC,关闭任何挂起的中断 144 | set_sleep_mode (SLEEP_MODE_ADC); //在取样时进行睡眠以降低噪音,需要开启ADC中断进行唤醒 145 | for (uint8_t i = 0; i < 16; i++) { // get 32 readings 146 | sleep_mode(); // go to sleep while taking ADC sample 147 | while (bitRead(ADCSRA, ADSC)); // 等待转换结束 148 | result += ADC; // add them up 149 | } 150 | bitClear (ADCSRA, ADEN); // 禁用ADC 151 | return (result >> 4); // devide by 32 and return value 152 | } 153 | //ADC中断服务 154 | EMPTY_INTERRUPT (ADC_vect); // 这里没什么可做的 155 | -------------------------------------------------------------------------------- /v1.03/v1.03.ino: -------------------------------------------------------------------------------- 1 | /*项目代码修改自 甘草酸不酸 开源https://github.com/jie326513988/mini-T12 2 | *PCB及BOM开源链接https://github.com/zxcvbnm1421899466/328P-MiNi-T12 3 | * _樱下小渚花田汐_ https://space.bilibili.com/34620092 修改 4 | * 编码器控制改为按键控制 5 | */ 6 | 7 | /* 8 | 默认支持深圳头,更换其他厂商的头需要自行校准温度曲线 9 | 一定要使用我提供的U8g2库,否者无法显示中文和提示内存过大无法编译!!! 10 | */ 11 | /*程序更新说明 12 | * v1.03 13 | 1.增大旋转的音调音量,修改进入和退出设置界面的音调音量 14 | 2.降低烙铁唤醒烙铁的灵敏度 15 | 3.优化pid,并不是很明显 16 | * v1.02 17 | 1.新增停止时记录当前的设置温度(休眠时也会自动保存) 18 | v1.01 19 | 1.调节PID运行间隔 20 | 2.降低PWM频率为15HZ,手柄和mos的声音几乎没有了!之前为61HZ,声音还是有一点的。 21 | v1.00(此版本需要更新U8G2库) 22 | 1.缩小一点点的内存 23 | 2.修复T12 ADC HIGH报警时无法进入息屏的BUG 24 | v0.99 25 | 1.开机就加热的模式下PWM动画会向下鬼畜,所以将开机过渡动画改为向上过渡,这样就看不到鬼畜啦 26 | 2.开机加热模式的选择改为按下确认键就切换模式,取消原实心选框旋转选择 27 | 3.添加只有在主界面下才能清除T12 ADC 超出读取读取范围的提示 28 | v0.98 29 | 1.温度曲线适配最新版本的PCB 30 | v0.97 31 | 1.优化校准界面的PID策略 32 | v0.96 33 | 1.优化内存 34 | v0.95 35 | 1.平滑的开机过度效果 36 | v0.94 37 | 1.曲线拟合改为3项式,以更加准确的绘制温度曲线 38 | v0.93 39 | 1.动态PID 40 | 2.取消电流传感器,主界面取消电流显示改为显示PWM百分比 41 | 3.设置菜单增加曲线拟合校准 42 | 4.休眠计时和息屏倒计时改用定时器2计时 43 | 5.息屏显示,无加热无操作3分钟后进入,息屏时显示环境温度 44 | 6.开机提示音和开机画面 45 | 7.休眠时自动保存当前设置温度到eeprom 46 | 8.待机功耗8.8ma 息屏待机功耗6.4ma 47 | */ 48 | /* 49 | 按键功能定义 50 | 长按操作(5下短音最后1下长音) 51 | 主界面:进入设置界面 52 | 其他界面:退出至主界面(校准界面除外) 53 | 双击操作(2下短音) 54 | 主界面:加热或停止状态切换 55 | 其他界面:无 56 | 单击(1下短音) 57 | 主界面:无 58 | 设置界面:进入二级菜单 59 | 二级菜单:切换数值更改的选中状态(空心选框或实心选框),或确认更改数值,无选框状态则退出至一级菜单 60 | 菜单选项 61 | PID 62 | P 63 | I 64 | D 65 | 休眠 66 | 休眠时间 67 | 休眠温度 68 | 屏幕 69 | 屏幕亮度 70 | 屏幕方向 71 | 编码器方向 72 | 电源 73 | 基准电压 74 | 电源电压 75 | 低压报警 76 | 校准 77 | 调节曲线1段温度 78 | 调节曲线2段温度 79 | 调节曲线2段温度 80 | 调节曲线3段温度 81 | 运行曲线拟合并校准曲线 82 | 烙铁 83 | 冷端补偿 84 | 开机加热 85 | 重置 86 | */ 87 | #include 88 | #include //掉电数值存储库 89 | #include //休眠库 90 | #include //屏幕驱动库 91 | #ifdef U8X8_HAVE_HW_I2C 92 | #include 93 | #endif 94 | U8G2_SSD1306_128X32_UNIVISION_2_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); 95 | 96 | //********** 版本号 ********** 97 | #define version "v1.03" 98 | //********** 引脚定义 ********** 99 | #define SW 4 //按下 ,可更改其他引脚 100 | #define CLK 3 //旋转 ,不可更改 101 | #define DT 2 //旋转 ,可更改其他引脚 102 | //除了10号脚不能改,其他都可以改,但模拟引脚只能改模拟引脚(休眠引脚除外) 103 | #define t12_sleep_pin A0 //t12休眠 模拟读取引脚 104 | #define t12_temp_pin A2 //t12温度 模拟读取引脚 105 | #define tc1047_pin A3 //机内温度 模拟读取引脚 106 | #define vin_pin A6 //电源电压 模拟读取引脚 107 | #define t12_pwm_pin 10 //t12加热 pwm输出引脚,定死不可更改 108 | #define buzzer_pin 8 //蜂鸣器 输出引脚 109 | //************ EEPROM地址定义 ************ 110 | uint8_t auto_get = 0; //自动刷写eeprom的状态存储,判断是否首次开机 0-首次 1-非首次 111 | #define auto_get_eeprom 0 //自动刷写eeprom的状态存储,1位 112 | #define p_eeprom 1 //p地址,4位 113 | #define i_eeprom p_eeprom+4 //i地址,4位 114 | #define d_eeprom i_eeprom+4 //d地址,4位 115 | #define sleep_time_eeprom d_eeprom+4 //休眠时间,4位 116 | #define sleep_temp_eeprom sleep_time_eeprom+4 //休眠温度,1位 117 | #define oled_ld_eeprom sleep_temp_eeprom+1 //OLED亮度,1位 118 | #define vcc_refer_eeprom oled_ld_eeprom+1 //基准电压,4位 119 | #define vin_refer_eeprom vcc_refer_eeprom+4 //电源电压校准值,4位 120 | #define t12_kj_jr_eeprom vin_refer_eeprom+4 //是否开机就加热?,1位 121 | #define vin_low_eeprom t12_kj_jr_eeprom+1 //输入电压低压报警阈值,4位 122 | #define tc1047_refer_eeprom vin_low_eeprom+4 //冷端补偿校准值,1位 123 | #define oled_fx_eeprom tc1047_refer_eeprom+1 //OELD方向,1位 124 | #define xzbmq_fx_eeprom oled_fx_eeprom+1 //编码器旋转方向,1位 125 | #define sz_temp0_eeprom xzbmq_fx_eeprom+1 //深圳头曲线温度校准1段,4位 126 | #define sz_temp1_eeprom sz_temp0_eeprom+4 //深圳头曲线温度校准2段,4位 127 | #define sz_temp2_eeprom sz_temp1_eeprom+4 //深圳头曲线温度校准3段,4位 128 | #define sz_temp3_eeprom sz_temp2_eeprom+4 //深圳头曲线温度校准4段,4位 129 | #define set_temp_eeprom sz_temp3_eeprom+4 //t12设置温度,4位 130 | //T12及温度相关 131 | boolean t12_switch = 0; //T12加热开关 132 | boolean t12_kj_jr = 1; //是否开机就加热? 0-否 1-是 133 | 134 | float t12_ad = 0.0; //T12即时ADC值 135 | uint16_t t12_temp = 0.0; //T12即时温度 136 | boolean t12_error = 0; //手柄未接提示 137 | boolean t12_adc_error = 0; //温度超出测量范围 138 | uint16_t set_temp_max; //自动计算设置的温度最大值 139 | uint16_t set_temp_min; //自动计算设置的温度最小值 140 | 141 | int16_t t12_temp_average_cache = 0; //记录采集温度,缓存用 142 | int16_t t12_temp_average = 0; //8次内采集到的平均温度,显示用 143 | uint8_t t12_temp_average_count = 0; //平均温度采集计数 144 | boolean buzzer_temp_average_state = 0; //到达温度提示声 145 | 146 | //float tc1047_ad = 0.0; //tc1047ADC值 147 | float tc1047_temp = 0.0; //tc1047温度,机内温度 148 | int8_t tc1047_refer = 30; //T12环境参考温度校准值 149 | 150 | float vcc_refer = 4.95; //参考电压,稳压芯片输出的电压是多少就填多少 151 | float vin = 0.0; //电源电压 152 | float vin_refer = 0.0; //输入电压校准值 153 | float vin_low = 3.3; //低压报警阈值 154 | boolean vin_error = 0; //低压报警提示 155 | #define vcc_refer_fl vcc_refer/1023.0 //参考电压每级分量 156 | 157 | uint32_t xzbmq_time = 0; //编码器消抖对比时间 158 | uint32_t temp_read_time = 0; //定时读取温度对比时间 159 | uint32_t vin_read_time = 0; //定时读取输入电压时间 160 | uint32_t t12_temp_read_time = 450; //定时T12温度采样时间 161 | 162 | boolean buzzer_state = 0; //蜂鸣器准备状态 163 | uint16_t buzzer_time; //蜂鸣器响的时间 164 | uint16_t buzzer_count; //蜂鸣器响的次数 165 | boolean buzzer_szjm_state = 0; //进入设置界面的长音状态 166 | boolean buzzer_zjm_state = 0; //退出至主界面的长音状态 167 | 168 | boolean zjm_sleep_ts = 0; //主界面休眠提示 0-无 1-休眠中 169 | uint16_t sleep_time = 180; //进入休眠的时间阈值,单位秒 170 | uint8_t sleep_temp = 200; //休眠时的温度,单位摄氏度 171 | boolean sleep_state = 0; //休眠引脚状态 0低电平 1高电平 172 | uint16_t sleep_count = 0; //休眠计数 173 | uint16_t sleep_temp_cache = 0; //休眠前的温度缓存 174 | 175 | uint8_t oled_ld = 50; //OLED亮度 176 | boolean oled_fx = 0; //OLED方向 0-不旋转,横向显示 1-旋转180度 177 | boolean xzbmq_fx = 0; //编码器方向 0-顺加逆减 1-顺减逆加 178 | boolean hfccsz_state = 0; //恢复出厂设置 0-NO 1-YES 179 | 180 | boolean xp_state = 0; //息屏状态 0-无 1-息屏 181 | uint16_t xp_time_count = 0; //息屏计数 182 | uint16_t xp_time_count_old = 0; //上一次时间计数 183 | int8_t xp_x = 0; //息屏随机变化位置X 184 | int8_t xp_y = 0; //息屏随机变化位置Y 185 | int8_t xp_x_old = 50; //上一次息屏随机变化位置X 186 | int8_t xp_y_old = 21; //上一次息屏随机变化位置Y 187 | 188 | //深圳头曲线拟合的4段ADC 189 | #define sz_adc0 10 190 | #define sz_adc1 350 191 | #define sz_adc2 650 192 | #define sz_adc3 940 193 | uint16_t sz_temp[4] = {49, 262, 391, 486}; //深圳头曲线拟合的4段温度 Y 194 | float sz_p[4]; //深圳头曲线拟合的4个系数 P 195 | //********** 菜单标志位相关 ********** 196 | #define ZJM 1 //主界面 197 | #define SZJM 2 //设置界面 198 | #define SZJM_PID 3 //PID设置界面 199 | #define SZJM_SLEEP 4 //休眠设置界面 200 | #define SZJM_OLED 5 //OLED设置界面 201 | #define SZJM_POWER 6 //电源设置界面 202 | #define SZJM_JIAOZHUN 7 //校准设置界面 203 | #define SZJM_LAOTIE 8 //烙铁头设置界面 204 | 205 | uint8_t display_count = 1; //默认要显示的界面 206 | boolean dec_state = 0; //小数点输入状态 0关闭 1开启 207 | uint8_t qj_ca_count = 0; //全局长按计数 208 | 209 | boolean szjm_kxxk_L = 0; //设置界面空心选框 顺时针转 210 | boolean szjm_kxxk_R = 0; //设置界面空心选框 逆时针转 211 | int8_t szjm_kxxk_count = 0; //设置界面空心选框 212 | 213 | int8_t szjm_pid_kxxk_count = 0; //pid界面空心选框 214 | int8_t szjm_pid_sxxk_count = 0; //pid界面实心选框 215 | 216 | int8_t szjm_sleep_kxxk_count = 0; //pid界面空心选框 217 | int8_t szjm_sleep_sxxk_count = 0; //pid界面实心选框 218 | 219 | int8_t szjm_oled_kxxk_count = 0; //oled界面空心选框 220 | int8_t szjm_oled_sxxk_count = 0; //oled界面实心选框 221 | 222 | int8_t szjm_power_kxxk_count = 0; //电源设置界面空心选框 223 | int8_t szjm_power_sxxk_count = 0; //电源设置界面实心选框 224 | 225 | int8_t szjm_pwm_kxxk_count = 0; //PWM界面空心选框 226 | int8_t szjm_pwm_sxxk_count = 0; //PWM界面实心选框 227 | 228 | int8_t szjm_laotie_kxxk_count = 0; //烙铁头设置界面空心选框 229 | int8_t szjm_laotie_sxxk_count = 0; //烙铁头设置界面实心选框 230 | 231 | int8_t szjm_jiaozhun_kxxk_count = 0; //烙铁头设置界面空心选框 232 | int8_t szjm_jiaozhun_sxxk_count = 0; //烙铁头设置界面实心选框 233 | //********** 动态调参PID ********** 234 | float p = 25.0; //比例系数 235 | float i = 8.7; //积分系数 236 | float d = 2.6; //微分系数 237 | 238 | #define p_jz 12.0 //校准界面用的 比例系数 239 | #define i_jz 2.2 //校准界面用的 积分系数 240 | #define d_jz 1.2 //校准界面用的 微分系数 241 | 242 | uint16_t set_temp = 320; //设置温度 243 | int16_t thisError = 0; //本次误差 244 | int16_t thisError_average = 0; //平均值的误差 245 | int16_t lasterror = 0; //前一拍偏差 246 | int16_t preerror = 0; //前两拍偏差 247 | const int8_t deadband = 0; //死区 248 | int16_t pid_out = 0.0; //PID控制器计算结果 249 | uint8_t pid_out_bfb = 0.0; //输出值0-100% 250 | const float pwm_max = 2047.0; //输出值上限 251 | const float pwm_min = 0.0; //输出值下限 252 | const float errorabsmax = 2000.0; //偏差绝对值最大值 253 | const float errorabsmin = 50.0; //偏差绝对值最小值 254 | const float alpha = 0.2; //不完全微分系数 255 | float deltadiff = 0.0; //微分增量 256 | 257 | void setup() 258 | { 259 | //***** 首次开机自动刷写eeprom 260 | eerpom_auto(); 261 | //***** 编码器配置 262 | pinMode(SW, INPUT_PULLUP); //按下 263 | pinMode(CLK, INPUT_PULLUP); //相位A 264 | pinMode(DT, INPUT_PULLUP); //相位B 265 | pinMode(t12_temp_pin, INPUT); //t12温度 266 | pinMode(t12_sleep_pin, INPUT_PULLUP); //t12休眠 267 | pinMode(vin_pin, INPUT); //电源电压 268 | pinMode(tc1047_pin, INPUT); //机内温度 269 | pinMode(buzzer_pin, OUTPUT); //蜂鸣器 270 | pinMode(t12_pwm_pin, OUTPUT); //t12加热,不可更改 271 | 272 | digitalWrite(t12_pwm_pin, 0); //默认关闭 273 | digitalWrite(buzzer_pin, 0); //默认关闭 274 | //***** OLED初始化 275 | u8g2.begin(); 276 | u8g2.enableUTF8Print(); 277 | u8g2.setContrast(oled_ld); //设置亮度1-255 278 | //u8g2.setBusClock(400000); //设置I2C通讯速度默认MAX400000 279 | //u8g2.setPowerSave(0); //0开启屏幕 1关闭屏幕 280 | if (oled_fx)u8g2.setDisplayRotation(U8G2_R2); //旋转180度 281 | else u8g2.setDisplayRotation(U8G2_R0); //0度,默认方向 282 | //***** ADC初始化 283 | //ADCSRA |= bit (ADPS0) | bit (ADPS1) | bit (ADPS2); // 设置ADC分频 128倍 284 | ADCSRA |= bit (ADPS1) | bit (ADPS2); //设置ADC分频 64倍 285 | ADCSRA |= bit (ADIE); // 开启ADC中断 286 | interrupts(); // 开启全局中断 287 | //***** 打开外部中断 288 | attachInterrupt(digitalPinToInterrupt(CLK), xuan_zhaun, FALLING); //PIN3,选择编码器 旋转,下降沿触发 FALLING 289 | attachInterrupt(digitalPinToInterrupt(DT), xuan_zhaun, FALLING); 290 | 291 | //***** 播放开机画面和开机声 292 | kj_display(); 293 | buzzer(600, 200); //时间,次数 294 | buzzer_run(); 295 | buzzer(400, 300); //时间,次数 296 | buzzer_run(); 297 | buzzer(130, 1000); //时间,次数 298 | buzzer_run(); 299 | //读取电压/温度 300 | for (uint8_t i = 0; i < 10; i++) //读取初始值 301 | { 302 | vin_read(); 303 | tc1047_temp_read(); 304 | read_t12_temp(); 305 | } 306 | //***** 开启看门狗 307 | //set_wdt_mod(1, 7); 308 | //***** 是否开机加热 309 | if (t12_kj_jr == 1) t12_switch = 1; 310 | else t12_switch = 0; 311 | //***** 开机计算曲线拟合系数 312 | qxnh_run(); 313 | //Serial.begin(9600); //打开串口调试 314 | } 315 | 316 | void loop() 317 | { 318 | //uint32_t time0 = micros(); 319 | 320 | __asm__ __volatile__ ("wdr"); //看门狗复位 321 | an_xia(); //编码器按下决策 322 | draw_page(); //刷新屏幕 323 | buzzer_run(); //蜂鸣器运行决策 324 | read_timing(); //定时读取任务 325 | MsTimer2_rw1(); //定时器2任务 326 | 327 | //uint32_t time1 = micros(); 328 | //Serial.println(time1 - time0); 329 | } 330 | -------------------------------------------------------------------------------- /v1.20.1/A_ReadMe.ino: -------------------------------------------------------------------------------- 1 | /* 2 | 校准温度曲线的方法 3 | 1.先校准基准电压,测量串口的5V接口就是基准电压 4 | 2.准备好能测量0-500摄氏度的设备,探头建议使用裸装,以免外壳热传导导致热量损失测量不准 5 | 3.将探头紧压住烙铁头发热前段(上锡部分再下来一点),一定要紧紧压住,不然也会测量不准 6 | 4.放置好烙铁头以免校准时烫伤手或物品! 7 | 5.接上电源,进入‘烙台’界面,将室温设置为当前的冷端补偿温度,再进入‘校准’界面,将空心选框移动至第1段温度处(即对应的ADC 10下面) 8 | 6.按下确认键,此时空心选框变成实心选框,烙铁头开始加热,等待最下方的‘Now ADC’值稳定在一定的范围,与第一行相应的ADC值差不多即可(此时是ADC 10) 9 | 7.使用测量设备测量烙铁头的温度,将第1段温度调至测量得到的温度(实心选框状态可旋转旋钮调节数值) 10 | 8.依次测量剩下的第2段、第3段、第4段温度并输入至控制器 11 | 9.测量完4段温度后将光标移至Save,按下确认键,等待程序计时温度曲线 12 | 10.计算完会显示P系数界面,,再按下确认键即可退出校准界面 13 | 11.在主界面准备进行二次校准 14 | 12.在主界面开启加热至第二段校准的温度,如265,则加热至260度,若不对则进入校准界面加减对应的计算温度,直至自己满意为止。 15 | 13.依次加热至第三、第四、第一、第四段温度并校准,直至自己满意为止。 16 | */ 17 | 18 | /* 19 | 长按操作(5下短音最后1下长音) 20 | 主界面,进入设置界面 21 | 其他界面,退出至主界面 22 | 双击操作(2下短音) 23 | 主界面,加热或停止状态切换 24 | 其他界面,无 25 | 单击(1下短音) 26 | 主界面,无 27 | 设置界面,进入二级菜单 28 | 二级菜单,切换数值更改选中状态,或确认更改数值,无选框状态则退出至一级菜单 29 | */ 30 | -------------------------------------------------------------------------------- /v1.20.1/Buzzer.ino: -------------------------------------------------------------------------------- 1 | //********** 控制蜂鸣器发声的频率和时间,系统延时法,占用系统速度大 ********** 2 | uint32_t error_buzzer_db_time = 0; 3 | void buzzer_run() 4 | { 5 | pinMode(buzzer_pin, OUTPUT); 6 | if (buzzer_state == 1) 7 | { 8 | for (uint16_t i = 0; i < buzzer_count; i++) 9 | { 10 | digitalWrite(buzzer_pin, 1); 11 | delayMicroseconds(buzzer_time); 12 | digitalWrite(buzzer_pin, 0); 13 | if (i < buzzer_count - 1) delayMicroseconds(buzzer_time); //最后一次不需要延时 14 | } 15 | buzzer_state = 0; 16 | } 17 | //错误提示报警音 18 | if (vin_error == 1 || t12_adc_error == 1) 19 | { 20 | if (millis() - error_buzzer_db_time > 1000) 21 | { 22 | buzzer(120, 300); 23 | error_buzzer_db_time = millis(); 24 | } 25 | } 26 | 27 | if (buzzer_szjm_state == 1) //进入设置界面时发出声音提示一下 28 | { 29 | buzzer(150, 720); 30 | buzzer_szjm_state = 0; 31 | } 32 | else if (buzzer_zjm_state == 1) //退出至主界面时发出声音提示一下 33 | { 34 | buzzer(150, 720); 35 | buzzer_zjm_state = 0; 36 | } 37 | pinMode(buzzer_pin, INPUT); 38 | } 39 | 40 | void buzzer(uint16_t time, uint16_t count) 41 | { 42 | buzzer_state = 1; //准备好蜂鸣器 43 | buzzer_time = time; //设置时间 44 | buzzer_count = count; //设置次数 45 | } 46 | //********************************************************* 47 | 48 | //****** 控制蜂鸣器发声的频率和时间,内部中断法,占用系统速度小 ****** 49 | 50 | /*void buzzer(uint16_t time, uint16_t count) //时间单位ms 51 | { 52 | if (buzzer_state == 0 && digitalRead(buzzer_pin) == 0) //蜂鸣器停止状态才能设置定时器 53 | { 54 | buzzer_count = count; //设置次数 55 | Timer1.initialize(time); //设置时间 56 | Timer1.attachInterrupt(buzzer_isr); //设置定时器中断函数 57 | Timer1.start(); //启动定时器 58 | } 59 | } 60 | void buzzer_isr() 61 | { 62 | buzzer_isr_count++; 63 | bitWrite(PINB, 0, 1); //设置pin8为输出 PINX写1翻转状态 64 | buzzer_state = 1; //标识蜂鸣器正在工作 65 | if (buzzer_isr_count >= buzzer_count) 66 | { 67 | buzzer_isr_count = 0; // 清除计数 68 | buzzer_state = 0; //标识蜂鸣器已停止 69 | digitalWrite(buzzer_pin, 0); //关闭蜂鸣器 70 | Timer1.stop(); //停止中断 71 | } 72 | }*/ 73 | //********************************************************* 74 | uint8_t get_num_digit(uint32_t num)//获取数字的位数 75 | { 76 | uint8_t count = 0; 77 | if (num == 0) count = 1; 78 | while (num != 0) 79 | { 80 | // n = n/10 81 | num /= 10; 82 | ++count; 83 | } 84 | return count; 85 | } 86 | -------------------------------------------------------------------------------- /v1.20.1/CurveFitting.ino: -------------------------------------------------------------------------------- 1 | //********** 曲线拟合程序 ********** 2 | //曲线拟合算法来至https://blog.csdn.net/m0_37362454/article/details/82456616 by欧阳小俊 3 | void qxnh_run() //曲线拟合运行 4 | { 5 | int16_t i, sizenum; 6 | float P[4]; 7 | int8_t dimension = 3; //3次多项式拟合 8 | // 要拟合的数据 9 | int xx[] = {sz_adc0, sz_adc1, sz_adc2, sz_adc3}; //t12 adc 10 | //int yy[] = {45, 219, 366, 435}; //测量设备的温度 11 | 12 | sizenum = sizeof(xx) / sizeof(xx[0]); //拟合数据的维数 13 | polyfit(sizenum, xx, sz_temp, dimension, P); 14 | 15 | sz_p[0] = P[0]; 16 | sz_p[1] = P[1]; 17 | sz_p[2] = P[2]; 18 | sz_p[3] = P[3]; 19 | /* 20 | 得出系数:P[0],P[1],P[2] 21 | 曲线公式:y = P[3]*X*X*X+P[2]*X*X + P[1]*X + P[0] 22 | 曲线公式:t12_temp =P[3]* t12_ad * t12_ad* t12_ad + P[2] * t12_ad * t12_ad + P[1] * t12_ad + P[0]; 23 | */ 24 | } 25 | 26 | /*==================polyfit(n,x,y,poly_n,a)===================*/ 27 | /*=======拟合y=a0+a1*x+a2*x^2+……+apoly_n*x^poly_n========*/ 28 | /*=====n是数据个数 xy是数据值 poly_n是多项式的项数======*/ 29 | /*===返回a0,a1,a2,……a[poly_n],系数比项数多一(常数项)=====*/ 30 | void polyfit(int n, int x[], int y[], int poly_n, float p[]) 31 | { 32 | int i, j; 33 | float *tempx, *tempy, *sumxx, *sumxy, *ata; 34 | 35 | tempx = (float *)calloc(n , sizeof(float)); 36 | sumxx = (float *)calloc((poly_n * 2 + 1) , sizeof(float)); 37 | tempy = (float *)calloc(n , sizeof(float)); 38 | sumxy = (float *)calloc((poly_n + 1) , sizeof(float)); 39 | ata = (float *)calloc( (poly_n + 1) * (poly_n + 1) , sizeof(float) ); 40 | for (i = 0; i < n; i++) 41 | { 42 | tempx[i] = 1; 43 | tempy[i] = y[i]; 44 | } 45 | for (i = 0; i < 2 * poly_n + 1; i++) 46 | { 47 | for (sumxx[i] = 0, j = 0; j < n; j++) 48 | { 49 | sumxx[i] += tempx[j]; 50 | tempx[j] *= x[j]; 51 | } 52 | } 53 | for (i = 0; i < poly_n + 1; i++) 54 | { 55 | for (sumxy[i] = 0, j = 0; j < n; j++) 56 | { 57 | sumxy[i] += tempy[j]; 58 | tempy[j] *= x[j]; 59 | } 60 | } 61 | for (i = 0; i < poly_n + 1; i++) 62 | { 63 | for (j = 0; j < poly_n + 1; j++) 64 | { 65 | ata[i * (poly_n + 1) + j] = sumxx[i + j]; 66 | } 67 | } 68 | gauss_solve(poly_n + 1, ata, p, sumxy); 69 | 70 | free(tempx); 71 | free(sumxx); 72 | free(tempy); 73 | free(sumxy); 74 | free(ata); 75 | } 76 | /*============================================================ 77 | 高斯消元法计算得到 n 次多项式的系数 78 | n: 系数的个数 79 | ata: 线性矩阵 80 | sumxy: 线性方程组的Y值 81 | p: 返回拟合的结果 82 | ============================================================*/ 83 | void gauss_solve(int n, float A[], float x[], float b[]) 84 | { 85 | int i, j, k, r; 86 | float max; 87 | for (k = 0; k < n - 1; k++) 88 | { 89 | max = fabs(A[k * n + k]); // find maxmum 90 | r = k; 91 | for (i = k + 1; i < n - 1; i++) 92 | { 93 | if (max < fabs(A[i * n + i])) 94 | { 95 | max = fabs(A[i * n + i]); 96 | r = i; 97 | } 98 | } 99 | if (r != k) 100 | { 101 | for (i = 0; i < n; i++) //change array:A[k]&A[r] 102 | { 103 | max = A[k * n + i]; 104 | A[k * n + i] = A[r * n + i]; 105 | A[r * n + i] = max; 106 | } 107 | max = b[k]; //change array:b[k]&b[r] 108 | b[k] = b[r]; 109 | b[r] = max; 110 | } 111 | 112 | for (i = k + 1; i < n; i++) 113 | { 114 | for (j = k + 1; j < n; j++) 115 | A[i * n + j] -= A[i * n + k] * A[k * n + j] / A[k * n + k]; 116 | b[i] -= A[i * n + k] * b[k] / A[k * n + k]; 117 | } 118 | } 119 | 120 | for (i = n - 1; i >= 0; x[i] /= A[i * n + i], i--) 121 | { 122 | for (j = i + 1, x[i] = b[i]; j < n; j++) 123 | x[i] -= A[i * n + j] * x[j]; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /v1.20.1/Display.ino: -------------------------------------------------------------------------------- 1 | //********** 显示决策 ********** 2 | uint32_t system_sleep_db_time = 0; //系统进入睡眠对比时间 3 | void display() 4 | { 5 | if (xp_state == 0) //正常显示 6 | { 7 | if (display_count == ZJM) zjm(); 8 | else if (display_count == SZJM) szjm(); 9 | else if (display_count == SZJM_PID) szjm_pid(); 10 | else if (display_count == SZJM_SLEEP) szjm_sleep(); 11 | else if (display_count == SZJM_OLED) szjm_oled(); 12 | else if (display_count == SZJM_POWER) szjm_power(); 13 | else if (display_count == SZJM_LAOTIE) szjm_laotie(); 14 | else if (display_count == SZJM_JIAOZHUN) szjm_jiaozhun(); 15 | } 16 | else xpjm(); //显示息屏界面 17 | } 18 | 19 | void draw_page(void) 20 | { 21 | static uint8_t is_next_page = 0; 22 | // 调用第一页,如果需要 23 | if ( is_next_page == 0 ) 24 | { 25 | u8g2.firstPage(); 26 | is_next_page = 1; 27 | } 28 | // 画我们的屏幕 29 | display(); 30 | // 调用下一页 31 | if ( u8g2.nextPage() == 0 ) 32 | { 33 | is_next_page = 0; // 确保调用了第一个页面 34 | } 35 | } 36 | 37 | void display_hfccsz() //恢复出厂设置进度显示界面 38 | { 39 | uint16_t x_old = 0; 40 | for (int i = 0 ; i < EEPROM.length() ; i++) 41 | { 42 | __asm__ __volatile__ ("wdr"); //防止没清除完因看门狗没喂狗导致重启 43 | uint16_t x_new = map(i, 0, EEPROM.length(), 0, 100); 44 | if (x_new - x_old >= 5) 45 | { 46 | u8g2.firstPage(); 47 | do { 48 | u8g2.setCursor(50, 16); 49 | u8g2.print(x_new); 50 | u8g2.setCursor(75, 16); 51 | u8g2.print("%"); 52 | x_old = x_new; 53 | } while ( u8g2.nextPage() ); 54 | } 55 | EEPROM.write(i, 0); //清除所有EEPROM 56 | } 57 | set_wdt_mod(1, 0); //利用看门狗实现软重启 58 | } 59 | 60 | void kj_display() //开机显示版本号 61 | { 62 | u8g2.firstPage(); 63 | do { 64 | u8g2.setFont(chinese_t12); 65 | u8g2.setCursor(50, 21); 66 | u8g2.print(version); 67 | } while ( u8g2.nextPage() ); 68 | } 69 | 70 | void xpjm() //息屏界面 71 | { 72 | if (xp_x - xp_x_old > 0) 73 | { 74 | if (xp_x_old != xp_x) xp_x_old++; 75 | } 76 | else if (xp_x - xp_x_old < 0 ) 77 | { 78 | if (xp_x_old != xp_x) xp_x_old--; 79 | } 80 | 81 | if (xp_y - xp_y_old > 0) 82 | { 83 | if (xp_y_old != xp_y) xp_y_old++; 84 | } 85 | else if (xp_y - xp_y_old < 0 ) 86 | { 87 | if (xp_y_old != xp_y) xp_y_old--; 88 | } 89 | 90 | u8g2.setFont(chinese_t12); 91 | u8g2.setCursor(xp_x_old, xp_y_old); 92 | u8g2.print(tc1047_temp, 1); 93 | u8g2.setCursor(xp_x_old + 27, xp_y_old - 1); 94 | u8g2.print("℃"); 95 | } 96 | 97 | /*u8g2.firstPage(); 98 | do { 99 | u8g2.setFont(chinese_t12); 100 | u8g2.setCursor(xp_x, xp_y); 101 | u8g2.print(tc1047_temp, 1); 102 | u8g2.setCursor(xp_x + 27, xp_y - 1); 103 | u8g2.print("℃"); 104 | } while ( u8g2.nextPage() );*/ 105 | -------------------------------------------------------------------------------- /v1.20.1/DisplayMain.ino: -------------------------------------------------------------------------------- 1 | //********** 画主界面 ********** 2 | uint8_t zjm_x1 = 0; 3 | uint8_t zjm_x2 = 100; 4 | #define zjm_x3 75 5 | #define zjm_x4 zjm_x3+4 6 | 7 | #define zjm_y1 7 8 | #define zjm_y2 19 9 | #define zjm_y3 32 10 | #define zjm_y4 14 11 | boolean zjm_dh_run = 0; //主界面动画状态 0-不允许 1-允许 12 | uint32_t zjm_dh_time1 = 0; //动画1运转对比时间 13 | uint32_t zjm_dh_time2 = 0; //动画2运转对比时间 14 | //热、停切换动画变量 15 | uint8_t zjm_dh_x1 = 0; 16 | uint8_t zjm_dh_y1 = 0; 17 | uint8_t zjm_dh_r1 = 1; 18 | //pwm动效动画 19 | uint8_t zjm_dh_l[14]; 20 | //开机过度动画y增量 21 | int8_t zjm_dh_y = 32; 22 | void zjm() 23 | { 24 | //****** 画当前温度及烙铁错误提示 25 | if (t12_error == 0 && t12_adc_error == 0) //正常画面 26 | { 27 | //显示当前烙铁温度 28 | /*u8g2.setFont(u8g2_font_bubble_tn); 29 | if (t12_temp >= 99)u8g2.setCursor(0, zjm_dh_y + 18); 30 | else u8g2.setCursor(10, zjm_dh_y + 18); 31 | if (t12_switch == 1 && (thisError_average <= 4 && thisError_average >= -4)) u8g2.print(t12_temp_average); 32 | else u8g2.print(t12_temp);*/ 33 | 34 | u8g2.setFont(u8g2_font_bubble_tn); 35 | if (t12_temp >= 99)u8g2.setCursor(0, zjm_dh_y + 18); 36 | else u8g2.setCursor(10, zjm_dh_y + 18); 37 | 38 | if (t12_switch == 1 && (thisError_average <= 4 && thisError_average >= -4)) { 39 | if (t12_temp_average - t12_temp_display > 0) t12_temp_display += 1; 40 | else if (t12_temp_average - t12_temp_display < 0) t12_temp_display -= 1; 41 | u8g2.print(t12_temp_display); 42 | } 43 | 44 | else { 45 | if (t12_temp - t12_temp_display > 0) t12_temp_display += 1; 46 | else if (t12_temp - t12_temp_display < 0) t12_temp_display -= 1; 47 | u8g2.print(t12_temp_display); 48 | } 49 | } 50 | else if (t12_adc_error == 1) zjm_error2(); //T12ADC超出测量范围画面 51 | else if (t12_error == 1) zjm_error3(); //手柄未接显示画面 52 | //****** 画设置温度进度条 53 | //u8g2.setFont(u8g2_font_saikyosansbold8_8n); 54 | u8g2.setFont(u8g2_font_lucasfont_alternate_tr); 55 | zjm_x1 = map(set_temp, set_temp_min, set_temp_max, 3, 57); 56 | u8g2.drawDisc(zjm_x1, zjm_dh_y + 28, 2);//画实心圆 57 | u8g2.drawBox(0, zjm_dh_y + 30, 61, 2); //画实心框 58 | if (set_temp <= 310)u8g2.setCursor(zjm_x1 + 5, zjm_dh_y + 29); //画设置温度 59 | else u8g2.setCursor(zjm_x1 - 21, zjm_dh_y + 29); //画设置温度 60 | u8g2.print(set_temp); 61 | 62 | //****** 画加热提示及切换动画 63 | u8g2.setFont(chinese_t12); 64 | if (zjm_dh_y != 0) //开机过渡动画变量变化 65 | { 66 | zjm_dh_y --; 67 | u8g2.setCursor(50, zjm_dh_y - 11); 68 | u8g2.print(version); 69 | } 70 | if (/*millis() - zjm_dh_time1 > 30 &&*/ zjm_dh_run == 1) 71 | { 72 | if (zjm_dh_x1 < 7) 73 | { 74 | zjm_dh_x1++; 75 | zjm_dh_y1++; 76 | if (zjm_dh_x1 == 7) 77 | { 78 | zjm_dh_r1 = 0; 79 | if (t12_switch == 1 && zjm_sleep_ts == 0) EEPROM.put(set_temp_eeprom, set_temp); //停止时保存当前的设置温度 80 | t12_switch = !t12_switch; //动画播放完,切换T12工作状态 81 | MsTimer2::stop(); //停止一次 然后在MsTimer2_rw1()里自动切换定时的中断任务 82 | } 83 | zjm_dh_time1 = millis(); 84 | } 85 | else if (zjm_dh_x1 >= 7 && millis() - zjm_dh_time1 > 300) 86 | { 87 | zjm_dh_x1 = 0; 88 | zjm_dh_y1 = 0; 89 | zjm_dh_r1 = 1; 90 | zjm_dh_run = 0; //关闭动画 91 | } 92 | } 93 | u8g2.drawRFrame(zjm_x3 - 3, zjm_dh_y + zjm_y4 - 14, 18, 18, 3); //空心圆角方形 94 | u8g2.setCursor(zjm_x3, zjm_dh_y + zjm_y4); 95 | if (t12_switch == 1 && zjm_sleep_ts == 0) u8g2.print("热"); 96 | else if (t12_switch == 1 && zjm_sleep_ts == 1) u8g2.print("休"); 97 | else u8g2.print("停"); 98 | if (zjm_dh_x1 == 7)u8g2.setDrawColor(2); 99 | u8g2.drawRBox(80 - zjm_dh_x1, zjm_dh_y + 8 - zjm_dh_y1, 2 + zjm_dh_x1 * 2, 2 + zjm_dh_y1 * 2, zjm_dh_r1); //实心圆角方形 100 | if (zjm_dh_x1 == 7)u8g2.setDrawColor(1); 101 | 102 | //****** 画PWM输出比例动画 103 | if (t12_switch == 1) 104 | { 105 | uint16_t zjm_pwmdh_time = map(pid_out, pwm_min, pwm_max, 450, 150); //输出比例决定刷新时间 106 | uint8_t zjm_pwmdh_l = map(pid_out, pwm_min, pwm_max, 3, 12); //输出比例决定L的最大值 107 | if (millis() - zjm_dh_time2 > zjm_pwmdh_time) 108 | { 109 | for (uint8_t i = 0; i < 14; i++) 110 | { 111 | zjm_dh_l[i] = random(1, zjm_pwmdh_l); 112 | } 113 | zjm_dh_time2 = millis(); 114 | } 115 | 116 | for (uint8_t i = 0; i < 14; i++) 117 | { 118 | u8g2.drawLine(74 + i, zjm_dh_y + 32, 74 + i, zjm_dh_y + 32 - zjm_dh_l[i]); //绘制垂直线,X,Y,长度 119 | //delay(100); 120 | } 121 | } 122 | else u8g2.drawHLine(74, zjm_dh_y + 31, 14); 123 | 124 | //****** 画室温-电压-电流-工作状态 125 | if (vin_error == 1) zjm_error1(); //电压电流有一个报警就显示 报警提示画面 126 | else zjm_vin_ec_temp_state(); //显示正常画面 127 | 128 | //****** 调试信息显示 129 | //u8g2.setCursor(75, 32); 130 | //u8g2.print(zjm_ca_count); 131 | } 132 | 133 | 134 | void zjm_vin_ec_temp_state() //画室温-电压-电流-工作状态 135 | { 136 | //画室温-电压 137 | u8g2.setFont(u8g2_font_lucasfont_alternate_tr); 138 | u8g2.setCursor(zjm_x2, zjm_dh_y + zjm_y1); 139 | u8g2.print(tc1047_temp, 1); 140 | u8g2.drawCircle(zjm_x2 + 21, zjm_dh_y + zjm_y1 - 6, 1, U8G2_DRAW_ALL); //画空心圆 141 | u8g2.setCursor(zjm_x2 + 23, zjm_dh_y + zjm_y1); 142 | u8g2.print("C"); 143 | 144 | u8g2.setCursor(zjm_x2, zjm_dh_y + zjm_y2); 145 | u8g2.print(vin, 1); 146 | u8g2.setCursor(zjm_x2 + 22, zjm_dh_y + zjm_y2); 147 | u8g2.print("V"); 148 | 149 | u8g2.setCursor(zjm_x2, zjm_dh_y + zjm_y3); 150 | u8g2.print(pid_out_bfb); 151 | u8g2.setCursor(zjm_x2 + 20, zjm_dh_y + zjm_y3); 152 | u8g2.print("%"); 153 | 154 | //u8g2.setCursor(70, 27); 155 | //u8g2.print(t12_ad,0); 156 | 157 | //u8g2.setCursor(45, 27); 158 | //u8g2.print(sleep_count); 159 | //u8g2.setCursor(65, 27); 160 | //u8g2.print(xp_time_count); 161 | 162 | /*u8g2.setCursor(55, 13); 163 | u8g2.print(sleep_MsTimer2_state);*/ 164 | 165 | //u8g2.setCursor(50, 27); 166 | //u8g2.print(pid_out); 167 | 168 | //u8g2.setCursor(0, 29); 169 | //u8g2.print(t12_temp_read_time); 170 | 171 | //u8g2.setCursor(0, 29); 172 | //u8g2.print(analogRead(tc1047_pin)); 173 | } 174 | void zjm_error1() //主界面 电压电流报警 提示 175 | { 176 | u8g2.setFont(chinese_t12); 177 | if (vin_error == 1) 178 | { 179 | u8g2.setCursor(95, zjm_dh_y + 13); 180 | u8g2.print("电 压"); 181 | u8g2.setCursor(95, zjm_dh_y + 29); 182 | u8g2.print("过 低"); 183 | } 184 | u8g2.setDrawColor(2); 185 | u8g2.drawBox(95 - 2, zjm_dh_y + 0, 40, 32); //实心方形 186 | u8g2.setDrawColor(1); 187 | } 188 | void zjm_error2() //主界面 温度超出测量范围 错误提示 189 | { 190 | u8g2.setFont(u8g2_font_lucasfont_alternate_tr); 191 | u8g2.setCursor(12, zjm_dh_y + 8); 192 | u8g2.print("T12 ADC"); 193 | u8g2.setCursor(23, zjm_dh_y + 17); 194 | u8g2.print("HIGH"); 195 | u8g2.setDrawColor(2); 196 | u8g2.drawBox(0, zjm_dh_y + 0, 61, 18); //实心方形 197 | u8g2.setDrawColor(1); 198 | } 199 | void zjm_error3() //主界面 手柄未接显示界面 错误提示 200 | { 201 | u8g2.setFont(chinese_t12); 202 | u8g2.setCursor(5, zjm_dh_y + 14); 203 | u8g2.print("手柄未接"); 204 | 205 | u8g2.setDrawColor(2); 206 | u8g2.drawBox(0, zjm_dh_y + 0, 61, 18); //实心方形 207 | u8g2.setDrawColor(1); 208 | } 209 | -------------------------------------------------------------------------------- /v1.20.1/DisplaySet.ino: -------------------------------------------------------------------------------- 1 | //********** 画设置主界面及其他界面 ********** 2 | #define szjm_y1 21 3 | int16_t szjm_dh_x[6] = {0, 50, 100, 150, 200, 250}; 4 | int16_t szjm_dh_x_count = 0; //设置界面动画x增量记录 5 | 6 | #define szjm_dh_bc 5 //变化步长,只能为5的倍数 7 | void szjm() 8 | { 9 | //画十字坐标 10 | //u8g2.drawHLine(0, 15, 128); 11 | //u8g2.drawVLine(63, 0, 32); 12 | //********** 线性滚动动画 13 | if (szjm_kxxk_L == 1) //顺时针滚动 14 | { 15 | szjm_dh_x_count += szjm_dh_bc; //记录变化次数 16 | for (uint8_t i = 0; i < 6; i++) //开始变化 17 | { 18 | szjm_dh_x[i] += szjm_dh_bc; //步长5 19 | } 20 | for (uint8_t i = 0; i < 6; i++) //数值限制 21 | { 22 | if (szjm_dh_x[i] > 250)szjm_dh_x[i] = -45; 23 | } 24 | if (szjm_dh_x_count >= 50) //变化完毕 25 | { 26 | szjm_kxxk_L = 0; //释放状态 27 | szjm_dh_x_count = 0; //变化次数清零 28 | if (szjm_kxxk_count >= 6) szjm_kxxk_count = 0; //数值限制 29 | } 30 | } 31 | else if (szjm_kxxk_R == 1) //逆时针滚动 32 | { 33 | szjm_dh_x_count -= szjm_dh_bc; //记录变化次数 34 | for (uint8_t i = 0; i < 6; i++) //开始变化 35 | { 36 | szjm_dh_x[i] -= szjm_dh_bc; //步长5 37 | } 38 | for (uint8_t i = 0; i < 6; i++) //数值限制 39 | { 40 | if (szjm_dh_x[i] < -150)szjm_dh_x[i] = 145; 41 | } 42 | if (szjm_dh_x_count <= -50) //变化完毕 43 | { 44 | szjm_kxxk_R = 0; //释放状态 45 | szjm_dh_x_count = 0; //变化次数清零 46 | if (szjm_kxxk_count <= -6) szjm_kxxk_count = 0; //数值限制 47 | } 48 | } 49 | //************************************************** 50 | //********** 画文字和框框 51 | //调试信息显示 52 | //u8g2.setFont(u8g2_font_lucasfont_alternate_tr); 53 | //u8g2.setCursor(0, 31); 54 | //u8g2.print(szjm_dh_x_count); 55 | //u8g2.setCursor(100, 31); 56 | //u8g2.print(szjm_kxxk_count); 57 | //u8g2.setCursor(50, 31); 58 | //u8g2.print(szjm_dh_x[0]); 59 | 60 | u8g2.setFont(chinese_t12); 61 | if (szjm_dh_x[0] >= -50 && szjm_dh_x[0] <= 150) 62 | { 63 | u8g2.setCursor(szjm_dh_x[0], szjm_y1); 64 | u8g2.print("PID"); 65 | } 66 | if (szjm_dh_x[1] >= -50 && szjm_dh_x[1] <= 150) 67 | { 68 | u8g2.setCursor(szjm_dh_x[1], szjm_y1); 69 | u8g2.print("休眠"); 70 | } 71 | if (szjm_dh_x[2] >= -50 && szjm_dh_x[2] <= 150) 72 | { 73 | u8g2.setCursor(szjm_dh_x[2], szjm_y1); 74 | u8g2.print("屏幕"); 75 | } 76 | if (szjm_dh_x[3] >= -50 && szjm_dh_x[3] <= 150) 77 | { 78 | u8g2.setCursor(szjm_dh_x[3], szjm_y1); 79 | u8g2.print("电源"); 80 | } 81 | if (szjm_dh_x[4] >= -50 && szjm_dh_x[4] <= 150) 82 | { 83 | u8g2.setCursor(szjm_dh_x[4], szjm_y1); 84 | u8g2.print("校准"); 85 | } 86 | if (szjm_dh_x[5] >= -50 && szjm_dh_x[5] <= 150) 87 | { 88 | u8g2.setCursor(szjm_dh_x[5], szjm_y1); 89 | u8g2.print("烙铁"); 90 | } 91 | u8g2.setDrawColor(2); 92 | u8g2.drawRBox(43, 6, 40, 20, 1); //空心圆角方形 93 | u8g2.setDrawColor(1); 94 | } 95 | 96 | //********** PID设置界面 ********** 97 | #define szjm_pid_x1 2 98 | #define szjm_pid_x2 14 99 | 100 | #define szjm_pid_x3 82 101 | #define szjm_pid_x4 94 102 | 103 | #define szjm_pid_y1 14 104 | #define szjm_pid_y2 29 105 | void szjm_pid() 106 | { 107 | u8g2.setCursor(szjm_pid_x1, szjm_pid_y1); 108 | u8g2.print("P"); 109 | u8g2.setCursor(szjm_pid_x2, szjm_pid_y1); 110 | u8g2.print(p, 1); 111 | 112 | u8g2.setCursor(szjm_pid_x3, szjm_pid_y1); 113 | u8g2.print("I"); 114 | u8g2.setCursor(szjm_pid_x4, szjm_pid_y1); 115 | u8g2.print(i, 1); 116 | 117 | u8g2.setCursor(szjm_pid_x1, szjm_pid_y2); 118 | u8g2.print("D"); 119 | u8g2.setCursor(szjm_pid_x2, szjm_pid_y2); 120 | u8g2.print(d, 1); 121 | 122 | //画选框 123 | switch (szjm_pid_kxxk_count) //空心选框的位置 124 | { 125 | case 1: //p 126 | if (szjm_pid_sxxk_count == szjm_pid_kxxk_count) 127 | { 128 | u8g2.setDrawColor(2); 129 | u8g2.drawBox(szjm_pid_x1 - 2, szjm_pid_y1 - 13, 48, 16); //实心方形 130 | //画水平线,标识进入小数点模式 131 | if (dec_state == 1) u8g2.drawHLine(szjm_pid_x2 + 4 + (get_num_digit(p) * 6), szjm_pid_y1 + 1, 10); 132 | u8g2.setDrawColor(1); 133 | } 134 | else u8g2.drawFrame(szjm_pid_x1 - 2, szjm_pid_y1 - 13, 48, 16); //空心方形 135 | break; 136 | case 2: //i 137 | if (szjm_pid_sxxk_count == szjm_pid_kxxk_count) 138 | { 139 | u8g2.setDrawColor(2); 140 | u8g2.drawBox(szjm_pid_x3 - 2, szjm_pid_y1 - 13, 48, 16); //实心方形 141 | //画水平线,标识进入小数点模式 142 | if (dec_state == 1) u8g2.drawHLine(szjm_pid_x4 + 4 + (get_num_digit(i) * 6), szjm_pid_y1 + 1, 10); 143 | u8g2.setDrawColor(1); 144 | } 145 | else u8g2.drawFrame(szjm_pid_x3 - 2, szjm_pid_y1 - 13, 48, 16); //空心方形 146 | break; 147 | case 3: //d 148 | if (szjm_pid_sxxk_count == szjm_pid_kxxk_count) 149 | { 150 | u8g2.setDrawColor(2); 151 | u8g2.drawBox(szjm_pid_x1 - 2, szjm_pid_y2 - 13, 48, 16); //实心方形 152 | //画水平线,标识进入小数点模式 153 | if (dec_state == 1) u8g2.drawHLine(szjm_pid_x2 + 4 + (get_num_digit(d) * 6), szjm_pid_y2 + 1, 10); 154 | u8g2.setDrawColor(1); 155 | } 156 | else u8g2.drawFrame(szjm_pid_x1 - 2, szjm_pid_y2 - 13, 48, 16); //空心方形 157 | break; 158 | } 159 | } 160 | 161 | //********** 休眠设置界面 ********** 162 | #define szjm_sleep_x1 2 163 | #define szjm_sleep_x2 105 164 | #define szjm_sleep_y1 14 165 | #define szjm_sleep_y2 29 166 | void szjm_sleep() 167 | { 168 | u8g2.setCursor(szjm_sleep_x1, szjm_sleep_y1); 169 | u8g2.print("休眠时间 S"); 170 | u8g2.setCursor(szjm_sleep_x2, szjm_sleep_y1); 171 | if (sleep_time != 999)u8g2.print(sleep_time); 172 | else u8g2.print("关"); 173 | 174 | u8g2.setCursor(szjm_sleep_x1, szjm_sleep_y2); 175 | u8g2.print("休眠温度 ℃"); 176 | u8g2.setCursor(szjm_sleep_x2, szjm_sleep_y2); 177 | u8g2.print(sleep_temp); 178 | 179 | //画选框 180 | switch (szjm_sleep_kxxk_count) //空心选框的位置 181 | { 182 | case 1: //设置温度 183 | if (szjm_sleep_sxxk_count == szjm_sleep_kxxk_count) 184 | { 185 | u8g2.setDrawColor(2); 186 | u8g2.drawBox(szjm_sleep_x1 - 2, szjm_sleep_y1 - 13, 128, 16); //实心方形 187 | u8g2.setDrawColor(1); 188 | } 189 | else u8g2.drawFrame(szjm_sleep_x1 - 2, szjm_sleep_y1 - 13, 128, 16); //空心方形 190 | break; 191 | case 2: //设置温度 192 | if (szjm_sleep_sxxk_count == szjm_sleep_kxxk_count) 193 | { 194 | u8g2.setDrawColor(2); 195 | u8g2.drawBox(szjm_sleep_x1 - 2, szjm_sleep_y2 - 13, 128, 16); //实心方形 196 | u8g2.setDrawColor(1); 197 | } 198 | else u8g2.drawFrame(szjm_sleep_x1 - 2, szjm_sleep_y2 - 13, 128, 16); //空心方形 199 | break; 200 | } 201 | } 202 | 203 | //********** OLED亮度设置界面 ********** 204 | #define szjm_oled_x1 2 205 | #define szjm_oled_x2 106 206 | #define szjm_oled_x3 86 207 | #define szjm_oled_y1 14 208 | #define szjm_oled_y2 29 209 | void szjm_oled() 210 | { 211 | if (szjm_oled_kxxk_count == 3) //第2页 212 | { 213 | u8g2.setCursor(szjm_oled_x1, szjm_oled_y1); 214 | u8g2.print("旋转方向"); 215 | u8g2.setCursor(szjm_oled_x3, szjm_oled_y1); 216 | if (xzbmq_fx == 0) u8g2.print("顺+逆-"); 217 | else u8g2.print("顺-逆+"); 218 | } 219 | else //第1页 220 | { 221 | u8g2.setCursor(szjm_oled_x1, szjm_oled_y1); 222 | u8g2.print("屏幕亮度"); 223 | u8g2.setCursor(szjm_oled_x2, szjm_oled_y1); 224 | u8g2.print(oled_ld); 225 | 226 | u8g2.setCursor(szjm_oled_x1, szjm_oled_y2); 227 | u8g2.print("屏幕方向"); 228 | u8g2.setCursor(szjm_oled_x2, szjm_oled_y2); 229 | if (oled_fx == 0) u8g2.print("0"); 230 | else u8g2.print("180"); 231 | } 232 | //画选框 233 | switch (szjm_oled_kxxk_count) //空心选框的位置 234 | { 235 | case 1: //OLED亮度 236 | if (szjm_oled_sxxk_count == szjm_oled_kxxk_count) 237 | { 238 | u8g2.setDrawColor(2); 239 | u8g2.drawBox(szjm_oled_x1 - 2, szjm_oled_y1 - 13, 128, 16); //实心方形 240 | u8g2.setDrawColor(1); 241 | } 242 | else u8g2.drawFrame(szjm_oled_x1 - 2, szjm_oled_y1 - 13, 128, 16); //空心方形 243 | break; 244 | case 2: //OLED方向 245 | if (szjm_oled_sxxk_count == szjm_oled_kxxk_count) 246 | { 247 | u8g2.setDrawColor(2); 248 | u8g2.drawBox(szjm_oled_x1 - 2, szjm_oled_y2 - 13, 128, 16); //实心方形 249 | u8g2.setDrawColor(1); 250 | } 251 | else u8g2.drawFrame(szjm_oled_x1 - 2, szjm_oled_y2 - 13, 128, 16); //空心方形 252 | break; 253 | case 3: //旋转方向 254 | u8g2.drawFrame(szjm_oled_x1 - 2, szjm_oled_y1 - 13, 128, 16); //空心方形 255 | break; 256 | } 257 | } 258 | 259 | //********** 电源设置界面 ********** 260 | #define szjm_power_x1 2 261 | #define szjm_power_x2 100 262 | #define szjm_power_y1 14 263 | #define szjm_power_y2 29 264 | void szjm_power() 265 | { 266 | if (szjm_power_kxxk_count == 3) //第2页 267 | { 268 | u8g2.setCursor(szjm_power_x1, szjm_power_y1); 269 | u8g2.print("低压报警 V"); 270 | u8g2.setCursor(szjm_power_x2, szjm_power_y1); 271 | if (vin_low >= 3.3) u8g2.print(vin_low, 1); 272 | else if (vin_low < 3.3) u8g2.print("关"); 273 | } 274 | else //第1页 275 | { 276 | u8g2.setCursor(szjm_power_x1, szjm_power_y1); 277 | u8g2.print("基准电压 V"); 278 | u8g2.setCursor(szjm_power_x2, szjm_power_y1); 279 | u8g2.print(vcc_refer); 280 | u8g2.setCursor(szjm_power_x1, szjm_power_y2); 281 | u8g2.print("电源电压 V"); 282 | if (vin_refer >= 0) 283 | { 284 | u8g2.setCursor(szjm_power_x2 - 8, szjm_power_y2); 285 | u8g2.print("+"); 286 | u8g2.setCursor(szjm_power_x2, szjm_power_y2); 287 | u8g2.print(vin_refer); 288 | } 289 | else 290 | { 291 | u8g2.setCursor(szjm_power_x2 - 6, szjm_power_y2); 292 | u8g2.print(vin_refer); 293 | } 294 | } 295 | //画选框 296 | switch (szjm_power_kxxk_count) //空心选框的位置 297 | { 298 | case 1: //基准电压(V) 299 | if (szjm_power_sxxk_count == szjm_power_kxxk_count) 300 | { 301 | u8g2.setDrawColor(2); 302 | u8g2.drawBox(szjm_power_x1 - 2, szjm_power_y1 - 13, 128, 16); //实心方形 303 | u8g2.setDrawColor(1); 304 | } 305 | else u8g2.drawFrame(szjm_power_x1 - 2, szjm_power_y1 - 13, 128, 16); //空心方形 306 | break; 307 | case 2: //基准电压(V) 308 | if (szjm_power_sxxk_count == szjm_power_kxxk_count) 309 | { 310 | u8g2.setDrawColor(2); 311 | u8g2.drawBox(szjm_power_x1 - 2, szjm_power_y2 - 13, 128, 16); //实心方形 312 | u8g2.setDrawColor(1); 313 | } 314 | else u8g2.drawFrame(szjm_power_x1 - 2, szjm_power_y2 - 13, 128, 16); //空心方形 315 | break; 316 | case 3: //电源电压(V) 317 | if (szjm_power_sxxk_count == szjm_power_kxxk_count) 318 | { 319 | u8g2.setDrawColor(2); 320 | u8g2.drawBox(szjm_power_x1 - 2, szjm_power_y1 - 13, 128, 16); //实心方形 321 | u8g2.setDrawColor(1); 322 | } 323 | else u8g2.drawFrame(szjm_power_x1 - 2, szjm_power_y1 - 13, 128, 16); //空心方形 324 | break; 325 | } 326 | } 327 | //********** 烙铁设置界面 ********** 328 | #define szjm_laotie_x1 2 329 | #define szjm_laotie_x4 105 330 | 331 | #define szjm_laotie_y1 14 332 | #define szjm_laotie_y2 29 333 | 334 | void szjm_laotie() 335 | { 336 | 337 | if (szjm_laotie_kxxk_count == 3) //第2页 338 | { 339 | u8g2.setCursor(szjm_laotie_x1, szjm_laotie_y1); 340 | u8g2.print("重置"); 341 | u8g2.setCursor(szjm_laotie_x4, szjm_laotie_y1); 342 | if (hfccsz_state) u8g2.print("是"); 343 | else u8g2.print("否"); 344 | } 345 | else //第1页 346 | { 347 | u8g2.setCursor(szjm_laotie_x1, szjm_laotie_y1); 348 | u8g2.print("冷端补偿 ℃"); 349 | if (tc1047_refer <= -10) u8g2.setCursor(szjm_laotie_x4, szjm_laotie_y1); 350 | else u8g2.setCursor(szjm_laotie_x4, szjm_laotie_y1); 351 | u8g2.print(tc1047_refer); 352 | 353 | u8g2.setCursor(szjm_laotie_x1, szjm_laotie_y2); 354 | u8g2.print("开机加热"); 355 | u8g2.setCursor(szjm_laotie_x4, szjm_laotie_y2); 356 | if (t12_kj_jr) u8g2.print("是"); 357 | else u8g2.print("否"); 358 | } 359 | 360 | //画选框 361 | switch (szjm_laotie_kxxk_count) //空心选框的位置 362 | { 363 | case 1: //冷端补偿 364 | if (szjm_laotie_sxxk_count == szjm_laotie_kxxk_count) 365 | { 366 | u8g2.setDrawColor(2); 367 | u8g2.drawBox(szjm_laotie_x1 - 2, szjm_laotie_y1 - 13, 128, 16); //实心方形 368 | u8g2.setDrawColor(1); 369 | } 370 | else u8g2.drawFrame(szjm_laotie_x1 - 2, szjm_laotie_y1 - 13, 128, 16); //空心方形 371 | break; 372 | case 2: //开机加热 373 | u8g2.drawFrame(szjm_laotie_x1 - 2, szjm_laotie_y2 - 13, 128, 16); //空心方形 374 | break; 375 | case 3: //恢复出厂设置 376 | if (szjm_laotie_sxxk_count == szjm_laotie_kxxk_count) 377 | { 378 | u8g2.setDrawColor(2); 379 | u8g2.drawBox(szjm_laotie_x1 - 2, szjm_laotie_y1 - 13, 128, 16); //实心方形 380 | u8g2.setDrawColor(1); 381 | } 382 | else u8g2.drawFrame(szjm_laotie_x1 - 2, szjm_laotie_y1 - 13, 128, 16); //空心方形 383 | break; 384 | } 385 | } 386 | //********** 校准设置界面 ********** 387 | #define szjm_jiaozhun_x1 0 388 | 389 | #define szjm_jiaozhun_x2 30 390 | #define szjm_jiaozhun_x3 54 391 | #define szjm_jiaozhun_x4 80 392 | #define szjm_jiaozhun_x5 106 393 | 394 | #define szjm_jiaozhun_x6 102 395 | 396 | #define szjm_jiaozhun_y1 7 397 | #define szjm_jiaozhun_y2 18 398 | #define szjm_jiaozhun_y3 31 399 | void szjm_jiaozhun() 400 | { 401 | u8g2.setFont(u8g2_font_lucasfont_alternate_tr); 402 | if (szjm_jiaozhun_kxxk_count == 6) 403 | { 404 | u8g2.setCursor(0, 7); 405 | u8g2.print("P0:"); 406 | u8g2.setCursor(25, 7); 407 | u8g2.print(sz_p[0], 10); 408 | 409 | u8g2.setCursor(0, 15); 410 | u8g2.print("P1:"); 411 | u8g2.setCursor(25, 15); 412 | u8g2.print(sz_p[1], 10); 413 | 414 | u8g2.setCursor(0, 24); 415 | u8g2.print("P2:"); 416 | u8g2.setCursor(25, 24); 417 | u8g2.print(sz_p[2], 10); 418 | 419 | u8g2.setCursor(0, 32); 420 | u8g2.print("P3:"); 421 | u8g2.setCursor(25, 32); 422 | u8g2.print(sz_p[3], 10); 423 | } 424 | else 425 | { 426 | u8g2.setCursor(szjm_jiaozhun_x1, szjm_jiaozhun_y1); 427 | u8g2.print("ADC 10 350 650 950"); 428 | u8g2.setCursor(szjm_jiaozhun_x1, szjm_jiaozhun_y2); 429 | u8g2.print("Temp"); 430 | u8g2.setCursor(szjm_jiaozhun_x2, szjm_jiaozhun_y2); 431 | u8g2.print(sz_temp[0]); 432 | u8g2.setCursor(szjm_jiaozhun_x3, szjm_jiaozhun_y2); 433 | u8g2.print(sz_temp[1]); 434 | u8g2.setCursor(szjm_jiaozhun_x4, szjm_jiaozhun_y2); 435 | u8g2.print(sz_temp[2]); 436 | u8g2.setCursor(szjm_jiaozhun_x5, szjm_jiaozhun_y2); 437 | u8g2.print(sz_temp[3]); 438 | 439 | u8g2.drawHLine(0, 22, 128); 440 | 441 | u8g2.setCursor(szjm_jiaozhun_x1, szjm_jiaozhun_y3); 442 | u8g2.print("Now ADC:"); 443 | u8g2.setCursor(48, szjm_jiaozhun_y3); 444 | u8g2.print(t12_ad, 0); 445 | 446 | u8g2.setCursor(szjm_jiaozhun_x6, szjm_jiaozhun_y3); 447 | u8g2.print("Save"); 448 | } 449 | //画选框 450 | switch (szjm_jiaozhun_kxxk_count) //空心选框的位置 451 | { 452 | case 1: //深圳头1段温度 453 | if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 454 | { 455 | u8g2.setDrawColor(2); 456 | u8g2.drawBox(szjm_jiaozhun_x2 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //实心方形 457 | u8g2.setDrawColor(1); 458 | } 459 | else u8g2.drawFrame(szjm_jiaozhun_x2 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //空心方形 460 | break; 461 | case 2: //深圳头2段温度 462 | if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 463 | { 464 | u8g2.setDrawColor(2); 465 | u8g2.drawBox(szjm_jiaozhun_x3 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //实心方形 466 | u8g2.setDrawColor(1); 467 | } 468 | else u8g2.drawFrame(szjm_jiaozhun_x3 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //空心方形 469 | break; 470 | case 3: //深圳头3段温度 471 | if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 472 | { 473 | u8g2.setDrawColor(2); 474 | u8g2.drawBox(szjm_jiaozhun_x4 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //实心方形 475 | u8g2.setDrawColor(1); 476 | } 477 | else u8g2.drawFrame(szjm_jiaozhun_x4 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //空心方形 478 | break; 479 | case 4: //深圳头4段温度 480 | if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 481 | { 482 | u8g2.setDrawColor(2); 483 | u8g2.drawBox(szjm_jiaozhun_x5 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //实心方形 484 | u8g2.setDrawColor(1); 485 | } 486 | else u8g2.drawFrame(szjm_jiaozhun_x5 - 2, szjm_jiaozhun_y2 - 9, 21, 11); //空心方形 487 | break; 488 | case 5: //保存 489 | u8g2.setDrawColor(2); 490 | u8g2.drawBox(szjm_jiaozhun_x6 - 2, szjm_jiaozhun_y3 - 8, 28, 9); //实心方形 491 | u8g2.setDrawColor(1); 492 | break; 493 | } 494 | } 495 | -------------------------------------------------------------------------------- /v1.20.1/EEPROM.ino: -------------------------------------------------------------------------------- 1 | //******************* 自动刷写eeprom ******************* 2 | void eerpom_auto() 3 | { 4 | EEPROM.get(auto_get_eeprom, auto_get); //获取自动刷写的状态 5 | if (auto_get > 1) auto_get = 0; //防止eeprom第0位不为0 6 | if (auto_get == 0) //状态为0开启刷写 7 | { 8 | EEPROM.put(p_eeprom, p); //pid-p 9 | EEPROM.put(i_eeprom, i); //pid-i 10 | EEPROM.put(d_eeprom, d); //pid-d 11 | EEPROM.put(sleep_time_eeprom, sleep_time); //休眠时间 12 | EEPROM.put(sleep_temp_eeprom, sleep_temp); //休眠温度 13 | EEPROM.put(oled_ld_eeprom, oled_ld); //OLED亮度 14 | EEPROM.put(vcc_refer_eeprom, vcc_refer); //基准电压 15 | EEPROM.put(vin_refer_eeprom, vin_refer); //电源电压校准值 16 | EEPROM.put(t12_kj_jr_eeprom, t12_kj_jr); //是否开机就加热 17 | EEPROM.put(vin_low_eeprom, vin_low); //输入电压过底报警阈值 18 | EEPROM.put(tc1047_refer_eeprom, tc1047_refer); //T12环境参考温度校准值 19 | EEPROM.put(oled_fx_eeprom, oled_fx); //OLED方向 20 | EEPROM.put(xzbmq_fx_eeprom, xzbmq_fx); //旋转编码器方向 21 | //写入曲线的4段温度 22 | EEPROM.put(sz_temp0_eeprom, sz_temp[0]); 23 | EEPROM.put(sz_temp1_eeprom, sz_temp[1]); 24 | EEPROM.put(sz_temp2_eeprom, sz_temp[2]); 25 | EEPROM.put(sz_temp3_eeprom, sz_temp[3]); 26 | //写入设置温度 27 | EEPROM.put(set_temp_eeprom, set_temp); 28 | //刷写完,记录auto_get的状态,防止下次开机再次刷写 29 | EEPROM.put(auto_get_eeprom, 1); 30 | auto_get = 1; 31 | } 32 | if (auto_get == 1)//状态为1只读取 33 | { 34 | EEPROM.get(p_eeprom, p); //pid-p 35 | EEPROM.get(i_eeprom, i); //pid-i 36 | EEPROM.get(d_eeprom, d); //pid-d 37 | EEPROM.get(sleep_time_eeprom, sleep_time); //休眠时间 38 | EEPROM.get(sleep_temp_eeprom, sleep_temp); //休眠温度 39 | EEPROM.get(oled_ld_eeprom, oled_ld); //OLED亮度 40 | EEPROM.get(vcc_refer_eeprom, vcc_refer); //基准电压 41 | EEPROM.get(vin_refer_eeprom, vin_refer); //电源电压校准值 42 | EEPROM.get(t12_kj_jr_eeprom, t12_kj_jr); //是否开机就加热 43 | EEPROM.get(vin_low_eeprom, vin_low); //输入电压过底报警阈值 44 | EEPROM.get(tc1047_refer_eeprom, tc1047_refer); //T12环境参考温度校准值 45 | EEPROM.get(oled_fx_eeprom, oled_fx); //OLED方向 46 | EEPROM.get(xzbmq_fx_eeprom, xzbmq_fx); //旋转编码器方向 47 | //获取曲线的4段温度 48 | EEPROM.get(sz_temp0_eeprom, sz_temp[0]); 49 | EEPROM.get(sz_temp1_eeprom, sz_temp[1]); 50 | EEPROM.get(sz_temp2_eeprom, sz_temp[2]); 51 | EEPROM.get(sz_temp3_eeprom, sz_temp[3]); 52 | //获取设置温度 53 | EEPROM.get(set_temp_eeprom, set_temp); 54 | } 55 | } 56 | //****************************************************** 57 | -------------------------------------------------------------------------------- /v1.20.1/InterruptKey.ino: -------------------------------------------------------------------------------- 1 | //********** 编码器按键决策 ********** 2 | void xuan_zhaun() //旋转中断 选框决策 3 | { 4 | 5 | /*Serial.print("DT "); Serial.print(digitalRead(DT)); 6 | Serial.print(" | "); 7 | Serial.print("CLK "); Serial.print(digitalRead(CLK)); 8 | Serial.print(" | "); 9 | Serial.print("SW "); Serial.print(digitalRead(SW)); 10 | Serial.println(" ");*/ 11 | if ((millis() - xzbmq_time) < 20) return; //旋转响应间隔 20ms 12 | buzzer(100, 70); //时间,次数 13 | if (display_count == ZJM) 14 | { 15 | zjm_xz_key(); 16 | buzzer_temp_average_state = 0; //准备好到达温度提示声 17 | sleep_count = 0; //休眠计数归零 18 | zjm_sleep_ts = 0; //提示主界面退出显示休眠状态 19 | t12_adc_error = 0; //清除温度超出测量范围提示 20 | xp_state = 0; //结束息屏 21 | xp_time_count = 0; //清除息屏计数 22 | xp_time_count_old = 0; //清除息屏计数旧 23 | } 24 | else if (display_count == SZJM) szjm_xz_key(); 25 | else if (display_count == SZJM_PID) pid_xz_key(); 26 | else if (display_count == SZJM_SLEEP) sleep_xz_key(); 27 | else if (display_count == SZJM_OLED) oled_xz_key(); 28 | else if (display_count == SZJM_POWER) power_xz_key(); 29 | else if (display_count == SZJM_LAOTIE) laotie_xz_key(); 30 | else if (display_count == SZJM_JIAOZHUN) jiaozhun_xz_key(); 31 | xzbmq_time = millis(); 32 | } 33 | 34 | void an_xia() //按下 35 | { 36 | if ((millis() - xzbmq_time) < 160) return; 37 | qj_sw_key(); //全局长按进入设置界面 或 退出至主界面 38 | } 39 | //************************ 全局长按进入设置界面 或 退出至主界面 ************************ 40 | void qj_sw_key() //全局长按计数 41 | { 42 | //长按计数增加 43 | if (digitalRead(SW) == 0) 44 | { 45 | qj_ca_count++; //计数加一 46 | buzzer(80, 150); //时间,次数 47 | 48 | if (display_count == ZJM) t12_adc_error = 0; //清除温度超出测量范围提示 49 | xp_state = 0; //结束息屏 50 | xp_time_count = 0; //清除息屏计数 51 | xp_time_count_old = 0; //清除息屏计数旧 52 | 53 | xzbmq_time = millis(); 54 | } 55 | //判断按了几次 该做些什么 56 | if (qj_ca_count >= 5) //进入设置界面 57 | { 58 | if (display_count == ZJM) 59 | { 60 | display_count = SZJM; //在主界面时进入设置界面 61 | buzzer_szjm_state = 1; 62 | } 63 | else if (display_count != SZJM_JIAOZHUN) 64 | { 65 | display_count = ZJM; //在其他界面是退出至主界面 66 | buzzer_zjm_state = 1; 67 | } 68 | qj_ca_count = 0; //计数清零 69 | } 70 | else if ((millis() - xzbmq_time) > 260) //等待一段时间,确定松手了 71 | { 72 | //在主界面的按下决策 73 | if (display_count == ZJM) zjm_sw_key(); 74 | //在设置界面的按下决策 75 | else if (display_count == SZJM) szjm_sw_key(); 76 | //在PID界面的按下决策 77 | else if (display_count == SZJM_PID) pid_sw_key(); 78 | //在休眠界面的按下决策 79 | else if (display_count == SZJM_SLEEP) sleep_sw_key(); 80 | //在OLED亮度界面的按下决策 81 | else if (display_count == SZJM_OLED) oled_sw_key(); 82 | //在电源校准界面的按下决策 83 | else if (display_count == SZJM_POWER) power_sw_key(); 84 | //在烙铁界面的按下决策 85 | else if (display_count == SZJM_LAOTIE) laotie_sw_key(); 86 | //在校准界面的按下决策 87 | else if (display_count == SZJM_JIAOZHUN) jiaozhun_sw_key(); 88 | qj_ca_count = 0;//计数清零 89 | } 90 | } 91 | //************************ 主界面 ************************ 92 | void zjm_sw_key() 93 | { 94 | if (qj_ca_count == 2 && vin_error == 0 && t12_error == 0) // 启动或停止加热 95 | { 96 | zjm_dh_run = 1; //允许播放动画 ,动画播放完在DisplayMain里切换T12工作状态 97 | zjm_sleep_ts = 0; //提示主界面退出显示休眠状态 98 | buzzer_temp_average_state = 0; //准备好到达温度提示声 99 | } 100 | } 101 | void zjm_xz_key() //主界面 旋转 102 | { 103 | if (digitalRead(DT) == xzbmq_fx) set_temp += 10; 104 | else if (digitalRead(CLK) == xzbmq_fx) set_temp -= 10; 105 | auto_get_set_temp();//自动获取设置温度的范围 106 | if (set_temp > set_temp_max) set_temp = set_temp_min; 107 | else if (set_temp < set_temp_min) set_temp = set_temp_max; 108 | } 109 | //************************ 设置界面 ************************ 110 | void szjm_sw_key() //设置界面 按下 111 | { 112 | if (qj_ca_count == 1) //进入二级菜单 113 | { 114 | if (szjm_kxxk_count == 0) display_count = SZJM_SLEEP; //进入休眠设置菜单 115 | else if (szjm_kxxk_count == -5 || szjm_kxxk_count == 1) display_count = SZJM_PID; //进入PID设置菜单 116 | else if (szjm_kxxk_count == -1 || szjm_kxxk_count == 5) display_count = SZJM_OLED; //进入OELD亮度设置菜单 117 | else if (szjm_kxxk_count == -2 || szjm_kxxk_count == 4) display_count = SZJM_POWER; //进入电源设置菜单 118 | else if (szjm_kxxk_count == -4 || szjm_kxxk_count == 2) display_count = SZJM_LAOTIE;//进入烙铁设置菜单 119 | else if (szjm_kxxk_count == -3 || szjm_kxxk_count == 3) 120 | { 121 | //使用比较柔和的pid参数,退出校准界面时记得恢复正常的PID策略 122 | p = p_jz; //比例系数 123 | i = i_jz; //积分系数 124 | d = d_jz; //微分系数 125 | display_count = SZJM_JIAOZHUN;//进入烙铁设置菜单 126 | } 127 | } 128 | } 129 | void szjm_xz_key() //设置界面 旋转 130 | { 131 | if (digitalRead(DT) == xzbmq_fx) 132 | { 133 | if (szjm_kxxk_L == 0 && szjm_kxxk_R == 0) //顺时针 134 | { 135 | szjm_kxxk_L = 1; //允许播放动画 136 | szjm_kxxk_count++; //下一项 137 | } 138 | } 139 | else if (digitalRead(CLK) == xzbmq_fx) 140 | { 141 | if (szjm_kxxk_L == 0 && szjm_kxxk_R == 0) //逆时针 142 | { 143 | szjm_kxxk_R = 1; //允许播放动画 144 | szjm_kxxk_count--; //上一项 145 | } 146 | } 147 | } 148 | //************************ PID设置界面 ************************ 149 | void pid_sw_key() //设置界面 按下 150 | { 151 | if (qj_ca_count == 1) //返回或进入调节框 152 | { 153 | switch (szjm_pid_kxxk_count) 154 | { 155 | case 0: //返回至设置界面 156 | display_count = SZJM; 157 | break; 158 | case 1: //p 存储 159 | if (szjm_pid_sxxk_count == 0) szjm_pid_sxxk_count = szjm_pid_kxxk_count; 160 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 0) dec_state = 1; 161 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 1) 162 | { 163 | EEPROM.put(p_eeprom, p); 164 | dec_state = 0; 165 | szjm_pid_sxxk_count = 0; 166 | } 167 | break; 168 | case 2: //i 存储 169 | if (szjm_pid_sxxk_count == 0) szjm_pid_sxxk_count = szjm_pid_kxxk_count; 170 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 0) dec_state = 1; 171 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 1) 172 | { 173 | EEPROM.put(i_eeprom, i); 174 | dec_state = 0; 175 | szjm_pid_sxxk_count = 0; 176 | } 177 | break; 178 | case 3: //d 存储 179 | if (szjm_pid_sxxk_count == 0) szjm_pid_sxxk_count = szjm_pid_kxxk_count; 180 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 0) dec_state = 1; 181 | else if (szjm_pid_sxxk_count == szjm_pid_kxxk_count && dec_state == 1) 182 | { 183 | EEPROM.put(d_eeprom, d); 184 | dec_state = 0; 185 | szjm_pid_sxxk_count = 0; 186 | } 187 | break; 188 | } 189 | } 190 | } 191 | void pid_xz_key() //设置界面 旋转 192 | { 193 | if (szjm_pid_sxxk_count == 0) //选框移动 194 | { 195 | if (digitalRead(DT) == xzbmq_fx) szjm_pid_kxxk_count++; 196 | else if (digitalRead(CLK) == xzbmq_fx) szjm_pid_kxxk_count--; 197 | } 198 | else if (szjm_pid_sxxk_count == 1) //p加减 199 | { 200 | if (digitalRead(DT) == xzbmq_fx && dec_state == 0) p += 1; 201 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 0) p -= 1; 202 | else if (digitalRead(DT) == xzbmq_fx && dec_state == 1) p += 0.1; 203 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 1) p -= 0.1; 204 | } 205 | else if (szjm_pid_sxxk_count == 2) //i加减 206 | { 207 | if (digitalRead(DT) == xzbmq_fx && dec_state == 0) i += 1; 208 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 0) i -= 1; 209 | else if (digitalRead(DT) == xzbmq_fx && dec_state == 1) i += 0.1; 210 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 1) i -= 0.1; 211 | } 212 | else if (szjm_pid_sxxk_count == 3) //d加减 213 | { 214 | if (digitalRead(DT) == xzbmq_fx && dec_state == 0) d += 1; 215 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 0) d -= 1; 216 | else if (digitalRead(DT) == xzbmq_fx && dec_state == 1) d += 0.1; 217 | else if (digitalRead(CLK) == xzbmq_fx && dec_state == 1) d -= 0.1; 218 | } 219 | if (szjm_pid_kxxk_count > 3) szjm_pid_kxxk_count = 0; 220 | else if (szjm_pid_kxxk_count < 0) szjm_pid_kxxk_count = 3; 221 | } 222 | //************************ 休眠设置界面 ************************ 223 | void sleep_sw_key() //设置界面 按下 224 | { 225 | if (qj_ca_count == 1) //返回或进入调节框 226 | { 227 | switch (szjm_sleep_kxxk_count) 228 | { 229 | case 0: //返回至设置界面 230 | display_count = SZJM; 231 | break; 232 | case 1: //休眠时间 存储 233 | if (szjm_sleep_sxxk_count == 0) szjm_sleep_sxxk_count = szjm_sleep_kxxk_count; 234 | else if (szjm_sleep_sxxk_count == szjm_sleep_kxxk_count) 235 | { 236 | EEPROM.put(sleep_time_eeprom, sleep_time); //休眠时间 237 | szjm_sleep_sxxk_count = 0; 238 | } 239 | break; 240 | case 2: //休眠温度 存储 241 | if (szjm_sleep_sxxk_count == 0) szjm_sleep_sxxk_count = szjm_sleep_kxxk_count; 242 | else if (szjm_sleep_sxxk_count == szjm_sleep_kxxk_count) 243 | { 244 | EEPROM.put(sleep_temp_eeprom, sleep_temp); //休眠温度 245 | szjm_sleep_sxxk_count = 0; 246 | } 247 | break; 248 | } 249 | } 250 | } 251 | void sleep_xz_key() //设置界面 旋转 252 | { 253 | if (szjm_sleep_sxxk_count == 0) //选框移动 254 | { 255 | if (digitalRead(DT) == xzbmq_fx) szjm_sleep_kxxk_count++; 256 | else if (digitalRead(CLK) == xzbmq_fx) szjm_sleep_kxxk_count--; 257 | } 258 | else if (szjm_sleep_sxxk_count == 1) //休眠时间加减 259 | { 260 | if (digitalRead(DT) == xzbmq_fx) sleep_time += 30; 261 | else if (digitalRead(CLK) == xzbmq_fx) sleep_time -= 30; 262 | } 263 | else if (szjm_sleep_sxxk_count == 2) //休眠温度加减 264 | { 265 | if (digitalRead(DT) == xzbmq_fx) sleep_temp += 1; 266 | else if (digitalRead(CLK) == xzbmq_fx) sleep_temp -= 1; 267 | } 268 | if (szjm_sleep_kxxk_count > 2) szjm_sleep_kxxk_count = 0; 269 | else if (szjm_sleep_kxxk_count < 0) szjm_sleep_kxxk_count = 2; 270 | else if (sleep_time > 999) sleep_time = 30; 271 | else if (sleep_time < 30) sleep_time = 999; 272 | } 273 | //************************ OLED亮度设置界面 ************************ 274 | void oled_sw_key() //设置界面 按下 275 | { 276 | if (qj_ca_count == 1) //返回或进入调节框 277 | { 278 | switch (szjm_oled_kxxk_count) 279 | { 280 | case 0: //返回至设置界面 281 | display_count = SZJM; 282 | break; 283 | case 1: //OLED亮度 存储 284 | if (szjm_oled_sxxk_count == 0) szjm_oled_sxxk_count = szjm_oled_kxxk_count; 285 | else if (szjm_oled_sxxk_count == szjm_oled_kxxk_count) 286 | { 287 | EEPROM.put(oled_ld_eeprom, oled_ld); //OLED亮度 288 | szjm_oled_sxxk_count = 0; 289 | } 290 | break; 291 | case 2: //OLED亮度 存储 292 | if (szjm_oled_sxxk_count == 0) szjm_oled_sxxk_count = szjm_oled_kxxk_count; 293 | else if (szjm_oled_sxxk_count == szjm_oled_kxxk_count) 294 | { 295 | EEPROM.put(oled_fx_eeprom, oled_fx); //OLED方向 296 | if (oled_fx == 1)u8g2.setDisplayRotation(U8G2_R2); //旋转180度 297 | else u8g2.setDisplayRotation(U8G2_R0); //0度,默认方向 298 | szjm_oled_sxxk_count = 0; 299 | } 300 | break; 301 | case 3: //旋转编码器方向 存储 302 | if (szjm_oled_sxxk_count == 0) 303 | { 304 | xzbmq_fx = !xzbmq_fx; 305 | EEPROM.put(xzbmq_fx_eeprom, xzbmq_fx); //OLED方向 306 | EEPROM.get(xzbmq_fx_eeprom, xzbmq_fx); //OLED方向 307 | } 308 | break; 309 | } 310 | } 311 | } 312 | 313 | void oled_xz_key() //设置界面 旋转 314 | { 315 | if (szjm_oled_sxxk_count == 0) //选框移动 316 | { 317 | if (digitalRead(DT) == xzbmq_fx) szjm_oled_kxxk_count++; 318 | else if (digitalRead(CLK) == xzbmq_fx) szjm_oled_kxxk_count--; 319 | if (szjm_oled_kxxk_count > 3) szjm_oled_kxxk_count = 0; 320 | else if (szjm_oled_kxxk_count < 0) szjm_oled_kxxk_count = 3; 321 | } 322 | else if (szjm_oled_sxxk_count == 1) //OLED亮度 加减 323 | { 324 | if (digitalRead(DT) == xzbmq_fx) oled_ld += 5; 325 | else if (digitalRead(CLK) == xzbmq_fx) oled_ld -= 5; 326 | if (oled_ld > 1 && oled_ld < 5) oled_ld = 5; 327 | else if (oled_ld == 0)oled_ld = 255; 328 | } 329 | else if (szjm_oled_sxxk_count == 2) //OLED方向 状态切换 330 | { 331 | if (digitalRead(DT) == xzbmq_fx) oled_fx = !oled_fx; 332 | else if (digitalRead(CLK) == xzbmq_fx) oled_fx = !oled_fx; 333 | } 334 | } 335 | //************************ 电源校准界面 ************************ 336 | void power_sw_key() //设置界面 按下 337 | { 338 | if (qj_ca_count == 1) //返回或进入调节框 339 | { 340 | switch (szjm_power_kxxk_count) 341 | { 342 | case 0: //返回至设置界面 343 | display_count = SZJM; 344 | break; 345 | case 1: //基准电压 存储 346 | if (szjm_power_sxxk_count == 0) szjm_power_sxxk_count = szjm_power_kxxk_count; 347 | else if (szjm_power_sxxk_count == szjm_power_kxxk_count) 348 | { 349 | EEPROM.put(vcc_refer_eeprom, vcc_refer); 350 | szjm_power_sxxk_count = 0; 351 | } 352 | break; 353 | case 2: //电源电压校准值 存储 354 | if (szjm_power_sxxk_count == 0) szjm_power_sxxk_count = szjm_power_kxxk_count; 355 | else if (szjm_power_sxxk_count == szjm_power_kxxk_count) 356 | { 357 | EEPROM.put(vin_refer_eeprom, vin_refer); 358 | szjm_power_sxxk_count = 0; 359 | } 360 | break; 361 | case 3: //低压报警阈值 存储 362 | if (szjm_power_sxxk_count == 0) szjm_power_sxxk_count = szjm_power_kxxk_count; 363 | else if (szjm_power_sxxk_count == szjm_power_kxxk_count) 364 | { 365 | EEPROM.put(vin_low_eeprom, vin_low); 366 | szjm_power_sxxk_count = 0; 367 | } 368 | break; 369 | } 370 | } 371 | } 372 | 373 | void power_xz_key() //设置界面 旋转 374 | { 375 | if (szjm_power_sxxk_count == 0) //选框移动 376 | { 377 | if (digitalRead(DT) == xzbmq_fx) szjm_power_kxxk_count++; 378 | else if (digitalRead(CLK) == xzbmq_fx) szjm_power_kxxk_count--; 379 | if (szjm_power_kxxk_count > 3) szjm_power_kxxk_count = 0; 380 | else if (szjm_power_kxxk_count < 0) szjm_power_kxxk_count = 3; 381 | } 382 | else if (szjm_power_sxxk_count == 1) //基准电压 加减 383 | { 384 | if (digitalRead(DT) == xzbmq_fx) vcc_refer += 0.01; 385 | else if (digitalRead(CLK) == xzbmq_fx) vcc_refer -= 0.01; 386 | } 387 | else if (szjm_power_sxxk_count == 2) //电源电压校准值 加减 388 | { 389 | if (digitalRead(DT) == xzbmq_fx) vin_refer += 0.1; 390 | else if (digitalRead(CLK) == xzbmq_fx) vin_refer -= 0.1; 391 | } 392 | else if (szjm_power_sxxk_count == 3) //低压报警阈值 加减 393 | { 394 | if (digitalRead(DT) == xzbmq_fx) vin_low += 0.1; 395 | else if (digitalRead(CLK) == xzbmq_fx) vin_low -= 0.1; 396 | if (vin_low > 30)vin_low = 3.2; 397 | else if (vin_low < 3.2)vin_low = 30; 398 | } 399 | } 400 | 401 | //************************ 烙铁界面 ************************ 402 | void laotie_sw_key() //设置界面 按下 403 | { 404 | if (qj_ca_count == 1) //返回或进入调节框 405 | { 406 | switch (szjm_laotie_kxxk_count) 407 | { 408 | case 0: //返回至设置界面 409 | display_count = SZJM; 410 | break; 411 | case 1: //冷端补偿 存储 412 | if (szjm_laotie_sxxk_count == 0) szjm_laotie_sxxk_count = szjm_laotie_kxxk_count; 413 | else if (szjm_laotie_sxxk_count == szjm_laotie_kxxk_count) 414 | { 415 | EEPROM.put(tc1047_refer_eeprom, tc1047_refer); 416 | szjm_laotie_sxxk_count = 0; 417 | } 418 | break; 419 | case 2: //开机加热 存储 420 | if (szjm_laotie_sxxk_count == 0) 421 | { 422 | t12_kj_jr = !t12_kj_jr; 423 | EEPROM.put(t12_kj_jr_eeprom, t12_kj_jr); 424 | } 425 | break; 426 | case 3: //恢复出厂设置 存储 427 | if (szjm_laotie_sxxk_count == 0) szjm_laotie_sxxk_count = szjm_laotie_kxxk_count; 428 | else if (szjm_laotie_sxxk_count == szjm_laotie_kxxk_count) 429 | { 430 | if (hfccsz_state == 1) display_hfccsz(); 431 | szjm_laotie_sxxk_count = 0; 432 | } 433 | break; 434 | } 435 | } 436 | } 437 | void laotie_xz_key() //设置界面 旋转 438 | { 439 | if (szjm_laotie_sxxk_count == 0) //选框移动 440 | { 441 | if (digitalRead(DT) == xzbmq_fx) szjm_laotie_kxxk_count++; 442 | else if (digitalRead(CLK) == xzbmq_fx) szjm_laotie_kxxk_count--; 443 | if (szjm_laotie_kxxk_count > 3) szjm_laotie_kxxk_count = 0; 444 | else if (szjm_laotie_kxxk_count < 0) szjm_laotie_kxxk_count = 3; 445 | } 446 | else if (szjm_laotie_sxxk_count == 1) //冷端补偿校准值 加减 447 | { 448 | if (digitalRead(DT) == xzbmq_fx) tc1047_refer += 1; 449 | else if (digitalRead(CLK) == xzbmq_fx) tc1047_refer -= 1; 450 | if (tc1047_refer > 99)tc1047_refer = 0; 451 | else if (tc1047_refer < -99) tc1047_refer = 0; 452 | } 453 | else if (szjm_laotie_sxxk_count == 3) //恢复出厂设置 状态切换 454 | { 455 | if (digitalRead(DT) == xzbmq_fx) hfccsz_state = !hfccsz_state; 456 | else if (digitalRead(CLK) == xzbmq_fx) hfccsz_state = !hfccsz_state; 457 | } 458 | } 459 | //************************ 校准界面 ************************ 460 | void jiaozhun_sw_key() //设置界面 按下 461 | { 462 | if (qj_ca_count == 1) //返回或进入调节框 463 | { 464 | switch (szjm_jiaozhun_kxxk_count) 465 | { 466 | case 0: //返回至设置界面,并恢复正常PID参数和获取设置温度范围 467 | display_count = SZJM; 468 | szjm_jiaozhun_kxxk_count = 0; 469 | EEPROM.get(p_eeprom, p); //pid-p 470 | EEPROM.get(i_eeprom, i); //pid-i 471 | EEPROM.get(d_eeprom, d); //pid-d 472 | 473 | break; 474 | case 1: //深圳校准温度1段 存储 475 | if (szjm_jiaozhun_sxxk_count == 0) 476 | { 477 | szjm_jiaozhun_sxxk_count = szjm_jiaozhun_kxxk_count; 478 | t12_switch = 1; //打开加热 479 | } 480 | else if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 481 | { 482 | EEPROM.put(sz_temp0_eeprom, sz_temp[0]); 483 | szjm_jiaozhun_sxxk_count = 0; 484 | t12_switch = 0; //关闭加热 485 | } 486 | break; 487 | case 2: //深圳校准温度2段 存储 488 | if (szjm_jiaozhun_sxxk_count == 0) 489 | { 490 | szjm_jiaozhun_sxxk_count = szjm_jiaozhun_kxxk_count; 491 | t12_switch = 1; //打开加热 492 | } 493 | else if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 494 | { 495 | EEPROM.put(sz_temp1_eeprom, sz_temp[1]); 496 | szjm_jiaozhun_sxxk_count = 0; 497 | t12_switch = 0; //关闭加热 498 | } 499 | break; 500 | case 3: //深圳校准温度3段 存储 501 | if (szjm_jiaozhun_sxxk_count == 0) 502 | { 503 | szjm_jiaozhun_sxxk_count = szjm_jiaozhun_kxxk_count; 504 | t12_switch = 1; //打开加热 505 | } 506 | else if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 507 | { 508 | EEPROM.put(sz_temp2_eeprom, sz_temp[2]); 509 | szjm_jiaozhun_sxxk_count = 0; 510 | t12_switch = 0; //关闭加热 511 | } 512 | break; 513 | case 4: //深圳校准温度4段 存储 514 | if (szjm_jiaozhun_sxxk_count == 0) 515 | { 516 | szjm_jiaozhun_sxxk_count = szjm_jiaozhun_kxxk_count; 517 | t12_switch = 1; //打开加热 518 | } 519 | else if (szjm_jiaozhun_sxxk_count == szjm_jiaozhun_kxxk_count) 520 | { 521 | EEPROM.put(sz_temp3_eeprom, sz_temp[3]); 522 | szjm_jiaozhun_sxxk_count = 0; 523 | t12_switch = 0; //关闭加热 524 | } 525 | break; 526 | case 5: //开始曲线拟合系数计算 527 | qxnh_run(); //计算曲线拟合系数 528 | szjm_jiaozhun_kxxk_count = 6; 529 | break; 530 | case 6: //返回至设置界面,并恢复正常PID参数 531 | display_count = SZJM; 532 | szjm_jiaozhun_kxxk_count = 0; 533 | EEPROM.get(p_eeprom, p); //pid-p 534 | EEPROM.get(i_eeprom, i); //pid-i 535 | EEPROM.get(d_eeprom, d); //pid-d 536 | break; 537 | } 538 | } 539 | } 540 | void jiaozhun_xz_key() //设置界面 旋转 541 | { 542 | if (szjm_jiaozhun_sxxk_count == 0) //选框移动 543 | { 544 | if (digitalRead(DT) == xzbmq_fx) szjm_jiaozhun_kxxk_count++; 545 | else if (digitalRead(CLK) == xzbmq_fx) szjm_jiaozhun_kxxk_count--; 546 | if (szjm_jiaozhun_kxxk_count > 6) szjm_jiaozhun_kxxk_count = 0; 547 | else if (szjm_jiaozhun_kxxk_count < 0) szjm_jiaozhun_kxxk_count = 6; 548 | } 549 | else if (szjm_jiaozhun_sxxk_count == 1) //选框移动 550 | { 551 | if (digitalRead(DT) == xzbmq_fx) sz_temp[0] += 1; 552 | else if (digitalRead(CLK) == xzbmq_fx) sz_temp[0] -= 1; 553 | } 554 | else if (szjm_jiaozhun_sxxk_count == 2) //选框移动 555 | { 556 | if (digitalRead(DT) == xzbmq_fx) sz_temp[1] += 1; 557 | else if (digitalRead(CLK) == xzbmq_fx) sz_temp[1] -= 1; 558 | } 559 | else if (szjm_jiaozhun_sxxk_count == 3) //选框移动 560 | { 561 | if (digitalRead(DT) == xzbmq_fx) sz_temp[2] += 1; 562 | else if (digitalRead(CLK) == xzbmq_fx) sz_temp[2] -= 1; 563 | } 564 | else if (szjm_jiaozhun_sxxk_count == 4) //选框移动 565 | { 566 | if (digitalRead(DT) == xzbmq_fx) sz_temp[3] += 1; 567 | else if (digitalRead(CLK) == xzbmq_fx) sz_temp[3] -= 1; 568 | } 569 | } 570 | -------------------------------------------------------------------------------- /v1.20.1/MsTimer2.ino: -------------------------------------------------------------------------------- 1 | //定时器2 2 | uint32_t t12_sleep_old_time = 0; 3 | void MsTimer2_rw1() 4 | { 5 | if (t12_switch == 1) //烙铁启动,打开休眠判断决策 6 | { 7 | if (bitRead(TIMSK2, TOIE2) == 0) //检测定时是否有打开 1-打开 0-无 8 | { 9 | sleep_count = 0; 10 | xp_time_count = 0; 11 | MsTimer2::set(1000, sleep_timing); // 1000ms 运行一次 12 | MsTimer2::start(); //打开定时器2计数 13 | } 14 | if (millis() - t12_sleep_old_time > 700) 15 | { 16 | t12_sleep(); //T12休眠决策 17 | t12_sleep_old_time = millis(); 18 | } 19 | } 20 | else if (t12_switch == 0) 21 | { 22 | if (bitRead(TIMSK2, TOIE2) == 0) 23 | { 24 | sleep_count = 0; 25 | xp_time_count = 0; 26 | MsTimer2::set(1000, xp_timing); // 1000ms 运行一次 27 | MsTimer2::start(); //打开定时器2计数 28 | } 29 | system_sleep(); //系统休眠决策 30 | } 31 | } 32 | 33 | void sleep_timing() //休眠定时任务 34 | { 35 | sleep_count++; //烙铁没动,计数增加 36 | } 37 | 38 | void xp_timing() //息屏定时任务,校准界面不息屏 39 | { 40 | if (display_count != SZJM_JIAOZHUN) xp_time_count++; //烙铁没动,计数增加 41 | } 42 | -------------------------------------------------------------------------------- /v1.20.1/PID.ino: -------------------------------------------------------------------------------- 1 | //********** PID算法 ********** 2 | //算法来至https://blog.csdn.net/foxclever/article/details/105006205 By foxclever 3 | void pid() 4 | { 5 | if (t12_switch == 1 && vin_error == 0 && t12_error == 0) //加热开关开启 6 | { 7 | //计算设定值与平均温度的差值 8 | int16_t ek_average = set_temp - t12_temp_average; 9 | //平均差值小于3,发出声音提示一下 10 | if (ek_average >= -3 && ek_average <= 3 && buzzer_temp_average_state == 0) 11 | { 12 | buzzer(120, 300); 13 | buzzer_temp_average_state = 1; 14 | } 15 | if (display_count == SZJM_JIAOZHUN) 16 | PIDRegulator(t12_ad); //在校准界面时使用T12的ADC作为PID的目标值 17 | else 18 | PIDRegulator(t12_temp); //在其他界面时使用T12的温度值作为PID的目标值 19 | } 20 | else 21 | { 22 | pid_out = 0; 23 | lasterror = 0; 24 | preerror = 0; 25 | t12_temp_read_time = 450; 26 | } 27 | pwm_1b(pid_out); 28 | pid_out_bfb = (pid_out / (pwm_max - pwm_min)) * 100; 29 | } 30 | 31 | void PIDRegulator(float PV) 32 | { 33 | float factor = 0.0; //变积分系数 34 | float increment = 0.0; 35 | float pError = 0.0, dError = 0.0, iError = 0.0; 36 | if (display_count == SZJM_JIAOZHUN) //在校准界面时使用T12的ADC作为PID的目标值 ,计算偏差 37 | { 38 | if (szjm_jiaozhun_sxxk_count == 1) thisError = sz_adc0 - PV; 39 | else if (szjm_jiaozhun_sxxk_count == 2) thisError = sz_adc1 - PV; 40 | else if (szjm_jiaozhun_sxxk_count == 3) thisError = sz_adc2 - PV; 41 | else if (szjm_jiaozhun_sxxk_count == 4) thisError = sz_adc3 - PV; 42 | } 43 | else //在其他界面时使用T12的温度值作为PID的目标值 ,计算偏差 44 | { 45 | thisError = set_temp - PV; //得到偏差值 46 | thisError_average = set_temp - t12_temp_average; //得到平均值的偏差值 47 | } 48 | //规定采样时间 49 | if (thisError < -5) t12_temp_read_time = 150; 50 | else if (thisError >= -5 && thisError <= 10) t12_temp_read_time = 400; 51 | else if (thisError > 10 && thisError <= 30) t12_temp_read_time = 500; 52 | else t12_temp_read_time = 800; 53 | if (thisError <= 30 && thisError > -15) 54 | { 55 | if (fabs(thisError) > deadband) 56 | { 57 | pError = thisError - lasterror; 58 | iError = float((thisError + lasterror)) / 2.0; 59 | dError = thisError - 2 * (lasterror) + preerror; 60 | 61 | //变积分系数获取 62 | factor = get_factor(thisError, errorabsmax, errorabsmin); 63 | 64 | //计算微分项增量带不完全微分 65 | deltadiff = d * (1 - alpha) * dError + alpha * deltadiff; 66 | 67 | increment = p * pError + i * factor * iError + deltadiff; //增量计算 68 | } 69 | else 70 | { 71 | if ((fabs(set_temp - pwm_min) < deadband) && (fabs(PV - pwm_min) < deadband)) 72 | { 73 | pid_out = pwm_min; 74 | } 75 | increment = 0.0; 76 | } 77 | 78 | pid_out = pid_out + increment; 79 | 80 | /*对输出限值,避免超调和积分饱和问题*/ 81 | if (pid_out >= pwm_max) 82 | { 83 | if (thisError <= 0) pid_out = pwm_min; 84 | else pid_out = pwm_max; 85 | } 86 | else if (pid_out <= pwm_min) pid_out = pwm_min; 87 | 88 | } 89 | else if (thisError > 30) pid_out = pwm_max; 90 | else if (thisError < -15) pid_out = pwm_min; 91 | preerror = lasterror; //存放偏差用于下次运算 92 | lasterror = thisError; 93 | } 94 | 95 | float get_factor(float ek0, float absmax, float absmin) //变积分系数获取 96 | { 97 | float factor1 = 0.0; 98 | factor1 = map(ek0, absmax, absmin, 0.0, 1.0); 99 | if (abs(ek0) >= absmax) factor1 = 0.0; 100 | else if (abs(ek0) <= absmin) factor1 = 1.0; 101 | return factor1; 102 | } 103 | 104 | void pwm_1b(uint16_t val)//自定义PWM,使用相位和频率校正模式,2048级控温 105 | { 106 | //输出通道B 占空比: (OCR1B+1) / (OCR1A+1) 107 | //占空比不能大于OCR1A 108 | 109 | if (val >= pwm_max) digitalWrite(t12_pwm_pin, 1); 110 | else if (val <= pwm_min) digitalWrite(t12_pwm_pin, 0); 111 | else 112 | { 113 | //pinMode(10, OUTPUT); //pin10连接至B通道 114 | //bitWrite(DDRB, 2, 1); //设置pin10为输出 115 | //相位和频率校正PWM,分频比64,频率: 16000000/2*256*(OCR1A+1) = 15HZ 116 | TCCR1A = B00100001; 117 | TCCR1B = B00010100; 118 | OCR1A = pwm_max; //从0开始数到0CR1A,0-65535,设置周期和频率 119 | OCR1B = val; //用来设置比较器,占空比 120 | } 121 | //ec_read(); //读取电流 122 | } 123 | /*时钟输出 | Arduino输出Pin | 芯片Pin | Pin 名字 124 | OC0A 6 12 PD6 125 | OC0B 5 11 PD5 126 | OC1A 9 15 PB1 127 | OC1B 10 16 PB2 128 | OC2A 11 17 PB3 129 | OC2B 3 5 PD3 130 | 131 | 脉冲生成模式控制位(WGM):用来设置PWM的模式或CTC模式 132 | 时钟选择位(CS):设置时钟的预分频 133 | 输出模式控制位(COMnA和COMnB):使能/禁用/反相 输出A和输出B 134 | 输出比较器(OCRnA和OCRnB):当计数器等于这两个值时,输出值根据不同的模式进行变化 135 | 136 | 快速PWM(0-255 0-255 数完归零) 137 | 相位修正PWM(0-255 255-0 数完倒数) 138 | 139 | 8位(定时器0/2) 140 | CSn0 001 = 1 141 | CSn1 010 = 8 142 | CSn2 011= 32 143 | CSn3 100= 64 144 | CSn4 101= 128 145 | CSn5 110= 256 146 | CSn6 111= 1024 147 | 16位(定时器1) 148 | CSn0 001 = 1 149 | CSn1 010 = 8 150 | CSn2 011= 64 151 | CSn3 100= 256 152 | CSn4 101= 1024 153 | 154 | COMnA1 COMnB1 = 占空比AB都可控 155 | 从0数到2047 0时输出高电平 156 | OCRnA 当数到OCRnA,输出低电平,即A的占空比=OCRnA的值 157 | OCRnB 当数到OCRnB,输出低电平,即B的占空比=OCRnB的值 158 | 159 | COMnA0 COMnB1 = A当数到头是反相 占空比A50% B可控 160 | OCRnA 从0数到OCRnA 0时输出高电平 161 | OCRnB 当OCRnA=OCRnB,输出低电平 162 | 输出通道B 占空比: (OCR1B+1) / (OCR1A+1) 163 | 占空比不能大于OCR1A 164 | pinMode(10, OUTPUT); //B 165 | bitWrite(DDRB, 2, 1); //设置pin10为输出 166 | 快速PWM,分频比64,频率: 16000000/64*(OCR1A+1) = 976HZ 167 | TCCR1A = B00100011; 168 | TCCR1B = B00011011; 169 | 相位和频率校正PWM,分频比8,频率: 16000,000/2*8*(OCR1A+1) = 488HZ 170 | TCCR1A = B00100001; 171 | TCCR1B = B00010010; 172 | 相位校正PWM,分频比256,频率: 16000000/2*256*(OCR1A+1) = 61HZ 173 | TCCR1A = B00100011; 174 | TCCR1B = B00010100; 175 | OCR1A = 2047; //从0开始数到0CR1A,0-65535,设置周期和频率 176 | OCR1B = val; //用来设置比较器,占空比*/ 177 | -------------------------------------------------------------------------------- /v1.20.1/Sleep.ino: -------------------------------------------------------------------------------- 1 | //********** T12休眠判断决策 ********** 2 | void t12_sleep() 3 | { 4 | if(sleep_time==999) return; 5 | if (sleep_state != digitalRead(t12_sleep_pin))//烙铁动了,计数清零 6 | { 7 | sleep_state = !sleep_state; //状态取反 8 | sleep_count = 0; //计数清零 9 | if (zjm_sleep_ts == 1) 10 | { 11 | zjm_sleep_ts = 0; //提示主界面退出显示休眠状态 12 | set_temp = sleep_temp_cache; 13 | sleep_temp_cache = 0; 14 | buzzer_temp_average_state = 0; //准备好到达温度提示声 15 | buzzer(150, 300); //提示一下 16 | } 17 | } 18 | if (sleep_count == sleep_time && zjm_sleep_ts == 0) //达到休眠的阈值,进入休眠 19 | { 20 | EEPROM.put(set_temp_eeprom, set_temp); //自动保存当前设置温度 21 | zjm_sleep_ts = 1; //提示主界面显示休眠中 22 | buzzer(150, 300); //提示一下 23 | 24 | if (set_temp > sleep_temp) //大于设置的休眠温度 25 | { 26 | sleep_temp_cache = set_temp; //休眠前将温度记录下来,记录和调温 27 | set_temp = sleep_temp; //将温度调至休眠温度 28 | } 29 | else if (set_temp <= sleep_temp) //小于等于设置的休眠温度,只记录不调温 30 | sleep_temp_cache = set_temp; //休眠前将温度记录下来 31 | } 32 | else if (sleep_count > 1800) //半小时没操作,关闭加热 33 | { 34 | MsTimer2::stop(); 35 | set_temp = sleep_temp_cache; 36 | sleep_temp_cache = 0; 37 | t12_switch = 0; 38 | sleep_count = 0; 39 | zjm_sleep_ts = 0; //提示主界面退出休眠 40 | buzzer(150, 1000); //提示一下 41 | } 42 | } 43 | 44 | //********** 系统休眠判断决策 ********** 45 | void system_sleep() 46 | { 47 | if (xp_time_count >= 180) //无加热无操作超过180秒就显示息屏界面 48 | { 49 | if (xp_time_count - xp_time_count_old > 3) //每隔3秒刷新一次位置 50 | { 51 | display_count = ZJM;//退出至主界面 52 | xp_state = 1; //标记息屏状态 53 | xp_x = random(0, 90); 54 | xp_y = random(11, 31); 55 | xp_time_count_old = xp_time_count; 56 | } 57 | else if (xp_time_count >= 65530) //防止数值溢出 58 | { 59 | xp_time_count = 180; 60 | xp_time_count_old = 0; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /v1.20.1/WDT.ino: -------------------------------------------------------------------------------- 1 | //********** 看门狗函数 ********** 2 | void set_wdt_mod(uint8_t mod, uint8_t ii) //模式,超时时间 3 | { 4 | /* 5 | WDCE 6 | 该位在定时序列中用于更改WDE和预分频器位 7 | 要清除WDE位或更改预分频器位,必须将WDCE置1。 8 | 一旦写入1,硬件将在四个时钟周期后清除WDCE。 9 | 0=16ms,1=32ms,2=64ms,3=128ms,4=250ms 10 | 5=500ms,6=1s,7=2s,8=4s,9=8s 11 | */ 12 | if (ii > 9 ) ii = 9; 13 | byte bb; 14 | bb = ii & 7; 15 | if (ii > 7) bb |= (1 << 5); 16 | bb |= (1 << WDCE); 17 | 18 | switch (mod) { 19 | case 0: //关闭看门狗 20 | __asm__ __volatile__ ("wdr"); //看门狗复位 21 | MCUSR = 0x00; //看门狗复位标志清零 22 | WDTCSR = (1 << WDCE) | (1 << WDE); //打开允许修改使能,并WDE置1 23 | WDTCSR = 0x00; //清除所有预分频位 24 | break; 25 | 26 | case 1: //打开看门狗,设置复位模式 27 | __asm__ __volatile__ ("wdr"); //看门狗复位 28 | MCUSR &= ~(1 << WDRF); //MUUSR中的WDRF清零,清除复位标志 29 | WDTCSR |= (1 << WDCE) | (1 << WDE); //打开允许修改使能,并WDE置1 30 | //设置新的看门狗超时值bb 31 | WDTCSR = bb; //8秒时bb=0011 0001 32 | WDTCSR |= _BV(WDE); //设置复位模式 33 | break; 34 | 35 | case 2: //打开看门狗,设置中断模式 36 | __asm__ __volatile__ ("wdr"); //看门狗复位 37 | MCUSR &= ~(1 << WDRF); //MUUSR中的WDRF清零,清除复位标志 38 | WDTCSR |= (1 << WDCE) | (1 << WDE); //打开允许修改使能,并WDE置1 39 | //设置新的看门狗超时值bb 40 | WDTCSR = bb; //8秒时bb=0011 0001 41 | WDTCSR |= _BV(WDIE); //设置中断模式 42 | break; 43 | 44 | case 3: //打开看门狗,设置中断+复位模式 45 | __asm__ __volatile__ ("wdr"); //看门狗复位 46 | MCUSR &= ~(1 << WDRF); //MUUSR中的WDRF清零,清除复位标志 47 | WDTCSR |= (1 << WDCE) | (1 << WDE); //打开允许修改使能,并WDE置1 48 | //设置新的看门狗超时值bb 49 | WDTCSR = bb; //8秒时bb=0011 0001 50 | WDTCSR |= _BV(WDIE); //设置中断模式 51 | WDTCSR |= _BV(WDE); //设置复位模式 52 | break; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /v1.20.1/analogRead.ino: -------------------------------------------------------------------------------- 1 | //********** 读取电压、电流、温度 ********** 2 | float vin_cache = 0.0; 3 | uint8_t vin_cache_count = 0; 4 | 5 | float tc1047_cache = 0.0; 6 | uint8_t tc1047_cache_count = 0; 7 | 8 | #define cycs 10 //时间平均滤波的采样次数 采样周期 = 采样次数*定时执行任务的时间 9 | uint8_t t12_adc_error_count = 0; //t12ADC超出检测范围错误计数 10 | void read_timing() //定时读取电源电压和机内温度 11 | { 12 | if (millis() - vin_read_time > t12_temp_read_time) 13 | { 14 | read_t12_temp(); 15 | vin_read_time = millis(); 16 | } 17 | } 18 | void read_timing2() 19 | { 20 | vin_read(); //读取电压 21 | tc1047_temp_read(); //读取室温 22 | if (szjm_oled_sxxk_count == 1) u8g2.setContrast(oled_ld); //改变亮度 23 | } 24 | void read_t12_temp() //定时读取T12的温度 25 | { 26 | float t12_ad_nwe = 0.0; //临时AD 27 | digitalWrite(t12_pwm_pin, 0); 28 | read_timing2(); 29 | delay(1); 30 | t12_ad_nwe = denoiseAnalog(t12_temp_pin); //读取即时AD 31 | //t12_ad_nwe = analogRead(t12_temp_pin); //读取即时AD 32 | t12_ad += (t12_ad_nwe - t12_ad) * 0.7; //平滑滤波 33 | //if (digitalRead(t12_sleep_pin) == 1) t12_ad += 2; //补偿上拉噪声干扰 34 | //计算温度,温度曲线由校准程序自动计算 35 | t12_temp = sz_p[3] * t12_ad * t12_ad * t12_ad + sz_p[2] * t12_ad * t12_ad + sz_p[1] * t12_ad + sz_p[0]; 36 | t12_temp += (tc1047_temp - tc1047_refer); //环境温度补偿 37 | 38 | //记录平均温度 39 | t12_temp_average_cache += t12_temp; 40 | t12_temp_average_count++; 41 | if (t12_temp_average_count == 8) 42 | { 43 | t12_temp_average = t12_temp_average_cache >> 3; 44 | t12_temp_average_cache = 0; //累计缓存温度清零 45 | t12_temp_average_count = 0; //计数清零 46 | } 47 | //运行PID 48 | pid(); 49 | 50 | //手柄检测及超出测量范围检测 51 | #define ADCMax 1000 52 | if (t12_switch == 0 && t12_ad >= ADCMax) //无手柄 53 | { 54 | t12_error = 1; 55 | t12_switch = 0; 56 | } 57 | else if (t12_switch == 1 && t12_ad >= ADCMax) //超出测量范围检测,延时检测 58 | { 59 | t12_adc_error_count++; 60 | if (t12_adc_error_count >= 10) 61 | { 62 | MsTimer2::stop(); //停止一次 然后在MsTimer2_rw1()里自动切换定时的中断任务 63 | t12_adc_error_count = 0; //清除计数 64 | t12_adc_error = 1; 65 | t12_switch = 0; 66 | } 67 | } 68 | else if (t12_switch == 1 && t12_ad < ADCMax) 69 | { 70 | t12_adc_error = 0; 71 | t12_adc_error_count = 0; //清除计数 72 | } 73 | else t12_error = 0; 74 | } 75 | 76 | void vin_read() 77 | { 78 | /* 79 | 串联电阻的中点电压计算公式 80 | Eout 中点电压 81 | Vcc 输入电压(两端施加电压) 82 | R1、R2 两个串联的分压电阻 83 | Eout = Vcc * R2/(R1+R2) R1靠近电源 R2靠近地 84 | */ 85 | /*vin = (denoiseAnalog(vin_pin) / 0.1282) * vcc_refer_fl; //计算电源电压 10/68+10=0.1282 86 | if (vin < vin_low && vin_low >= 3.3) //电压过低提示 87 | { 88 | vin_error = 1; 89 | t12_switch = 0; 90 | }*/ 91 | 92 | vin_cache += (denoiseAnalog(vin_pin) / 0.1389) * vcc_refer_fl; 93 | vin_cache_count++; 94 | if (vin_cache_count >= cycs) 95 | { 96 | vin = vin_cache / cycs + vin_refer; 97 | vin_cache_count = 0; 98 | vin_cache = 0; 99 | //电压过低提示 100 | if (vin < vin_low && vin_low >= 3.3) 101 | { 102 | vin_error = 1; 103 | t12_switch = 0; 104 | } 105 | else vin_error = 0; 106 | } 107 | } 108 | 109 | void tc1047_temp_read() //读取tc1047温度 110 | { 111 | //tc1047_temp = ((denoiseAnalog(tc1047_pin) * vcc_refer_fl) - 0.5) * 100; 112 | 113 | tc1047_cache += ((denoiseAnalog(tc1047_pin) * vcc_refer_fl) - 0.5) * 100; 114 | tc1047_cache_count++; 115 | if (tc1047_cache_count >= cycs) 116 | { 117 | tc1047_temp = tc1047_cache / cycs; 118 | tc1047_cache_count = 0; 119 | tc1047_cache = 0; 120 | } 121 | } 122 | void auto_get_set_temp() //自动获取设置温度的范围 123 | { 124 | set_temp_max = ((sz_temp[3]) / 10 ) * 10 - 20; 125 | if (set_temp_max > 450) set_temp_max = 450; 126 | set_temp_min = ((sz_temp[0]) / 10) * 10; 127 | } 128 | /*uint16_t denoiseAnalog(uint8_t pin) 129 | { 130 | uint8_t low, high; 131 | if (pin >= A0) pin -= A0; //设置端口 132 | ADMUX = (0x0F & pin) | bit(REFS0); //设置基准电压为5V,设置端口 133 | ADCSRA |= bit (ADEN) | bit (ADIF); //启用ADC,关闭任何挂起的中断 134 | set_sleep_mode (SLEEP_MODE_ADC); //在取样时进行睡眠以降低噪音,需要开启ADC中断进行唤醒 135 | sleep_mode(); //进入休眠自动启动转换 136 | //bitSet(ADCSRA, ADSC); //ADSC 写1启动AD转换 137 | while (bitRead(ADCSRA, ADSC)); //等待转换结束 138 | low = ADCL; 139 | high = ADCH; 140 | bitClear (ADCSRA, ADEN); // 禁用ADC 141 | return (high << 8) | low; //返回数值 142 | }*/ 143 | uint16_t denoiseAnalog (byte port) 144 | { 145 | uint16_t result = 0; 146 | if (port >= A0) port -= A0; //设置端口 147 | ADMUX = (0x0F & port) | bit(REFS0); //设置基准电压为5V,设置端口 148 | ADCSRA |= bit (ADEN) | bit (ADIF); //启用ADC,关闭任何挂起的中断 149 | set_sleep_mode (SLEEP_MODE_ADC); //在取样时进行睡眠以降低噪音,需要开启ADC中断进行唤醒 150 | for (uint8_t i = 0; i < 16; i++) { // get 32 readings 151 | sleep_mode(); // go to sleep while taking ADC sample 152 | while (bitRead(ADCSRA, ADSC)); // 等待转换结束 153 | result += ADC; // add them up 154 | } 155 | bitClear (ADCSRA, ADEN); // 禁用ADC 156 | return (result >> 4); // devide by 32 and return value 157 | } 158 | //ADC中断服务 159 | EMPTY_INTERRUPT (ADC_vect); // 这里没什么可做的 160 | -------------------------------------------------------------------------------- /v1.20.1/font.c: -------------------------------------------------------------------------------- 1 | //#include 2 | #include 3 | const uint8_t chinese_t12[1591] U8G2_FONT_SECTION("chinese_t12") = 4 | "A\0\3\2\4\4\2\4\5\14\14\0\377\11\375\12\376\0\0\0\0\0\337 \5\0\242\5+\13w\346" 5 | "]\134\33\206,\256\1-\6\26\362\305\1.\6\42c\305\20\60\13\226\342\315\220\204~L\206\4\61\11" 6 | "\225\242\305\330O\203\0\62\13\226\342\315\220\204b_\207\1\63\16\226\342\315\220\204iiN\305dH\0" 7 | "\64\17\226\342\235\226D]\262$K\206\61M\0\65\16\226\342\305!M\7\71M\305dH\0\66\17\226" 8 | "\342\315\220\204j\262h\242\61\31\22\0\67\13\226\342\305\61\15\323bZ\3\70\17\226\342\315\220\204\306d" 9 | "HBc\62$\0\71\17\226\342\315\220\204\306dPS\61\31\22\0D\15\227\42\306 \205I\352c\62" 10 | "H\0I\10\223\42\305\22\365eP\14\226\342\305\240\204\216\303\222V\1S\17\226\342\315\220\204j<\304" 11 | "\251\230\14\11\0V\17\227\42FjM\262(\253\204I\32g\0\0\0\0\4\377\377!\3\27\271_O" 12 | "\16$\321T\13s Gr$Gr(G\262t\1N\256\34\314^w:\274\245\351\60\344\224\341\240" 13 | "\344P\22\15R\230\345@\26\207Q\42\17O\21\35\314^_\35\310\342\60N\206!\22+\331\232\255Q" 14 | "R\214\222b\22\325\264R\30\2ON\33\314^_*&C\32U\243\242TK\242a\210Z\243j\324" 15 | "KS\64I\35P\134\35\314^_\35\10\323d\30\244\34\223\206\245\24f\311\60HI\34E\303\226v" 16 | "\333\0P\177\37\314^_\22\325\242\244\226V\206AQb%\32\266\34L\206A\12\343\254e\30\244j" 17 | "\0Qs\31\313^WZ\313\201$\35\316\71\226\16\7\65\207\222\34\310\322\222\16\10Q\267\34\314^w" 18 | "\232\252Y\24Fa(eR\230&\303\20\351@V\12C\265\216f\0Q\306\42\314^G\230\244Y\24" 19 | "&\311\60dI\224&R\32\15\213\26\205\331\60eQ\230Ea\66\14i\14R\240$\314^_\16\346" 20 | "\310\60$C\26%Q\26%Q\26%Q\26%Q-\211jITK\242$L\6M*S\213\33\314" 21 | "^\327p\210r\260\34\306a\234\14C\26\306a\22\226\252Q\65\214\206\3T\21\32\312_g\216\304\303" 22 | "AGtD\32\42\251$\225\244!\322\21\71\321\201\4T&\31\273^\307\203\250#\255QI\313\324\60" 23 | "\32\206\60\15\323p\30\302\64\2W\372\31\313^_m\70h\345A\316\342A\316\262\341 \65)\203\242" 24 | "\246\303A\134O\35\314^\327p\313\201l\270%a\251:\34\242\326\250:\34\222,\12\243\254\24f\0" 25 | "^U\34\313^_m\70h\325a\10\323p\30\302$\213\206\203\324\64\34\244\306(\221\0^\246\36\314" 26 | "^\77\20\17\207\250\26\16\207\250\26F\203\230\203\311\60dQVL\302p\213\266\1_\0\34\314^\317" 27 | "pH\263\34\310r \313\201,\33\36\263\34\310\342\60\16\323b\234\1bK\30\313^\367\20\15:\226" 28 | "c\361p\316\261t\70\250\71\226#u(\6b\245!\314^W\64lQ\230Ea\62Lb\224#\321" 29 | "\260)\245dJ\242,J\212Q-\211\222Zfc\245\37\314^WZ\32\206(\253\14R\22F\303\20" 30 | "\245\251\62\34\302(+\205\241\226\204I\226\31e\271\27\314^o\216\246\303c\16\346\340\60\207i\307\70" 31 | "\13\223,\16\1e\313\42\314^W\230\3Y\70 107 | #include //掉电数值存储库 108 | #include //休眠库 109 | #include //屏幕驱动库 110 | #ifdef U8X8_HAVE_HW_I2C 111 | #include 112 | #endif 113 | 114 | U8G2_SSD1306_128X32_UNIVISION_2_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); //SSD1306 0.96寸OLED 115 | //U8G2_SSD1316_128X32_2_HW_I2C u8g2(U8G2_R0,/* reset=*/ U8X8_PIN_NONE); //SSD1316 0.87寸OLED 116 | 117 | //调用字库 118 | #include "font.c" 119 | //声明外部变量 120 | extern const uint8_t chinese_t12[1591] U8G2_FONT_SECTION("chinese19"); 121 | 122 | //********** 引脚定义 ********** 123 | #define SW 4 //按下 ,可更改其他引脚 124 | #define CLK 3 //减,只可修改为2或3 125 | #define DT 2 //加,只可修改为2或3 126 | //除了10号脚不能改,其他都可以改,但模拟引脚只能改模拟引脚(休眠引脚除外) 127 | #define t12_sleep_pin A0 //t12休眠 模拟读取引脚 128 | #define t12_temp_pin A2 //t12温度 模拟读取引脚 129 | #define tc1047_pin A3 //机内温度 模拟读取引脚 130 | #define vin_pin A6 //电源电压 模拟读取引脚 131 | #define t12_pwm_pin 10 //t12加热 pwm输出引脚,定死不可更改 132 | #define buzzer_pin 8 //蜂鸣器 输出引脚 133 | //************ EEPROM地址定义 ************ 134 | uint8_t auto_get = 0; //自动刷写eeprom的状态存储,判断是否首次开机 0-首次 1-非首次 135 | #define auto_get_eeprom 0 //自动刷写eeprom的状态存储,1位 136 | #define p_eeprom 1 //p地址,4位 137 | #define i_eeprom p_eeprom+4 //i地址,4位 138 | #define d_eeprom i_eeprom+4 //d地址,4位 139 | #define sleep_time_eeprom d_eeprom+4 //休眠时间,4位 140 | #define sleep_temp_eeprom sleep_time_eeprom+4 //休眠温度,1位 141 | #define oled_ld_eeprom sleep_temp_eeprom+1 //OLED亮度,1位 142 | #define vcc_refer_eeprom oled_ld_eeprom+1 //基准电压,4位 143 | #define vin_refer_eeprom vcc_refer_eeprom+4 //电源电压校准值,4位 144 | #define t12_kj_jr_eeprom vin_refer_eeprom+4 //是否开机就加热?,1位 145 | #define vin_low_eeprom t12_kj_jr_eeprom+1 //输入电压低压报警阈值,4位 146 | #define tc1047_refer_eeprom vin_low_eeprom+4 //冷端补偿校准值,1位 147 | #define oled_fx_eeprom tc1047_refer_eeprom+1 //OELD方向,1位 148 | #define xzbmq_fx_eeprom oled_fx_eeprom+1 //编码器旋转方向,1位 149 | #define sz_temp0_eeprom xzbmq_fx_eeprom+1 //深圳头曲线温度校准1段,4位 150 | #define sz_temp1_eeprom sz_temp0_eeprom+4 //深圳头曲线温度校准2段,4位 151 | #define sz_temp2_eeprom sz_temp1_eeprom+4 //深圳头曲线温度校准3段,4位 152 | #define sz_temp3_eeprom sz_temp2_eeprom+4 //深圳头曲线温度校准4段,4位 153 | #define set_temp_eeprom sz_temp3_eeprom+4 //t12设置温度,4位 154 | //T12及温度相关 155 | boolean t12_switch = 0; //T12加热开关 156 | boolean t12_kj_jr = 0; //是否开机就加热? 0-否 1-是 157 | 158 | float t12_ad = 0.0; //T12即时ADC值 159 | int16_t t12_temp = 0; //T12即时温度 160 | int16_t t12_temp_display = 0; //T12显示温度 161 | 162 | boolean t12_error = 0; //手柄未接提示 163 | boolean t12_adc_error = 0; //温度超出测量范围 164 | int16_t set_temp_max; //自动计算设置的温度最大值 165 | int16_t set_temp_min; //自动计算设置的温度最小值 166 | 167 | int16_t t12_temp_average_cache = 0; //记录采集温度,缓存用 168 | int16_t t12_temp_average = 0; //8次内采集到的平均温度,显示用 169 | uint8_t t12_temp_average_count = 0; //平均温度采集计数 170 | boolean buzzer_temp_average_state = 0; //到达温度提示声 171 | 172 | //float tc1047_ad = 0.0; //tc1047ADC值 173 | float tc1047_temp = 0.0; //tc1047温度,机内温度 174 | int8_t tc1047_refer = 30; //T12环境参考温度校准值 175 | 176 | float vcc_refer = 4.98; //参考电压,稳压芯片输出的电压是多少就填多少 177 | float vin = 0.0; //电源电压 178 | float vin_refer = 0.0; //输入电压校准值 179 | float vin_low = 3.3; //低压报警阈值 180 | boolean vin_error = 0; //低压报警提示 181 | #define vcc_refer_fl vcc_refer/1023.0 //参考电压每级分量 182 | 183 | uint32_t xzbmq_time = 0; //编码器消抖对比时间 184 | uint32_t temp_read_time = 0; //定时读取温度对比时间 185 | uint32_t vin_read_time = 0; //定时读取输入电压时间 186 | uint32_t t12_temp_read_time = 450; //定时T12温度采样时间 187 | 188 | boolean buzzer_state = 0; //蜂鸣器准备状态 189 | uint16_t buzzer_time; //蜂鸣器响的时间 190 | uint16_t buzzer_count; //蜂鸣器响的次数 191 | boolean buzzer_szjm_state = 0; //进入设置界面的长音状态 192 | boolean buzzer_zjm_state = 0; //退出至主界面的长音状态 193 | 194 | boolean zjm_sleep_ts = 0; //主界面休眠提示 0-无 1-休眠中 195 | uint16_t sleep_time = 150; //进入休眠的时间阈值,单位秒 196 | uint8_t sleep_temp = 200; //休眠时的温度,单位摄氏度 197 | boolean sleep_state = 0; //休眠引脚状态 0低电平 1高电平 198 | uint16_t sleep_count = 0; //休眠计数 199 | uint16_t sleep_temp_cache = 0; //休眠前的温度缓存 200 | 201 | uint8_t oled_ld = 50; //OLED亮度 202 | boolean oled_fx = 0; //OLED方向 0-不旋转,横向显示 1-旋转180度 203 | boolean xzbmq_fx = 0; //编码器方向 0-顺加逆减 1-顺减逆加 204 | boolean hfccsz_state = 0; //恢复出厂设置 0-NO 1-YES 205 | 206 | boolean xp_state = 0; //息屏状态 0-无 1-息屏 207 | uint16_t xp_time_count = 0; //息屏计数 208 | uint16_t xp_time_count_old = 0; //上一次时间计数 209 | int8_t xp_x = 0; //息屏随机变化位置X 210 | int8_t xp_y = 0; //息屏随机变化位置Y 211 | int8_t xp_x_old = 50; //上一次息屏随机变化位置X 212 | int8_t xp_y_old = 21; //上一次息屏随机变化位置Y 213 | 214 | //深圳头曲线拟合的4段ADC 215 | #define sz_adc0 10 216 | #define sz_adc1 350 217 | #define sz_adc2 650 218 | #define sz_adc3 940 //原950 219 | //uint16_t sz_temp[4] = {36, 224, 347, 446}; //深圳头曲线拟合的4段温度 Y 390倍 220 | //uint16_t sz_temp[4] = {43, 259, 382, 490}; //深圳头曲线拟合的4段温度 Y 330倍 221 | uint16_t sz_temp[4] = {49, 262, 391, 486}; //深圳头曲线拟合的4段温度 Y 1.03版本程序移植 222 | float sz_p[4]; //深圳头曲线拟合的4个系数 P 223 | //********** 菜单标志位相关 ********** 224 | #define ZJM 1 //主界面 225 | #define SZJM 2 //设置界面 226 | #define SZJM_PID 3 //PID设置界面 227 | #define SZJM_SLEEP 4 //休眠设置界面 228 | #define SZJM_OLED 5 //OLED设置界面 229 | #define SZJM_POWER 6 //电源设置界面 230 | #define SZJM_JIAOZHUN 7 //校准设置界面 231 | #define SZJM_LAOTIE 8 //烙铁头设置界面 232 | 233 | uint8_t display_count = 1; //默认要显示的界面 234 | boolean dec_state = 0; //小数点输入状态 0关闭 1开启 235 | uint8_t qj_ca_count = 0; //全局长按计数 236 | 237 | boolean szjm_kxxk_L = 0; //设置界面空心选框 顺时针转 238 | boolean szjm_kxxk_R = 0; //设置界面空心选框 逆时针转 239 | int8_t szjm_kxxk_count = 0; //设置界面空心选框 240 | 241 | int8_t szjm_pid_kxxk_count = 0; //pid界面空心选框 242 | int8_t szjm_pid_sxxk_count = 0; //pid界面实心选框 243 | 244 | int8_t szjm_sleep_kxxk_count = 0; //pid界面空心选框 245 | int8_t szjm_sleep_sxxk_count = 0; //pid界面实心选框 246 | 247 | int8_t szjm_oled_kxxk_count = 0; //oled界面空心选框 248 | int8_t szjm_oled_sxxk_count = 0; //oled界面实心选框 249 | 250 | int8_t szjm_power_kxxk_count = 0; //电源设置界面空心选框 251 | int8_t szjm_power_sxxk_count = 0; //电源设置界面实心选框 252 | 253 | int8_t szjm_pwm_kxxk_count = 0; //PWM界面空心选框 254 | int8_t szjm_pwm_sxxk_count = 0; //PWM界面实心选框 255 | 256 | int8_t szjm_laotie_kxxk_count = 0; //烙铁头设置界面空心选框 257 | int8_t szjm_laotie_sxxk_count = 0; //烙铁头设置界面实心选框 258 | 259 | int8_t szjm_jiaozhun_kxxk_count = 0; //烙铁头设置界面空心选框 260 | int8_t szjm_jiaozhun_sxxk_count = 0; //烙铁头设置界面实心选框 261 | //********** 动态调参PID ********** 262 | float p = 25.0; //比例系数 263 | float i = 8.7; //积分系数 264 | float d = 2.6; //微分系数 265 | 266 | #define p_jz 12.0 //校准界面用的 比例系数 267 | #define i_jz 2.2 //校准界面用的 积分系数 268 | #define d_jz 1.2 //校准界面用的 微分系数 269 | 270 | uint16_t set_temp = 320; //设置温度 271 | int16_t thisError = 0; //本次误差 272 | int16_t thisError_average = 0; //累积误差的平均值 273 | int16_t lasterror = 0; //前一拍偏差 274 | int16_t preerror = 0; //前两拍偏差 275 | const int8_t deadband = 0; //死区 276 | int16_t pid_out = 0.0; //PID控制器计算结果 277 | uint8_t pid_out_bfb = 0.0; //输出值0-100% 278 | const float pwm_max = 2047.0; //输出值上限 279 | const float pwm_min = 0.0; //输出值下限 280 | const float errorabsmax = 2000.0; //偏差绝对值最大值 281 | const float errorabsmin = 50.0; //偏差绝对值最小值 282 | const float alpha = 0.2; //不完全微分系数 283 | float deltadiff = 0.0; //微分增量 284 | 285 | void setup() 286 | { 287 | //***** 首次开机自动刷写eeprom 288 | eerpom_auto(); 289 | //***** 编码器配置 290 | pinMode(SW, INPUT_PULLUP); //按下 291 | pinMode(CLK, INPUT_PULLUP); //相位A 292 | pinMode(DT, INPUT_PULLUP); //相位B 293 | pinMode(t12_temp_pin, INPUT); //t12温度 294 | pinMode(t12_sleep_pin, INPUT_PULLUP); //t12休眠 295 | pinMode(vin_pin, INPUT); //电源电压 296 | pinMode(tc1047_pin, INPUT); //机内温度 297 | pinMode(buzzer_pin, OUTPUT); //蜂鸣器 298 | pinMode(t12_pwm_pin, OUTPUT); //t12加热,不可更改 299 | 300 | digitalWrite(t12_pwm_pin, 0); //默认关闭 301 | digitalWrite(buzzer_pin, 0); //默认关闭 302 | //***** OLED初始化 303 | u8g2.begin(); 304 | u8g2.enableUTF8Print(); 305 | u8g2.setContrast(oled_ld); //设置亮度1-255 306 | //u8g2.setBusClock(400000); //设置I2C通讯速度默认MAX400000 307 | //u8g2.setPowerSave(0); //0开启屏幕 1关闭屏幕 308 | if (oled_fx)u8g2.setDisplayRotation(U8G2_R2); //旋转180度 309 | else u8g2.setDisplayRotation(U8G2_R0); //0度,默认方向 310 | //***** ADC初始化 311 | //ADCSRA |= bit (ADPS0) | bit (ADPS1) | bit (ADPS2); // 设置ADC分频 128倍 312 | ADCSRA |= bit (ADPS1) | bit (ADPS2); //设置ADC分频 64倍 313 | ADCSRA |= bit (ADIE); // 开启ADC中断 314 | interrupts(); // 开启全局中断 315 | //***** 打开外部中断 316 | attachInterrupt(digitalPinToInterrupt(CLK), xuan_zhaun, FALLING); 317 | attachInterrupt(digitalPinToInterrupt(DT), xuan_zhaun, FALLING); 318 | 319 | //***** 播放开机画面和开机声 320 | kj_display(); 321 | buzzer(600, 200); //时间,次数 322 | buzzer_run(); 323 | buzzer(400, 300); //时间,次数 324 | buzzer_run(); 325 | buzzer(130, 1000); //时间,次数 326 | buzzer_run(); 327 | //读取电压/温度 328 | for (uint8_t i = 0; i < 10; i++) //读取初始值 329 | { 330 | vin_read(); 331 | tc1047_temp_read(); 332 | read_t12_temp(); 333 | } 334 | //自动获取设置温度的范围 335 | auto_get_set_temp(); 336 | //***** 开启看门狗 337 | //set_wdt_mod(1, 7); 338 | //***** 是否开机加热 339 | if (t12_kj_jr == 1) t12_switch = 1; 340 | else t12_switch = 0; 341 | //***** 开机计算曲线拟合系数 342 | qxnh_run(); 343 | //Serial.begin(9600); //打开串口调试 344 | } 345 | 346 | void loop() 347 | { 348 | //uint32_t time0 = micros(); 349 | 350 | __asm__ __volatile__ ("wdr"); //看门狗复位 351 | an_xia(); //编码器按下决策 352 | draw_page(); //刷新屏幕 353 | buzzer_run(); //蜂鸣器运行决策 354 | read_timing(); //定时读取任务 355 | MsTimer2_rw1(); //定时器2任务 356 | 357 | //uint32_t time1 = micros(); 358 | //Serial.println(time1 - time0); 359 | } 360 | -------------------------------------------------------------------------------- /v1.20.1/v1.20.1.ino.eep: -------------------------------------------------------------------------------- 1 | :00000001FF 2 | -------------------------------------------------------------------------------- /用到的库/MsTimer2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/用到的库/MsTimer2.zip -------------------------------------------------------------------------------- /用到的库/U8g2-2020-11-15.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sakura-ushio/328P-MiNi-T12/cc4f56ff197394a046ffdd6df54034baf6ea7b17/用到的库/U8g2-2020-11-15.7z --------------------------------------------------------------------------------