559 lines
20 KiB
C
559 lines
20 KiB
C
/*
|
||
* @Author: mypx
|
||
* @Date: 2025-08-11 08:30:45
|
||
* @LastEditTime: 2025-09-24 16:12:52
|
||
* @LastEditors: mypx mypx_coder@163.com
|
||
* @Description:
|
||
*/
|
||
#include "pm_meas.h"
|
||
#include "data_process.h"
|
||
#include "data_sampling.h"
|
||
#include "et_waveform_analysis.h"
|
||
#include "etk_diff.h"
|
||
#include "etk_ringbuffer.h"
|
||
#include "servo.h"
|
||
#include <float.h>
|
||
#include <rtthread.h>
|
||
#include <stdio.h>
|
||
|
||
|
||
static pm_fsm_t *pm_fsm = NULL;
|
||
|
||
pm_fsm_t *get_pm_fsm(void)
|
||
{
|
||
return pm_fsm;
|
||
}
|
||
|
||
void fsm_state_toggle(void)
|
||
{
|
||
pm_fsm_t *fsm = get_pm_fsm();
|
||
if (!fsm)
|
||
return;
|
||
fsm->fz_fsm_state = !fsm->fz_fsm_state;
|
||
}
|
||
MSH_CMD_EXPORT_ALIAS(fsm_state_toggle, fsm, calculate state toggle);
|
||
|
||
void calibrate_mode_toggle(void)
|
||
{
|
||
pm_fsm_t *fsm = get_pm_fsm();
|
||
if (!fsm)
|
||
return;
|
||
fsm->fz_fsm_state = false;
|
||
fsm->meas_mode = fsm->meas_mode == PM_MEAS_NORMAL_Mode ? PM_MEAS_TEST_Mode : PM_MEAS_NORMAL_Mode;
|
||
}
|
||
MSH_CMD_EXPORT_ALIAS(calibrate_mode_toggle, cali, calibrate mode toggle);
|
||
|
||
void trend_handle_init(trend_handle_t *handle)
|
||
{
|
||
handle->last_val = NAN;
|
||
handle->inc_cnt = 0;
|
||
handle->dec_cnt = 0;
|
||
}
|
||
|
||
TrendStatus get_data_trend(trend_handle_t *handle, double new_val)
|
||
{
|
||
const double EPS = 1e-6; // 浮点数比较精度(避免误差)
|
||
|
||
// 1. 首次调用:无历史数据,返回“未知”并初始化上次值
|
||
if (isnan(handle->last_val))
|
||
{
|
||
handle->last_val = new_val;
|
||
return TREND_UNKNOWN;
|
||
}
|
||
|
||
// 2. 比较本次与上次数据,更新计数
|
||
if (new_val > handle->last_val + EPS)
|
||
{
|
||
// 数据上升
|
||
handle->inc_cnt++;
|
||
handle->dec_cnt = 0;
|
||
}
|
||
else if (new_val < handle->last_val - EPS)
|
||
{
|
||
// 数据下降
|
||
handle->dec_cnt++;
|
||
handle->inc_cnt = 0;
|
||
}
|
||
|
||
handle->last_val = new_val;
|
||
// 3. 判断是否达到“连续6次”的触发阈值(原逻辑:cnt > 5)
|
||
if (handle->inc_cnt > TREND_MAX_CNT)
|
||
{
|
||
//inc_cnt = 0; // 触发后清零,重新开始计数
|
||
return TREND_INCREASE;
|
||
}
|
||
if (handle->dec_cnt > TREND_MAX_CNT)
|
||
{
|
||
//dec_cnt = 0; // 触发后清零,重新开始计数
|
||
return TREND_DECREASE;
|
||
}
|
||
return TREND_STABLE;
|
||
}
|
||
|
||
void trend_handle_reset(trend_handle_t *handle)
|
||
{
|
||
handle->last_val = NAN;
|
||
handle->inc_cnt = 0;
|
||
handle->dec_cnt = 0;
|
||
}
|
||
|
||
void measurement_info_print(pm_meas_t *fz)
|
||
{
|
||
ET_WARN("------------------------Calibration Info Start----------------------------");
|
||
ET_INFO("Find zero time: %lu ms", fz->calib_info[0].end_time - fz->calib_info[0].start_time);
|
||
float min_angle = FLT_MAX;
|
||
float max_angle = -FLT_MAX;
|
||
|
||
for (int i = 0; i < fz->calib_cnt; i++)
|
||
{
|
||
#if (ENABLE_CALIB_DOUBLE_DIR == 1)
|
||
if (fz->calib_info[i].m_dir == -1)
|
||
fz->calib_info[i].cali_angle = fz->calib_info[i].angle - CALIB_OFFSET;
|
||
else
|
||
#endif
|
||
fz->calib_info[i].cali_angle = fz->calib_info[i].angle;
|
||
if (fz->calib_info[i].cali_angle < min_angle)
|
||
{
|
||
min_angle = fz->calib_info[i].cali_angle;
|
||
}
|
||
if (fz->calib_info[i].cali_angle > max_angle)
|
||
{
|
||
max_angle = fz->calib_info[i].cali_angle;
|
||
}
|
||
// ET_INFO("[%d]: Used time:%d ms, start:%.3f, end zero pos:%.3f, cali_angle:%.2f, power:%.3f", i,
|
||
// fz->calib_info[i].end_time - fz->calib_info[i].start_time, fz->calib_info[i].target_angle,
|
||
// fz->calib_info[i].angle, fz->calib_info[i].cali_angle, fz->calib_info[i].power);
|
||
ET_INFO("[%d]: Used time:%d ms, start:%.3f, end zero pos:%.3f, power:%.3f", i,
|
||
fz->calib_info[i].end_time - fz->calib_info[i].start_time, fz->calib_info[i].target_angle,
|
||
fz->calib_info[i].angle, fz->calib_info[i].power);
|
||
}
|
||
ET_INFO("Final min_angle: %.3f, max_angle: %.3f", min_angle, max_angle);
|
||
if (min_angle != FLT_MAX && max_angle != FLT_MIN)
|
||
{
|
||
float accuracy = (max_angle - min_angle) / ENCODER_TO_POLARIZER_RATIO;
|
||
ET_INFO("Accuracy: %.3f (max_angle-min_angle=%.3f, ratio=%d)", accuracy, max_angle - min_angle,
|
||
ENCODER_TO_POLARIZER_RATIO);
|
||
}
|
||
else
|
||
{
|
||
ET_WARN("Accuracy not calculated: min_angle=%.3f, max_angle=%.3f", min_angle, max_angle);
|
||
}
|
||
ET_WARN("------------------------Calibration Info End----------------------------");
|
||
}
|
||
|
||
void accuracy_auto_measurement_once(pm_meas_t *fz, float angle)
|
||
{
|
||
ET_INFO("Start to calibrate again:%d", fz->calib_cnt);
|
||
|
||
#if (CALIB_TO_FIX_STAGE == 1)
|
||
float diff = angle - fz->stage_info[ZF_PREPARE_ENTER_STAGE].angle;
|
||
#else
|
||
float diff = CALIB_OSCI_ANGLE;
|
||
#endif
|
||
ET_INFO("diff:%.2f", diff);
|
||
float target_angle = 0.0f;
|
||
#if (ENABLE_CALIB_DOUBLE_DIR == 1)
|
||
if (fz->calib_cnt % 2 == 0)
|
||
{
|
||
target_angle = angle - diff;
|
||
ET_INFO("Odd times, turn back");
|
||
}
|
||
else
|
||
{
|
||
target_angle = angle + diff;
|
||
ET_INFO("Even times, turn forward");
|
||
}
|
||
#else
|
||
target_angle = angle + diff * CALIB_ONE_DIR;
|
||
#endif
|
||
uint32_t delay = convert_encoder_angle_rpm_to_to_time(diff, RUN_OFFSET_ANGLE_RPM);
|
||
ET_DBG("wait %d ms to target:%.2f", delay, target_angle);
|
||
int speed = (target_angle > angle) ? -RUN_OFFSET_ANGLE_RPM
|
||
: RUN_OFFSET_ANGLE_RPM; // FIXME:note encoder dir and motor dir
|
||
sv630p_speed_mode_start(&sv630p_handle, speed);
|
||
fz->target_dir = (speed > 0) ? -1 : 1;
|
||
ET_WARN("SPEED:%d", speed);
|
||
while (1)
|
||
{
|
||
angle = get_real_time_angle_degree();
|
||
//ET_DBG("angle:%.2f", angle);
|
||
// 根据方向判断是否达到目标角度,处理负数角度情况
|
||
if (((speed > 0) && (target_angle > angle)) || ((speed < 0) && (target_angle < angle)))
|
||
{
|
||
sv630p_speed_mode_stop(&sv630p_handle);
|
||
ET_INFO("Set angle:%.3f, reached:%.3f", target_angle, angle);
|
||
#if (CALIB_TO_FIX_STAGE == 1)
|
||
fz->state = ZF_PREPARE_ENTER_STAGE;
|
||
ET_WARN("Back to ZF_PREPARE_ENTER_STAGE state");
|
||
#else
|
||
fz->state = ZF_FAST_CLOSE_STAGE;
|
||
ET_WARN("Back to ZF_FAST_CLOSE_STAGE state");
|
||
#endif
|
||
uint8_t index = fz->calib_cnt % FZ_CALI_MAX_COUNT;
|
||
fz->calib_info[index].target_angle = target_angle;
|
||
ET_INFO("update start calib index:%d", index);
|
||
fz->calib_info[index].start_time = rt_tick_get_millisecond();
|
||
//fz->target_dir *= -1; // reverse dir
|
||
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 饱和高噪声状态判断,不会误判为其他状态,任何情形都无需从这个状态反转
|
||
StageResult is_saturate_starting(pm_meas_t *fz)
|
||
{
|
||
if (fabs(fz->slope) < FZ_SATURATED_SLOPE_MAX && fz->p50 < FZ_SATURATED_POWER_MAX && (fz->freq < 10))
|
||
{
|
||
//fz->state = ZF_SATURATED_STAGE;
|
||
return STAGE_RESULT_OK;
|
||
}
|
||
else
|
||
return STAGE_RESULT_NO;
|
||
}
|
||
|
||
int goto_saturated_stage(pm_meas_t *fz)
|
||
{
|
||
fz->state = ZF_SATURATED_STAGE;
|
||
ET_WARN("power state: ZF_SATURATED_STAGE");
|
||
return sv630p_speed_update(&sv630p_handle, FZ_SATURATED_STAGE_RPM * fz->target_dir);
|
||
}
|
||
|
||
StageResult is_wave_enter_stage(pm_meas_t *fz)
|
||
{
|
||
if (fz->slope > 100000)
|
||
return STAGE_RESULT_OK;
|
||
else
|
||
return STAGE_RESULT_NO;
|
||
}
|
||
|
||
StageResult is_prepare_enter_stage(pm_meas_t *fz)
|
||
{
|
||
if (fz->p50 > 100000 && fz->trend == TREND_DECREASE && fz->state != ZF_WAVE_LEAVE_STAGE)
|
||
return STAGE_RESULT_OK;
|
||
else
|
||
return STAGE_RESULT_NO;
|
||
}
|
||
|
||
int goto_prepare_enter_stage(pm_meas_t *fz, double p50, double slope, float freq, double angle)
|
||
{
|
||
fz->state = ZF_PREPARE_ENTER_STAGE;
|
||
if (fz->stage_info[ZF_PREPARE_ENTER_STAGE].is_updated == 0)
|
||
{
|
||
fz->stage_info[ZF_PREPARE_ENTER_STAGE].angle = angle;
|
||
fz->stage_info[ZF_PREPARE_ENTER_STAGE].time = rt_tick_get_millisecond();
|
||
fz->stage_info[ZF_PREPARE_ENTER_STAGE].p50 = p50;
|
||
fz->stage_info[ZF_PREPARE_ENTER_STAGE].slope = slope;
|
||
fz->stage_info[ZF_PREPARE_ENTER_STAGE].freq = freq;
|
||
fz->stage_info[ZF_PREPARE_ENTER_STAGE].is_updated = 1;
|
||
}
|
||
ET_WARN("enter ZF_PREPARE_ENTER_STAGE angle:%.3f", angle);
|
||
return sv630p_speed_update(&sv630p_handle, FZ_PREPARE_STAGE_RPM * fz->target_dir);
|
||
}
|
||
|
||
int goto_prepare_leave_stage(pm_meas_t *fz, double angle)
|
||
{
|
||
fz->target_dir = fz->target_dir * -1;
|
||
if (fz->stage_info[ZF_PREPARE_LEAVE_STAGE].is_updated == 0)
|
||
{
|
||
fz->stage_info[ZF_PREPARE_LEAVE_STAGE].is_updated = 1;
|
||
fz->stage_info[ZF_PREPARE_LEAVE_STAGE].angle = angle;
|
||
fz->stage_info[ZF_PREPARE_LEAVE_STAGE].time = rt_tick_get_millisecond();
|
||
fz->stage_info[ZF_PREPARE_LEAVE_STAGE].p50 = fz->p50;
|
||
fz->stage_info[ZF_PREPARE_LEAVE_STAGE].slope = fz->slope;
|
||
fz->stage_info[ZF_PREPARE_LEAVE_STAGE].freq = fz->freq;
|
||
}
|
||
ET_WARN("ZF_PREPARE_LEAVE_STAGE, angle:%.3f", angle);
|
||
return sv630p_speed_update(&sv630p_handle, FZ_PREPARE_STAGE_RPM * fz->target_dir);
|
||
}
|
||
|
||
StageResult is_fast_close_enter(pm_meas_t *fz)
|
||
{
|
||
if (fz->p50 <= 100000 && fz->trend == TREND_DECREASE && fz->state == ZF_PREPARE_ENTER_STAGE)
|
||
return STAGE_RESULT_OK;
|
||
else
|
||
return STAGE_RESULT_NO;
|
||
}
|
||
|
||
int goto_fast_close_stage(pm_meas_t *fz, double p50, double slope, float freq, double angle)
|
||
{
|
||
fz->state = ZF_FAST_CLOSE_STAGE;
|
||
if (fz->stage_info[ZF_FAST_CLOSE_STAGE].is_updated == 0)
|
||
{
|
||
fz->stage_info[ZF_FAST_CLOSE_STAGE].is_updated = 1;
|
||
fz->stage_info[ZF_FAST_CLOSE_STAGE].angle = angle;
|
||
fz->stage_info[ZF_FAST_CLOSE_STAGE].time = rt_tick_get_millisecond();
|
||
fz->stage_info[ZF_FAST_CLOSE_STAGE].p50 = p50;
|
||
fz->stage_info[ZF_FAST_CLOSE_STAGE].slope = slope;
|
||
fz->stage_info[ZF_FAST_CLOSE_STAGE].freq = freq;
|
||
}
|
||
ET_WARN("FAST_CLOSE, angle:%.3f\r\n", angle);
|
||
return sv630p_speed_update(&sv630p_handle, FZ_FAST_CLOSE_STAGE_RPM * fz->target_dir);
|
||
}
|
||
|
||
StageResult is_zero_stage(pm_meas_t *fz)
|
||
{
|
||
if (fabs(fz->slope) < 0.5 && fz->p50 < ZERO_POS_THRESHOLD && (fz->freq >= 99.95 && fz->freq < 100.3f)
|
||
&& fz->trend == TREND_STABLE)
|
||
return STAGE_RESULT_OK;
|
||
else
|
||
return STAGE_RESULT_NO;
|
||
}
|
||
|
||
StageResult is_fast_leave_stage(pm_meas_t *fz)
|
||
{
|
||
if ((fz->p50 <= 100000) && (fz->slope > 10000)
|
||
&& (fz->freq > FZ_FAST_CLOSE_ENTER_FREQ_MIN && fz->freq < FZ_FAST_CLOSE_ENTER_FREQ_MAX)
|
||
&& fz->state != ZF_SATURATED_STAGE)
|
||
return STAGE_RESULT_OK;
|
||
else
|
||
return STAGE_RESULT_NO;
|
||
}
|
||
|
||
StageResult is_prepare_leave_stage(pm_meas_t *fz)
|
||
{
|
||
if (fz->p50 >= 100000 && fz->trend == TREND_INCREASE
|
||
&& (fz->state == ZF_FAST_CLOSE_STAGE || fz->state == ZF_ZERO_STAGE))
|
||
return STAGE_RESULT_OK;
|
||
else
|
||
return STAGE_RESULT_NO;
|
||
}
|
||
|
||
StageResult is_wave_leave_stage(pm_meas_t *fz)
|
||
{
|
||
if ((fz->slope < -100000) || (fz->freq > 52 && fz->freq < 98 && fz->p50 < 1000 && fz->trend == TREND_DECREASE)
|
||
|| (fz->freq < 1.0 && fz->trend == TREND_DECREASE))
|
||
return STAGE_RESULT_OK;
|
||
else
|
||
return STAGE_RESULT_NO;
|
||
}
|
||
|
||
ZeroFindState get_find_zero_state(pm_meas_t *fz)
|
||
{
|
||
return fz->state;
|
||
}
|
||
|
||
void calculate_stage(pm_meas_t *fz)
|
||
{
|
||
if (is_saturate_starting(fz) == STAGE_RESULT_OK && fz->stage_info[ZF_SATURATED_STAGE].is_print == false)
|
||
{
|
||
ET_WARN("enter saturated");
|
||
fz->stage_info[ZF_SATURATED_STAGE].is_print = true;
|
||
fz->state = ZF_SATURATED_STAGE;
|
||
}
|
||
if (is_wave_enter_stage(fz) == STAGE_RESULT_OK && fz->stage_info[ZF_WAVE_ENTER_STAGE].is_print == false)
|
||
{
|
||
ET_WARN("enter 50hz started");
|
||
fz->stage_info[ZF_WAVE_ENTER_STAGE].is_print = true;
|
||
fz->stage_info[ZF_SATURATED_STAGE].is_print = false;
|
||
fz->state = ZF_WAVE_ENTER_STAGE;
|
||
}
|
||
if (is_prepare_enter_stage(fz) == STAGE_RESULT_OK && fz->stage_info[ZF_PREPARE_ENTER_STAGE].is_print == false)
|
||
{
|
||
ET_WARN("enter prepare stage");
|
||
fz->stage_info[ZF_PREPARE_ENTER_STAGE].is_print = true;
|
||
fz->state = ZF_PREPARE_ENTER_STAGE;
|
||
fz->stage_info[ZF_WAVE_ENTER_STAGE].is_print = false;
|
||
}
|
||
if (is_fast_close_enter(fz) == STAGE_RESULT_OK && fz->stage_info[ZF_FAST_CLOSE_STAGE].is_print == false)
|
||
{
|
||
ET_WARN("enter fast close stage, dir:%d, target dir :%d", sv630p_get_dir(&sv630p_handle), fz->target_dir);
|
||
fz->stage_info[ZF_FAST_CLOSE_STAGE].is_print = true;
|
||
fz->stage_info[ZF_PREPARE_ENTER_STAGE].is_print = false;
|
||
fz->state = ZF_FAST_CLOSE_STAGE;
|
||
}
|
||
|
||
if (is_zero_stage(fz) == STAGE_RESULT_OK && fz->stage_info[ZF_ZERO_STAGE].is_print == false)
|
||
{
|
||
ET_WARN("enter zero state");
|
||
fz->stage_info[ZF_ZERO_STAGE].is_print = true;
|
||
if (fz->state == ZF_UNKNOWN_STAGE)
|
||
fz->state = ZF_ZERO_STAGE; // 开机判断
|
||
}
|
||
else
|
||
{
|
||
fz->stage_info[ZF_ZERO_STAGE].is_print = false;
|
||
}
|
||
|
||
if (is_fast_leave_stage(fz) == STAGE_RESULT_OK && fz->stage_info[ZF_FAST_LEAVE_STAGE].is_print == false)
|
||
{
|
||
ET_WARN("fast leave stage");
|
||
fz->stage_info[ZF_FAST_LEAVE_STAGE].is_print = true;
|
||
//fz->stage_info[ZF_PRECISE_ADJUST_LEAVE_STAGE].is_print = false;
|
||
fz->state = ZF_FAST_LEAVE_STAGE;
|
||
}
|
||
if (is_prepare_leave_stage(fz) == STAGE_RESULT_OK && fz->stage_info[ZF_PREPARE_LEAVE_STAGE].is_print == false)
|
||
{
|
||
ET_WARN("prepare leave stage");
|
||
fz->stage_info[ZF_PREPARE_LEAVE_STAGE].is_print = true;
|
||
fz->stage_info[ZF_FAST_LEAVE_STAGE].is_print = false;
|
||
fz->stage_info[ZF_WAVE_LEAVE_STAGE].is_print = false;
|
||
fz->state = ZF_PREPARE_LEAVE_STAGE;
|
||
}
|
||
if (is_wave_leave_stage(fz) == STAGE_RESULT_OK && fz->stage_info[ZF_WAVE_LEAVE_STAGE].is_print == false)
|
||
{
|
||
ET_WARN("small 50hz leave stage");
|
||
fz->stage_info[ZF_WAVE_LEAVE_STAGE].is_print = true;
|
||
fz->stage_info[ZF_PREPARE_LEAVE_STAGE].is_print = false;
|
||
fz->state = ZF_WAVE_LEAVE_STAGE;
|
||
}
|
||
}
|
||
|
||
int find_zero_process(pm_meas_t *fz, const uint16_t *adc_buf, uint32_t len)
|
||
{
|
||
pm_fsm_t *fsm = get_pm_fsm();
|
||
if (!fsm)
|
||
{
|
||
ET_ERR("fsm is not init");
|
||
return 0;
|
||
}
|
||
double rpm = 0.0;
|
||
//static uint8_t wait_time = 0;
|
||
float angle;
|
||
|
||
fz->p50 = et_goertzel_compute_power_u16(&fz->cfg, adc_buf);
|
||
fz->slope = etk_slope_update_slope(&fz->slope_handle, fz->p50);
|
||
|
||
// if (wait_time++ < BUFFER_SIZE)
|
||
// return 0;
|
||
angle = get_real_time_angle_degree();
|
||
|
||
fz->freq = et_zero_cross_freq_u16(&fz->zc, adc_buf, len, sampling_rate, DC_OFFSET_ADC_VALUE);
|
||
fz->trend = get_data_trend(&fz->trend_handle, fz->p50);
|
||
calculate_stage(fz);
|
||
|
||
ET_DBG("[%d]tr:%d, s:%.2f, p50:%.2f, freq:%.2f, angle:%.2f", fz->state, fz->trend, fz->slope, fz->p50, fz->freq,
|
||
angle);
|
||
if (fsm->fz_fsm_state)
|
||
{
|
||
return 0;
|
||
}
|
||
if (fz->calib_info[0].start_time == 0)
|
||
{
|
||
fz->calib_info[0].start_time = rt_tick_get_millisecond();
|
||
fz->calib_info[0].angle = 0;
|
||
fz->calib_info[0].target_angle = 0;
|
||
}
|
||
switch (fz->state)
|
||
{
|
||
case ZF_UNKNOWN_STAGE:
|
||
case ZF_SATURATED_STAGE:
|
||
fz->target_dir = MEASURE_DEF_DIR;
|
||
sv630p_speed_update(&sv630p_handle, FZ_UNKNOWN_STAGE_RPM * fz->target_dir);
|
||
break;
|
||
case ZF_WAVE_ENTER_STAGE:
|
||
sv630p_speed_update(&sv630p_handle, FZ_WAVE_ENTER_STAGE_RPM * fz->target_dir);
|
||
break;
|
||
case ZF_PREPARE_ENTER_STAGE:
|
||
sv630p_speed_update(&sv630p_handle, FZ_PREPARE_STAGE_RPM * fz->target_dir);
|
||
break;
|
||
case ZF_FAST_CLOSE_STAGE:
|
||
// 优化方向反转逻辑,减少过零点超调
|
||
if (get_data_trend(&fz->trend_handle, fz->p50) == TREND_INCREASE && fz->slope > 200 && fz->p50 < 40000)
|
||
{
|
||
fz->target_dir *= -1;
|
||
etk_position_pid_reset(&fz->pid); // 重置PID避免累积误差影响
|
||
trend_handle_reset(&fz->trend_handle); // 防止很快的重复进来
|
||
ET_WARN("passed the zero point and rotated in the opposite direction (slope=%.1f, p50=%.0f)", fz->slope,
|
||
fz->p50);
|
||
}
|
||
|
||
if (fz->p50 < ZERO_POS_THRESHOLD)
|
||
{
|
||
fz->zero_stable_count++;
|
||
if (fz->zero_stable_count > ZC_COUNT_STABLE_TIMES || fz->p50 < 0.03)
|
||
{
|
||
fz->state = ZF_ZERO_STAGE;
|
||
fz->calib_info[fz->calib_cnt].m_dir = sv630p_get_last_rpm(&sv630p_handle) > 0 ? 1 : -1;
|
||
sv630p_speed_mode_stop(&sv630p_handle);
|
||
uint8_t index = fz->calib_cnt % FZ_CALI_MAX_COUNT;
|
||
fz->calib_info[index].angle = angle;
|
||
fz->calib_info[index].end_time = rt_tick_get_millisecond();
|
||
fz->calib_info[index].power = fz->p50;
|
||
ET_INFO("update END calib index:%d", index);
|
||
ET_WARN("Find zero done:%.3f", angle);
|
||
fz->calib_cnt++;
|
||
etk_position_pid_reset(&fz->pid);
|
||
fz->target_dir = MEASURE_DEF_DIR;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
fz->zero_stable_count = 0;
|
||
#if 1
|
||
// 根据p50值大小采用三级控制策略,优化不同阶段的控制效果
|
||
if (fz->p50 > 40000)
|
||
{
|
||
rpm = 850.0f;
|
||
rpm = rpm * (fz->target_dir);
|
||
}
|
||
else if (fz->p50 > 10000)
|
||
{
|
||
rpm = etk_position_pid_update(&fz->pid, fz->p50, 0.535, 0.7f);
|
||
rpm = rpm * fz->target_dir;
|
||
}
|
||
else
|
||
#endif
|
||
{
|
||
// p50较小时使用保守PID控制,降低微分滤波系数以提高稳定性
|
||
rpm = etk_position_pid_update(&fz->pid, fz->p50, 0.535, 0.9f);
|
||
if (rpm > 350.0f)
|
||
rpm = 350.0f;
|
||
if (rpm < -350.0f)
|
||
rpm = -350.0f;
|
||
rpm = rpm * fz->target_dir;
|
||
}
|
||
|
||
if (fabs(rpm) < FZ_PRECISE_ADJUST_MIN_RPM)
|
||
{
|
||
rpm = (rpm >= 0) ? FZ_PRECISE_ADJUST_MIN_RPM : -FZ_PRECISE_ADJUST_MIN_RPM;
|
||
}
|
||
ET_DBG("rpm:%.2f", rpm);
|
||
sv630p_speed_update(&sv630p_handle, rpm);
|
||
}
|
||
break;
|
||
case ZF_ZERO_STAGE:
|
||
if (fsm->meas_mode == PM_MEAS_TEST_Mode && fz->calib_cnt < FZ_CALI_MAX_COUNT)
|
||
{
|
||
fz->calib_info[fz->calib_cnt].start_time = rt_tick_get_millisecond();
|
||
accuracy_auto_measurement_once(fz, angle);
|
||
}
|
||
else
|
||
{
|
||
sv630p_speed_mode_stop(&sv630p_handle);
|
||
measurement_info_print(fz);
|
||
fsm->fz_fsm_state = true; // test use
|
||
fz->calib_cnt = 0;
|
||
fsm->meas_mode = PM_MEAS_NORMAL_Mode;
|
||
fz->target_dir = MEASURE_DEF_DIR;
|
||
//ET_WARN("Mesaure time:%d ms", rt_tick_get_millisecond() - fz->calib_start_time);
|
||
}
|
||
break;
|
||
case ZF_FAST_LEAVE_STAGE:
|
||
fz->target_dir *= -1;
|
||
fz->state = ZF_FAST_CLOSE_STAGE;
|
||
sv630p_speed_update(&sv630p_handle, FZ_FAST_CLOSE_STAGE_RPM * fz->target_dir);
|
||
break;
|
||
case ZF_PREPARE_LEAVE_STAGE:
|
||
goto_prepare_leave_stage(fz, angle);
|
||
fz->state = ZF_PREPARE_ENTER_STAGE;
|
||
break;
|
||
case ZF_WAVE_LEAVE_STAGE:
|
||
fz->target_dir *= -1;
|
||
fz->state = ZF_WAVE_ENTER_STAGE;
|
||
break;
|
||
case ZF_STATE_MAX:
|
||
break;
|
||
default:
|
||
ET_INFO("not process state %d", fz->state);
|
||
break;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int pm_fsm_init(pm_fsm_t *fsm)
|
||
{
|
||
pm_fsm = fsm;
|
||
return 0;
|
||
}
|