ALGO_WaveAnalyse_ATY.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /**
  2. * @file ALGO_WaveAnalyse_ATY.c
  3. *
  4. * @param Project ALGO_Algorithm_ATY_LIB
  5. *
  6. * @author ATY
  7. *
  8. * @copyright
  9. * - Copyright 2017 - 2023 MZ-ATY
  10. * - This code follows:
  11. * - MZ-ATY Various Contents Joint Statement -
  12. * <a href="https://mengze.top/MZ-ATY_VCJS">
  13. * https://mengze.top/MZ-ATY_VCJS</a>
  14. * - CC 4.0 BY-NC-SA -
  15. * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
  16. * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
  17. * - Your use will be deemed to have accepted the terms of this statement.
  18. *
  19. * @brief Familiar functions of wave analyse from ad
  20. *
  21. * @version
  22. * - 1_01_220601 > ATY
  23. * -# Preliminary version, first Release
  24. * - Undone
  25. ********************************************************************************
  26. */
  27. #ifndef __ALGO_WaveAnalyse_ATY_C
  28. #define __ALGO_WaveAnalyse_ATY_C
  29. #include "ALGO_WaveAnalyse_ATY.h"
  30. /******************************* For user *************************************/
  31. /******************************************************************************/
  32. // wave_lastWaveAve_Kalman use last calc signal base voltage or direct signal base voltage
  33. uint16_t wave_lastWaveAve_Kalman = 0;
  34. // uint16_t wave_lastWaveAve_Kalman = 1468;
  35. /**
  36. * @brief find peak and zero points from origin wave data
  37. * @param inputWave origin wave data from adc
  38. * @param kalmanWave wave data after kalman filter
  39. * @param deepKalmanWave wave data after deep kalman filter, wave averange save to [0]
  40. * @param peakZeroPoints peak and zero points
  41. * @param size deal size
  42. * @note inputWave/kalmanWave/deepKalmanWave/peakZeroPoints group size must >= size
  43. */
  44. void WavePeakZeroPointFind(
  45. uint16_t* inputWave,
  46. uint16_t* kalmanWave,
  47. uint16_t* deepKalmanWave,
  48. uint16_t* peakZeroPoints,
  49. uint16_t size)
  50. {
  51. uint16_t i = 0;
  52. ALGO_Kalman1D_S temp_kfpDeep = {1, 0, 0, 0, 0, 0};
  53. int tempKalmanDiff = 0; // size should be a multiple of 5
  54. /* first smoothing in kalman **********************************************/
  55. ALGO_Kalman1D_S temp_kfp = {1, 0, 0, 0, 0, 0};
  56. temp_kfp.Q = 0.000000001;
  57. temp_kfp.R = 0.000001;
  58. // kalman filter delay 12 points
  59. for(i = 0; i < size; i++)
  60. kalmanWave[i] = (uint16_t)ALGO_KalmanFilter1D(&temp_kfp, (float)inputWave[i]);
  61. /* find difference for peaks and troughs **********************************/
  62. for(i = 1; i < size; i++)
  63. {
  64. if(kalmanWave[i - 1] > kalmanWave[i])
  65. peakZeroPoints[i] = WAVE_BASE_AVE + 1;
  66. else if(kalmanWave[i - 1] < kalmanWave[i])
  67. peakZeroPoints[i] = WAVE_BASE_AVE - 1;
  68. else
  69. peakZeroPoints[i] = peakZeroPoints[i - 1];
  70. }
  71. /* find peaks point and add base value to display *************************/
  72. for(i = 1; i < size; i++)
  73. {
  74. if(peakZeroPoints[i - 1] < peakZeroPoints[i])
  75. peakZeroPoints[i - 1] = WAVE_DISPLAY_PEAK_HIGH;
  76. else if(peakZeroPoints[i - 1] > peakZeroPoints[i])
  77. peakZeroPoints[i - 1] = WAVE_DISPLAY_PEAK_LOW;
  78. else
  79. peakZeroPoints[i - 1] = WAVE_BASE_AVE;
  80. }
  81. /* calc averange through deep kalman **************************************/
  82. temp_kfpDeep.Q = 0;
  83. temp_kfpDeep.R = 1;
  84. for(i = 0; i < size; i++)
  85. deepKalmanWave[i] = (uint16_t)ALGO_KalmanFilter1D(&temp_kfpDeep, (float)inputWave[i]);
  86. deepKalmanWave[0] = deepKalmanWave[size * 3 / 5];
  87. for(i = size * 3 / 5; i < size * 4 / 5; i++)
  88. tempKalmanDiff += deepKalmanWave[i] - deepKalmanWave[size * 3 / 5];
  89. tempKalmanDiff /= (float)(size / 5.0f);
  90. deepKalmanWave[0] += tempKalmanDiff; // wave averange
  91. // printf("\r\ndeepKalmanAve: %d\r\n", deepKalmanWave[0]);
  92. /* find zero points with rise and fall and add base value to display ******/
  93. for(i = 1; i < size; i++)
  94. {
  95. if((kalmanWave[i - 1] < deepKalmanWave[0]) && (kalmanWave[i] >= deepKalmanWave[0]))
  96. {
  97. if(deepKalmanWave[0] - kalmanWave[i - 1] <= kalmanWave[i] - deepKalmanWave[0])
  98. peakZeroPoints[i - 1] = WAVE_DISPLAY_ZERO_RAISE;
  99. else
  100. peakZeroPoints[i] = WAVE_DISPLAY_ZERO_RAISE;
  101. }
  102. else if((kalmanWave[i - 1] > deepKalmanWave[0]) && (kalmanWave[i] <= deepKalmanWave[0]))
  103. {
  104. if(kalmanWave[i - 1] - deepKalmanWave[0] <= deepKalmanWave[0] - kalmanWave[i])
  105. peakZeroPoints[i - 1] = WAVE_DISPLAY_ZERO_FALL;
  106. else
  107. peakZeroPoints[i] = WAVE_DISPLAY_ZERO_FALL;
  108. }
  109. }
  110. }
  111. /* First wave find ************************************************************/
  112. uint16_t wave_firstWavePeakPoint = 0, wave_firstWaveZeroPoint = 0;
  113. /**
  114. * @brief find peak and zero points from origin wave data
  115. * @param kalmanWave wave data from kalman filter
  116. * @param peakZeroPoints peak and zero points
  117. * @param size deal size
  118. * @note kalmanWave/peakZeroPoints group size must >= size
  119. */
  120. void WaveFirstPulseFind(uint16_t* kalmanWave, uint16_t* peakZeroPoints, uint16_t size)
  121. {
  122. // zero point must near mid of high peak and low peak, then count 1 valid wave data
  123. // step 1: find one high peak higher than vol
  124. // step 2: this high peak near last zero point is rise and neaxt zero point is fall
  125. // step 3(todo): high point subtract last zero and next zero, two space little than a value, save this high peak point
  126. // step 4: find low peak like this
  127. // step 5: find next 10 point like this
  128. uint16_t i = 0, j = 0, k = 0;
  129. uint8_t firstWaveAnalyseStep = 0, firstWaveAnalyseCount = 0;
  130. uint8_t secondZeroPoint = 0;
  131. wave_firstWavePeakPoint = 0;
  132. wave_firstWaveZeroPoint = 0;
  133. for(i = 1; i < size; i++)
  134. {
  135. if((firstWaveAnalyseStep == 0)
  136. && (peakZeroPoints[i] == WAVE_DISPLAY_PEAK_HIGH))
  137. {
  138. if(kalmanWave[i] > FIRST_THRESHOLD_HIGH)
  139. {
  140. if(firstWaveAnalyseCount == 0)
  141. wave_firstWavePeakPoint = i;
  142. for(j = i - 1; j > 0; j--)
  143. {
  144. if(peakZeroPoints[j] != WAVE_BASE_AVE)
  145. {
  146. if(peakZeroPoints[j] == WAVE_DISPLAY_ZERO_RAISE)
  147. {
  148. if(firstWaveAnalyseCount == 0)
  149. wave_firstWaveZeroPoint = j;
  150. for(k = i + 1; k < size; k++)
  151. {
  152. if(peakZeroPoints[k] != WAVE_BASE_AVE)
  153. {
  154. if(peakZeroPoints[k] == WAVE_DISPLAY_ZERO_FALL)
  155. {
  156. firstWaveAnalyseStep = 2;
  157. }
  158. else
  159. {
  160. wave_firstWavePeakPoint = 0;
  161. wave_firstWaveZeroPoint = 0;
  162. firstWaveAnalyseStep = 0;
  163. firstWaveAnalyseCount = 0;
  164. }
  165. break;
  166. }
  167. }
  168. }
  169. else
  170. {
  171. wave_firstWavePeakPoint = 0;
  172. wave_firstWaveZeroPoint = 0;
  173. firstWaveAnalyseStep = 0;
  174. firstWaveAnalyseCount = 0;
  175. }
  176. break;
  177. }
  178. }
  179. }
  180. else
  181. {
  182. wave_firstWavePeakPoint = 0;
  183. wave_firstWaveZeroPoint = 0;
  184. firstWaveAnalyseStep = 0;
  185. firstWaveAnalyseCount = 0;
  186. }
  187. }
  188. else if((firstWaveAnalyseStep == 2)
  189. && (peakZeroPoints[i] == WAVE_DISPLAY_PEAK_LOW))
  190. {
  191. if(kalmanWave[i] < FIRST_THRESHOLD_LOW)
  192. {
  193. for(j = i - 1; j > 0; j--)
  194. {
  195. if(peakZeroPoints[j] != WAVE_BASE_AVE)
  196. {
  197. if(peakZeroPoints[j] == WAVE_DISPLAY_ZERO_FALL)
  198. {
  199. if(secondZeroPoint == 0)
  200. {
  201. secondZeroPoint = j;
  202. if(((j - wave_firstWavePeakPoint) > (wave_firstWavePeakPoint - wave_firstWaveZeroPoint)
  203. && (j - wave_firstWavePeakPoint) - (wave_firstWavePeakPoint - wave_firstWaveZeroPoint) > 5)
  204. || ((wave_firstWavePeakPoint - wave_firstWaveZeroPoint) > (j - wave_firstWavePeakPoint)
  205. && (wave_firstWavePeakPoint - wave_firstWaveZeroPoint) - (j - wave_firstWavePeakPoint) > 5))
  206. break;
  207. }
  208. for(k = i + 1; k < size; k++)
  209. {
  210. if(peakZeroPoints[k] != WAVE_BASE_AVE)
  211. {
  212. if(peakZeroPoints[k] == WAVE_DISPLAY_ZERO_RAISE)
  213. {
  214. firstWaveAnalyseStep = 4;
  215. }
  216. else
  217. {
  218. wave_firstWavePeakPoint = 0;
  219. wave_firstWaveZeroPoint = 0;
  220. firstWaveAnalyseStep = 0;
  221. firstWaveAnalyseCount = 0;
  222. }
  223. break;
  224. }
  225. }
  226. }
  227. else
  228. {
  229. wave_firstWavePeakPoint = 0;
  230. wave_firstWaveZeroPoint = 0;
  231. firstWaveAnalyseStep = 0;
  232. firstWaveAnalyseCount = 0;
  233. }
  234. break;
  235. }
  236. }
  237. }
  238. else
  239. {
  240. wave_firstWavePeakPoint = 0;
  241. wave_firstWaveZeroPoint = 0;
  242. firstWaveAnalyseStep = 0;
  243. firstWaveAnalyseCount = 0;
  244. }
  245. }
  246. if(firstWaveAnalyseStep == 4)
  247. {
  248. firstWaveAnalyseStep = 0;
  249. firstWaveAnalyseCount++;
  250. if(firstWaveAnalyseCount >= WAVE_FIRST_COUNT)
  251. break;
  252. }
  253. }
  254. if(firstWaveAnalyseCount < WAVE_FIRST_COUNT)
  255. {
  256. wave_firstWavePeakPoint = 0;
  257. wave_firstWaveZeroPoint = 0;
  258. firstWaveAnalyseStep = 0;
  259. firstWaveAnalyseCount = 0;
  260. }
  261. }
  262. /* Calc wave period and frequence *********************************************/
  263. uint16_t wave_quarterSpace = 0;
  264. /**
  265. * @brief calculate period and frequence
  266. * @param peakZeroPoints wave peak and zero points after WavePeakZeroPointFind()
  267. * @param firstWavePoint first wave pulse zero point, where to start analyse
  268. * @param size deal size
  269. * @note peakZeroPoints group size must >= size, function suit freq < 100KHz
  270. */
  271. void WaveParamCalc(uint16_t* peakZeroPoints, uint16_t firstWavePoint, uint16_t size)
  272. {
  273. uint16_t i = 0;
  274. float wavePeriod = 0.0, waveFreq = 0.0;
  275. uint16_t lastPoint = 0;
  276. uint16_t lastSpace = 0, newSpace = 0;
  277. uint16_t repetitionCount = 0;
  278. ALGO_Kalman1D_S temp_kfpDeep = {1, 0, 0, 0, 0, 0};
  279. temp_kfpDeep.Q = 0;
  280. temp_kfpDeep.R = 1;
  281. for(i = firstWavePoint; i < size; i++)
  282. {
  283. if(peakZeroPoints[i] != WAVE_BASE_AVE)
  284. {
  285. newSpace = i - lastPoint;
  286. if(repetitionCount < 2000)
  287. {
  288. // filter big changes at begining
  289. if((newSpace < lastSpace + 3) && (newSpace + 3 > lastSpace) && (newSpace > 5))
  290. {
  291. repetitionCount++;
  292. if(temp_kfpDeep.L_P == 1)
  293. temp_kfpDeep.L_P = newSpace;
  294. // carry, float to uint
  295. wave_quarterSpace = ALGO_KalmanFilter1D(&temp_kfpDeep, (float)newSpace) + 0.6f;
  296. // printf("$%d %d;", newSpace, wave_quarterSpace);
  297. }
  298. else
  299. repetitionCount = 0;
  300. }
  301. else
  302. {
  303. // printf("$0 %d;", i);
  304. break;
  305. }
  306. lastSpace = newSpace;
  307. lastPoint = i;
  308. }
  309. }
  310. if(wave_quarterSpace > 0)
  311. {
  312. wavePeriod = wave_quarterSpace * 4.0f * ADC_TIME_UNIT;
  313. waveFreq = 1000.0f / wavePeriod;
  314. // printf("$%d %f %f;", wave_quarterSpace, wavePeriod, waveFreq);
  315. peakZeroPoints[0] = wave_quarterSpace;
  316. }
  317. }
  318. /* Calc wave vpp voltage ******************************************************/
  319. uint16_t wave_maxVpp = 0;
  320. /**
  321. * @brief find peak and zero points from origin wave data
  322. * @param kalmanWave wave data from kalman filter
  323. * @param peakZeroPoints peak and zero points
  324. * @param size deal size
  325. * @note kalmanWave/peakZeroPoints group size must >= size
  326. */
  327. void WaveVppCalc(uint16_t* kalmanWave, uint16_t* peakZeroPoints, uint16_t size)
  328. {
  329. uint16_t i = 0;
  330. uint16_t lastWaveValue = 0;
  331. float maxVppVoltagge;
  332. for(i = 0; i < size; i++)
  333. {
  334. if((peakZeroPoints[i] == WAVE_DISPLAY_PEAK_HIGH) || (peakZeroPoints[i] == WAVE_DISPLAY_PEAK_LOW))
  335. {
  336. if(lastWaveValue != 0)
  337. {
  338. if(wave_maxVpp < kalmanWave[i] - lastWaveValue)
  339. wave_maxVpp = kalmanWave[i] - lastWaveValue;
  340. // printf("$%d %d %d %d;", kalmanWave[i], lastWaveValue, wave_maxVpp);
  341. }
  342. lastWaveValue = kalmanWave[i];
  343. }
  344. }
  345. maxVppVoltagge = 2.5 * (wave_maxVpp * WAVE_KALMAN_ATTENUATION) / 4096.0f;
  346. }
  347. void WaveWholeProcess(
  348. uint16_t* inputWave,
  349. uint16_t* kalmanWave,
  350. uint16_t* deepKalmanWave,
  351. uint16_t* peakZeroPoints,
  352. uint16_t size)
  353. {
  354. wave_firstWavePeakPoint = 0;
  355. wave_firstWaveZeroPoint = 0;
  356. wave_quarterSpace = 0;
  357. wave_maxVpp = 0;
  358. WavePeakZeroPointFind(inputWave, kalmanWave, deepKalmanWave, peakZeroPoints, size);
  359. WaveFirstPulseFind(kalmanWave, peakZeroPoints, size);
  360. WaveParamCalc(peakZeroPoints, wave_firstWaveZeroPoint, size);
  361. WaveVppCalc(kalmanWave, peakZeroPoints, size);
  362. wave_lastWaveAve_Kalman = deepKalmanWave[0];
  363. }
  364. #ifdef __DEBUG_WAVE_ATY
  365. uint16_t kalmanWave_Test[TEST_WAVE_SIZE] = {0};
  366. uint16_t deepKalmanWave_Test[TEST_WAVE_SIZE] = {0};
  367. uint16_t peakZeroPoints_Test[TEST_WAVE_SIZE] = {0};
  368. void WaveAnalyse_Test(uint16_t* testWaveDataIn, uint8_t WAVE_DISPLAY_FLAG)
  369. {
  370. uint16_t i = 0;
  371. // debug WaveAnalyse test
  372. // IWDG_ENABLE_WRITE_ACCESS(&hiwdg);
  373. // hiwdg.Instance->PR = IWDG_PRESCALER_256;
  374. // hiwdg.Instance->RLR = 0xFFFFFFFF;
  375. // HAL_IWDG_Refresh(&hiwdg);
  376. WaveWholeProcess(testWaveDataIn, kalmanWave_Test, deepKalmanWave_Test, peakZeroPoints_Test, TEST_WAVE_SIZE);
  377. // WAVE_DISPLAY_FLAG = 1;
  378. if(WAVE_DISPLAY_FLAG)
  379. {
  380. if(WAVE_DISPLAY_FLAG == 1)
  381. {
  382. // for(uint16_t i = 0; i < TEST_WAVE_SIZE; i++)
  383. for(i = 0; i < 2000; i++)
  384. {
  385. // this "for" need feed watch dog or close it
  386. // HAL_IWDG_Refresh(&hiwdg);
  387. printf("$");
  388. printf("%04d ", testWaveDataIn[i]);
  389. printf("%04d ", kalmanWave_Test[i]);
  390. // printf("%04d ", deepKalmanWave_Test[i]);
  391. // printf("%04d ", deepKalmanWave_Test[0]); // wave averange
  392. printf("%04d ", peakZeroPoints_Test[i]);
  393. printf("%04d ", peakZeroPoints_Test[0] * 200); // wave 1/4 period points space
  394. if(i == wave_firstWavePeakPoint)
  395. printf("%d ", 3000);
  396. else if(i == wave_firstWaveZeroPoint)
  397. printf("%d ", 0);
  398. else
  399. printf("%d ", deepKalmanWave_Test[0]);
  400. printf("%d ", wave_firstWavePeakPoint * 10);
  401. // printf("%f ", wave_firstWavePeakPoint * ADC_TIME_UNIT);
  402. // printf("%d ", wave_quarterSpace);
  403. // printf("%f ", wave_quarterSpace * 4.0f * ADC_TIME_UNIT);
  404. // printf("%f ", 1000.0f / (wave_quarterSpace * 4.0f * ADC_TIME_UNIT));
  405. // printf("%d ", wave_maxVpp);
  406. // printf("%f ", 2.5 * (wave_maxVpp * WAVE_KALMAN_ATTENUATION) / 4096.0f);
  407. printf(";");
  408. }
  409. }
  410. else if(WAVE_DISPLAY_FLAG == 2)
  411. {
  412. printf("$");
  413. printf("%d ", wave_firstWavePeakPoint);
  414. // printf("%f ", wave_firstWavePeakPoint * ADC_TIME_UNIT);
  415. printf("%d ", wave_quarterSpace * 40);
  416. // printf("%d ", wave_quarterSpace);
  417. // printf("%f ", wave_quarterSpace * 4.0f * ADC_TIME_UNIT);
  418. // printf("%f ", 1000.0f / (wave_quarterSpace * 4.0f * ADC_TIME_UNIT));
  419. printf("%d ", wave_maxVpp);
  420. // printf("%f ", 2.5 * (wave_maxVpp * WAVE_KALMAN_ATTENUATION) / 4096.0f);
  421. printf(";");
  422. }
  423. // printf("$%d;", 0);
  424. }
  425. }
  426. #endif /* __DEBUG_WAVE_ATY */
  427. #endif /* __ALGO_WaveAnalyse_ATY_C */
  428. /******************************** End Of File *********************************/