1 /* 2 * Copyright (c) 2023 HPMicro 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 */ 7 #ifndef HPM_MCL_ENCODER_H 8 #define HPM_MCL_ENCODER_H 9 #include "hpm_mcl_common.h" 10 #include "hpm_mcl_filter.h" 11 12 enum { 13 mcl_encoder_start_sample_error = MAKE_STATUS(mcl_group_encoder, 0), 14 mcl_encoder_get_tick_error = MAKE_STATUS(mcl_group_encoder, 1), 15 mcl_encoder_update_tick_error = MAKE_STATUS(mcl_group_encoder, 2), 16 mcl_encoder_get_theta_error = MAKE_STATUS(mcl_group_encoder, 3), 17 mcl_encoder_not_ready = MAKE_STATUS(mcl_group_encoder, 4), 18 }; 19 20 typedef enum { 21 encoder_status_null = 0, 22 encoder_status_init = 1, 23 encoder_status_run = 2, 24 encoder_status_fail = 3, 25 } mcl_encoder_status_t; 26 27 /** 28 * @brief Method of calculating speed 29 * 30 */ 31 typedef enum { 32 encoder_method_t, 33 encoder_method_m, 34 encoder_method_m_t, 35 encoder_method_pll, 36 encoder_method_user, 37 } mcl_encoder_cal_speed_function_t; 38 39 /** 40 * @brief callback function 41 * 42 */ 43 typedef struct mcl_encoder_callback { 44 hpm_mcl_stat_t (*init)(void); 45 _FUNC_OPTIONAL_ hpm_mcl_stat_t (*update_trig_lead_tick)(uint32_t lead_tick); 46 _FUNC_OPTIONAL_ hpm_mcl_stat_t (*get_lead_tick)(uint32_t *lead_tick); 47 hpm_mcl_stat_t (*start_sample)(void); 48 hpm_mcl_stat_t (*get_theta)(float *theta); 49 _FUNC_OPTIONAL_ hpm_mcl_stat_t (*get_absolute_theta)(float *theta); 50 _FUNC_OPTIONAL_ hpm_mcl_stat_t (*process_by_user)(float theta, float *speed, float *theta_forecast); 51 } mcl_encoder_callback_t; 52 53 /** 54 * @brief Maximum memory required for computational speed, word 55 * 56 */ 57 #define MCL_ENCODER_CAL_STRUCT_MAX_MEMMORY (16) 58 typedef struct { 59 float theta_last; 60 float speed_last; 61 float ts_sigma; 62 } mcl_encoder_cal_speed_t_function_t; 63 64 typedef struct { 65 float theta_last; 66 float ts_sigma; 67 } mcl_encoder_cal_speed_m_function_t; 68 69 typedef struct { 70 float theta_last; 71 float ts_sigma; 72 float theta_sigma; 73 float speed_filter_last; 74 float speed_last; 75 } mcl_encoder_cal_speed_m_t_function_t; 76 77 /** 78 * @brief pll filter configuration 79 * 80 */ 81 typedef struct { 82 float kp; /**< scale factor */ 83 float ki; /**< Integration factor */ 84 } mcl_encoder_cal_speed_pll_cfg_t; 85 86 /** 87 * @brief Running data for the pll method of calculating speed 88 * 89 */ 90 typedef struct { 91 mcl_encoder_cal_speed_pll_cfg_t *cfg; 92 float *period_call_time_s; 93 float pi_integrator; 94 float omega_integrator; 95 float theta_last; 96 } mcl_encoder_cal_speed_pll_function_t; 97 98 /** 99 * @brief Encoder Configuration 100 * 101 */ 102 typedef struct { 103 uint8_t disable_start_sample_interrupt; 104 uint64_t communication_interval_us; /**< The communication interval of the communicating encoder ensures that an angle reading can be completed within the interval. Optical encoders can be read at any time, given as zero. */ 105 mcl_encoder_cal_speed_function_t speed_cal_method; 106 mcl_encoder_cal_speed_pll_cfg_t cal_speed_pll_cfg; 107 float timeout_s; /**< Timeout time, after this time angle is not updated, the speed will be cleared to zero. */ 108 float speed_abs_switch_m_t; /**< Use the m_t method to set the validity, the speed is greater than the set speed, use the m method, the speed is less than the set speed t use the t method to calculate the speed. */ 109 uint32_t precision; /**< Sensor accuracy, various encoders converted to number of lines. The maximum number of angular changes that can occur per revolution of the motor. */ 110 float period_call_time_s; /**< The time of the cycle call, the handler function should be called periodically, in s. */ 111 mcl_encoder_callback_t callback; 112 } mcl_encoer_cfg_t; 113 114 115 /** 116 * @brief Encoder operation data 117 * 118 */ 119 typedef struct { 120 union { 121 mcl_encoder_cal_speed_t_function_t t_method; 122 mcl_encoder_cal_speed_m_function_t m_method; 123 mcl_encoder_cal_speed_m_t_function_t m_t_method; 124 mcl_encoder_cal_speed_pll_function_t pll_method; 125 uint32_t memory[MCL_ENCODER_CAL_STRUCT_MAX_MEMMORY]; 126 } cal_speed; 127 mcl_filter_iir_df1_t *iirfilter; 128 mcl_encoder_status_t status; 129 mcl_encoer_cfg_t *cfg; 130 int32_t *mcu_clock_tick; 131 int32_t *pole_num; 132 float theta_initial; 133 float *current_loop_ts; 134 mcl_user_value_t force_set_theta; 135 struct { 136 float speed; 137 float theta; 138 float theta_forecast; 139 } result; 140 } mcl_encoder_t; 141 142 #ifdef __cplusplus 143 extern "C" { 144 #endif 145 146 /** 147 * @brief Initialize encoder data 148 * 149 * @param encoder @ref mcl_encoder_t 150 * @param mcl_cfg @ref mcl_cfg_t 151 * @param encoder_cfg @ref mcl_encoer_cfg_t 152 * @param iir @ref mcl_filter_iir_df1_t 153 * @return hpm_mcl_stat_t 154 */ 155 hpm_mcl_stat_t hpm_mcl_encoder_init(mcl_encoder_t *encoder, mcl_cfg_t *mcl_cfg, mcl_encoer_cfg_t *encoder_cfg, mcl_filter_iir_df1_t *iir); 156 157 /** 158 * @brief Encoder starts sampling 159 * 160 * @param encoder @ref mcl_encoder_t 161 * @return hpm_mcl_stat_t 162 */ 163 hpm_mcl_stat_t hpm_mcl_encoder_start_sample(mcl_encoder_t *encoder); 164 165 /** 166 * @brief Setting the initial angle of the encoder 167 * 168 * @param encoder @ref mcl_encoder_t 169 * @param theta Initial angle value 170 * @return hpm_mcl_stat_t 171 */ 172 hpm_mcl_stat_t hpm_mcl_encoder_set_initial_theta(mcl_encoder_t *encoder, float theta); 173 174 /** 175 * @brief Encoder processing, cycle call 176 * 177 * @param encoder @ref mcl_encoder_t 178 * @param tick_deta Difference in the number of cycles between two calls 179 * @return hpm_mcl_stat_t 180 */ 181 hpm_mcl_stat_t hpm_mcl_encoder_process(mcl_encoder_t *encoder, uint32_t tick_deta); 182 183 /** 184 * @brief Force update of encoder status 185 * 186 * @param encoder @ref mcl_encoder_t 187 * @param status @ref mcl_encoder_status_t 188 * @return hpm_mcl_stat_t 189 */ 190 hpm_mcl_stat_t hpm_mcl_encoder_set_status(mcl_encoder_t *encoder, mcl_encoder_status_t status); 191 192 /** 193 * @brief Get the encoder angle value 194 * 195 * @param encoder @ref mcl_encoder_t 196 * @return angle value, rad 197 */ 198 float hpm_mcl_encoder_get_theta(mcl_encoder_t *encoder); 199 200 /** 201 * @brief Get speed 202 * 203 * @param encoder @ref mcl_encoder_t 204 * @return rad/s 205 */ 206 float hpm_mcl_encoder_get_speed(mcl_encoder_t *encoder); 207 208 /** 209 * @brief Get the angle predicted from the speed 210 * 211 * @param encoder @ref mcl_encoder_t 212 * @return theta, rad 213 */ 214 float hpm_mcl_encoder_get_forecast_theta(mcl_encoder_t *encoder); 215 216 /** 217 * @brief Getting the raw angle data of the encoder 218 * 219 * @param encoder @ref mcl_encoder_t 220 * @return theta, rad 221 */ 222 float hpm_mcl_encoder_get_raw_theta(mcl_encoder_t *encoder); 223 224 /** 225 * @brief Force setting of the output angle of the encoder function 226 * 227 * @param encoder @ref mcl_encoder_t 228 * @param theta rad 229 * @param enable Enable or disable the forced output function 230 */ 231 void hpm_mcl_encoder_force_theta(mcl_encoder_t *encoder, float theta, bool enable); 232 233 /** 234 * @brief Get the absolute position of the angle 235 * 236 * @param encoder @ref mcl_encoder_t 237 * @param theta rad 238 * @return hpm_mcl_stat_t 239 */ 240 hpm_mcl_stat_t hpm_mcl_encoder_get_absolute_theta(mcl_encoder_t *encoder, float *theta); 241 242 #ifdef __cplusplus 243 } 244 #endif 245 246 #endif