PWM/PPM Left/Right, UART update

- created possiblity to use PWM, PPM input also on both LEFT and RIGHT cable (RIGHT cable is 5V tolerant)
- updated UART: disabled the Rx errors to avoid DMA stop and additional need to manage the UART error handler
- added Button support LEFT/RIGHT
This commit is contained in:
EmanuelFeru 2020-06-25 20:17:55 +02:00
parent 526cee4c0f
commit 17e127a8b7
11 changed files with 242 additions and 138 deletions

View File

@ -153,7 +153,6 @@
#define INACTIVITY_TIMEOUT 8 // Minutes of not driving until poweroff. it is not very precise.
#define BEEPS_BACKWARD 1 // 0 or 1
#define FLASH_WRITE_KEY 0x1234 // Flash writing key, used when writing data to flash memory
// #define SUPPORT_BUTTONS // Define for buttons support on ADC, Nunchuck
/* FILTER is in fixdt(0,16,16): VAL_fixedPoint = VAL_floatingPoint * 2^16. In this case 6553 = 0.1 * 2^16
* Value of COEFFICIENT is in fixdt(1,16,14)
@ -192,7 +191,7 @@
*/
// #define DEBUG_SERIAL_USART2 // left sensor board cable, disable if ADC or PPM is used!
#if defined(VARIANT_ADC) || defined(VARIANT_PPM)
#if defined(VARIANT_ADC)
#define DEBUG_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used!
#endif
@ -232,6 +231,8 @@
#define ADC2_MIN 0 // min ADC2-value while poti at minimum-position (0 - 4095)
#define ADC2_MID 2048 // mid ADC2-value while poti at minimum-position (ADC2_MIN - ADC2_MAX)
#define ADC2_MAX 4095 // max ADC2-value while poti at maximum-position (0 - 4095)
// #define SUPPORT_BUTTONS_LEFT // use left sensor board cable for button inputs. Disable DEBUG_SERIAL_USART2!
// #define SUPPORT_BUTTONS_RIGHT // use right sensor board cable for button inputs. Disable DEBUG_SERIAL_USART3!
#endif
// ############################# END OF VARIANT_ADC SETTINGS #########################
@ -246,6 +247,8 @@
// #define SIDEBOARD_SERIAL_USART3
#define CONTROL_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used! For Arduino control check the hoverSerial.ino
#define FEEDBACK_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used!
// #define SUPPORT_BUTTONS_LEFT // use left sensor board cable for button inputs. Disable DEBUG_SERIAL_USART2!
// #define SUPPORT_BUTTONS_RIGHT // use right sensor board cable for button inputs. Disable DEBUG_SERIAL_USART3!
#endif
// ######################## END OF VARIANT_USART SETTINGS #########################
@ -264,6 +267,7 @@
#define FILTER 3276 // 0.05f
#define SPEED_COEFFICIENT 8192 // 0.5f
#define STEER_COEFFICIENT 62259 // -0.2f
// #define SUPPORT_BUTTONS // Define for Nunchuck buttons support
#endif
// ############################# END OF VARIANT_NUNCHUK SETTINGS #########################
@ -275,14 +279,18 @@
* left sensor board cable. Channel 1: steering, Channel 2: speed.
* https://gist.github.com/peterpoetzi/1b63a4a844162196613871767189bd05
*/
#define CONTROL_PPM // use PPM-Sum as input. disable CONTROL_SERIAL_USART2!
#define CONTROL_PPM_LEFT // use PPM-Sum as input on the LEFT cable . disable CONTROL_SERIAL_USART2!
// #define CONTROL_PPM_RIGHT // use PPM-Sum as input on the RIGHT cable. disable CONTROL_SERIAL_USART3!
#define PPM_NUM_CHANNELS 6 // total number of PPM channels to receive, even if they are not used.
#define PPM_DEADBAND 100 // How much of the center position is considered 'center' (100 = values -100 to 100 are considered 0)
// Min / Max values of each channel (use DEBUG to determine these values)
#define PPM_CH1_MAX 1000 // (0 - 1000)
#define PPM_CH1_MIN -1000 // (-1000 - 0)
#define PPM_CH2_MAX 1000 // (0 - 1000)
#define PPM_CH2_MIN -1000 // (-1000 - 0)
#define PPM_CH2_MIN -1000 // (-1000 - 0)
// #define SUPPORT_BUTTONS // Define for PPM buttons support
// #define SUPPORT_BUTTONS_LEFT // use left sensor board cable for button inputs. Disable DEBUG_SERIAL_USART2!
// #define SUPPORT_BUTTONS_RIGHT // use right sensor board cable for button inputs. Disable DEBUG_SERIAL_USART3!
#endif
// ############################# END OF VARIANT_PPM SETTINGS ############################
@ -293,7 +301,8 @@
* left sensor board cable. Connect PA2 to channel 1 and PA3 to channel 2 on receiver.
* Channel 1: steering, Channel 2: speed.
*/
#define CONTROL_PWM // use RC PWM as input. disable DEBUG_SERIAL_USART2!
#define CONTROL_PWM_LEFT // use RC PWM as input on the LEFT cable. disable DEBUG_SERIAL_USART2!
// #define CONTROL_PWM_RIGHT // use RC PWM as input on the RIGHT cable. disable DEBUG_SERIAL_USART3!
#define PWM_DEADBAND 100 // How much of the center position is considered 'center' (100 = values -100 to 100 are considered 0)
// Min / Max values of each channel (use DEBUG to determine these values)
#define PWM_CH1_MAX 1000 // (0 - 1000)
@ -303,9 +312,10 @@
#define FILTER 6553 // 0.1f [-] fixdt(0,16,16) lower value == softer filter [0, 65535] = [0.0 - 1.0].
#define SPEED_COEFFICIENT 16384 // 1.0f [-] fixdt(1,16,14) higher value == stronger. [0, 65535] = [-2.0 - 2.0]. In this case 16384 = 1.0 * 2^14
#define STEER_COEFFICIENT 16384 // 1.0f [-] fixdt(1,16,14) higher value == stronger. [0, 65535] = [-2.0 - 2.0]. In this case 16384 = 1.0 * 2^14. If you do not want any steering, set it to 0.
// #define SUPPORT_BUTTONS // use right sensor board cable for button inputs. Disable DEBUG_SERIAL_USART3!
// #define INVERT_R_DIRECTION
// #define INVERT_L_DIRECTION
// #define SUPPORT_BUTTONS_LEFT // use left sensor board cable for button inputs. Disable DEBUG_SERIAL_USART2!
// #define SUPPORT_BUTTONS_RIGHT // use right sensor board cable for button inputs. Disable DEBUG_SERIAL_USART3!
#endif
// ############################# END OF VARIANT_PPM SETTINGS ############################
@ -344,11 +354,11 @@
#define ADC2_MAX 2200 // max ADC2-value while poti at maximum-position (0 - 4095)
#define SPEED_COEFFICIENT 16384 // 1.0f
#define STEER_COEFFICIENT 0 // 0.0f
// #define INVERT_R_DIRECTION // Invert rotation of right motor
// #define INVERT_L_DIRECTION // Invert rotation of left motor
// #define INVERT_R_DIRECTION // Invert rotation of right motor
// #define INVERT_L_DIRECTION // Invert rotation of left motor
#define SIDEBOARD_SERIAL_USART3
#define FEEDBACK_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used!
// #define DEBUG_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used!
// #define DEBUG_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used!
#endif
// Multiple tap detection: default DOUBLE Tap on Brake pedal (4 pulses)
@ -436,8 +446,11 @@
#error Variant not defined! Please check platformio.ini or Inc/config.h for available variants.
#endif
#if defined(CONTROL_SERIAL_USART2) && defined(CONTROL_SERIAL_USART3)
#error CONTROL_SERIAL_USART2 and CONTROL_SERIAL_USART3 not allowed, choose one.
// General checks
#if (defined(CONTROL_ADC) || defined(CONTROL_SERIAL_USART2) || defined(CONTROL_PPM_LEFT) || defined(CONTROL_PWM_LEFT)) && \
(defined(CONTROL_NUNCHUK) || defined(CONTROL_SERIAL_USART3) || defined(CONTROL_PPM_RIGHT) || defined(CONTROL_PWM_RIGHT))
#warning !! Multiple control input sources defined !! If NOT handled correctly, it can lead to undesired behavior!
#endif
#if defined(CONTROL_SERIAL_USART2) && defined(SIDEBOARD_SERIAL_USART2)
@ -460,34 +473,88 @@
#error DEBUG_SERIAL_USART2 and DEBUG_SERIAL_USART3 not allowed, choose one.
#endif
#if defined(CONTROL_PPM_LEFT) && defined(CONTROL_PPM_RIGHT)
#error CONTROL_PPM_LEFT and CONTROL_PPM_RIGHT not allowed, choose one.
#endif
#if defined(CONTROL_PWM_LEFT) && defined(CONTROL_PWM_RIGHT)
#error CONTROL_PWM_LEFT and CONTROL_PWM_RIGHT not allowed, choose one.
#endif
#if defined(SUPPORT_BUTTONS_LEFT) && defined(SUPPORT_BUTTONS_RIGHT)
#error SUPPORT_BUTTONS_LEFT and SUPPORT_BUTTONS_RIGHT not allowed, choose one.
#endif
// LEFT cable checks
#if defined(CONTROL_ADC) && (defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2) || defined(FEEDBACK_SERIAL_USART2) || defined(DEBUG_SERIAL_USART2))
#error CONTROL_ADC and SERIAL_USART2 not allowed. It is on the same cable.
#endif
#if (defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2) || defined(DEBUG_SERIAL_USART2)) && defined(CONTROL_PPM)
#error CONTROL_PPM and SERIAL_USART2 not allowed. It is on the same cable.
#if defined(CONTROL_PPM_LEFT) && (defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2) || defined(FEEDBACK_SERIAL_USART2) || defined(DEBUG_SERIAL_USART2))
#error CONTROL_PPM_LEFT and SERIAL_USART2 not allowed. It is on the same cable.
#endif
#if (defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2) || defined(DEBUG_SERIAL_USART2)) && defined(CONTROL_PWM)
#error CONTROL_PWM and SERIAL_USART2 not allowed. It is on the same cable.
#if defined(CONTROL_PWM_LEFT) && (defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2) || defined(FEEDBACK_SERIAL_USART2) || defined(DEBUG_SERIAL_USART2))
#error CONTROL_PWM_LEFT and SERIAL_USART2 not allowed. It is on the same cable.
#endif
#if (defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3) || defined(DEBUG_SERIAL_USART3)) && defined(CONTROL_PWM) && defined(SUPPORT_BUTTONS)
#error SUPPORT_BUTTONS and SERIAL_USART3 not allowed for VARIANT_PWM. It is on the same cable.
#if defined(SUPPORT_BUTTONS_LEFT) && (defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2) || defined(FEEDBACK_SERIAL_USART2) || defined(DEBUG_SERIAL_USART2))
#error SUPPORT_BUTTONS_LEFT and SERIAL_USART2 not allowed. It is on the same cable.
#endif
#if (defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3) || defined(DEBUG_SERIAL_USART3)) && defined(CONTROL_NUNCHUK)
#if defined(SUPPORT_BUTTONS_LEFT) && (defined(CONTROL_ADC) || defined(CONTROL_PPM_LEFT) || defined(CONTROL_PWM_LEFT))
#error SUPPORT_BUTTONS_LEFT and (CONTROL_ADC or CONTROL_PPM_LEFT or CONTROL_PWM_LEFT) not allowed. It is on the same cable.
#endif
#if defined(CONTROL_ADC) && (defined(CONTROL_PPM_LEFT) || defined(CONTROL_PWM_LEFT))
#error CONTROL_ADC and (CONTROL_PPM_LEFT or CONTROL_PWM_LEFT) not allowed. It is on the same cable.
#endif
#if defined(CONTROL_PPM_LEFT) && defined(CONTROL_PWM_LEFT)
#error CONTROL_PPM_LEFT and CONTROL_PWM_LEFT not allowed. It is on the same cable.
#endif
// RIGHT cable checks
#if defined(CONTROL_NUNCHUK) && (defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3) || defined(FEEDBACK_SERIAL_USART3) || defined(DEBUG_SERIAL_USART3))
#error CONTROL_NUNCHUK and SERIAL_USART3 not allowed. It is on the same cable.
#endif
#if (defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3) || defined(DEBUG_SERIAL_USART3)) && defined(DEBUG_I2C_LCD)
#if defined(CONTROL_PPM_RIGHT) && (defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3) || defined(FEEDBACK_SERIAL_USART3) || defined(DEBUG_SERIAL_USART3))
#error CONTROL_PPM_RIGHT and SERIAL_USART3 not allowed. It is on the same cable.
#endif
#if defined(CONTROL_PWM_RIGHT) && (defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3) || defined(FEEDBACK_SERIAL_USART3) || defined(DEBUG_SERIAL_USART3))
#error CONTROL_PWM_RIGHT and SERIAL_USART3 not allowed. It is on the same cable.
#endif
#if defined(DEBUG_I2C_LCD) && (defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3) || defined(FEEDBACK_SERIAL_USART3) || defined(DEBUG_SERIAL_USART3))
#error DEBUG_I2C_LCD and SERIAL_USART3 not allowed. It is on the same cable.
#endif
#if defined(CONTROL_ADC) && (defined(CONTROL_PPM) || defined(CONTROL_PWM) || defined(CONTROL_NUNCHUK)) || defined(CONTROL_PPM) && (defined(CONTROL_PWM) || defined(CONTROL_NUNCHUK)) || defined(CONTROL_PWM) && defined(CONTROL_NUNCHUK)
#error only 1 input method allowed. use CONTROL_ADC or CONTROL_PPM or CONTROL_PWM or CONTROL_NUNCHUK.
#if defined(SUPPORT_BUTTONS_RIGHT) && (defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3) || defined(FEEDBACK_SERIAL_USART3) || defined(DEBUG_SERIAL_USART3))
#error SUPPORT_BUTTONS_RIGHT and SERIAL_USART3 not allowed. It is on the same cable.
#endif
#if defined(SUPPORT_BUTTONS_RIGHT) && (defined(CONTROL_NUNCHUK) || defined(CONTROL_PPM_RIGHT) || defined(CONTROL_PWM_RIGHT) || defined(DEBUG_I2C_LCD))
#error SUPPORT_BUTTONS_RIGHT and (CONTROL_NUNCHUK or CONTROL_PPM_RIGHT or CONTROL_PWM_RIGHT or DEBUG_I2C_LCD) not allowed. It is on the same cable.
#endif
#if defined(CONTROL_NUNCHUK) && (defined(CONTROL_PPM_RIGHT) || defined(CONTROL_PWM_RIGHT) || defined(DEBUG_I2C_LCD))
#error CONTROL_NUNCHUK and (CONTROL_PPM_RIGHT or CONTROL_PWM_RIGHT or DEBUG_I2C_LCD) not allowed. It is on the same cable.
#endif
#if defined(DEBUG_I2C_LCD) && (defined(CONTROL_PPM_RIGHT) || defined(CONTROL_PWM_RIGHT))
#error DEBUG_I2C_LCD and (CONTROL_PPM_RIGHT or CONTROL_PWM_RIGHT) not allowed. It is on the same cable.
#endif
#if defined(CONTROL_PPM_RIGHT) && defined(CONTROL_PWM_RIGHT)
#error CONTROL_PPM_RIGHT and CONTROL_PWM_RIGHT not allowed. It is on the same cable.
#endif
// Functional checks
#if defined(ADC_PROTECT_ENA) && ((ADC1_MIN - ADC_PROTECT_THRESH) <= 0 || (ADC1_MAX + ADC_PROTECT_THRESH) >= 4095)
#warning ADC1 Protection NOT possible! Adjust the ADC thresholds.
#undef ADC_PROTECT_ENA
@ -498,7 +565,7 @@
#undef ADC_PROTECT_ENA
#endif
#if defined(CONTROL_PPM) && !defined(PPM_NUM_CHANNELS)
#if (defined(CONTROL_PPM_LEFT) || defined(CONTROL_PPM_RIGHT)) && !defined(PPM_NUM_CHANNELS)
#error Total number of PPM channels needs to be set
#endif
// ############################# END OF VALIDATE SETTINGS ############################

