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.

134 lines
5.2 KiB

3 years ago
  1. #include "frequency_sweep_service.h"
  2. #include "zes8p5066lib/basic.h"
  3. #include "zes8p5066lib/systicket.h"
  4. /***********************************************************************************************************************
  5. * ========================================================================================================= *
  6. ***********************************************************************************************************************/
  7. typedef struct {
  8. float LastP; //上次估算协方差 初始化值为0.02
  9. float Now_P; //当前估算协方差 初始化值为0
  10. float out; //卡尔曼滤波器输出 初始化值为0
  11. float Kg; //卡尔曼增益 初始化值为0
  12. float Q; //过程噪声协方差 初始化值为0.001
  13. float R; //观测噪声协方差 初始化值为0.543
  14. } KFP; // Kalman Filter parameter
  15. // 2. 以高度为例 定义卡尔曼结构体并初始化参数
  16. /**
  17. *
  18. *@param KFP *kfp
  19. * float input
  20. *@return
  21. */
  22. float kalmanFilter(KFP* kfp, float input) {
  23. //预测协方差方程:k时刻系统估算协方差 = k-1时刻的系统协方差 + 过程噪声协方差
  24. kfp->Now_P = kfp->LastP + kfp->Q;
  25. //卡尔曼增益方程:卡尔曼增益 = k时刻系统估算协方差 / (k时刻系统估算协方差 + 观测噪声协方差)
  26. kfp->Kg = kfp->Now_P / (kfp->Now_P + kfp->R);
  27. //更新最优值方程:k时刻状态变量的最优值 = 状态变量的预测值 + 卡尔曼增益 * (测量值 - 状态变量的预测值)
  28. kfp->out = kfp->out + kfp->Kg * (input - kfp->out); //因为这一次的预测值就是上一次的输出值
  29. //更新协方差方程: 本次的系统协方差付给 kfp->LastP 威下一次运算准备。
  30. kfp->LastP = (1 - kfp->Kg) * kfp->Now_P;
  31. return kfp->out;
  32. }
  33. /***********************************************************************************************************************
  34. * ====================================================THIS_MODULE==================================================== *
  35. ***********************************************************************************************************************/
  36. struct {
  37. float power_table[350];
  38. uint16_t startfreq;
  39. uint16_t endfreq;
  40. uint16_t step;
  41. bool is_schedule;
  42. bool firstloop;
  43. uint16_t nowfreq;
  44. uint32_t startticket;
  45. uint32_t dutyns;
  46. } this;
  47. KFP KFPConfig = {0.02, 0, 0, 0, 0.05, 0.543};
  48. /***********************************************************************************************************************
  49. * ====================================================PowerTable===================================================== *
  50. ***********************************************************************************************************************/
  51. static void mf_setpower(uint16_t freq, float power) {
  52. uint16_t index = (freq - this.startfreq) / this.step;
  53. if (index >= ZARR_SIZE(this.power_table)) return;
  54. this.power_table[index] = power;
  55. }
  56. static float mf_getpower(uint16_t freq) {
  57. uint16_t index = (freq - this.startfreq) / this.step;
  58. if (index >= ZARR_SIZE(this.power_table)) return 0;
  59. if (index > (this.endfreq - this.startfreq) / this.step) {
  60. return 0;
  61. }
  62. return this.power_table[index];
  63. }
  64. static float mf_get_ozone_power() {
  65. float powersum = 0;
  66. for (size_t i = 0; i < 10; i++) {
  67. powersum += port_adc_get_ozone_generator_power();
  68. }
  69. return powersum / 10;
  70. }
  71. /***********************************************************************************************************************
  72. * ======================================================Extern======================================================= *
  73. ***********************************************************************************************************************/
  74. void frequency_sweep_start(uint32_t startfreq, uint32_t step, uint32_t endfreq, uint16_t dutyns) {
  75. this.startfreq = startfreq;
  76. this.endfreq = endfreq;
  77. this.step = step;
  78. this.dutyns = dutyns;
  79. this.firstloop = true;
  80. this.is_schedule = true;
  81. this.startticket = systicket_get_now_ms();
  82. this.nowfreq = this.startfreq;
  83. printf("cls\n");
  84. }
  85. bool frequency_sweep_is_finished() { return !this.is_schedule; }
  86. float frequency_sweep_get_power(uint16_t freq) { return mf_getpower(freq); }
  87. void frequency_sweep_schedule() {
  88. if (!this.is_schedule) {
  89. return;
  90. }
  91. /// loop
  92. if (systicket_haspassedms(this.startticket) > 1) {
  93. /**
  94. * @brief
  95. */
  96. port_ozone_pwm_set_duty(this.nowfreq, this.dutyns);
  97. port_ozone_pwm_start();
  98. systicket_delay_ms(3);
  99. /**
  100. * @brief
  101. */
  102. float power = mf_get_ozone_power();
  103. if (this.firstloop) {
  104. KFPConfig.LastP = power;
  105. }
  106. float afterfileter = kalmanFilter(&KFPConfig, power);
  107. mf_setpower(this.nowfreq, afterfileter);
  108. printf("%d,%f,%f\n", this.nowfreq, afterfileter, power);
  109. /**
  110. * @brief
  111. */
  112. this.nowfreq += this.step;
  113. if (this.nowfreq > this.endfreq) {
  114. this.is_schedule = false;
  115. }
  116. port_ozone_pwm_stop();
  117. //
  118. this.firstloop = false;
  119. this.startticket = systicket_get_now_ms();
  120. }
  121. }