Updated IBUS variant
- separated the implementation from USART implementation for more clarity - fixed warnings - minor visual updates
This commit is contained in:
parent
c3a40f6454
commit
d2c846cda9
13
Inc/config.h
13
Inc/config.h
|
@ -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
|
||||||
|
|
||||||
|
// ###### CONTROL VIA RC REMOTE WITH FLYSKY IBUS PROTOCOL ######
|
||||||
|
/* Connected to Left sensor board cable. Channel 1: steering, Channel 2: speed. */
|
||||||
#ifdef VARIANT_IBUS
|
#ifdef VARIANT_IBUS
|
||||||
// ###### CONTROL VIA RC REMOTE WITH FLYSKY IBUS PROTOCOL ######
|
|
||||||
// left sensor board cable. Channel 1: steering, Channel 2: speed.
|
|
||||||
#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
|
||||||
|
|
||||||
|
// ###### CONTROL VIA RC REMOTE ######
|
||||||
#ifdef VARIANT_PPM
|
#ifdef VARIANT_PPM
|
||||||
// ###### CONTROL VIA RC REMOTE ######
|
|
||||||
// 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.
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
47
Src/main.c
47
Src/main.c
|
@ -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
|
||||||
|
@ -525,27 +525,41 @@ int main(void) {
|
||||||
// Handle received data validity, timeout and fix out-of-sync if necessary
|
// Handle received data validity, timeout and fix out-of-sync if necessary
|
||||||
#ifdef CONTROL_IBUS
|
#ifdef CONTROL_IBUS
|
||||||
ibus_chksum = 0xFFFF - IBUS_LENGTH - IBUS_COMMAND;
|
ibus_chksum = 0xFFFF - IBUS_LENGTH - IBUS_COMMAND;
|
||||||
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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue