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.

585 lines
18 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
4 years ago
3 years ago
4 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 <stdbool.h> //定义布尔
  2. #include <string.h>
  3. #include "board.h"
  4. //
  5. #include "zes8p5066lib/basic.h"
  6. #include "zes8p5066lib/gpio.h"
  7. #include "zes8p5066lib/key.h"
  8. #include "zes8p5066lib/systicket.h"
  9. #include "zes8p5066lib/uart0.h"
  10. //
  11. #include "service/light_control_service.h"
  12. #include "service/thisdevice.h"
  13. #include "test.h"
  14. #include "zsimple_timer/zsimple_timer.h"
  15. /***********************************************************************************************************************
  16. * =========================================================================================================== *
  17. ***********************************************************************************************************************/
  18. void onkey(zkey_t* key, zkey_state_t key_state);
  19. /***********************************************************************************************************************
  20. * =========================================================================================================== *
  21. ***********************************************************************************************************************/
  22. static zkey_t s_keys[] = {
  23. ZKEY_INIT("powerkey", port_gpio_get_power_key_state), //电源按键
  24. ZKEY_INIT("levelkey", port_gpio_get_level_key_state), //左1
  25. ZKEY_INIT("timerkey", port_gpio_get_timer_key_state), //左2
  26. ZKEY_INIT("intervalkey", port_gpio_get_interval_key_state), //左3
  27. };
  28. zkey_module_t key_module = ZMODULE_INIT(s_keys, onkey);
  29. static zsimple_timer_t zsimple_timer_mem[10]; //最多同时存在10个定时器
  30. zsimple_timer_t* debuglighttimer;
  31. /***********************************************************************************************************************
  32. * =============================================================================================================== *
  33. ***********************************************************************************************************************/
  34. static uint32_t compute_countdown_num(int countdowns) {
  35. if (countdowns) return countdowns / kconst_countdown_step_s + !!(countdowns % kconst_countdown_step_s);
  36. }
  37. static void shutdwon() {
  38. printf("power off\n");
  39. thisDevice.poweron = false;
  40. port_fan_set(false);
  41. //@TODO:关闭臭氧
  42. }
  43. static void increase_and_assign_countdonwnum() {
  44. if (thisDevice.countdonwnum == 4) {
  45. thisDevice.countdonwnum = 0;
  46. thisDevice.countdonwnum_s = 0;
  47. thisDevice.countdonw_setting_num = 0;
  48. lcs_active_input(knone_active);
  49. } else {
  50. thisDevice.countdonwnum_s = (thisDevice.countdonwnum + 1) * kconst_countdown_step_s;
  51. thisDevice.countdonwnum = thisDevice.countdonwnum + 1;
  52. thisDevice.countdonw_setting_num = thisDevice.countdonwnum;
  53. thisDevice.countdonw_start_ticket = systicket_get_now_ms();
  54. }
  55. }
  56. static void set_countdown(int countdownnum) {
  57. thisDevice.countdonwnum = countdownnum;
  58. thisDevice.countdonwnum_s = thisDevice.countdonwnum * kconst_countdown_step_s;
  59. thisDevice.countdonw_setting_num = thisDevice.countdonwnum;
  60. thisDevice.countdonw_start_ticket = systicket_get_now_ms();
  61. }
  62. static void onkey(zkey_t* key, zkey_state_t key_state) {
  63. if /* */ (strcmp(key->name, "powerkey") == 0 && zks_rising_edge == key_state) {
  64. printf("on %s \n", key->name);
  65. if (!thisDevice.poweron) {
  66. printf("power on\n");
  67. thisDevice.poweron = true;
  68. thisDevice.level = klevel1;
  69. thisDevice.mode = knormal;
  70. //设置灯光效果
  71. port_fan_set(true);
  72. //@TODO:启动臭氧
  73. } else {
  74. shutdwon();
  75. }
  76. return;
  77. }
  78. // levelkey
  79. if (strcmp(key->name, "levelkey") == 0 && zks_rising_edge == key_state) {
  80. if (!thisDevice.poweron) return;
  81. printf("on %s \n", key->name);
  82. /**
  83. * @brief
  84. */
  85. if (!lcs_input_is_active(kchange_level_input)) {
  86. lcs_active_input(kchange_level_input);
  87. return;
  88. }
  89. if (thisDevice.level == klevel1) {
  90. printf("changet level to level2\n");
  91. thisDevice.level = klevel2;
  92. //更改臭氧状态
  93. } else if (thisDevice.level == klevel2) {
  94. printf("changet level to level1\n");
  95. thisDevice.level = klevel1;
  96. //更改臭氧状态
  97. }
  98. lcs_active_input(kchange_level_input);
  99. return;
  100. }
  101. // timerkey
  102. if (strcmp(key->name, "timerkey") == 0 && zks_rising_edge == key_state) {
  103. if (!thisDevice.poweron) return;
  104. printf("on %s \n", key->name);
  105. if (!lcs_input_is_active(kchange_countdonw_time_input)) {
  106. lcs_active_input(kchange_countdonw_time_input);
  107. if (thisDevice.mode != ktimingMode || thisDevice.countdonwnum_s == 0) {
  108. set_countdown(1);
  109. thisDevice.mode = ktimingMode;
  110. }
  111. return;
  112. }
  113. lcs_active_input(kchange_countdonw_time_input);
  114. increase_and_assign_countdonwnum();
  115. }
  116. if (strcmp(key->name, "intervalkey") == 0 && zks_rising_edge == key_state) {
  117. if (!thisDevice.poweron) return;
  118. printf("on %s \n", key->name);
  119. if (!lcs_input_is_active(kchange_intermittentmode_time_input)) {
  120. lcs_active_input(kchange_intermittentmode_time_input);
  121. if (thisDevice.mode != kintermittentMode || thisDevice.countdonwnum_s == 0) {
  122. set_countdown(1);
  123. thisDevice.mode = kintermittentMode;
  124. }
  125. return;
  126. }
  127. lcs_active_input(kchange_intermittentmode_time_input);
  128. increase_and_assign_countdonwnum();
  129. }
  130. }
  131. void compute_countdown() {
  132. if /* */ (thisDevice.mode == knormal) {
  133. thisDevice.countdonwnum = 0;
  134. thisDevice.countdonwnum_s = 0;
  135. } else if (thisDevice.mode == ktimingMode || thisDevice.mode == kintermittentMode) {
  136. if (thisDevice.countdonwnum_s != 0) {
  137. thisDevice.countdonwnum_s = //
  138. thisDevice.countdonw_setting_num * kconst_countdown_step_s - systicket_haspassedms(thisDevice.countdonw_start_ticket) / 1000;
  139. thisDevice.countdonwnum = compute_countdown_num(thisDevice.countdonwnum_s);
  140. }
  141. }
  142. }
  143. void process_countdwonevent() {
  144. //计算countdown
  145. compute_countdown();
  146. /**
  147. * @brief
  148. */
  149. if (thisDevice.mode == ktimingMode) {
  150. //定时自动关机
  151. if (thisDevice.poweron) {
  152. if (thisDevice.countdonwnum_s == 0) {
  153. shutdwon();
  154. }
  155. }
  156. } else if (thisDevice.mode == kintermittentMode) {
  157. /**
  158. * @brief
  159. * ,,,,,
  160. */
  161. if (!thisDevice.intermittentMode_idle) {
  162. if (thisDevice.countdonwnum_s == 0) {
  163. //切换状态到待机状态
  164. // TODO:关闭臭氧
  165. thisDevice.intermittentMode_idle = true;
  166. port_fan_set(false);
  167. }
  168. } else {
  169. if (systicket_haspassedms(thisDevice.countdonw_start_ticket) / 1000 > INTERMITTENTMODE_PERIOD_S) {
  170. thisDevice.intermittentMode_idle = false;
  171. set_countdown(thisDevice.countdonw_setting_num);
  172. //启动设备
  173. port_fan_set(true);
  174. }
  175. }
  176. }
  177. };
  178. void do_debug_light_state(zsimple_timer_t* handler) {
  179. static uint8_t debug_led_state = 1;
  180. debug_led_state = !debug_led_state;
  181. port_debug_set(debug_led_state);
  182. }
  183. #if 0
  184. typedef struct {
  185. float LastP; //上次估算协方差 初始化值为0.02
  186. float Now_P; //当前估算协方差 初始化值为0
  187. float out; //卡尔曼滤波器输出 初始化值为0
  188. float Kg; //卡尔曼增益 初始化值为0
  189. float Q; //过程噪声协方差 初始化值为0.001
  190. float R; //观测噪声协方差 初始化值为0.543
  191. } KFP; // Kalman Filter parameter
  192. // 2. 以高度为例 定义卡尔曼结构体并初始化参数
  193. KFP KFP_height = {0.02, 0, 0, 0, 0.03, 0.543};
  194. /**
  195. *
  196. *@param KFP *kfp
  197. * float input
  198. *@return
  199. */
  200. float kalmanFilter(KFP* kfp, float input) {
  201. //预测协方差方程:k时刻系统估算协方差 = k-1时刻的系统协方差 + 过程噪声协方差
  202. kfp->Now_P = kfp->LastP + kfp->Q;
  203. //卡尔曼增益方程:卡尔曼增益 = k时刻系统估算协方差 / (k时刻系统估算协方差 + 观测噪声协方差)
  204. kfp->Kg = kfp->Now_P / (kfp->Now_P + kfp->R);
  205. //更新最优值方程:k时刻状态变量的最优值 = 状态变量的预测值 + 卡尔曼增益 * (测量值 - 状态变量的预测值)
  206. kfp->out = kfp->out + kfp->Kg * (input - kfp->out); //因为这一次的预测值就是上一次的输出值
  207. //更新协方差方程: 本次的系统协方差付给 kfp->LastP 威下一次运算准备。
  208. kfp->LastP = (1 - kfp->Kg) * kfp->Now_P;
  209. return kfp->out;
  210. }
  211. float derivative(float now) {
  212. static float last = 0;
  213. float diff = now - last;
  214. last = now;
  215. return diff;
  216. }
  217. void printf_ozone_freq_and_power_table() {
  218. /**
  219. * @brief
  220. */
  221. float startfreq = 10 * 1000;
  222. float stepfreq = 100;
  223. float nowfreq = startfreq;
  224. port_ozone_pwm_set_duty(nowfreq, 1000);
  225. port_ozone_pwm_start();
  226. systicket_delay_ms(10);
  227. bool first = true;
  228. while (true) {
  229. port_ozone_pwm_set_duty(nowfreq, 3000);
  230. systicket_delay_ms(2);
  231. float power = get_ozone_power();
  232. // printf("%f %f\n", nowfreq, freq);
  233. // printf("{freq power:%f,%f}\r\n", nowfreq, power);
  234. // printf("{freq power:%f,%f}\r\n", nowfreq, power);
  235. if (first) {
  236. // kalmanFilter(&KFP_height, power);
  237. KFP_height.LastP = power;
  238. first = false;
  239. }
  240. float afterfilter = kalmanFilter(&KFP_height, power);
  241. printf("%f,%f,%f,%f\r\n", nowfreq, power, afterfilter,derivative(afterfilter)*10);
  242. // printf("{power:%f}\r\n", power);
  243. nowfreq += stepfreq;
  244. if (nowfreq >= 40 * 1000) break;
  245. }
  246. port_ozone_pwm_set_duty(33000, 3000);
  247. port_fan_set(true);
  248. while (true) {
  249. }
  250. port_ozone_pwm_stop();
  251. while (true) {
  252. systicket_delay_ms(2);
  253. float power = get_ozone_power();
  254. float afterfilter = kalmanFilter(&KFP_height, power);
  255. nowfreq+=50;
  256. printf("%f,%f,%f\r\n", nowfreq, power, afterfilter);
  257. }
  258. }
  259. #endif
  260. #if 0
  261. float kalmanFilter1(float input) {
  262. static KFP kfp = {0.02, 0, 0, 0, 0.03, 0.543};
  263. return kalmanFilter(&kfp, input);
  264. }
  265. float kalmanFilter2(float input) {
  266. static KFP kfp = {0.02, 0, 0, 0, 0.03, 0.543};
  267. return kalmanFilter(&kfp, input);
  268. }
  269. float kalmanFilter3(float input) {
  270. static KFP kfp = {0.02, 0, 0, 0, 0.03, 0.543};
  271. return kalmanFilter(&kfp, input);
  272. }
  273. float kalmanFilter4(float input) {
  274. static KFP kfp = {0.02, 0, 0, 0, 0.03, 0.543};
  275. return kalmanFilter(&kfp, input);
  276. }
  277. float set_pwm_and_get_power(uint32_t freq, uint32_t dutyns) {
  278. port_ozone_pwm_set_duty(freq, dutyns);
  279. systicket_delay_ms(2);
  280. float power1 = get_ozone_power();
  281. return power1;
  282. }
  283. void printf_ozone_freq_and_power_table() {
  284. /**
  285. * @brief
  286. */
  287. uint32_t startfreq = 10 * 1000;
  288. uint32_t stepfreq = 100;
  289. uint32_t nowfreq = startfreq;
  290. port_ozone_pwm_set_duty(nowfreq, 1000);
  291. // port_ozone_pwm_stop();
  292. port_ozone_pwm_start();
  293. systicket_delay_ms(10);
  294. bool first = true;
  295. while (true) {
  296. // printf("%d,%f,%f,%f,%f\r\n", nowfreq, //
  297. // /*kalmanFilter1*/(set_pwm_and_get_power(nowfreq, 2000)), //
  298. // /*kalmanFilter2*/(set_pwm_and_get_power(nowfreq, 4000)), //
  299. // /*kalmanFilter3*/(set_pwm_and_get_power(nowfreq, 6000)), //
  300. // /*kalmanFilter4*/(set_pwm_and_get_power(nowfreq, 8000)) //
  301. // );
  302. // printf("{power:%f}\r\n", power);
  303. nowfreq += stepfreq;
  304. if (nowfreq >= 40 * 1000) break;
  305. }
  306. port_ozone_pwm_set_duty(33000, 3500);
  307. port_fan_set(true);
  308. while (true) {
  309. }
  310. }
  311. #endif
  312. // void printf_ozone_freq_and_power_table() {
  313. // /**
  314. // * @brief 打印臭氧发生器和频率之间的关系
  315. // */
  316. // float startfreq = 20 * 1000;
  317. // float stepfreq = 50;
  318. // float nowfreq = startfreq;
  319. // // port_ozone_pwm_set_duty(nowfreq, 1000);
  320. // // port_ozone_pwm_start();
  321. // // systicket_delay_ms(10);
  322. // while (true) {
  323. // // printf("{power:%f}\r\n", nowfreq);
  324. // printf("%d,%d\r\n", (int)nowfreq,(int)nowfreq);
  325. // systicket_delay_ms(100);
  326. // nowfreq += stepfreq;
  327. // // if (nowfreq >= 40 * 1000) break;
  328. // }
  329. // port_ozone_pwm_stop();
  330. // }
  331. float s_power_table[200];
  332. void setpower(uint16_t freq, float power) {
  333. /**
  334. * @brief
  335. * [0]->20k
  336. * [1]->20.1k
  337. */
  338. uint16_t index = (freq - 20000) / 100;
  339. if (index < 0) return;
  340. if (index >= ARRAY_SIZE(s_power_table)) return;
  341. s_power_table[index] = power;
  342. }
  343. float getpower(uint16_t freq) {
  344. /**
  345. * @brief
  346. * [0]->20k
  347. * [1]->20.1k
  348. */
  349. uint16_t index = (freq - 20000) / 100;
  350. if (index < 0) return 0;
  351. if (index >= ARRAY_SIZE(s_power_table)) return 0;
  352. return s_power_table[index];
  353. }
  354. float get_ozone_power() {
  355. float powersum = 0;
  356. for (size_t i = 0; i < 20; i++) {
  357. powersum += port_adc_get_ozone_generator_power();
  358. }
  359. return powersum / 20;
  360. }
  361. float set_pwm_and_get_power(uint32_t freq, uint32_t dutyns) {
  362. port_ozone_pwm_set_duty(freq, dutyns);
  363. systicket_delay_ms(3);
  364. float power1 = get_ozone_power();
  365. return power1;
  366. }
  367. void create_power_table() {
  368. /**
  369. * @brief
  370. */
  371. port_ozone_pwm_set_duty(20000, 3000);
  372. port_ozone_pwm_start();
  373. systicket_delay_ms(3);
  374. for (size_t i = 0; i < 200; i++) {
  375. nowfreq = 20000 + i * 100;
  376. float power = set_pwm_and_get_power(nowfreq, 3000);
  377. setpower(nowfreq, power);
  378. }
  379. port_ozone_pwm_stop();
  380. printf("%d,%f\r\n", nowfreq, power);
  381. }
  382. void printf_ozone_freq_and_power_table() {
  383. /**
  384. * @brief
  385. */
  386. for (size_t i = 0; i < 200; i++) {
  387. nowfreq = 20000 + i * 100;
  388. float power = getpower(nowfreq);
  389. printf("%d,%f\r\n", nowfreq, power);
  390. }
  391. }
  392. void checkdevice() {
  393. /**
  394. * @brief
  395. *
  396. *
  397. * :3us扫频
  398. * 1.35k->40k时候的功率40k的要大
  399. * 2.35k->40k时候的功率
  400. * 3.25k到30k扫频25k到35k的点绝大多数都比25k时候的大
  401. * 4.
  402. *
  403. * :
  404. *
  405. * 1 35k到40k40k功率大的点的占比
  406. * 2 35k到40k
  407. * 3 25k到30k25k大的点的占比
  408. * 4 25k到30k,
  409. *
  410. *
  411. * :
  412. *
  413. *
  414. */
  415. printf("checkdevice\r\n");
  416. float indicator_1 = 0;
  417. float indicator_2 = 0;
  418. float indicator_3 = 0;
  419. uint16_t resonant_frequency = 0;
  420. {
  421. //指标1 35k到40k,比40k功率大的点的占比
  422. int count = 0;
  423. size_t i = 0;
  424. for (;; i++) {
  425. int nowfreq = 35000 + i * 100;
  426. float power = getpower(nowfreq);
  427. if (power > getpower(40000)) {
  428. count++;
  429. }
  430. if (nowfreq >= 40 * 1000) {
  431. break;
  432. }
  433. }
  434. indicator_1 = count * 1.0 / i * 100;
  435. }
  436. {
  437. // 指标2 35k到40k,功率平均值
  438. int count = 0;
  439. float sumpower = 0;
  440. size_t i = 0;
  441. for (;; i++) {
  442. int nowfreq = 35000 + i * 100;
  443. float power = getpower(nowfreq);
  444. sumpower += power;
  445. }
  446. indicator_2 = sumpower / i;
  447. }
  448. // 指标3 25k到30k,功率比25k大的点的占比
  449. {
  450. int count = 0;
  451. size_t i = 0;
  452. for (;; i++) {
  453. int nowfreq = 25000 + i * 100;
  454. float power = getpower(nowfreq);
  455. if (power > getpower(25000)) {
  456. count++;
  457. }
  458. if (nowfreq >= 30 * 1000) {
  459. break;
  460. }
  461. }
  462. indicator_3 = count * 1.0 / i * 100;
  463. }
  464. // 指标4 25k到30k, 功率最小的点
  465. {
  466. size_t i = 0;
  467. float minpower = getpower(25000);
  468. uint16_t minpowerfreq = 25000;
  469. for (;; i++) {
  470. int nowfreq = 25000 + i * 100;
  471. float power = getpower(nowfreq);
  472. if (power < minpower) {
  473. minpower = power;
  474. minpowerfreq = nowfreq;
  475. }
  476. }
  477. resonant_frequency = minpowerfreq;
  478. }
  479. }
  480. void init_all_subdevice_state() {
  481. port_debug_set(false);
  482. port_fan_set(false);
  483. port_led0_set(false);
  484. port_led1_set(false);
  485. port_led2_set(false);
  486. port_led3_set(false);
  487. port_led_r_set(false);
  488. port_led_g_set(false);
  489. port_led_b_set(false);
  490. }
  491. int main(void) {
  492. SystemInit(); //配置系统时钟
  493. DeviceClockAllEnable(); //打开所有外设时钟
  494. systicket_init();
  495. /*系统初始化*/
  496. zgpio_init_all_gpio(); //
  497. port_init(); //
  498. init_all_subdevice_state(); //
  499. printf("==========OZONE_GENERATOR==========\n"); //
  500. printf("= manufactor: iflytop\n"); //
  501. printf("= version : %s\n", VERSION); //
  502. printf("=\n"); //
  503. /*组件初始化*/
  504. zsimple_timer_module_init(zsimple_timer_mem, ZARR_SIZE(zsimple_timer_mem), systicket_get_now_ms); //定时器模块初始化
  505. zkey_init(&key_module); //按键初始化
  506. debuglighttimer = zsimple_timer_alloc();
  507. zsimple_timer_trigger_static(debuglighttimer, 300, INFINITE_TIMES /*触发次数:*/, true, do_debug_light_state);
  508. /**
  509. * @brief
  510. * 20k起步50hz100ms计算功率
  511. */
  512. printf_ozone_freq_and_power_table();
  513. while (true) {
  514. //按键扫描逻辑
  515. DO_IT_EACH_MS(KEY_PERIOD) { zkey_do_loop_in_each_period(NULL); }
  516. END();
  517. zsimple_timer_schedule();
  518. lcs_shcedule();
  519. process_countdwonevent();
  520. // printf("countddonw %d\n", thisDevice.countdonwnum_s);
  521. }
  522. }