View File

@ -125,10 +125,37 @@
#define CHARGER_PIN GPIO_PIN_12
#define CHARGER_PORT GPIOA
#define BUTTON1_RIGHT_PIN GPIO_PIN_10
#define BUTTON1_RIGHT_PORT GPIOB
#define BUTTON2_RIGHT_PIN GPIO_PIN_11
#define BUTTON2_RIGHT_PORT GPIOB
#if defined(CONTROL_PPM_LEFT)
#define PPM_PIN GPIO_PIN_3
#define PPM_PORT GPIOA
#elif defined(CONTROL_PPM_RIGHT)
#define PPM_PIN GPIO_PIN_11
#define PPM_PORT GPIOB
#endif
#if defined(CONTROL_PWM_LEFT)
#define PWM_PIN_CH1 GPIO_PIN_2
#define PWM_PORT_CH1 GPIOA
#define PWM_PIN_CH2 GPIO_PIN_3
#define PWM_PORT_CH2 GPIOA
#elif defined(CONTROL_PWM_RIGHT)
#define PWM_PIN_CH1 GPIO_PIN_10
#define PWM_PORT_CH1 GPIOB
#define PWM_PIN_CH2 GPIO_PIN_11
#define PWM_PORT_CH2 GPIOB
#endif
#if defined(SUPPORT_BUTTONS_LEFT)
#define BUTTON1_PIN GPIO_PIN_2
#define BUTTON1_PORT GPIOA
#define BUTTON2_PIN GPIO_PIN_3
#define BUTTON2_PORT GPIOA
#elif defined(SUPPORT_BUTTONS_RIGHT)
#define BUTTON1_PIN GPIO_PIN_10
#define BUTTON1_PORT GPIOB
#define BUTTON2_PIN GPIO_PIN_11
#define BUTTON2_PORT GPIOB
#endif
#define DELAY_TIM_FREQUENCY_US 1000000

