#include "myfreertos.h" #define SENSOR_ADDRESS 0x02 char pubTopic[512] = "/sys/hp8oQhMZJ67/Device1/thing/event/property/post"; // Publish topic char subTopic[512] = "/sys/hp8oQhMZJ67/Device1/thing/service/property/set"; // Subscribe topic #define MQTT_SOCK 5 // task priority #define START_TASK_PRIO 0 // Task stack size #define START_STK_SIZE 128 // task handle TaskHandle_t StartTask_Handler; // task function void start_task(void *pvParameters); // task priority #define Sensor_Communication_TASK_PRIO 1 // Communication with sensors // Task stack size #define Sensor_Communication_STK_SIZE 512 // task handle TaskHandle_t Sensor_CommunicationTask_Handler; // task function void Sensor_Communication_task(void *pvParameters); void Host_Computer_Communication(void); // 10seconds delay #define SENSOR_DATA_REQUEST_PERIOD pdMS_TO_TICKS(5000) // 60seconds delay #define SYNC_ENVIRONMENT_DATA_REQUEST_PERIOD pdMS_TO_TICKS(60000) /** * sensor data request: 02 03 */ void SensorDataRequestTask(void *pvParameters); /** * sync environment data: EE B5 01 */ void SyncEnvironmentDataRequestTask(void *pvParameters); int isZeros(u8 arr[]); u8 RS485_RX_BUF_COPY[128] = {0}; u8 cnt_flag = 0, sub_flag = 0, pub_flag = 0; u16 time = 0; // Record the time of pinging the server char wet_temp[256]; // Cache area for subscription and publication of messages u8 store_stage = 1; // Write the stage number of the flash, and after a power outage and restart, it can run immediately following the previous stage and status extern PID pid; extern float kd; extern float ki; u8 batch_sync_buf[11]; // Array obtained by single synchronous cutting u8 ins_1 = 0; int diff = 0; u8 gpio_state = 0x00; // relay status u8 NUM = 1; // 批量同步发送的阶段号 u8 n; // 阶段号 u16 i; // 序列号 u8 chour; // 已运行小时数 u8 cminute; // 运行分钟数 u8 hot_clod_flag = 0; // 加热制冷标志位。hot_clod_flag=0, 不加热不制冷;hot_clod_flag=2,加热;hot_clod_flag=1,制冷 u8 humidity_flag = 0; // 加湿除湿标志位。 humidity_flag=0,不加湿不除湿; humidity_flag=2,加湿; humidity_flag=1,除湿 u8 ALARM = 0; // 报警标志位。ALARM=0,不报警;ALARM=1,报警 u16 tick = 0; // tick大于600,触发报警条件会报警;小于600则不报警 u8 Feed_Dog_Count = 0; // Feeding dog timing u8 now_stage = 1; // Current operational phase u16 tem, hum, red, blue, white; u8 hour, min; u8 rs485buf[8] = {SENSOR_ADDRESS, 0x03, 0x00, 0x01, 0x00, 0x09, 0xD4, 0x3F}; // Sensor exchange data u16 sync_cnt = 0; // 同步环境控制参数的计数器,到0同步 int T = 0, H = 0, C = 0, G = 0, current_T = 0; extern u8 total[]; float Humidity = 0; float temperature = 0; // pages in hmi #define page_index 43 #define page_curve 45 #define page_setting 46 #define page_upgrade 23 #define page_scan_wifi 48 #define page_wifi_setting 49 #define page_param_adjust 50 #define page_status 51 // u8 RS485_RX_BUF[64]; /********************* ********************** entry function ********************** *********************/ void os_init(void) { // printf("Entry function call successful\r\n"); xTaskCreate((TaskFunction_t)start_task, (char *)"start_task", (uint16_t)START_STK_SIZE, (void *)NULL, (UBaseType_t)START_TASK_PRIO, (TaskHandle_t *)&StartTask_Handler); // 创建传感器数据请求任务 xTaskCreate(SensorDataRequestTask, "SensorDataRequestTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); xTaskCreate(SyncEnvironmentDataRequestTask, "SyncEnvironmentDataRequestTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, NULL); vTaskStartScheduler(); } /********************* ********************** Create handles for tasks, queues, signal sets, etc., which can also be tested using ********************** *********************/ BaseType_t handler = 0; BaseType_t handler1 = 0; BaseType_t handler2 = 0; BaseType_t handler3 = 0; BaseType_t handler4 = 0; BaseType_t handler5 = 0; BaseType_t handler6 = 0; BaseType_t handler7 = 0; BaseType_t handler8 = 0; BaseType_t handler9 = 0; BaseType_t handler10 = 0; BaseType_t handler11 = 0; /* Start function: Create other functions and timers */ void start_task(void *pvParameters) { taskENTER_CRITICAL(); // 进入临界区 // 创建与传感器通信任务 handler = xTaskCreate((TaskFunction_t)Sensor_Communication_task, (const char *)"Sensor_Communication_task", (uint16_t)Sensor_Communication_STK_SIZE, (void *)NULL, (UBaseType_t)Sensor_Communication_TASK_PRIO, (TaskHandle_t *)&Sensor_CommunicationTask_Handler); // if(handler==pdPASS){printf("与传感器通信任务创建成功\r\n");} // else{printf("与传感器通信任务创建失败\r\n");} // //创建控灯任务 // handler4=xTaskCreate((TaskFunction_t )led_task, // (const char* )"led_task", // (uint16_t )LED_STK_SIZE, // (void* )NULL, // (UBaseType_t )LED_TASK_PRIO, // (TaskHandle_t* )&LEDTask_Handler); // if(handler4==pdPASS){printf("控灯任务创建成功\r\n");} // else{printf("控灯任务创建失败\r\n");} vTaskDelete(StartTask_Handler); // 删除开始任务 taskEXIT_CRITICAL(); // 退出临界区 } void SensorDataRequestTask(void *pvParameters) { while (1) { // 发送传感器数据请求的操作 RS485_1_Send_Data_1(rs485buf, 8); vTaskDelay(SENSOR_DATA_REQUEST_PERIOD); } } void SyncEnvironmentDataRequestTask(void *pvParameters) { while (1) { // 发送传感器数据请求的操作 RS485_1_Send_Data_3(); vTaskDelay(SYNC_ENVIRONMENT_DATA_REQUEST_PERIOD); } } u8 temp[4] = {0xaa,0xbb,0xcc,0xdd}; void Sensor_Communication_task(void *pvParameters) { while (1) { // cnt_flag=do_mqtt(MQTT_SOCK,NET_CONFIG.rip,1883,5500); // Humidity=H*0.1; // temperature=T*0.1; // delay_ms(50); // sprintf(wet_temp,"{\"method\":\"thing.event.property.post\",\"params\":{\"Humidity\":%.2f,\"temperature\":%.2f,\"CO2\":%d,\"red_light\":%d,\"white_light\":%d,\"blue_light\":%d},\"version\":\"1.0.0\"}",Humidity,temperature,C,red/10,white/10,blue/10); //构建数据 // //sprintf(wet_temp,"{\"method\":\"thing.event.property.post\",\"params\":{\"Humidity\":%.2f,\"temperature\":%.2f,\"CO2\":%d},\"version\":\"1.0.0\"}",Humidity,temperature,C); //构建数据 // if(cnt_flag==0){sub_flag=0;pub_flag=0;time=0;} // if(cnt_flag&&sub_flag==0)sub_flag=!subscribMqtt(MQTT_SOCK,subTopic); // if(cnt_flag&&sub_flag&&pub_flag==0)pub_flag=!publishMqtt(MQTT_SOCK,pubTopic,wet_temp); // if(cnt_flag)time++; // if(time==50){ // time=0; // pingMqtt(MQTT_SOCK); // } now_stage = timelong_Compare(); // // printf("%d %d\r\n",chour,cminute); Array(&now_stage, &hour, &min, &tem, &hum, &red, &blue, &white); // 更新对应阶段号的参数 printf("current stage: %d\r\n",now_stage); // RS485_1_Send_Data_1(rs485buf, 8); //(RS485_RX_CNT=0已被注释) // delay_xms(50); // // RX_BUF_Printf(128); // if (sync_cnt <= 0) // { // RS485_1_Send_Data_3(); // sync_cnt = 10; // } // else // { // sync_cnt--; // } delay_xms(50); // RX_BUF_Printf(128); bufcut_Init(RS485_RX_BUF_COPY, RS485_RX_BUF, 0, 128); RS485_RX_CNT = 0; while (isAllZeros(RS485_RX_BUF_COPY, 128) == 0) { if (RS485_RX_BUF_COPY[0] == 0x02 && RS485_RX_BUF_COPY[1] == 0x03 && CRC16_check(RS485_RX_BUF_COPY, 21) == 1) { // receive message from sensor u8 temp_data[23] = {0}; for (int i=0;i<23;i++) { temp_data[i] = RS485_RX_BUF_COPY[i]; } process_sensor_data(temp_data); RX_BUF_Transfer(0, 23); } else if (RS485_RX_BUF_COPY[0] == 0xEE && RS485_RX_BUF_COPY[1] == 0xB6 && RS485_RX_BUF_COPY[2] == 0x01) { // batch update params in a stage // total length: 22 if (CRC16_check(RS485_RX_BUF_COPY, 16) == 1) { Batch_synchronization(&n, RS485_RX_BUF_COPY); Array(&now_stage, &hour, &min, &tem, &hum, &red, &blue, &white); // update param correspond to current stage } RX_BUF_Transfer(0, 22); } else if (RS485_RX_BUF_COPY[0] == 0xEE && RS485_RX_BUF_COPY[1] == 0xB6 && RS485_RX_BUF_COPY[2] == 0x03) { // update single environment param // total length: 13 if (CRC16_check(RS485_RX_BUF_COPY, 7) == 1) { Analysis(&n, &i, RS485_RX_BUF_COPY); Array(&now_stage, &hour, &min, &tem, &hum, &red, &blue, &white); // update param correspond to current stage Write_Init(); } RX_BUF_Transfer(0, 13); } else if (RS485_RX_BUF_COPY[0] == 0xEE && RS485_RX_BUF_COPY[1] == 0xB6 && RS485_RX_BUF_COPY[2] == 0x04) { // change running stage // total length: 10 if (CRC16_check(RS485_RX_BUF_COPY, 4) == 1) { int target_stage = RS485_RX_BUF_COPY[3]; RTC_synchronization_ins(2023, 9, 1, 0, 00, 00); now_stage = target_stage; store_stage = target_stage; Write_Init(); } RX_BUF_Transfer(0, 10); } else if (RS485_RX_BUF_COPY[0] == 0xEE && RS485_RX_BUF_COPY[1] == 0xB6 && RS485_RX_BUF_COPY[2] == 0x05) { // change pid params // total length: 12 if (CRC16_check(RS485_RX_BUF_COPY, 6) == 1) { int param_index = RS485_RX_BUF_COPY[3]; switch(param_index) { case 0x01: { pid.Kp = RS485_RX_BUF_COPY[4] * 256.0 + RS485_RX_BUF_COPY[5]; break; } case 0x02: { pid.Ki = (RS485_RX_BUF_COPY[4] * 256.0 + RS485_RX_BUF_COPY[5]) / 100000.0; break; } case 0x03: { pid.Kd = RS485_RX_BUF_COPY[4] * 256.0 + RS485_RX_BUF_COPY[5]; break; } } Write_Init(); } RX_BUF_Transfer(0, 12); } else if (RS485_RX_BUF_COPY[0] == 0xEE && RS485_RX_BUF_COPY[1] == 0xB1 && RS485_RX_BUF_COPY[2] == 0x11 && RS485_RX_BUF_COPY[15] == 0xFF && RS485_RX_BUF[16] == 0xFF) { RX_BUF_Transfer(0, 17); } else if (RS485_RX_BUF_COPY[0] == 0xEE && RS485_RX_BUF_COPY[1] == 0xB1 && RS485_RX_BUF_COPY[2] == 0x11 && RS485_RX_BUF_COPY[14] == 0xFF && RS485_RX_BUF[15] == 0xFF) { RX_BUF_Transfer(0, 16); } else if (RS485_RX_BUF_COPY[0] == 0xEE && RS485_RX_BUF_COPY[1] == 0xB1 && RS485_RX_BUF_COPY[2] == 0x11 && RS485_RX_BUF_COPY[12] == 0xFF && RS485_RX_BUF[13] == 0xFF) { // btn down or up process_hmi_btn_event(RS485_RX_BUF_COPY[3] * 256 + RS485_RX_BUF_COPY[4], RS485_RX_BUF_COPY[5] * 256 + RS485_RX_BUF_COPY[6], RS485_RX_BUF_COPY[9]); RX_BUF_Transfer(0, 14); } else if (RS485_RX_BUF_COPY[0] == 0xEE && RS485_RX_BUF_COPY[1] == 0xB1 && RS485_RX_BUF_COPY[2] == 0x01 && RS485_RX_BUF_COPY[7] == 0xFF && RS485_RX_BUF_COPY[8] == 0xFF) { RX_BUF_Transfer(0, 9); } else { int ZERO_Count = 0; if ((RS485_RX_BUF_COPY[0] != 0x00)) { RX_BUF_Transfer(0, 1); } while (RS485_RX_BUF_COPY[ZERO_Count] == 0x00) { ZERO_Count++; } RX_BUF_Transfer(0, ZERO_Count); } } if (red <= 1000 && blue <= 1000) { PWM_SetCompare1((red / 100.0 * 3.5 + 28)); // J9 PWM_SetCompare2((blue / 100.0 * 3.5 + 28)); // J11 PWM_SetCompare4((white / 100.0 * 3.5 + 28)); // J10 } RS485_RX_CNT = 0; } } /** * process sensor data */ void process_sensor_data(u8 *data) { T = data[3]; T = T << 8 | data[4]; // Negative temperature treatment if (T & 0x8000) { T = ((~T + 1) & 0xFFFF); } H = data[5]; H = H << 8 | data[6]; C = data[19]; C = C << 8 | data[20]; /*GPIO1->报警铃 GPIO3->加热棒 GPIO4—>新风风扇 GPIO5->加湿器 GPIO6->压缩机 */ if ((T < (tem - 20) || T > (tem + 20) || H < (hum - 100) || H > (hum + 100)) && (tick > 600)) // 温度偏差2℃报警,湿度偏差10报警 { // HC595_Send_Byte(gpio_state |= 0x01); // 打开报警铃 GPIO1->PB1 |=0000 0001 0x01 gpio_state |= 0x01; ALARM = 1; } else { // HC595_Send_Byte(gpio_state &= 0xFE); // 关闭报警铃 &=1111 1110 0xFE gpio_state &= 0xFE; ALARM = 0; } if (T < 600 && T > -400) { diff = current_T - T; if (diff < 0) diff = -diff; if (diff < 3 || current_T == 0) // 最近两次温差相差0.3℃,消除传感器感应出错的影响 { pid.set_tem = tem / 10.0; pid.now_tem = T / 10.0; PID_Calc(); // send sign to 485 // out: 0-200 // num=(((pid.OUT*400)/pid.pwmcycle)-1);//请问这个pid.OUT与pwm占空比的值是如何换算过来的 // TIM_SetCompare3(TIM3,num); // TIM_SetCompare3(TIM3,0.845*num); // printf("%d\r\n",num); // 0-200对应0-100%,如果pid.out=50,占空比就是25%,//num=50*400/200=100,100/400=25% // printf("%d ,%d ,%d ,%d ,%f ,%f ,%f ,%f ,%f ,%f ,%f ,%.3f\r\n",T,H,C,num,(pid.set_tem*10),pid.Kp,ki,kd,pid.Pout,pid.Iout,pid.Dout,num/399.0); current_T = T; } } if (H > (hum + 50)) // 湿度高于设定值5,打开新风风扇 GPIO4->PD1 { // HC595_Send_Byte(gpio_state |= 0x08); // 打开新风风扇 |=0000 1000 0x08 gpio_state |= 0x08; // HC595_Send_Byte(gpio_state &= 0xEF); // 关闭加湿器 &=1110 1111 0xEF gpio_state &= 0xEF; humidity_flag = 1; // 除湿 } if (H < (hum - 50)) // 湿度低于设定值5,打开加湿器 GPIO5->PD0 { // HC595_Send_Byte(gpio_state |= 0x10); // 启动加湿器 |=0001 0000 0x10 gpio_state |= 0x10; // HC595_Send_Byte(gpio_state &= 0xF7); // 关闭风扇 &=1111 0111 0xF7 gpio_state &= 0xF7; humidity_flag = 2; } if (humidity_flag == 1 && H <= hum) { // HC595_Send_Byte(gpio_state &= 0xE7); // 关闭风扇 关闭加湿器 &=1110 0111 0xE7 gpio_state &= 0xE7; humidity_flag = 0; } if (humidity_flag == 2 && H >= hum) { // HC595_Send_Byte(gpio_state &= 0xE7); // 关闭加湿器 关闭风扇 &=1110 0111 0xE7 gpio_state &= 0xE7; humidity_flag = 0; } HC595_Send_Byte(gpio_state); RS485_1_Send_Data_2(); // 上传参数 delay_xms(200); } /** * hmi event process */ void process_hmi_btn_event(u8 page, u8 btn_index, u8 value) { switch(page) { case page_param_adjust: { // change current stage if (btn_index >= 45 && btn_index <= 50 && value == 0x01) { int target_stage = btn_index - 44; RTC_synchronization_ins(2023, 9, 1, 0, 00, 00); now_stage = target_stage; store_stage = target_stage; Write_Init(); } break; } } } // void Host_Computer_Communication(void) //{ // if(RS485_RX_BUF_COPY[0]==0xEE&&RS485_RX_BUF_COPY[1]==0xB6) // { // if(RS485_RX_BUF_COPY[2]==0x03)//单个同步 // { // Analysis(&n,&i,RS485_RX_BUF_COPY); // //printf("B6 03 cmd: batch sync\r\n"); // Array(&now_stage,&hour,&min,&tem,&hum,&red,&blue,&white);//更新对应阶段号的参数 // Write_Init(); // RX_BUF_Transfer(0,11); // // } // if(RS485_RX_BUF_COPY[2]==0x04)//阶段切换 // { // change_stage_rev1=RS485_RX_BUF_COPY[3]; // //printf("B6 04 cmd: change stage\r\n"); // RTC_synchronization_ins(2023,9,1,0,00,00); // now_stage=change_stage_rev1; // store_stage=change_stage_rev1; // Write_Init(); // RX_BUF_Transfer(0,8); // } // if(RS485_RX_BUF_COPY[2]==0x01)//批量同步 // { // Batch_synchronization(&n,RS485_RX_BUF_COPY); // //printf("B6 01 cmd: get one %d\r\n", n); // Array(&now_stage,&hour,&min,&tem,&hum,&red,&blue,&white);//更新对应阶段号的参数 // //Write_Init();减少擦写的次数 // RX_BUF_Transfer(0,20); // } // } // else if(RS485_RX_BUF_COPY[0]==0xEE&&RS485_RX_BUF_COPY[1]==0xB1) // { // if(RS485_RX_BUF_COPY[2]==0x11&&RS485_RX_BUF_COPY[15]==0xFF&&RS485_RX_BUF[16]==0xFF)//单个同步默认带的数据 // { // //printf("cut overdata of B6 03 \r\n"); // RX_BUF_Transfer(0,17); // } // if(RS485_RX_BUF_COPY[2]==0x11&&RS485_RX_BUF_COPY[14]==0xFF&&RS485_RX_BUF[15]==0xFF)//单个同步默认带的数据 // { // //printf("cut overdata of B6 03 \r\n"); // //RX_BUF_Printf(128); // RX_BUF_Transfer(0,16); // //RX_BUF_Printf(128); // } // if(RS485_RX_BUF_COPY[2]==0x11&&RS485_RX_BUF_COPY[12]==0xFF&&RS485_RX_BUF_COPY[13]==0xFF)//阶段切换默认带的数据 // { // //printf("cut overdata of B6 04 \r\n"); // //RX_BUF_Printf(128); // RX_BUF_Transfer(0,14); // } // if(RS485_RX_BUF_COPY[2]==0x01&&RS485_RX_BUF_COPY[7]==0xFF&&RS485_RX_BUF_COPY[8]==0xFF)//上位机默认带的数据 // { // //printf("cut overdata of Upper computer \r\n"); // //RX_BUF_Printf(128); // RX_BUF_Transfer(0,9); // //RX_BUF_Printf(128); // // } // } // else // { // //int ZERO_Count=0; // //if()与while()的顺序不能变 //// if((RS485_RX_BUF_COPY[0]!=0x00))//不为0,处理掉 //// { //// RX_BUF_Transfer(0,1); //// //printf("the number is no zero\r\n"); //// } //// //// while(RS485_RX_BUF_COPY[ZERO_Count]==0x00) //// { //// ZERO_Count++; //// } //// RX_BUF_Transfer(0,ZERO_Count); // // RX_BUF_Transfer(0,1); // //printf("previous array cut\r\n"); // } //}