Merge pull request #12 from Candas1/master

Add FLYSKY IBUS protocol for RC remotes
This commit is contained in:
EmanuelFeru 2020-01-09 08:38:13 +01:00 committed by GitHub
commit fb362f04a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 132 additions and 51 deletions

View File

@ -10,6 +10,7 @@
//#define VARIANT_USART3 // Variant for Serial control via USART3 input //#define VARIANT_USART3 // Variant for Serial control via USART3 input
//#define VARIANT_NUNCHUCK // Variant for Nunchuck controlled vehicle build //#define VARIANT_NUNCHUCK // Variant for Nunchuck controlled vehicle build
//#define VARIANT_PPM // Variant for RC-Remote with PPM-Sum Signal //#define VARIANT_PPM // Variant for RC-Remote with PPM-Sum Signal
//#define VARIANT_IBUS // Variant for RC-Remotes with FLYSKY IBUS
//#define VARIANT_HOVERCAR // Variant for HOVERCAR build //#define VARIANT_HOVERCAR // Variant for HOVERCAR build
//#define VARIANT_TRANSPOTTER // Variant for TRANSPOTTER build https://github.com/NiklasFauth/hoverboard-firmware-hack/wiki/Build-Instruction:-TranspOtter https://hackaday.io/project/161891-transpotter-ng //#define VARIANT_TRANSPOTTER // Variant for TRANSPOTTER build https://github.com/NiklasFauth/hoverboard-firmware-hack/wiki/Build-Instruction:-TranspOtter https://hackaday.io/project/161891-transpotter-ng
#endif #endif
@ -61,7 +62,7 @@
* Then you can verify voltage on value 6 (to get calibrated voltage multiplied by 100). * Then you can verify voltage on value 6 (to get calibrated voltage multiplied by 100).
*/ */
#define BAT_FILT_COEF 655 // battery voltage filter coefficient in fixed-point. coef_fixedPoint = coef_floatingPoint * 2^16. In this case 655 = 0.01 * 2^16 #define BAT_FILT_COEF 655 // battery voltage filter coefficient in fixed-point. coef_fixedPoint = coef_floatingPoint * 2^16. In this case 655 = 0.01 * 2^16
#define BAT_CALIB_REAL_VOLTAGE 3970 // input voltage measured by multimeter (multiplied by 100). In this case 43.00 V * 100 = 4300 #define BAT_CALIB_REAL_VOLTAGE 3970 // input voltage measured by multimeter (multiplied by 100). For example 43.00 V * 100 = 4300
#define BAT_CALIB_ADC 1492 // adc-value measured by mainboard (value nr 5 on UART debug output) #define BAT_CALIB_ADC 1492 // adc-value measured by mainboard (value nr 5 on UART debug output)
#define BAT_CELLS 10 // battery number of cells. Normal Hoverboard battery: 10s #define BAT_CELLS 10 // battery number of cells. Normal Hoverboard battery: 10s
@ -133,6 +134,21 @@
// #define DEBUG_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuck or lcd) is used! // #define DEBUG_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuck or lcd) is used!
#endif #endif
// ###### CONTROL VIA RC REMOTE WITH FLYSKY IBUS PROTOCOL ######
/* Connected to Left sensor board cable. Channel 1: steering, Channel 2: speed. */
#ifdef VARIANT_IBUS
#define CONTROL_IBUS // use IBUS as input
#define IBUS_NUM_CHANNELS 14 // total number of IBUS channels to receive, even if they are not used.
#define IBUS_LENGTH 0x20
#define IBUS_COMMAND 0x40
#undef USART2_BAUD
#define USART2_BAUD 115200
#define CONTROL_SERIAL_USART2 // left sensor board cable, disable if ADC or PPM is used!
#define FEEDBACK_SERIAL_USART2 // left sensor board cable, disable if ADC or PPM is used!
#endif
#if defined(FEEDBACK_SERIAL_USART2) || defined(DEBUG_SERIAL_USART2) #if defined(FEEDBACK_SERIAL_USART2) || defined(DEBUG_SERIAL_USART2)
#define UART_DMA_CHANNEL DMA1_Channel7 #define UART_DMA_CHANNEL DMA1_Channel7
#endif #endif
@ -141,12 +157,12 @@
#define UART_DMA_CHANNEL DMA1_Channel2 #define UART_DMA_CHANNEL DMA1_Channel2
#endif #endif
#ifdef VARIANT_PPM
// ###### CONTROL VIA RC REMOTE ###### // ###### CONTROL VIA RC REMOTE ######
// left sensor board cable. Channel 1: steering, Channel 2: speed. #ifdef VARIANT_PPM
#define CONTROL_PPM // use PPM-Sum as input. disable CONTROL_SERIAL_USART2! // left sensor board cable. Channel 1: steering, Channel 2: speed.
#define PPM_NUM_CHANNELS 6 // total number of PPM channels to receive, even if they are not used. #define CONTROL_PPM // use PPM-Sum as input. disable CONTROL_SERIAL_USART2!
#endif #define PPM_NUM_CHANNELS 6 // total number of PPM channels to receive, even if they are not used.
#endif
// ###### CONTROL VIA TWO POTENTIOMETERS ###### // ###### CONTROL VIA TWO POTENTIOMETERS ######
/* ADC-calibration to cover the full poti-range: /* ADC-calibration to cover the full poti-range:
@ -317,7 +333,7 @@
// ############################### VALIDATE SETTINGS ############################### // ############################### VALIDATE SETTINGS ###############################
#if !defined(VARIANT_ADC) && !defined(VARIANT_USART3) && !defined(VARIANT_HOVERCAR) && !defined(VARIANT_TRANSPOTTER) && !defined(VARIANT_NUNCHUCK) && !defined(VARIANT_PPM) #if !defined(VARIANT_ADC) && !defined(VARIANT_USART3) && !defined(VARIANT_HOVERCAR) && !defined(VARIANT_TRANSPOTTER) && !defined(VARIANT_NUNCHUCK) && !defined(VARIANT_PPM)&& !defined(VARIANT_IBUS)
#error Variant not defined! Please check platformio.ini or Inc/config.h for available variants. #error Variant not defined! Please check platformio.ini or Inc/config.h for available variants.
#endif #endif

View File

@ -156,10 +156,11 @@ Most robust way for input is to use the ADC and potis. It works well even on 1m
This firmware offers currently these variants (selectable in [platformio.ini](/platformio.ini) and / or [/Inc/config.h](/Inc/config.h)): This firmware offers currently these variants (selectable in [platformio.ini](/platformio.ini) and / or [/Inc/config.h](/Inc/config.h)):
- **VARIANT_ADC**: In this variant the motors are controlled by two potentiometers connected to the Left sensor cable (long wired) - **VARIANT_ADC**: In this variant the motors are controlled by two potentiometers connected to the Left sensor cable (long wired)
- **VARIANT_USART3**: In this variant the motors are controlled via serial protocol on USART3 right sensor cable (short wired). The commands can be sent from an Arduino. Check out the [hoverserial.ino](/02_Arduino/hoverserial) as an example sketch. - **VARIANT_USART3**: In this variant the motors are controlled via serial protocol on USART3 right sensor cable (short wired). The commands can be sent from an Arduino. Check out the [hoverserial.ino](/02_Arduino/hoverserial) as an example sketch.
- **VARIANT_NUNCHUCK**: Wii Nunchuck offers one hand control for throttle, braking and steering. This was one of the first input device used for electric armchairs or bottle crates.
- **VARIANT_PPM**: This is when you want to use a RC remote control with PPM Sum signal
- **VARIANT_IBUS**: This is when you want to use a RC remote control with Flysky IBUS protocol connected to the Left sensor cable.
- **VARIANT_HOVERCAR**: In this variant the motors are controlled by two pedals brake and throttle. Reverse is engaged by double tapping on the brake pedal at standstill. - **VARIANT_HOVERCAR**: In this variant the motors are controlled by two pedals brake and throttle. Reverse is engaged by double tapping on the brake pedal at standstill.
- **VARIANT_TRANSPOTTER**: This build is for transpotter which is a hoverboard based transportation system. For more details on how to build it check [here](https://github.com/NiklasFauth/hoverboard-firmware-hack/wiki/Build-Instruction:-TranspOtter) and [here](https://hackaday.io/project/161891-transpotter-ng). - **VARIANT_TRANSPOTTER**: This build is for transpotter which is a hoverboard based transportation system. For more details on how to build it check [here](https://github.com/NiklasFauth/hoverboard-firmware-hack/wiki/Build-Instruction:-TranspOtter) and [here](https://hackaday.io/project/161891-transpotter-ng).
- **VARIANT_NUNCHUCK**: Wii Nunchuck offers one hand control for throttle, braking and steering. This was one of the first input device used for electric armchairs or bottle crates.
- **VARIANT_PPM**: This is when you want to use a RC remote control with PPM Sum singnal
Of course the firmware can be further customized for other needs or projects. Of course the firmware can be further customized for other needs or projects.

View File

@ -112,8 +112,6 @@ void Nunchuck_Read(void) {
HAL_Delay(3); HAL_Delay(3);
if (HAL_I2C_Master_Receive(&hi2c2,0xA4,(uint8_t*)nunchuck_data, 6, 10) == HAL_OK) { if (HAL_I2C_Master_Receive(&hi2c2,0xA4,(uint8_t*)nunchuck_data, 6, 10) == HAL_OK) {
timeout = 0; timeout = 0;
} else {
timeout++;
} }
#ifndef TRANSPOTTER #ifndef TRANSPOTTER

View File

@ -106,12 +106,25 @@ static int16_t timeoutCntADC = 0; // Timeout counter for ADC Protection
static uint8_t timeoutFlagADC = 0; // Timeout Flag for for ADC Protection: 0 = OK, 1 = Problem detected (line disconnected or wrong ADC data) static uint8_t timeoutFlagADC = 0; // Timeout Flag for for ADC Protection: 0 = OK, 1 = Problem detected (line disconnected or wrong ADC data)
#if defined(CONTROL_SERIAL_USART2) || defined(CONTROL_SERIAL_USART3) #if defined(CONTROL_SERIAL_USART2) || defined(CONTROL_SERIAL_USART3)
typedef struct{ #ifdef CONTROL_IBUS
uint16_t start; static uint16_t ibus_chksum;
int16_t steer; static uint16_t ibus_captured_value[IBUS_NUM_CHANNELS];
int16_t speed;
uint16_t checksum; typedef struct{
} Serialcommand; uint8_t start;
uint8_t type;
uint8_t channels[IBUS_NUM_CHANNELS*2];
uint8_t checksuml;
uint8_t checksumh;
} Serialcommand;
#else
typedef struct{
uint16_t start;
int16_t steer;
int16_t speed;
uint16_t checksum;
} Serialcommand;
#endif
static volatile Serialcommand command; static volatile Serialcommand command;
static int16_t timeoutCntSerial = 0; // Timeout counter for Rx Serial command static int16_t timeoutCntSerial = 0; // Timeout counter for Rx Serial command
#endif #endif
@ -132,7 +145,6 @@ typedef struct{
} SerialFeedback; } SerialFeedback;
static SerialFeedback Feedback; static SerialFeedback Feedback;
#endif #endif
static uint8_t serialSendCnt; // serial send counter
#if defined(CONTROL_NUNCHUCK) || defined(SUPPORT_NUNCHUCK) || defined(CONTROL_PPM) || defined(CONTROL_ADC) #if defined(CONTROL_NUNCHUCK) || defined(SUPPORT_NUNCHUCK) || defined(CONTROL_PPM) || defined(CONTROL_ADC)
static uint8_t button1, button2; static uint8_t button1, button2;
@ -168,6 +180,7 @@ extern volatile uint32_t timeout; // global variable for timeout
extern int16_t batVoltage; // global variable for battery voltage extern int16_t batVoltage; // global variable for battery voltage
static uint32_t inactivity_timeout_counter; static uint32_t inactivity_timeout_counter;
static uint32_t main_loop_counter;
extern uint8_t nunchuck_data[6]; extern uint8_t nunchuck_data[6];
#ifdef CONTROL_PPM #ifdef CONTROL_PPM
@ -510,35 +523,65 @@ int main(void) {
#if defined CONTROL_SERIAL_USART2 || defined CONTROL_SERIAL_USART3 #if defined CONTROL_SERIAL_USART2 || defined CONTROL_SERIAL_USART3
// Handle received data validity, timeout and fix out-of-sync if necessary // Handle received data validity, timeout and fix out-of-sync if necessary
if (command.start == START_FRAME && command.checksum == (uint16_t)(command.start ^ command.steer ^ command.speed)) { #ifdef CONTROL_IBUS
if (timeoutFlagSerial) { // Check for previous timeout flag ibus_chksum = 0xFFFF - IBUS_LENGTH - IBUS_COMMAND;
if (timeoutCntSerial-- <= 0) // Timeout de-qualification for (uint8_t i = 0; i < (IBUS_NUM_CHANNELS * 2); i++) {
timeoutFlagSerial = 0; // Timeout flag cleared ibus_chksum -= command.channels[i];
}
if (command.start == IBUS_LENGTH && command.type == IBUS_COMMAND && ibus_chksum == (uint16_t)((command.checksumh << 8) + command.checksuml)) {
if (timeoutFlagSerial) { // Check for previous timeout flag
if (timeoutCntSerial-- <= 0) // Timeout de-qualification
timeoutFlagSerial = 0; // Timeout flag cleared
} else {
for (uint8_t i = 0; i < (IBUS_NUM_CHANNELS * 2); i+=2) {
ibus_captured_value[(i/2)] = CLAMP(command.channels[i] + (command.channels[i+1] << 8) - 1000, 0, INPUT_MAX); // 1000-2000 -> 0-1000
}
cmd1 = CLAMP((ibus_captured_value[0] - INPUT_MID) * 2, INPUT_MIN, INPUT_MAX);
cmd2 = CLAMP((ibus_captured_value[1] - INPUT_MID) * 2, INPUT_MIN, INPUT_MAX);
command.start = 0xFF; // Change the Start Frame for timeout detection in the next cycle
timeoutCntSerial = 0; // Reset the timeout counter
}
} else { } else {
cmd1 = CLAMP((int16_t)command.steer, INPUT_MIN, INPUT_MAX); if (timeoutCntSerial++ >= SERIAL_TIMEOUT) { // Timeout qualification
cmd2 = CLAMP((int16_t)command.speed, INPUT_MIN, INPUT_MAX); timeoutFlagSerial = 1; // Timeout detected
command.start = 0xFFFF; // Change the Start Frame for timeout detection in the next cycle timeoutCntSerial = SERIAL_TIMEOUT; // Limit timout counter value
timeoutCntSerial = 0; // Reset the timeout counter }
// Check periodically the received Start Frame. If it is NOT OK, most probably we are out-of-sync. Try to re-sync by reseting the DMA
if (main_loop_counter % 25 == 0 && command.start != IBUS_LENGTH && command.start != 0xFF) {
HAL_UART_DMAStop(&huart);
HAL_UART_Receive_DMA(&huart, (uint8_t *)&command, sizeof(command));
}
}
#else
if (command.start == START_FRAME && command.checksum == (uint16_t)(command.start ^ command.steer ^ command.speed)) {
if (timeoutFlagSerial) { // Check for previous timeout flag
if (timeoutCntSerial-- <= 0) // Timeout de-qualification
timeoutFlagSerial = 0; // Timeout flag cleared
} else {
cmd1 = CLAMP((int16_t)command.steer, INPUT_MIN, INPUT_MAX);
cmd2 = CLAMP((int16_t)command.speed, INPUT_MIN, INPUT_MAX);
command.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
}
// Check periodically the received Start Frame. If it is NOT OK, most probably we are out-of-sync. Try to re-sync by reseting the DMA
if (main_loop_counter % 25 == 0 && command.start != START_FRAME && command.start != 0xFFFF) {
HAL_UART_DMAStop(&huart);
HAL_UART_Receive_DMA(&huart, (uint8_t *)&command, sizeof(command));
}
} }
} else { #endif
if (timeoutCntSerial++ >= SERIAL_TIMEOUT) { // Timeout qualification
timeoutFlagSerial = 1; // Timeout detected
timeoutCntSerial = SERIAL_TIMEOUT; // Limit timout counter value
}
// Check the received Start Frame. If it is NOT OK, most probably we are out-of-sync.
// Try to re-sync by reseting the DMA
if (command.start != START_FRAME && command.start != 0xFFFF) {
HAL_UART_DMAStop(&huart);
HAL_UART_Receive_DMA(&huart, (uint8_t *)&command, sizeof(command));
}
}
if (timeoutFlagSerial) { // In case of timeout bring the system to a Safe State if (timeoutFlagSerial) { // In case of timeout bring the system to a Safe State
ctrlModReq = 0; // OPEN_MODE request. This will bring the motor power to 0 in a controlled way ctrlModReq = 0; // OPEN_MODE request. This will bring the motor power to 0 in a controlled way
cmd1 = 0; cmd1 = 0;
cmd2 = 0; cmd2 = 0;
} else { } else {
ctrlModReq = ctrlModReqRaw; // Follow the Mode request ctrlModReq = ctrlModReqRaw; // Follow the Mode request
} }
timeout = 0; timeout = 0;
@ -717,9 +760,7 @@ int main(void) {
board_temp_adcFilt = (int16_t)(board_temp_adcFixdt >> 20); // convert fixed-point to integer board_temp_adcFilt = (int16_t)(board_temp_adcFixdt >> 20); // convert fixed-point to integer
board_temp_deg_c = (TEMP_CAL_HIGH_DEG_C - TEMP_CAL_LOW_DEG_C) * (board_temp_adcFilt - TEMP_CAL_LOW_ADC) / (TEMP_CAL_HIGH_ADC - TEMP_CAL_LOW_ADC) + TEMP_CAL_LOW_DEG_C; board_temp_deg_c = (TEMP_CAL_HIGH_DEG_C - TEMP_CAL_LOW_DEG_C) * (board_temp_adcFilt - TEMP_CAL_LOW_ADC) / (TEMP_CAL_HIGH_ADC - TEMP_CAL_LOW_ADC) + TEMP_CAL_LOW_DEG_C;
serialSendCnt++; // Increment the counter if (main_loop_counter % 25 == 0) { // Send data periodically
if (serialSendCnt > 20) { // Send data every 100 ms = 20 * 5 ms, where 5 ms is approximately the main loop duration
serialSendCnt = 0; // Reset the counter
// ####### DEBUG SERIAL OUT ####### // ####### DEBUG SERIAL OUT #######
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3) #if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
@ -808,6 +849,9 @@ int main(void) {
if (inactivity_timeout_counter > (INACTIVITY_TIMEOUT * 60 * 1000) / (DELAY_IN_MAIN_LOOP + 1)) { // rest of main loop needs maybe 1ms if (inactivity_timeout_counter > (INACTIVITY_TIMEOUT * 60 * 1000) / (DELAY_IN_MAIN_LOOP + 1)) { // rest of main loop needs maybe 1ms
poweroff(); poweroff();
} }
main_loop_counter++;
timeout++;
} }
} }
@ -1011,4 +1055,4 @@ void SystemClock_Config(void) {
/* SysTick_IRQn interrupt configuration */ /* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0); HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
} }

View File

@ -13,6 +13,7 @@ src_dir = Src
;default_envs = VARIANT_USART3 ; Variant for Serial control via USART3 input ;default_envs = VARIANT_USART3 ; Variant for Serial control via USART3 input
;default_envs = VARIANT_NUNCHUCK ; Variant for Nunchuck controlled vehicle build ;default_envs = VARIANT_NUNCHUCK ; Variant for Nunchuck controlled vehicle build
;default_envs = VARIANT_PPM ; Variant for RC-Remotes with PPM-Sum signal ;default_envs = VARIANT_PPM ; Variant for RC-Remotes with PPM-Sum signal
;default_envs = VARIANT_IBUS ; Variant for RC-Remotes with FLYSKY IBUS
;default_envs = VARIANT_HOVERCAR ; Variant for HOVERCAR build ;default_envs = VARIANT_HOVERCAR ; Variant for HOVERCAR build
;default_envs = VARIANT_TRANSPOTTER ; Variant for TRANSPOTTER build https://github.com/NiklasFauth/hoverboard-firmware-hack/wiki/Build-Instruction:-TranspOtter https://hackaday.io/project/161891-transpotter-ng ;default_envs = VARIANT_TRANSPOTTER ; Variant for TRANSPOTTER build https://github.com/NiklasFauth/hoverboard-firmware-hack/wiki/Build-Instruction:-TranspOtter https://hackaday.io/project/161891-transpotter-ng
;================================================================ ;================================================================
@ -40,7 +41,7 @@ build_flags =
-g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization -g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization
# -Wl,-lnosys # -Wl,-lnosys
-D VARIANT_ADC -D VARIANT_ADC
-D PALTFORMIO -D PLATFORMIO
;================================================================ ;================================================================
@ -65,7 +66,7 @@ build_flags =
-g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization -g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization
# -Wl,-lnosys # -Wl,-lnosys
-D VARIANT_USART3 -D VARIANT_USART3
-D PALTFORMIO -D PLATFORMIO
;================================================================ ;================================================================
@ -86,7 +87,7 @@ build_flags =
-g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization -g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization
# -Wl,-lnosys # -Wl,-lnosys
-D VARIANT_NUNCHUCK -D VARIANT_NUNCHUCK
-D PALTFORMIO -D PLATFORMIO
;================================================================ ;================================================================
@ -107,7 +108,28 @@ build_flags =
-g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization -g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization
# -Wl,-lnosys # -Wl,-lnosys
-D VARIANT_PPM -D VARIANT_PPM
-D PALTFORMIO -D PLATFORMIO
;================================================================
[env:VARIANT_IBUS]
platform = ststm32
framework = stm32cube
board = genericSTM32F103RC
debug_tool = stlink
upload_protocol = stlink
build_flags =
-I${PROJECT_DIR}/inc/
-DUSE_HAL_DRIVER
-DSTM32F103xE
-Wl,-T./STM32F103RCTx_FLASH.ld
-Wl,-lc
-Wl,-lm
-g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization
# -Wl,-lnosys
-D VARIANT_IBUS
-D PLATFORMIO
;================================================================ ;================================================================
@ -132,7 +154,7 @@ build_flags =
-g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization -g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization
# -Wl,-lnosys # -Wl,-lnosys
-D VARIANT_HOVERCAR -D VARIANT_HOVERCAR
-D PALTFORMIO -D PLATFORMIO
;================================================================ ;================================================================
@ -153,6 +175,6 @@ build_flags =
-g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization -g -ggdb ; to generate correctly the 'firmware.elf' for STM STUDIO vizualization
# -Wl,-lnosys # -Wl,-lnosys
-D VARIANT_TRANSPOTTER -D VARIANT_TRANSPOTTER
-D PALTFORMIO -D PLATFORMIO
;================================================================ ;================================================================