forked from EFeru/hoverboard-firmware-hack-FOC
Compare commits
91 Commits
Author | SHA1 | Date | |
---|---|---|---|
efb438bf51 | |||
e5f7e9457a | |||
24b3d2515f | |||
a6430e3a3e | |||
5aa85d9af0 | |||
dbc485bbf4 | |||
4c0861e9de | |||
5505a71260 | |||
cb7f3e9183 | |||
87f9d4e8a3 | |||
6b2cf03ef1 | |||
4ef368330d | |||
873fc8ea14 | |||
4b16b64771 | |||
f18eec5ac1 | |||
7e6a65199c | |||
c7aa31b66c | |||
12cc722cef | |||
29535a26e6 | |||
31326ad158 | |||
ac489d51e6 | |||
2fbeb1fca4 | |||
5612af0a90 | |||
bb119d7a38 | |||
39a59e0870 | |||
bd4a34dabf | |||
b5c6fa0a67 | |||
0057cff9a1 | |||
3a5cd3331c | |||
be6ac57c76 | |||
baf4a1e691 | |||
faae9f9033 | |||
6a72b03c41 | |||
7c247cee4c | |||
22b1c76c97 | |||
2b0a4ea7de | |||
8cadd430c5 | |||
ae492d1e09 | |||
99f36738ce | |||
5001ed5563 | |||
4bd75c59ec | |||
453b048382 | |||
4cd8421fa4 | |||
77bf95771b | |||
9522c4b325 | |||
81c5a0dd44 | |||
dfb95cd522 | |||
785f64778a | |||
124f3d046a | |||
837fd02990 | |||
ac33240d20 | |||
e9eb7fa720 | |||
33eae7e24b | |||
eb784bcf3b | |||
34ec8d8e92 | |||
18d406982e | |||
08880f4823 | |||
88fd069c60 | |||
ef990ed5e7 | |||
f38e97d135 | |||
bcf3656e95 | |||
2f6d1f191f | |||
b02cded3b0 | |||
b3a3d904f2 | |||
9aa2dcf725 | |||
8ee426e335 | |||
7bb9a4b3f0 | |||
ff42d9787e | |||
4441847569 | |||
bf60799358 | |||
9d9501ad97 | |||
79bf9ef768 | |||
d97ec61c03 | |||
50704b3395 | |||
39b98cc0c0 | |||
4770b13b2c | |||
5470f0f63c | |||
ddadcb9d70 | |||
c71c102bc2 | |||
669d227898 | |||
b840051037 | |||
91f2d4c4d5 | |||
0504b10de5 | |||
f1139d1b66 | |||
5da9966f8c | |||
cf7b1d0de1 | |||
928a86b86b | |||
7d9d822342 | |||
ba2af41fa8 | |||
eb20cc0aca | |||
48c5474057 |
54
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
54
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
name: 🐞 Bug report
|
||||
description: Create a report to help us improve
|
||||
labels: "bug"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "**Please check the [Wiki](https://github.com/EFeru/hoverboard-firmware-hack-FOC/wiki), it contains tips for troubleshooting**"
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Variant
|
||||
description: What variant of the firmware are you using?
|
||||
multiple: false
|
||||
options:
|
||||
- ADC
|
||||
- USART
|
||||
- NUNCHUK
|
||||
- PPM
|
||||
- PWM
|
||||
- IBUS
|
||||
- HOVERCAR
|
||||
- TRANSPOTTER
|
||||
- SKATEBOARD
|
||||
- HOVERBOARD
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Control type
|
||||
description: What Control type are you using?
|
||||
multiple: false
|
||||
options:
|
||||
- Commutation
|
||||
- Sinusoidale
|
||||
- FOC
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Control mode
|
||||
description: What Control mode are you using?
|
||||
multiple: false
|
||||
options:
|
||||
- Voltage
|
||||
- Speed
|
||||
- Torque
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What is the bug and how to reproduce it ?
|
||||
placeholder: Describe the bug and how to reproduce it
|
||||
validations:
|
||||
required: true
|
9
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
9
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
blank_issues_enabled: false
|
||||
|
||||
contact_links:
|
||||
- name: ℹ️ Wiki Pages
|
||||
url: https://github.com/EFeru/hoverboard-firmware-hack-FOC/wiki
|
||||
about: Please check the Wiki first
|
||||
- name: 💬 Telegram Community
|
||||
url: https://t.me/joinchat/BHWO_RKu2LT5ZxEkvUB8uw
|
||||
about: Connect with the Telegram Community
|
60
.github/ISSUE_TEMPLATE/idea---feature-request.yaml
vendored
Normal file
60
.github/ISSUE_TEMPLATE/idea---feature-request.yaml
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
name: 🚀 Idea / Feature request
|
||||
description: Suggest an idea for this project
|
||||
labels: "enhancement"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "**Please check the [Wiki](https://github.com/EFeru/hoverboard-firmware-hack-FOC/wiki) for existing features**"
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Variant
|
||||
description: What variant of the firmware are you using?
|
||||
multiple: false
|
||||
options:
|
||||
- ADC
|
||||
- USART
|
||||
- NUNCHUK
|
||||
- PPM
|
||||
- PWM
|
||||
- IBUS
|
||||
- HOVERCAR
|
||||
- TRANSPOTTER
|
||||
- SKATEBOARD
|
||||
- HOVERBOARD
|
||||
validations:
|
||||
required: false
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Control type
|
||||
description: What Control type are you using?
|
||||
multiple: false
|
||||
options:
|
||||
- Commutation
|
||||
- Sinusoidale
|
||||
- FOC
|
||||
validations:
|
||||
required: false
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Control mode
|
||||
description: What Control mode are you using?
|
||||
multiple: false
|
||||
options:
|
||||
- Voltage
|
||||
- Speed
|
||||
- Torque
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What can we do to make the firmware better?
|
||||
placeholder: Consider if code examples or images would help communicate your request
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe suggestions or alternatives you have considered
|
||||
placeholder: A clear and concise description of any alternative solutions or features you've considered
|
||||
validations:
|
||||
required: true
|
54
.github/ISSUE_TEMPLATE/question-about-the-firmware.yaml
vendored
Normal file
54
.github/ISSUE_TEMPLATE/question-about-the-firmware.yaml
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
name: ❓ Question about the firmware
|
||||
description: How to use the firmware to...
|
||||
labels: "question"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: "**Please check the [Wiki](https://github.com/EFeru/hoverboard-firmware-hack-FOC/wiki), it might already contain an answer to your question**"
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Variant
|
||||
description: What variant of the firmware are you using?
|
||||
multiple: false
|
||||
options:
|
||||
- ADC
|
||||
- USART
|
||||
- NUNCHUK
|
||||
- PPM
|
||||
- PWM
|
||||
- IBUS
|
||||
- HOVERCAR
|
||||
- TRANSPOTTER
|
||||
- SKATEBOARD
|
||||
- HOVERBOARD
|
||||
validations:
|
||||
required: false
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Control type
|
||||
description: What Control type are you using?
|
||||
multiple: false
|
||||
options:
|
||||
- Commutation
|
||||
- Sinusoidale
|
||||
- FOC
|
||||
validations:
|
||||
required: false
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Control mode
|
||||
description: What Control mode are you using?
|
||||
multiple: false
|
||||
options:
|
||||
- Voltage
|
||||
- Speed
|
||||
- Torque
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
placeholder: If applicable, indicate what you tried that doesn't work
|
||||
validations:
|
||||
required: true
|
41
.github/workflows/build_on_commit.yml
vendored
Normal file
41
.github/workflows/build_on_commit.yml
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ '*' ]
|
||||
pull_request:
|
||||
branches: [ '*' ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# Get required packages
|
||||
- uses: actions/checkout@v2
|
||||
- uses: carlosperate/arm-none-eabi-gcc-action@v1
|
||||
with:
|
||||
release: '9-2019-q4'
|
||||
|
||||
# Build with make
|
||||
- name: make
|
||||
env:
|
||||
VARIANT: VARIANT_ADC
|
||||
run: make
|
||||
|
||||
# Build with Platformio
|
||||
- name: PlatformIO Install
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --upgrade platformio
|
||||
- name: PlatformIO Run
|
||||
run: pio run
|
||||
|
||||
- name: 'Upload Build Artifact'
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
path: ${{github.workspace}}/.pio/build/**
|
||||
name: ${{github.event.repository.name}}_build_${{github.run_number}}
|
||||
retention-days: 5
|
||||
|
55
.travis.yml
55
.travis.yml
@ -1,55 +0,0 @@
|
||||
notifications:
|
||||
email: true
|
||||
|
||||
os: linux
|
||||
|
||||
jobs:
|
||||
fast_finish: true
|
||||
include:
|
||||
|
||||
- name: make (gcc-arm-none-eabi-7)
|
||||
script: make
|
||||
env: VARIANT=VARIANT_ADC
|
||||
language: c
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libc6-i386
|
||||
install:
|
||||
- pushd .
|
||||
- cd ~
|
||||
- mkdir arm-gcc-toolchain
|
||||
- wget -O $HOME/arm-gcc-toolchain/gcc.tar.bz2 https://developer.arm.com/-/media/Files/downloads/gnu-rm/7-2018q2/gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2?revision=bc2c96c0-14b5-4bb4-9f18-bceb4050fee7?product=GNU%20Arm%20Embedded%20Toolchain,64-bit,,Linux,7-2018-q2-update
|
||||
- cd arm-gcc-toolchain
|
||||
- tar -jxf gcc.tar.bz2 --strip=1
|
||||
- popd
|
||||
- export PATH=$HOME/arm-gcc-toolchain/bin:$PATH
|
||||
before_script: arm-none-eabi-gcc --version
|
||||
|
||||
- name: make (gcc-arm-none-eabi-5)
|
||||
script: make
|
||||
env: VARIANT=VARIANT_ADC
|
||||
language: c
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libc6-i386
|
||||
install:
|
||||
- pushd .
|
||||
- cd ~
|
||||
- mkdir arm-gcc-toolchain
|
||||
- wget -O $HOME/arm-gcc-toolchain/gcc.tar.bz2 https://developer.arm.com/-/media/Files/downloads/gnu-rm/5_4-2016q3/gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2?revision=111dee36-f88b-4672-8ac6-48cf41b4d375?product=GNU%20Arm%20Embedded%20Toolchain,32-bit,,Linux,5-2016-q3-update
|
||||
- cd arm-gcc-toolchain
|
||||
- tar -jxf gcc.tar.bz2 --strip=1
|
||||
- popd
|
||||
- export PATH=$HOME/arm-gcc-toolchain/bin:$PATH
|
||||
before_script: arm-none-eabi-gcc --version
|
||||
|
||||
- name: platformio
|
||||
script: platformio run
|
||||
language: python
|
||||
install:
|
||||
- pip install -U platformio
|
||||
- platformio update
|
||||
cache:
|
||||
- directories: "~/.platformio"
|
@ -11,6 +11,8 @@
|
||||
// it is recommended to use the built-in Serial interface for full speed perfomace.
|
||||
// • The data packaging includes a Start Frame, checksum, and re-syncronization capability for reliable communication
|
||||
//
|
||||
// The code starts with zero speed and moves towards +
|
||||
//
|
||||
// CONFIGURATION on the hoverboard side in config.h:
|
||||
// • Option 1: Serial on Right Sensor cable (short wired cable) - recommended, since the USART3 pins are 5V tolerant.
|
||||
// #define CONTROL_SERIAL_USART3
|
||||
@ -28,6 +30,7 @@
|
||||
#define START_FRAME 0xABCD // [-] Start frme definition for reliable serial communication
|
||||
#define TIME_SEND 100 // [ms] Sending time interval
|
||||
#define SPEED_MAX_TEST 300 // [-] Maximum speed for testing
|
||||
#define SPEED_STEP 20 // [-] Speed step
|
||||
// #define DEBUG_RX // [-] Debug received data. Prints all bytes to serial (comment-out to disable)
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
@ -146,8 +149,8 @@ void Receive()
|
||||
// ########################## LOOP ##########################
|
||||
|
||||
unsigned long iTimeSend = 0;
|
||||
int iTestMax = SPEED_MAX_TEST;
|
||||
int iTest = 0;
|
||||
int iStep = SPEED_STEP;
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
@ -159,11 +162,14 @@ void loop(void)
|
||||
// Send commands
|
||||
if (iTimeSend > timeNow) return;
|
||||
iTimeSend = timeNow + TIME_SEND;
|
||||
Send(0, SPEED_MAX_TEST - 2*abs(iTest));
|
||||
Send(0, iTest);
|
||||
|
||||
// Calculate test command signal
|
||||
iTest += 10;
|
||||
if (iTest > iTestMax) iTest = -iTestMax;
|
||||
iTest += iStep;
|
||||
|
||||
// invert step if reaching limit
|
||||
if (iTest >= SPEED_MAX_TEST || iTest <= -SPEED_MAX_TEST)
|
||||
iStep = -iStep;
|
||||
|
||||
// Blink the LED
|
||||
digitalWrite(LED_BUILTIN, (timeNow%2000)<1000);
|
||||
|
@ -3,9 +3,9 @@
|
||||
*
|
||||
* Code generated for Simulink model 'BLDC_controller'.
|
||||
*
|
||||
* Model version : 1.1296
|
||||
* Model version : 1.1297
|
||||
* Simulink Coder version : 8.13 (R2017b) 24-Jul-2017
|
||||
* C/C++ source code generated on : Tue Oct 20 17:29:57 2020
|
||||
* C/C++ source code generated on : Sun Mar 6 11:02:11 2022
|
||||
*
|
||||
* Target selection: ert.tlc
|
||||
* Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||
|
33
Inc/config.h
33
Inc/config.h
@ -78,6 +78,7 @@
|
||||
#define BAT_CELLS 10 // battery number of cells. Normal Hoverboard battery: 10s
|
||||
#define BAT_LVL2_ENABLE 0 // to beep or not to beep, 1 or 0
|
||||
#define BAT_LVL1_ENABLE 1 // to beep or not to beep, 1 or 0
|
||||
#define BAT_DEAD_ENABLE 1 // to poweroff or not to poweroff, 1 or 0
|
||||
#define BAT_BLINK_INTERVAL 80 // battery led blink interval (80 loops * 5ms ~= 400ms)
|
||||
#define BAT_LVL5 (390 * BAT_CELLS * BAT_CALIB_ADC) / BAT_CALIB_REAL_VOLTAGE // Green blink: no beep
|
||||
#define BAT_LVL4 (380 * BAT_CELLS * BAT_CALIB_ADC) / BAT_CALIB_REAL_VOLTAGE // Yellow: no beep
|
||||
@ -299,6 +300,7 @@
|
||||
#define DEBUG_SERIAL_USART3 // right sensor board cable, disable if I2C (nunchuk or lcd) is used!
|
||||
#endif
|
||||
|
||||
// #define TANK_STEERING // use for tank steering, each input controls each wheel
|
||||
// #define ADC_ALTERNATE_CONNECT // use to swap ADC inputs
|
||||
// #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!
|
||||
@ -316,7 +318,7 @@
|
||||
// #define SIDEBOARD_SERIAL_USART3 0
|
||||
// #define CONTROL_SERIAL_USART3 0 // right sensor board cable. Number indicates priority for dual-input. 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 DUAL_INPUTS // UART*(Primary) + SIDEBOARD(Auxiliary). Uncomment this to use Dual-inputs
|
||||
#define PRI_INPUT1 3, -1000, 0, 1000, 0 // TYPE, MIN, MID, MAX, DEADBAND. See INPUT FORMAT section
|
||||
#define PRI_INPUT2 3, -1000, 0, 1000, 0 // TYPE, MIN, MID, MAX, DEADBAND. See INPUT FORMAT section
|
||||
@ -330,6 +332,7 @@
|
||||
#define FLASH_WRITE_KEY 0x1002 // Flash memory writing key. Change this key to ignore the input calibrations from the flash memory and use the ones in config.h
|
||||
#endif
|
||||
|
||||
// #define TANK_STEERING // use for tank steering, each input controls each wheel
|
||||
// #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
|
||||
@ -396,6 +399,7 @@
|
||||
#endif
|
||||
#define PPM_NUM_CHANNELS 6 // total number of PPM channels to receive, even if they are not used.
|
||||
|
||||
// #define TANK_STEERING // use for tank steering, each input controls each wheel
|
||||
// #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!
|
||||
@ -435,6 +439,7 @@
|
||||
#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 TANK_STEERING // use for tank steering, each input controls each wheel
|
||||
// #define INVERT_R_DIRECTION
|
||||
// #define INVERT_L_DIRECTION
|
||||
// #define SUPPORT_BUTTONS_LEFT // use left sensor board cable for button inputs. Disable DEBUG_SERIAL_USART2!
|
||||
@ -479,6 +484,8 @@
|
||||
#define PRI_INPUT2 3, -1000, 0, 1000, 0 // TYPE, MIN, MID, MAX, DEADBAND. See INPUT FORMAT section
|
||||
#endif
|
||||
|
||||
// #define TANK_STEERING // use for tank steering, each input controls each wheel
|
||||
|
||||
#if defined(CONTROL_SERIAL_USART3) && !defined(DUAL_INPUTS)
|
||||
#define DEBUG_SERIAL_USART2 // left sensor cable debug
|
||||
#elif defined(DEBUG_SERIAL_USART2) && !defined(DUAL_INPUTS)
|
||||
@ -493,7 +500,7 @@
|
||||
#ifdef VARIANT_HOVERCAR
|
||||
#define FLASH_WRITE_KEY 0x1107 // Flash memory writing key. Change this key to ignore the input calibrations from the flash memory and use the ones in config.h
|
||||
#undef CTRL_MOD_REQ
|
||||
#define CTRL_MOD_REQ TRQ_MODE // HOVERCAR works best in TORQUE Mode
|
||||
#define CTRL_MOD_REQ VLT_MODE // HOVERCAR works best in TORQUE Mode. VOLTAGE mode is preffered when freewheeling is not desired when throttle is released.
|
||||
#define CONTROL_ADC 0 // use ADC as input. Number indicates priority for dual-input. Disable CONTROL_SERIAL_USART2, FEEDBACK_SERIAL_USART2, DEBUG_SERIAL_USART2!
|
||||
#define SIDEBOARD_SERIAL_USART3 1 // Rx from right sensor board: to use photosensors as buttons. Number indicates priority for dual-input. Comment-out if sideboard is not used!
|
||||
#define FEEDBACK_SERIAL_USART3 // Tx to right sensor board: for LED battery indication. Comment-out if sideboard is not used!
|
||||
@ -517,6 +524,28 @@
|
||||
// #define ELECTRIC_BRAKE_ENABLE // [-] Flag to enable electric brake and replace the motor "freewheel" with a constant braking when the input torque request is 0. Only available and makes sense for TORQUE mode.
|
||||
// #define ELECTRIC_BRAKE_MAX 100 // (0, 500) Maximum electric brake to be applied when input torque request is 0 (pedal fully released).
|
||||
// #define ELECTRIC_BRAKE_THRES 120 // (0, 500) Threshold below at which the electric brake starts engaging.
|
||||
|
||||
#define MULTI_MODE_DRIVE // This option enables the selection of 3 driving modes at start-up using combinations of Brake and Throttle pedals (see below)
|
||||
#ifdef MULTI_MODE_DRIVE
|
||||
// BEGINNER MODE: Power ON + Brake [released] + Throttle [released or pressed]
|
||||
#define MULTI_MODE_DRIVE_M1_MAX 175
|
||||
#define MULTI_MODE_DRIVE_M1_RATE 250
|
||||
#define MULTI_MODE_M1_I_MOT_MAX 4
|
||||
#define MULTI_MODE_M1_N_MOT_MAX 30
|
||||
|
||||
// INTERMEDIATE MODE: Power ON + Brake [pressed] + Throttle [released]
|
||||
#define MULTI_MODE_DRIVE_M2_MAX 500
|
||||
#define MULTI_MODE_DRIVE_M2_RATE 300
|
||||
#define MULTI_MODE_M2_I_MOT_MAX 8
|
||||
#define MULTI_MODE_M2_N_MOT_MAX 80
|
||||
|
||||
// ADVANCED MODE: Power ON + Brake [pressed] + Throttle [pressed]
|
||||
#define MULTI_MODE_DRIVE_M3_MAX 1000
|
||||
#define MULTI_MODE_DRIVE_M3_RATE 450
|
||||
#define MULTI_MODE_M3_I_MOT_MAX I_MOT_MAX
|
||||
#define MULTI_MODE_M3_N_MOT_MAX N_MOT_MAX
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// Multiple tap detection: default DOUBLE Tap on Brake pedal (4 pulses)
|
||||
|
@ -229,11 +229,16 @@ typedef struct {
|
||||
uint16_t l_rx2;
|
||||
} adc_buf_t;
|
||||
|
||||
typedef enum {
|
||||
NUNCHUK_CONNECTING,
|
||||
NUNCHUK_DISCONNECTED,
|
||||
NUNCHUK_RECONNECTING,
|
||||
NUNCHUK_CONNECTED
|
||||
} nunchuk_state;
|
||||
|
||||
// Define I2C, Nunchuk, PPM, PWM functions
|
||||
void I2C_Init(void);
|
||||
void Nunchuk_Init(void);
|
||||
void Nunchuk_Read(void);
|
||||
uint8_t Nunchuk_Ping(void);
|
||||
nunchuk_state Nunchuk_Read(void);
|
||||
void PPM_Init(void);
|
||||
void PPM_ISR_Callback(void);
|
||||
void PWM_Init(void);
|
||||
@ -256,6 +261,5 @@ void PWM_ISR_CH2_Callback(void);
|
||||
#define SWC_SET (0x1800) // 0001 1000 0000 0000
|
||||
#define SWD_SET (0x2000) // 0010 0000 0000 0000
|
||||
|
||||
|
||||
#endif // DEFINES_H
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
*
|
||||
* Code generated for Simulink model 'BLDC_controller'.
|
||||
*
|
||||
* Model version : 1.1296
|
||||
* Model version : 1.1297
|
||||
* Simulink Coder version : 8.13 (R2017b) 24-Jul-2017
|
||||
* C/C++ source code generated on : Tue Oct 20 17:29:57 2020
|
||||
* C/C++ source code generated on : Sun Mar 6 11:02:11 2022
|
||||
*
|
||||
* Target selection: ert.tlc
|
||||
* Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||
|
200
README.md
200
README.md
@ -1,5 +1,5 @@
|
||||
# hoverboard-firmware-hack-FOC
|
||||
[](https://travis-ci.com/EmanuelFeru/hoverboard-firmware-hack-FOC)
|
||||
[](https://github.com/EFeru/hoverboard-firmware-hack-FOC/actions/workflows/build_on_commit.yml)
|
||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=CU2SWN2XV9SCY¤cy_code=EUR&source=url)
|
||||
|
||||
@ -8,26 +8,20 @@ This repository implements Field Oriented Control (FOC) for stock hoverboards. C
|
||||
- smooth torque output and improved motor efficiency. Thus, lower energy consumption
|
||||
- field weakening to increase maximum speed range
|
||||
|
||||
|
||||
Table of Contents
|
||||
=======================
|
||||
|
||||
* **Wiki:** please check the wiki pages for [Getting Started](https://github.com/EFeru/hoverboard-firmware-hack-FOC/wiki#getting-started) and for [Troubleshooting](https://github.com/EFeru/hoverboard-firmware-hack-FOC/wiki#troubleshooting)
|
||||
* [Hardware](#hardware)
|
||||
* [FOC Firmware](#foc-firmware)
|
||||
* [Example Variants](#example-variants)
|
||||
* [Dual Inputs](#dual-inputs)
|
||||
* [Flashing](#flashing)
|
||||
* [Troubleshooting](#troubleshooting)
|
||||
* [Diagnostics](#diagnostics)
|
||||
* [Projects and Links](#projects-and-links)
|
||||
* [Contributions](#contributions)
|
||||
|
||||
#### For the hoverboard sideboard firmware, see the following repositories:
|
||||
- [hoverboard-sideboard-hack-GD](https://github.com/EmanuelFeru/hoverboard-sideboard-hack-GD)
|
||||
- [hoverboard-sideboard-hack-STM](https://github.com/EmanuelFeru/hoverboard-sideboard-hack-STM)
|
||||
|
||||
#### The hoverboards with mainboards also come with 2 sideboards(not [splitboards](https://github.com/EFeru/hoverboard-firmware-hack-FOC/wiki/Firmware-Compatibility#split-boards)), check the following [wiki](https://github.com/EFeru/hoverboard-firmware-hack-FOC/wiki/Sideboards) about this firmware
|
||||
|
||||
#### For the FOC controller design, see the following repository:
|
||||
- [bldc-motor-control-FOC](https://github.com/EmanuelFeru/bldc-motor-control-FOC)
|
||||
- [bldc-motor-control-FOC](https://github.com/EFeru/bldc-motor-control-FOC)
|
||||
|
||||
#### Videos:
|
||||
<table>
|
||||
@ -59,14 +53,14 @@ For the reverse-engineered schematics of the mainboard, see [20150722_hoverboard
|
||||
---
|
||||
## FOC Firmware
|
||||
|
||||
In this firmware 3 control types are available:
|
||||
- Commutation
|
||||
- SIN (Sinusoidal)
|
||||
- FOC (Field Oriented Control) with the following 3 control modes:
|
||||
- **VOLTAGE MODE**: in this mode the controller applies a constant Voltage to the motors. Recommended for robotics applications or applications where a fast motor response is required.
|
||||
- **SPEED MODE**: in this mode a closed-loop controller realizes the input speed target by rejecting any of the disturbance (resistive load) applied to the motor. Recommended for robotics applications or constant speed applications.
|
||||
- **TORQUE MODE**: in this mode the input torque target is realized. This mode enables motor "freewheeling" when the torque target is `0`. Recommended for most applications with a sitting human driver.
|
||||
|
||||
In this firmware 3 control types are available, it can be set in config.h file via CTRL_TYP_SEL parameter:
|
||||
- Commutation (COM_CTRL)
|
||||
- Sinusoidal (SIN_CTRL)
|
||||
- Field Oriented Control (FOC_CTRL) with the following 3 control modes that can be set in config.h file with parameter CTRL_MOD_REQ:
|
||||
- **VOLTAGE MODE(VLT_MODE)**: in this mode the controller applies a constant Voltage to the motors. Recommended for robotics applications or applications where a fast motor response is required.
|
||||
- **SPEED MODE(SPD_MODE)**: in this mode a closed-loop controller realizes the input speed RPM target by rejecting any of the disturbance (resistive load) applied to the motor. Recommended for robotics applications or constant speed applications.
|
||||
- **TORQUE MODE(TRQ_MODE)**: in this mode the input torque target is realized. This mode enables motor "freewheeling" when the torque target is `0`. Recommended for most applications with a sitting human driver.
|
||||
|
||||
#### Comparison between different control methods
|
||||
|
||||
|Control method| Complexity | Efficiency | Smoothness | Field Weakening | Freewheeling | Standstill hold |
|
||||
@ -89,28 +83,35 @@ In all FOC control modes, the controller features maximum motor speed and maximu
|
||||
- The Field Weakening is a linear interpolation from 0 to FIELD_WEAK_MAX or PHASE_ADV_MAX (depeding if FOC or SIN is selected, respectively)
|
||||
- The Field Weakening starts engaging at FIELD_WEAK_LO and reaches the maximum value at FIELD_WEAK_HI
|
||||
- The figure below shows different possible calibrations for Field Weakening / Phase Advance
|
||||

|
||||
- If you re-calibrate the Field Weakening please take all the safety measures! The motors can spin very fast!
|
||||

|
||||
|
||||
⚠️ If you re-calibrate the Field Weakening please take all the safety measures! The motors can spin very fast!
|
||||
Power consumption will be highly increase and you can trigger the overvoltage protection of your BMS ⚠️
|
||||
|
||||
|
||||
### Parameters
|
||||
- All the calibratable motor parameters can be found in the 'BLDC_controller_data.c'. I provided you with an already calibrated controller, but if you feel like fine tuning it feel free to do so
|
||||
- The parameters are represented in Fixed-point data type for a more efficient code execution
|
||||
- For calibrating the fixed-point parameters use the [Fixed-Point Viewer](https://github.com/EmanuelFeru/FixedPointViewer) tool
|
||||
- The controller parameters are given in [this table](https://github.com/EmanuelFeru/bldc-motor-control-FOC/blob/master/02_Figures/paramTable.png)
|
||||
- For calibrating the fixed-point parameters use the [Fixed-Point Viewer](https://github.com/EFeru/FixedPointViewer) tool
|
||||
- The controller parameters are given in [this table](https://github.com/EFeru/bldc-motor-control-FOC/blob/master/02_Figures/paramTable.png)
|
||||
|
||||
|
||||
### FOC Webview
|
||||
|
||||
To explore the controller without a Matlab/Simulink installation click on the link below:
|
||||
|
||||
[https://eferu.github.io/bldc-motor-control-FOC/](https://eferu.github.io/bldc-motor-control-FOC/)
|
||||
|
||||
---
|
||||
## Example Variants
|
||||
|
||||
This firmware offers currently these variants (selectable in [platformio.ini](/platformio.ini) or [config.h](/Inc/config.h)):
|
||||
- **VARIANT_ADC**: The motors are controlled by two potentiometers connected to the Left sensor cable (long wired)
|
||||
- **VARIANT_USART**: The motors are controlled via serial protocol (e.g. on USART3 right sensor cable, the short wired cable). The commands can be sent from an Arduino. Check out the [hoverserial.ino](/Arduino/hoverserial) as an example sketch.
|
||||
- **VARIANT_NUNCHUK**: Wii Nunchuk 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**: RC remote control with PPM Sum signal.
|
||||
- **VARIANT_PWM**: RC remote control with PWM signal.
|
||||
- **VARIANT_IBUS**: RC remote control with Flysky iBUS protocol connected to the Left sensor cable.
|
||||
- **VARIANT_HOVERCAR**: The motors are controlled by two pedals brake and throttle. Reverse is engaged by double tapping on the brake pedal at standstill. See [HOVERCAR wiki](https://github.com/EmanuelFeru/hoverboard-firmware-hack-FOC/wiki/Variant-HOVERCAR).
|
||||
- **VARIANT_HOVERCAR**: The motors are controlled by two pedals brake and throttle. Reverse is engaged by double tapping on the brake pedal at standstill. See [HOVERCAR wiki](https://github.com/EFeru/hoverboard-firmware-hack-FOC/wiki/Variant-HOVERCAR).
|
||||
- **VARIANT_HOVERBOARD**: The mainboard reads the two sideboards data. The sideboards need to be flashed with the hacked version. The balancing controller is **not** yet implemented.
|
||||
- **VARIANT_TRANSPOTTER**: This is for transpotter build, 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_SKATEBOARD**: This is for skateboard build, controlled using an RC remote with PWM signal connected to the right sensor cable.
|
||||
@ -118,163 +119,34 @@ This firmware offers currently these variants (selectable in [platformio.ini](/p
|
||||
Of course the firmware can be further customized for other needs or projects.
|
||||
|
||||
|
||||
---
|
||||
## Dual Inputs
|
||||
|
||||
The firmware supports the input to be provided from two different sources connected to the Left and Right cable, respectively. To enable dual-inputs functionality uncomment `#define DUAL_INPUTS` in config.h for the respective variant. Various dual-inputs combinations can be realized as illustrated in the following table:
|
||||
| Left | Right | Availability |
|
||||
| --- | --- | --- |
|
||||
| ADC<sup>(0)</sup> | UART<sup>(1)</sup> | VARIANT_ADC |
|
||||
| ADC<sup>(0)</sup> | {PPM,PWM,iBUS}<sup>(1)</sup> | VARIANT_{PPM,PWM,IBUS} |
|
||||
| ADC<sup>(0)</sup> | Sideboard<sup></sup><sup>(1*)</sup> | VARIANT_HOVERCAR |
|
||||
| UART<sup>(0)</sup> | Sideboard<sup>(1*)</sup> | VARIANT_UART |
|
||||
| UART<sup>(1)</sup> | Nunchuk<sup>(0)</sup> | VARIANT_NUNCHUK |
|
||||
|
||||
<sup>(0)</sup> Primary input: this input is used when the Auxilliary input is not available or not connected.<br/>
|
||||
<sup>(1)</sup> Auxilliary input: this inputs is used when connected or enabled by a switch<sup>(*)</sup>. If the Auxilliary input is disconnected, the firmware will automatically switch to the Primary input. Timeout is reported **only** on the Primary input.
|
||||
|
||||
With slight modifications in config.h, other dual-inputs combinations can be realized as:
|
||||
| Left | Right | Possibility |
|
||||
| --- | --- | --- |
|
||||
| Sideboard<sup>(1*)</sup> | UART<sup>(0)</sup> | VARIANT_UART |
|
||||
| UART<sup>(0)</sup> | {PPM,PWM,iBUS}<sup>(1)</sup> | VARIANT_{PPM,PWM,IBUS} |
|
||||
| {PPM,PWM,iBUS}<sup>(1)</sup> | Nunchuk<sup>(0)</sup> | VARIANT_{PPM,PWM,IBUS} |
|
||||
|
||||
|
||||
---
|
||||
## Flashing
|
||||
|
||||
Right to the STM32, there is a debugging header with GND, 3V3, SWDIO and SWCLK. Connect GND, SWDIO and SWCLK to your SWD programmer, like the ST-Link found on many STM devboards.
|
||||
|
||||
If you have never flashed your sideboard before, the MCU is probably locked. To unlock the flash, check-out the wiki page [How to Unlock MCU flash](https://github.com/EmanuelFeru/hoverboard-firmware-hack-FOC/wiki/How-to-Unlock-MCU-flash).
|
||||
|
||||
Do not power the mainboard from the 3.3V of your programmer! This has already killed multiple mainboards.
|
||||
|
||||
Make sure you hold the powerbutton or connect a jumper to the power button pins while flashing the firmware, as the STM might release the power latch and switches itself off during flashing. Battery > 36V have to be connected while flashing.
|
||||
|
||||
To build and flash choose one of the following methods:
|
||||
|
||||
### Method 1: Using Platformio IDE
|
||||
|
||||
- open the folder in the IDE of choice (vscode or Atom)
|
||||
- press the 'PlatformIO:Build' or the 'PlatformIO:Upload' button (bottom left in vscode).
|
||||
|
||||
### Method 2: Using Keil uVision
|
||||
|
||||
- in [Keil uVision](https://www.keil.com/download/product/), open the [mainboard-hack.uvproj](/MDK-ARM/)
|
||||
- if you are asked to install missing packages, click Yes
|
||||
- click Build Target (or press F7) to build the firmware
|
||||
- click Load Code (or press F8) to flash the firmware.
|
||||
|
||||
### Method 3: Using Linux CLI
|
||||
|
||||
- prerequisites: install [ST-Flash utility](https://github.com/texane/stlink).
|
||||
- open a terminal in the repo check-out folder and if you have definded the variant in [config.h](/Inc/config.h) type:
|
||||
```
|
||||
make
|
||||
```
|
||||
or you can set the variant like this
|
||||
```
|
||||
make -e VARIANT=VARIANT_####
|
||||
```
|
||||
- flash the firmware by typing:
|
||||
```
|
||||
make flash
|
||||
```
|
||||
- or
|
||||
```
|
||||
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c flash "write_image erase build/hover.bin 0x8000000"
|
||||
```
|
||||
|
||||
### Method 4: MacOS CLI
|
||||
- prerequisites: first get brew https://brew.sh
|
||||
- then install stlink ST-Flash utility
|
||||
|
||||
#### Using Make
|
||||
```
|
||||
brew install stlink
|
||||
```
|
||||
- open a terminal in the repo check-out folder and if you have definded the variant in [config.h](/Inc/config.h) type:
|
||||
```
|
||||
make
|
||||
```
|
||||
or you can set the variant like this
|
||||
```
|
||||
make -e VARIANT=VARIANT_####
|
||||
```
|
||||
If compiling fails because something is missing just install it with brew AND leave a comment to improve this howto or pull request ;-)
|
||||
|
||||
- flash the firmware by typing:
|
||||
```
|
||||
make flash
|
||||
```
|
||||
- if unlock is needed
|
||||
```
|
||||
make unlock
|
||||
```
|
||||
|
||||
#### Using platformio CLI
|
||||
|
||||
```
|
||||
brew install platformio
|
||||
platformio run -e VARIANT_####
|
||||
platformio run –target upload -e VARIANT_####
|
||||
```
|
||||
If you have set default_envs in [platformio.ini](/platformio.ini) you can ommit -e parameter
|
||||
|
||||
|
||||
---
|
||||
## Troubleshooting
|
||||
First, check that power is connected and voltage is >36V while flashing.
|
||||
If the board draws more than 100mA in idle, it's probably broken.
|
||||
|
||||
If the motors do something, but don't rotate smooth and quietly, try to use an alternative phase mapping. Usually, color-correct mapping (blue to blue, green to green, yellow to yellow) works fine. However, some hoverboards have a different layout then others, and this might be the reason your motor isn't spinning.
|
||||
|
||||
Nunchuk not working: Use the right one of the 2 types of nunchuks. Use i2c pullups.
|
||||
|
||||
Nunchuk or PPM working bad: The i2c bus and PPM signal are very sensitive to emv distortions of the motor controller. They get stronger the faster you are. Keep cables short, use shielded cable, use ferrits, stabilize voltage in nunchuk or reviever, add i2c pullups. To many errors leads to very high accelerations which triggers the protection board within the battery to shut everything down.
|
||||
|
||||
Recommendation: Nunchuk Breakout Board https://github.com/Jan--Henrik/hoverboard-breakout
|
||||
|
||||
Most robust way for input is to use the ADC and potis. It works well even on 1m unshielded cable. Solder ~100k Ohm resistors between ADC-inputs and gnd directly on the mainboard. Use potis as pullups to 3.3V.
|
||||
|
||||
|
||||
---
|
||||
## Diagnostics
|
||||
The errors reported by the board are in the form of audible beeps:
|
||||
- **1 beep (low pitch)**: Motor error (see [possible causes](https://github.com/EmanuelFeru/bldc-motor-control-FOC#diagnostics))
|
||||
- **2 beeps (low pitch)**: ADC timeout
|
||||
- **3 beeps (low pitch)**: Serial communication timeout
|
||||
- **4 beeps (low pitch)**: General timeout (PPM, PWM, Nunchuk)
|
||||
- **5 beeps (low pitch)**: Mainboard temperature warning
|
||||
- **1 beep slow (medium pitch)**: Low battery voltage < 36V
|
||||
- **1 beep fast (medium pitch)**: Low battery voltage < 35V
|
||||
- **1 beep fast (high pitch)**: Backward spinning motors
|
||||
|
||||
For a more detailed troubleshooting connect an [FTDI Serial adapter](https://s.click.aliexpress.com/e/_AqPOBr) or a [Bluetooth module](https://s.click.aliexpress.com/e/_A4gkMD) to the DEBUG_SERIAL cable (Left or Right) and monitor the output data using the [Hoverboard Web Serial Control](https://candas1.github.io/Hoverboard-Web-Serial-Control/) tool developed by [Candas](https://github.com/Candas1/).
|
||||
|
||||
---
|
||||
## Projects and Links
|
||||
|
||||
- **Original firmware:** [https://github.com/NiklasFauth/hoverboard-firmware-hack](https://github.com/NiklasFauth/hoverboard-firmware-hack)
|
||||
- **Original firmware:** [https://github.com/lucysrausch/hoverboard-firmware-hack](https://github.com/lucysrausch/hoverboard-firmware-hack)
|
||||
- **[Candas](https://github.com/Candas1/) Hoverboard Web Serial Control:** [https://github.com/Candas1/Hoverboard-Web-Serial-Control](https://github.com/Candas1/Hoverboard-Web-Serial-Control)
|
||||
- **[RoboDurden's](https://github.com/RoboDurden) online compiler:** [https://pionierland.de/hoverhack/](https://pionierland.de/hoverhack/)
|
||||
- **Hoverboard hack for AT32F403RCT6 mainboards:** [https://github.com/cloidnerux/hoverboard-firmware-hack](https://github.com/cloidnerux/hoverboard-firmware-hack)
|
||||
- **Hoverboard hack for split mainboards:** [https://github.com/flo199213/Hoverboard-Firmware-Hack-Gen2](https://github.com/flo199213/Hoverboard-Firmware-Hack-Gen2)
|
||||
- **Hoverboard hack from BiPropellant:** [https://github.com/bipropellant](https://github.com/bipropellant)
|
||||
- **Hoverboard breakout boards:** [https://github.com/Jan--Henrik/hoverboard-breakout](https://github.com/Jan--Henrik/hoverboard-breakout)
|
||||
- **Hoverboard breakout boards:** [https://github.com/Jana-Marie/hoverboard-breakout](https://github.com/Jana-Marie/hoverboard-breakout)
|
||||
|
||||
<a/>
|
||||
|
||||
- **Bobbycar** [https://github.com/larsmm/hoverboard-firmware-hack-bbcar](https://github.com/larsmm/hoverboard-firmware-hack-bbcar)
|
||||
- **Bobbycar** [https://github.com/larsmm/hoverboard-firmware-hack-FOC-bbcar](https://github.com/larsmm/hoverboard-firmware-hack-FOC-bbcar)
|
||||
- **Wheel chair:** [https://github.com/Lahorde/steer_speed_ctrl](https://github.com/Lahorde/steer_speed_ctrl)
|
||||
- **TranspOtterNG:** [https://github.com/Jan--Henrik/transpOtterNG](https://github.com/Jan--Henrik/transpOtterNG)
|
||||
- **Hoverboard driver for ROS:** [https://github.com/alex-makarov/hoverboard-driver](https://github.com/alex-makarov/hoverboard-driver)
|
||||
- **Ongoing OneWheel project:** [https://forum.esk8.news/t/yet-another-hoverboard-to-onewheel-project/60979/14](https://forum.esk8.news/t/yet-another-hoverboard-to-onewheel-project/60979/14)
|
||||
- **ST Community:** [Custom FOC motor control](https://community.st.com/s/question/0D50X0000B28qTDSQY/custom-foc-control-current-measurement-dma-timer-interrupt-needs-review)
|
||||
|
||||
<a/>
|
||||
|
||||
- **Telegram Community:** If you are an enthusiast join our [Hooover Telegram Group](https://t.me/joinchat/BHWO_RKu2LT5ZxEkvUB8uw)
|
||||
|
||||
---
|
||||
## Stargazers
|
||||
|
||||
[](https://starchart.cc/EFeru/hoverboard-firmware-hack-FOC)
|
||||
|
||||
---
|
||||
## Contributions
|
||||
@ -285,6 +157,4 @@ If you want to donate to keep this firmware updated, please use the link below:
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=CU2SWN2XV9SCY¤cy_code=EUR&source=url)
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
@ -3,9 +3,9 @@
|
||||
*
|
||||
* Code generated for Simulink model 'BLDC_controller'.
|
||||
*
|
||||
* Model version : 1.1296
|
||||
* Model version : 1.1297
|
||||
* Simulink Coder version : 8.13 (R2017b) 24-Jul-2017
|
||||
* C/C++ source code generated on : Tue Oct 20 17:29:57 2020
|
||||
* C/C++ source code generated on : Sun Mar 6 11:02:11 2022
|
||||
*
|
||||
* Target selection: ert.tlc
|
||||
* Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||
@ -1019,6 +1019,8 @@ void BLDC_controller_step(RT_MODEL *const rtM)
|
||||
int32_T rtb_Sum1_jt;
|
||||
int16_T rtb_Merge_m;
|
||||
int16_T rtb_Merge1;
|
||||
uint16_T rtb_Divide14_e;
|
||||
uint16_T rtb_Divide1_f;
|
||||
int16_T rtb_TmpSignalConversionAtLow_Pa[2];
|
||||
int32_T rtb_Switch1;
|
||||
int32_T rtb_Sum1;
|
||||
@ -2116,20 +2118,15 @@ void BLDC_controller_step(RT_MODEL *const rtM)
|
||||
|
||||
/* End of Switch: '<S44>/Switch2' */
|
||||
|
||||
/* Switch: '<S42>/Switch2' incorporates:
|
||||
* Constant: '<S1>/z_ctrlTypSel'
|
||||
* Constant: '<S42>/CTRL_COMM2'
|
||||
* Constant: '<S42>/a_phaAdvMax'
|
||||
* Constant: '<S42>/id_fieldWeakMax'
|
||||
* RelationalOperator: '<S42>/Relational Operator1'
|
||||
/* Product: '<S42>/Divide14' incorporates:
|
||||
* Constant: '<S42>/r_fieldWeakHi'
|
||||
* Constant: '<S42>/r_fieldWeakLo'
|
||||
* Sum: '<S42>/Sum1'
|
||||
* Sum: '<S42>/Sum3'
|
||||
*/
|
||||
if (rtP->z_ctrlTypSel == 2) {
|
||||
rtb_Saturation1 = rtP->id_fieldWeakMax;
|
||||
} else {
|
||||
rtb_Saturation1 = rtP->a_phaAdvMax;
|
||||
}
|
||||
|
||||
/* End of Switch: '<S42>/Switch2' */
|
||||
rtb_Divide14_e = (uint16_T)(((int16_T)(DataTypeConversion2 -
|
||||
rtP->r_fieldWeakLo) << 15) / (int16_T)(rtP->r_fieldWeakHi -
|
||||
rtP->r_fieldWeakLo));
|
||||
|
||||
/* Switch: '<S43>/Switch2' incorporates:
|
||||
* Constant: '<S42>/n_fieldWeakAuthHi'
|
||||
@ -2151,25 +2148,53 @@ void BLDC_controller_step(RT_MODEL *const rtM)
|
||||
|
||||
/* End of Switch: '<S43>/Switch2' */
|
||||
|
||||
/* Product: '<S42>/Divide3' incorporates:
|
||||
/* Product: '<S42>/Divide1' incorporates:
|
||||
* Constant: '<S42>/n_fieldWeakAuthHi'
|
||||
* Constant: '<S42>/n_fieldWeakAuthLo'
|
||||
* Constant: '<S42>/r_fieldWeakHi'
|
||||
* Constant: '<S42>/r_fieldWeakLo'
|
||||
* Product: '<S42>/Divide1'
|
||||
* Product: '<S42>/Divide14'
|
||||
* Product: '<S42>/Divide2'
|
||||
* Sum: '<S42>/Sum1'
|
||||
* Sum: '<S42>/Sum2'
|
||||
* Sum: '<S42>/Sum3'
|
||||
* Sum: '<S42>/Sum4'
|
||||
*/
|
||||
rtDW->Divide3 = (int16_T)(((uint16_T)(((uint32_T)(uint16_T)(((int16_T)
|
||||
(DataTypeConversion2 - rtP->r_fieldWeakLo) << 15) / (int16_T)
|
||||
(rtP->r_fieldWeakHi - rtP->r_fieldWeakLo)) * (uint16_T)(((int16_T)
|
||||
(rtb_Saturation - rtP->n_fieldWeakAuthLo) << 15) / (int16_T)
|
||||
(rtP->n_fieldWeakAuthHi - rtP->n_fieldWeakAuthLo))) >> 15) *
|
||||
rtb_Saturation1) >> 15);
|
||||
rtb_Divide1_f = (uint16_T)(((int16_T)(rtb_Saturation -
|
||||
rtP->n_fieldWeakAuthLo) << 15) / (int16_T)(rtP->n_fieldWeakAuthHi -
|
||||
rtP->n_fieldWeakAuthLo));
|
||||
|
||||
/* Switch: '<S42>/Switch1' incorporates:
|
||||
* MinMax: '<S42>/MinMax1'
|
||||
* RelationalOperator: '<S42>/Relational Operator6'
|
||||
*/
|
||||
if (rtb_Divide14_e < rtb_Divide1_f) {
|
||||
/* MinMax: '<S42>/MinMax' */
|
||||
if (!(rtb_Divide14_e > rtb_Divide1_f)) {
|
||||
rtb_Divide14_e = rtb_Divide1_f;
|
||||
}
|
||||
|
||||
/* End of MinMax: '<S42>/MinMax' */
|
||||
} else {
|
||||
if (rtb_Divide1_f < rtb_Divide14_e) {
|
||||
/* MinMax: '<S42>/MinMax1' */
|
||||
rtb_Divide14_e = rtb_Divide1_f;
|
||||
}
|
||||
}
|
||||
|
||||
/* End of Switch: '<S42>/Switch1' */
|
||||
|
||||
/* Switch: '<S42>/Switch2' incorporates:
|
||||
* Constant: '<S1>/z_ctrlTypSel'
|
||||
* Constant: '<S42>/CTRL_COMM2'
|
||||
* Constant: '<S42>/a_phaAdvMax'
|
||||
* Constant: '<S42>/id_fieldWeakMax'
|
||||
* RelationalOperator: '<S42>/Relational Operator1'
|
||||
*/
|
||||
if (rtP->z_ctrlTypSel == 2) {
|
||||
rtb_Saturation1 = rtP->id_fieldWeakMax;
|
||||
} else {
|
||||
rtb_Saturation1 = rtP->a_phaAdvMax;
|
||||
}
|
||||
|
||||
/* End of Switch: '<S42>/Switch2' */
|
||||
|
||||
/* Product: '<S42>/Divide3' */
|
||||
rtDW->Divide3 = (int16_T)((rtb_Saturation1 * rtb_Divide14_e) >> 15);
|
||||
|
||||
/* End of Outputs for SubSystem: '<S6>/Field_Weakening_Enabled' */
|
||||
}
|
||||
|
@ -3,9 +3,9 @@
|
||||
*
|
||||
* Code generated for Simulink model 'BLDC_controller'.
|
||||
*
|
||||
* Model version : 1.1296
|
||||
* Model version : 1.1297
|
||||
* Simulink Coder version : 8.13 (R2017b) 24-Jul-2017
|
||||
* C/C++ source code generated on : Tue Oct 20 17:29:57 2020
|
||||
* C/C++ source code generated on : Sun Mar 6 11:02:11 2022
|
||||
*
|
||||
* Target selection: ert.tlc
|
||||
* Embedded hardware selection: ARM Compatible->ARM Cortex
|
||||
|
@ -487,7 +487,8 @@ void handle_input(uint8_t *userCommand, uint32_t len)
|
||||
|
||||
// If there is already an unprocessed command, exit
|
||||
if (command.semaphore == 1) return;
|
||||
|
||||
if (*userCommand != '$') return; // reject if first character is not $
|
||||
|
||||
// Check end of line
|
||||
userCommand+=len-1; // Go to last char
|
||||
if (*userCommand != '\n' && *userCommand != '\r'){
|
||||
@ -495,6 +496,7 @@ void handle_input(uint8_t *userCommand, uint32_t len)
|
||||
return;
|
||||
}
|
||||
userCommand-=len-1; // Come back
|
||||
userCommand++; // Skip $
|
||||
|
||||
int8_t cindex = -1;
|
||||
int8_t pindex = -1;
|
||||
|
128
Src/control.c
128
Src/control.c
@ -6,6 +6,8 @@
|
||||
#include "setup.h"
|
||||
#include "config.h"
|
||||
|
||||
#define NUNCHUK_I2C_ADDRESS 0xA4
|
||||
|
||||
TIM_HandleTypeDef TimHandle;
|
||||
TIM_HandleTypeDef TimHandle2;
|
||||
uint8_t ppm_count = 0;
|
||||
@ -15,6 +17,7 @@ uint8_t timeoutFlgGen = 0;
|
||||
uint8_t nunchuk_data[6] = {0};
|
||||
|
||||
uint8_t i2cBuffer[2];
|
||||
nunchuk_state nunchukState = NUNCHUK_CONNECTING;
|
||||
|
||||
extern I2C_HandleTypeDef hi2c2;
|
||||
extern DMA_HandleTypeDef hdma_i2c2_rx;
|
||||
@ -214,44 +217,127 @@ void PWM_Init(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t Nunchuk_Ping(void) {
|
||||
if (HAL_I2C_Master_Receive(&hi2c2,0xA4,(uint8_t*)nunchuk_data, 1, 10) == HAL_OK) {
|
||||
return 1;
|
||||
uint8_t Nunchuk_tx(uint8_t i2cBuffer[], uint8_t i2cBufferLength) {
|
||||
if(HAL_I2C_Master_Transmit(&hi2c2,NUNCHUK_I2C_ADDRESS,(uint8_t*)i2cBuffer, i2cBufferLength, 100) == HAL_OK) {
|
||||
return true;
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Nunchuk_Init(void) {
|
||||
//-- START -- init WiiNunchuk
|
||||
uint8_t Nunchuk_rx(uint8_t i2cBuffer[], uint8_t i2cBufferLength) {
|
||||
if(HAL_I2C_Master_Receive(&hi2c2,NUNCHUK_I2C_ADDRESS,(uint8_t*)i2cBuffer, i2cBufferLength, 100) == HAL_OK) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t Nunchuk_Init(void) {
|
||||
//-- START -- init WiiNunchuk
|
||||
i2cBuffer[0] = 0xF0;
|
||||
i2cBuffer[1] = 0x55;
|
||||
|
||||
HAL_I2C_Master_Transmit(&hi2c2,0xA4,(uint8_t*)i2cBuffer, 2, 100);
|
||||
if(Nunchuk_tx(i2cBuffer, 2) == false) {
|
||||
return false;
|
||||
}
|
||||
HAL_Delay(10);
|
||||
|
||||
i2cBuffer[0] = 0xFB;
|
||||
i2cBuffer[1] = 0x00;
|
||||
|
||||
HAL_I2C_Master_Transmit(&hi2c2,0xA4,(uint8_t*)i2cBuffer, 2, 100);
|
||||
if(Nunchuk_tx(i2cBuffer, 2) == false) {
|
||||
return false;
|
||||
}
|
||||
HAL_Delay(10);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Nunchuk_Read(void) {
|
||||
i2cBuffer[0] = 0x00;
|
||||
HAL_I2C_Master_Transmit(&hi2c2,0xA4,(uint8_t*)i2cBuffer, 1, 10);
|
||||
HAL_Delay(3);
|
||||
if (HAL_I2C_Master_Receive(&hi2c2,0xA4,(uint8_t*)nunchuk_data, 6, 10) == HAL_OK) {
|
||||
uint8_t Nunchuk_Connect() {
|
||||
/* Initialise / re-initialise I2C peripheral */
|
||||
I2C_Init();
|
||||
|
||||
/* Initialise / re-initialise nunchuk */
|
||||
if(Nunchuk_Init() == true) {
|
||||
nunchukState = NUNCHUK_CONNECTED;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
nunchuk_state Nunchuk_Read(void) {
|
||||
static uint8_t delay_counter = 0;
|
||||
uint16_t checksum = 0;
|
||||
uint8_t success = true;
|
||||
uint8_t i = 0;
|
||||
|
||||
switch(nunchukState) {
|
||||
case NUNCHUK_DISCONNECTED:
|
||||
success = false;
|
||||
/* Delay a bit before reconnecting */
|
||||
if(delay_counter++ > 100) {
|
||||
success = Nunchuk_Connect();
|
||||
delay_counter = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case NUNCHUK_CONNECTING:
|
||||
case NUNCHUK_RECONNECTING:
|
||||
/* Try to reconnect once, if fails again fall back to disconnected state */
|
||||
success = Nunchuk_Connect();
|
||||
if(!success) {
|
||||
nunchukState = NUNCHUK_DISCONNECTED;
|
||||
}
|
||||
break;
|
||||
|
||||
case NUNCHUK_CONNECTED:
|
||||
/* Send read address of 0x00 to the Nunchuk */
|
||||
i2cBuffer[0] = 0x00;
|
||||
if(!Nunchuk_tx(i2cBuffer, 1)) {
|
||||
success = false;
|
||||
}
|
||||
HAL_Delay(3);
|
||||
|
||||
/* Clear the receive data buffer */
|
||||
for(i = 0; i<6; i++) {
|
||||
nunchuk_data[i] = 0;
|
||||
}
|
||||
|
||||
/* Read back 6 bytes from the Nunchuk */
|
||||
if(!Nunchuk_rx(nunchuk_data, 6)) {
|
||||
success = false;
|
||||
}
|
||||
HAL_Delay(3);
|
||||
|
||||
/* Checksum the receive buffer to ensure it is not in an error condition, i.e. all 0x00 or 0xFF */
|
||||
for(i = 0; i<6; i++) {
|
||||
checksum += nunchuk_data[i];
|
||||
}
|
||||
if(checksum == 0 || checksum == 0x5FA) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
/* Comms failure or timeout counter reached timeout limit */
|
||||
if(success == false || timeoutCntGen > 3) {
|
||||
/* Clear the receive data buffer */
|
||||
for(i = 0; i<6; i++) {
|
||||
nunchuk_data[i] = 0;
|
||||
}
|
||||
/* Brings motors to safe stop */
|
||||
/* Expected values from nunchuk for stopped (mid) position */
|
||||
nunchuk_data[0] = 127;
|
||||
nunchuk_data[1] = 128;
|
||||
timeoutFlgGen = 1;
|
||||
nunchukState = NUNCHUK_RECONNECTING;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Reset the timeout flag and counter if successful communication */
|
||||
if(success == true) {
|
||||
timeoutCntGen = 0;
|
||||
timeoutFlgGen = 0;
|
||||
}
|
||||
|
||||
#ifndef TRANSPOTTER
|
||||
if (timeoutCntGen > 3) {
|
||||
HAL_Delay(50);
|
||||
Nunchuk_Init();
|
||||
}
|
||||
#endif
|
||||
|
||||
return nunchukState;
|
||||
//setScopeChannel(0, (int)nunchuk_data[0]);
|
||||
//setScopeChannel(1, (int)nunchuk_data[1]);
|
||||
//setScopeChannel(2, (int)nunchuk_data[5] & 1);
|
||||
|
131
Src/main.c
131
Src/main.c
@ -138,7 +138,7 @@ static uint8_t sideboard_leds_R;
|
||||
#endif
|
||||
|
||||
#ifdef VARIANT_TRANSPOTTER
|
||||
extern uint8_t nunchuk_connected;
|
||||
uint8_t nunchuk_connected;
|
||||
extern float setDistance;
|
||||
|
||||
static uint8_t checkRemote = 0;
|
||||
@ -162,6 +162,14 @@ static uint32_t buzzerTimer_prev = 0;
|
||||
static uint32_t inactivity_timeout_counter;
|
||||
static MultipleTap MultipleTapBrake; // define multiple tap functionality for the Brake pedal
|
||||
|
||||
static uint16_t rate = RATE; // Adjustable rate to support multiple drive modes on startup
|
||||
|
||||
#ifdef MULTI_MODE_DRIVE
|
||||
static uint8_t drive_mode;
|
||||
static uint16_t max_speed;
|
||||
#endif
|
||||
|
||||
|
||||
int main(void) {
|
||||
|
||||
HAL_Init();
|
||||
@ -205,9 +213,41 @@ int main(void) {
|
||||
int32_t board_temp_adcFixdt = adc_buffer.temp << 16; // Fixed-point filter output initialized with current ADC converted to fixed-point
|
||||
int16_t board_temp_adcFilt = adc_buffer.temp;
|
||||
|
||||
#ifdef MULTI_MODE_DRIVE
|
||||
if (adc_buffer.l_tx2 > input1[0].min + 50 && adc_buffer.l_rx2 > input2[0].min + 50) {
|
||||
drive_mode = 2;
|
||||
max_speed = MULTI_MODE_DRIVE_M3_MAX;
|
||||
rate = MULTI_MODE_DRIVE_M3_RATE;
|
||||
rtP_Left.n_max = rtP_Right.n_max = MULTI_MODE_M3_N_MOT_MAX << 4;
|
||||
rtP_Left.i_max = rtP_Right.i_max = (MULTI_MODE_M3_I_MOT_MAX * A2BIT_CONV) << 4;
|
||||
} else if (adc_buffer.l_tx2 > input1[0].min + 50) {
|
||||
drive_mode = 1;
|
||||
max_speed = MULTI_MODE_DRIVE_M2_MAX;
|
||||
rate = MULTI_MODE_DRIVE_M2_RATE;
|
||||
rtP_Left.n_max = rtP_Right.n_max = MULTI_MODE_M2_N_MOT_MAX << 4;
|
||||
rtP_Left.i_max = rtP_Right.i_max = (MULTI_MODE_M2_I_MOT_MAX * A2BIT_CONV) << 4;
|
||||
} else {
|
||||
drive_mode = 0;
|
||||
max_speed = MULTI_MODE_DRIVE_M1_MAX;
|
||||
rate = MULTI_MODE_DRIVE_M1_RATE;
|
||||
rtP_Left.n_max = rtP_Right.n_max = MULTI_MODE_M1_N_MOT_MAX << 4;
|
||||
rtP_Left.i_max = rtP_Right.i_max = (MULTI_MODE_M1_I_MOT_MAX * A2BIT_CONV) << 4;
|
||||
}
|
||||
|
||||
printf("Drive mode %i selected: max_speed:%i acc_rate:%i \r\n", drive_mode, max_speed, rate);
|
||||
#endif
|
||||
|
||||
// Loop until button is released
|
||||
while(HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN)) { HAL_Delay(10); }
|
||||
|
||||
#ifdef MULTI_MODE_DRIVE
|
||||
// Wait until triggers are released. Exit if timeout elapses (to unblock if the inputs are not calibrated)
|
||||
int iTimeout = 0;
|
||||
while((adc_buffer.l_rx2 + adc_buffer.l_tx2) >= (input1[0].min + input2[0].min) && iTimeout++ < 300) {
|
||||
HAL_Delay(10);
|
||||
}
|
||||
#endif
|
||||
|
||||
while(1) {
|
||||
if (buzzerTimer - buzzerTimer_prev > 16*DELAY_IN_MAIN_LOOP) { // 1 ms = 16 ticks buzzerTimer
|
||||
|
||||
@ -216,7 +256,8 @@ int main(void) {
|
||||
|
||||
#ifndef VARIANT_TRANSPOTTER
|
||||
// ####### MOTOR ENABLING: Only if the initial input is very small (for SAFETY) #######
|
||||
if (enable == 0 && (!rtY_Left.z_errCode && !rtY_Right.z_errCode) && (input1[inIdx].cmd > -50 && input1[inIdx].cmd < 50) && (input2[inIdx].cmd > -50 && input2[inIdx].cmd < 50)){
|
||||
if (enable == 0 && !rtY_Left.z_errCode && !rtY_Right.z_errCode &&
|
||||
ABS(input1[inIdx].cmd) < 50 && ABS(input2[inIdx].cmd) < 50){
|
||||
beepShort(6); // make 2 beeps indicating the motor enable
|
||||
beepShort(4); HAL_Delay(100);
|
||||
steerFixdt = speedFixdt = 0; // reset filters
|
||||
@ -274,8 +315,8 @@ int main(void) {
|
||||
#endif
|
||||
|
||||
// ####### LOW-PASS FILTER #######
|
||||
rateLimiter16(input1[inIdx].cmd , RATE, &steerRateFixdt);
|
||||
rateLimiter16(input2[inIdx].cmd , RATE, &speedRateFixdt);
|
||||
rateLimiter16(input1[inIdx].cmd, rate, &steerRateFixdt);
|
||||
rateLimiter16(input2[inIdx].cmd, rate, &speedRateFixdt);
|
||||
filtLowPass32(steerRateFixdt >> 4, FILTER, &steerFixdt);
|
||||
filtLowPass32(speedRateFixdt >> 4, FILTER, &speedFixdt);
|
||||
steer = (int16_t)(steerFixdt >> 16); // convert fixed-point to integer
|
||||
@ -284,6 +325,13 @@ int main(void) {
|
||||
// ####### VARIANT_HOVERCAR #######
|
||||
#ifdef VARIANT_HOVERCAR
|
||||
if (inIdx == CONTROL_ADC) { // Only use use implementation below if pedals are in use (ADC input)
|
||||
|
||||
#ifdef MULTI_MODE_DRIVE
|
||||
if (speed >= max_speed) {
|
||||
speed = max_speed;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!MultipleTapBrake.b_multipleTap) { // Check driving direction
|
||||
speed = steer + speed; // Forward driving: in this case steer = Brake, speed = Throttle
|
||||
} else {
|
||||
@ -293,10 +341,15 @@ int main(void) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// ####### MIXER #######
|
||||
// cmdR = CLAMP((int)(speed * SPEED_COEFFICIENT - steer * STEER_COEFFICIENT), INPUT_MIN, INPUT_MAX);
|
||||
// cmdL = CLAMP((int)(speed * SPEED_COEFFICIENT + steer * STEER_COEFFICIENT), INPUT_MIN, INPUT_MAX);
|
||||
mixerFcn(speed << 4, steer << 4, &cmdR, &cmdL); // This function implements the equations above
|
||||
#if defined(TANK_STEERING) && !defined(VARIANT_HOVERCAR) && !defined(VARIANT_SKATEBOARD)
|
||||
// Tank steering (no mixing)
|
||||
cmdL = steer;
|
||||
cmdR = speed;
|
||||
#else
|
||||
// ####### MIXER #######
|
||||
mixerFcn(speed << 4, steer << 4, &cmdR, &cmdL); // This function implements the equations above
|
||||
#endif
|
||||
|
||||
|
||||
// ####### SET OUTPUTS (if the target change is less than +/- 100) #######
|
||||
#ifdef INVERT_R_DIRECTION
|
||||
@ -376,17 +429,15 @@ int main(void) {
|
||||
#ifdef SUPPORT_NUNCHUK
|
||||
if (transpotter_counter % 500 == 0) {
|
||||
if (nunchuk_connected == 0 && enable == 0) {
|
||||
if (Nunchuk_Ping()) {
|
||||
HAL_Delay(500);
|
||||
Nunchuk_Init();
|
||||
#ifdef SUPPORT_LCD
|
||||
LCD_SetLocation(&lcd, 0, 0); LCD_WriteString(&lcd, "Nunchuk Control");
|
||||
#endif
|
||||
timeoutCntGen = 0;
|
||||
timeoutFlgGen = 0;
|
||||
HAL_Delay(1000);
|
||||
nunchuk_connected = 1;
|
||||
}
|
||||
if(Nunchuk_Read() == NUNCHUK_CONNECTED) {
|
||||
#ifdef SUPPORT_LCD
|
||||
LCD_SetLocation(&lcd, 0, 0); LCD_WriteString(&lcd, "Nunchuk Control");
|
||||
#endif
|
||||
nunchuk_connected = 1;
|
||||
}
|
||||
} else {
|
||||
nunchuk_connected = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -409,14 +460,19 @@ int main(void) {
|
||||
#endif
|
||||
|
||||
// ####### SIDEBOARDS HANDLING #######
|
||||
#if defined(SIDEBOARD_SERIAL_USART2) && defined(FEEDBACK_SERIAL_USART2)
|
||||
sideboardLeds(&sideboard_leds_L);
|
||||
#if defined(SIDEBOARD_SERIAL_USART2)
|
||||
sideboardSensors((uint8_t)Sideboard_L.sensors);
|
||||
#endif
|
||||
#if defined(SIDEBOARD_SERIAL_USART3) && defined(FEEDBACK_SERIAL_USART3)
|
||||
sideboardLeds(&sideboard_leds_R);
|
||||
#if defined(FEEDBACK_SERIAL_USART2)
|
||||
sideboardLeds(&sideboard_leds_L);
|
||||
#endif
|
||||
#if defined(SIDEBOARD_SERIAL_USART3)
|
||||
sideboardSensors((uint8_t)Sideboard_R.sensors);
|
||||
#endif
|
||||
#if defined(FEEDBACK_SERIAL_USART3)
|
||||
sideboardLeds(&sideboard_leds_R);
|
||||
#endif
|
||||
|
||||
|
||||
// ####### CALC BOARD TEMPERATURE #######
|
||||
filtLowPass32(adc_buffer.temp, TEMP_FILT_COEF, &board_temp_adcFixdt);
|
||||
@ -437,7 +493,7 @@ int main(void) {
|
||||
#if defined(DEBUG_SERIAL_PROTOCOL)
|
||||
process_debug();
|
||||
#else
|
||||
printf("in1:%i in2:%i cmdL:%i cmdR:%i BatADC:%i BatV:%i TempADC:%i Temp:%i\r\n",
|
||||
printf("in1:%i in2:%i cmdL:%i cmdR:%i BatADC:%i BatV:%i TempADC:%i Temp:%i \r\n",
|
||||
input1[inIdx].raw, // 1: INPUT1
|
||||
input2[inIdx].raw, // 2: INPUT2
|
||||
cmdL, // 3: output command: [-1000, 1000]
|
||||
@ -486,7 +542,15 @@ int main(void) {
|
||||
poweroffPressCheck();
|
||||
|
||||
// ####### BEEP AND EMERGENCY POWEROFF #######
|
||||
if ((TEMP_POWEROFF_ENABLE && board_temp_deg_c >= TEMP_POWEROFF && speedAvgAbs < 20) || (batVoltage < BAT_DEAD && speedAvgAbs < 20)) { // poweroff before mainboard burns OR low bat 3
|
||||
if (TEMP_POWEROFF_ENABLE && board_temp_deg_c >= TEMP_POWEROFF && speedAvgAbs < 20){ // poweroff before mainboard burns OR low bat 3
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Powering off, temperature is too high\r\n");
|
||||
#endif
|
||||
poweroff();
|
||||
} else if ( BAT_DEAD_ENABLE && batVoltage < BAT_DEAD && speedAvgAbs < 20){
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Powering off, battery voltage is too low\r\n");
|
||||
#endif
|
||||
poweroff();
|
||||
} else if (rtY_Left.z_errCode || rtY_Right.z_errCode) { // 1 beep (low pitch): Motor error, disable motors
|
||||
enable = 0;
|
||||
@ -503,7 +567,7 @@ int main(void) {
|
||||
beepCount(0, 10, 6);
|
||||
} else if (BAT_LVL2_ENABLE && batVoltage < BAT_LVL2) { // 1 beep slow (medium pitch): Low bat 2
|
||||
beepCount(0, 10, 30);
|
||||
} else if (BEEPS_BACKWARD && ((speed < -50 && speedAvg < 0) || MultipleTapBrake.b_multipleTap)) { // 1 beep fast (high pitch): Backward spinning motors
|
||||
} else if (BEEPS_BACKWARD && (((cmdR < -50 || cmdL < -50) && speedAvg < 0) || MultipleTapBrake.b_multipleTap)) { // 1 beep fast (high pitch): Backward spinning motors
|
||||
beepCount(0, 5, 1);
|
||||
backwardDrive = 1;
|
||||
} else { // do not beep
|
||||
@ -512,13 +576,24 @@ int main(void) {
|
||||
}
|
||||
|
||||
|
||||
inactivity_timeout_counter++;
|
||||
|
||||
// ####### INACTIVITY TIMEOUT #######
|
||||
if (abs(cmdL) > 50 || abs(cmdR) > 50) {
|
||||
inactivity_timeout_counter = 0;
|
||||
} else {
|
||||
inactivity_timeout_counter++;
|
||||
}
|
||||
|
||||
#if defined(CRUISE_CONTROL_SUPPORT) || defined(STANDSTILL_HOLD_ENABLE)
|
||||
if ((abs(rtP_Left.n_cruiseMotTgt) > 50 && rtP_Left.b_cruiseCtrlEna) ||
|
||||
(abs(rtP_Right.n_cruiseMotTgt) > 50 && rtP_Right.b_cruiseCtrlEna)) {
|
||||
inactivity_timeout_counter = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (inactivity_timeout_counter > (INACTIVITY_TIMEOUT * 60 * 1000) / (DELAY_IN_MAIN_LOOP + 1)) { // rest of main loop needs maybe 1ms
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Powering off, wheels were inactive for too long\r\n");
|
||||
#endif
|
||||
poweroff();
|
||||
}
|
||||
|
||||
|
116
Src/setup.c
116
Src/setup.c
@ -283,17 +283,21 @@ DMA_HandleTypeDef hdma_i2c2_tx;
|
||||
|
||||
void I2C_Init(void)
|
||||
{
|
||||
/* Initialise I2C2 GPIO pins
|
||||
* I2C2 GPIO Configuration
|
||||
* PB10 ------> I2C2_SCL
|
||||
* PB11 ------> I2C2_SDA
|
||||
*/
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* Initialise I2C peripheral */
|
||||
__HAL_RCC_I2C2_CLK_ENABLE();
|
||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||
|
||||
/* DMA1_Channel4_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 1, 4);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
|
||||
/* DMA1_Channel5_IRQn interrupt configuration */
|
||||
HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 1, 3);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
|
||||
|
||||
hi2c2.Instance = I2C2;
|
||||
hi2c2.Init.ClockSpeed = 200000;
|
||||
hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
|
||||
@ -303,65 +307,53 @@ void I2C_Init(void)
|
||||
hi2c2.Init.OwnAddress2 = 0;
|
||||
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
|
||||
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
|
||||
__HAL_RCC_I2C2_FORCE_RESET();
|
||||
__HAL_RCC_I2C2_RELEASE_RESET();
|
||||
HAL_I2C_Init(&hi2c2);
|
||||
|
||||
GPIO_InitTypeDef GPIO_InitStruct;
|
||||
/* Peripheral DMA init*/
|
||||
/* __HAL_RCC_DMA1_CLK_ENABLE();
|
||||
*/
|
||||
/* DMA1_Channel4_IRQn interrupt configuration */
|
||||
/* HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 1, 4);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);
|
||||
*/
|
||||
/* DMA1_Channel5_IRQn interrupt configuration */
|
||||
/* HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 1, 3);
|
||||
HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
|
||||
*/
|
||||
|
||||
__HAL_RCC_DMA1_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
/* USER CODE BEGIN I2C2_MspInit 0 */
|
||||
/* hdma_i2c2_rx.Instance = DMA1_Channel5;
|
||||
hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_i2c2_rx.Init.Mode = DMA_NORMAL;
|
||||
hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
|
||||
HAL_DMA_Init(&hdma_i2c2_rx);
|
||||
|
||||
/* USER CODE END I2C2_MspInit 0 */
|
||||
|
||||
/**I2C2 GPIO Configuration
|
||||
PB10 ------> I2C2_SCL
|
||||
PB11 ------> I2C2_SDA
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_I2C2_CLK_ENABLE();
|
||||
|
||||
/* Peripheral DMA init*/
|
||||
|
||||
hdma_i2c2_rx.Instance = DMA1_Channel5;
|
||||
hdma_i2c2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
hdma_i2c2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_i2c2_rx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_i2c2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_i2c2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_i2c2_rx.Init.Mode = DMA_NORMAL;
|
||||
hdma_i2c2_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
|
||||
HAL_DMA_Init(&hdma_i2c2_rx);
|
||||
|
||||
__HAL_LINKDMA(&hi2c2,hdmarx,hdma_i2c2_rx);
|
||||
|
||||
hdma_i2c2_tx.Instance = DMA1_Channel4;
|
||||
hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_i2c2_tx.Init.Mode = DMA_NORMAL;
|
||||
hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
|
||||
HAL_DMA_Init(&hdma_i2c2_tx);
|
||||
|
||||
__HAL_LINKDMA(&hi2c2,hdmatx,hdma_i2c2_tx);
|
||||
|
||||
/* Peripheral interrupt init */
|
||||
HAL_NVIC_SetPriority(I2C2_EV_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(I2C2_EV_IRQn);
|
||||
HAL_NVIC_SetPriority(I2C2_ER_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(I2C2_ER_IRQn);
|
||||
/* USER CODE BEGIN I2C2_MspInit 1 */
|
||||
|
||||
/* USER CODE END I2C2_MspInit 1 */
|
||||
__HAL_LINKDMA(&hi2c2,hdmarx,hdma_i2c2_rx);
|
||||
*/
|
||||
|
||||
/* hdma_i2c2_tx.Instance = DMA1_Channel4;
|
||||
hdma_i2c2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
hdma_i2c2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_i2c2_tx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_i2c2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_i2c2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_i2c2_tx.Init.Mode = DMA_NORMAL;
|
||||
hdma_i2c2_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
|
||||
HAL_DMA_Init(&hdma_i2c2_tx);
|
||||
|
||||
__HAL_LINKDMA(&hi2c2,hdmatx,hdma_i2c2_tx);
|
||||
*/
|
||||
/* Peripheral interrupt init */
|
||||
/* HAL_NVIC_SetPriority(I2C2_EV_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(I2C2_EV_IRQn);
|
||||
HAL_NVIC_SetPriority(I2C2_ER_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(I2C2_ER_IRQn);
|
||||
*/
|
||||
}
|
||||
|
||||
void MX_GPIO_Init(void) {
|
||||
|
210
Src/util.c
210
Src/util.c
@ -111,12 +111,6 @@ uint8_t ctrlModReq = CTRL_MOD_REQ; // Final control mode request
|
||||
LCD_PCF8574_HandleTypeDef lcd;
|
||||
#endif
|
||||
|
||||
#if defined(CONTROL_NUNCHUK) || defined(SUPPORT_NUNCHUK)
|
||||
uint8_t nunchuk_connected = 1;
|
||||
#else
|
||||
uint8_t nunchuk_connected = 0;
|
||||
#endif
|
||||
|
||||
#ifdef VARIANT_TRANSPOTTER
|
||||
float setDistance;
|
||||
uint16_t VirtAddVarTab[NB_OF_VAR] = {1337}; // Virtual address defined by the user: 0xFFFF value is prohibited
|
||||
@ -288,11 +282,6 @@ void Input_Init(void) {
|
||||
PWM_Init();
|
||||
#endif
|
||||
|
||||
#ifdef CONTROL_NUNCHUK
|
||||
I2C_Init();
|
||||
Nunchuk_Init();
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(CONTROL_SERIAL_USART2) || defined(FEEDBACK_SERIAL_USART2) || defined(SIDEBOARD_SERIAL_USART2)
|
||||
UART2_Init();
|
||||
#endif
|
||||
@ -314,6 +303,10 @@ void Input_Init(void) {
|
||||
EE_Init(); /* EEPROM Init */
|
||||
EE_ReadVariable(VirtAddVarTab[0], &writeCheck);
|
||||
if (writeCheck == FLASH_WRITE_KEY) {
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Using the configuration from EEprom\r\n");
|
||||
#endif
|
||||
|
||||
EE_ReadVariable(VirtAddVarTab[1] , &readVal); rtP_Left.i_max = rtP_Right.i_max = (int16_t)readVal;
|
||||
EE_ReadVariable(VirtAddVarTab[2] , &readVal); rtP_Left.n_max = rtP_Right.n_max = (int16_t)readVal;
|
||||
for (uint8_t i=0; i<INPUTS_NR; i++) {
|
||||
@ -325,8 +318,16 @@ void Input_Init(void) {
|
||||
EE_ReadVariable(VirtAddVarTab[ 8+8*i] , &readVal); input2[i].min = (int16_t)readVal;
|
||||
EE_ReadVariable(VirtAddVarTab[ 9+8*i] , &readVal); input2[i].mid = (int16_t)readVal;
|
||||
EE_ReadVariable(VirtAddVarTab[10+8*i] , &readVal); input2[i].max = (int16_t)readVal;
|
||||
|
||||
printf("Limits Input1: TYP:%i MIN:%i MID:%i MAX:%i\r\nLimits Input2: TYP:%i MIN:%i MID:%i MAX:%i\r\n",
|
||||
input1[i].typ, input1[i].min, input1[i].mid, input1[i].max,
|
||||
input2[i].typ, input2[i].min, input2[i].mid, input2[i].max);
|
||||
}
|
||||
} else {
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Using the configuration from config.h\r\n");
|
||||
#endif
|
||||
|
||||
for (uint8_t i=0; i<INPUTS_NR; i++) {
|
||||
if (input1[i].typDef == 3) { // If Input type defined is 3 (auto), identify the input type based on the values from config.h
|
||||
input1[i].typ = checkInputType(input1[i].min, input1[i].mid, input1[i].max);
|
||||
@ -338,6 +339,9 @@ void Input_Init(void) {
|
||||
} else {
|
||||
input2[i].typ = input2[i].typDef;
|
||||
}
|
||||
printf("Limits Input1: TYP:%i MIN:%i MID:%i MAX:%i\r\nLimits Input2: TYP:%i MIN:%i MID:%i MAX:%i\r\n",
|
||||
input1[i].typ, input1[i].min, input1[i].mid, input1[i].max,
|
||||
input2[i].typ, input2[i].min, input2[i].mid, input2[i].max);
|
||||
}
|
||||
}
|
||||
HAL_FLASH_Lock();
|
||||
@ -455,14 +459,25 @@ void beepShortMany(uint8_t cnt, int8_t dir) {
|
||||
|
||||
void calcAvgSpeed(void) {
|
||||
// Calculate measured average speed. The minus sign (-) is because motors spin in opposite directions
|
||||
#if !defined(INVERT_L_DIRECTION) && !defined(INVERT_R_DIRECTION)
|
||||
speedAvg = ( rtY_Left.n_mot - rtY_Right.n_mot) / 2;
|
||||
#elif !defined(INVERT_L_DIRECTION) && defined(INVERT_R_DIRECTION)
|
||||
speedAvg = ( rtY_Left.n_mot + rtY_Right.n_mot) / 2;
|
||||
#elif defined(INVERT_L_DIRECTION) && !defined(INVERT_R_DIRECTION)
|
||||
speedAvg = (-rtY_Left.n_mot - rtY_Right.n_mot) / 2;
|
||||
#elif defined(INVERT_L_DIRECTION) && defined(INVERT_R_DIRECTION)
|
||||
speedAvg = (-rtY_Left.n_mot + rtY_Right.n_mot) / 2;
|
||||
speedAvg = 0;
|
||||
#if defined(MOTOR_LEFT_ENA)
|
||||
#if defined(INVERT_L_DIRECTION)
|
||||
speedAvg -= rtY_Left.n_mot;
|
||||
#else
|
||||
speedAvg += rtY_Left.n_mot;
|
||||
#endif
|
||||
#endif
|
||||
#if defined(MOTOR_RIGHT_ENA)
|
||||
#if defined(INVERT_R_DIRECTION)
|
||||
speedAvg += rtY_Right.n_mot;
|
||||
#else
|
||||
speedAvg -= rtY_Right.n_mot;
|
||||
#endif
|
||||
|
||||
// Average only if both motors are enabled
|
||||
#if defined(MOTOR_LEFT_ENA)
|
||||
speedAvg /= 2;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Handle the case when SPEED_COEFFICIENT sign is negative (which is when most significant bit is 1)
|
||||
@ -532,16 +547,13 @@ void adcCalibLim(void) {
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Input1 is ");
|
||||
#endif
|
||||
input1[inIdx].typ = checkInputType(INPUT1_MIN_temp, INPUT1_MID_temp, INPUT1_MAX_temp);
|
||||
if (input1[inIdx].typ == input1[inIdx].typDef || input1[inIdx].typDef == 3) { // Accept calibration only if the type is correct OR type was set to 3 (auto)
|
||||
input1[inIdx].min = INPUT1_MIN_temp + input_margin;
|
||||
input1[inIdx].mid = INPUT1_MID_temp;
|
||||
input1[inIdx].max = INPUT1_MAX_temp - input_margin;
|
||||
uint8_t input1TypTemp = checkInputType(INPUT1_MIN_temp, INPUT1_MID_temp, INPUT1_MAX_temp);
|
||||
if (input1TypTemp == input1[inIdx].typDef || input1[inIdx].typDef == 3) { // Accept calibration only if the type is correct OR type was set to 3 (auto)
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("..OK\r\n");
|
||||
#endif
|
||||
} else {
|
||||
input1[inIdx].typ = 0; // Disable input
|
||||
input1TypTemp = 0; // Disable input
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("..NOK\r\n");
|
||||
#endif
|
||||
@ -550,26 +562,42 @@ void adcCalibLim(void) {
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Input2 is ");
|
||||
#endif
|
||||
input2[inIdx].typ = checkInputType(INPUT2_MIN_temp, INPUT2_MID_temp, INPUT2_MAX_temp);
|
||||
if (input2[inIdx].typ == input2[inIdx].typDef || input2[inIdx].typDef == 3) { // Accept calibration only if the type is correct OR type was set to 3 (auto)
|
||||
input2[inIdx].min = INPUT2_MIN_temp + input_margin;
|
||||
input2[inIdx].mid = INPUT2_MID_temp;
|
||||
input2[inIdx].max = INPUT2_MAX_temp - input_margin;
|
||||
uint8_t input2TypTemp = checkInputType(INPUT2_MIN_temp, INPUT2_MID_temp, INPUT2_MAX_temp);
|
||||
if (input2TypTemp == input2[inIdx].typDef || input2[inIdx].typDef == 3) { // Accept calibration only if the type is correct OR type was set to 3 (auto)
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("..OK\r\n");
|
||||
#endif
|
||||
} else {
|
||||
input2[inIdx].typ = 0; // Disable input
|
||||
input2TypTemp = 0; // Disable input
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("..NOK\r\n");
|
||||
#endif
|
||||
}
|
||||
inp_cal_valid = 1; // Mark calibration to be saved in Flash at shutdown
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Limits Input1: TYP:%i MIN:%i MID:%i MAX:%i\r\nLimits Input2: TYP:%i MIN:%i MID:%i MAX:%i\r\n",
|
||||
input1[inIdx].typ, input1[inIdx].min, input1[inIdx].mid, input1[inIdx].max,
|
||||
input2[inIdx].typ, input2[inIdx].min, input2[inIdx].mid, input2[inIdx].max);
|
||||
#endif
|
||||
|
||||
|
||||
// At least one of the inputs is not ignored
|
||||
if (input1TypTemp != 0 || input2TypTemp != 0){
|
||||
input1[inIdx].typ = input1TypTemp;
|
||||
input1[inIdx].min = INPUT1_MIN_temp + input_margin;
|
||||
input1[inIdx].mid = INPUT1_MID_temp;
|
||||
input1[inIdx].max = INPUT1_MAX_temp - input_margin;
|
||||
|
||||
input2[inIdx].typ = input2TypTemp;
|
||||
input2[inIdx].min = INPUT2_MIN_temp + input_margin;
|
||||
input2[inIdx].mid = INPUT2_MID_temp;
|
||||
input2[inIdx].max = INPUT2_MAX_temp - input_margin;
|
||||
|
||||
inp_cal_valid = 1; // Mark calibration to be saved in Flash at shutdown
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Limits Input1: TYP:%i MIN:%i MID:%i MAX:%i\r\nLimits Input2: TYP:%i MIN:%i MID:%i MAX:%i\r\n",
|
||||
input1[inIdx].typ, input1[inIdx].min, input1[inIdx].mid, input1[inIdx].max,
|
||||
input2[inIdx].typ, input2[inIdx].min, input2[inIdx].mid, input2[inIdx].max);
|
||||
#endif
|
||||
}else{
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Both inputs cannot be ignored, calibration rejected.\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // AUTO_CALIBRATION_ENA
|
||||
@ -813,8 +841,7 @@ void readInputRaw(void) {
|
||||
#endif
|
||||
|
||||
#if defined(CONTROL_NUNCHUK) || defined(SUPPORT_NUNCHUK)
|
||||
if (nunchuk_connected) {
|
||||
Nunchuk_Read();
|
||||
if (Nunchuk_Read() == NUNCHUK_CONNECTED) {
|
||||
if (inIdx == CONTROL_NUNCHUK) {
|
||||
input1[inIdx].raw = (nunchuk_data[0] - 127) * 8; // X axis 0-255
|
||||
input2[inIdx].raw = (nunchuk_data[1] - 128) * 8; // Y axis 0-255
|
||||
@ -1052,7 +1079,7 @@ void readCommand(void) {
|
||||
#endif
|
||||
|
||||
#if defined(CRUISE_CONTROL_SUPPORT) && (defined(SUPPORT_BUTTONS) || defined(SUPPORT_BUTTONS_LEFT) || defined(SUPPORT_BUTTONS_RIGHT))
|
||||
cruiseControl(button1); // Cruise control activation/deactivation
|
||||
cruiseControl(button1); // Cruise control activation/deactivation
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1070,16 +1097,16 @@ void usart2_rx_check(void)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_SERIAL_USART2)
|
||||
uint8_t ptr[SERIAL_BUFFER_SIZE];
|
||||
uint8_t ptr_debug[SERIAL_BUFFER_SIZE];
|
||||
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_L[old_pos], pos - old_pos); // Process data
|
||||
} else { // "Overflow" buffer mode
|
||||
memcpy(&ptr[0], &rx_buffer_L[old_pos], rx_buffer_L_len - old_pos); // First copy data from the end of buffer
|
||||
memcpy(&ptr_debug[0], &rx_buffer_L[old_pos], rx_buffer_L_len - old_pos); // First copy data from the end of buffer
|
||||
if (pos > 0) { // Check and continue with beginning of buffer
|
||||
memcpy(&ptr[rx_buffer_L_len - old_pos], &rx_buffer_L[0], pos); // Copy remaining data
|
||||
memcpy(&ptr_debug[rx_buffer_L_len - old_pos], &rx_buffer_L[0], pos); // Copy remaining data
|
||||
}
|
||||
usart_process_debug(ptr, rx_buffer_L_len - old_pos + pos); // Process data
|
||||
usart_process_debug(ptr_debug, rx_buffer_L_len - old_pos + pos); // Process data
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_SERIAL_USART2
|
||||
@ -1142,17 +1169,17 @@ void usart3_rx_check(void)
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_SERIAL_USART3)
|
||||
uint8_t ptr[SERIAL_BUFFER_SIZE];
|
||||
uint8_t ptr_debug[SERIAL_BUFFER_SIZE];
|
||||
|
||||
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_R[old_pos], pos - old_pos); // Process data
|
||||
} else { // "Overflow" buffer mode
|
||||
memcpy(&ptr[0], &rx_buffer_R[old_pos], rx_buffer_R_len - old_pos); // First copy data from the end of buffer
|
||||
memcpy(&ptr_debug[0], &rx_buffer_R[old_pos], rx_buffer_R_len - old_pos); // First copy data from the end of buffer
|
||||
if (pos > 0) { // Check and continue with beginning of buffer
|
||||
memcpy(&ptr[rx_buffer_R_len - old_pos], &rx_buffer_R[0], pos); // Copy remaining data
|
||||
memcpy(&ptr_debug[rx_buffer_R_len - old_pos], &rx_buffer_R[0], pos); // Copy remaining data
|
||||
}
|
||||
usart_process_debug(ptr, rx_buffer_R_len - old_pos + pos); // Process data
|
||||
usart_process_debug(ptr_debug, rx_buffer_R_len - old_pos + pos); // Process data
|
||||
}
|
||||
}
|
||||
#endif // DEBUG_SERIAL_USART3
|
||||
@ -1399,9 +1426,7 @@ void sideboardSensors(uint8_t sensors) {
|
||||
sensor1_prev = sensor1_index;
|
||||
} else { // Use Optical switches
|
||||
sensor1_trig = (sensors & SENSOR1_SET) && !sensor1_prev; // rising edge detection
|
||||
sensor2_trig = (sensors & SENSOR2_SET) && !sensor2_prev; // rising edge detection
|
||||
sensor1_prev = sensors & SENSOR1_SET;
|
||||
sensor2_prev = sensors & SENSOR2_SET;
|
||||
}
|
||||
|
||||
// Control MODE and Control Type Handling
|
||||
@ -1430,11 +1455,7 @@ void sideboardSensors(uint8_t sensors) {
|
||||
if (++sensor1_index > 4) { sensor1_index = 0; }
|
||||
}
|
||||
|
||||
#ifdef CRUISE_CONTROL_SUPPORT // Cruise Control Activation/Deactivation
|
||||
if (sensor2_trig) {
|
||||
cruiseControl(sensor2_trig);
|
||||
}
|
||||
#else // Field Weakening Activation/Deactivation
|
||||
// Field Weakening Activation/Deactivation
|
||||
static uint8_t sensor2_index = 1; // holds the press index number for sensor2, when used as a button
|
||||
|
||||
// Override in case the Sideboard control is Active
|
||||
@ -1445,25 +1466,33 @@ void sideboardSensors(uint8_t sensors) {
|
||||
sensor2_trig = 1;
|
||||
}
|
||||
sensor2_prev = sensor2_index;
|
||||
}else{
|
||||
sensor2_trig = (sensors & SENSOR2_SET) && !sensor2_prev; // rising edge detection
|
||||
sensor2_prev = sensors & SENSOR2_SET;
|
||||
}
|
||||
|
||||
if (sensor2_trig) {
|
||||
switch (sensor2_index) {
|
||||
case 0: // FW Disabled
|
||||
rtP_Left.b_fieldWeakEna = 0;
|
||||
rtP_Right.b_fieldWeakEna = 0;
|
||||
Input_Lim_Init();
|
||||
break;
|
||||
case 1: // FW Enabled
|
||||
rtP_Left.b_fieldWeakEna = 1;
|
||||
rtP_Right.b_fieldWeakEna = 1;
|
||||
Input_Lim_Init();
|
||||
break;
|
||||
#ifdef CRUISE_CONTROL_SUPPORT // Cruise Control Activation/Deactivation
|
||||
if (sensor2_trig) {
|
||||
cruiseControl(sensor2_trig);
|
||||
}
|
||||
if (inIdx == inIdx_prev) { beepShortMany(sensor2_index + 1, 1); }
|
||||
if (++sensor2_index > 1) { sensor2_index = 0; }
|
||||
}
|
||||
#endif // CRUISE_CONTROL_SUPPORT
|
||||
#else
|
||||
if (sensor2_trig) {
|
||||
switch (sensor2_index) {
|
||||
case 0: // FW Disabled
|
||||
rtP_Left.b_fieldWeakEna = 0;
|
||||
rtP_Right.b_fieldWeakEna = 0;
|
||||
Input_Lim_Init();
|
||||
break;
|
||||
case 1: // FW Enabled
|
||||
rtP_Left.b_fieldWeakEna = 1;
|
||||
rtP_Right.b_fieldWeakEna = 1;
|
||||
Input_Lim_Init();
|
||||
break;
|
||||
}
|
||||
if (inIdx == inIdx_prev) { beepShortMany(sensor2_index + 1, 1); }
|
||||
if (++sensor2_index > 1) { sensor2_index = 0; }
|
||||
}
|
||||
#endif // CRUISE_CONTROL_SUPPORT
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1485,6 +1514,10 @@ void saveConfig() {
|
||||
#endif
|
||||
#if !defined(VARIANT_HOVERBOARD) && !defined(VARIANT_TRANSPOTTER)
|
||||
if (inp_cal_valid || cur_spd_valid) {
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Saving configuration to EEprom\r\n");
|
||||
#endif
|
||||
|
||||
HAL_FLASH_Unlock();
|
||||
EE_WriteVariable(VirtAddVarTab[0] , (uint16_t)FLASH_WRITE_KEY);
|
||||
EE_WriteVariable(VirtAddVarTab[1] , (uint16_t)rtP_Left.i_max);
|
||||
@ -1525,12 +1558,14 @@ void poweroff(void) {
|
||||
void poweroffPressCheck(void) {
|
||||
#if !defined(VARIANT_HOVERBOARD) && !defined(VARIANT_TRANSPOTTER)
|
||||
if(HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN)) {
|
||||
enable = 0;
|
||||
uint16_t cnt_press = 0;
|
||||
while(HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN)) {
|
||||
HAL_Delay(10);
|
||||
if (cnt_press++ == 5 * 100) { beepShort(5); }
|
||||
}
|
||||
|
||||
if (cnt_press > 8) enable = 0;
|
||||
|
||||
if (cnt_press >= 5 * 100) { // Check if press is more than 5 sec
|
||||
HAL_Delay(1000);
|
||||
if (HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN)) { // Double press: Adjust Max Current, Max Speed
|
||||
@ -1546,7 +1581,10 @@ void poweroffPressCheck(void) {
|
||||
#endif
|
||||
}
|
||||
} else if (cnt_press > 8) { // Short press: power off (80 ms debounce)
|
||||
poweroff();
|
||||
#if defined(DEBUG_SERIAL_USART2) || defined(DEBUG_SERIAL_USART3)
|
||||
printf("Powering off, button has been pressed\r\n");
|
||||
#endif
|
||||
poweroff();
|
||||
}
|
||||
}
|
||||
#elif defined(VARIANT_TRANSPOTTER)
|
||||
@ -1646,22 +1684,22 @@ void rateLimiter16(int16_t u, int16_t rate, int16_t *y) {
|
||||
* Parameters: SPEED_COEFFICIENT, STEER_COEFFICIENT = fixdt(0,16,14)
|
||||
*/
|
||||
void mixerFcn(int16_t rtu_speed, int16_t rtu_steer, int16_t *rty_speedR, int16_t *rty_speedL) {
|
||||
int16_t prodSpeed;
|
||||
int16_t prodSteer;
|
||||
int32_t tmp;
|
||||
int16_t prodSpeed;
|
||||
int16_t prodSteer;
|
||||
int32_t tmp;
|
||||
|
||||
prodSpeed = (int16_t)((rtu_speed * (int16_t)SPEED_COEFFICIENT) >> 14);
|
||||
prodSteer = (int16_t)((rtu_steer * (int16_t)STEER_COEFFICIENT) >> 14);
|
||||
prodSpeed = (int16_t)((rtu_speed * (int16_t)SPEED_COEFFICIENT) >> 14);
|
||||
prodSteer = (int16_t)((rtu_steer * (int16_t)STEER_COEFFICIENT) >> 14);
|
||||
|
||||
tmp = prodSpeed - prodSteer;
|
||||
tmp = CLAMP(tmp, -32768, 32767); // Overflow protection
|
||||
*rty_speedR = (int16_t)(tmp >> 4); // Convert from fixed-point to int
|
||||
*rty_speedR = CLAMP(*rty_speedR, INPUT_MIN, INPUT_MAX);
|
||||
tmp = prodSpeed - prodSteer;
|
||||
tmp = CLAMP(tmp, -32768, 32767); // Overflow protection
|
||||
*rty_speedR = (int16_t)(tmp >> 4); // Convert from fixed-point to int
|
||||
*rty_speedR = CLAMP(*rty_speedR, INPUT_MIN, INPUT_MAX);
|
||||
|
||||
tmp = prodSpeed + prodSteer;
|
||||
tmp = CLAMP(tmp, -32768, 32767); // Overflow protection
|
||||
*rty_speedL = (int16_t)(tmp >> 4); // Convert from fixed-point to int
|
||||
*rty_speedL = CLAMP(*rty_speedL, INPUT_MIN, INPUT_MAX);
|
||||
tmp = prodSpeed + prodSteer;
|
||||
tmp = CLAMP(tmp, -32768, 32767); // Overflow protection
|
||||
*rty_speedL = (int16_t)(tmp >> 4); // Convert from fixed-point to int
|
||||
*rty_speedL = CLAMP(*rty_speedL, INPUT_MIN, INPUT_MAX);
|
||||
}
|
||||
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 234 KiB |
BIN
docs/pictures/wiki_unlock/download_build.png
Normal file
BIN
docs/pictures/wiki_unlock/download_build.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
Reference in New Issue
Block a user