Updated IBUS variant

- separated the implementation from USART implementation for more clarity
- fixed warnings
- minor visual updates
This commit is contained in:
EmanuelFeru 2020-01-08 19:16:34 +01:00
parent c3a40f6454
commit d2c846cda9
4 changed files with 73 additions and 58 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,18 +134,18 @@
// #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
#ifdef VARIANT_IBUS
// ###### CONTROL VIA RC REMOTE WITH FLYSKY IBUS PROTOCOL ###### // ###### CONTROL VIA RC REMOTE WITH FLYSKY IBUS PROTOCOL ######
// left sensor board cable. Channel 1: steering, Channel 2: speed. /* Connected to Left sensor board cable. Channel 1: steering, Channel 2: speed. */
#ifdef VARIANT_IBUS
#define CONTROL_IBUS // use IBUS as input #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_NUM_CHANNELS 14 // total number of IBUS channels to receive, even if they are not used.
#define IBUS_LENGTH 0x20 #define IBUS_LENGTH 0x20
#define IBUS_COMMAND 0x40 #define IBUS_COMMAND 0x40
#define CONTROL_SERIAL_USART2 // left sensor board cable, disable if ADC or PPM is used! For Arduino control check the hoverSerial.ino
#define FEEDBACK_SERIAL_USART2 // left sensor board cable, disable if ADC or PPM is used!
#undef USART2_BAUD #undef USART2_BAUD
#define USART2_BAUD 115200 #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 #endif
@ -156,8 +157,8 @@
#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 ######
#ifdef VARIANT_PPM
// left sensor board cable. Channel 1: steering, Channel 2: speed. // left sensor board cable. Channel 1: steering, Channel 2: speed.
#define CONTROL_PPM // use PPM-Sum as input. disable CONTROL_SERIAL_USART2! #define CONTROL_PPM // use PPM-Sum as input. disable CONTROL_SERIAL_USART2!
#define PPM_NUM_CHANNELS 6 // total number of PPM channels to receive, even if they are not used. #define PPM_NUM_CHANNELS 6 // total number of PPM channels to receive, even if they are not used.

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

@ -145,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;
@ -181,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
@ -528,24 +528,38 @@ int main(void) {
for (uint8_t i = 0; i < (IBUS_NUM_CHANNELS * 2); i++) { for (uint8_t i = 0; i < (IBUS_NUM_CHANNELS * 2); i++) {
ibus_chksum -= command.channels[i]; ibus_chksum -= command.channels[i];
} }
if (command.start == IBUS_LENGTH && command.type == IBUS_COMMAND && ibus_chksum == ( command.checksumh << 8) + command.checksuml ) { if (command.start == IBUS_LENGTH && command.type == IBUS_COMMAND && ibus_chksum == (uint16_t)((command.checksumh << 8) + command.checksuml)) {
#else
if (command.start == START_FRAME && command.checksum == (uint16_t)(command.start ^ command.steer ^ command.speed)) {
#endif
if (timeoutFlagSerial) { // Check for previous timeout flag if (timeoutFlagSerial) { // Check for previous timeout flag
if (timeoutCntSerial-- <= 0) // Timeout de-qualification if (timeoutCntSerial-- <= 0) // Timeout de-qualification
timeoutFlagSerial = 0; // Timeout flag cleared timeoutFlagSerial = 0; // Timeout flag cleared
} else { } else {
#ifdef CONTROL_IBUS
for (uint8_t i = 0; i < (IBUS_NUM_CHANNELS * 2); i+=2) { 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 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); 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); 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 {
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 != IBUS_LENGTH && command.start != 0xFF) {
HAL_UART_DMAStop(&huart);
HAL_UART_Receive_DMA(&huart, (uint8_t *)&command, sizeof(command));
}
}
#else #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); cmd1 = CLAMP((int16_t)command.steer, INPUT_MIN, INPUT_MAX);
cmd2 = CLAMP((int16_t)command.speed, INPUT_MIN, INPUT_MAX); cmd2 = CLAMP((int16_t)command.speed, INPUT_MIN, INPUT_MAX);
#endif
command.start = 0xFFFF; // Change the Start Frame for timeout detection in the next cycle command.start = 0xFFFF; // Change the Start Frame for timeout detection in the next cycle
timeoutCntSerial = 0; // Reset the timeout counter timeoutCntSerial = 0; // Reset the timeout counter
} }
@ -554,13 +568,13 @@ int main(void) {
timeoutFlagSerial = 1; // Timeout detected timeoutFlagSerial = 1; // Timeout detected
timeoutCntSerial = SERIAL_TIMEOUT; // Limit timout counter value timeoutCntSerial = SERIAL_TIMEOUT; // Limit timout counter value
} }
// Check the received Start Frame. If it is NOT OK, most probably we are out-of-sync. // 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
// Try to re-sync by reseting the DMA if (main_loop_counter % 25 == 0 && command.start != START_FRAME && command.start != 0xFFFF) {
if (command.start != START_FRAME && command.start != 0xFFFF) {
HAL_UART_DMAStop(&huart); HAL_UART_DMAStop(&huart);
HAL_UART_Receive_DMA(&huart, (uint8_t *)&command, sizeof(command)); HAL_UART_Receive_DMA(&huart, (uint8_t *)&command, sizeof(command));
} }
} }
#endif
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
@ -746,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)
@ -837,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++;
} }
} }