View File

@ -58,6 +58,7 @@
void BLDC_Init(void);
void Input_Lim_Init(void);
void Input_Init(void);
void UART_DisableRxErrors(UART_HandleTypeDef *huart);
// General Functions
void poweronMelody(void);
@ -87,7 +88,6 @@ void usart_process_command(SerialCommand *command_in, SerialCommand *command_out
#if defined(SIDEBOARD_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART3)
void usart_process_sideboard(SerialSideboard *Sideboard_in, SerialSideboard *Sideboard_out, uint8_t usart_idx);
#endif
void UART_EndRxTransfer(UART_HandleTypeDef *huart);
// Sideboard functions
void sideboardLeds(uint8_t *leds);

View File

@ -17,7 +17,7 @@ This repository implements Field Oriented Control (FOC) for stock hoverboards. C
![mainboard_pinout](/docs/pictures/mainboard_pinout.png)
The original Hardware supports two 4-pin cables that originally were connected to the two sensor boards. They break out GND, 12/15V and USART2&3 of the Hoverboard mainboard. Both USART2&3 can be used for UART and I2C, PA2&3 can be used as 12bit ADCs. Note that while USART3 (right sideboard cable) is 5V tolerant, USART2 (left sideboard cable) is **not** 5V tolerant.
The original Hardware supports two 4-pin cables that originally were connected to the two sideboards. They break out GND, 12/15V and USART2&3 of the Hoverboard mainboard. Both USART2&3 support UART, PWM, PPM, and iBUS input. Additionally, the USART2 can be used as 12bit ADC, while USART3 can be used for I2C. Note that while USART3 (right sideboard cable) is 5V tolerant, USART2 (left sideboard cable) is **not** 5V tolerant.
Typically, the mainboard brain is an [STM32F103RCT6](/docs/literature/[10]_STM32F103xC_datasheet.pdf), however some mainboards feature a [GD32F103RCT6](/docs/literature/[11]_GD32F103xx-Datasheet-Rev-2.7.pdf) which is also supported by this firmware.

View File

@ -19,7 +19,7 @@ extern I2C_HandleTypeDef hi2c2;
extern DMA_HandleTypeDef hdma_i2c2_rx;
extern DMA_HandleTypeDef hdma_i2c2_tx;
#ifdef CONTROL_PPM
#if defined(CONTROL_PPM_LEFT) || defined(CONTROL_PPM_RIGHT)
uint16_t ppm_captured_value[PPM_NUM_CHANNELS + 1] = {500, 500};
uint16_t ppm_captured_value_buffer[PPM_NUM_CHANNELS+1] = {500, 500};
uint32_t ppm_timeout = 0;
@ -61,13 +61,13 @@ void PPM_SysTick_Callback(void) {
}
void PPM_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct = {0};
/*Configure GPIO pin : PA3 */
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Pin = PPM_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_Init(PPM_PORT, &GPIO_InitStruct);
__HAL_RCC_TIM2_CLK_ENABLE();
TimHandle.Instance = TIM2;
@ -85,7 +85,7 @@ void PPM_Init(void) {
#endif
#ifdef CONTROL_PWM
#if defined(CONTROL_PWM_LEFT) || defined(CONTROL_PWM_RIGHT)
/*
* Illustration of the PWM functionality
* CH1 ________||________
@ -103,8 +103,8 @@ uint32_t pwm_timeout_ch2 = 0;
void PWM_ISR_CH1_Callback(void) {
// Dummy loop with 16 bit count wrap around
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2)) { // Rising Edge interrupt -> save timer value OR reset timer
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3)) {
if(HAL_GPIO_ReadPin(PWM_PORT_CH1, PWM_PIN_CH1)) { // Rising Edge interrupt -> save timer value OR reset timer
if (HAL_GPIO_ReadPin(PWM_PORT_CH2, PWM_PIN_CH2)) {
pwm_CNT_prev_ch1 = TIM2->CNT;
} else {
TIM2->CNT = 0;
@ -122,8 +122,8 @@ void PWM_ISR_CH1_Callback(void) {
void PWM_ISR_CH2_Callback(void) {
// Dummy loop with 16 bit count wrap around
if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3)) { // Rising Edge interrupt -> save timer value OR reset timer
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_2)) {
if(HAL_GPIO_ReadPin(PWM_PORT_CH2, PWM_PIN_CH2)) { // Rising Edge interrupt -> save timer value OR reset timer
if (HAL_GPIO_ReadPin(PWM_PORT_CH1, PWM_PIN_CH1)) {
pwm_CNT_prev_ch2 = TIM2->CNT;
} else {
TIM2->CNT = 0;
@ -162,35 +162,39 @@ void PWM_Init(void) {
TimHandle.Init.Prescaler = (SystemCoreClock/DELAY_TIM_FREQUENCY_US)-1;;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_Base_Init(&TimHandle);
HAL_TIM_Base_Init(&TimHandle);
// Channel 1 (steering)
GPIO_InitTypeDef GPIO_InitStruct2;
// Configure GPIO pin : PA2
GPIO_InitStruct2.Pin = GPIO_PIN_2;
GPIO_InitTypeDef GPIO_InitStruct1 = {0};
// Configure GPIO pin : PA2 (Left) or PB10 (Right)
GPIO_InitStruct1.Pin = PWM_PIN_CH1;
GPIO_InitStruct1.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_InitStruct1.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct1.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(PWM_PORT_CH1, &GPIO_InitStruct1);
// Channel 2 (speed)
GPIO_InitTypeDef GPIO_InitStruct2 = {0};
/*Configure GPIO pin : PA3 (Left) or PB11 (Right) */
GPIO_InitStruct2.Pin = PWM_PIN_CH2;
GPIO_InitStruct2.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_InitStruct2.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct2.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct2);
HAL_GPIO_Init(PWM_PORT_CH2, &GPIO_InitStruct2);
// EXTI interrupt init
#ifdef CONTROL_PWM_LEFT
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI2_IRQn);
// Channel 2 (speed)
GPIO_InitTypeDef GPIO_InitStruct;
/*Configure GPIO pin : PA3 */
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI3_IRQn);
#endif
#ifdef CONTROL_PWM_RIGHT
/* EXTI interrupt init*/
HAL_NVIC_SetPriority(EXTI15_10_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(EXTI15_10_IRQn);
#endif
// Start timer
HAL_TIM_Base_Start(&TimHandle);

View File

@ -85,10 +85,10 @@ extern SerialSideboard Sideboard_L;
#if defined(SIDEBOARD_SERIAL_USART3)
extern SerialSideboard Sideboard_R;
#endif
#if defined(CONTROL_PPM) && defined(DEBUG_SERIAL_USART3)
#if (defined(CONTROL_PPM_LEFT) && defined(DEBUG_SERIAL_USART3)) || (defined(CONTROL_PPM_RIGHT) && defined(DEBUG_SERIAL_USART2))
extern volatile uint16_t ppm_captured_value[PPM_NUM_CHANNELS+1];
#endif
#if defined(CONTROL_PWM) && defined(DEBUG_SERIAL_USART3)
#if (defined(CONTROL_PWM_LEFT) && defined(DEBUG_SERIAL_USART3)) || (defined(CONTROL_PWM_RIGHT) && defined(DEBUG_SERIAL_USART2))
extern volatile uint16_t pwm_captured_ch1_value;
extern volatile uint16_t pwm_captured_ch2_value;
#endif
@ -392,11 +392,11 @@ int main(void) {
setScopeChannel(0, (int16_t)adc_buffer.l_tx2); // 1: ADC1
setScopeChannel(1, (int16_t)adc_buffer.l_rx2); // 2: ADC2
#endif
#ifdef CONTROL_PPM
#if defined(CONTROL_PPM_LEFT) || defined(CONTROL_PPM_RIGHT)
setScopeChannel(0, ppm_captured_value[0]); // 1: CH1
setScopeChannel(1, ppm_captured_value[1]); // 2: CH2
#endif
#ifdef CONTROL_PWM
#if defined(CONTROL_PWM_LEFT) || defined(CONTROL_PWM_RIGHT)
setScopeChannel(0, pwm_captured_ch1_value); // 1: CH1
setScopeChannel(1, pwm_captured_ch2_value); // 2: CH2
#endif

View File

@ -107,6 +107,8 @@ void UART3_Init(void)
}
#endif
#if defined(DEBUG_SERIAL_USART2) || defined(CONTROL_SERIAL_USART2) || defined(FEEDBACK_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2) || \
defined(DEBUG_SERIAL_USART3) || defined(CONTROL_SERIAL_USART3) || defined(FEEDBACK_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3)
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
@ -274,7 +276,7 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
/* USER CODE END USART3_MspDeInit 1 */
}
}
#endif
DMA_HandleTypeDef hdma_i2c2_rx;
DMA_HandleTypeDef hdma_i2c2_tx;

