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.

262 lines
9.4 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. #include "ozone_control_service.h"
  2. #include "../zes8p5066lib/basic.h"
  3. #include "../zes8p5066lib/systicket.h"
  4. #include "frequency_sweep_service.h"
  5. #include "kalmanFilter.h"
  6. #include "state_machine.h"
  7. //
  8. #include "least_square_method.h"
  9. /**
  10. * @brief
  11. *
  12. * :
  13. * ------> ---->
  14. *
  15. **/
  16. #define PRV_START_EVENT (STATE_MACHINE_PUBLIC_EVENT + 1)
  17. #define PRV_STOP_EVENT (STATE_MACHINE_PUBLIC_EVENT + 2)
  18. state_machine_state_t m_states[] = {
  19. [kIdleState] =
  20. {
  21. .name = "kIdleState",
  22. .stateId = kIdleState,
  23. },
  24. [kBeforeWorkingStateSweepFrequency] =
  25. {
  26. .name = "kBeforeWorkingStateSweepFrequency",
  27. .stateId = kBeforeWorkingStateSweepFrequency,
  28. },
  29. [kWorkingState] = //
  30. {
  31. .name = "kWorkingState",
  32. .stateId = kWorkingState,
  33. }
  34. //
  35. };
  36. state_machine_t m_statemachine;
  37. static ozone_control_working_state_t s_workingstate;
  38. static uint16_t get_resonant_frequency(uint16_t startfreq, uint16_t step, uint16_t endfreq) {
  39. /**
  40. * @brief
  41. * ,
  42. *
  43. * http://192.168.1.3:3000/project_ozone_generator/doc/src/branch/master/ref/20220815频率-功率关系图.png
  44. */
  45. float minpower = 0;
  46. uint16_t retfreq = 0;
  47. bool inited = false;
  48. for (uint16_t freq = startfreq; freq <= endfreq; freq += step) {
  49. float power = frequency_sweep_get_power(freq);
  50. if (!inited) {
  51. minpower = power;
  52. retfreq = freq;
  53. inited = true;
  54. continue;
  55. }
  56. if (power < minpower) {
  57. minpower = power;
  58. retfreq = freq;
  59. }
  60. }
  61. return retfreq;
  62. }
  63. static KFP KFPConfig = KALMAN_FILTER_PARA;
  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. static void mf_get_ozone_power_reset_filter() { KFPConfig.LastP = __mf_get_ozone_power(); }
  72. static float mf_get_ozone_power() { return kalmanFilter(&KFPConfig, __mf_get_ozone_power()); }
  73. float get_expect_power() {
  74. float expectpower = 0;
  75. if (thisDevice.level == klevel1) {
  76. expectpower = LEVEL1_EXPECT_POWER;
  77. } else if (thisDevice.level == klevel2) {
  78. expectpower = LEVEL2_EXPECT_POWER;
  79. }
  80. return expectpower;
  81. }
  82. static float gety(int x) { return frequency_sweep_get_power((uint16_t)x); }
  83. static float compute_slope(uint16_t startfreq, uint16_t step, uint16_t endfreq) {
  84. float k = 0;
  85. float c = 0;
  86. least_square_method(startfreq, step, endfreq, gety, &c, &k);
  87. return k;
  88. }
  89. static float compute_avarage_power(uint16_t startfreq, uint16_t step, uint16_t endfreq) {
  90. float sumpower = 0;
  91. int count = 0;
  92. for (uint16_t freq = startfreq; freq <= endfreq; freq += step) {
  93. count++;
  94. float power = frequency_sweep_get_power(freq);
  95. sumpower += power;
  96. }
  97. return sumpower / count;
  98. }
  99. static state_machine_state_t* processBeforeWorkingStateSweepFrequency(state_machine_t* machine, state_machine_state_t* nowstate, int event) {
  100. /**
  101. * @brief
  102. */
  103. if (event == ENTER_STATE) {
  104. frequency_sweep_start(20000, 100, 41000, 3000);
  105. } else if (event == TIME_EVENT) {
  106. if (frequency_sweep_is_finished()) {
  107. s_workingstate.resonant_frequency = get_resonant_frequency(25000, 100, 35000); //谐振频率点
  108. s_workingstate.slope_when_freq40k = compute_slope(39000, 100, 41000); //利用最小二乘法计算出45K频率的斜率
  109. s_workingstate.avarage_power = compute_avarage_power(20000, 100, 41000); //平均功率
  110. printf("----------Summarize--------\n");
  111. printf("-resonant_frequency: %d\n", s_workingstate.resonant_frequency);
  112. printf("-slope_when_freq40k: %f\n", s_workingstate.slope_when_freq40k);
  113. printf("-avarage_power : %f\n", s_workingstate.avarage_power);
  114. s_workingstate.nowfreq = s_workingstate.resonant_frequency;
  115. return &m_states[kWorkingState];
  116. }
  117. } else if (event == EXIT_STATE) {
  118. frequency_sweep_stop();
  119. }
  120. return NULL;
  121. }
  122. static state_machine_state_t* processWorkingState(state_machine_t* machine, state_machine_state_t* nowstate, int event) {
  123. /**
  124. * @brief
  125. *
  126. * ([expertpower+window,expertpower-window])
  127. *
  128. */
  129. if (event == ENTER_STATE) {
  130. /**
  131. * @brief
  132. */
  133. if (s_workingstate.nowfreq < s_workingstate.resonant_frequency) {
  134. s_workingstate.nowfreq = s_workingstate.resonant_frequency;
  135. }
  136. port_ozone_pwm_set_duty(s_workingstate.nowfreq, 5000);
  137. port_ozone_pwm_start();
  138. s_workingstate.adjustedToTheProperPower = false;
  139. mf_get_ozone_power_reset_filter();
  140. printf("----------start working--------\n");
  141. } else if (event == TIME_EVENT) {
  142. float nowpower = mf_get_ozone_power();
  143. // float fanpower = mf_fan_get_power();
  144. if (s_workingstate.adjustedToTheProperPower) {
  145. /**
  146. * ([expertpower+window,expertpower-window])
  147. */
  148. // printf("change freq [ no ],freq %d, ozonePower %f-->%f fanPower:%f\n", s_workingstate.nowfreq, nowpower, get_expect_power(), fanpower);
  149. if (nowpower < (get_expect_power() - EXPECT_POWER_WINDONWS) || //
  150. nowpower > (get_expect_power() + EXPECT_POWER_WINDONWS)) {
  151. s_workingstate.adjustedToTheProperPower = false;
  152. if (nowpower < get_expect_power()) {
  153. s_workingstate.changefreqdirection = true;
  154. } else {
  155. s_workingstate.changefreqdirection = false;
  156. }
  157. }
  158. } else {
  159. /**
  160. *
  161. */
  162. if (s_workingstate.changefreqdirection) {
  163. if (nowpower < get_expect_power()) {
  164. s_workingstate.nowfreq += 25;
  165. if (s_workingstate.nowfreq > MAX_FREQ) s_workingstate.nowfreq = MAX_FREQ;
  166. printf("change freq [ up ],freq %d, ozonePower %f-->%f\n", s_workingstate.nowfreq, nowpower, get_expect_power());
  167. port_ozone_pwm_set_duty(s_workingstate.nowfreq, kconst_pwm_work_dutyns);
  168. } else {
  169. // printf("reach %f->%f\n", nowpower, get_expect_power());
  170. s_workingstate.adjustedToTheProperPower = true;
  171. }
  172. } else {
  173. if (nowpower > get_expect_power()) {
  174. s_workingstate.nowfreq -= 25;
  175. if (s_workingstate.nowfreq < s_workingstate.resonant_frequency) s_workingstate.nowfreq = s_workingstate.resonant_frequency;
  176. printf("change freq [down],freq %d, ozonePower %f-->%f\n", s_workingstate.nowfreq, nowpower, get_expect_power());
  177. port_ozone_pwm_set_duty(s_workingstate.nowfreq, kconst_pwm_work_dutyns);
  178. } else {
  179. // printf("reach %f->%f\n", nowpower, get_expect_power());
  180. s_workingstate.adjustedToTheProperPower = true;
  181. }
  182. }
  183. }
  184. } else if (event == EXIT_STATE) {
  185. port_ozone_pwm_stop();
  186. }
  187. return NULL;
  188. }
  189. static state_machine_state_t* state_machine_process_event(state_machine_t* machine, state_machine_state_t* nowstate, int event) {
  190. /**
  191. * @brief Start和Stop事件
  192. */
  193. if (event == PRV_START_EVENT || event == PRV_STOP_EVENT) {
  194. if (event == PRV_START_EVENT) {
  195. printf("start\n");
  196. return &m_states[kBeforeWorkingStateSweepFrequency];
  197. } else {
  198. printf("stop\n");
  199. return &m_states[kIdleState];
  200. }
  201. }
  202. /**
  203. * @brief
  204. */
  205. if /* */ (nowstate == &m_states[kIdleState]) {
  206. } else if (nowstate == &m_states[kBeforeWorkingStateSweepFrequency]) {
  207. return processBeforeWorkingStateSweepFrequency(machine, nowstate, event);
  208. } else if (nowstate == &m_states[kWorkingState]) {
  209. return processWorkingState(machine, nowstate, event);
  210. }
  211. return NULL;
  212. }
  213. /***********************************************************************************************************************
  214. * ======================================================Export======================================================= *
  215. ***********************************************************************************************************************/
  216. void ozone_control_init() { state_machine_init(&m_statemachine, m_states, ZARR_SIZE(m_states), state_machine_process_event); }
  217. void ozone_control_start() { state_machine_trigger_event(&m_statemachine, PRV_START_EVENT); }
  218. void ozone_control_stop() { state_machine_trigger_event(&m_statemachine, PRV_STOP_EVENT); }
  219. void ozone_control_schedule() {
  220. static uint32_t ticket = 0;
  221. if (systicket_haspassedms(ticket) > 10) {
  222. ticket = systicket_get_now_ms();
  223. state_machine_schedule_each10ms(&m_statemachine);
  224. }
  225. frequency_sweep_schedule();
  226. }
  227. ozone_control_working_state_id_t ozone_control_get_working_state_id() {
  228. if (state_machine_get_now_state(&m_statemachine) == &m_states[kIdleState]) {
  229. return kIdleState;
  230. }
  231. if (state_machine_get_now_state(&m_statemachine) == &m_states[kBeforeWorkingStateSweepFrequency]) {
  232. return kBeforeWorkingStateSweepFrequency;
  233. }
  234. if (state_machine_get_now_state(&m_statemachine) == &m_states[kWorkingState]) {
  235. return kWorkingState;
  236. }
  237. return kIdleState;
  238. }
  239. ozone_control_working_state_t* ozone_control_get_working_state() { return &s_workingstate; }
  240. float ozone_control_get_ozone_power() { return mf_get_ozone_power(); }
  241. float ozone_control_get_expect_power() { return get_expect_power(); }
  242. // float ozone_control_get_fan_power() { return mf_fan_get_power(); }