mirror of
https://github.com/EFeru/hoverboard-sideboard-hack-GD.git
synced 2025-07-27 01:29:32 +00:00
Major UART communication improvement
- the UART communication is improved based on UART Idle line detection interrupt - both Tx and Rx are efficiently handled using DMA Other: - minor visual improvements
This commit is contained in:
parent
e9d74bea29
commit
1e7bf7cd90
69
Inc/config.h
69
Inc/config.h
@ -27,60 +27,61 @@
|
||||
// Ubuntu: define the desired build variant here if you want to use make in console
|
||||
// or use VARIANT environment variable for example like "make -e VARIANT=VARIANT_DEBUG". Select only one at a time.
|
||||
#if !defined(PLATFORMIO)
|
||||
// #define VARIANT_DEBUG // Variant for debugging and checking the capabilities of the side-board
|
||||
// #define VARIANT_HOVERBOARD // Variant for using the side-boards connected to the Hoverboard mainboard
|
||||
// #define VARIANT_DEBUG // Variant for debugging and checking the capabilities of the side-board
|
||||
// #define VARIANT_HOVERBOARD // Variant for using the side-boards connected to the Hoverboard mainboard
|
||||
#endif
|
||||
|
||||
/* ==================================== DO NOT TOUCH SETTINGS ==================================== */
|
||||
#define MPU6050 // [-] Define IMU sensor type
|
||||
#define MPU_GYRO_FSR 2000 // [deg/s] Set Gyroscope Full Scale Range: 250 deg/s, 500 deg/s, 1000 deg/s, 2000 deg/s. !! DMP sensor fusion works only with 2000 deg/s !!
|
||||
#define MPU_ACCEL_FSR 2 // [g] Set Acceleromenter Full Scale Range: 2g, 4g, 8g, 16g. !! DMP sensor fusion works only with 2g !!
|
||||
#define MPU_I2C_SPEED 400000 // [bit/s] Define I2C speed for communicating with the MPU6050
|
||||
#define DELAY_IN_MAIN_LOOP 1 // [ms] Delay in the main loop
|
||||
// #define PRINTF_FLOAT_SUPPORT // [-] Uncomment this for printf to support float on Serial Debug. It will increase code size! Better to avoid it!
|
||||
#define MPU6050 // [-] Define IMU sensor type
|
||||
#define MPU_GYRO_FSR 2000 // [deg/s] Set Gyroscope Full Scale Range: 250 deg/s, 500 deg/s, 1000 deg/s, 2000 deg/s. !! DMP sensor fusion works only with 2000 deg/s !!
|
||||
#define MPU_ACCEL_FSR 2 // [g] Set Acceleromenter Full Scale Range: 2g, 4g, 8g, 16g. !! DMP sensor fusion works only with 2g !!
|
||||
#define MPU_I2C_SPEED 400000 // [bit/s] Define I2C speed for communicating with the MPU6050
|
||||
#define DELAY_IN_MAIN_LOOP 1 // [ms] Delay in the main loop
|
||||
// #define PRINTF_FLOAT_SUPPORT // [-] Uncomment this for printf to support float on Serial Debug. It will increase code size! Better to avoid it!
|
||||
/* =============================================================================================== */
|
||||
|
||||
|
||||
/* ==================================== SETTINGS MPU-6050 ==================================== */
|
||||
#define MPU_SENSOR_ENABLE // [-] Enable flag for MPU-6050 sensor. Comment-out this flag to Disable the MPU sensor and reduce code size.
|
||||
#define MPU_DMP_ENABLE // [-] Enable flag for MPU-6050 DMP (Digital Motion Processing) functionality.
|
||||
#define MPU_DEFAULT_HZ 20 // [Hz] Default MPU frequecy: must be between 1Hz and 200Hz.
|
||||
#define TEMP_READ_MS 500 // [ms] Temperature read time interval
|
||||
#define PEDO_READ_MS 1000 // [ms] Pedometer read time interval
|
||||
// #define USE_CAL_HW_REGISTERS // [-] Uncommnent this to SAVE the sensor calibration to the MPU-6050 registers after the Self-test was run
|
||||
#define MPU_DMP_ENABLE // [-] Enable flag for MPU-6050 DMP (Digital Motion Processing) functionality.
|
||||
#define MPU_DEFAULT_HZ 20 // [Hz] Default MPU frequecy: must be between 1Hz and 200Hz.
|
||||
#define TEMP_READ_MS 500 // [ms] Temperature read time interval
|
||||
#define PEDO_READ_MS 1000 // [ms] Pedometer read time interval
|
||||
// #define USE_CAL_HW_REGISTERS // [-] Uncommnent this to SAVE the sensor calibration to the MPU-6050 registers after the Self-test was run
|
||||
|
||||
// DMP Tap Detection Settings
|
||||
#define DMP_TAP_AXES TAP_XYZ // [-] Set which axes will register a tap: TAP_XYZ, TAP_X, TAP_Y, TAP_Z
|
||||
#define DMP_TAP_THRESH 250 // [mg/ms] Set tap threshold for the selected axis.
|
||||
#define DMP_TAP_COUNT 1 // [-] Set minimum number of taps needed for an interrupt. Minimum consecutive taps: 1 to 4
|
||||
#define DMP_TAP_TIME 100 // [ms] Set time length between valid taps.
|
||||
#define DMP_TAP_TIME_MULTI 500 // [ms] Set max time between taps to register as a multi-tap.
|
||||
#define DMP_SHAKE_REJECT_THRESH 200 // [deg/s] Set shake rejection threshold in degree per second (dps). If the DMP detects a gyro sample larger than the thresh, taps are rejected.
|
||||
#define DMP_SHAKE_REJECT_TIME 40 // [ms] Set shake rejection time. Sets the length of time that the gyro must be outside of the DMP_SHAKE_REJECT_THRESH before taps are rejected. A mandatory 60 ms is added to this parameter.
|
||||
#define DMP_SHAKE_REJECT_TIMEOUT 10 // [ms] Set shake rejection timeout. Sets the length of time after a shake rejection that the gyro must stay inside of the threshold before taps can be detected again. A mandatory 60 ms is added to this parameter.
|
||||
#define DMP_TAP_AXES TAP_XYZ // [-] Set which axes will register a tap: TAP_XYZ, TAP_X, TAP_Y, TAP_Z
|
||||
#define DMP_TAP_THRESH 250 // [mg/ms] Set tap threshold for the selected axis.
|
||||
#define DMP_TAP_COUNT 1 // [-] Set minimum number of taps needed for an interrupt. Minimum consecutive taps: 1 to 4
|
||||
#define DMP_TAP_TIME 100 // [ms] Set time length between valid taps.
|
||||
#define DMP_TAP_TIME_MULTI 500 // [ms] Set max time between taps to register as a multi-tap.
|
||||
#define DMP_SHAKE_REJECT_THRESH 200 // [deg/s] Set shake rejection threshold in degree per second (dps). If the DMP detects a gyro sample larger than the thresh, taps are rejected.
|
||||
#define DMP_SHAKE_REJECT_TIME 40 // [ms] Set shake rejection time. Sets the length of time that the gyro must be outside of the DMP_SHAKE_REJECT_THRESH before taps are rejected. A mandatory 60 ms is added to this parameter.
|
||||
#define DMP_SHAKE_REJECT_TIMEOUT 10 // [ms] Set shake rejection timeout. Sets the length of time after a shake rejection that the gyro must stay inside of the threshold before taps can be detected again. A mandatory 60 ms is added to this parameter.
|
||||
|
||||
|
||||
/* ==================================== SETTINGS USART ==================================== */
|
||||
#if defined(VARIANT_DEBUG)
|
||||
#define SERIAL_DEBUG // [-] Define for Serial Debug via the serial port
|
||||
#define SERIAL_DEBUG // [-] Define for Serial Debug via the serial port
|
||||
#elif defined(VARIANT_HOVERBOARD)
|
||||
#define SERIAL_CONTROL // [-] Define for Serial Control via the serial port
|
||||
#define SERIAL_FEEDBACK // [-] Define for Serial Feedback via the serial port
|
||||
#define SERIAL_CONTROL // [-] Define for Serial Control via the serial port
|
||||
#define SERIAL_FEEDBACK // [-] Define for Serial Feedback via the serial port
|
||||
#endif
|
||||
#define USART_MAIN_BAUD 38400 // [bit/s] MAIN Serial Tx/Rx baud rate
|
||||
#define SERIAL_START_FRAME 0xABCD // [-] Start frame definition for reliable serial communication
|
||||
#define SERIAL_TIMEOUT 800 // [-] Numer of wrong received data for Serial timeout detection
|
||||
#define USART_MAIN_BAUD 38400 // [bit/s] MAIN Serial Tx/Rx baud rate
|
||||
#define SERIAL_START_FRAME 0xABCD // [-] Start frame definition for reliable serial communication
|
||||
#define SERIAL_TIMEOUT 500 // [-] Number of wrong received data for Serial timeout detection. Depends on DELAY_IN_MAIN_LOOP
|
||||
#define SERIAL_BUFFER_SIZE 64 // [bytes] Size of Serial Rx buffer. Make sure it is always larger than the 'Feedback' structure size
|
||||
|
||||
|
||||
/* ==================================== SETTINGS AUX ==================================== */
|
||||
// #define AUX45_USE_GPIO // [-] Use AUX4, AUX5 as GPIO ports
|
||||
// #define AUX45_USE_I2C // [-] Use AUX4, AUX5 as I2C port
|
||||
#define AUX45_USE_USART // [-] Use AUX4, AUX5 as USART port
|
||||
// #define AUX45_USE_GPIO // [-] Use AUX4, AUX5 as GPIO ports
|
||||
// #define AUX45_USE_I2C // [-] Use AUX4, AUX5 as I2C port
|
||||
#define AUX45_USE_USART // [-] Use AUX4, AUX5 as USART port
|
||||
#ifdef AUX45_USE_USART
|
||||
#define USART_AUX_BAUD 38400 // [bit/s] AUX Serial Tx/Rx baud rate
|
||||
#define USART_AUX_BAUD 38400 // [bit/s] AUX Serial Tx/Rx baud rate
|
||||
#endif
|
||||
#ifdef AUX45_USE_I2C
|
||||
#define AUX_I2C_SPEED 100000 // [bit/s] Define I2C speed for communicating via AUX45 wires
|
||||
#define AUX_I2C_SPEED 100000 // [bit/s] Define I2C speed for communicating via AUX45 wires
|
||||
#endif
|
||||
|
||||
|
||||
@ -89,6 +90,10 @@
|
||||
#error SERIAL_DEBUG and SERIAL_CONTROL not allowed. It is on the same cable.
|
||||
#endif
|
||||
|
||||
#if defined(SERIAL_DEBUG) && defined(SERIAL_FEEDBACK)
|
||||
#error SERIAL_DEBUG and SERIAL_FEEDBACK not allowed. It is on the same cable.
|
||||
#endif
|
||||
|
||||
#if defined(AUX45_USE_GPIO) && (defined(AUX45_USE_USART) || defined(AUX45_USE_I2C)) || (defined(AUX45_USE_USART) && defined(AUX45_USE_I2C))
|
||||
#error AUX45_USE_(GPIO,USART,I2C) not allowed in the same time. It is on the same cable.
|
||||
#endif
|
||||
|
@ -31,14 +31,15 @@
|
||||
#endif
|
||||
|
||||
/* =========================== Defines General =========================== */
|
||||
// #define _BV(bit) (1 << (bit))
|
||||
// #define ARRAYNUM(arr_nanme) (uint32_t)(sizeof(arr_nanme) / sizeof(*(arr_nanme)))
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define i2c_write i2c_writeBytes
|
||||
#define i2c_read i2c_readBytes
|
||||
#define delay_ms delay_1ms
|
||||
#define get_ms get_tick_count_ms
|
||||
// #define _BV(bit) (1 << (bit))
|
||||
#define ARRAY_LEN(x) (uint32_t)(sizeof(x) / sizeof(*(x)))
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define i2c_write i2c_writeBytes
|
||||
#define i2c_read i2c_readBytes
|
||||
#define delay_ms delay_1ms
|
||||
#define get_ms get_tick_count_ms
|
||||
#define log_i printf // redirect the log_i debug function to printf
|
||||
|
||||
|
||||
/* =========================== Defines LEDs =========================== */
|
||||
@ -132,7 +133,6 @@ typedef enum {READ = 0, WRITE = !READ} i2c_cmd;
|
||||
#endif
|
||||
|
||||
/* =========================== Defines MPU-6050 =========================== */
|
||||
#define log_i printf // redirect the log_i debug function to printf
|
||||
#define RAD2DEG 57.295779513082323 // RAD2DEG = 180/pi. Example: angle[deg] = angle[rad] * RAD2DEG
|
||||
#define q30 1073741824 // 1073741824 = 2^30
|
||||
#define ACCEL_ON (0x01)
|
||||
|
@ -37,6 +37,8 @@ void DebugMon_Handler(void);
|
||||
void PendSV_Handler(void);
|
||||
/* SysTick handle function */
|
||||
void SysTick_Handler(void);
|
||||
/* USART0 handle function */
|
||||
void USART1_IRQHandler(void);
|
||||
/* I2C0 event handle function */
|
||||
void I2C0_EV_IRQHandler(void);
|
||||
/* I2C0 error handle function */
|
||||
|
@ -27,8 +27,9 @@
|
||||
// Function declarations
|
||||
void gpio_config(void);
|
||||
void usart_config(uint32_t selUSART, uint32_t selBaudRate);
|
||||
void usart_Tx_DMA_config(uint32_t selUSART, uint8_t *pData, uint32_t Size);
|
||||
void usart_Rx_DMA_config(uint32_t selUSART, uint8_t *pData, uint32_t Size);
|
||||
void usart_Tx_DMA_config(uint32_t selUSART, uint8_t *pData, uint32_t dSize);
|
||||
void usart_Rx_DMA_config(uint32_t selUSART, uint8_t *pData, uint32_t dSize);
|
||||
void usart_nvic_config(void);
|
||||
|
||||
void i2c_config(void);
|
||||
void i2c_nvic_config(void);
|
||||
|
35
Inc/util.h
35
Inc/util.h
@ -51,6 +51,41 @@ void consoleLog(char *message);
|
||||
void toggle_led(uint32_t gpio_periph, uint32_t pin);
|
||||
void intro_demo_led(uint32_t tDelay);
|
||||
|
||||
/* input initialization function */
|
||||
void input_init(void);
|
||||
|
||||
/* usart read functions */
|
||||
void usart_rx_check(void);
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
void usart_process_debug(uint8_t *userCommand, uint32_t len);
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_CONTROL
|
||||
typedef struct{
|
||||
uint16_t start;
|
||||
int16_t roll;
|
||||
int16_t pitch;
|
||||
int16_t yaw;
|
||||
uint16_t sensors;
|
||||
uint16_t checksum;
|
||||
} SerialSideboard;
|
||||
#endif
|
||||
#ifdef SERIAL_FEEDBACK
|
||||
typedef struct{
|
||||
uint16_t start;
|
||||
int16_t cmd1;
|
||||
int16_t cmd2;
|
||||
int16_t speedR_meas;
|
||||
int16_t speedL_meas;
|
||||
int16_t batVoltage;
|
||||
int16_t boardTemp;
|
||||
uint16_t cmdLed;
|
||||
uint16_t checksum;
|
||||
} SerialFeedback;
|
||||
void usart_process_data(SerialFeedback *Feedback_in, SerialFeedback *Feedback_out);
|
||||
#endif
|
||||
|
||||
/* i2c write/read functions */
|
||||
int8_t i2c_writeBytes(uint8_t slaveAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
|
||||
int8_t i2c_writeByte (uint8_t slaveAddr, uint8_t regAddr, uint8_t data);
|
||||
|
@ -17,7 +17,7 @@ The original sideboard hardware supports one 4-pin cable that originally was con
|
||||
The LED boards consist of colored LEDs (blue, red, green, orange) used for design and to inform the user about the current hoverboard state. Below the pinout of the LED boards is shown.
|
||||

|
||||
|
||||
The heart of the sideboard is a [GD32F130C6T6](/docs/GD32F130xx-Datasheet_Rev3.3.pdf) with the pinout shown in the follwing figure:
|
||||
The sideboard brain is a [GD32F130C6T6](/docs/GD32F130xx-Datasheet_Rev3.3.pdf) with the pinout shown in the follwing figure:
|
||||

|
||||
|
||||
A very important component of the sideboard is the IMU [MPU-6050](https://www.invensense.com/products/motion-tracking/6-axis/mpu-6050/) from Invensense. The [MPU-6050](https://www.invensense.com/products/motion-tracking/6-axis/mpu-6050/) determines the board orientation by combining a 3-axis gyroscope and a 3-axis accelerometer on the same silicon die, together with an onboard Digital Motion Processor™ (DMP™), which processes complex 6-axis MotionFusion algorithms. The DMP™ offers many features, such as:
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "systick.h"
|
||||
#include "i2c_it.h"
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
|
||||
/*!
|
||||
\brief this function handles NMI exception
|
||||
@ -121,6 +122,20 @@ void SysTick_Handler(void)
|
||||
delay_decrement();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function handles the USART1 interrupt request
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void USART1_IRQHandler(void)
|
||||
{
|
||||
if(RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_IDLE)) { // Check for IDLE line interrupt
|
||||
usart_flag_clear(USART1, USART_FLAG_IDLE); // Clear IDLE line flag (otherwise it will continue to enter interrupt)
|
||||
usart_rx_check(); // Check for data to process
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief this function handles I2C0 event interrupt request exception
|
||||
\param[in] none
|
||||
|
133
Src/main.c
133
Src/main.c
@ -30,76 +30,33 @@
|
||||
#include "mpu6050_dmp.h"
|
||||
|
||||
#ifdef SERIAL_CONTROL
|
||||
typedef struct{
|
||||
uint16_t start;
|
||||
int16_t roll;
|
||||
int16_t pitch;
|
||||
int16_t yaw;
|
||||
uint16_t sensors;
|
||||
uint16_t checksum;
|
||||
} SerialSideboard;
|
||||
SerialSideboard Sideboard;
|
||||
extern SerialSideboard Sideboard;
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_FEEDBACK
|
||||
typedef struct{
|
||||
uint16_t start;
|
||||
int16_t cmd1;
|
||||
int16_t cmd2;
|
||||
int16_t speedR_meas;
|
||||
int16_t speedL_meas;
|
||||
int16_t batVoltage;
|
||||
int16_t boardTemp;
|
||||
uint16_t cmdLed;
|
||||
uint16_t checksum;
|
||||
} SerialFeedback;
|
||||
SerialFeedback Feedback;
|
||||
SerialFeedback NewFeedback;
|
||||
|
||||
static int16_t timeoutCntSerial = 0; // Timeout counter for Rx Serial command
|
||||
static uint8_t timeoutFlagSerial = 0; // Timeout Flag for Rx Serial command: 0 = OK, 1 = Problem detected (line disconnected or wrong Rx data)
|
||||
extern SerialFeedback Feedback;
|
||||
extern uint16_t timeoutCntSerial; // Timeout counter for Rx Serial command
|
||||
extern uint8_t timeoutFlagSerial; // Timeout Flag for Rx Serial command: 0 = OK, 1 = Problem detected (line disconnected or wrong Rx data)
|
||||
#endif
|
||||
|
||||
extern MPU_Data mpu; // holds the MPU-6050 data
|
||||
ErrStatus mpuStatus; // holds the MPU-6050 status: SUCCESS or ERROR
|
||||
extern MPU_Data mpu; // holds the MPU-6050 data
|
||||
extern ErrStatus mpuStatus; // holds the MPU-6050 status: SUCCESS or ERROR
|
||||
|
||||
uint8_t userCommand; // holds the user command input
|
||||
FlagStatus sensor1, sensor2; // holds the sensor1 and sensor 2 values
|
||||
FlagStatus sensor1_read, sensor2_read; // holds the instantaneous Read for sensor1 and sensor 2
|
||||
FlagStatus sensor1, sensor2; // holds the sensor1 and sensor 2 values
|
||||
FlagStatus sensor1_read, sensor2_read; // holds the instantaneous Read for sensor1 and sensor 2
|
||||
|
||||
static uint32_t main_loop_counter; // main loop counter to perform task squeduling inside main()
|
||||
static uint32_t main_loop_counter; // main loop counter to perform task squeduling inside main()
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
systick_config(); // SysTick config
|
||||
gpio_config(); // GPIO config
|
||||
usart_config(USART_MAIN, USART_MAIN_BAUD); // USART config
|
||||
gpio_config(); // GPIO config
|
||||
usart_nvic_config(); // USART interrupt configuration
|
||||
usart_config(USART_MAIN, USART_MAIN_BAUD); // USART config
|
||||
i2c_config(); // I2C config
|
||||
i2c_nvic_config(); // NVIC peripheral config
|
||||
|
||||
#ifdef SERIAL_CONTROL
|
||||
usart_Tx_DMA_config(USART_MAIN, (uint8_t *)&Sideboard, sizeof(Sideboard));
|
||||
#endif
|
||||
#ifdef SERIAL_FEEDBACK
|
||||
usart_Rx_DMA_config(USART_MAIN, (uint8_t *)&NewFeedback, sizeof(NewFeedback));
|
||||
#endif
|
||||
|
||||
intro_demo_led(100); // Short LEDs intro demo with 100 ms delay. This also gives some time for the MPU-6050 to power-up.
|
||||
|
||||
#ifdef MPU_SENSOR_ENABLE
|
||||
if(mpu_config()) { // IMU MPU-6050 config
|
||||
mpuStatus = ERROR;
|
||||
gpio_bit_set(LED1_GPIO_Port, LED1_Pin); // Turn on RED LED
|
||||
}
|
||||
else {
|
||||
mpuStatus = SUCCESS;
|
||||
gpio_bit_set(LED2_GPIO_Port, LED2_Pin); // Turn on GREEN LED
|
||||
}
|
||||
mpu_handle_input('h'); // Print the User Help commands to serial
|
||||
#else
|
||||
gpio_bit_set(LED2_GPIO_Port, LED2_Pin); // Turn on GREEN LED
|
||||
#endif
|
||||
i2c_nvic_config(); // I2C interrupt configuration
|
||||
input_init(); // Input initialization
|
||||
|
||||
while(1) {
|
||||
|
||||
@ -116,22 +73,9 @@ int main(void)
|
||||
if (Feedback.cmdLed & LED5_SET) { gpio_bit_set(LED5_GPIO_Port, LED5_Pin); } else { gpio_bit_reset(LED5_GPIO_Port, LED5_Pin); }
|
||||
if (Feedback.cmdLed & LED4_SET) { gpio_bit_set(AUX3_GPIO_Port, AUX3_Pin); } else { gpio_bit_reset(AUX3_GPIO_Port, AUX3_Pin); }
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// ==================================== USER Handling ====================================
|
||||
#if defined(MPU_SENSOR_ENABLE) && defined(SERIAL_DEBUG)
|
||||
// Get the user Input as one character from Serial
|
||||
if(SET == usart_flag_get(USART_MAIN, USART_FLAG_RBNE)) { // Check if Read Buffer Not Empty meanind Serial data is available
|
||||
userCommand = usart_data_receive(USART_MAIN);
|
||||
if (userCommand != 10 && userCommand != 13) { // Do not accept 'new line' (ascii 10) and 'carriage return' (ascii 13) commands
|
||||
log_i("Command = %c\n", userCommand);
|
||||
mpu_handle_input(userCommand);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// ==================================== MPU-6050 Handling ====================================
|
||||
#ifdef MPU_SENSOR_ENABLE
|
||||
// Get MPU data. Because the MPU-6050 interrupt pin is not wired we have to check DMP data by pooling periodically
|
||||
@ -152,26 +96,28 @@ int main(void)
|
||||
|
||||
// SENSOR1
|
||||
if (sensor1 == RESET && sensor1_read == SET) {
|
||||
sensor1 = SET;
|
||||
// Sensor ACTIVE: Do something here (one time task on activation)
|
||||
sensor1 = SET;
|
||||
gpio_bit_set(LED4_GPIO_Port, LED4_Pin);
|
||||
consoleLog("-- SENSOR 1 Active --\n");
|
||||
consoleLog("-- SENSOR 1 Active --\n");
|
||||
} else if(sensor1 == SET && sensor1_read == RESET) {
|
||||
// Sensor DEACTIVE: Do something here (one time task on deactivation)
|
||||
sensor1 = RESET;
|
||||
gpio_bit_reset(LED4_GPIO_Port, LED4_Pin);
|
||||
consoleLog("-- SENSOR 1 Deactive --\n");
|
||||
consoleLog("-- SENSOR 1 Deactive --\n");
|
||||
}
|
||||
|
||||
// SENSOR2
|
||||
if (sensor2 == RESET && sensor2_read == SET) {
|
||||
sensor2 = SET;
|
||||
// Sensor ACTIVE: Do something here (one time task on activation)
|
||||
sensor2 = SET;
|
||||
gpio_bit_set(LED5_GPIO_Port, LED5_Pin);
|
||||
consoleLog("-- SENSOR 2 Active --\n");
|
||||
consoleLog("-- SENSOR 2 Active --\n");
|
||||
} else if (sensor2 == SET && sensor2_read == RESET) {
|
||||
// Sensor DEACTIVE: Do something here (one time task on deactivation)
|
||||
sensor2 = RESET;
|
||||
gpio_bit_reset(LED5_GPIO_Port, LED5_Pin);
|
||||
consoleLog("-- SENSOR 2 Deactive --\n");
|
||||
consoleLog("-- SENSOR 2 Deactive --\n");
|
||||
}
|
||||
|
||||
if (sensor1 == SET) {
|
||||
@ -181,10 +127,11 @@ int main(void)
|
||||
// Sensor ACTIVE: Do something here (continuous task)
|
||||
}
|
||||
|
||||
|
||||
// ==================================== SERIAL Tx/Rx Handling ====================================
|
||||
#ifdef SERIAL_CONTROL
|
||||
// To transmit on USART
|
||||
if (main_loop_counter % 5 == 0 && SET == dma_flag_get(DMA_CH3, DMA_FLAG_FTF)) { // check if DMA channel transfer complete (Full Transfer Finish flag == 1)
|
||||
if (main_loop_counter % 5 == 0 && dma_transfer_number_get(DMA_CH3) == 0) { // Check if DMA channel counter is 0 (meaning all data has been transferred)
|
||||
Sideboard.start = (uint16_t)SERIAL_START_FRAME;
|
||||
Sideboard.roll = (int16_t)mpu.euler.roll;
|
||||
Sideboard.pitch = (int16_t)mpu.euler.pitch;
|
||||
@ -200,33 +147,13 @@ int main(void)
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_FEEDBACK
|
||||
uint16_t checksum;
|
||||
checksum = (uint16_t)(NewFeedback.start ^ NewFeedback.cmd1 ^ NewFeedback.cmd2 ^ NewFeedback.speedR_meas ^ NewFeedback.speedL_meas
|
||||
^ NewFeedback.batVoltage ^ NewFeedback.boardTemp ^ NewFeedback.cmdLed);
|
||||
if (NewFeedback.start == SERIAL_START_FRAME && NewFeedback.checksum == checksum) {
|
||||
if (timeoutFlagSerial) { // Check for previous timeout flag
|
||||
if (timeoutCntSerial-- <= 0) // Timeout de-qualification
|
||||
timeoutFlagSerial = 0; // Timeout flag cleared
|
||||
} else {
|
||||
memcpy(&Feedback, &NewFeedback, sizeof(Feedback)); // Copy the new data
|
||||
NewFeedback.start = 0xFFFF; // Change the Start Frame for timeout detection in the next cycle
|
||||
timeoutCntSerial = 0; // Reset the timeout counter
|
||||
}
|
||||
} else {
|
||||
if (timeoutCntSerial++ >= SERIAL_TIMEOUT) { // Timeout qualification
|
||||
timeoutFlagSerial = 1; // Timeout detected
|
||||
timeoutCntSerial = SERIAL_TIMEOUT; // Limit timout counter value
|
||||
}
|
||||
// Most probably we are out-of-sync. Try to re-sync by reseting the DMA
|
||||
if (NewFeedback.start != SERIAL_START_FRAME && NewFeedback.start != 0xFFFF && main_loop_counter % 5 == 0) {
|
||||
dma_channel_disable(DMA_CH4);
|
||||
usart_Rx_DMA_config(USART_MAIN, (uint8_t *)&NewFeedback, sizeof(NewFeedback));
|
||||
}
|
||||
if (timeoutCntSerial++ >= SERIAL_TIMEOUT) { // Timeout qualification
|
||||
timeoutFlagSerial = 1; // Timeout detected
|
||||
timeoutCntSerial = SERIAL_TIMEOUT; // Limit timout counter value
|
||||
}
|
||||
|
||||
if (timeoutFlagSerial && main_loop_counter % 100 == 0) { // In case of timeout bring the system to a Safe State and indicate error if desired
|
||||
toggle_led(LED3_GPIO_Port, LED3_Pin); // Toggle the Yellow LED every 100 ms
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
main_loop_counter++;
|
||||
|
@ -3714,10 +3714,11 @@ void mpu_android_orient_func(unsigned char orientation)
|
||||
/* =========================== User Input Handling =========================== */
|
||||
void mpu_handle_input(char c)
|
||||
{
|
||||
#ifdef SERIAL_DEBUG
|
||||
switch (c) {
|
||||
/* This command prints the Help text. */
|
||||
case 'h':
|
||||
consoleLog("=================== HELP COMMANDS ===================\n");
|
||||
consoleLog("====== HELP COMMANDS ======\n");
|
||||
consoleLog("h: Print Help commands\n");
|
||||
consoleLog("8: Set Accelerometer sensor on/off\n");
|
||||
consoleLog("9: Set Gyroscope sensor on/off\n");
|
||||
@ -3730,17 +3731,15 @@ void mpu_handle_input(char c)
|
||||
consoleLog("p: Print Pedometer data\n");
|
||||
consoleLog("0: Reset Pedometer\n");
|
||||
consoleLog("1: Set DMP/MPU frequency 10 Hz\n");
|
||||
consoleLog("2: Set DMP/MPU frequency 20 Hz\n");
|
||||
consoleLog("3: Set DMP/MPU frequency 40 Hz\n");
|
||||
consoleLog("4: Set DMP/MPU frequency 50 Hz\n");
|
||||
consoleLog("5: Set DMP/MPU frequency 100 Hz\n");
|
||||
consoleLog("2: Set DMP/MPU frequency 50 Hz\n");
|
||||
consoleLog("3: Set DMP/MPU frequency 100 Hz\n");
|
||||
consoleLog(",: Set DMP interrupt to gesture event only\n");
|
||||
consoleLog(".: Set DMP interrupt to continuous\n");
|
||||
consoleLog("f: Set DMP on/off\n");
|
||||
consoleLog("v: Set Quaternion on/off\n");
|
||||
consoleLog("w: Test out low-power accel mode\n");
|
||||
consoleLog("w: Test low-power accel mode\n");
|
||||
consoleLog("s: Run self-test (device must be facing up or down)\n");
|
||||
consoleLog("=====================================================\n");
|
||||
consoleLog("===========================\n");
|
||||
break;
|
||||
|
||||
/* These commands turn off individual sensors. */
|
||||
@ -3793,33 +3792,21 @@ void mpu_handle_input(char c)
|
||||
*/
|
||||
case '1':
|
||||
if (hal.dmp_on) {
|
||||
if (0 == dmp_set_fifo_rate(10)) {consoleLog("DMP set to 10 Hz.\n");}
|
||||
if (0 == dmp_set_fifo_rate(10)) {consoleLog("DMP: 10 Hz\n");}
|
||||
} else
|
||||
if (0 == mpu_set_sample_rate(10)) {consoleLog("MPU set to 10 Hz.\n");}
|
||||
if (0 == mpu_set_sample_rate(10)) {consoleLog("MPU: 10 Hz\n");}
|
||||
break;
|
||||
case '2':
|
||||
if (hal.dmp_on) {
|
||||
if (0 == dmp_set_fifo_rate(20)) {consoleLog("DMP set to 20 Hz.\n");}
|
||||
if (0 == dmp_set_fifo_rate(50)) {consoleLog("DMP: 50 Hz\n");}
|
||||
} else
|
||||
if (0 == mpu_set_sample_rate(20)) {consoleLog("MPU set to 20 Hz.\n");}
|
||||
if (0 == mpu_set_sample_rate(50)) {consoleLog("MPU: 50 Hz\n");}
|
||||
break;
|
||||
case '3':
|
||||
if (hal.dmp_on) {
|
||||
if (0 == dmp_set_fifo_rate(40)) {consoleLog("DMP set to 40 Hz.\n");}
|
||||
if (0 == dmp_set_fifo_rate(100)) {consoleLog("DMP: 100 Hz\n");}
|
||||
} else
|
||||
if (0 == mpu_set_sample_rate(40)) {consoleLog("MPU set to 40 Hz.\n");}
|
||||
break;
|
||||
case '4':
|
||||
if (hal.dmp_on) {
|
||||
if (0 == dmp_set_fifo_rate(50)) {consoleLog("DMP set to 50 Hz.\n");}
|
||||
} else
|
||||
if (0 == mpu_set_sample_rate(50)) {consoleLog("MPU set to 50 Hz.\n");}
|
||||
break;
|
||||
case '5':
|
||||
if (hal.dmp_on) {
|
||||
if (0 == dmp_set_fifo_rate(100)) {consoleLog("DMP set to 100 Hz.\n");}
|
||||
} else
|
||||
if (0 == mpu_set_sample_rate(100)) {consoleLog("MPU set to 100 Hz.\n");}
|
||||
if (0 == mpu_set_sample_rate(100)) {consoleLog("MPU: 100 Hz\n");}
|
||||
break;
|
||||
|
||||
/* Set hardware to interrupt on gesture event only. This feature is
|
||||
@ -3918,7 +3905,7 @@ void mpu_handle_input(char c)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#endif // SERIAL_DEBUG
|
||||
}
|
||||
|
||||
|
||||
|
37
Src/setup.c
37
Src/setup.c
@ -26,7 +26,7 @@
|
||||
#include "util.h"
|
||||
|
||||
// Global variables
|
||||
extern volatile ErrStatus status;
|
||||
extern volatile ErrStatus status;
|
||||
|
||||
// Private variables
|
||||
static rcu_periph_enum USART_CLK[USARTn] = { USART_AUX_CLK,
|
||||
@ -179,7 +179,12 @@ void usart_config(uint32_t selUSART, uint32_t selBaudRate) {
|
||||
usart_baudrate_set(selUSART, selBaudRate);
|
||||
usart_transmit_config(selUSART, USART_TRANSMIT_ENABLE);
|
||||
usart_receive_config(selUSART, USART_RECEIVE_ENABLE);
|
||||
usart_oversample_config(selUSART, USART_OVSMOD_16); // oversampling: {USART_OVSMOD_8, USART_OVSMOD_16}
|
||||
usart_sample_bit_config(selUSART, USART_OSB_3BIT); // sample bit: {USART_OSB_1BIT, USART_OSB_3BIT }
|
||||
usart_enable(selUSART);
|
||||
|
||||
/* enable the USART IDLE line detection interrupt */
|
||||
usart_interrupt_enable(selUSART, USART_INT_IDLE);
|
||||
|
||||
}
|
||||
|
||||
@ -188,7 +193,7 @@ void usart_config(uint32_t selUSART, uint32_t selBaudRate) {
|
||||
// DMA_CH3 = USART1_TX
|
||||
// DMA_CH4 = USART1_RX
|
||||
|
||||
void usart_Tx_DMA_config(uint32_t selUSART, uint8_t *pData, uint32_t Size) {
|
||||
void usart_Tx_DMA_config(uint32_t selUSART, uint8_t *pData, uint32_t dSize) {
|
||||
|
||||
dma_parameter_struct dma_init_struct;
|
||||
|
||||
@ -203,7 +208,7 @@ void usart_Tx_DMA_config(uint32_t selUSART, uint8_t *pData, uint32_t Size) {
|
||||
dma_init_struct.memory_addr = (uint32_t)pData;
|
||||
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
|
||||
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
|
||||
dma_init_struct.number = Size;
|
||||
dma_init_struct.number = dSize;
|
||||
dma_init_struct.periph_addr = USART1_TDATA_ADDRESS;
|
||||
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
|
||||
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
|
||||
@ -214,30 +219,33 @@ void usart_Tx_DMA_config(uint32_t selUSART, uint8_t *pData, uint32_t Size) {
|
||||
dma_circulation_disable(DMA_CH3);
|
||||
dma_memory_to_memory_disable(DMA_CH3);
|
||||
|
||||
/* USART DMA enable for transmission */
|
||||
usart_dma_transmit_config(selUSART, USART_DENT_ENABLE);
|
||||
|
||||
/* enable DMA channel1 */
|
||||
dma_channel_enable(DMA_CH3);
|
||||
|
||||
/* USART DMA enable for transmission and reception */
|
||||
usart_dma_transmit_config(selUSART, USART_DENT_ENABLE);
|
||||
|
||||
/* wait DMA channel transfer complete */
|
||||
// while (RESET == dma_flag_get(DMA_CH3, DMA_FLAG_FTF));
|
||||
|
||||
}
|
||||
|
||||
void usart_Rx_DMA_config(uint32_t selUSART, uint8_t *pData, uint32_t Size) {
|
||||
void usart_Rx_DMA_config(uint32_t selUSART, uint8_t *pData, uint32_t dSize) {
|
||||
|
||||
dma_parameter_struct dma_init_struct;
|
||||
|
||||
// --------------------------- RX Channel ---------------------------
|
||||
|
||||
/* enable DMA clock */
|
||||
rcu_periph_clock_enable(RCU_DMA);
|
||||
|
||||
/* deinitialize DMA channel4 */
|
||||
dma_deinit(DMA_CH4);
|
||||
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
|
||||
dma_init_struct.memory_addr = (uint32_t)pData;
|
||||
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
|
||||
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
|
||||
dma_init_struct.number = Size;
|
||||
dma_init_struct.number = dSize;
|
||||
dma_init_struct.periph_addr = USART1_RDATA_ADDRESS;
|
||||
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
|
||||
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
|
||||
@ -248,9 +256,12 @@ void usart_Rx_DMA_config(uint32_t selUSART, uint8_t *pData, uint32_t Size) {
|
||||
dma_circulation_enable(DMA_CH4); // dma_circulation_disable(DMA_CH4);
|
||||
dma_memory_to_memory_disable(DMA_CH4);
|
||||
|
||||
dma_channel_enable(DMA_CH4);
|
||||
/* USART DMA enable for reception */
|
||||
usart_dma_receive_config(selUSART, USART_DENR_ENABLE);
|
||||
|
||||
|
||||
/* enable DMA channel */
|
||||
dma_channel_enable(DMA_CH4);
|
||||
|
||||
/* wait DMA channel transfer complete */
|
||||
// while (RESET == dma_flag_get(DMA_CH4, DMA_FLAG_FTF));
|
||||
|
||||
@ -284,6 +295,12 @@ void i2c_config(void) {
|
||||
}
|
||||
|
||||
|
||||
void usart_nvic_config(void)
|
||||
{
|
||||
nvic_irq_enable(USART1_IRQn, 0, 1);
|
||||
}
|
||||
|
||||
|
||||
void i2c_nvic_config(void)
|
||||
{
|
||||
/* configure the NVIC peripheral */
|
||||
|
140
Src/util.c
140
Src/util.c
@ -19,12 +19,35 @@
|
||||
|
||||
// Includes
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "systick.h"
|
||||
#include "gd32f1x0.h"
|
||||
#include "defines.h"
|
||||
#include "config.h"
|
||||
#include "setup.h"
|
||||
#include "util.h"
|
||||
#include "mpu6050.h"
|
||||
|
||||
// USART variables
|
||||
#ifdef SERIAL_CONTROL
|
||||
SerialSideboard Sideboard;
|
||||
#endif
|
||||
|
||||
#if defined(SERIAL_DEBUG) || defined(SERIAL_FEEDBACK)
|
||||
static uint8_t rx_buffer[SERIAL_BUFFER_SIZE]; // USART Rx DMA circular buffer
|
||||
static uint32_t rx_buffer_len = ARRAY_LEN(rx_buffer);
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_FEEDBACK
|
||||
SerialFeedback Feedback;
|
||||
SerialFeedback FeedbackRaw;
|
||||
uint16_t timeoutCntSerial = 0; // Timeout counter for Rx Serial command
|
||||
uint8_t timeoutFlagSerial = 0; // Timeout Flag for Rx Serial command: 0 = OK, 1 = Problem detected (line disconnected or wrong Rx data)
|
||||
static uint32_t Feedback_len = sizeof(Feedback);
|
||||
#endif
|
||||
|
||||
// MPU variables
|
||||
ErrStatus mpuStatus; // holds the MPU-6050 status: SUCCESS or ERROR
|
||||
|
||||
// MAIN I2C variables
|
||||
volatile int8_t i2c_status;
|
||||
@ -120,6 +143,123 @@ void intro_demo_led(uint32_t tDelay)
|
||||
|
||||
}
|
||||
|
||||
/* =========================== Input Initialization Function =========================== */
|
||||
void input_init(void) {
|
||||
#ifdef SERIAL_CONTROL
|
||||
usart_Tx_DMA_config(USART_MAIN, (uint8_t *)&Sideboard, sizeof(Sideboard));
|
||||
#endif
|
||||
#if defined(SERIAL_DEBUG) || defined(SERIAL_FEEDBACK)
|
||||
usart_Rx_DMA_config(USART_MAIN, (uint8_t *)rx_buffer, sizeof(rx_buffer));
|
||||
#endif
|
||||
|
||||
intro_demo_led(100); // Short LEDs intro demo with 100 ms delay. This also gives some time for the MPU-6050 to power-up.
|
||||
|
||||
#ifdef MPU_SENSOR_ENABLE
|
||||
if(mpu_config()) { // IMU MPU-6050 config
|
||||
mpuStatus = ERROR;
|
||||
gpio_bit_set(LED1_GPIO_Port, LED1_Pin); // Turn on RED LED
|
||||
}
|
||||
else {
|
||||
mpuStatus = SUCCESS;
|
||||
gpio_bit_set(LED2_GPIO_Port, LED2_Pin); // Turn on GREEN LED
|
||||
}
|
||||
mpu_handle_input('h'); // Print the User Help commands to serial
|
||||
#else
|
||||
gpio_bit_set(LED2_GPIO_Port, LED2_Pin); // Turn on GREEN LED
|
||||
#endif
|
||||
}
|
||||
|
||||
/* =========================== USART READ Functions =========================== */
|
||||
|
||||
/*
|
||||
* Check for new data received on USART with DMA: refactored function from https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx
|
||||
* - this function is called for every USART IDLE line detection, in the USART interrupt handler
|
||||
*/
|
||||
void usart_rx_check(void)
|
||||
{
|
||||
#ifdef SERIAL_DEBUG
|
||||
static uint32_t old_pos;
|
||||
uint32_t pos;
|
||||
|
||||
pos = rx_buffer_len - dma_transfer_number_get(DMA_CH4); // Calculate current position in buffer
|
||||
if (pos != old_pos) { // Check change in received data
|
||||
if (pos > old_pos) { // "Linear" buffer mode: check if current position is over previous one
|
||||
usart_process_debug(&rx_buffer[old_pos], pos - old_pos); // Process data
|
||||
} else { // "Overflow" buffer mode
|
||||
usart_process_debug(&rx_buffer[old_pos], rx_buffer_len - old_pos); // First Process data from the end of buffer
|
||||
if (pos > 0) { // Check and continue with beginning of buffer
|
||||
usart_process_debug(&rx_buffer[0], pos); // Process remaining data
|
||||
}
|
||||
}
|
||||
}
|
||||
old_pos = pos; // Update old position
|
||||
if (old_pos == rx_buffer_len) { // Check and manually update if we reached end of buffer
|
||||
old_pos = 0;
|
||||
}
|
||||
#endif // SERIAL_DEBUG
|
||||
|
||||
#ifdef SERIAL_FEEDBACK
|
||||
static uint32_t old_pos;
|
||||
uint32_t pos;
|
||||
uint8_t *ptr;
|
||||
|
||||
pos = rx_buffer_len - dma_transfer_number_get(DMA_CH4); // Calculate current position in buffer
|
||||
if (pos != old_pos) { // Check change in received data
|
||||
ptr = (uint8_t *)&FeedbackRaw; // Initialize the pointer with FeedbackRaw address
|
||||
if (pos > old_pos && (pos - old_pos) == Feedback_len) { // "Linear" buffer mode: check if current position is over previous one AND data length equals expected length
|
||||
memcpy(ptr, &rx_buffer[old_pos], Feedback_len); // Copy data. This is possible only if FeedbackRaw is contiguous! (meaning all the structure members have the same size)
|
||||
usart_process_data(&FeedbackRaw, &Feedback); // Process data
|
||||
} else if ((rx_buffer_len - old_pos + pos) == Feedback_len) { // "Overflow" buffer mode: check if data length equals expected length
|
||||
memcpy(ptr, &rx_buffer[old_pos], rx_buffer_len - old_pos); // First copy data from the end of buffer
|
||||
if (pos > 0) { // Check and continue with beginning of buffer
|
||||
ptr += rx_buffer_len - old_pos; // Move to correct position in FeedbackRaw
|
||||
memcpy(ptr, &rx_buffer[0], pos); // Copy remaining data
|
||||
}
|
||||
usart_process_data(&FeedbackRaw, &Feedback); // Process data
|
||||
}
|
||||
}
|
||||
old_pos = pos; // Updated old position
|
||||
if (old_pos == rx_buffer_len) { // Check and manually update if we reached end of buffer
|
||||
old_pos = 0;
|
||||
}
|
||||
#endif // SERIAL_FEEDBACK
|
||||
}
|
||||
|
||||
/*
|
||||
* Process Rx debug user command input
|
||||
*/
|
||||
#ifdef SERIAL_DEBUG
|
||||
void usart_process_debug(uint8_t *userCommand, uint32_t len)
|
||||
{
|
||||
for (; len > 0; len--, userCommand++) {
|
||||
if (*userCommand != '\n' && *userCommand != '\r') { // Do not accept 'new line' and 'carriage return' commands
|
||||
log_i("Command = %c\n", *userCommand);
|
||||
mpu_handle_input(*userCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // SERIAL_DEBUG
|
||||
|
||||
/*
|
||||
* Process Rx data
|
||||
* - if the Feedback_in data is valid (correct START_FRAME and checksum) copy the Feedback_in to Feedback_out
|
||||
*/
|
||||
#ifdef SERIAL_FEEDBACK
|
||||
void usart_process_data(SerialFeedback *Feedback_in, SerialFeedback *Feedback_out)
|
||||
{
|
||||
uint16_t checksum;
|
||||
if (Feedback_in->start == SERIAL_START_FRAME) {
|
||||
checksum = (uint16_t)(Feedback_in->start ^ Feedback_in->cmd1 ^ Feedback_in->cmd2 ^ Feedback_in->speedR_meas ^ Feedback_in->speedL_meas
|
||||
^ Feedback_in->batVoltage ^ Feedback_in->boardTemp ^ Feedback_in->cmdLed);
|
||||
if (Feedback_in->checksum == checksum) {
|
||||
*Feedback_out = *Feedback_in;
|
||||
timeoutCntSerial = 0; // Reset timeout counter
|
||||
timeoutFlagSerial = 0; // Clear timeout flag
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // SERIAL_FEEDBACK
|
||||
|
||||
/* =========================== I2C WRITE Functions =========================== */
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user