Velocity RMS calculation
c_cpp
16 days ago
5.5 kB
4
Indexable
Never
static uint32_t CalculateIntegralRms(uint32_t num_of_adc_samples, bool *is_overflow) { const int32_t vel_max = 65000000; // if vel_maxx > vel >vel_max, devided by 10 const int32_t vel_maxx = 650000000; // / 100 int32_t cons; int16_t *acc; // FRAM1_Start+2 int32_t *ampAcc; const int16_t amp = 1000; const int32_t amp1 = 1000000; int32_t sum; int64_t x; int16_t sum_cnt; int16_t i; int64_t z; int32_t *vel; uint64_t m; int64_t veloffset1, veloffset; int32_t temp_pk; int32_t temp_val; RESLO = 0x00; RESHI = 0x00; ampAcc = (int32_t *)FRAM3_START; acc = (int16_t *)(FRAM1_START + 2); for (i = num_of_adc_samples; i > 0; i--) // Signed 16 x 16, not accumulate 1.5S { MPYS = *acc++; OP2 = amp; *ampAcc = RESHI; // read result *ampAcc = (*ampAcc << 16) | (RESLO); ampAcc++; } // remove DC from Accel veloffset = 0; ampAcc = (int32_t *)FRAM3_START; for (i = num_of_adc_samples; i > 0; i--) { veloffset += *ampAcc++; } veloffset = veloffset / (int32_t)num_of_adc_samples; // check avg if in normal range if (veloffset < 2184000 || veloffset > 2526000) { return (0xFFFFFFFE); } // peak_rms_value = peak_rms_value - (veloffset/1000); ampAcc = (int32_t *)FRAM3_START; for (i = num_of_adc_samples; i > 0; i--) { *ampAcc = (*ampAcc - (int32_t)veloffset); ampAcc++; } sum = 0; for (i = num_of_adc_samples; i > 0; i--) // calculate Weight Cn { sum += i; } // calculate dotprod SUM RES0 = 0; RES1 = 0; RES2 = 0; RES3 = 0; MPY32CTL0 |= 0x0040 + MPYM_3; // 32 x 16 bits signed accu ampAcc = (int32_t *)FRAM3_START; for (i = num_of_adc_samples; i > 0; i--) { MACS32L = (int16_t)*ampAcc; MACS32H = (int16_t)((*ampAcc++) >> 16); OP2L = i; OP2H = 0; } z = 0; z = RES0; z += ((int64_t)RES1 << 16); z += ((int64_t)RES2 << 32); z += ((int64_t)RES3 << 48); z = z / sum; // calculate new accel ampAcc = (int32_t *)FRAM3_START; for (i = num_of_adc_samples; i > 0; i--) { *ampAcc = ((*ampAcc) + z); ampAcc++; } // integral vel = (int32_t *)(FRAM1_START + 2); // was no +2 ampAcc = (int32_t *)(FRAM3_START); *vel++ = *ampAcc; // vel 0 for (i = num_of_adc_samples; i > 0; i--) { *vel = *(vel - 1) + *ampAcc; ampAcc++; vel++; } // remove DC from vel veloffset1 = 0; veloffset = 0; sum_cnt = (num_of_adc_samples >> 1); vel = (int32_t *)(FRAM1_START + 2); // was no +2 while (sum_cnt--) { veloffset1 += *vel++; } veloffset1 = veloffset1 / (int64_t)(num_of_adc_samples >> 1); vel = (int32_t *)(FRAM1_START + 2); // was no +2 for (i = num_of_adc_samples; i > 0; i--) { veloffset += *vel++; } veloffset = veloffset / (int64_t)num_of_adc_samples; veloffset = veloffset1 + veloffset1 - veloffset; vel = (int32_t *)(FRAM1_START + 2); // was no +2 for (i = num_of_adc_samples; i > 0; i--) { *vel = (*vel - (int32_t)veloffset); vel++; } // cal mean of vel vel = (int32_t *)(FRAM1_START + 2); // was no +2 for (i = num_of_adc_samples; i > 0; i--) { veloffset1 += *vel++; } veloffset1 = veloffset1 / (int64_t)num_of_adc_samples; // x = (-2) * veloffset1/ (int64_t)num_of_adc_samples; x = (veloffset1 << 1) / (int64_t)num_of_adc_samples; // cal new vel vel = (int32_t *)(FRAM1_START + 2); // was no +2 for (i = 0; i < num_of_adc_samples; i++) { *vel = *vel - i * x; // MPY? vel++; } vel = (int32_t *)(FRAM1_START + 2); // was no +2 if (*vel > 0) { temp_pk = *vel; } else { temp_pk = (*vel ^ (*vel >> 31)) - (*vel >> 31); } for (i = num_of_adc_samples; i > 0; i--) { *vel++; if (*vel > 0) { temp_val = *vel++; } else { temp_val = (*vel ^ (*vel >> 31)) - (*vel >> 31); } if (temp_pk < temp_val) { temp_pk = temp_val; } } temp_pk = temp_pk / amp; peak_rms_value = (uint16_t)temp_pk; vel = (int32_t *)(FRAM1_START + 2); // was no +2 cons = 1; for (i = 0; i < num_of_adc_samples; i++) { if (*vel > vel_max) { cons = 10; i = num_of_adc_samples; } vel++; } vel = (int32_t *)(FRAM1_START + 2); // was no +2 for (i = 0; i < num_of_adc_samples; i++) { if (*vel > vel_maxx) { cons = 100; i = num_of_adc_samples; } vel++; } vel = (int32_t *)(FRAM1_START + 2); // was no +2 for (i = 0; i < num_of_adc_samples; i++) { *vel = *vel / cons; // MPY? // *vel= *vel>>7; vel++; } // 32 x 32 signed accumu multiplication MPY32CTL0 |= 0x0040 + MPYM_3 + 0x0080; // // 32 x 32 bits signed accu RES3 = 0; RES2 = 0; RES1 = 0; RES0 = 0; vel = (int32_t *)(FRAM1_START + 2); // was no +2 for (i = (num_of_adc_samples); i > 0; i--) { MACS32L = (int16_t)*vel; MACS32H = (int16_t)((*vel) >> 16); OP2L = (int16_t)*vel; OP2H = (int16_t)((*vel) >> 16); vel++; } m = 0; m = RES0; m += ((uint64_t)RES1 << 16); m += ((uint64_t)RES2 << 32); m += ((uint64_t)RES3 << 48); m = m / num_of_adc_samples; m = m / (uint64_t)amp1; m = sqrt430(m); if (cons == 10) m = m * 10; if (cons == 100) m = m * 100; // Set re-measure flag if velocity value is too high if (m > VRMS_HIGH_LIMIT) // 1874195 { *is_overflow = true; // m = 0; // if very high unnormal value, set m=0 to remeasure it // add some delay __delay_cycles(8000000); // around 1s } else { *is_overflow = false; } return (uint32_t)m; }