View File

@ -166,11 +166,11 @@ void PendSV_Handler(void) {
/**
* @brief This function handles System tick timer.
*/
#ifdef CONTROL_PPM
#if defined(CONTROL_PPM_LEFT) || defined(CONTROL_PPM_RIGHT)
void PPM_SysTick_Callback(void);
#endif
#ifdef CONTROL_PWM
#if defined(CONTROL_PWM_LEFT) || defined(CONTROL_PWM_RIGHT)
void PWM_SysTick_Callback(void);
#endif
@ -181,11 +181,11 @@ void SysTick_Handler(void) {
HAL_IncTick();
HAL_SYSTICK_IRQHandler();
/* USER CODE BEGIN SysTick_IRQn 1 */
#ifdef CONTROL_PPM
#if defined(CONTROL_PPM_LEFT) || defined(CONTROL_PPM_RIGHT)
PPM_SysTick_Callback();
#endif
#ifdef CONTROL_PWM
#if defined(CONTROL_PWM_LEFT) || defined(CONTROL_PWM_RIGHT)
PWM_SysTick_Callback();
#endif
/* USER CODE END SysTick_IRQn 1 */
@ -232,25 +232,47 @@ void DMA1_Channel5_IRQHandler(void)
}
#endif
#ifdef CONTROL_PPM
#ifdef CONTROL_PPM_LEFT
void EXTI3_IRQHandler(void)
{
__HAL_GPIO_EXTI_CLEAR_IT(PPM_PIN);
PPM_ISR_Callback();
}
#endif
#ifdef CONTROL_PPM_RIGHT
void EXTI15_10_IRQHandler(void)
{
if(__HAL_GPIO_EXTI_GET_IT(PPM_PIN) != RESET) {
__HAL_GPIO_EXTI_CLEAR_IT(PPM_PIN);
PPM_ISR_Callback();
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_3);
}
}
#endif
#ifdef CONTROL_PWM
void EXTI3_IRQHandler(void)
{
PWM_ISR_CH2_Callback();
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_3);
#ifdef CONTROL_PWM_LEFT
void EXTI2_IRQHandler(void)
{
__HAL_GPIO_EXTI_CLEAR_IT(PWM_PIN_CH1);
PWM_ISR_CH1_Callback();
}
void EXTI2_IRQHandler(void)
void EXTI3_IRQHandler(void)
{
__HAL_GPIO_EXTI_CLEAR_IT(PWM_PIN_CH2);
PWM_ISR_CH2_Callback();
}
#endif
#ifdef CONTROL_PWM_RIGHT
void EXTI15_10_IRQHandler(void)
{
if(__HAL_GPIO_EXTI_GET_IT(PWM_PIN_CH1) != RESET) {
__HAL_GPIO_EXTI_CLEAR_IT(PWM_PIN_CH1);
PWM_ISR_CH1_Callback();
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_2);
}
if(__HAL_GPIO_EXTI_GET_IT(PWM_PIN_CH2) != RESET) {
__HAL_GPIO_EXTI_CLEAR_IT(PWM_PIN_CH2);
PWM_ISR_CH2_Callback();
}
}
#endif

