adc.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /**********************************
  2. * 文件名称: adc.c
  3. * 功能描述: ADC采样和电机控制模块
  4. * 主要功能:
  5. * 1. 温度传感器采样与转换
  6. * 2. 电流偏移校准
  7. * 3. FOC算法计算
  8. * 4. ADC中断处理
  9. *
  10. * 注意事项:
  11. * - 使用ADC1进行电流和电压采样
  12. * - 使用ADC3进行UVW端电压和温度采样
  13. * - 采样频率为10kHz(与PWM频率同步)
  14. **********************************/
  15. #include "main.h"
  16. #include "arm_math.h"
  17. #include "adc.h"
  18. #include "board_config.h"
  19. #define _constrain(amt, low, high) ((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
  20. // 测试变量
  21. int32_t ia_test,ib_test,ic_test;
  22. float Ua,Ualpha,Ub,Ubeta, Uc, dc_a,dc_b,dc_c,sin_theta;
  23. //float err;
  24. // 电流和电压变量
  25. double Ia,Ib,Ic;
  26. float Ia_test,Ib_test,Ic_test;
  27. float Vbus;
  28. float Temp;
  29. // ADC采样值数组
  30. uint16_t ADC3ConvertedValue[ADC3_DMA_BUFFER_SIZE];
  31. uint16_t i = 0;
  32. // 电流偏移校准值
  33. uint32_t A_offset,B_offset,C_offset;
  34. uint8_t get_offset_flag = 0;
  35. uint8_t get_offset_sample_cnt = 0;
  36. // 速度闭环控制标志和参考电流
  37. u8 speed_close_loop_flag;
  38. float Iq_ref = 0.0f;
  39. float Id_ref = 0.0f;
  40. // EKF相关变量
  41. float EKF_Hz;
  42. // 角度变量
  43. float theta_add;
  44. float theta;
  45. // 电机参数(从其他模块导入)
  46. extern float Rs;
  47. extern float Ls;
  48. extern float flux;
  49. /**
  50. * @brief 根据热敏电阻阻值计算温度
  51. * @param rt_kohm: 热敏电阻阻值,单位为千欧姆
  52. * @retval 温度值,单位为摄氏度
  53. */
  54. float calculate_temperature(float rt_kohm)
  55. {
  56. float temp;
  57. const float Rp_kohm = 10.0f; /* 10K热敏电阻参考电阻 */
  58. const float T2 = (273.15f + 25.0f); /* T2温度,单位为K */
  59. const float Bx = 3380.0f; /* B值 */
  60. const float Ka = 273.15f; /* 绝对零度,单位为℃ */
  61. temp = rt_kohm / Rp_kohm; /* 电阻比值 */
  62. temp = log(temp); /* 取自然对数 */
  63. temp /= Bx; /* 除以B值 */
  64. temp += (1.0f / T2); /* 加上1/T2 */
  65. temp = 1.0f / temp; /* 取倒数 */
  66. temp -= Ka; /* 减去绝对零度 */
  67. return temp;
  68. }
  69. /**
  70. * @brief 获取电流偏移值
  71. * @param a_offset A相电流偏移值指针
  72. * @param b_offset B相电流偏移值指针
  73. * @note 采集128次求平均值,在PWM关闭时采集
  74. * - ADC1->JDR2: A相电流采样值
  75. * - ADC1->JDR3: B相电流采样值
  76. * - 右移7位 = 除以128求平均值
  77. */
  78. static void get_offset(uint32_t *a_offset, uint32_t *b_offset, uint32_t* c_offset)
  79. {
  80. if(get_offset_sample_cnt<128)
  81. {
  82. *a_offset += ADC1->JDR1;
  83. *b_offset += ADC2->JDR1;
  84. *c_offset += ADC3->JDR1;
  85. get_offset_sample_cnt++;
  86. }
  87. else
  88. {
  89. *a_offset >>= 7;
  90. *b_offset >>= 7;
  91. *c_offset >>= 7;
  92. get_offset_sample_cnt=0;
  93. TIM_CtrlPWMOutputs(PWM_TIM,DISABLE);
  94. get_offset_flag = 2;
  95. }
  96. }
  97. static void FOC_parm_input(void)
  98. {
  99. get_foc_input()->Id_ref = 0.0f;
  100. get_foc_input()->Tpwm = PWM_TIM_PULSE_TPWM; // FOC算法需要的PWM周期
  101. get_foc_input()->Udc = Vbus;
  102. get_foc_input()->Rs = Rs;
  103. get_foc_input()->Ls = Ls;
  104. get_foc_input()->flux = flux;
  105. get_foc_input()->ia = Ia;
  106. get_foc_input()->ib = Ib;
  107. get_foc_input()->ic = Ic;
  108. }
  109. static void FOC_parm_output(void)
  110. {
  111. EKF_Hz = get_foc_ouput()->EKF[2]/(2.0f*PI) ;
  112. }
  113. static void uvw_current_and_vbus_get(float* vbus, double* iu, double* iv, double* iw)
  114. {
  115. *vbus = ADC_TO_VBUS( ADC3ConvertedValue[ADC3_VBUS_INDEX]);
  116. *iu = ADC_TO_CURRENT((int16_t)((int16_t)ADC1->JDR1 - (int16_t)A_offset ));
  117. *iv = ADC_TO_CURRENT((int16_t)((int16_t)ADC2->JDR1 - (int16_t)B_offset ));
  118. *iw = ADC_TO_CURRENT((int16_t)((int16_t)ADC3->JDR1 - (int16_t)C_offset ));
  119. Ia_test = *iu;
  120. Ib_test = *iv;
  121. Ic_test = *iw;
  122. }
  123. /**
  124. * @brief 电机运行函数
  125. * @note 在PWM中断中调用,频率10kHz
  126. * - 读取ADC采样值,获取A/B相电流
  127. * - 根据基尔霍夫定律计算C相电流(Ia + Ib + Ic = 0)
  128. * - 速度环控制,计算速度PID输出
  129. * - 根据控制模式选择开环/闭环控制
  130. * - 执行FOC算法,计算SVPWM占空比
  131. * - 更新PWM占空比
  132. */
  133. void motor_run(void)
  134. {
  135. uvw_current_and_vbus_get(&Vbus, &Ia, &Ib, &Ic); // 获取母线电压,相电流
  136. // 选择电机运行方式 霍尔 开环加闭环 无感EKF
  137. if(speed_close_loop_flag==0) // 启动阶段,逐渐增加电流
  138. { // 电流从零开始,避免启动冲击
  139. if((Iq_ref<MOTOR_STARTUP_CURRENT)) // 未达到启动电流
  140. {
  141. Iq_ref += 0.00004f; // 缓慢增加电流
  142. }
  143. else
  144. {
  145. speed_close_loop_flag=1;
  146. }
  147. }
  148. else
  149. {
  150. if(speed_close_loop_flag==1)
  151. {
  152. if(Iq_ref>(MOTOR_STARTUP_CURRENT/2.0f))
  153. {
  154. Iq_ref -= 0.001f;
  155. }
  156. else
  157. {
  158. speed_close_loop_flag=2;
  159. }
  160. }
  161. }
  162. // 根据传感器类型选择FOC控制模式
  163. #ifdef HALL_FOC_SELECT // 使用霍尔传感器的FOC控制
  164. // if((hall_speed*2.0f*PI)>SPEED_LOOP_CLOSE_RAD_S) // 速度达到闭环阈值
  165. // {
  166. // FOC_Input.Id_ref = 0.0f;
  167. // Speed_Fdk = hall_speed*2.0f*PI;
  168. // FOC_Input.Iq_ref = Speed_Pid_Out;
  169. // }
  170. // else
  171. // {
  172. // FOC_Input.Id_ref = 0.0f;
  173. // FOC_Input.Iq_ref = Iq_ref;
  174. // Speed_Pid.I_Sum = Iq_ref;
  175. // }
  176. // FOC_Input.theta = hall_angle;
  177. // FOC_Input.speed_fdk = hall_speed*2.0f*PI;
  178. #endif
  179. #ifdef SENSORLESS_FOC_SELECT // 无传感器FOC控制
  180. if(FOC_Output.EKF[2]>SPEED_LOOP_CLOSE_RAD_S) // 速度达到闭环阈值
  181. {
  182. FOC_Input.Id_ref = 0.0f;
  183. Speed_Fdk = FOC_Output.EKF[2];
  184. FOC_Input.Iq_ref = Speed_Pid_Out;
  185. }
  186. else
  187. {
  188. FOC_Input.Id_ref = 0.0f;
  189. FOC_Input.Iq_ref = Iq_ref;
  190. Speed_Pid.I_Sum = Iq_ref;
  191. }
  192. FOC_Input.theta = FOC_Output.EKF[3];
  193. FOC_Input.speed_fdk = FOC_Output.EKF[2];
  194. #endif
  195. //============================== FOC算法计算 ==============================
  196. FOC_parm_input();
  197. FOC_parm_output();
  198. theta += 0.005f; // 使用 float 后缀
  199. if(theta >= 2.0f * PI)
  200. {
  201. theta -= 2.0f * PI;
  202. }
  203. // 额外保护
  204. if(theta < 0.0f || theta > 100.0f) // 异常保护
  205. {
  206. theta = 0.0f;
  207. }
  208. get_foc_input()->theta = theta;
  209. get_foc_input()->Id_ref = Id_ref;
  210. get_foc_input()->Iq_ref = Iq_ref;
  211. motor_foc_openloop_run();
  212. // foc_algorithm_step(); // 执行FOC算法,计算SVPWM占空比
  213. if(motor_start_stop==1)
  214. {
  215. PWM_TIM->CCR1 = (u16)(FOC_Output.Tcmp1); // 更新SVPWM占空比
  216. PWM_TIM->CCR2 = (u16)(FOC_Output.Tcmp2);
  217. PWM_TIM->CCR3 = (u16)(FOC_Output.Tcmp3);
  218. }
  219. else
  220. {
  221. PWM_TIM->CCR1 = PWM_TIM_PULSE>>1;
  222. PWM_TIM->CCR2 = PWM_TIM_PULSE>>1;
  223. PWM_TIM->CCR3 = PWM_TIM_PULSE>>1;
  224. }
  225. //communication_task();
  226. }
  227. /**
  228. * @brief ADC中断处理函数
  229. * @note 处理ADC注入通道转换完成中断
  230. * - 当偏移校准完成后,执行电机运行函数
  231. * - 当需要校准偏移时,执行偏移校准函数
  232. * 为什么VBUS不需要零偏校准? 开始采样即VBUS已经接在电源上了
  233. */
  234. void ADC_IRQHandler(void)
  235. {
  236. // 检查ADC1注入组完成(三个ADC已同步完成)
  237. if((SAMPLE_ADC1->SR & ADC_FLAG_JEOC) == ADC_FLAG_JEOC)
  238. {
  239. // 处理数据
  240. if(get_offset_flag == 2)
  241. {
  242. // hall_angle += hall_angle_add;
  243. // if(hall_angle < 0.0f)
  244. // hall_angle += 2.0f * PI;
  245. // else if(hall_angle > (2.0f * PI))
  246. // hall_angle -= 2.0f * PI;
  247. motor_run();
  248. }
  249. else if(get_offset_flag == 1) // get_offset_flag = 2 表示偏移已经获取完成
  250. {
  251. get_offset(&A_offset, &B_offset, &C_offset);
  252. }
  253. // 清除所有三个ADC的JEOC标志
  254. SAMPLE_ADC1->SR = ~ADC_SR_JEOC;
  255. SAMPLE_ADC2->SR = ~ADC_SR_JEOC;
  256. SAMPLE_ADC3->SR = ~ADC_SR_JEOC;
  257. }
  258. }