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.

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