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.

270 lines
9.6 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
  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 float mf_fan_get_power() {
  72. float fanpower = 0;
  73. for (size_t i = 0; i < 20; i++) {
  74. fanpower += port_adc_get_fan_power();
  75. }
  76. return fanpower / 20;
  77. }
  78. static void mf_get_ozone_power_reset_filter() { KFPConfig.LastP = __mf_get_ozone_power(); }
  79. static float mf_get_ozone_power() { return kalmanFilter(&KFPConfig, __mf_get_ozone_power()); }
  80. float get_expect_power() {
  81. float expectpower = 0;
  82. if (thisDevice.level == klevel1) {
  83. expectpower = LEVEL1_EXPECT_POWER;
  84. } else if (thisDevice.level == klevel2) {
  85. expectpower = LEVEL2_EXPECT_POWER;
  86. }
  87. return expectpower;
  88. }
  89. static float gety(int x) { return frequency_sweep_get_power((uint16_t)x); }
  90. static float compute_slope(uint16_t startfreq, uint16_t step, uint16_t endfreq) {
  91. float k = 0;
  92. float c = 0;
  93. least_square_method(startfreq, step, endfreq, gety, &c, &k);
  94. return k;
  95. }
  96. static float compute_avarage_power(uint16_t startfreq, uint16_t step, uint16_t endfreq) {
  97. float sumpower = 0;
  98. int count = 0;
  99. for (uint16_t freq = startfreq; freq <= endfreq; freq += step) {
  100. count++;
  101. float power = frequency_sweep_get_power(freq);
  102. sumpower += power;
  103. }
  104. return sumpower / count;
  105. }
  106. static state_machine_state_t* processBeforeWorkingStateSweepFrequency(state_machine_t* machine, state_machine_state_t* nowstate, int event) {
  107. /**
  108. * @brief
  109. */
  110. if (event == ENTER_STATE) {
  111. frequency_sweep_start(20000, 100, 41000, 3000);
  112. } else if (event == TIME_EVENT) {
  113. if (frequency_sweep_is_finished()) {
  114. s_workingstate.resonant_frequency = get_resonant_frequency(25000, 100, 35000); //谐振频率点
  115. s_workingstate.slope_when_freq40k = compute_slope(39000, 100, 41000); //利用最小二乘法计算出45K频率的斜率
  116. s_workingstate.avarage_power = compute_avarage_power(20000, 100, 41000); //平均功率
  117. printf("----------Summarize--------\n");
  118. printf("-resonant_frequency: %d\n", s_workingstate.resonant_frequency);
  119. printf("-slope_when_freq40k: %f\n", s_workingstate.slope_when_freq40k);
  120. printf("-avarage_power : %f\n", s_workingstate.avarage_power);
  121. s_workingstate.nowfreq = s_workingstate.resonant_frequency;
  122. return &m_states[kWorkingState];
  123. }
  124. } else if (event == EXIT_STATE) {
  125. frequency_sweep_stop();
  126. }
  127. return NULL;
  128. }
  129. static state_machine_state_t* processWorkingState(state_machine_t* machine, state_machine_state_t* nowstate, int event) {
  130. /**
  131. * @brief
  132. *
  133. * ([expertpower+window,expertpower-window])
  134. *
  135. */
  136. if (event == ENTER_STATE) {
  137. /**
  138. * @brief
  139. */
  140. if (s_workingstate.nowfreq < s_workingstate.resonant_frequency) {
  141. s_workingstate.nowfreq = s_workingstate.resonant_frequency;
  142. }
  143. port_ozone_pwm_set_duty(s_workingstate.nowfreq, 5000);
  144. port_ozone_pwm_start();
  145. s_workingstate.adjustedToTheProperPower = false;
  146. mf_get_ozone_power_reset_filter();
  147. printf("----------start working--------\n");
  148. } else if (event == TIME_EVENT) {
  149. float nowpower = mf_get_ozone_power();
  150. float fanpower = mf_fan_get_power();
  151. if (s_workingstate.adjustedToTheProperPower) {
  152. /**
  153. * ([expertpower+window,expertpower-window])
  154. */
  155. if (nowpower < (get_expect_power() - EXPECT_POWER_WINDONWS) || //
  156. nowpower > (get_expect_power() + EXPECT_POWER_WINDONWS)) {
  157. s_workingstate.adjustedToTheProperPower = false;
  158. printf("change freq [ no ],freq %d, ozonePower %f-->%f fanPower:%f\n", s_workingstate.nowfreq, nowpower, get_expect_power(), fanpower);
  159. if (nowpower < get_expect_power()) {
  160. s_workingstate.changefreqdirection = true;
  161. } else {
  162. s_workingstate.changefreqdirection = false;
  163. }
  164. }
  165. } else {
  166. /**
  167. *
  168. */
  169. if (s_workingstate.changefreqdirection) {
  170. if (nowpower < get_expect_power()) {
  171. s_workingstate.nowfreq += 25;
  172. if (s_workingstate.nowfreq > MAX_FREQ) s_workingstate.nowfreq = MAX_FREQ;
  173. printf("change freq [ up ],freq %d, ozonePower %f-->%f fanPower:%f\n", s_workingstate.nowfreq, nowpower, get_expect_power(), fanpower);
  174. port_ozone_pwm_set_duty(s_workingstate.nowfreq, kconst_pwm_work_dutyns);
  175. } else {
  176. // printf("reach %f->%f\n", nowpower, get_expect_power());
  177. s_workingstate.adjustedToTheProperPower = true;
  178. }
  179. } else {
  180. if (nowpower > get_expect_power()) {
  181. s_workingstate.nowfreq -= 25;
  182. if (s_workingstate.nowfreq < s_workingstate.resonant_frequency) s_workingstate.nowfreq = s_workingstate.resonant_frequency;
  183. printf("change freq [down],freq %d, ozonePower %f-->%f fanPower:%f\n", s_workingstate.nowfreq, nowpower, get_expect_power(), fanpower);
  184. port_ozone_pwm_set_duty(s_workingstate.nowfreq, kconst_pwm_work_dutyns);
  185. } else {
  186. // printf("reach %f->%f\n", nowpower, get_expect_power());
  187. s_workingstate.adjustedToTheProperPower = true;
  188. }
  189. }
  190. }
  191. } else if (event == EXIT_STATE) {
  192. port_ozone_pwm_stop();
  193. }
  194. return NULL;
  195. }
  196. static state_machine_state_t* state_machine_process_event(state_machine_t* machine, state_machine_state_t* nowstate, int event) {
  197. /**
  198. * @brief Start和Stop事件
  199. */
  200. if (event == PRV_START_EVENT || event == PRV_STOP_EVENT) {
  201. if (event == PRV_START_EVENT) {
  202. printf("start\n");
  203. return &m_states[kBeforeWorkingStateSweepFrequency];
  204. } else {
  205. printf("stop\n");
  206. return &m_states[kIdleState];
  207. }
  208. }
  209. /**
  210. * @brief
  211. */
  212. if /* */ (nowstate == &m_states[kIdleState]) {
  213. } else if (nowstate == &m_states[kBeforeWorkingStateSweepFrequency]) {
  214. return processBeforeWorkingStateSweepFrequency(machine, nowstate, event);
  215. } else if (nowstate == &m_states[kWorkingState]) {
  216. return processWorkingState(machine, nowstate, event);
  217. }
  218. return NULL;
  219. }
  220. /***********************************************************************************************************************
  221. * ======================================================Export======================================================= *
  222. ***********************************************************************************************************************/
  223. void ozone_control_init() { state_machine_init(&m_statemachine, m_states, ZARR_SIZE(m_states), state_machine_process_event); }
  224. void ozone_control_start() { state_machine_trigger_event(&m_statemachine, PRV_START_EVENT); }
  225. void ozone_control_stop() { state_machine_trigger_event(&m_statemachine, PRV_STOP_EVENT); }
  226. void ozone_control_schedule() {
  227. static uint32_t ticket = 0;
  228. if (systicket_haspassedms(ticket) > 10) {
  229. ticket = systicket_get_now_ms();
  230. state_machine_schedule_each10ms(&m_statemachine);
  231. }
  232. frequency_sweep_schedule();
  233. }
  234. ozone_control_working_state_id_t ozone_control_get_working_state_id() {
  235. if (state_machine_get_now_state(&m_statemachine) == &m_states[kIdleState]) {
  236. return kIdleState;
  237. }
  238. if (state_machine_get_now_state(&m_statemachine) == &m_states[kBeforeWorkingStateSweepFrequency]) {
  239. return kBeforeWorkingStateSweepFrequency;
  240. }
  241. if (state_machine_get_now_state(&m_statemachine) == &m_states[kWorkingState]) {
  242. return kWorkingState;
  243. }
  244. return kIdleState;
  245. }
  246. ozone_control_working_state_t* ozone_control_get_working_state() { return &s_workingstate; }
  247. float ozone_control_get_ozone_power() { return mf_get_ozone_power(); }
  248. float ozone_control_get_expect_power() { return get_expect_power(); }
  249. float ozone_control_get_fan_power() { return mf_fan_get_power(); }