You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
486 lines
18 KiB
486 lines
18 KiB
|
|
#include <stdbool.h> //定义布尔
|
|
#include <string.h>
|
|
|
|
#include "board.h"
|
|
//
|
|
#include "zes8p5066lib/basic.h"
|
|
#include "zes8p5066lib/gpio.h"
|
|
#include "zes8p5066lib/key.h"
|
|
#include "zes8p5066lib/systicket.h"
|
|
#include "zes8p5066lib/uart0.h"
|
|
//
|
|
#include "service/human_computer_interaction_service.h"
|
|
#include "service/ozone_control_service.h"
|
|
#include "service/thisdevice.h"
|
|
#include "test.h"
|
|
#include "zsimple_timer/zsimple_timer.h"
|
|
|
|
/***********************************************************************************************************************
|
|
* =====================================================函数声明====================================================== *
|
|
***********************************************************************************************************************/
|
|
void onkey(zkey_t* key, zkey_state_t key_state);
|
|
/***********************************************************************************************************************
|
|
* =====================================================全局变量====================================================== *
|
|
***********************************************************************************************************************/
|
|
static zkey_t s_keys[] = {
|
|
ZKEY_INIT("powerkey", port_gpio_get_power_key_state), //电源按键
|
|
ZKEY_INIT("levelkey", port_gpio_get_level_key_state), //左1
|
|
ZKEY_INIT("timerkey", port_gpio_get_timer_key_state), //左2
|
|
ZKEY_INIT("intervalkey", port_gpio_get_interval_key_state), //左3
|
|
};
|
|
zkey_module_t key_module = ZMODULE_INIT(s_keys, onkey);
|
|
static int m_fanerronum = 0;
|
|
|
|
/***********************************************************************************************************************
|
|
* =======================================================方法======================================================== *
|
|
***********************************************************************************************************************/
|
|
static float mf_fan_get_power() {
|
|
float fanpower = 0;
|
|
for (size_t i = 0; i < 20; i++) {
|
|
fanpower += port_adc_get_fan_power();
|
|
}
|
|
return fanpower / 20;
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* ===================================================COUNT_COMPUTE=================================================== *
|
|
***********************************************************************************************************************/
|
|
static uint32_t compute_countdown_num(int countdowns) { return countdowns / kconst_countdown_step_s + !!(countdowns % kconst_countdown_step_s); }
|
|
|
|
static void increase_and_assign_countdonwnum() {
|
|
if (thisDevice.countdonwnum == 4) {
|
|
thisDevice.countdonwnum = 0;
|
|
thisDevice.countdonwnum_s = 0;
|
|
thisDevice.countdonw_setting_num = 0;
|
|
} else {
|
|
thisDevice.countdonwnum_s = (thisDevice.countdonwnum + 1) * kconst_countdown_step_s;
|
|
thisDevice.countdonwnum = thisDevice.countdonwnum + 1;
|
|
thisDevice.countdonw_setting_num = thisDevice.countdonwnum;
|
|
thisDevice.countdonw_start_ticket = systicket_get_now_ms();
|
|
}
|
|
}
|
|
|
|
static void mf_set_countdown(int countdownnum) {
|
|
thisDevice.countdonwnum = countdownnum;
|
|
thisDevice.countdonwnum_s = thisDevice.countdonwnum * kconst_countdown_step_s;
|
|
thisDevice.countdonw_setting_num = thisDevice.countdonwnum;
|
|
thisDevice.countdonw_start_ticket = systicket_get_now_ms();
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* ===================================================POWER_CONTROL=================================================== *
|
|
***********************************************************************************************************************/
|
|
//设备开始工作
|
|
static void startwork() {
|
|
port_fan_set(true);
|
|
ozone_control_start();
|
|
thisDevice.working = true;
|
|
m_fanerronum = 0;
|
|
}
|
|
//停止设备工作
|
|
static void stopwork() {
|
|
ozone_control_stop();
|
|
port_fan_set(false);
|
|
thisDevice.working = false;
|
|
}
|
|
//关机
|
|
static void shutdwon() {
|
|
printf("power off\n");
|
|
thisDevice.poweron = false;
|
|
stopwork();
|
|
}
|
|
//开机
|
|
static void poweron() {
|
|
printf("power on\n");
|
|
thisDevice.poweron = true;
|
|
thisDevice.level = klevel2;
|
|
thisDevice.mode = knormal;
|
|
thisDevice.error = knoneException;
|
|
startwork();
|
|
}
|
|
|
|
/***********************************************************************************************************************
|
|
* =================================================KEY_EVENT_PROCESS================================================= *
|
|
***********************************************************************************************************************/
|
|
//电源按键处理
|
|
static void mf_process_poweron_key(zkey_t* key) {
|
|
printf("on %s \n", key->name);
|
|
if (!thisDevice.poweron) {
|
|
poweron();
|
|
} else {
|
|
shutdwon();
|
|
}
|
|
return;
|
|
}
|
|
//等级按键处理
|
|
static void mf_process_level_key(zkey_t* key) {
|
|
if (!thisDevice.poweron) return;
|
|
if (thisDevice.error != knoneException) return;
|
|
|
|
printf("on %s \n", key->name);
|
|
/**
|
|
* @brief 当前在不在修改状态,不在,则进入修改状态
|
|
*/
|
|
if (thisDevice.level == klevel1) {
|
|
printf("changet level to level2\n");
|
|
thisDevice.level = klevel2;
|
|
//更改臭氧状态
|
|
} else if (thisDevice.level == klevel2) {
|
|
printf("changet level to level1\n");
|
|
thisDevice.level = klevel1;
|
|
//更改臭氧状态
|
|
}
|
|
hcis_active_input(kchange_level_input);
|
|
return;
|
|
}
|
|
//定时按键处理
|
|
static void mf_process_timer_key(zkey_t* key) {
|
|
if (!thisDevice.poweron) return;
|
|
if (thisDevice.error != knoneException) return;
|
|
|
|
printf("on %s \n", key->name);
|
|
if (!thisDevice.working) {
|
|
startwork();
|
|
}
|
|
if (thisDevice.mode != ktimingMode) {
|
|
mf_set_countdown(0);
|
|
}
|
|
increase_and_assign_countdonwnum();
|
|
if (thisDevice.countdonwnum_s == 0) {
|
|
hcis_active_input(knone_active);
|
|
thisDevice.mode = knormal;
|
|
} else {
|
|
hcis_active_input(kchange_countdonw_time_input);
|
|
thisDevice.mode = ktimingMode;
|
|
}
|
|
}
|
|
//间隔按键处理
|
|
static void mf_process_interval_key(zkey_t* key) {
|
|
if (!thisDevice.poweron) return;
|
|
if (thisDevice.error != knoneException) return;
|
|
printf("on %s \n", key->name);
|
|
if (!thisDevice.working) {
|
|
startwork();
|
|
}
|
|
if (thisDevice.mode != kintermittentMode) {
|
|
mf_set_countdown(0);
|
|
}
|
|
increase_and_assign_countdonwnum();
|
|
if (thisDevice.countdonwnum_s == 0) {
|
|
hcis_active_input(knone_active);
|
|
thisDevice.mode = knormal;
|
|
} else {
|
|
hcis_active_input(kchange_intermittentmode_time_input);
|
|
thisDevice.mode = kintermittentMode;
|
|
}
|
|
}
|
|
|
|
static void onkey(zkey_t* key, zkey_state_t key_state) {
|
|
if /* */ (strcmp(key->name, "powerkey") == 0 && zks_rising_edge == key_state) {
|
|
mf_process_poweron_key(key);
|
|
} else if (strcmp(key->name, "levelkey") == 0 && zks_rising_edge == key_state) {
|
|
mf_process_level_key(key);
|
|
} else if (strcmp(key->name, "timerkey") == 0 && zks_rising_edge == key_state) {
|
|
mf_process_timer_key(key);
|
|
} else if (strcmp(key->name, "intervalkey") == 0 && zks_rising_edge == key_state) {
|
|
mf_process_interval_key(key);
|
|
}
|
|
}
|
|
/***********************************************************************************************************************
|
|
* ===============================================THIS_MODULE_SCHEDULE================================================ *
|
|
***********************************************************************************************************************/
|
|
static void mf_try_autoshutdown() {
|
|
if (thisDevice.poweron) {
|
|
if (thisDevice.countdonwnum_s == 0) {
|
|
shutdwon();
|
|
}
|
|
}
|
|
}
|
|
|
|
static void mf_try_autostop() {
|
|
//间歇模式下,定时到达定时时间,停止工作
|
|
if (thisDevice.countdonwnum_s == 0) stopwork();
|
|
}
|
|
|
|
static void mf_try_auto_restart() {
|
|
//间歇模式下,设备工作一定时间后,休息一定时间
|
|
|
|
DO_IT_EACH_MS(3000) {
|
|
printf("try auto restart [%d->%d]\n",
|
|
systicket_haspassedms(thisDevice.countdonw_start_ticket) / 1000 - thisDevice.countdonw_setting_num * kconst_countdown_step_s,
|
|
thisDevice.countdonw_setting_num * kconst_countdown_step_s);
|
|
}
|
|
END();
|
|
|
|
if (systicket_haspassedms(thisDevice.countdonw_start_ticket) / 1000 > //
|
|
(/*设备工作时间:*/ thisDevice.countdonw_setting_num * kconst_countdown_step_s + //
|
|
/*设备休息时间*/ thisDevice.countdonw_setting_num * kconst_countdown_step_s)) {
|
|
mf_set_countdown(thisDevice.countdonw_setting_num);
|
|
startwork();
|
|
}
|
|
}
|
|
|
|
static void mf_update_countdown() {
|
|
if /* */ (thisDevice.mode == knormal) {
|
|
thisDevice.countdonwnum = 0;
|
|
thisDevice.countdonwnum_s = 0;
|
|
} else if (thisDevice.mode == ktimingMode || thisDevice.mode == kintermittentMode) {
|
|
if (thisDevice.countdonwnum_s != 0) {
|
|
thisDevice.countdonwnum_s = //
|
|
thisDevice.countdonw_setting_num * kconst_countdown_step_s - systicket_haspassedms(thisDevice.countdonw_start_ticket) / 1000;
|
|
thisDevice.countdonwnum = compute_countdown_num(thisDevice.countdonwnum_s);
|
|
}
|
|
}
|
|
}
|
|
|
|
void this_module_schedule() {
|
|
if (thisDevice.error != knoneException) {
|
|
return;
|
|
}
|
|
/**
|
|
* @brief 定时模式下
|
|
*/
|
|
if (thisDevice.mode == ktimingMode) {
|
|
//定时自动关机
|
|
mf_update_countdown();
|
|
mf_try_autoshutdown();
|
|
}
|
|
|
|
/**
|
|
* @brief 间歇模式下,自动停止,自动重启
|
|
*/
|
|
if (thisDevice.mode == kintermittentMode) {
|
|
mf_update_countdown();
|
|
if (thisDevice.working) {
|
|
mf_try_autostop();
|
|
} else {
|
|
mf_try_auto_restart();
|
|
}
|
|
}
|
|
};
|
|
|
|
/***********************************************************************************************************************
|
|
* =======================================================MAIN======================================================== *
|
|
***********************************************************************************************************************/
|
|
static void mf_do_debug_light_state() {
|
|
static uint8_t debug_led_state = 1;
|
|
debug_led_state = !debug_led_state;
|
|
port_debug_set(debug_led_state);
|
|
}
|
|
|
|
static void mf_init_all_subdevice_state() {
|
|
port_debug_set(false);
|
|
port_fan_set(false);
|
|
port_led0_set(false);
|
|
port_led1_set(false);
|
|
port_led2_set(false);
|
|
port_led3_set(false);
|
|
port_led_r_set(false);
|
|
port_led_g_set(false);
|
|
port_led_b_set(false);
|
|
}
|
|
|
|
void WDTInit(void) {
|
|
IWDT_InitStruType x;
|
|
|
|
x.WDT_Tms = 10000;
|
|
x.WDT_IE = Enable; /* IWDT中断使能 */
|
|
x.WDT_Rst = Enable; /* IWDT复位使能 */
|
|
x.WDT_Clock = IWDT_CLOCK_WDT; /* LRC */
|
|
IWDT_Init(&x);
|
|
|
|
/* 使能IWDT */
|
|
IWDT_Enable();
|
|
}
|
|
|
|
// static float mf_get_ozone_generator_power() {
|
|
// float fanpower = 0;
|
|
// for (size_t i = 0; i < 20; i++) {
|
|
// fanpower += port_adc_get_ozone_generator_power();
|
|
// }
|
|
// return fanpower / 20;
|
|
// }
|
|
|
|
static const char* errorToStr(error_t exception) {
|
|
if (exception == knoneException) {
|
|
return "kNoError";
|
|
}
|
|
if (exception == kOzonePrimaryCircuitAnomaly) {
|
|
return "kOzonePrimaryCircuitAnomaly";
|
|
}
|
|
if (exception == kOzoneSecondaryCircuitAnomaly) {
|
|
return "kOzoneSecondaryCircuitAnomaly";
|
|
}
|
|
if (exception == kfanIsBroken) {
|
|
return "kfanIsBroken";
|
|
}
|
|
if (exception == kPowerOutOfControl) {
|
|
return "kPowerOutOfControl";
|
|
}
|
|
return "kUnknownException";
|
|
}
|
|
|
|
void trigger_exception(error_t exception) {
|
|
thisDevice.error = exception;
|
|
|
|
printf("======================DeviceSnapshot==========================\n");
|
|
/*Exception*/
|
|
printf("= Exception\n");
|
|
printf("=\terror :%s\n", errorToStr(exception));
|
|
//
|
|
printf("= IOState\n");
|
|
printf("=\tFan :%d\n", port_fan_get());
|
|
/*Power*/
|
|
printf("= Power\n");
|
|
printf("=\tfanpower :%f\n", mf_fan_get_power());
|
|
printf("=\tozonepower :%f\n", ozone_control_get_ozone_power());
|
|
|
|
/*ThisDevice*/
|
|
printf("= ThisDevice\n");
|
|
printf("=\tworking :%d\n", thisDevice.working);
|
|
printf("=\tmode :%d\n", thisDevice.mode);
|
|
printf("=\tlevel :%d\n", thisDevice.level);
|
|
printf("=\tpoweron :%d\n", thisDevice.poweron);
|
|
printf("=\tcountdonwnum :%d\n", thisDevice.countdonwnum);
|
|
printf("=\tcountdonwnum_s :%d\n", thisDevice.countdonwnum_s);
|
|
printf("=\tcountdonw_setting_num :%d\n", thisDevice.countdonw_setting_num);
|
|
printf("=\tcountdonw_start_ticket :%d\n", thisDevice.countdonw_start_ticket);
|
|
printf("=\tactive_input :%d\n", thisDevice.active_input);
|
|
printf("=\tactive_start_ticket :%d\n", thisDevice.active_start_ticket);
|
|
|
|
/*ozone_control*/
|
|
printf("= OZONE CONTROL\n");
|
|
printf("=\tworking_state_id :%d\n", ozone_control_get_working_state_id());
|
|
printf("=\tnowfreq :%d\n", ozone_control_get_working_state()->nowfreq);
|
|
printf("=\tchangefreqdirection :%d\n", ozone_control_get_working_state()->changefreqdirection);
|
|
printf("=\tadjustedToTheProperPower:%d\n", ozone_control_get_working_state()->adjustedToTheProperPower);
|
|
printf("=\tresonant_frequency :%d\n", ozone_control_get_working_state()->resonant_frequency);
|
|
printf("=\tslope_when_freq40k :%f\n", ozone_control_get_working_state()->slope_when_freq40k);
|
|
printf("=\tavarage_power :%f\n", ozone_control_get_working_state()->avarage_power);
|
|
printf("=\texpect_power :%f\n", ozone_control_get_expect_power());
|
|
|
|
printf("=\n");
|
|
|
|
// reset device
|
|
thisDevice.mode = knormal;
|
|
stopwork();
|
|
}
|
|
|
|
void exception_monitor_schedule() {
|
|
if (!thisDevice.poweron) {
|
|
return;
|
|
}
|
|
if (thisDevice.error != knoneException) {
|
|
return;
|
|
}
|
|
|
|
// printf("FanPower:%f,OzonePower:%f\n", fan_get_power(), mf_get_ozone_generator_power());
|
|
|
|
/*****************************************************************************************************************
|
|
* ================================================检查风扇异常================================================= *
|
|
*****************************************************************************************************************/
|
|
if (port_fan_get()) {
|
|
float fanpower = mf_fan_get_power();
|
|
/**
|
|
* @brief 当前风扇阻转后功率依然不高只比正常的功率1.5大0.3
|
|
*
|
|
* http://192.168.1.3:3000/project_ozone_generator/doc/src/branch/master/ref/风扇功率日志-正常工作和阻转时候的功率变化.png
|
|
* http://192.168.1.3:3000/project_ozone_generator/doc/src/branch/master/ref/风扇不工作时候的功率.png
|
|
*
|
|
*/
|
|
if (fanpower > 3 || fanpower < 0.6) {
|
|
m_fanerronum++;
|
|
printf("fanpower error: %f ,%d\n", fanpower, m_fanerronum);
|
|
if (m_fanerronum > 3) {
|
|
trigger_exception(kfanIsBroken);
|
|
return;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
m_fanerronum = 0;
|
|
}
|
|
/*****************************************************************************************************************
|
|
* ============================================检查臭氧是否工作异常============================================= *
|
|
*****************************************************************************************************************/
|
|
if (ozone_control_get_working_state_id() == kWorkingState) {
|
|
/**
|
|
* @brief 检查一级电路是否工作正常
|
|
*/
|
|
if (ozone_control_get_working_state()->avarage_power < 0.2) {
|
|
trigger_exception(kOzonePrimaryCircuitAnomaly);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief 检查二级电路是否工作正常
|
|
* -0.000344
|
|
*/
|
|
if (ozone_control_get_working_state()->slope_when_freq40k < -0.000200) {
|
|
trigger_exception(kOzoneSecondaryCircuitAnomaly);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* @brief 监控功率变化情况
|
|
* 当频率已经调整到了可调范围的最低时候,功率依然大于期望功率,则触发异常
|
|
*/
|
|
if (ozone_control_get_ozone_power() > (ozone_control_get_expect_power() + EXPECT_POWER_WINDONWS) && //
|
|
ozone_control_get_working_state()->nowfreq == ozone_control_get_working_state()->resonant_frequency) {
|
|
trigger_exception(kPowerOutOfControl);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
SystemInit(); //配置系统时钟
|
|
DeviceClockAllEnable(); //打开所有外设时钟
|
|
systicket_init();
|
|
|
|
/*系统初始化*/
|
|
zgpio_init_all_gpio(); //
|
|
port_init(); //
|
|
mf_init_all_subdevice_state(); //
|
|
printf("==========OZONE_GENERATOR==========\n"); //
|
|
printf("= manufactor: iflytop\n"); //
|
|
printf("= version : %s\n", VERSION); //
|
|
printf("=\n"); //
|
|
|
|
/*组件初始化*/
|
|
zkey_init(&key_module); //按键初始化
|
|
|
|
ozone_control_init();
|
|
/**
|
|
* @brief
|
|
* 频率从20k起步,递增50hz,每次等待100ms计算功率
|
|
*/
|
|
WDTInit();
|
|
while (true) {
|
|
//按键扫描逻辑
|
|
DO_IT_EACH_MS(KEY_PERIOD) { zkey_do_loop_in_each_period(NULL); }
|
|
END();
|
|
//调试指示灯
|
|
DO_IT_EACH_MS(150) { mf_do_debug_light_state(); }
|
|
END();
|
|
//臭氧控制逻辑Schedule
|
|
ozone_control_schedule();
|
|
//人机交互逻辑Schedule
|
|
hcis_shcedule();
|
|
//当前模块逻辑Schedule
|
|
this_module_schedule();
|
|
DO_IT_EACH_MS(1000) { exception_monitor_schedule(); }
|
|
END();
|
|
// port_fan_set(true);
|
|
// DO_IT_EACH_MS(100) { dumpfanpower(); }
|
|
// END();
|
|
|
|
// DO_IT_EACH_MS(500) { dumpstate(); }
|
|
// END();
|
|
|
|
//喂狗
|
|
if (0x01 == IWDT_GetFlagStatus()) IWDT_Clear();
|
|
}
|
|
}
|