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.
 
 
 
 

223 lines
7.4 KiB

#include "ozone_control_service.h"
#include "../zes8p5066lib/basic.h"
#include "../zes8p5066lib/systicket.h"
#include "frequency_sweep_service.h"
#include "state_machine.h"
/**
* @brief
*
* 状态机:
* 不工作 ------> 扫描频率 ----> 工作
*
**/
#define PRV_START_EVENT (STATE_MACHINE_PUBLIC_EVENT + 1)
#define PRV_STOP_EVENT (STATE_MACHINE_PUBLIC_EVENT + 2)
typedef struct {
float resonant_frequency; //谐振频率点
float nowfreq; //当前频率
bool changefreqdirection; //频率调整方向,如果当前功率大于期望功率,则减少频率,反之亦然
bool adjustedToTheProperPower; //是否已经调整到恰当的功率
} Context_t;
typedef enum {
kIdleState,
kBeforeWorkingStateSweepFrequency,
kWorkingState,
} StateId_t;
state_machine_state_t m_states[] = {
[kIdleState] =
{
.name = "kIdleState",
.stateId = kIdleState,
},
[kBeforeWorkingStateSweepFrequency] =
{
.name = "kBeforeWorkingStateSweepFrequency",
.stateId = kBeforeWorkingStateSweepFrequency,
},
[kWorkingState] = //
{
.name = "kWorkingState",
.stateId = kWorkingState,
}
//
};
state_machine_t m_statemachine;
static Context_t context;
const static float const_windonws = 0.3;
const static float const_level1_expect_power = 3.0;
const static float const_level2_expect_power = 6.0;
const static float const_max_freq = 38000;
static uint16_t get_resonant_frequency(uint16_t startfreq, uint16_t step, uint16_t endfreq) {
/**
* @brief
* 计算谐振频率,频率和功率的图像接近下图,由此可知,当设备工作正常时,在一定频率范围内,查找功率最小的点即可。
*
* http://192.168.1.3:3000/project_ozone_generator/doc/src/branch/master/ref/20220815频率-功率关系图.png
*/
float minpower = 0;
uint16_t retfreq = 0;
bool inited = false;
for (uint16_t freq = startfreq; freq <= endfreq; freq += step) {
float power = frequency_sweep_get_power(freq);
if (inited) {
minpower = power;
retfreq = freq;
inited = false;
continue;
}
if (power < minpower) {
minpower = power;
retfreq = freq;
}
}
return retfreq;
}
static float mf_get_ozone_power() {
float powersum = 0;
for (size_t i = 0; i < 10; i++) {
powersum += port_adc_get_ozone_generator_power();
}
return powersum / 10;
}
float get_expect_power() {
float expectpower = 0;
if (thisDevice.level == klevel1) {
expectpower = const_level1_expect_power;
} else if (thisDevice.level == klevel2) {
expectpower = const_level2_expect_power;
}
return expectpower;
}
static state_machine_state_t* processBeforeWorkingStateSweepFrequency(state_machine_t* machine, state_machine_state_t* nowstate, int event) {
/**
* @brief 扫频
*/
if (event == ENTER_STATE) {
frequency_sweep_start(20000, 100, 40000, 3000);
} else if (event == TIME_EVENT) {
if (frequency_sweep_is_done()) {
context.resonant_frequency = get_resonant_frequency(25000, 100, 35000);
printf("----------Summarize--------\n");
printf("-resonant_frequency: %f\n", context.resonant_frequency);
context.nowfreq = context.resonant_frequency;
return &m_states[kWorkingState];
}
} else if (event == EXIT_STATE) {
frequency_sweep_stop();
}
}
static state_machine_state_t* processWorkingState(state_machine_t* machine, state_machine_state_t* nowstate, int event) {
/**
* @brief 检查当前功率是否正常
*
* 当功率在期望功率窗口之外时候([expertpower+window,expertpower-window]),
* 开始调整当前频率,直到功率接近期望功率。
*/
if (event == ENTER_STATE) {
/**
* @brief 在谐振点启动,此时臭氧功率最小
*/
if (context.nowfreq < context.resonant_frequency) {
context.nowfreq = context.resonant_frequency;
}
port_ozone_pwm_set_duty(context.nowfreq, 5000);
port_ozone_pwm_start();
context.adjustedToTheProperPower = false;
} else if (event == TIME_EVENT) {
if (context.adjustedToTheProperPower) {
/**
* 检查当前功率是否在期望功率窗口之外时候([expertpower+window,expertpower-window]),
*/
float nowpower = mf_get_ozone_power();
if (nowpower < get_expect_power() - const_windonws || nowpower > get_expect_power() + const_windonws) {
context.adjustedToTheProperPower = false;
if (nowpower < get_expect_power()) {
context.changefreqdirection = true;
} else {
context.changefreqdirection = false;
}
}
} else {
/**
* 调整功率到期望功率
*/
if (context.changefreqdirection) {
float nowpower = mf_get_ozone_power();
if (nowpower < get_expect_power()) {
context.nowfreq += 100;
if (context.nowfreq > const_max_freq) context.nowfreq = const_max_freq;
printf("change freq to match power,freq %d, power %f-->%f \n", context.nowfreq, nowpower, get_expect_power());
port_ozone_pwm_set_duty(context.nowfreq, 5000);
} else {
context.adjustedToTheProperPower = true;
}
} else {
float nowpower = mf_get_ozone_power();
if (nowpower > get_expect_power()) {
context.nowfreq -= 100;
if (context.nowfreq < context.resonant_frequency) context.nowfreq = context.resonant_frequency;
printf("change freq to match power,freq %d, power %f-->%f \n", context.nowfreq, nowpower, get_expect_power());
port_ozone_pwm_set_duty(context.nowfreq, 5000);
} else {
context.adjustedToTheProperPower = true;
}
}
}
} else if (event == EXIT_STATE) {
port_ozone_pwm_stop();
}
}
static state_machine_state_t* state_machine_process_event(state_machine_t* machine, state_machine_state_t* nowstate, int event) {
/**
* @brief 处理Start和Stop事件
*/
if (event == PRV_START_EVENT || event == PRV_STOP_EVENT) {
if (event == PRV_START_EVENT) {
printf("start\n");
return &m_states[kBeforeWorkingStateSweepFrequency];
} else {
printf("stop\n");
return &m_states[kIdleState];
}
}
/**
* @brief 处理其他事件
*/
if /* */ (nowstate == &m_states[kIdleState]) {
} else if (nowstate == &m_states[kBeforeWorkingStateSweepFrequency]) {
return processBeforeWorkingStateSweepFrequency(machine, nowstate, event);
} else if (nowstate == &m_states[kWorkingState]) {
return processWorkingState(machine, nowstate, event);
}
return NULL;
}
/***********************************************************************************************************************
* ======================================================Export======================================================= *
***********************************************************************************************************************/
void ozone_control_init() { state_machine_init(&m_statemachine, m_states, ZARR_SIZE(m_states), state_machine_process_event); }
void ozone_control_start() { state_machine_trigger_event(&m_statemachine, PRV_START_EVENT); }
void ozone_control_stop() { state_machine_trigger_event(&m_statemachine, PRV_STOP_EVENT); }
void ozone_control_schedule() {
static uint32_t ticket = 0;
if (systicket_haspassedms(&ticket) > 10 * 1000) {
ticket = systicket_get_now_ms();
state_machine_schedule_each10ms(&m_statemachine);
}
}