ALGO_Algorithm_ATY.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. /**
  2. * @file ALGO_Algorithm_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 algorithm
  20. *
  21. * @version
  22. * - 1_01_220601 > ATY
  23. * -# Preliminary version, first Release
  24. ********************************************************************************
  25. */
  26. #ifndef __ALGO_Algorithm_ATY_C
  27. #define __ALGO_Algorithm_ATY_C
  28. #include "ALGO_Algorithm_ATY.h"
  29. /******************************* For user *************************************/
  30. /******************************************************************************/
  31. /* Wave parameters ************************************************************/
  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. // float AdcVoltageCalc(uint16_t data_t)
  428. // {
  429. // return ((data_t * REF_VOLTAGE_2_5) / 4096);
  430. // }
  431. // void BatVoltageGet(void) // 12V
  432. // {
  433. // mainReg.powerQuantity = AdcVoltageCalc(lowAdData[1]) * 1000;
  434. // mainReg.chargeState = 0;
  435. // if(mainReg.powerQuantity >= (FULL_BAT_VOLTAGE + 300)) // higher 3V more than one bat
  436. // {
  437. // mainReg.machineState |= SELFCHECK_WRONGBAT;
  438. // }
  439. // else if((mainReg.powerQuantity >= (FULL_BAT_VOLTAGE - 20))
  440. // && (mainReg.powerQuantity < (FULL_BAT_VOLTAGE + 300)))
  441. // {
  442. // mainReg.chargeState = 1;
  443. // }
  444. // // BV: mainReg.maxBatVoltage, y: battery level(*100%), x: detect voltage value
  445. // // BV*41/42->100(fullBV), BV*37/42->20(twentyBV), BV*30/42->0(emptyBV)
  446. // // BV*39/42->80(eightyBV)(adjustable)
  447. // //
  448. // // y1=a*x*x+b*x+c, 100~20
  449. // // 100=fullBV<-x, 80=eightyBV<-x, 20=twentyBV<-x
  450. // // -> a=-8820/(BV*BV) -> b=17220/BV -> c=-8305
  451. // // y1=-8820*x*x/(BV*BV)+17220*x/BV-8305
  452. // //
  453. // // y2=a*x*x+b*x+c, 20~0
  454. // // -b/2*a=emptyBV -> b=-2*emptyBV*a
  455. // // 0=a*emptyBV*emptyBV+b*emptyBV+c -> c=emptyBV*emptyBV*a
  456. // // -> y2=a*x*x-2*emptyBV*a*x+a*emptyBV*emptyBV
  457. // // 20=a*twentyBV*twentyBV-2*emptyBV*a*twentyBV+a*emptyBV*emptyBV
  458. // // -> a=720/(BV*BV) -> b=-7200/(7*BV) -> c=18000/49
  459. // // y2=720*x*x/(BV*BV)-7200*x/(7*BV)+18000/49
  460. // if(mainReg.powerQuantity >= FULL_BAT_VOLTAGE)
  461. // {
  462. // mainReg.powerQuantity = 100 * 100;
  463. // }
  464. // else if((mainReg.powerQuantity < FULL_BAT_VOLTAGE) && (mainReg.powerQuantity >= TWENTY_BAT_VOLTAGE))
  465. // {
  466. // mainReg.powerQuantity =
  467. // ((17220.0f * (float)mainReg.powerQuantity / (float)mainReg.maxBatVoltage)
  468. // - ((8820.0f * (float)mainReg.powerQuantity * (float)mainReg.powerQuantity)
  469. // / ((float)mainReg.maxBatVoltage * (float)mainReg.maxBatVoltage))
  470. // - 8305.0f) * 100;
  471. // }
  472. // else if((mainReg.powerQuantity < TWENTY_BAT_VOLTAGE) && (mainReg.powerQuantity > EMPTY_BAT_VOLTAGE))
  473. // {
  474. // mainReg.powerQuantity =
  475. // (((720.0f * (float)mainReg.powerQuantity * (float)mainReg.powerQuantity)
  476. // / ((float)mainReg.maxBatVoltage * (float)mainReg.maxBatVoltage))
  477. // - ((7200.0f * (float)mainReg.powerQuantity) / (7 * (float)mainReg.maxBatVoltage))
  478. // + (18000.0f / 49.0f)) * 100;
  479. // }
  480. // else// if(mainReg.powerQuantity <= EMPTY_BAT_VOLTAGE)
  481. // {
  482. // mainReg.powerQuantity = 0;
  483. // mainReg.machineState |= SELFCHECK_LOWPOWER;
  484. // }
  485. // }
  486. // 17 significant digits
  487. double ALGO_MATH_Pow(double num, uint8_t n)
  488. {
  489. uint8_t i = 0;
  490. double result = 1;
  491. for(i = 0; i < n; i++)
  492. result *= num;
  493. return result;
  494. }
  495. double ALGO_MATH_LogLn(double num)
  496. {
  497. // take the first 15+1 terms to estimate
  498. int N = 15;
  499. int k, nk;
  500. double x, xx, y;
  501. x = (num - 1) / (num + 1);
  502. xx = x * x;
  503. nk = 2 * N + 1;
  504. y = 1.0 / nk;
  505. for(k = N; k > 0; k--)
  506. {
  507. nk = nk - 2;
  508. y = 1.0 / nk + xx * y;
  509. }
  510. return 2.0 * x * y;
  511. }
  512. /**
  513. * @brief Calculate temperature from ntc resistance
  514. * @param Rntc Current NTC resistance value
  515. * @param R25 NTC standard resistance value at 25C
  516. * @param B B value of NTC
  517. * @return Current temperature in Celsius
  518. * @note T25: Kelvin temperature at 25C = 298.15 = ALGO_TEMP_CtoT(25)
  519. * R25: NTC standard resistance value at 25C like 10K,5K,100K...
  520. * B: B value of NTC like 3435,3950...
  521. * Rntc: Current NTC resistance value
  522. * Tn: Actual Kelvin temperature(Cn = Tn-273.15)
  523. * B = (lnR25 - lnRntc)/(1/T25 - 1/Tn)
  524. */
  525. float ALGO_ResToKelvinTemp(float Rntc, float R25, float B)
  526. {
  527. float Tn = 0.0;
  528. float Cn = 0.0;
  529. float temp_f[2];
  530. temp_f[0] = (ALGO_MATH_LogLn(R25) - ALGO_MATH_LogLn(Rntc)) / B;
  531. temp_f[1] = (1 / ALGO_TEMP_CtoT(25)) - temp_f[0];
  532. Tn = 1 / temp_f[1];
  533. Cn = ALGO_TEMP_TtoC(Tn);
  534. return Cn;
  535. }
  536. /*
  537. Pure water density with temperature at one atmosphere, 1.0g/cm3 or 1000kg/m3
  538. y = 2E-05x3 - 0.0059x2 + 0.0141x + 1000.1 R2 = 0.9998 (Upper 4)
  539. y = -0.0085x2 + 0.067x + 999.84 R2 = 0.9999 (Below 4)
  540. (International Temperature Scale 1990 pure water density table)
  541. */
  542. float ALGO_WaterDensityFromTemp(float temperature)
  543. {
  544. float waterDensity = 0.0;
  545. if(temperature > 4)
  546. waterDensity =
  547. 0.00002 * ALGO_MATH_Pow(temperature, 3)
  548. - 0.0059 * ALGO_MATH_Pow(temperature, 2)
  549. + 0.0141 * ALGO_MATH_Pow(temperature, 1)
  550. + 1000.1;
  551. else
  552. waterDensity =
  553. -0.0085 * ALGO_MATH_Pow(temperature, 2)
  554. + 0.067 * ALGO_MATH_Pow(temperature, 1)
  555. + 999.84;
  556. #ifdef __DEBUG_ALGO_Algorithm_ATY
  557. printf("\r\nCurrent water density: %f", waterDensity);
  558. #endif /* __DEBUG_ALGO_Algorithm_ATY */
  559. return waterDensity;
  560. }
  561. /*
  562. <table><tr><th>名称Ch</th><td>名称En</td><td>名称EnB</td><td>符号</td><td>单位</td><td>公式</td><td>换算</td><td>备注</td><td></td></tr><tr><th>电阻</th><td>resistance</td><td>Resistance</td><td>R</td><td>Ω(欧姆)(Ohm)</td><td>U/I</td><td>1000</td><td></td><td></td></tr><tr><th>电导</th><td>conductance</td><td>Conductance</td><td>G</td><td>S(西门子)(1/Ω)</td><td>1/R</td><td>1000</td><td></td><td></td></tr><tr><th>电导池(电极)常数(系数)</th><td>cell constant</td><td>Cell Constant</td><td>K/Kcell</td><td>1/m</td><td>L/A</td><td>10</td><td>S:面积, L:距离(长度)</td><td></td></tr><tr><th>电阻率</th><td>resistivity</td><td>Resistivity</td><td>ρ</td><td>Ω*m</td><td>R*A/L</td><td></td><td></td><td></td></tr><tr><th>电导率</th><td>conductivity</td><td>Conductivity</td><td>σ/κ</td><td>S/m</td><td>L/R*A(1/ρ)</td><td>1S/m = 10000uS/cm</td><td></td><td></td></tr><tr><th>摩尔电导率</th><td>molar conductivity</td><td>Molar Conductivity</td><td>Λm</td><td>S*m^2/mol</td><td>κ/c(κ·VY)</td><td></td><td></td><td></td></tr><tr><th>物质的量</th><td>amount of substance</td><td>Amount Of Substance</td><td>n</td><td>mol(摩尔)</td><td>m/M(N/NA)</td><td>1000</td><td></td><td></td></tr><tr><th>摩尔量/摩尔质量</th><td>molal weight</td><td>Molal Weight</td><td>M</td><td>g/mol</td><td>1000</td><td></td><td></td><td></td></tr><tr><th>物质的量浓度/摩尔浓度</th><td>molarity</td><td>Molarity</td><td>c</td><td>mol/L</td><td>n/V</td><td>1L=1dm^3=1000cm^3</td><td></td><td></td></tr><tr><th>密度</th><td>density</td><td>Density</td><td>ρ</td><td>kg/m^3(g/L)</td><td>m/V</td><td></td><td></td><td></td></tr><tr><th>溶液密度</th><td>density</td><td>Density</td><td>ρY</td><td>kg/L(g/L)</td><td>mY/VY</td><td></td><td></td><td></td></tr><tr><th>质量浓度/质量-体积浓度</th><td>mass concentration</td><td>Mass Concentration</td><td>ρn</td><td>kg/L(g/L)</td><td>mZ/VY</td><td></td><td></td><td></td></tr><tr><th>质量分数/质量百分浓度/溶质质量分数</th><td>mass fraction</td><td>Mass Fraction</td><td>ω/C%</td><td>100%</td><td>mZ/mY</td><td></td><td></td><td></td></tr><tr><th>比重/相对浓度</th><td>specific gravitys</td><td>Specific Gravitys</td><td>s.g.</td><td>1</td><td>ρY/ρC</td><td>ρC一般为水ρw=1000g/L</td><td></td><td></td></tr></table>
  563. | **NameCh** | **NameEn** | **NameEnB** | **Symbol** | **Unit** | **formula** | **conversion** | **comment** |
  564. |:--------------------------------------:|:-------------------:|:-------------------:|:-----------:|:--------------:|:-----------:|:---------------------:|:--------------------:|
  565. | **电阻** | resistance | Resistance | R | Ω(欧姆)(Ohm) | U/I | 1000 |
  566. | **电导** | conductance | Conductance | G | S(西门子)(1/Ω) | 1/R | 1000 |
  567. | **电导池(电极)常数(系数)** | cell constant | Cell Constant | K/Kcell | 1/m | L/A | 10 | S:面积, L:距离(长度) |
  568. | **电阻率** | resistivity | Resistivity | ρ | Ω*m | R*A/L |
  569. | **电导率** | conductivity | Conductivity | σ/κ | S/m | L/R*A(1/ρ) | 1S/m = 10000uS/cm |
  570. | **摩尔电导率** | molar conductivity | Molar Conductivity | Λm | S*m^2/mol | κ/c(κ·VY) |
  571. | **物质的量** | amount of substance | Amount Of Substance | n | mol(摩尔) | m/M(N/NA) | 1000 |
  572. | **摩尔量/摩尔质量** | molal weight | Molal Weight | M | g/mol | 1000 |
  573. | **物质的量浓度/摩尔浓度** | molarity | Molarity | c | mol/L | n/V | 1L=1dm^3=1000cm^3 |
  574. | **密度** | density | Density | ρ | kg/m^3(g/L) | m/V |
  575. | **溶液密度** | density | Density | ρY | kg/L(g/L) | mY/VY |
  576. | **质量浓度/质量-体积浓度** | mass concentration | Mass Concentration | ρn | kg/L(g/L) | mZ/VY |
  577. | **质量分数/质量百分浓度/溶质质量分数** | mass fraction | Mass Fraction | ω/C% | 100% | mZ/mY |
  578. | **比重/相对浓度** | specific gravitys | Specific Gravitys | s.g. | 1 | ρY/ρC | ρC一般为水ρw=1000g/L |
  579. */
  580. /**
  581. * @brief Calculate Electric Conductance in S from Ohm
  582. * @param Res resistance value in Ohm
  583. * @return Electric Conductance value in uS
  584. */
  585. float ALGO_EConductanceFromRes(float Res)
  586. {
  587. float electricConductance = ((Res > 0) ? (100000 / Res) : 0);
  588. #ifdef __DEBUG_ALGO_Algorithm_ATY
  589. printf("\r\nElectric Conductance: %f uS", electricConductance);
  590. printf("\r\nElectric Conductance: %f S-", electricConductance / 100000);
  591. #endif /* __DEBUG_ALGO_Algorithm_ATY */
  592. return electricConductance;
  593. }
  594. /**
  595. * @brief Calculate resistivity in Ohm*cm
  596. * @param Res resistance value in Ohm
  597. * @param A area of electrode in cm^2
  598. * @param L length between electrodes in cm
  599. * @return resistivity value in Ohm*cm
  600. * @note 1Ohm*m = 100Ohm*cm
  601. */
  602. float ALGO_ResistivityFromRes(float Res, float A, float L)
  603. {
  604. float resistivity = ((Res > 0) ? (Res * A / L) : 0);
  605. #ifdef __DEBUG_ALGO_Algorithm_ATY
  606. printf("\r\nResistivity: %f Ohm*cm", resistivity);
  607. printf("\r\nResistivity: %f Ohm*m-", resistivity / 100);
  608. #endif /* __DEBUG_ALGO_Algorithm_ATY */
  609. return resistivity;
  610. }
  611. /**
  612. * @brief Calculate conductivity in uS/cm
  613. * @param Res resistance value in Ohm
  614. * @param A area of electrode in cm^2
  615. * @param L length between electrodes in cm
  616. * @return conductivity value in uS/cm
  617. * @note 1S/m = 10000uS/cm
  618. */
  619. float ALGO_ConductivityFromRes(float Res, float A, float L)
  620. {
  621. float conductivity = ((Res > 0) ? (1000000 * L / (Res * A)) : 0);
  622. #ifdef __DEBUG_ALGO_Algorithm_ATY
  623. printf("\r\nConductivity: %f uS/cm", conductivity);
  624. printf("\r\nConductivity: %f S/m-", conductivity / 10000);
  625. #endif /* __DEBUG_ALGO_Algorithm_ATY */
  626. return conductivity;
  627. }
  628. /**
  629. * @brief Calculate molarity in mol/L
  630. * @param Conductivity conductivity in uS/cm
  631. * @param MC molar conductivity in S*cm^2/mol
  632. * @return molarity value in mol/L
  633. * @note 1L = 1dm^3 = 1000cm^3
  634. */
  635. // TODO: not reality, MC is changed
  636. #define MC_NaCl 126.5 // S*cm^2/mol, Na+Cl = 50.1+76.4
  637. float ALGO_MolarityFromConductivity(float Conductivity, float MC)
  638. {
  639. // MC * 10000: change to uS*dm^2/mol
  640. // 10 * Conductivity: change to us/dm
  641. float molarity = ((Conductivity > 0) ? (10 * Conductivity / (MC * 10000)) : 0);
  642. // float molarity = ((Conductivity > 0) ? (10 * Conductivity / 2) : 0);
  643. #ifdef __DEBUG_ALGO_Algorithm_ATY
  644. printf("\r\nMolarity: %f mol/cm^3-", molarity / 1000);
  645. printf("\r\nMolarity: %f mol/L", molarity);
  646. #endif /* __DEBUG_ALGO_Algorithm_ATY */
  647. return molarity;
  648. }
  649. /**
  650. * @brief Calculate mass concentration in g/L
  651. * @param Molarity molarity in mol/L
  652. * @param MM molar mass in g/mol
  653. * @return density value in g/L
  654. */
  655. #define MM_NaCl 58.44 // g/mol, Na+Cl = 22.99+35.45
  656. float ALGO_MassConcentrationFromMolarity(float Molarity, float MM)
  657. {
  658. float massConcentration = ((Molarity > 0) ? (Molarity * MM) : 0);
  659. #ifdef __DEBUG_ALGO_Algorithm_ATY
  660. printf("\r\nMass Concentration: %f g/L", massConcentration);
  661. #endif /* __DEBUG_ALGO_Algorithm_ATY */
  662. return massConcentration;
  663. }
  664. #define REF_VOLTAGE_2_5 2.5
  665. float AdcVoltageCalc(uint16_t data_t)
  666. {
  667. return ((data_t * REF_VOLTAGE_2_5) / 4096);
  668. }
  669. float AdcTempResCalc(uint16_t data_t)
  670. {
  671. // NTC pull up resistance connect to the same voltage as Vref/VDDA in MCU
  672. return ((data_t * 10.0) / (4096 - data_t));
  673. }
  674. /*
  675. // Least square polynomial fitting
  676. uint8_t LSPF_Calc(uint8_t dataSize, uint8_t rank)
  677. {
  678. #include "math.h"
  679. #define maxn 60
  680. #define RANK_MAX 3
  681. // double x[maxn] = {0, 0.25, 0.5, 0.75, 1};
  682. // double y[maxn] = {1, 1.283, 1.649, 2.212, 2.178};
  683. // double x[maxn] = {0, 5, 10, 15, 20};//, 25, 30, 35, 40, 45, 50, 55};
  684. // double y[maxn] = {0, 1.27, 2.16, 2.86, 3.44};//, 3.87, 4.15, 4.37, 4.51, 4.58, 4.02, 4.64};
  685. double x[maxn] = {0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55};
  686. double y[maxn] = {0, 1.27, 2.16, 2.86, 3.44, 3.87, 4.15, 4.37, 4.51, 4.58, 4.02, 4.64};
  687. double atemp[2 * (RANK_MAX + 1)] = {0}, btemp = 0, a[RANK_MAX + 1][RANK_MAX + 1], b[RANK_MAX + 1] = {0};
  688. int i, j, k;
  689. for(i = 0; i < dataSize; i++)
  690. {
  691. for(j = 0; j < rank + 1; j++)
  692. b[j] += pow(x[i], j) * y[i];
  693. for(j = 0; j < (2 * rank + 1); j++)
  694. atemp[j] += pow(x[i], j);
  695. }
  696. atemp[0] = dataSize;
  697. // 构建线性方程组系数矩阵,b[]不变
  698. for(i = 0; i < rank + 1; i++)
  699. {
  700. k = i;
  701. for(j = 0; j < rank + 1; j++)
  702. a[i][j] = atemp[k++];
  703. }
  704. // 以下为高斯列主元消去法解线性方程组
  705. for(k = 0; k < rank + 1 - 1; k++)
  706. { // n - 1列
  707. int column = k;
  708. double mainelement = a[k][k];
  709. // 找主元素
  710. for(i = k; i < rank + 1; i++)
  711. if(fabs(a[i][k]) > mainelement)
  712. {
  713. mainelement = fabs(a[i][k]);
  714. column = i;
  715. }
  716. // 交换两行
  717. for(j = k; j < rank + 1; j++)
  718. {
  719. double atemp = a[k][j];
  720. a[k][j] = a[column][j];
  721. a[column][j] = atemp;
  722. }
  723. btemp = b[k];
  724. b[k] = b[column];
  725. b[column] = btemp;
  726. // 消元过程
  727. for(i = k + 1; i < rank + 1; i++)
  728. {
  729. double Mik = a[i][k] / a[k][k];
  730. for(j = k; j < rank + 1; j++)
  731. a[i][j] -= Mik * a[k][j];
  732. b[i] -= Mik * b[k];
  733. }
  734. }
  735. // 回代过程
  736. b[rank + 1 - 1] /= a[rank + 1 - 1][rank + 1 - 1];
  737. for(i = rank + 1 - 2; i >= 0; i--)
  738. {
  739. double sum = 0;
  740. for(j = i + 1; j < rank + 1; j++)
  741. sum += a[i][j] * b[j];
  742. b[i] = (b[i] - sum) / a[i][i];
  743. }
  744. //高斯列主元消去法结束,输出
  745. // [0] = c, [1] = b (* x)
  746. for(i = 0; i < rank + 1; i++)
  747. UartSendFloatStr(b[i]);
  748. return 0;
  749. }
  750. */
  751. #endif /* __ALGO_Algorithm_ATY_C */
  752. /******************************** End Of File *********************************/