EBiCS_Firmware icon indicating copy to clipboard operation
EBiCS_Firmware copied to clipboard

Dangerous error produced in speed calculation for EBiCS display method

Open wuwbobo2021 opened this issue 2 years ago • 2 comments

In case of 2.2 m of wheel circumference, single magnet in the spokes:

#define WHEEL_CIRCUMFERENCE 2200
#define PULSES_PER_REVOLUTION 1

When the speed reaches 4r/s (4 * 2.2 * 3.6 = 31.68 km/h), the interval measured by TIM3 is (1/f)/[1/(64M/7814)] = 8190/f = 8190/4 = 2048; the value in EBiCS is [(int)2200 / ((int)2048 >> 3)] * 36 / 10 = 28.8, nearly 2 km/h error produced.

you can draw two functions in the calculator

y = 2.2*3.6*x
y = 3.6*floor(2200/floor(8190/x/8))

to see the maximum error 4.3 km/h. 29 km/h will be shown as 25 km/h!

I have extracted related code from your project (with many unindented code):

int main(void)
{
	...
	while (1)
	{
		...
		// SPEED signal processing
		if (ui8_SPEED_flag) {
			if(uint32_SPEED_counter > 200) { //debounce
				MS.Speed = uint32_SPEED_counter;
				uint32_SPEED_counter = 0;
				ui8_SPEED_flag = 0;
			}
		}
		...
		if (ui32_tim3_counter > 500) {
			if(uint32_SPEED_counter > 127999)
				MS.Speed = 128000;
			...
			ui8_slowloop_counter++;
			if (ui8_slowloop_counter > 3) {
				ui8_slowloop_counter = 0;
				send_ant_page(0, &MS, &MP);
			}
			ui32_tim3_counter = 0;
		}
		...
	}
}

// elapse frequency of TIM3 is 64M/7814 (Hz), interval is about 122.1 us
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim == &htim3) {
		if(ui32_tim3_counter < 32000)
			ui32_tim3_counter++;
		...
		if (uint32_SPEED_counter < 128000)
			uint32_SPEED_counter++; //counter for external Speed sensor
	}
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	...
	//Speed processing
	if(GPIO_Pin == Speed_EXTI5_Pin)
		ui8_SPEED_flag = 1; //with debounce

}

void send_ant_page(uint8_t page, MotorState_t* MS, MotorParams_t* MP)
{
	...
	// *3,6 for km/h then *10 for LEV standard definition.
	uint16_t speedx10 = MP->wheel_cirumference / ((MS->Speed*MP->pulses_per_revolution) >> 3) * 36;
	
	ui8_tx_buffer[9] = speedx10 & 0xFF; //low byte of speed
	ui8_tx_buffer[10] = speedx10>>8 & 0x07; //lower 3 Bytes(needs correction) of high byte
	...
	HAL_UART_Transmit_DMA(&huart1, (uint8_t *)&ui8_tx_buffer, 12);
}

Thanks.

wuwbobo2021 avatar Apr 06 '23 11:04 wuwbobo2021

Looking into kingmeter_update() and internal_tics_to_speedx100() in main.c, it seems like MS.Speed may have different units for speed sources EXTERNAL and INTERNAL, but the current speedx10 sent for EBiCS display just takes care of EXTERNAL source. Am I wrong?

wuwbobo2021 avatar Dec 24 '24 08:12 wuwbobo2021

Also note that current UART transfer routines may not work with bluetooth serial adapters (connected to the controller's meter interface) featuring AT-like protocol before connection. In my case, bytes sent from the host device are always dislocated in the MCU receive buffer if I don't power on the serial adapter and connect to it before turning on the controller's power. It's probably caused by +CONNECTED\r\n received before the adapter turned into passthrough mode. The byte dislocation looks like this in Android logcat: (with my modified protocol, sending back the data)

01-08 09:42:31.121 30740 30754 W ebics_panel: ebics_panel: Prepared data to be sent: [0, 0, 0, 16, 0, 0, 8, 0, 0, 0, 0, 24].
01-08 09:42:31.121 30740 30754 W ebics_panel: ebics_panel: data should be sent.
01-08 09:42:31.220 30740 30754 W ebics_panel: ebics_panel: Unknown data received: [0, 0, 8, 0, 0, 0, 0, 24, 0, 0, 0, 16]
01-08 09:42:31.545 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 4, 0, 0, 0, 0, 3, 6, 0, 231].
01-08 09:42:31.774 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 1, 7, 0, 0, 0, 0, 125, 0, 157].
01-08 09:42:32.197 30740 30754 W ebics_panel: ebics_panel: Prepared data to be sent: [0, 0, 0, 16, 0, 0, 8, 0, 0, 0, 0, 24].
01-08 09:42:32.203 30740 30754 W ebics_panel: ebics_panel: data should be sent.
01-08 09:42:32.268 30740 30754 W ebics_panel: ebics_panel: Unknown data received: [0, 0, 8, 0, 0, 0, 0, 24, 0, 0, 0, 16]
01-08 09:42:32.517 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 4, 0, 0, 0, 0, 4, 6, 0, 224].
01-08 09:42:32.747 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 1, 7, 0, 0, 0, 0, 125, 0, 157].
01-08 09:42:33.485 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 4, 0, 0, 0, 0, 4, 6, 0, 224].
01-08 09:42:33.738 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 1, 7, 0, 0, 0, 0, 125, 0, 157].
01-08 09:42:34.454 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 4, 0, 0, 0, 0, 4, 6, 0, 224].
01-08 09:42:34.725 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 1, 7, 0, 0, 0, 0, 125, 0, 157].
01-08 09:42:35.452 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 4, 0, 0, 0, 0, 4, 6, 0, 224].
01-08 09:42:35.682 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 1, 7, 0, 0, 0, 0, 125, 0, 157].
01-08 09:42:36.031 30740 30754 W ebics_panel: ebics_panel: Prepared data to be sent: [0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 16].
01-08 09:42:36.031 30740 30754 W ebics_panel: ebics_panel: data should be sent.
01-08 09:42:36.097 30740 30754 W ebics_panel: ebics_panel: Unknown data received: [0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16]
01-08 09:42:36.442 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 4, 0, 0, 0, 0, 4, 6, 0, 224].
01-08 09:42:36.668 30740 30754 W ebics_panel: ebics_panel: Received status data: [164, 12, 78, 1, 7, 0, 0, 0, 0, 125, 0, 157].
01-08 09:42:37.028 30740 30754 W ebics_panel: ebics_panel: Prepared data to be sent: [0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 16].
01-08 09:42:37.028 30740 30754 W ebics_panel: ebics_panel: data should be sent.
01-08 09:42:37.091 30740 30754 W ebics_panel: ebics_panel: Unknown data received: [0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16]

My solution is to add this at the end of process_ebics_page in display_ebics.c. Do you think it's a bad idea?

		// restart DMA in case of the received data length isn't 12
		HAL_UART_AbortReceive(&huart1); // this disables the DMA transfer too
		if (HAL_UART_Receive_DMA(&huart1, (uint8_t *) ui8_rx_buffer, 12) != HAL_OK) {
		    // do not halt the program while riding, in case of it happens
			//Error_Handler();
		}

wuwbobo2021 avatar Jan 08 '25 05:01 wuwbobo2021