Velocity RMS calculation

mail@pastecode.io avatar
unknown
c_cpp
a year ago
5.5 kB
5
Indexable
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;
}