View File

@ -55,11 +55,11 @@ extern uint8_t nunchuk_data[6];
extern volatile uint32_t timeout; // global variable for timeout
extern volatile uint32_t main_loop_counter;
#ifdef CONTROL_PPM
#if defined(CONTROL_PPM_LEFT) || defined(CONTROL_PPM_RIGHT)
extern volatile uint16_t ppm_captured_value[PPM_NUM_CHANNELS+1];
#endif
#ifdef CONTROL_PWM
#if defined(CONTROL_PWM_LEFT) || defined(CONTROL_PWM_RIGHT)
extern volatile uint16_t pwm_captured_ch1_value;
extern volatile uint16_t pwm_captured_ch2_value;
#endif
@ -156,7 +156,6 @@ static int16_t timeoutCntADC = 0; // Timeout counter for ADC Protection
#if defined(DEBUG_SERIAL_USART2) || defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2)
static uint8_t rx_buffer_L[SERIAL_BUFFER_SIZE]; // USART Rx DMA circular buffer
static uint32_t rx_buffer_L_len = ARRAY_LEN(rx_buffer_L);
static uint32_t old_pos;
#endif
#if defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2)
static uint16_t timeoutCntSerial_L = 0; // Timeout counter for Rx Serial command
@ -171,7 +170,6 @@ static uint32_t Sideboard_L_len = sizeof(Sideboard_L);
#if defined(DEBUG_SERIAL_USART3) || defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3)
static uint8_t rx_buffer_R[SERIAL_BUFFER_SIZE]; // USART Rx DMA circular buffer
static uint32_t rx_buffer_R_len = ARRAY_LEN(rx_buffer_R);
static uint32_t old_pos;
#endif
#if defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3)
static uint16_t timeoutCntSerial_R = 0; // Timeout counter for Rx Serial command
@ -200,12 +198,12 @@ static uint8_t sensor1_index; // holds the press index number for sens
static uint8_t sensor2_index; // holds the press index number for sensor2, when used as a button
#endif
#ifdef SUPPORT_BUTTONS
#if defined(SUPPORT_BUTTONS) || defined(SUPPORT_BUTTONS_LEFT) || defined(SUPPORT_BUTTONS_RIGHT)
static uint8_t button1, button2;
#endif
#ifdef VARIANT_HOVERCAR
static uint8_t brakePressed;
static uint8_t brakePressed;
#endif
@ -255,11 +253,11 @@ void Input_Lim_Init(void) { // Input Limitations - ! Do NOT touch !
}
void Input_Init(void) {
#ifdef CONTROL_PPM
#if defined(CONTROL_PPM_LEFT) || defined(CONTROL_PPM_RIGHT)
PPM_Init();
#endif
#ifdef CONTROL_PWM
#if defined(CONTROL_PWM_LEFT) || defined(CONTROL_PWM_RIGHT)
PWM_Init();
#endif
@ -276,9 +274,11 @@ void Input_Init(void) {
#endif
#if defined(DEBUG_SERIAL_USART2) || defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2)
HAL_UART_Receive_DMA(&huart2, (uint8_t *)rx_buffer_L, sizeof(rx_buffer_L));
UART_DisableRxErrors(&huart2);
#endif
#if defined(DEBUG_SERIAL_USART3) || defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3)
HAL_UART_Receive_DMA(&huart3, (uint8_t *)rx_buffer_R, sizeof(rx_buffer_R));
UART_DisableRxErrors(&huart3);
#endif
#ifdef CONTROL_ADC
@ -356,6 +356,23 @@ void Input_Init(void) {
#endif
}
/**
* @brief Disable Rx Errors detection interrupts on UART peripheral (since we do not want DMA to be stopped)
* The incorrect data will be filtered based on the START_FRAME and checksum.
* @param huart: UART handle.
* @retval None
*/
#if defined(DEBUG_SERIAL_USART2) || defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2) || \
defined(DEBUG_SERIAL_USART3) || defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3)
void UART_DisableRxErrors(UART_HandleTypeDef *huart)
{
/* Disable PE (Parity Error) interrupts */
CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
/* Disable EIE (Frame error, noise error, overrun error) interrupts */
CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
}
#endif
/* =========================== General Functions =========================== */
@ -555,7 +572,7 @@ void saveConfig() {
* This function realizes a dead-band around 0 and scales the input within a min and a max
*/
int addDeadBand(int16_t u, int16_t deadBand, int16_t min, int16_t max) {
#if defined(CONTROL_PPM) || defined(CONTROL_PWM)
#if defined(CONTROL_PPM_LEFT) || defined(CONTROL_PPM_RIGHT) || defined(CONTROL_PWM_LEFT) || defined(CONTROL_PWM_RIGHT)
int outVal = 0;
if(u > -deadBand && u < deadBand) {
outVal = 0;
@ -662,22 +679,25 @@ void readCommand(void) {
}
#endif
#ifdef CONTROL_PPM
#if defined(CONTROL_PPM_LEFT) || defined(CONTROL_PPM_RIGHT)
cmd1 = CLAMP(addDeadBand((ppm_captured_value[0] - 500) * 2, PPM_DEADBAND, PPM_CH1_MIN, PPM_CH1_MAX), INPUT_MIN, INPUT_MAX);
cmd2 = CLAMP(addDeadBand((ppm_captured_value[1] - 500) * 2, PPM_DEADBAND, PPM_CH2_MIN, PPM_CH2_MAX), INPUT_MIN, INPUT_MAX);
#ifdef SUPPORT_BUTTONS
button1 = ppm_captured_value[5] > 500;
button2 = 0;
#elif defined(SUPPORT_BUTTONS_LEFT) || defined(SUPPORT_BUTTONS_RIGHT)
button1 = !HAL_GPIO_ReadPin(BUTTON1_PORT, BUTTON1_PIN);
button2 = !HAL_GPIO_ReadPin(BUTTON2_PORT, BUTTON2_PIN);
#endif
// float scale = ppm_captured_value[2] / 1000.0f; // not used for now, uncomment if needed
#endif
#ifdef CONTROL_PWM
#if defined(CONTROL_PWM_LEFT) || defined(CONTROL_PWM_RIGHT)
cmd1 = CLAMP(addDeadBand((pwm_captured_ch1_value - 500) * 2, PWM_DEADBAND, PWM_CH1_MIN, PWM_CH1_MAX), INPUT_MIN, INPUT_MAX);
cmd2 = CLAMP(addDeadBand((pwm_captured_ch2_value - 500) * 2, PWM_DEADBAND, PWM_CH2_MIN, PWM_CH2_MAX), INPUT_MIN, INPUT_MAX);
#ifdef SUPPORT_BUTTONS
button1 = !HAL_GPIO_ReadPin(BUTTON1_RIGHT_PORT, BUTTON1_RIGHT_PIN);
button2 = !HAL_GPIO_ReadPin(BUTTON2_RIGHT_PORT, BUTTON2_RIGHT_PIN);
#if defined(SUPPORT_BUTTONS_LEFT) || defined(SUPPORT_BUTTONS_RIGHT)
button1 = !HAL_GPIO_ReadPin(BUTTON1_PORT, BUTTON1_PIN);
button2 = !HAL_GPIO_ReadPin(BUTTON2_PORT, BUTTON2_PIN);
#endif
#endif
@ -722,12 +742,10 @@ void readCommand(void) {
}
#endif
// use ADCs as button inputs:
#ifdef SUPPORT_BUTTONS
button1 = (uint8_t)(adc_buffer.l_tx2 > 2000); // ADC1
button2 = (uint8_t)(adc_buffer.l_rx2 > 2000); // ADC2
#endif
#if defined(SUPPORT_BUTTONS_LEFT) || defined(SUPPORT_BUTTONS_RIGHT)
button1 = !HAL_GPIO_ReadPin(BUTTON1_PORT, BUTTON1_PIN);
button2 = !HAL_GPIO_ReadPin(BUTTON2_PORT, BUTTON2_PIN);
#endif
timeout = 0;
#endif
@ -753,6 +771,11 @@ void readCommand(void) {
} else {
ctrlModReq = ctrlModReqRaw; // Follow the Mode request
}
#if defined(SUPPORT_BUTTONS_LEFT) || defined(SUPPORT_BUTTONS_RIGHT)
button1 = !HAL_GPIO_ReadPin(BUTTON1_PORT, BUTTON1_PIN);
button2 = !HAL_GPIO_ReadPin(BUTTON2_PORT, BUTTON2_PIN);
#endif
timeout = 0;
#endif
@ -799,6 +822,7 @@ void readCommand(void) {
void usart2_rx_check(void)
{
#if defined(DEBUG_SERIAL_USART2) || defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2)
static uint32_t old_pos;
uint32_t pos;
pos = rx_buffer_L_len - __HAL_DMA_GET_COUNTER(huart2.hdmarx); // Calculate current position in buffer
#endif
@ -868,6 +892,7 @@ void usart2_rx_check(void)
void usart3_rx_check(void)
{
#if defined(DEBUG_SERIAL_USART3) || defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3)
static uint32_t old_pos;
uint32_t pos;
pos = rx_buffer_R_len - __HAL_DMA_GET_COUNTER(huart3.hdmarx); // Calculate current position in buffer
#endif
@ -940,7 +965,7 @@ void usart_process_debug(uint8_t *userCommand, uint32_t len)
consoleLog("-- Command received --\r\n");
// handle_input(*userCommand); // -> Create this function to handle the user commands
}
}
}
}
#endif // SERIAL_DEBUG
@ -1024,49 +1049,6 @@ void usart_process_sideboard(SerialSideboard *Sideboard_in, SerialSideboard *Sid
#endif
/*
* UART User Error Callback
* - According to the STM documentation, when a DMA transfer error occurs during a DMA read or a write access,
* the faulty channel is automatically disabled through a hardware clear of its EN bit
* - For hoverboard applications, the UART communication can be unrealiable, disablind the DMA transfer
* - therefore the DMA needs to be re-started
*/
void HAL_UART_ErrorCallback(UART_HandleTypeDef *uartHandle) {
#if defined(DEBUG_SERIAL_USART2) || defined(CONTROL_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2)
if(uartHandle->Instance == USART2) {
HAL_DMA_Abort(uartHandle->hdmarx);
UART_EndRxTransfer(uartHandle);
HAL_UART_Receive_DMA(uartHandle, (uint8_t *)rx_buffer_L, sizeof(rx_buffer_L));
old_pos = 0;
}
#endif
#if defined(DEBUG_SERIAL_USART3) || defined(CONTROL_SERIAL_USART3) || defined(SIDEBOARD_SERIAL_USART3)
if(uartHandle->Instance == USART3) {
HAL_DMA_Abort(uartHandle->hdmarx);
UART_EndRxTransfer(uartHandle);
HAL_UART_Receive_DMA(uartHandle, (uint8_t *)rx_buffer_R, sizeof(rx_buffer_R));
old_pos = 0;
}
#endif
}
/**
* @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion).
* @param huart: UART handle.
* @retval None
*/
void UART_EndRxTransfer(UART_HandleTypeDef *huart)
{
/* Disable RXNE (Interrupt Enable) and PE (Parity Error) interrupts */
CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
/* Disable EIE (Frame error, noise error, overrun error) interrupts */
CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
/* At end of Rx process, restore huart->RxState to Ready */
huart->RxState = HAL_UART_STATE_READY;
}
/* =========================== Sideboard Functions =========================== */
/*

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB