From 3b2bf2e30e55eb5afff2078f58a63dc426a73e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zeng=20wei=20=28=E6=9B=BE=E5=A8=81=29?= Date: Mon, 29 Jan 2024 09:51:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Epid=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E5=92=8Cout=E7=9A=84=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HARDWARE/PID.c | 43 +- HARDWARE/PID.h | 6 +- HARDWARE/rs485.c | 51 +- OBJ/LED.axf | Bin 566992 -> 567536 bytes OBJ/LED.build_log.htm | 95 +- OBJ/LED.hex | 3147 +++++++++++++++-------------- OBJ/LED.htm | 1671 +++++++-------- OBJ/bufcut.o | Bin 389060 -> 389060 bytes OBJ/cjson.o | Bin 124800 -> 124800 bytes OBJ/control_LED.dep | 20 +- OBJ/core_cm3.o | Bin 11452 -> 11452 bytes OBJ/croutine.o | Bin 413640 -> 413640 bytes OBJ/dhcp.o | Bin 422308 -> 422308 bytes OBJ/dns.o | Bin 415280 -> 415280 bytes OBJ/event_groups.o | Bin 437752 -> 437752 bytes OBJ/heap_4.o | Bin 426072 -> 426072 bytes OBJ/iwdg.o | Bin 383948 -> 383948 bytes OBJ/list.o | Bin 416532 -> 416532 bytes OBJ/main.crf | Bin 411251 -> 411301 bytes OBJ/main.o | Bin 444448 -> 444468 bytes OBJ/md5.o | Bin 400872 -> 400872 bytes OBJ/misc.o | Bin 385464 -> 385464 bytes OBJ/mqtt_api.o | Bin 422532 -> 422532 bytes OBJ/mqttconnectclient.o | Bin 408928 -> 408928 bytes OBJ/mqttconnectserver.o | Bin 403952 -> 403952 bytes OBJ/mqttdeserializepublish.o | Bin 402260 -> 402260 bytes OBJ/mqttformat.o | Bin 420924 -> 420924 bytes OBJ/mqttpacket.o | Bin 430348 -> 430348 bytes OBJ/mqttserializepublish.o | Bin 408768 -> 408768 bytes OBJ/mqttsubscribeclient.o | Bin 404056 -> 404056 bytes OBJ/mqttsubscribeserver.o | Bin 402252 -> 402252 bytes OBJ/mqttunsubscribeclient.o | Bin 403600 -> 403600 bytes OBJ/mqttunsubscribeserver.o | Bin 402020 -> 402020 bytes OBJ/myfreertos.crf | Bin 414285 -> 414335 bytes OBJ/myfreertos.o | Bin 456796 -> 456812 bytes OBJ/myspi.o | Bin 386056 -> 386056 bytes OBJ/osc.o | Bin 385880 -> 385880 bytes OBJ/pid.crf | Bin 353881 -> 353966 bytes OBJ/pid.o | Bin 390960 -> 391040 bytes OBJ/port.o | Bin 431092 -> 431092 bytes OBJ/pwm.o | Bin 399692 -> 399692 bytes OBJ/pwmout.crf | Bin 349049 -> 349099 bytes OBJ/pwmout.o | Bin 387456 -> 387476 bytes OBJ/queue.o | Bin 486936 -> 486936 bytes OBJ/relays.o | Bin 390104 -> 390104 bytes OBJ/rs485.crf | Bin 417795 -> 417956 bytes OBJ/rs485.o | Bin 468292 -> 468788 bytes OBJ/rtc.o | Bin 404264 -> 404264 bytes OBJ/socket.o | Bin 403728 -> 403728 bytes OBJ/spi.o | Bin 383836 -> 383836 bytes OBJ/stm32f10x_adc.o | Bin 434316 -> 434316 bytes OBJ/stm32f10x_bkp.o | Bin 395708 -> 395708 bytes OBJ/stm32f10x_can.o | Bin 418876 -> 418876 bytes OBJ/stm32f10x_cec.o | Bin 398456 -> 398456 bytes OBJ/stm32f10x_crc.o | Bin 386540 -> 386540 bytes OBJ/stm32f10x_dac.o | Bin 396368 -> 396368 bytes OBJ/stm32f10x_dbgmcu.o | Bin 382440 -> 382440 bytes OBJ/stm32f10x_dma.o | Bin 395792 -> 395792 bytes OBJ/stm32f10x_exti.o | Bin 389748 -> 389748 bytes OBJ/stm32f10x_flash.o | Bin 422744 -> 422744 bytes OBJ/stm32f10x_fsmc.o | Bin 407696 -> 407696 bytes OBJ/stm32f10x_gpio.o | Bin 406484 -> 406484 bytes OBJ/stm32f10x_i2c.o | Bin 428268 -> 428268 bytes OBJ/stm32f10x_it.o | Bin 420640 -> 420640 bytes OBJ/stm32f10x_iwdg.o | Bin 386532 -> 386532 bytes OBJ/stm32f10x_pwr.o | Bin 391412 -> 391412 bytes OBJ/stm32f10x_rcc.o | Bin 426988 -> 426988 bytes OBJ/stm32f10x_rtc.o | Bin 398000 -> 398000 bytes OBJ/stm32f10x_sdio.o | Bin 421692 -> 421692 bytes OBJ/stm32f10x_spi.o | Bin 413240 -> 413240 bytes OBJ/stm32f10x_tim.o | Bin 516336 -> 516336 bytes OBJ/stm32f10x_usart.o | Bin 422864 -> 422864 bytes OBJ/stm32f10x_wwdg.o | Bin 389576 -> 389576 bytes OBJ/system.o | Bin 380048 -> 380048 bytes OBJ/system_stm32f10x.o | Bin 384432 -> 384432 bytes OBJ/systick.o | Bin 418556 -> 418556 bytes OBJ/tasks.o | Bin 513496 -> 513496 bytes OBJ/timers.o | Bin 454692 -> 454692 bytes OBJ/usart.o | Bin 389216 -> 389216 bytes OBJ/utility.o | Bin 20580 -> 20580 bytes OBJ/w25q128.o | Bin 410780 -> 410780 bytes OBJ/w5500.o | Bin 438276 -> 438276 bytes OBJ/w5500api.o | Bin 410916 -> 410916 bytes OBJ/write.crf | Bin 412122 -> 412172 bytes OBJ/write.o | Bin 455412 -> 455432 bytes USER/Listings/LED.map | 1960 +++++++++--------- USER/control.uvguix.Administrator | 95 +- myfreertos/myfreertos.c | 10 +- 88 files changed, 3634 insertions(+), 3464 deletions(-) diff --git a/HARDWARE/PID.c b/HARDWARE/PID.c index 23e1246..aaa82cb 100644 --- a/HARDWARE/PID.c +++ b/HARDWARE/PID.c @@ -17,6 +17,8 @@ void PID_Init() { // pid.set_tem=tem;//用户设定温度 pid.Kp = 110; + pid.Ki = 0.001; + pid.Kd = 340; pid.t = 500; // PID计算周期 // pid.Ti=5000000;//积分时间 // pid.Td=1000;//微分时间 @@ -52,12 +54,12 @@ void PID_Calc() // pid // ti=pid.t/pid.Ti; // ki=ti*pid.Kp; - pid.Iout = ki * pid.SEk; // 积分输出 + pid.Iout = pid.Ki * pid.SEk; // 积分输出 // td=pid.Td/pid.t; // kd=pid.Kp*td; - pid.Dout = kd * DelEk; // 微分输出 + pid.Dout = pid.Kd * DelEk; // 微分输出 if (pid.Dout < 0) { pid.Dout = 0 - pid.Dout; @@ -82,39 +84,38 @@ void PID_Calc() // pid if (pid.set_tem > pid.now_tem + 1) { - // 得到当前的偏差值,设置温度大于实际温度1℃,加热,关闭压缩机,打开加热棒 - /*GPIO1->报警铃 GPIO6->压缩机 GPIO3->加热棒 GPIO4—>新风风扇 GPIO5->加湿器 */ - // HC595_Send_Byte(gpio_state&=0xDF);//关闭压缩机 &=1101 1111 0xDF + // 得到当前的偏差值,设置温度大于实际温度1℃,加热,close compressor,open heater + /*GPIO1->报警铃 GPIO3->heater GPIO4—>新风风扇 GPIO5->加湿器 GPIO6->compressor */ + HC595_Send_Byte(gpio_state &= 0xDF);//close compressor &=1101 1111 0xDF TIM_SetCompare3(TIM3, 0); - HC595_Send_Byte(gpio_state |= 0x04); // 打开加热棒 |=0000 0100 0x04 + HC595_Send_Byte(gpio_state |= 0x04); // open heater |=0000 0100 0x04 hot_clod_flag = 2; pid.Iout = 0; - } - if (pid.now_tem > pid.set_tem) + } else if (pid.now_tem > pid.set_tem) { - // 得到当前的偏差值,设置温度小于实际温度,制冷,打开压缩机,关闭加热棒 - HC595_Send_Byte(gpio_state &= 0xFB); // 关闭加热棒 &=1111 1011 0xFB - num = (((pid.OUT * 400) / pid.pwmcycle) - 1); // 请问这个pid.OUT与pwm占空比的值是如何换算过来的 - TIM_SetCompare3(TIM3, num); - // printf("%d\r\n",num); + // 得到当前的偏差值,设置温度小于实际温度,制冷,open compressor,close heater + HC595_Send_Byte(gpio_state &= 0xFB); // close heater &=1111 1011 0xFB // 0-200对应0-100%,如果pid.out=50,占空比就是25%,//num=50*400/200=100,100/400=25% - // HC595_Send_Byte(gpio_state|=0x20);//打开压缩机 |=0010 0000 + // TODO:: change maxinum from 400 to 300 + num = (((pid.OUT * 400) / pid.pwmcycle) - 1); // pid.OUT与pwm占空比的值换算 + TIM_SetCompare3(TIM3, num / 4); + // printf("%d\r\n",num); + HC595_Send_Byte(gpio_state|=0x20);//open compressor |=0010 0000 hot_clod_flag = 1; // pid.Iout=0; } if (hot_clod_flag == 1 && T <= tem - 3) // 制冷过程中温度下降低于设定温度0.3℃ { - // HC595_Send_Byte(gpio_state&=0xDB);//关闭压缩机 关闭加热棒 &=1101 1101 0xDB - TIM_SetCompare3(TIM3, 0); // 关闭压缩机 - HC595_Send_Byte(gpio_state &= 0xFB); // 关闭加热棒 + HC595_Send_Byte(gpio_state&=0xDB);// close compressor and heater &=1101 1011 0xDB + TIM_SetCompare3(TIM3, 0); // close compressor hot_clod_flag = 0; } - if (hot_clod_flag == 2 && T >= tem) + if (hot_clod_flag == 2 && T >= tem) // while heat, T above tem { - // HC595_Send_Byte(gpio_state&=0xDB);//关闭压缩机 关闭四通阀 &=1101 1101 0xDB - TIM_SetCompare3(TIM3, 0); // 关闭压缩机 - HC595_Send_Byte(gpio_state &= 0xFB); // 关闭加热棒 + HC595_Send_Byte(gpio_state&=0xDB);//close compressor and heater &=1101 1011 0xDB + TIM_SetCompare3(TIM3, 0); // close compressor hot_clod_flag = 0; } + // HC595_Send_Byte(gpio_state&=0xDB);// close compressor and heater &=1101 1011 0xDB } diff --git a/HARDWARE/PID.h b/HARDWARE/PID.h index e40e542..558c111 100644 --- a/HARDWARE/PID.h +++ b/HARDWARE/PID.h @@ -9,10 +9,12 @@ typedef struct Pid float set_tem;//用户设定值 float now_tem;//当前温度 - float Kp; + float Kp; // 110 int t; //PID计算周期--采样周期 float Ti; - float Td; + float Td; + float Ki; // 0.001 + float Kd; // 340 float Ek; //本次偏差 float Ek_1;//上次偏差 diff --git a/HARDWARE/rs485.c b/HARDWARE/rs485.c index 2b7a496..bf0fb83 100644 --- a/HARDWARE/rs485.c +++ b/HARDWARE/rs485.c @@ -4,8 +4,8 @@ #include "Relays.h" #include "myfreertos.h" -u8 sendbuf[29] = {0xEE, 0xB5, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF}; // 发送给串口屏的实时数据 +u8 sendbuf[37] = {0xEE, 0xB5, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFF}; // 发送给串口屏的实时数据 u8 sendbuf_crc[20] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; extern u8 global_buffer[64]; @@ -45,6 +45,7 @@ u8 crc_num2 = 0xFF; extern int T; extern int H; extern int C; +extern PID pid; // extern u16 RED_LIGHT; // extern u16 WHITE_LIGHT; // extern u16 BLUE_LIGHT; @@ -366,10 +367,10 @@ void RS485_1_Send_Data_2(void) // sendbuf[0] = 0xEE; sendbuf[1] = 0xB5; sendbuf[2] = 0x05; - sendbuf[25] = 0xFF; - sendbuf[26] = 0xFC; - sendbuf[27] = 0xFF; - sendbuf[28] = 0xFF; + sendbuf[33] = 0xFF; + sendbuf[34] = 0xFC; + sendbuf[35] = 0xFF; + sendbuf[36] = 0xFF; u8 a; RS485_1_TX_EN = 1; // 设置为发送模式 if (T <= 500000) @@ -419,20 +420,30 @@ void RS485_1_Send_Data_2(void) // sendbuf[14] = CO2_2; if (now_stage < 7 && total[3 + 18 * (now_stage - 1)] < 24 && total[4 + 18 * (now_stage - 1)] < 60 && chour < 24 && cminute < 60) { - sendbuf[15] = now_stage; // 当前阶段 - sendbuf[16] = total[3 + 18 * (now_stage - 1)]; // 阶段小时 - sendbuf[17] = total[4 + 18 * (now_stage - 1)]; // 阶段分钟 - sendbuf[18] = chour; // 已运行小时数 - sendbuf[19] = cminute; // 已运行分钟数 + sendbuf[15] = now_stage; // current state + sendbuf[16] = total[3 + 18 * (now_stage - 1)]; // stage hour + sendbuf[17] = total[4 + 18 * (now_stage - 1)]; // stage minute + sendbuf[18] = chour; // run hour + sendbuf[19] = cminute; // run minute } - sendbuf[20] = hot_clod_flag; // 加热制冷状态 - sendbuf[21] = humidity_flag; // 加湿干燥状态 - sendbuf[22] = ALARM; // 报警状态状态 - - bufcut_Init(sendbuf_crc, sendbuf, 3, 23); - GetCRC16(sendbuf_crc, 20, &crc_num1, &crc_num2); - sendbuf[23] = crc_num1; - sendbuf[24] = crc_num2; + sendbuf[20] = hot_clod_flag; // hot clod state + sendbuf[21] = humidity_flag; // humidity state + sendbuf[22] = ALARM; // ALARM state + + sendbuf[23] = (int)pid.Kp / 256; // Kp 110 + sendbuf[24] = (int)pid.Kp % 256; // Kp 110 + sendbuf[25] = ((int)(pid.Ki * 100000)) / 256; // Ti 0.001 + sendbuf[26] = ((int)(pid.Ki * 100000)) % 256; // Ti 0.001 + sendbuf[27] = (int)pid.Kd / 256; // Td 340 + sendbuf[28] = (int)pid.Kd % 256; // Td 340 + // num = (((pid.OUT * 350) / pid.pwmcycle) - 1); + sendbuf[29] = ((int)(pid.OUT * 1000)) / 256; + sendbuf[30] = ((int)(pid.OUT * 1000)) % 256; + + bufcut_Init(sendbuf_crc, sendbuf, 3, 31); + GetCRC16(sendbuf_crc, 28, &crc_num1, &crc_num2); + sendbuf[31] = crc_num1; + sendbuf[32] = crc_num2; // for(int i=0;i<20;i++) // { // printf("%x ",sendbuf_crc[i]); @@ -446,7 +457,7 @@ void RS485_1_Send_Data_2(void) // // } // printf("%x\r\n",sendbuf[0]); - for (a = 0; a < 29; a++) // 循环发送数据 + for (a = 0; a < 37; a++) // 循环发送数据 { while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) ; diff --git a/OBJ/LED.axf b/OBJ/LED.axf index 345a2c8ed0a94d5ca09e7f4c888e38ed44187065..1627dee8e81c64b8a0d382120903370e87405da2 100644 GIT binary patch delta 38206 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