Created
November 16, 2018 10:36
-
-
Save aurimasniekis/84fc5897492221fda36a69294338fddd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Only in Raptor2 Sources/bldc-firmware_2_80: .dep | |
Only in bldc-cc171422641a50c56452280575f2074f8a88aa45: .gitignore | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/Makefile Raptor2 Sources/bldc-firmware_2_80/Makefile | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/Makefile 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/Makefile 2016-09-19 10:07:06.000000000 +0100 | |
@@ -270,8 +270,8 @@ | |
# Program | |
upload: build/$(PROJECT).bin | |
#qstlink2 --cli --erase --write build/$(PROJECT).bin | |
- openocd -f interface/stlink-v2.cfg -c "set WORKAREASIZE 0x2000" -f target/stm32f4x_stlink.cfg -c "program build/$(PROJECT).elf verify reset" | |
- #openocd -f board/stm32f4discovery.cfg -c "reset_config trst_only combined" -c "program build/$(PROJECT).elf verify reset exit" # For openocd 0.9 | |
+ #openocd -f interface/stlink-v2.cfg -c "set WORKAREASIZE 0x2000" -f target/stm32f4x_stlink.cfg -c "program build/$(PROJECT).elf verify reset" # Older openocd | |
+ openocd -f board/stm32f4discovery.cfg -c "reset_config trst_only combined" -c "program build/$(PROJECT).elf verify reset exit" # For openocd 0.9 | |
#program with olimex arm-usb-tiny-h and jtag-swd adapter board. needs openocd>=0.9 | |
upload-olimex: build/$(PROJECT).bin | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/README.md Raptor2 Sources/bldc-firmware_2_80/README.md | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/README.md 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/README.md 2018-08-27 20:57:58.000000000 +0100 | |
@@ -1 +1,12 @@ | |
-This is the source code for my custom BLDC controller. A complete description and tutorial about how to use it can be found here: http://vedder.se/2015/01/vesc-open-source-esc/ | |
+A complete description and tutorial about how to use it can be found here: http://vedder.se/2015/01/vesc-open-source-esc/ | |
+ | |
+This is free software: you can redistribute it and/or modify | |
+it under the terms of the GNU General Public License as published by | |
+the Free Software Foundation, either version 3 of the License, or | |
+(at your option) any later version. | |
+The software is distributed in the hope that it will be useful, | |
+but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+GNU General Public License for more details. | |
+You should have received a copy of the GNU General Public License | |
+along with this program. If not, see <http://www.gnu.org/licenses | |
\ No newline at end of file | |
Only in Raptor2 Sources/bldc-firmware_2_80/appconf: appconf_custom.h | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/appconf/appconf_default.h Raptor2 Sources/bldc-firmware_2_80/appconf/appconf_default.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/appconf/appconf_default.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/appconf/appconf_default.h 2017-05-31 20:43:38.000000000 +0100 | |
@@ -26,36 +26,39 @@ | |
#define APPCONF_TIMEOUT_MSEC 1000 | |
#endif | |
#ifndef APPCONF_TIMEOUT_BRAKE_CURRENT | |
-#define APPCONF_TIMEOUT_BRAKE_CURRENT 0.0 | |
+#define APPCONF_TIMEOUT_BRAKE_CURRENT 0.0 | |
#endif | |
#ifndef APPCONF_SEND_CAN_STATUS | |
#define APPCONF_SEND_CAN_STATUS false | |
#endif | |
#ifndef APPCONF_SEND_CAN_STATUS_RATE_HZ | |
-#define APPCONF_SEND_CAN_STATUS_RATE_HZ 500 | |
+#define APPCONF_SEND_CAN_STATUS_RATE_HZ 500 | |
#endif | |
// The default app is UART in case the UART port is used for | |
// firmware updates. | |
#ifndef APPCONF_APP_TO_USE | |
-#define APPCONF_APP_TO_USE APP_UART | |
+#define APPCONF_APP_TO_USE APP_PPM_UART | |
#endif | |
// PPM app | |
#ifndef APPCONF_PPM_CTRL_TYPE | |
-#define APPCONF_PPM_CTRL_TYPE PPM_CTRL_TYPE_NONE | |
+#define APPCONF_PPM_CTRL_TYPE PPM_CTRL_TYPE_NONE //PPM_CTRL_TYPE_WATT_NOREV_BRAKE | |
#endif | |
#ifndef APPCONF_PPM_PID_MAX_ERPM | |
-#define APPCONF_PPM_PID_MAX_ERPM 15000 | |
+#define APPCONF_PPM_PID_MAX_ERPM 60000 | |
#endif | |
#ifndef APPCONF_PPM_HYST | |
-#define APPCONF_PPM_HYST 0.15 | |
+#define APPCONF_PPM_HYST 0.05 | |
#endif | |
#ifndef APPCONF_PPM_PULSE_START | |
-#define APPCONF_PPM_PULSE_START 1.0 | |
+#define APPCONF_PPM_PULSE_START 1.04 | |
+#endif | |
+#ifndef APPCONF_PPM_PULSE_CENTER | |
+#define APPCONF_PPM_PULSE_CENTER 1.54 | |
#endif | |
#ifndef APPCONF_PPM_PULSE_END | |
-#define APPCONF_PPM_PULSE_END 2.0 | |
+#define APPCONF_PPM_PULSE_END 2.04 | |
#endif | |
#ifndef APPCONF_PPM_MEDIAN_FILTER | |
#define APPCONF_PPM_MEDIAN_FILTER true | |
@@ -64,19 +67,77 @@ | |
#define APPCONF_PPM_SAFE_START true | |
#endif | |
#ifndef APPCONF_PPM_RPM_LIM_START | |
-#define APPCONF_PPM_RPM_LIM_START 150000 | |
+#define APPCONF_PPM_RPM_LIM_START 55000 | |
#endif | |
#ifndef APPCONF_PPM_RPM_LIM_END | |
-#define APPCONF_PPM_RPM_LIM_END 200000 | |
+#define APPCONF_PPM_RPM_LIM_END 60000 | |
#endif | |
#ifndef APPCONF_PPM_MULTI_ESC | |
-#define APPCONF_PPM_MULTI_ESC false | |
+#define APPCONF_PPM_MULTI_ESC true | |
#endif | |
#ifndef APPCONF_PPM_TC | |
-#define APPCONF_PPM_TC false | |
+#define APPCONF_PPM_TC true | |
#endif | |
#ifndef APPCONF_PPM_TC_MAX_DIFF | |
-#define APPCONF_PPM_TC_MAX_DIFF 3000.0 | |
+#define APPCONF_PPM_TC_MAX_DIFF 5000.0 | |
+#endif | |
+#ifndef APPCONF_PPM_TC_OFFSET | |
+#define APPCONF_PPM_TC_OFFSET 3000.0 | |
+#endif | |
+#ifndef APPCONF_PPM_MAX_ERPM_FOR_DIR_ACTIVE | |
+#define APPCONF_PPM_MAX_ERPM_FOR_DIR_ACTIVE true | |
+#endif | |
+#ifndef APPCONF_PPM_MAX_ERPM_FOR_DIR | |
+#define APPCONF_PPM_MAX_ERPM_FOR_DIR 4000.0 | |
+#endif | |
+ | |
+#ifndef APPCONF_ADJUSTABLE_THROTTLE_ENABLED | |
+#define APPCONF_ADJUSTABLE_THROTTLE_ENABLED true | |
+#endif | |
+#ifndef APPCONF_Y1_THROTTLE | |
+#define APPCONF_Y1_THROTTLE 0.08 | |
+#endif | |
+#ifndef APPCONF_Y2_THROTTLE | |
+#define APPCONF_Y2_THROTTLE 0.225 | |
+#endif | |
+#ifndef APPCONF_Y3_THROTTLE | |
+#define APPCONF_Y3_THROTTLE 0.50 | |
+#endif | |
+#ifndef APPCONF_X1_THROTTLE | |
+#define APPCONF_X1_THROTTLE 0.25 | |
+#endif | |
+#ifndef APPCONF_X2_THROTTLE | |
+#define APPCONF_X2_THROTTLE 0.50 | |
+#endif | |
+#ifndef APPCONF_X3_THROTTLE | |
+#define APPCONF_X3_THROTTLE 0.75 | |
+#endif | |
+ | |
+#ifndef APPCONF_BEZIER_REDUCE_FACTOR | |
+#define APPCONF_BEZIER_REDUCE_FACTOR 0 | |
+#endif | |
+ | |
+#ifndef APPCONF_Y1_NEG_THROTTLE | |
+#define APPCONF_Y1_NEG_THROTTLE 0.125 | |
+#endif | |
+#ifndef APPCONF_Y2_NEG_THROTTLE | |
+#define APPCONF_Y2_NEG_THROTTLE 0.30 | |
+#endif | |
+#ifndef APPCONF_Y3_NEG_THROTTLE | |
+#define APPCONF_Y3_NEG_THROTTLE 0.60 | |
+#endif | |
+#ifndef APPCONF_X1_NEG_THROTTLE | |
+#define APPCONF_X1_NEG_THROTTLE 0.25 | |
+#endif | |
+#ifndef APPCONF_X2_NEG_THROTTLE | |
+#define APPCONF_X2_NEG_THROTTLE 0.50 | |
+#endif | |
+#ifndef APPCONF_X3_NEG_THROTTLE | |
+#define APPCONF_X3_NEG_THROTTLE 0.75 | |
+#endif | |
+ | |
+#ifndef APPCONF_BEZIER_REDUCE_NEG_FACTOR | |
+#define APPCONF_BEZIER_REDUCE_NEG_FACTOR 0 | |
#endif | |
// ADC app configureation | |
@@ -84,7 +145,7 @@ | |
#define APPCONF_ADC_CTRL_TYPE ADC_CTRL_TYPE_NONE | |
#endif | |
#ifndef APPCONF_ADC_HYST | |
-#define APPCONF_ADC_HYST 0.15 | |
+#define APPCONF_ADC_HYST 0.15 | |
#endif | |
#ifndef APPCONF_ADC_VOLTAGE_START | |
#define APPCONF_ADC_VOLTAGE_START 0.9 | |
@@ -99,25 +160,25 @@ | |
#define APPCONF_ADC_SAFE_START true | |
#endif | |
#ifndef APPCONF_ADC_CC_BUTTON_INVERTED | |
-#define APPCONF_ADC_CC_BUTTON_INVERTED false | |
+#define APPCONF_ADC_CC_BUTTON_INVERTED false | |
#endif | |
#ifndef APPCONF_ADC_REV_BUTTON_INVERTED | |
-#define APPCONF_ADC_REV_BUTTON_INVERTED false | |
+#define APPCONF_ADC_REV_BUTTON_INVERTED false | |
#endif | |
#ifndef APPCONF_ADC_VOLTAGE_INVERTED | |
-#define APPCONF_ADC_VOLTAGE_INVERTED false | |
+#define APPCONF_ADC_VOLTAGE_INVERTED false | |
#endif | |
#ifndef APPCONF_ADC_RPM_LIM_START | |
-#define APPCONF_ADC_RPM_LIM_START 150000.0 | |
+#define APPCONF_ADC_RPM_LIM_START 2.0 | |
#endif | |
#ifndef APPCONF_ADC_RPM_LIM_END | |
-#define APPCONF_ADC_RPM_LIM_END 200000.0 | |
+#define APPCONF_ADC_RPM_LIM_END 80.0 | |
#endif | |
#ifndef APPCONF_ADC_MULTI_ESC | |
#define APPCONF_ADC_MULTI_ESC false | |
#endif | |
#ifndef APPCONF_ADC_TC | |
-#define APPCONF_ADC_TC false | |
+#define APPCONF_ADC_TC false | |
#endif | |
#ifndef APPCONF_ADC_TC_MAX_DIFF | |
#define APPCONF_ADC_TC_MAX_DIFF 3000.0 | |
@@ -128,7 +189,7 @@ | |
// UART app | |
#ifndef APPCONF_UART_BAUDRATE | |
-#define APPCONF_UART_BAUDRATE 115200 | |
+#define APPCONF_UART_BAUDRATE 9600 | |
#endif | |
// Nunchuk app | |
@@ -136,7 +197,7 @@ | |
#define APPCONF_CHUK_CTRL_TYPE CHUK_CTRL_TYPE_CURRENT | |
#endif | |
#ifndef APPCONF_CHUK_HYST | |
-#define APPCONF_CHUK_HYST 0.15 | |
+#define APPCONF_CHUK_HYST 0.15 | |
#endif | |
#ifndef APPCONF_CHUK_RPM_LIM_START | |
#define APPCONF_CHUK_RPM_LIM_START 150000.0 | |
@@ -151,16 +212,54 @@ | |
#define APPCONF_CHUK_RAMP_TIME_NEG 0.3 | |
#endif | |
#ifndef APPCONF_STICK_ERPM_PER_S_IN_CC | |
-#define APPCONF_STICK_ERPM_PER_S_IN_CC 3000.0 | |
+#define APPCONF_STICK_ERPM_PER_S_IN_CC 3000.0 | |
#endif | |
#ifndef APPCONF_CHUK_MULTI_ESC | |
#define APPCONF_CHUK_MULTI_ESC false | |
#endif | |
#ifndef APPCONF_CHUK_TC | |
-#define APPCONF_CHUK_TC false | |
+#define APPCONF_CHUK_TC false | |
#endif | |
#ifndef APPCONF_CHUK_TC_MAX_DIFF | |
-#define APPCONF_CHUK_TC_MAX_DIFF 3000.0 | |
+#define APPCONF_CHUK_TC_MAX_DIFF 5000.0 | |
+#endif | |
+#ifndef APPCONF_CHUK_TC_OFFSET | |
+#define APPCONF_CHUK_TC_OFFSET 3000.0 | |
+#endif | |
+#ifndef APPCONF_CHUK_BUTTONS_MIRRORED | |
+#define APPCONF_CHUK_BUTTONS_MIRRORED false | |
+#endif | |
+ | |
+// NRF app | |
+#ifndef APPCONF_NRF_SPEED | |
+#define APPCONF_NRF_SPEED NRF_SPEED_2M | |
+#endif | |
+#ifndef APPCONF_NRF_POWER | |
+#define APPCONF_NRF_POWER NRF_POWER_0DBM | |
+#endif | |
+#ifndef APPCONF_NRF_CRC | |
+#define APPCONF_NRF_CRC NRF_CRC_1B | |
+#endif | |
+#ifndef APPCONF_NRF_RETR_DELAY | |
+#define APPCONF_NRF_RETR_DELAY NRF_RETR_DELAY_250US | |
+#endif | |
+#ifndef APPCONF_NRF_RETRIES | |
+#define APPCONF_NRF_RETRIES 3 | |
+#endif | |
+#ifndef APPCONF_NRF_CHANNEL | |
+#define APPCONF_NRF_CHANNEL 76 | |
+#endif | |
+#ifndef APPCONF_NRF_ADDR_B0 | |
+#define APPCONF_NRF_ADDR_B0 0xC6 | |
+#endif | |
+#ifndef APPCONF_NRF_ADDR_B1 | |
+#define APPCONF_NRF_ADDR_B1 0xC7 | |
+#endif | |
+#ifndef APPCONF_NRF_ADDR_B2 | |
+#define APPCONF_NRF_ADDR_B2 0x0 | |
+#endif | |
+#ifndef APPCONF_NRF_SEND_CRC_ACK | |
+#define APPCONF_NRF_SEND_CRC_ACK true | |
#endif | |
#endif /* APPCONF_DEFAULT_H_ */ | |
Only in Raptor2 Sources/bldc-firmware_2_80/appconf: appconf_default_master.h | |
Only in Raptor2 Sources/bldc-firmware_2_80/appconf: appconf_default_slave.h | |
Only in bldc-cc171422641a50c56452280575f2074f8a88aa45/appconf: appconf_example_ppm.h | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app.c Raptor2 Sources/bldc-firmware_2_80/applications/app.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app.c 2016-11-16 19:08:14.000000000 +0000 | |
@@ -26,6 +26,7 @@ | |
#include "hal.h" | |
#include "hw.h" | |
#include "nrf_driver.h" | |
+#include "rfhelp.h" | |
// Private variables | |
static app_configuration appconf; | |
@@ -65,6 +66,7 @@ | |
case APP_NRF: | |
nrf_driver_init(); | |
+ rfhelp_restart(); | |
break; | |
case APP_CUSTOM: | |
@@ -92,8 +94,9 @@ | |
*/ | |
void app_set_configuration(app_configuration *conf) { | |
appconf = *conf; | |
- app_ppm_configure(&appconf.app_ppm_conf); | |
+ app_ppm_configure(&appconf.app_ppm_conf, &appconf.app_throttle_conf); | |
app_adc_configure(&appconf.app_adc_conf); | |
app_uartcomm_configure(appconf.app_uart_baudrate); | |
- app_nunchuk_configure(&appconf.app_chuk_conf); | |
+ app_nunchuk_configure(&appconf.app_chuk_conf, &appconf.app_throttle_conf); | |
+ rfhelp_update_conf(&appconf.app_nrf_conf); | |
} | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app.h Raptor2 Sources/bldc-firmware_2_80/applications/app.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app.h 2016-11-16 23:21:16.000000000 +0000 | |
@@ -34,15 +34,17 @@ | |
// Standard apps | |
void app_ppm_start(void); | |
-void app_ppm_configure(ppm_config *conf); | |
+void app_ppm_configure(ppm_config *conf, throttle_config *throt_config); | |
void app_adc_start(bool use_rx_tx); | |
void app_adc_configure(adc_config *conf); | |
float app_adc_get_decoded_level(void); | |
float app_adc_get_voltage(void); | |
+float app_adc_get_decoded_level2(void); | |
+float app_adc_get_voltage2(void); | |
void app_uartcomm_start(void); | |
void app_uartcomm_configure(uint32_t baudrate); | |
void app_nunchuk_start(void); | |
-void app_nunchuk_configure(chuk_config *conf); | |
+void app_nunchuk_configure(chuk_config *conf, throttle_config *throt_config); | |
float app_nunchuk_get_decoded_chuk(void); | |
void app_nunchuk_update_output(chuck_data *data); | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app_adc.c Raptor2 Sources/bldc-firmware_2_80/applications/app_adc.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app_adc.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app_adc.c 2016-09-19 10:07:22.000000000 +0100 | |
@@ -49,6 +49,8 @@ | |
static volatile float ms_without_power = 0; | |
static volatile float decoded_level = 0.0; | |
static volatile float read_voltage = 0.0; | |
+static volatile float decoded_level2 = 0.0; | |
+static volatile float read_voltage2 = 0.0; | |
static volatile bool use_rx_tx_as_buttons = false; | |
void app_adc_configure(adc_config *conf) { | |
@@ -69,6 +71,15 @@ | |
return read_voltage; | |
} | |
+float app_adc_get_decoded_level2(void) { | |
+ return decoded_level2; | |
+} | |
+ | |
+float app_adc_get_voltage2(void) { | |
+ return read_voltage2; | |
+} | |
+ | |
+ | |
static THD_FUNCTION(adc_thread, arg) { | |
(void)arg; | |
@@ -132,6 +143,46 @@ | |
decoded_level = pwr; | |
+ // Read the external ADC pin and convert the value to a voltage. | |
+#ifdef ADC_IND_EXT2 | |
+ float brake = (float)ADC_Value[ADC_IND_EXT2]; | |
+ brake /= 4095; | |
+ brake *= V_REG; | |
+#else | |
+ float brake = 0.0; | |
+#endif | |
+ | |
+ read_voltage2 = brake; | |
+ | |
+ // Optionally apply a mean value filter | |
+ if (config.use_filter) { | |
+ static float filter_buffer2[FILTER_SAMPLES]; | |
+ static int filter_ptr2 = 0; | |
+ | |
+ filter_buffer2[filter_ptr2++] = brake; | |
+ if (filter_ptr2 >= FILTER_SAMPLES) { | |
+ filter_ptr2 = 0; | |
+ } | |
+ | |
+ brake = 0.0; | |
+ for (int i = 0;i < FILTER_SAMPLES;i++) { | |
+ brake += filter_buffer2[i]; | |
+ } | |
+ brake /= FILTER_SAMPLES; | |
+ } | |
+ | |
+ // Map and truncate the read voltage | |
+ brake = utils_map(brake, config.voltage_start, config.voltage_end, 0.0, 1.0); | |
+ utils_truncate_number(&brake, 0.0, 1.0); | |
+ | |
+ // Optionally invert the read voltage | |
+ if (config.voltage_inverted) { | |
+ brake = 1.0 - brake; | |
+ } | |
+ | |
+ decoded_level2 = brake; | |
+ | |
+ | |
// Read the button pins | |
bool cc_button = false; | |
bool rev_button = false; | |
@@ -170,6 +221,13 @@ | |
pwr -= 1.0; | |
break; | |
+ case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_ADC: | |
+ if( brake > 0.01 ) { | |
+ pwr = -brake; | |
+ } | |
+ | |
+ break; | |
+ | |
case ADC_CTRL_TYPE_CURRENT_REV_BUTTON: | |
case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_BUTTON: | |
case ADC_CTRL_TYPE_DUTY_REV_BUTTON: | |
@@ -211,6 +269,7 @@ | |
case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_CENTER: | |
case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_BUTTON: | |
+ case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_ADC: | |
current_mode = true; | |
if (pwr >= 0.0) { | |
current = pwr * mcconf->l_current_max; | |
@@ -232,7 +291,7 @@ | |
} | |
if (!(ms_without_power < MIN_MS_WITHOUT_POWER && config.safe_start)) { | |
- mc_interface_set_duty(pwr); | |
+ mc_interface_set_duty(utils_map(pwr, -1.0, 1.0, -mcconf->l_max_duty, mcconf->l_max_duty)); | |
send_duty = true; | |
} | |
break; | |
@@ -249,6 +308,17 @@ | |
} | |
pulses_without_power_before = ms_without_power; | |
mc_interface_set_brake_current(timeout_get_brake_current()); | |
+ | |
+ if (config.multi_esc) { | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
+ comm_can_set_current_brake(msg->id, timeout_get_brake_current()); | |
+ } | |
+ } | |
+ } | |
+ | |
continue; | |
} | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app_nunchuk.c Raptor2 Sources/bldc-firmware_2_80/applications/app_nunchuk.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app_nunchuk.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app_nunchuk.c 2017-04-13 18:12:14.000000000 +0100 | |
@@ -53,10 +53,71 @@ | |
static volatile chuck_data chuck_d; | |
static volatile int chuck_error = 0; | |
static volatile chuk_config config; | |
+static volatile throttle_config throt_config; | |
+ | |
static volatile bool output_running = false; | |
-void app_nunchuk_configure(chuk_config *conf) { | |
+static float px[5]; | |
+static float py[5]; | |
+static float nx[5]; | |
+static float ny[5]; | |
+ | |
+float calculate_throttle_curve_chuk(float *x, float *y, float bezier_reduce_factor, float t) { | |
+ | |
+ float directSteps; | |
+ if (t < x[1]){ | |
+ directSteps = (y[1] / x[1] * t); | |
+ } else if (t > x[3]) { | |
+ directSteps = ((y[4] - y[3]) / (x[4] - x[3]) * (t-x[3]) + y[3]); | |
+ } else if (t > x[2]) { | |
+ directSteps = ((y[3] - y[2]) / (x[3] - x[2]) * (t-x[2]) + y[2]); | |
+ } else if (t > x[1]) { | |
+ directSteps = ((y[2] - y[1]) / (x[2] - x[1]) * (t-x[1]) + y[1]); | |
+ } else { // (throttle == x[1]) | |
+ directSteps = y[1]; | |
+ }; | |
+ | |
+ float f[5]; | |
+ for (int i = 0; i < 5; i++) f[i] = y[i]; | |
+ | |
+ for (int j = 1; j < 5; j++ ) | |
+ for (int i = 4; i >= j; i--) | |
+ f[i] = ( (t - x[i-j]) * f[i] - (t - x[i]) * f[i-1]) / (x[i] - x[i-j]); | |
+ | |
+ float spline = f[4] - ((f[4] - directSteps) * bezier_reduce_factor); | |
+ | |
+ // safety when stupid values are entered for x and y | |
+ if (spline > 1.0) return 1.0; | |
+ if (spline < 0.0) return 0.0; | |
+ | |
+ return spline; | |
+} | |
+ | |
+void app_nunchuk_configure(chuk_config *conf, throttle_config *throttle_conf) { | |
config = *conf; | |
+ throt_config = *throttle_conf; | |
+ | |
+ px[0] = 0.0; | |
+ px[1] = throt_config.x1_throttle; | |
+ px[2] = throt_config.x2_throttle; | |
+ px[3] = throt_config.x3_throttle; | |
+ px[4] = 1.0; | |
+ py[0] = 0.0; | |
+ py[1] = throt_config.y1_throttle; | |
+ py[2] = throt_config.y2_throttle; | |
+ py[3] = throt_config.y3_throttle; | |
+ py[4] = 1.0; | |
+ | |
+ nx[0] = 0.0; | |
+ nx[1] = throt_config.x1_neg_throttle; | |
+ nx[2] = throt_config.x2_neg_throttle; | |
+ nx[3] = throt_config.x3_neg_throttle; | |
+ nx[4] = 1.0; | |
+ ny[0] = 0.0; | |
+ ny[1] = throt_config.y1_neg_throttle; | |
+ ny[2] = throt_config.y2_neg_throttle; | |
+ ny[3] = throt_config.y3_neg_throttle; | |
+ ny[4] = 1.0; | |
} | |
void app_nunchuk_start(void) { | |
@@ -132,7 +193,7 @@ | |
} | |
if (is_ok) { | |
- static uint8_t last_buffer[10]; | |
+ static uint8_t last_buffer[6]; | |
int same = 1; | |
for (int i = 0;i < 6;i++) { | |
@@ -191,7 +252,7 @@ | |
continue; | |
} | |
- if (chuck_d.bt_z && !was_z && config.ctrl_type == CHUK_CTRL_TYPE_CURRENT && | |
+ if ((config.buttons_mirrored ? chuck_d.bt_c : chuck_d.bt_z) && !was_z && (config.ctrl_type == CHUK_CTRL_TYPE_CURRENT || config.ctrl_type == CHUK_CTRL_TYPE_WATT) && | |
fabsf(current_now) < MAX_CURR_DIFFERENCE) { | |
if (is_reverse) { | |
is_reverse = false; | |
@@ -200,12 +261,20 @@ | |
} | |
} | |
- was_z = chuck_d.bt_z; | |
+ was_z = config.buttons_mirrored ? chuck_d.bt_c : chuck_d.bt_z; | |
led_external_set_reversed(is_reverse); | |
float out_val = app_nunchuk_get_decoded_chuk(); | |
utils_deadband(&out_val, config.hyst, 1.0); | |
+ | |
+ if (throt_config.adjustable_throttle_enabled && out_val != 0.0){ | |
+ if (out_val > 0.0) { | |
+ out_val = calculate_throttle_curve_chuk(px, py, throt_config.bezier_reduce_factor, out_val); | |
+ } else { | |
+ out_val = -calculate_throttle_curve_chuk(nx, ny, throt_config.bezier_neg_reduce_factor, -out_val); | |
+ } | |
+ } | |
// LEDs | |
float x_axis = ((float)chuck_d.js_x - 128.0) / 128.0; | |
@@ -245,7 +314,7 @@ | |
} | |
rpm_filtered /= RPM_FILTER_SAMPLES; | |
- if (chuck_d.bt_c) { | |
+ if (config.buttons_mirrored ? chuck_d.bt_z : chuck_d.bt_c) { | |
static float pid_rpm = 0.0; | |
if (!was_pid) { | |
@@ -277,8 +346,21 @@ | |
} | |
} | |
- mc_interface_set_pid_speed(pid_rpm); | |
- | |
+ // NEW | |
+ switch (config.ctrl_type) { | |
+ case CHUK_CTRL_TYPE_CURRENT: | |
+ case CHUK_CTRL_TYPE_CURRENT_NOREV: | |
+ mc_interface_set_pid_speed(pid_rpm); | |
+ break; | |
+ case CHUK_CTRL_TYPE_WATT: | |
+ case CHUK_CTRL_TYPE_WATT_NOREV: | |
+ mc_interface_set_pid_speed(pid_rpm); | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ // END NEW | |
+ | |
// Send the same duty cycle to the other controllers | |
if (config.multi_esc) { | |
float duty = mc_interface_get_duty_cycle_now(); | |
@@ -302,12 +384,35 @@ | |
was_pid = false; | |
float current = 0; | |
- | |
- if (out_val >= 0.0) { | |
- current = out_val * mcconf->l_current_max; | |
- } else { | |
- current = out_val * fabsf(mcconf->l_current_min); | |
+ | |
+ // NEW | |
+ switch (config.ctrl_type) { | |
+ case CHUK_CTRL_TYPE_CURRENT: | |
+ case CHUK_CTRL_TYPE_CURRENT_NOREV: | |
+ if (out_val >= 0.0) { | |
+ current = out_val * mcconf->l_current_max; | |
+ } else { | |
+ current = out_val * fabsf(mcconf->l_current_min); | |
+ } | |
+ break; | |
+ case CHUK_CTRL_TYPE_WATT: | |
+ case CHUK_CTRL_TYPE_WATT_NOREV: | |
+ if (out_val >= 0.0) { | |
+ if (mcconf->use_max_watt_limit) { | |
+ current = utils_smallest_of_2(out_val * mcconf->l_current_max, | |
+ out_val * (mcconf->watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } else { | |
+ current = utils_smallest_of_2(out_val * mcconf->l_current_max, | |
+ out_val * mcconf->l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation()); | |
+ } | |
+ } else { | |
+ current = out_val * fabsf(mcconf->l_current_min); | |
+ } | |
+ break; | |
+ default: | |
+ break; | |
} | |
+ // END NEW | |
// Find lowest RPM and highest current | |
float rpm_local = mc_interface_get_rpm(); | |
@@ -334,7 +439,7 @@ | |
// Make the current directional | |
float msg_current = msg->current; | |
- if (msg->duty < 0.0) { | |
+ if (msg->duty < 0) { | |
msg_current = -msg_current; | |
} | |
@@ -344,12 +449,17 @@ | |
} | |
} | |
} | |
- | |
+ | |
// Apply ramping | |
const float current_range = mcconf->l_current_max + fabsf(mcconf->l_current_min); | |
const float ramp_time = fabsf(current) > fabsf(prev_current) ? config.ramp_time_pos : config.ramp_time_neg; | |
- | |
- if (ramp_time > 0.01) { | |
+ | |
+ if (ramp_time > 0.01 && current != 0.0) { | |
+ | |
+ if (prev_current * current < 0.0) { | |
+ prev_current = 0.0; | |
+ } | |
+ | |
const float ramp_step = ((float)OUTPUT_ITERATION_TIME_MS * current_range) / (ramp_time * 1000.0); | |
float current_goal = prev_current; | |
@@ -376,38 +486,55 @@ | |
current_goal = goal_tmp2; | |
} | |
+ out_val = out_val / current * current_goal; | |
+ | |
current = current_goal; | |
} | |
prev_current = current; | |
- | |
+ | |
if (current < 0.0) { | |
+ | |
mc_interface_set_brake_current(current); | |
- // Send brake command to all ESCs seen recently on the CAN bus | |
- for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
- can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ if (config.multi_esc) { | |
+ // Send brake command to all ESCs seen recently on the CAN bus | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
- if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
- comm_can_set_current_brake(msg->id, current); | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
+ if (config.ctrl_type == CHUK_CTRL_TYPE_WATT || config.ctrl_type == CHUK_CTRL_TYPE_WATT_NOREV) { | |
+ comm_can_set_brake_servo(msg->id, out_val); | |
+ } else { | |
+ comm_can_set_current_brake(msg->id, current); | |
+ } | |
+ } | |
} | |
} | |
} else { | |
+ | |
+ bool use_min_current = false; | |
// Apply soft RPM limit | |
- if (rpm_lowest > config.rpm_lim_end && current > 0.0) { | |
- current = mcconf->cc_min_current; | |
- } else if (rpm_lowest > config.rpm_lim_start && current > 0.0) { | |
- current = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, mcconf->cc_min_current); | |
- } else if (rpm_lowest < -config.rpm_lim_end && current < 0.0) { | |
- current = mcconf->cc_min_current; | |
- } else if (rpm_lowest < -config.rpm_lim_start && current < 0.0) { | |
- rpm_lowest = -rpm_lowest; | |
- current = -current; | |
- current = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, mcconf->cc_min_current); | |
- current = -current; | |
+ if (rpm_lowest > config.rpm_lim_end) { | |
+ if (out_val > 0.0) { | |
+ use_min_current = true; | |
+ out_val = 0.000001; // make sure min current ius used | |
+ } | |
+ if (current > 0.0) { | |
+ current = mcconf->cc_min_current; | |
+ } | |
+ } else if (rpm_lowest > config.rpm_lim_start) { | |
+ if (out_val > 0.0) { | |
+ use_min_current = true; | |
+ out_val = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, out_val, 0.000001); | |
+ } | |
+ if (current > 0.0) { | |
+ current = utils_highest_of_2(utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, 0.0), mcconf->cc_min_current); | |
+ } | |
} | |
float current_out = current; | |
+ float servo_val_out = out_val; | |
// Traction control | |
if (config.multi_esc) { | |
@@ -422,25 +549,39 @@ | |
} | |
float diff = rpm_tmp - rpm_lowest; | |
- current_out = utils_map(diff, 0.0, config.tc_max_diff, current, 0.0); | |
- if (current_out < mcconf->cc_min_current) { | |
- current_out = 0.0; | |
+ | |
+ if (diff > config.tc_offset) { | |
+ current_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, current, 0.0); | |
+ servo_val_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, out_val, 0.0); | |
+ } else { | |
+ current_out = current; | |
+ servo_val_out = out_val; | |
} | |
} | |
if (is_reverse) { | |
- comm_can_set_current(msg->id, -current_out); | |
+ if (config.ctrl_type == CHUK_CTRL_TYPE_WATT || config.ctrl_type == CHUK_CTRL_TYPE_WATT_NOREV) { | |
+ comm_can_set_servo(msg->id, -servo_val_out, use_min_current); | |
+ } else { | |
+ comm_can_set_current(msg->id, -current_out); | |
+ } | |
} else { | |
- comm_can_set_current(msg->id, current_out); | |
+ if (config.ctrl_type == CHUK_CTRL_TYPE_WATT || config.ctrl_type == CHUK_CTRL_TYPE_WATT_NOREV) { | |
+ comm_can_set_servo(msg->id, servo_val_out, use_min_current); | |
+ } else { | |
+ comm_can_set_current(msg->id, current_out); | |
+ } | |
} | |
} | |
} | |
if (config.tc) { | |
float diff = rpm_local - rpm_lowest; | |
- current_out = utils_map(diff, 0.0, config.tc_max_diff, current, 0.0); | |
- if (current_out < mcconf->cc_min_current) { | |
- current_out = 0.0; | |
+ | |
+ if (diff > config.tc_offset) { | |
+ current_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, current, 0.0); | |
+ } else { | |
+ current_out = current; | |
} | |
} | |
} | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app_ppm.c Raptor2 Sources/bldc-firmware_2_80/applications/app_ppm.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app_ppm.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app_ppm.c 2017-04-13 18:12:22.000000000 +0100 | |
@@ -26,6 +26,7 @@ | |
#include "ch.h" | |
#include "hal.h" | |
+#include "hw.h" | |
#include "stm32f4xx_conf.h" | |
#include "servo_dec.h" | |
#include "mc_interface.h" | |
@@ -33,13 +34,15 @@ | |
#include "utils.h" | |
#include "comm_can.h" | |
#include <math.h> | |
+//#include "commands.h" | |
// Only available if servo output is not active | |
#if !SERVO_OUT_ENABLE | |
// Settings | |
-#define MAX_CAN_AGE 0.1 | |
-#define MIN_PULSES_WITHOUT_POWER 50 | |
+#define MAX_CAN_AGE 0.1 | |
+#define MIN_PULSES_WITHOUT_POWER 50 | |
+#define RPM_FILTER_SAMPLES 8 | |
// Threads | |
static THD_FUNCTION(ppm_thread, arg); | |
@@ -52,21 +55,96 @@ | |
// Private variables | |
static volatile bool is_running = false; | |
+static volatile float pid_rpm = 0; | |
+//static volatile int mode_switch_pulses = 0; | |
static volatile ppm_config config; | |
+static volatile throttle_config throt_config; | |
static volatile int pulses_without_power = 0; | |
+//static volatile int count = 0; | |
+ | |
+static volatile float filter_buffer[RPM_FILTER_SAMPLES]; | |
+static volatile int filter_ptr = 0; | |
+static volatile bool has_enough_pid_filter_data = false; | |
+static volatile float direction_hyst = 0; | |
+ | |
+static float px[5]; | |
+static float py[5]; | |
+static float nx[5]; | |
+static float ny[5]; | |
+ | |
// Private functions | |
static void update(void *p); | |
#endif | |
-void app_ppm_configure(ppm_config *conf) { | |
+float calculate_throttle_curve_ppm(float *x, float *y, float bezier_reduce_factor, float t) { | |
+ | |
+ float directSteps; | |
+ if (t < x[1]){ | |
+ directSteps = (y[1] / x[1] * t); | |
+ } else if (t > x[3]) { | |
+ directSteps = ((y[4] - y[3]) / (x[4] - x[3]) * (t-x[3]) + y[3]); | |
+ } else if (t > x[2]) { | |
+ directSteps = ((y[3] - y[2]) / (x[3] - x[2]) * (t-x[2]) + y[2]); | |
+ } else if (t > x[1]) { | |
+ directSteps = ((y[2] - y[1]) / (x[2] - x[1]) * (t-x[1]) + y[1]); | |
+ } else { // (throttle == x[1]) | |
+ directSteps = y[1]; | |
+ }; | |
+ | |
+ float f[5]; | |
+ for (int i = 0; i < 5; i++) f[i] = y[i]; | |
+ | |
+ for (int j = 1; j < 5; j++ ) | |
+ for (int i = 4; i >= j; i--) | |
+ f[i] = ( (t - x[i-j]) * f[i] - (t - x[i]) * f[i-1]) / (x[i] - x[i-j]); | |
+ | |
+ float spline = f[4] - ((f[4] - directSteps) * bezier_reduce_factor); | |
+ | |
+ // safety when stupid values are entered for x and y | |
+ if (spline > 1.0) return 1.0; | |
+ if (spline < 0.0) return 0.0; | |
+ | |
+ return spline; | |
+} | |
+ | |
+void app_ppm_configure(ppm_config *conf, throttle_config *throttle_conf) { | |
#if !SERVO_OUT_ENABLE | |
config = *conf; | |
+ throt_config = *throttle_conf; | |
pulses_without_power = 0; | |
+ | |
+ has_enough_pid_filter_data = false; | |
+ filter_ptr = 0; | |
+ mc_interface_set_cruise_control_status(CRUISE_CONTROL_INACTIVE); | |
if (is_running) { | |
- servodec_set_pulse_options(config.pulse_start, config.pulse_end, config.median_filter); | |
+ servodec_set_pulse_options(config.pulse_start, config.pulse_center, config.pulse_end, config.median_filter); | |
} | |
+ | |
+ px[0] = 0.0; | |
+ px[1] = throt_config.x1_throttle; | |
+ px[2] = throt_config.x2_throttle; | |
+ px[3] = throt_config.x3_throttle; | |
+ px[4] = 1.0; | |
+ py[0] = 0.0; | |
+ py[1] = throt_config.y1_throttle; | |
+ py[2] = throt_config.y2_throttle; | |
+ py[3] = throt_config.y3_throttle; | |
+ py[4] = 1.0; | |
+ | |
+ nx[0] = 0.0; | |
+ nx[1] = throt_config.x1_neg_throttle; | |
+ nx[2] = throt_config.x2_neg_throttle; | |
+ nx[3] = throt_config.x3_neg_throttle; | |
+ nx[4] = 1.0; | |
+ ny[0] = 0.0; | |
+ ny[1] = throt_config.y1_neg_throttle; | |
+ ny[2] = throt_config.y2_neg_throttle; | |
+ ny[3] = throt_config.y3_neg_throttle; | |
+ ny[4] = 1.0; | |
+ | |
+ direction_hyst = config.max_erpm_for_dir * 0.20; | |
#else | |
(void)conf; | |
#endif | |
@@ -103,8 +181,9 @@ | |
chRegSetThreadName("APP_PPM"); | |
ppm_tp = chThdGetSelfX(); | |
- servodec_set_pulse_options(config.pulse_start, config.pulse_end, config.median_filter); | |
+ servodec_set_pulse_options(config.pulse_start, config.pulse_center, config.pulse_end, config.median_filter); | |
servodec_init(servodec_func); | |
+ | |
is_running = true; | |
for(;;) { | |
@@ -124,26 +203,99 @@ | |
case PPM_CTRL_TYPE_PID_NOREV: | |
servo_val += 1.0; | |
servo_val /= 2.0; | |
+ | |
+ utils_deadband(&servo_val, config.hyst, 1.0); | |
+ | |
+ servo_val = calculate_throttle_curve_ppm(px, py, throt_config.bezier_reduce_factor, servo_val); | |
+ | |
+ break; | |
+ //case PPM_CTRL_TYPE_CURRENT: | |
+ case PPM_CTRL_TYPE_WATT: | |
+ utils_deadband(&servo_val, config.hyst, 1.0); | |
+ | |
+ if (throt_config.adjustable_throttle_enabled && servo_val != 0.0){ | |
+ if (servo_val > 0.0) { | |
+ servo_val = calculate_throttle_curve_ppm(px, py, throt_config.bezier_reduce_factor, servo_val); | |
+ } else if (config.max_erpm_for_dir_active == false) { | |
+ servo_val = -calculate_throttle_curve_ppm(nx, ny, throt_config.bezier_neg_reduce_factor, -servo_val); | |
+ } | |
+ } | |
break; | |
- | |
default: | |
+ | |
+ utils_deadband(&servo_val, config.hyst, 1.0); | |
+ | |
+ if (throt_config.adjustable_throttle_enabled && servo_val != 0.0){ | |
+ if (servo_val > 0.0) { | |
+ servo_val = calculate_throttle_curve_ppm(px, py, throt_config.bezier_reduce_factor, servo_val); | |
+ } else { | |
+ servo_val = -calculate_throttle_curve_ppm(nx, ny, throt_config.bezier_neg_reduce_factor, -servo_val); | |
+ } | |
+ } | |
+ | |
break; | |
} | |
- utils_deadband(&servo_val, config.hyst, 1.0); | |
- | |
float current = 0; | |
+ //float desired_watt = 0; | |
bool current_mode = false; | |
bool current_mode_brake = false; | |
const volatile mc_configuration *mcconf = mc_interface_get_configuration(); | |
bool send_duty = false; | |
+ //bool send_watt = false; | |
+ bool send_pid = false; | |
+ | |
+ // Find lowest RPM and cruise control | |
+ float rpm_local = mc_interface_get_rpm(); | |
+ float rpm_lowest = rpm_local; | |
+ float mid_rpm = rpm_local; | |
+ int motor_count = 1; | |
+ ppm_cruise cruise_control_status = CRUISE_CONTROL_INACTIVE; | |
+ if (config.multi_esc) { | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
+ // add to middle rpm count | |
+ mid_rpm += msg->rpm; | |
+ motor_count += 1; | |
+ if (fabsf(msg->rpm) < fabsf(rpm_lowest)) { | |
+ rpm_lowest = msg->rpm; | |
+ } | |
+ | |
+ // if any controller (VESC) sends the cruise contol status | |
+ if (msg->cruise_control_status != CRUISE_CONTROL_INACTIVE) { | |
+ cruise_control_status = msg->cruise_control_status; | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ // get middle rpm | |
+ mid_rpm /= motor_count; | |
+ | |
switch (config.ctrl_type) { | |
case PPM_CTRL_TYPE_CURRENT: | |
- case PPM_CTRL_TYPE_CURRENT_NOREV: | |
current_mode = true; | |
if (servo_val >= 0.0) { | |
- current = servo_val * mcconf->l_current_max; | |
+ // check of can bus send cruise control command | |
+ if (cruise_control_status != CRUISE_CONTROL_INACTIVE && servo_val == 0.0) { | |
+ // is rpm in range for cruise control | |
+ if (rpm_lowest > mcconf->s_pid_min_erpm) { | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = rpm_lowest; | |
+ } | |
+ current_mode = false; | |
+ send_pid = true; | |
+ mc_interface_set_pid_speed_with_cruise_status(rpm_local + pid_rpm - mid_rpm, cruise_control_status); | |
+ } else { | |
+ pid_rpm = 0; | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ current = servo_val * mcconf->l_current_max; | |
+ } | |
} else { | |
current = servo_val * fabsf(mcconf->l_current_min); | |
} | |
@@ -152,21 +304,294 @@ | |
pulses_without_power++; | |
} | |
break; | |
- | |
+ case PPM_CTRL_TYPE_CURRENT_NOREV: | |
case PPM_CTRL_TYPE_CURRENT_NOREV_BRAKE: | |
current_mode = true; | |
+ | |
if (servo_val >= 0.0) { | |
- current = servo_val * mcconf->l_current_max; | |
+ // check of can bus send cruise control command | |
+ if (cruise_control_status != CRUISE_CONTROL_INACTIVE && servo_val == 0.0) { | |
+ // is rpm in range for cruise control | |
+ if (rpm_lowest > mcconf->s_pid_min_erpm) { | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = rpm_lowest; | |
+ } | |
+ current_mode = false; | |
+ send_pid = true; | |
+ mc_interface_set_pid_speed_with_cruise_status(rpm_local + pid_rpm - mid_rpm, cruise_control_status); | |
+ } else { | |
+ pid_rpm = 0; | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ current = servo_val * mcconf->l_current_max; | |
+ } | |
+ | |
} else { | |
current = fabsf(servo_val * mcconf->l_current_min); | |
current_mode_brake = true; | |
} | |
+ if (servo_val < 0.001) { | |
+ pulses_without_power++; | |
+ } | |
+ break; | |
+ case PPM_CTRL_TYPE_WATT: | |
+ current_mode = true; | |
+ | |
+ if (config.max_erpm_for_dir_active) { // advanced backwards | |
+ static bool force_brake = true; | |
+ | |
+ static int8_t did_idle_once = 0; | |
+ | |
+ // Hysteresis 20 % of actual RPM | |
+ if (force_brake) { | |
+ if (rpm_local < config.max_erpm_for_dir - direction_hyst) { // for 2500 it's 2000 | |
+ force_brake = false; | |
+ did_idle_once = 0; | |
+ } | |
+ } else { | |
+ if (rpm_local > config.max_erpm_for_dir + direction_hyst) { // for 2500 it's 3000 | |
+ force_brake = true; | |
+ did_idle_once = 0; | |
+ } | |
+ } | |
+ | |
+ if (servo_val >= 0.0) { | |
+ if (servo_val == 0.0) { | |
+ // if there was a idle in between then allow going backwards | |
+ if (did_idle_once == 1 && !force_brake) { | |
+ did_idle_once = 2; | |
+ } | |
+ }else{ | |
+ // accelerated forward or fast enough at least | |
+ if (rpm_local > -config.max_erpm_for_dir){ // for 2500 it's -2500 | |
+ did_idle_once = 0; | |
+ } | |
+ } | |
+ | |
+ // check of can bus send cruise control command | |
+ if (cruise_control_status != CRUISE_CONTROL_INACTIVE && servo_val == 0.0) { | |
+ // is rpm in range for cruise control | |
+ if (fabsf(rpm_lowest) > mcconf->s_pid_min_erpm) { | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = mid_rpm; | |
+ } | |
+ current_mode = false; | |
+ send_pid = true; | |
+ | |
+ mc_interface_set_pid_speed_with_cruise_status(rpm_local + pid_rpm - mid_rpm, cruise_control_status); | |
+ } else { | |
+ pid_rpm = 0; | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ if (mcconf->use_max_watt_limit) { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * (mcconf->watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } else { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * mcconf->l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation()); | |
+ } | |
+ } | |
+ } else { | |
+ | |
+ // too fast | |
+ if (force_brake){ | |
+ current_mode_brake = true; | |
+ }else{ | |
+ // not too fast backwards | |
+ if (rpm_local > -config.max_erpm_for_dir) { // for 2500 it's -2500 | |
+ // first time that we brake and we are not too fast | |
+ if (did_idle_once != 2) { | |
+ did_idle_once = 1; | |
+ current_mode_brake = true; | |
+ } | |
+ // too fast backwards | |
+ } else { | |
+ // if brake was active already | |
+ if (did_idle_once == 1) { | |
+ current_mode_brake = true; | |
+ } else { | |
+ // it's ok to go backwards now braking would be strange now | |
+ did_idle_once = 2; | |
+ } | |
+ } | |
+ } | |
+ | |
+ if (current_mode_brake) { | |
+ // braking | |
+ if (throt_config.adjustable_throttle_enabled) { | |
+ // negative calculation | |
+ servo_val = -calculate_throttle_curve_ppm(nx, ny, throt_config.bezier_neg_reduce_factor, -servo_val); | |
+ } | |
+ current = fabsf(servo_val * mcconf->l_current_min); | |
+ }else { | |
+ // reverse acceleration | |
+ if (throt_config.adjustable_throttle_enabled) { | |
+ // positive calculation | |
+ servo_val = -calculate_throttle_curve_ppm(px, py, throt_config.bezier_reduce_factor, -servo_val); | |
+ } | |
+ | |
+ if (mcconf->use_max_watt_limit) { | |
+ current = -utils_smallest_of_2(fabsf(servo_val * mcconf->l_current_min), | |
+ fabsf(servo_val * (mcconf->watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation()))); | |
+ } else { | |
+ current = -utils_smallest_of_2(fabsf(servo_val * mcconf->l_current_min), | |
+ fabsf(servo_val * mcconf->l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } | |
+ } | |
+ } | |
+ } else { // normal backwards | |
+ if (servo_val >= 0.0) { | |
+ // check of can bus send cruise control command | |
+ if (cruise_control_status != CRUISE_CONTROL_INACTIVE && servo_val == 0.0) { | |
+ // is rpm in range for cruise control | |
+ if (fabsf(rpm_lowest) > mcconf->s_pid_min_erpm) { | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = mid_rpm; | |
+ } | |
+ current_mode = false; | |
+ send_pid = true; | |
+ | |
+ mc_interface_set_pid_speed_with_cruise_status(rpm_local + pid_rpm - mid_rpm, cruise_control_status); | |
+ } else { | |
+ pid_rpm = 0; | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ if (mcconf->use_max_watt_limit) { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * (mcconf->watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } else { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * mcconf->l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation()); | |
+ } | |
+ } | |
+ } else { | |
+ current = servo_val * fabsf(mcconf->l_current_min); | |
+ } | |
+ } | |
if (servo_val < 0.001) { | |
pulses_without_power++; | |
} | |
break; | |
+ case PPM_CTRL_TYPE_WATT_NOREV_BRAKE: | |
+ current_mode = true; | |
+ | |
+ if (servo_val >= 0.0) { | |
+ // check of can bus send cruise control command | |
+ if (cruise_control_status != CRUISE_CONTROL_INACTIVE && servo_val == 0.0) { | |
+ // is rpm in range for cruise control | |
+ if (rpm_lowest > mcconf->s_pid_min_erpm) { | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = mid_rpm; | |
+ } | |
+ current_mode = false; | |
+ send_pid = true; | |
+ mc_interface_set_pid_speed_with_cruise_status(rpm_local + pid_rpm - mid_rpm, cruise_control_status); | |
+ | |
+ } else { | |
+ pid_rpm = 0; | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ if (mcconf->use_max_watt_limit) { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * (mcconf->watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } else { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * mcconf->l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation()); | |
+ } | |
+ } | |
+ } else { | |
+ | |
+ current_mode_brake = true; | |
+ | |
+ // brake as in current mode if not enabled. Calculating via Battery Voltage would brake far too hard | |
+ current = fabsf(servo_val * mcconf->l_current_min); | |
+ } | |
+ if (servo_val < 0.001) { | |
+ pulses_without_power++; | |
+ } | |
+ break; | |
+ case PPM_CTRL_TYPE_PID_NOACCELERATION: | |
+ current_mode = true; | |
+ | |
+ filter_buffer[filter_ptr++] = mid_rpm; | |
+ if (filter_ptr >= RPM_FILTER_SAMPLES) { | |
+ filter_ptr = 0; | |
+ has_enough_pid_filter_data = true; | |
+ } | |
+ | |
+ float rpm_filtered = 0.0; | |
+ // only send when enough values are collected | |
+ if (has_enough_pid_filter_data) { | |
+ for (int i = 0; i < RPM_FILTER_SAMPLES; i++) { | |
+ rpm_filtered += filter_buffer[i]; | |
+ } | |
+ rpm_filtered /= RPM_FILTER_SAMPLES; | |
+ } | |
+ | |
+ if (servo_val >= 0.0) { | |
+ // check if pid needs to be lowered | |
+ if (servo_val > 0.0) { | |
+ // needs to be set first ? | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = rpm_filtered; | |
+ } | |
+ | |
+ if(rpm_filtered > 1000){ | |
+ float diff = pid_rpm - rpm_filtered; | |
+ if (diff > 1500) { | |
+ pid_rpm = pid_rpm - 10; | |
+ }else if(diff > 500 && rpm_filtered < 1500) { | |
+ pid_rpm = pid_rpm - 10; | |
+ } | |
+ }else{ | |
+ pid_rpm = 0; | |
+ } | |
+ | |
+ // if not too slow than set the pid | |
+ if(pid_rpm > 0 && pid_rpm < config.pid_max_erpm) { | |
+ current_mode = false; | |
+ | |
+ send_pid = true; | |
+ mc_interface_set_pid_speed(rpm_local + pid_rpm - rpm_filtered); | |
+ | |
+ // overwrite mid_rpm | |
+ mid_rpm = rpm_filtered; | |
+ } else { | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ current = 0.0; | |
+ } | |
+ } else { | |
+ current = fabsf(servo_val * mcconf->l_current_min); | |
+ current_mode_brake = true; | |
+ } | |
+ | |
+ if (servo_val < 0.001) { | |
+ pulses_without_power++; | |
+ } | |
+ break; | |
+ case PPM_CTRL_TYPE_CRUISE_CONTROL_SECONDARY_CHANNEL: | |
+ if (servo_val < -0.3 && config.cruise_left != CRUISE_CONTROL_INACTIVE) { | |
+ mc_interface_set_cruise_control_status(config.cruise_left); | |
+ } else if (servo_val > 0.3 && config.cruise_right != CRUISE_CONTROL_INACTIVE) { | |
+ mc_interface_set_cruise_control_status(config.cruise_right); | |
+ } else { | |
+ mc_interface_set_cruise_control_status(CRUISE_CONTROL_INACTIVE); | |
+ } | |
+ // Run this loop at 500Hz | |
+ chThdSleepMilliseconds(2); | |
+ | |
+ // Reset the timeout | |
+ //timeout_reset(); | |
+ continue; | |
+ break; | |
case PPM_CTRL_TYPE_DUTY: | |
case PPM_CTRL_TYPE_DUTY_NOREV: | |
if (fabsf(servo_val) < 0.001) { | |
@@ -174,7 +599,7 @@ | |
} | |
if (!(pulses_without_power < MIN_PULSES_WITHOUT_POWER && config.safe_start)) { | |
- mc_interface_set_duty(servo_val); | |
+ mc_interface_set_duty(utils_map(servo_val, -1.0, 1.0, -mcconf->l_max_duty, mcconf->l_max_duty)); | |
send_duty = true; | |
} | |
break; | |
@@ -194,6 +619,17 @@ | |
default: | |
continue; | |
} | |
+ | |
+ // switch the mode | |
+ /*if (servo_val == -1.0){ | |
+ mode_switch_pulses++; | |
+ }else{ | |
+ if (mode_switch_pulses > 1000){ | |
+ //switch mode | |
+ //mc_interface_change_speed_mode(); // ??? | |
+ } | |
+ mode_switch_pulses = 0; | |
+ }*/ | |
if (pulses_without_power < MIN_PULSES_WITHOUT_POWER && config.safe_start) { | |
static int pulses_without_power_before = 0; | |
@@ -205,69 +641,99 @@ | |
continue; | |
} | |
- // Find lowest RPM | |
- float rpm_local = mc_interface_get_rpm(); | |
- float rpm_lowest = rpm_local; | |
- if (config.multi_esc) { | |
+ if (send_duty && config.multi_esc) { | |
+ float duty = mc_interface_get_duty_cycle_now(); | |
+ | |
for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
can_status_msg *msg = comm_can_get_status_msg_index(i); | |
if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
- float rpm_tmp = msg->rpm; | |
- | |
- if (fabsf(rpm_tmp) < fabsf(rpm_lowest)) { | |
- rpm_lowest = rpm_tmp; | |
- } | |
+ comm_can_set_duty(msg->id, duty); | |
} | |
} | |
} | |
- if (send_duty && config.multi_esc) { | |
- float duty = mc_interface_get_duty_cycle_now(); | |
- | |
+ if (send_pid && config.multi_esc) { | |
+ | |
for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
can_status_msg *msg = comm_can_get_status_msg_index(i); | |
if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
- comm_can_set_duty(msg->id, duty); | |
+ comm_can_set_rpm(msg->id, msg->rpm + pid_rpm - mid_rpm, cruise_control_status); | |
} | |
} | |
} | |
if (current_mode) { | |
+ | |
+ pid_rpm = 0; // always reset in current, not that something stupid happens | |
+ | |
if (current_mode_brake) { | |
mc_interface_set_brake_current(current); | |
- // Send brake command to all ESCs seen recently on the CAN bus | |
- for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
- can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ if (config.multi_esc) { | |
+ // Send brake command to all ESCs seen recently on the CAN bus | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
- if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
- comm_can_set_current_brake(msg->id, current); | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
+ if (config.ctrl_type == PPM_CTRL_TYPE_WATT_NOREV_BRAKE || config.ctrl_type == PPM_CTRL_TYPE_WATT) { | |
+ comm_can_set_brake_servo(msg->id, fabsf(servo_val)); | |
+ } else { | |
+ comm_can_set_current_brake(msg->id, current); | |
+ } | |
+ } | |
} | |
} | |
} else { | |
// Apply soft RPM limit | |
- if (rpm_lowest > config.rpm_lim_end && current > 0.0) { | |
- current = mcconf->cc_min_current; | |
- } else if (rpm_lowest > config.rpm_lim_start && current > 0.0) { | |
- current = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, mcconf->cc_min_current); | |
- } else if (rpm_lowest < -config.rpm_lim_end && current < 0.0) { | |
- current = mcconf->cc_min_current; | |
- } else if (rpm_lowest < -config.rpm_lim_start && current < 0.0) { | |
- rpm_lowest = -rpm_lowest; | |
- current = -current; | |
- current = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, mcconf->cc_min_current); | |
- current = -current; | |
- rpm_lowest = -rpm_lowest; | |
- } | |
+ bool use_min_current = false; | |
+ if (rpm_lowest > config.rpm_lim_end) { | |
+ if (servo_val > 0.0) { | |
+ use_min_current = true; | |
+ servo_val = 0.000001; // make sure min current ius used | |
+ } | |
+ if (current > 0.0) { | |
+ current = mcconf->cc_min_current; | |
+ } | |
+ | |
+ } else if (rpm_lowest > config.rpm_lim_start) { | |
+ if (servo_val > 0.0) { | |
+ use_min_current = true; | |
+ servo_val = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, servo_val, 0.000001); | |
+ } | |
+ if (current > 0.0) { | |
+ current = utils_highest_of_2(utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, 0.0), mcconf->cc_min_current); | |
+ } | |
+ } else if (rpm_lowest < -config.rpm_lim_end) { | |
+ if (servo_val < 0.0) { | |
+ use_min_current = true; | |
+ servo_val = -0.000001; // make sure min current ius used | |
+ } | |
+ if (current < 0.0) { | |
+ current = -mcconf->cc_min_current; // wrong in original | |
+ } | |
+ | |
+ } else if (rpm_lowest < -config.rpm_lim_start) { | |
+ if (servo_val < 0.0) { | |
+ use_min_current = true; | |
+ servo_val = -utils_map(-rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, -servo_val, 0.000001); | |
+ } | |
+ if (current < 0.0) { | |
+ current = utils_smallest_of_2(-utils_map(-rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, -current, 0.0), -mcconf->cc_min_current); | |
+ } | |
+ } | |
+ | |
float current_out = current; | |
+ float servo_val_out = servo_val; | |
bool is_reverse = false; | |
- if (current_out < 0.0) { | |
+ if (servo_val < 0.0) { | |
is_reverse = true; | |
current_out = -current_out; | |
current = -current; | |
+ servo_val_out = -servo_val_out; | |
+ servo_val = -servo_val; | |
rpm_local = -rpm_local; | |
rpm_lowest = -rpm_lowest; | |
} | |
@@ -285,25 +751,38 @@ | |
} | |
float diff = rpm_tmp - rpm_lowest; | |
- current_out = utils_map(diff, 0.0, config.tc_max_diff, current, 0.0); | |
- if (current_out < mcconf->cc_min_current) { | |
- current_out = 0.0; | |
+ if (diff > config.tc_offset) { | |
+ current_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, current, 0.0); | |
+ servo_val_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, servo_val, 0.0); | |
+ } else { | |
+ current_out = current; | |
+ servo_val_out = servo_val; | |
} | |
} | |
if (is_reverse) { | |
- comm_can_set_current(msg->id, -current_out); | |
+ if (config.ctrl_type == PPM_CTRL_TYPE_WATT_NOREV_BRAKE || (config.ctrl_type == PPM_CTRL_TYPE_WATT && config.max_erpm_for_dir_active)) { // if not active you want real brakes | |
+ comm_can_set_servo(msg->id, -servo_val_out, use_min_current); | |
+ } else { | |
+ comm_can_set_current(msg->id, -current_out); | |
+ } | |
} else { | |
- comm_can_set_current(msg->id, current_out); | |
+ if (config.ctrl_type == PPM_CTRL_TYPE_WATT_NOREV_BRAKE || config.ctrl_type == PPM_CTRL_TYPE_WATT) { | |
+ comm_can_set_servo(msg->id, servo_val_out, use_min_current); | |
+ } else { | |
+ comm_can_set_current(msg->id, current_out); | |
+ } | |
} | |
} | |
} | |
if (config.tc) { | |
+ | |
float diff = rpm_local - rpm_lowest; | |
- current_out = utils_map(diff, 0.0, config.tc_max_diff, current, 0.0); | |
- if (current_out < mcconf->cc_min_current) { | |
- current_out = 0.0; | |
+ if (diff > config.tc_offset) { | |
+ current_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, current, 0.0); | |
+ } else { | |
+ current_out = current; | |
} | |
} | |
} | |
@@ -315,7 +794,6 @@ | |
} | |
} | |
} | |
- | |
} | |
} | |
#endif | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app_sten.c Raptor2 Sources/bldc-firmware_2_80/applications/app_sten.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/applications/app_sten.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app_sten.c 2016-09-19 10:07:18.000000000 +0100 | |
@@ -32,6 +32,8 @@ | |
#include "utils.h" | |
#include "hw.h" | |
#include "timeout.h" | |
+#include "comm_can.h" | |
+ | |
#include <math.h> | |
// Settings | |
@@ -147,15 +149,7 @@ | |
} | |
static void set_output(float output) { | |
- output /= (1.0 - HYST); | |
- | |
- if (output > HYST) { | |
- output -= HYST; | |
- } else if (output < -HYST) { | |
- output += HYST; | |
- } else { | |
- output = 0.0; | |
- } | |
+ utils_deadband(&output, HYST, 1.0); | |
const float rpm = mc_interface_get_rpm(); | |
@@ -182,13 +176,11 @@ | |
current_p2 = current_p1; | |
current_p1 = current; | |
- if (fabsf(current) < mc_interface_get_configuration()->cc_min_current) { | |
- current = -mc_interface_get_configuration()->cc_min_current; | |
- } | |
- | |
mc_interface_set_current(current); | |
+ comm_can_set_current(255, current); | |
} else { | |
mc_interface_set_brake_current(output * mc_interface_get_configuration()->l_current_min); | |
+ comm_can_set_current_brake(255, output * mc_interface_get_configuration()->l_current_min); | |
} | |
} | |
Only in Raptor2 Sources/bldc-firmware_2_80: build | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/comm_can.c Raptor2 Sources/bldc-firmware_2_80/comm_can.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/comm_can.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/comm_can.c 2017-04-13 17:59:58.000000000 +0100 | |
@@ -23,6 +23,7 @@ | |
*/ | |
#include <string.h> | |
+#include <math.h> | |
#include "comm_can.h" | |
#include "ch.h" | |
#include "hal.h" | |
@@ -179,7 +180,19 @@ | |
case CAN_PACKET_SET_RPM: | |
ind = 0; | |
- mc_interface_set_pid_speed((float)buffer_get_int32(rxmsg.data8, &ind)); | |
+ mc_interface_set_pid_speed_with_cruise_status((float)buffer_get_int32(rxmsg.data8, &ind), rxmsg.data8[ind++]); | |
+ timeout_reset(); | |
+ break; | |
+ | |
+ case CAN_PACKET_SET_SERVO: | |
+ ind = 0; | |
+ mc_interface_set_servo((float)buffer_get_int32(rxmsg.data8, &ind) / 1000000.0, rxmsg.data8[ind++]); | |
+ timeout_reset(); | |
+ break; | |
+ | |
+ case CAN_PACKET_SET_BRAKE_SERVO: | |
+ ind = 0; | |
+ mc_interface_set_brake_servo((float)buffer_get_int32(rxmsg.data8, &ind) / 1000000.0); | |
timeout_reset(); | |
break; | |
@@ -256,7 +269,8 @@ | |
stat_tmp->rx_time = chVTGetSystemTime(); | |
stat_tmp->rpm = (float)buffer_get_int32(rxmsg.data8, &ind); | |
stat_tmp->current = (float)buffer_get_int16(rxmsg.data8, &ind) / 10.0; | |
- stat_tmp->duty = (float)buffer_get_int16(rxmsg.data8, &ind) / 1000.0; | |
+ stat_tmp->duty = rxmsg.data8[ind++]; | |
+ stat_tmp->cruise_control_status = rxmsg.data8[ind++]; | |
break; | |
} | |
} | |
@@ -285,7 +299,9 @@ | |
uint8_t buffer[8]; | |
buffer_append_int32(buffer, (int32_t)mc_interface_get_rpm(), &send_index); | |
buffer_append_int16(buffer, (int16_t)(mc_interface_get_tot_current() * 10.0), &send_index); | |
- buffer_append_int16(buffer, (int16_t)(mc_interface_get_duty_cycle_now() * 1000.0), &send_index); | |
+ buffer[send_index++] = (int8_t) floor(mc_interface_get_duty_cycle_now() * 100); | |
+ buffer[send_index++] = mc_interface_get_cruise_control_status(); | |
+ | |
comm_can_transmit(app_get_configuration()->controller_id | ((uint32_t)CAN_PACKET_STATUS << 8), buffer, send_index); | |
} | |
@@ -349,12 +365,12 @@ | |
} else { | |
unsigned int end_a = 0; | |
for (unsigned int i = 0;i < len;i += 7) { | |
- end_a = i; | |
- | |
if (i > 255) { | |
break; | |
} | |
+ end_a = i + 7; | |
+ | |
uint8_t send_len = 7; | |
send_buffer[0] = i; | |
@@ -410,6 +426,21 @@ | |
comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_SET_CURRENT << 8), buffer, send_index); | |
} | |
+void comm_can_set_servo(uint8_t controller_id, float servo_val, bool use_min_current) { | |
+ int32_t send_index = 0; | |
+ uint8_t buffer[5]; | |
+ buffer_append_int32(buffer, (int32_t)(servo_val * 1000000.0), &send_index); | |
+ buffer[send_index++] = use_min_current; | |
+ comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_SET_SERVO << 8), buffer, send_index); | |
+} | |
+ | |
+void comm_can_set_brake_servo(uint8_t controller_id, float servo_val) { | |
+ int32_t send_index = 0; | |
+ uint8_t buffer[4]; | |
+ buffer_append_int32(buffer, (int32_t)(servo_val * 1000000.0), &send_index); | |
+ comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_SET_BRAKE_SERVO << 8), buffer, send_index); | |
+} | |
+ | |
void comm_can_set_current_brake(uint8_t controller_id, float current) { | |
int32_t send_index = 0; | |
uint8_t buffer[4]; | |
@@ -417,10 +448,12 @@ | |
comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_SET_CURRENT_BRAKE << 8), buffer, send_index); | |
} | |
-void comm_can_set_rpm(uint8_t controller_id, float rpm) { | |
+void comm_can_set_rpm(uint8_t controller_id, float rpm, ppm_cruise cruise_status) { | |
int32_t send_index = 0; | |
- uint8_t buffer[4]; | |
+ uint8_t buffer[5]; | |
buffer_append_int32(buffer, (int32_t)rpm, &send_index); | |
+ buffer[send_index++] = cruise_status; | |
+ | |
comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_SET_RPM << 8), buffer, send_index); | |
} | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/comm_can.h Raptor2 Sources/bldc-firmware_2_80/comm_can.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/comm_can.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/comm_can.h 2017-04-13 18:00:08.000000000 +0100 | |
@@ -29,7 +29,7 @@ | |
// Settings | |
#define CAN_STATUS_MSG_INT_MS 1 | |
-#define CAN_STATUS_MSGS_TO_STORE 10 | |
+#define CAN_STATUS_MSGS_TO_STORE 3 | |
// Functions | |
void comm_can_init(void); | |
@@ -38,7 +38,9 @@ | |
void comm_can_set_duty(uint8_t controller_id, float duty); | |
void comm_can_set_current(uint8_t controller_id, float current); | |
void comm_can_set_current_brake(uint8_t controller_id, float current); | |
-void comm_can_set_rpm(uint8_t controller_id, float rpm); | |
+void comm_can_set_servo(uint8_t controller_id, float servo_val, bool use_min_current); | |
+void comm_can_set_brake_servo(uint8_t controller_id, float servo_val); | |
+void comm_can_set_rpm(uint8_t controller_id, float rpm, ppm_cruise cruise_status); | |
void comm_can_set_pos(uint8_t controller_id, float pos); | |
can_status_msg *comm_can_get_status_msg_index(int index); | |
can_status_msg *comm_can_get_status_msg_id(int id); | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/commands.c Raptor2 Sources/bldc-firmware_2_80/commands.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/commands.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/commands.c 2017-06-16 22:45:08.000000000 +0100 | |
@@ -25,7 +25,7 @@ | |
#include "commands.h" | |
#include "ch.h" | |
#include "hal.h" | |
-#include "main.h" | |
+#include "mc_interface.h" | |
#include "stm32f4xx_conf.h" | |
#include "servo.h" | |
#include "servo_simple.h" | |
@@ -64,10 +64,14 @@ | |
static int8_t detect_hall_table[8]; | |
static int detect_hall_res; | |
static void(*send_func)(unsigned char *data, unsigned int len) = 0; | |
+static void(*appdata_func)(unsigned char *data, unsigned int len) = 0; | |
static disp_pos_mode display_position_mode; | |
+static uint8_t remote_Mode; | |
+ | |
void commands_init(void) { | |
chThdCreateStatic(detect_thread_wa, sizeof(detect_thread_wa), NORMALPRIO, detect_thread, NULL); | |
+ remote_Mode = 0; | |
} | |
/** | |
@@ -118,6 +122,9 @@ | |
app_configuration appconf; | |
uint16_t flash_res; | |
uint32_t new_app_offset; | |
+ chuck_data chuck_d_tmp; | |
+ | |
+ bool sendActualSpeedMode = false; | |
packet_id = data[0]; | |
data++; | |
@@ -171,7 +178,7 @@ | |
buffer_append_float32(send_buffer, mc_interface_read_reset_avg_input_current(), 1e2, &ind); | |
buffer_append_float16(send_buffer, mc_interface_get_duty_cycle_now(), 1e3, &ind); | |
buffer_append_float32(send_buffer, mc_interface_get_rpm(), 1e0, &ind); | |
- buffer_append_float16(send_buffer, GET_INPUT_VOLTAGE(), 1e1, &ind); | |
+ buffer_append_float16(send_buffer, GET_INPUT_VOLTAGE(), 1e2, &ind); | |
buffer_append_float32(send_buffer, mc_interface_get_amp_hours(false), 1e4, &ind); | |
buffer_append_float32(send_buffer, mc_interface_get_amp_hours_charged(false), 1e4, &ind); | |
buffer_append_float32(send_buffer, mc_interface_get_watt_hours(false), 1e4, &ind); | |
@@ -243,6 +250,7 @@ | |
case COMM_SET_MCCONF: | |
mcconf = *mc_interface_get_configuration(); | |
+ appconf = *app_get_configuration(); | |
ind = 0; | |
mcconf.pwm_mode = data[ind++]; | |
@@ -251,22 +259,61 @@ | |
mcconf.sensor_mode = data[ind++]; | |
mcconf.l_current_max = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_current_max > 80.0){ | |
+ mcconf.l_current_max = 80.0; | |
+ } | |
+ | |
mcconf.l_current_min = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_current_min < -80.0){ | |
+ mcconf.l_current_min = -80.0; | |
+ } | |
+ | |
mcconf.l_in_current_max = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_in_current_max > 40.0){ | |
+ mcconf.l_in_current_max = 40.0; | |
+ } | |
+ | |
mcconf.l_in_current_min = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_in_current_min < -12.0){ | |
+ mcconf.l_in_current_min = -12.0; | |
+ } | |
+ | |
mcconf.l_abs_current_max = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_min_erpm = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_max_erpm = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_max_erpm_fbrake = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_max_erpm_fbrake_cc = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_min_vin = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_min_vin < 8.0){ | |
+ mcconf.l_min_vin = 8.0; | |
+ } | |
+ | |
mcconf.l_max_vin = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_max_vin > 57.0){ | |
+ mcconf.l_max_vin = 57.0; | |
+ } | |
+ | |
mcconf.l_battery_cut_start = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_battery_cut_start < 31.0){ | |
+ mcconf.l_battery_cut_start = 31.0; | |
+ } | |
+ | |
mcconf.l_battery_cut_end = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_battery_cut_end < 29.0){ | |
+ mcconf.l_battery_cut_end = 29.0; | |
+ } | |
mcconf.l_slow_abs_current = data[ind++]; | |
mcconf.l_rpm_lim_neg_torque = data[ind++]; | |
mcconf.l_temp_fet_start = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_temp_fet_start > 80.0){ | |
+ mcconf.l_temp_fet_start = 80.0; | |
+ } | |
+ | |
mcconf.l_temp_fet_end = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_temp_fet_end > 100.0){ | |
+ mcconf.l_temp_fet_end = 100.0; | |
+ } | |
+ | |
mcconf.l_temp_motor_start = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_temp_motor_end = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_min_duty = buffer_get_float32(data, 1000000.0, &ind); | |
@@ -280,17 +327,32 @@ | |
mcconf.sl_min_erpm = (float)buffer_get_int32(data, &ind) / 1000.0; | |
mcconf.sl_min_erpm_cycle_int_limit = (float)buffer_get_int32(data, &ind) / 1000.0; | |
mcconf.sl_max_fullbreak_current_dir_change = (float)buffer_get_int32(data, &ind) / 1000.0; | |
- mcconf.sl_cycle_int_limit = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ mcconf.sl_cycle_int_limit = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ }else{ | |
+ ind += 4; | |
+ } | |
mcconf.sl_phase_advance_at_br = (float)buffer_get_int32(data, &ind) / 1000.0; | |
mcconf.sl_cycle_int_rpm_br = (float)buffer_get_int32(data, &ind) / 1000.0; | |
- mcconf.sl_bemf_coupling_k = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ mcconf.sl_bemf_coupling_k = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ }else{ | |
+ ind += 4; | |
+ } | |
- memcpy(mcconf.hall_table, data + ind, 8); | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ memcpy(mcconf.hall_table, data + ind, 8); | |
+ } | |
ind += 8; | |
+ | |
mcconf.hall_sl_erpm = (float)buffer_get_int32(data, &ind) / 1000.0; | |
- mcconf.foc_current_kp = buffer_get_float32(data, 1e5, &ind); | |
- mcconf.foc_current_ki = buffer_get_float32(data, 1e5, &ind); | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ mcconf.foc_current_kp = buffer_get_float32(data, 1e5, &ind); | |
+ mcconf.foc_current_ki = buffer_get_float32(data, 1e5, &ind); | |
+ } else { | |
+ ind += 8; | |
+ } | |
mcconf.foc_f_sw = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_dt_us = buffer_get_float32(data, 1e6, &ind); | |
mcconf.foc_encoder_inverted = data[ind++]; | |
@@ -299,10 +361,15 @@ | |
mcconf.foc_sensor_mode = data[ind++]; | |
mcconf.foc_pll_kp = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_pll_ki = buffer_get_float32(data, 1e3, &ind); | |
- mcconf.foc_motor_l = buffer_get_float32(data, 1e8, &ind); | |
- mcconf.foc_motor_r = buffer_get_float32(data, 1e5, &ind); | |
- mcconf.foc_motor_flux_linkage = buffer_get_float32(data, 1e5, &ind); | |
- mcconf.foc_observer_gain = buffer_get_float32(data, 1e0, &ind); | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ mcconf.foc_motor_l = buffer_get_float32(data, 1e8, &ind); | |
+ mcconf.foc_motor_r = buffer_get_float32(data, 1e5, &ind); | |
+ mcconf.foc_motor_flux_linkage = buffer_get_float32(data, 1e5, &ind); | |
+ mcconf.foc_observer_gain = buffer_get_float32(data, 1e0, &ind); | |
+ }else{ | |
+ ind += 16; | |
+ } | |
+ | |
mcconf.foc_duty_dowmramp_kp = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_duty_dowmramp_ki = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_openloop_rpm = buffer_get_float32(data, 1e3, &ind); | |
@@ -310,33 +377,64 @@ | |
mcconf.foc_sl_openloop_time = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_sl_d_current_duty = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_sl_d_current_factor = buffer_get_float32(data, 1e3, &ind); | |
+ | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ memcpy(mcconf.foc_hall_table, data + ind, 8); | |
+ } | |
+ ind += 8; | |
+ | |
+ mcconf.foc_sl_erpm = (float)buffer_get_int32(data, &ind) / 1000.0; | |
mcconf.s_pid_kp = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.s_pid_ki = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.s_pid_kd = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.s_pid_min_erpm = (float)buffer_get_int32(data, &ind) / 1000.0; | |
- | |
+ | |
mcconf.p_pid_kp = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.p_pid_ki = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.p_pid_kd = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
+ mcconf.p_pid_ang_div = (float)buffer_get_int32(data, &ind) / 100000.0; | |
mcconf.cc_startup_boost_duty = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.cc_min_current = (float)buffer_get_int32(data, &ind) / 1000.0; | |
mcconf.cc_gain = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
- mcconf.cc_ramp_step_max = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
+ mcconf.cc_ramp_step_max = buffer_get_float32(data, 1e6, &ind); | |
mcconf.m_fault_stop_time_ms = buffer_get_int32(data, &ind); | |
mcconf.m_duty_ramp_step = (float)buffer_get_float32(data, 1000000.0, &ind); | |
mcconf.m_duty_ramp_step_rpm_lim = (float)buffer_get_float32(data, 1000000.0, &ind); | |
mcconf.m_current_backoff_gain = (float)buffer_get_float32(data, 1000000.0, &ind); | |
mcconf.m_encoder_counts = buffer_get_uint32(data, &ind); | |
+ mcconf.m_sensor_port_mode = data[ind++]; | |
+ | |
+ // new config | |
+ mcconf.s_pid_breaking_enabled = data[ind++]; | |
+ mcconf.use_max_watt_limit = data[ind++]; | |
+ mcconf.watts_max = (float)buffer_get_int16(data, &ind); | |
+ // new config end | |
conf_general_store_mc_configuration(&mcconf); | |
mc_interface_set_configuration(&mcconf); | |
- | |
-#if ENCODER_ENABLE | |
- encoder_set_counts(mcconf.m_encoder_counts); | |
-#endif | |
+ | |
+ if (!appconf.send_can_status) { | |
+ | |
+ ind = 0; | |
+ // send to all others | |
+ uint8_t send_buffer_can[PACKET_MAX_PL_LEN]; | |
+ | |
+ send_buffer_can[ind++] = packet_id; | |
+ for(unsigned int i = 0; i < len; i++){ | |
+ send_buffer_can[ind++] = data[i]; | |
+ } | |
+ | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1) { | |
+ comm_can_send_buffer(msg->id, send_buffer_can, len + 1, false); | |
+ } | |
+ } | |
+ } | |
ind = 0; | |
send_buffer[ind++] = packet_id; | |
@@ -414,15 +512,19 @@ | |
buffer_append_float32(send_buffer, mcconf.foc_sl_openloop_time, 1e3, &ind); | |
buffer_append_float32(send_buffer, mcconf.foc_sl_d_current_duty, 1e3, &ind); | |
buffer_append_float32(send_buffer, mcconf.foc_sl_d_current_factor, 1e3, &ind); | |
+ memcpy(send_buffer + ind, mcconf.foc_hall_table, 8); | |
+ ind += 8; | |
+ buffer_append_int32(send_buffer, (int32_t)(mcconf.foc_sl_erpm * 1000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_kp * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_ki * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_kd * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_min_erpm * 1000.0), &ind); | |
- | |
+ | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.p_pid_kp * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.p_pid_ki * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.p_pid_kd * 1000000.0), &ind); | |
+ buffer_append_float32(send_buffer, mcconf.p_pid_ang_div, 1e5, &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.cc_startup_boost_duty * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.cc_min_current * 1000.0), &ind); | |
@@ -434,6 +536,13 @@ | |
buffer_append_float32(send_buffer, mcconf.m_duty_ramp_step_rpm_lim, 1000000.0, &ind); | |
buffer_append_float32(send_buffer, mcconf.m_current_backoff_gain, 1000000.0, &ind); | |
buffer_append_uint32(send_buffer, mcconf.m_encoder_counts, &ind); | |
+ send_buffer[ind++] = mcconf.m_sensor_port_mode; | |
+ | |
+ // new config | |
+ send_buffer[ind++] = mcconf.s_pid_breaking_enabled; | |
+ send_buffer[ind++] = mcconf.use_max_watt_limit; | |
+ buffer_append_int16(send_buffer, (int16_t)(mcconf.watts_max), &ind); | |
+ // new config end | |
commands_send_packet(send_buffer, ind); | |
break; | |
@@ -462,7 +571,7 @@ | |
appconf.app_ppm_conf.multi_esc = data[ind++]; | |
appconf.app_ppm_conf.tc = data[ind++]; | |
appconf.app_ppm_conf.tc_max_diff = (float)buffer_get_int32(data, &ind) / 1000.0; | |
- | |
+ | |
appconf.app_adc_conf.ctrl_type = data[ind++]; | |
appconf.app_adc_conf.hyst = (float)buffer_get_int32(data, &ind) / 1000.0; | |
appconf.app_adc_conf.voltage_start = (float)buffer_get_int32(data, &ind) / 1000.0; | |
@@ -491,7 +600,45 @@ | |
appconf.app_chuk_conf.multi_esc = data[ind++]; | |
appconf.app_chuk_conf.tc = data[ind++]; | |
appconf.app_chuk_conf.tc_max_diff = buffer_get_float32(data, 1000.0, &ind); | |
- | |
+ | |
+ appconf.app_nrf_conf.speed = data[ind++]; | |
+ appconf.app_nrf_conf.power = data[ind++]; | |
+ appconf.app_nrf_conf.crc_type = data[ind++]; | |
+ appconf.app_nrf_conf.retry_delay = data[ind++]; | |
+ appconf.app_nrf_conf.retries = data[ind++]; | |
+ appconf.app_nrf_conf.channel = data[ind++]; | |
+ memcpy(appconf.app_nrf_conf.address, data + ind, 3); | |
+ ind += 3; | |
+ appconf.app_nrf_conf.send_crc_ack = data[ind++]; | |
+ | |
+ // new config | |
+ appconf.app_ppm_conf.pulse_center = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ appconf.app_ppm_conf.tc_offset = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ appconf.app_ppm_conf.cruise_left = data[ind++]; | |
+ appconf.app_ppm_conf.cruise_right = data[ind++]; | |
+ appconf.app_ppm_conf.max_erpm_for_dir_active = data[ind++]; | |
+ appconf.app_ppm_conf.max_erpm_for_dir = buffer_get_float32(data, 1000.0, &ind); | |
+ | |
+ appconf.app_chuk_conf.tc_offset = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ appconf.app_chuk_conf.buttons_mirrored = data[ind++]; | |
+ | |
+ appconf.app_throttle_conf.adjustable_throttle_enabled = data[ind++]; | |
+ appconf.app_throttle_conf.y1_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.y2_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.y3_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x1_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x2_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x3_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.bezier_reduce_factor = (float)buffer_get_int16(data, &ind) / 100.0; | |
+ appconf.app_throttle_conf.y1_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.y2_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.y3_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x1_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x2_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x3_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.bezier_neg_reduce_factor = (float)buffer_get_int16(data, &ind) / 100.0; | |
+ // new config end | |
+ | |
conf_general_store_app_configuration(&appconf); | |
app_set_configuration(&appconf); | |
timeout_configure(appconf.timeout_msec, appconf.timeout_brake_current); | |
@@ -531,7 +678,7 @@ | |
send_buffer[ind++] = appconf.app_ppm_conf.multi_esc; | |
send_buffer[ind++] = appconf.app_ppm_conf.tc; | |
buffer_append_int32(send_buffer, (int32_t)(appconf.app_ppm_conf.tc_max_diff * 1000.0), &ind); | |
- | |
+ | |
send_buffer[ind++] = appconf.app_adc_conf.ctrl_type; | |
buffer_append_int32(send_buffer, (int32_t)(appconf.app_adc_conf.hyst * 1000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(appconf.app_adc_conf.voltage_start * 1000.0), &ind); | |
@@ -560,7 +707,45 @@ | |
send_buffer[ind++] = appconf.app_chuk_conf.multi_esc; | |
send_buffer[ind++] = appconf.app_chuk_conf.tc; | |
buffer_append_int32(send_buffer, (int32_t)(appconf.app_chuk_conf.tc_max_diff * 1000.0), &ind); | |
- | |
+ | |
+ send_buffer[ind++] = appconf.app_nrf_conf.speed; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.power; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.crc_type; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.retry_delay; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.retries; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.channel; | |
+ memcpy(send_buffer + ind, appconf.app_nrf_conf.address, 3); | |
+ ind += 3; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.send_crc_ack; | |
+ | |
+ // new config | |
+ buffer_append_int32(send_buffer, (int32_t)(appconf.app_ppm_conf.pulse_center * 1000.0), &ind); | |
+ buffer_append_int32(send_buffer, (int32_t)(appconf.app_ppm_conf.tc_offset * 1000.0), &ind); | |
+ send_buffer[ind++] = appconf.app_ppm_conf.cruise_left; | |
+ send_buffer[ind++] = appconf.app_ppm_conf.cruise_right; | |
+ send_buffer[ind++] = appconf.app_ppm_conf.max_erpm_for_dir_active; | |
+ buffer_append_float32(send_buffer, appconf.app_ppm_conf.max_erpm_for_dir, 1000.0, &ind); | |
+ | |
+ buffer_append_int32(send_buffer, (int32_t)(appconf.app_chuk_conf.tc_offset * 1000.0), &ind); | |
+ send_buffer[ind++] = appconf.app_chuk_conf.buttons_mirrored; | |
+ | |
+ send_buffer[ind++] = appconf.app_throttle_conf.adjustable_throttle_enabled; | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y1_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y2_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y3_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x1_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x2_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x3_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.bezier_reduce_factor * 100.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y1_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y2_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y3_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x1_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x2_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x3_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.bezier_neg_reduce_factor * 100.0), &ind); | |
+ // end new config | |
+ | |
commands_send_packet(send_buffer, ind); | |
break; | |
@@ -569,7 +754,7 @@ | |
at_start = data[ind++]; | |
sample_len = buffer_get_uint16(data, &ind); | |
decimation = data[ind++]; | |
- main_sample_print_data(at_start, sample_len, decimation); | |
+ mc_interface_sample_print_data(at_start, sample_len, decimation); | |
break; | |
case COMM_TERMINAL_CMD: | |
@@ -633,39 +818,74 @@ | |
break; | |
case COMM_DETECT_ENCODER: { | |
-#if ENCODER_ENABLE | |
- mcconf = *mc_interface_get_configuration(); | |
- mcconf_old = mcconf; | |
+ if (encoder_is_configured()) { | |
+ mcconf = *mc_interface_get_configuration(); | |
+ mcconf_old = mcconf; | |
- ind = 0; | |
- float current = buffer_get_float32(data, 1e3, &ind); | |
+ ind = 0; | |
+ float current = buffer_get_float32(data, 1e3, &ind); | |
- mcconf.motor_type = MOTOR_TYPE_FOC; | |
- mcconf.foc_f_sw = 10000.0; | |
- mcconf.foc_current_kp = 0.01; | |
- mcconf.foc_current_ki = 10.0; | |
- mc_interface_set_configuration(&mcconf); | |
+ mcconf.motor_type = MOTOR_TYPE_FOC; | |
+ mcconf.foc_f_sw = 10000.0; | |
+ mcconf.foc_current_kp = 0.01; | |
+ mcconf.foc_current_ki = 10.0; | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ float offset = 0.0; | |
+ float ratio = 0.0; | |
+ bool inverted = false; | |
+ mcpwm_foc_encoder_detect(current, false, &offset, &ratio, &inverted); | |
+ mc_interface_set_configuration(&mcconf_old); | |
+ | |
+ ind = 0; | |
+ send_buffer[ind++] = COMM_DETECT_ENCODER; | |
+ buffer_append_float32(send_buffer, offset, 1e6, &ind); | |
+ buffer_append_float32(send_buffer, ratio, 1e6, &ind); | |
+ send_buffer[ind++] = inverted; | |
+ commands_send_packet(send_buffer, ind); | |
+ } else { | |
+ ind = 0; | |
+ send_buffer[ind++] = COMM_DETECT_ENCODER; | |
+ buffer_append_float32(send_buffer, 1001.0, 1e6, &ind); | |
+ buffer_append_float32(send_buffer, 0.0, 1e6, &ind); | |
+ send_buffer[ind++] = false; | |
+ commands_send_packet(send_buffer, ind); | |
+ } | |
+ } | |
+ break; | |
- float offset = 0.0; | |
- float ratio = 0.0; | |
- bool inverted = false; | |
- mcpwm_foc_encoder_detect(current, false, &offset, &ratio, &inverted); | |
- mc_interface_set_configuration(&mcconf_old); | |
+ case COMM_DETECT_HALL_FOC: { | |
+ mcconf = *mc_interface_get_configuration(); | |
- ind = 0; | |
- send_buffer[ind++] = COMM_DETECT_ENCODER; | |
- buffer_append_float32(send_buffer, offset, 1e6, &ind); | |
- buffer_append_float32(send_buffer, ratio, 1e6, &ind); | |
- send_buffer[ind++] = inverted; | |
- commands_send_packet(send_buffer, ind); | |
-#else | |
- ind = 0; | |
- send_buffer[ind++] = COMM_DETECT_ENCODER; | |
- buffer_append_float32(send_buffer, 1001.0, 1e6, &ind); | |
- buffer_append_float32(send_buffer, 0.0, 1e6, &ind); | |
- send_buffer[ind++] = false; | |
- commands_send_packet(send_buffer, ind); | |
-#endif | |
+ if (mcconf.m_sensor_port_mode == SENSOR_PORT_MODE_HALL) { | |
+ mcconf_old = mcconf; | |
+ ind = 0; | |
+ float current = buffer_get_float32(data, 1e3, &ind); | |
+ | |
+ mcconf.motor_type = MOTOR_TYPE_FOC; | |
+ mcconf.foc_f_sw = 10000.0; | |
+ mcconf.foc_current_kp = 0.01; | |
+ mcconf.foc_current_ki = 10.0; | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ uint8_t hall_tab[8]; | |
+ bool res = mcpwm_foc_hall_detect(current, hall_tab); | |
+ mc_interface_set_configuration(&mcconf_old); | |
+ | |
+ ind = 0; | |
+ send_buffer[ind++] = COMM_DETECT_HALL_FOC; | |
+ memcpy(send_buffer + ind, hall_tab, 8); | |
+ ind += 8; | |
+ send_buffer[ind++] = res ? 0 : 1; | |
+ | |
+ commands_send_packet(send_buffer, ind); | |
+ } else { | |
+ ind = 0; | |
+ send_buffer[ind++] = COMM_DETECT_HALL_FOC; | |
+ memset(send_buffer, 255, 8); | |
+ ind += 8; | |
+ send_buffer[ind++] = 0; | |
+ } | |
} | |
break; | |
@@ -692,6 +912,8 @@ | |
send_buffer[ind++] = COMM_GET_DECODED_ADC; | |
buffer_append_int32(send_buffer, (int32_t)(app_adc_get_decoded_level() * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(app_adc_get_voltage() * 1000000.0), &ind); | |
+ buffer_append_int32(send_buffer, (int32_t)(app_adc_get_decoded_level2() * 1000000.0), &ind); | |
+ buffer_append_int32(send_buffer, (int32_t)(app_adc_get_voltage2() * 1000000.0), &ind); | |
commands_send_packet(send_buffer, ind); | |
break; | |
@@ -706,9 +928,535 @@ | |
comm_can_send_buffer(data[0], data + 1, len - 1, false); | |
break; | |
+ case COMM_SET_CHUCK_DATA: | |
+ ind = 0; | |
+ chuck_d_tmp.js_x = data[ind++]; | |
+ chuck_d_tmp.js_y = data[ind++]; | |
+ chuck_d_tmp.bt_c = data[ind++]; | |
+ chuck_d_tmp.bt_z = data[ind++]; | |
+ chuck_d_tmp.acc_x = buffer_get_int16(data, &ind); | |
+ chuck_d_tmp.acc_y = buffer_get_int16(data, &ind); | |
+ chuck_d_tmp.acc_z = buffer_get_int16(data, &ind); | |
+ app_nunchuk_update_output(&chuck_d_tmp); | |
+ break; | |
+ | |
+ case COMM_CUSTOM_APP_DATA: | |
+ if (appdata_func) { | |
+ appdata_func(data, len); | |
+ } | |
+ break; | |
+ | |
+ case COMM_SET_SPEED_MODE: | |
+ ind = 0; | |
+ uint8_t new_remote_Mode = data[ind++]; | |
+ uint8_t new_speed_mode_int = data[ind++]; | |
+ bool use_max_watt = data[ind++]; | |
+ float watts_max = buffer_get_float16(data, 1, &ind); | |
+ float cur_mot_max = buffer_get_float16(data, 10, &ind); | |
+ float cur_bat_max = buffer_get_float16(data, 10, &ind); | |
+ float cur_mot_min = buffer_get_float16(data, 10, &ind); | |
+ float cur_bat_min = buffer_get_float16(data, 10, &ind); | |
+ float max_erpm = buffer_get_float16(data, 0.1, &ind); | |
+ | |
+ bool useSpecialThrottleCurve = data[ind++]; | |
+ float newY1 = 0.0, newY2 = 0.0, newY3 = 0.0, newX1 = 0.0, newX2 = 0.0, newX3 = 0.0, newBezier_pos = 0.0, newY1_neg = 0.0, newY2_neg = 0.0, newY3_neg = 0.0, newX1_neg = 0.0, newX2_neg = 0.0, newX3_neg = 0.0, newBezier_neg = 0.0; | |
+ if (useSpecialThrottleCurve) { | |
+ newY1 = buffer_get_float16(data, 1000, &ind); | |
+ newY2 = buffer_get_float16(data, 1000, &ind); | |
+ newY3 = buffer_get_float16(data, 1000, &ind); | |
+ newX1 = buffer_get_float16(data, 1000, &ind); | |
+ newX2 = buffer_get_float16(data, 1000, &ind); | |
+ newX3 = buffer_get_float16(data, 1000, &ind); | |
+ newBezier_pos = buffer_get_float16(data, 100, &ind); | |
+ newY1_neg = buffer_get_float16(data, 1000, &ind); | |
+ newY2_neg = buffer_get_float16(data, 1000, &ind); | |
+ newY3_neg = buffer_get_float16(data, 1000, &ind); | |
+ newX1_neg = buffer_get_float16(data, 1000, &ind); | |
+ newX2_neg = buffer_get_float16(data, 1000, &ind); | |
+ newX3_neg = buffer_get_float16(data, 1000, &ind); | |
+ newBezier_neg = buffer_get_float16(data, 100, &ind); | |
+ } | |
+ | |
+ bool useSpecialPIDBrakingEnabled = data[ind++]; | |
+ bool pidBrakingEnabled = false; | |
+ if (useSpecialPIDBrakingEnabled) { | |
+ pidBrakingEnabled = data[ind++]; | |
+ } | |
+ | |
+ bool useSpecialSpeedPID = data[ind++]; | |
+ float speed_pid_kp = 0.0, speed_pid_ki = 0.0, speed_pid_kd = 0.0; | |
+ if (useSpecialSpeedPID) { | |
+ speed_pid_kp = buffer_get_float32(data, 1000000.0, &ind); | |
+ speed_pid_ki = buffer_get_float32(data, 1000000.0, &ind); | |
+ speed_pid_kd = buffer_get_float32(data, 1000000.0, &ind); | |
+ } | |
+ | |
+ uint8_t front_controller_first = data[ind++]; | |
+ uint8_t front_controller_second = data[ind++]; | |
+ bool front_use_max_watt = false; | |
+ float front_watts_max = 0.0, front_cur_mot_max = 0.0, front_cur_bat_max = 0.0, front_cur_mot_min = 0.0, front_cur_bat_min = 0.0; | |
+ if (front_controller_first != 9 || front_controller_second != 9) { | |
+ front_use_max_watt = data[ind++]; | |
+ front_watts_max = buffer_get_float16(data, 1, &ind); | |
+ front_cur_mot_max = buffer_get_float16(data, 10, &ind); | |
+ front_cur_bat_max = buffer_get_float16(data, 10, &ind); | |
+ front_cur_mot_min = buffer_get_float16(data, 10, &ind); | |
+ front_cur_bat_min = buffer_get_float16(data, 10, &ind); | |
+ } | |
+ | |
+ appconf = *app_get_configuration(); | |
+ | |
+ if (appconf.app_to_use == APP_PPM_UART | |
+ || appconf.app_to_use == APP_PPM | |
+ || appconf.app_to_use == APP_NONE | |
+ || appconf.app_to_use == APP_UART | |
+ || appconf.app_to_use == APP_NUNCHUK | |
+ || appconf.app_to_use == APP_NRF) { | |
+ | |
+ app_configuration saved_appconf; | |
+ | |
+ conf_general_read_app_configuration(&saved_appconf); | |
+ | |
+ mcconf = *mc_interface_get_configuration(); | |
+ | |
+ mc_configuration saved_mcconf; | |
+ // gett base settings for motor | |
+ conf_general_read_mc_configuration(&saved_mcconf); | |
+ | |
+ // reset app ppm | |
+ appconf.app_ppm_conf.ctrl_type = saved_appconf.app_ppm_conf.ctrl_type; | |
+ appconf.app_ppm_conf.pid_max_erpm = saved_appconf.app_ppm_conf.pid_max_erpm; | |
+ appconf.app_ppm_conf.rpm_lim_end = saved_appconf.app_ppm_conf.rpm_lim_end; | |
+ appconf.app_ppm_conf.rpm_lim_start = saved_appconf.app_ppm_conf.rpm_lim_start; | |
+ | |
+ // reset app chuk | |
+ appconf.app_chuk_conf.ctrl_type = saved_appconf.app_chuk_conf.ctrl_type; | |
+ appconf.app_chuk_conf.rpm_lim_end = saved_appconf.app_chuk_conf.rpm_lim_end; | |
+ appconf.app_chuk_conf.rpm_lim_start = saved_appconf.app_chuk_conf.rpm_lim_start; | |
+ | |
+ // reset throttle curve | |
+ appconf.app_throttle_conf.adjustable_throttle_enabled = saved_appconf.app_throttle_conf.adjustable_throttle_enabled; | |
+ appconf.app_throttle_conf.y1_throttle = saved_appconf.app_throttle_conf.y1_throttle; | |
+ appconf.app_throttle_conf.y2_throttle = saved_appconf.app_throttle_conf.y2_throttle; | |
+ appconf.app_throttle_conf.y3_throttle = saved_appconf.app_throttle_conf.y3_throttle; | |
+ appconf.app_throttle_conf.x1_throttle = saved_appconf.app_throttle_conf.x1_throttle; | |
+ appconf.app_throttle_conf.x2_throttle = saved_appconf.app_throttle_conf.x2_throttle; | |
+ appconf.app_throttle_conf.x3_throttle = saved_appconf.app_throttle_conf.x3_throttle; | |
+ appconf.app_throttle_conf.bezier_reduce_factor = saved_appconf.app_throttle_conf.bezier_reduce_factor; | |
+ appconf.app_throttle_conf.y1_neg_throttle = saved_appconf.app_throttle_conf.y1_neg_throttle; | |
+ appconf.app_throttle_conf.y2_neg_throttle = saved_appconf.app_throttle_conf.y2_neg_throttle; | |
+ appconf.app_throttle_conf.y3_neg_throttle = saved_appconf.app_throttle_conf.y3_neg_throttle; | |
+ appconf.app_throttle_conf.x1_neg_throttle = saved_appconf.app_throttle_conf.x1_neg_throttle; | |
+ appconf.app_throttle_conf.x2_neg_throttle = saved_appconf.app_throttle_conf.x2_neg_throttle; | |
+ appconf.app_throttle_conf.x3_neg_throttle = saved_appconf.app_throttle_conf.x3_neg_throttle; | |
+ appconf.app_throttle_conf.bezier_neg_reduce_factor = saved_appconf.app_throttle_conf.bezier_neg_reduce_factor; | |
+ | |
+ // reset motor | |
+ mcconf.l_current_max = saved_mcconf.l_current_max; | |
+ mcconf.l_current_min = saved_mcconf.l_current_min; | |
+ mcconf.l_in_current_max = saved_mcconf.l_in_current_max; | |
+ mcconf.l_in_current_min = saved_mcconf.l_in_current_min; | |
+ | |
+ mcconf.use_max_watt_limit = saved_mcconf.use_max_watt_limit; | |
+ mcconf.watts_max = saved_mcconf.watts_max; | |
+ | |
+ mcconf.s_pid_breaking_enabled = saved_mcconf.s_pid_breaking_enabled; | |
+ | |
+ mcconf.s_pid_kp = saved_mcconf.s_pid_kp; | |
+ mcconf.s_pid_ki = saved_mcconf.s_pid_ki; | |
+ mcconf.s_pid_kd = saved_mcconf.s_pid_kd; | |
+ | |
+ if (new_remote_Mode == 0){ | |
+ remote_Mode = new_remote_Mode; | |
+ } else { | |
+ if (appconf.app_to_use == APP_NONE || appconf.app_to_use == APP_UART) { | |
+ if (appconf.send_can_status) { | |
+ remote_Mode = new_remote_Mode; | |
+ } | |
+ } | |
+ | |
+ if (appconf.app_to_use == APP_PPM_UART || appconf.app_to_use == APP_PPM) { | |
+ switch (new_speed_mode_int) { | |
+ case PPM_CTRL_TYPE_PID_NOACCELERATION: | |
+ case PPM_CTRL_TYPE_NONE: | |
+ case PPM_CTRL_TYPE_CURRENT: | |
+ case PPM_CTRL_TYPE_CURRENT_NOREV: | |
+ case PPM_CTRL_TYPE_CURRENT_NOREV_BRAKE: | |
+ case PPM_CTRL_TYPE_DUTY: | |
+ case PPM_CTRL_TYPE_DUTY_NOREV: | |
+ case PPM_CTRL_TYPE_PID: | |
+ case PPM_CTRL_TYPE_PID_NOREV: | |
+ case PPM_CTRL_TYPE_WATT_NOREV_BRAKE: | |
+ case PPM_CTRL_TYPE_WATT: | |
+ if (!appconf.send_can_status) { | |
+ appconf.app_ppm_conf.ctrl_type = new_speed_mode_int; | |
+ | |
+ if (max_erpm > 0 && max_erpm <= 100000.0) { | |
+ appconf.app_ppm_conf.pid_max_erpm = max_erpm; | |
+ appconf.app_ppm_conf.rpm_lim_end = max_erpm; | |
+ appconf.app_ppm_conf.rpm_lim_start = max_erpm - ((int16_t)(max_erpm / 10)); // 10% off | |
+ } | |
+ } | |
+ | |
+ remote_Mode = new_remote_Mode; | |
+ break; | |
+ default: | |
+ //only the basic settings which are defined by the bldc-tool | |
+ remote_Mode = 0; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if (appconf.app_to_use == APP_NUNCHUK || appconf.app_to_use == APP_NRF) { | |
+ switch (new_speed_mode_int) { | |
+ case CHUK_CTRL_TYPE_NONE: | |
+ case CHUK_CTRL_TYPE_CURRENT: | |
+ case CHUK_CTRL_TYPE_CURRENT_NOREV: | |
+ case CHUK_CTRL_TYPE_WATT: | |
+ case CHUK_CTRL_TYPE_WATT_NOREV: | |
+ if (!appconf.send_can_status) { | |
+ appconf.app_chuk_conf.ctrl_type = new_speed_mode_int; | |
+ | |
+ if (max_erpm > 0 && max_erpm <= 100000.0) { | |
+ appconf.app_chuk_conf.rpm_lim_end = max_erpm; | |
+ appconf.app_chuk_conf.rpm_lim_start = max_erpm - ((int16_t)(max_erpm / 10)); // 10% off | |
+ } | |
+ | |
+ } | |
+ | |
+ remote_Mode = new_remote_Mode; | |
+ break; | |
+ default: | |
+ //only the basic settings which are defined by the bldc-tool | |
+ remote_Mode = 0; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if(remote_Mode != 0){ | |
+ if (!appconf.send_can_status) { | |
+ if (useSpecialThrottleCurve) { | |
+ appconf.app_throttle_conf.adjustable_throttle_enabled = true; | |
+ appconf.app_throttle_conf.y1_throttle = newY1; | |
+ appconf.app_throttle_conf.y2_throttle = newY2; | |
+ appconf.app_throttle_conf.y3_throttle = newY3; | |
+ appconf.app_throttle_conf.x1_throttle = newX1; | |
+ appconf.app_throttle_conf.x2_throttle = newX2; | |
+ appconf.app_throttle_conf.x3_throttle = newX3; | |
+ appconf.app_throttle_conf.bezier_reduce_factor = newBezier_pos; | |
+ appconf.app_throttle_conf.y1_neg_throttle = newY1_neg; | |
+ appconf.app_throttle_conf.y2_neg_throttle = newY2_neg; | |
+ appconf.app_throttle_conf.y3_neg_throttle = newY3_neg; | |
+ appconf.app_throttle_conf.x1_neg_throttle = newX1_neg; | |
+ appconf.app_throttle_conf.x2_neg_throttle = newX2_neg; | |
+ appconf.app_throttle_conf.x3_neg_throttle = newX3_neg; | |
+ appconf.app_throttle_conf.bezier_neg_reduce_factor = newBezier_neg; | |
+ } | |
+ } | |
+ | |
+ if (useSpecialPIDBrakingEnabled) { | |
+ mcconf.s_pid_breaking_enabled = pidBrakingEnabled; | |
+ } | |
+ | |
+ if (useSpecialSpeedPID) { | |
+ mcconf.s_pid_kp = speed_pid_kp; | |
+ mcconf.s_pid_ki = speed_pid_ki; | |
+ mcconf.s_pid_kd = speed_pid_kd; | |
+ } | |
+ | |
+ if ((front_controller_first != 9 && appconf.controller_id == front_controller_first) | |
+ || (front_controller_second != 9 && appconf.controller_id == front_controller_second)) { // or last position | |
+ | |
+ mcconf.use_max_watt_limit = front_use_max_watt; | |
+ mcconf.watts_max = front_watts_max; | |
+ | |
+ if (front_cur_mot_max >= mcconf.cc_min_current && front_cur_mot_max <= 80) mcconf.l_current_max = front_cur_mot_max; | |
+ | |
+ if (front_cur_bat_max >= mcconf.cc_min_current && front_cur_bat_max <= 40) mcconf.l_in_current_max = front_cur_bat_max; | |
+ | |
+ if (front_cur_mot_min <= -mcconf.cc_min_current && front_cur_mot_min >= -80) mcconf.l_current_min = front_cur_mot_min; | |
+ | |
+ if (front_cur_bat_min <= -mcconf.cc_min_current && front_cur_bat_min >= -12) mcconf.l_in_current_min = front_cur_bat_min; | |
+ | |
+ } else { // normal or rear setup | |
+ mcconf.use_max_watt_limit = use_max_watt; | |
+ mcconf.watts_max = watts_max; | |
+ | |
+ if (cur_mot_max >= mcconf.cc_min_current && cur_mot_max <= 80) mcconf.l_current_max = cur_mot_max; | |
+ | |
+ if (cur_bat_max >= mcconf.cc_min_current && cur_bat_max <= 40) mcconf.l_in_current_max = cur_bat_max; | |
+ | |
+ if (cur_mot_min <= -mcconf.cc_min_current && cur_mot_min >= -80) mcconf.l_current_min = cur_mot_min; | |
+ | |
+ if (cur_bat_min <= -mcconf.cc_min_current && cur_bat_min >= -12) mcconf.l_in_current_min = cur_bat_min; | |
+ } | |
+ } | |
+ } | |
+ | |
+ if (!appconf.send_can_status) { | |
+ sendActualSpeedMode = true; | |
+ | |
+ ind = 0; | |
+ // send to all others | |
+ uint8_t send_buffer_can[PACKET_MAX_PL_LEN]; | |
+ | |
+ send_buffer_can[ind++] = packet_id; | |
+ send_buffer_can[ind++] = remote_Mode; | |
+ | |
+ for(unsigned int i = 1; i < len; i++){ | |
+ send_buffer_can[ind++] = data[i]; | |
+ } | |
+ | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1) { | |
+ comm_can_send_buffer(msg->id, send_buffer_can, len + 1, false); | |
+ } | |
+ } | |
+ } | |
+ | |
+ mc_interface_set_configuration(&mcconf); | |
+ app_set_configuration(&appconf); | |
+ | |
+ timeout_configure(appconf.timeout_msec, appconf.timeout_brake_current); | |
+ | |
+ timeout_reset(); | |
+ } | |
+ | |
+ break; | |
+ case COMM_CHANGE_SPEED_MODE: | |
+/* | |
+ ind = 0; | |
+ | |
+ app_configuration saved_appconf2; | |
+ | |
+ conf_general_read_app_configuration(&saved_appconf2); | |
+ | |
+ appconf = *app_get_configuration(); | |
+ | |
+ appconf.app_ppm_conf.ctrl_type = saved_appconf2.app_ppm_conf.ctrl_type; | |
+ | |
+ mcconf = *mc_interface_get_configuration(); | |
+ | |
+ mc_configuration saved_mcconf2; | |
+ // gett base settings for motor | |
+ conf_general_read_mc_configuration(&saved_mcconf2); | |
+ | |
+ mcconf.l_current_max = saved_mcconf2.l_current_max; | |
+ mcconf.l_in_current_max = saved_mcconf2.l_in_current_max; | |
+ | |
+ if (appconf.app_to_use == APP_PPM_UART || appconf.app_to_use == APP_PPM) { | |
+ if (appconf.app_ppm_conf.ctrl_type == PPM_CTRL_TYPE_WATT_NOREV_BRAKE) { | |
+ appconf.app_ppm_conf.ctrl_type = PPM_CTRL_TYPE_PID_NOACCELERATION; | |
+ float watt = 250 / 0.9; | |
+ } else if (appconf.app_ppm_conf.ctrl_type == PPM_CTRL_TYPE_PID_NOACCELERATION) { | |
+ appconf.app_ppm_conf.ctrl_type = PPM_CTRL_TYPE_WATT_NOREV_BRAKE; | |
+ *//*} else if (new_speed_mode_int == PPM_CTRL_TYPE_CURRENT_NOREV_BRAKE) { | |
+ appconf.app_ppm_conf.ctrl_type = new_speed_mode_int; | |
+ | |
+ if (current_motor >= mcconf.cc_min_current && current_motor <= mcconf.l_current_max){ | |
+ mcconf.l_current_max = current_motor; | |
+ } | |
+ | |
+ if (current_battery >= mcconf.cc_min_current && current_battery <= mcconf.l_in_current_max){ | |
+ mcconf.l_in_current_max = current_battery; | |
+ }*/ | |
+/* | |
+ } else if (appconf.app_ppm_conf.ctrl_type == PPM_CTRL_TYPE_WATT_NOREV_BRAKE) { | |
+ appconf.app_ppm_conf.ctrl_type = PPM_CTRL_TYPE_CURRENT_NOREV_BRAKE; | |
+ //currents will be the default values | |
+ } else{ | |
+ //only the basic settings which are defined by the bldc-tool | |
+ } | |
+ } | |
+ | |
+ mc_interface_set_configuration(&mcconf); | |
+ app_set_configuration(&appconf); | |
+ timeout_configure(appconf.timeout_msec, appconf.timeout_brake_current); | |
+ | |
+ timeout_reset(); | |
+ sendActualSpeedMode = true; | |
+*/ | |
+ break; | |
+ case COMM_GET_SPEED_MODE: | |
+ sendActualSpeedMode = true; | |
+ break; | |
+ case COMM_SET_CURRENT_CONF_AS_DEFAULT: | |
+ | |
+ mcconf = *mc_interface_get_configuration(); | |
+ | |
+ appconf = *app_get_configuration(); | |
+ | |
+ if (!appconf.send_can_status) { | |
+ sendActualSpeedMode = true; | |
+ | |
+ ind = 0; | |
+ // send to all others | |
+ uint8_t send_buffer_can[PACKET_MAX_PL_LEN]; | |
+ | |
+ send_buffer_can[ind++] = packet_id; | |
+ | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1) { | |
+ comm_can_send_buffer(msg->id, send_buffer_can, len + 1, false); | |
+ } | |
+ } | |
+ } | |
+ | |
+ conf_general_store_mc_configuration(&mcconf); | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ conf_general_store_app_configuration(&appconf); | |
+ app_set_configuration(&appconf); | |
+ | |
+ timeout_configure(appconf.timeout_msec, appconf.timeout_brake_current); | |
+ | |
+ remote_Mode = 0; | |
+ break; | |
+ case COMM_SET_MOTOR_TYPE: | |
+ | |
+ appconf = *app_get_configuration(); | |
+ | |
+ bool change_allowed = false; | |
+ | |
+ ind = 0; | |
+ uint8_t new_motor_type = data[ind++]; | |
+ | |
+ if (new_motor_type == MOTOR_TYPE_FOC || new_motor_type == MOTOR_TYPE_BLDC) { | |
+ | |
+ mcconf = *mc_interface_get_configuration(); | |
+ | |
+ if (mcconf.motor_type != new_motor_type) { | |
+ | |
+ mc_configuration default_mcconf; | |
+ //get default settings | |
+ conf_general_get_default_mc_configuration(&default_mcconf); | |
+ | |
+ change_allowed = true; | |
+ | |
+ /*if (new_motor_type == MOTOR_TYPE_FOC && | |
+ (mcconf.foc_motor_l != default_mcconf.foc_motor_l | |
+ || mcconf.foc_motor_r != default_mcconf.foc_motor_r | |
+ || mcconf.foc_motor_flux_linkage != default_mcconf.foc_motor_flux_linkage)) { | |
+ change_allowed = true; | |
+ } | |
+ | |
+ if (new_motor_type == MOTOR_TYPE_BLDC && | |
+ (mcconf.sl_cycle_int_limit != default_mcconf.sl_cycle_int_limit | |
+ || mcconf.sl_bemf_coupling_k != default_mcconf.sl_bemf_coupling_k)) { | |
+ change_allowed = true; | |
+ }*/ | |
+ | |
+ | |
+ if (change_allowed) { | |
+ if (!appconf.send_can_status) { | |
+ ind = 0; | |
+ // send to all others | |
+ uint8_t send_buffer_can[PACKET_MAX_PL_LEN]; | |
+ | |
+ send_buffer_can[ind++] = packet_id; | |
+ send_buffer_can[ind++] = new_motor_type; | |
+ | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1) { | |
+ comm_can_send_buffer(msg->id, send_buffer_can, len + 1, false); | |
+ } | |
+ } | |
+ } | |
+ | |
+ //change motor config | |
+ mcconf.motor_type = new_motor_type; | |
+ | |
+ //write motor config | |
+ //conf_general_store_mc_configuration(&saved_mcconf); | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ if (!appconf.send_can_status) { | |
+ int32_t ind_motor_type = 0; | |
+ uint8_t send_buffer_motor_type[PACKET_MAX_PL_LEN]; | |
+ | |
+ send_buffer_motor_type[ind_motor_type++] = packet_id; | |
+ send_buffer_motor_type[ind_motor_type++] = new_motor_type; | |
+ commands_send_packet(send_buffer_motor_type, ind_motor_type); | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ //if (change_allowed == false && !appconf.send_can_status) { | |
+ if (!appconf.send_can_status) { | |
+ sendActualSpeedMode = true; | |
+ } | |
+ | |
+ break; | |
default: | |
break; | |
} | |
+ | |
+ if (sendActualSpeedMode) { | |
+ appconf = *app_get_configuration(); | |
+ mcconf = *mc_interface_get_configuration(); | |
+ | |
+ ind = 0; | |
+ send_buffer[ind++] = COMM_GET_SPEED_MODE; | |
+ send_buffer[ind++] = remote_Mode; | |
+ if(appconf.app_to_use == APP_NUNCHUK || appconf.app_to_use == APP_NRF){ | |
+ send_buffer[ind++] = appconf.app_chuk_conf.ctrl_type; | |
+ }else{ | |
+ send_buffer[ind++] = appconf.app_ppm_conf.ctrl_type; | |
+ } | |
+ | |
+ send_buffer[ind++] = mcconf.use_max_watt_limit; | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.watts_max), &ind); | |
+ | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_current_max * 10), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_in_current_max * 10), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_current_min * 10), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_in_current_min * 10), &ind); | |
+ | |
+ if(appconf.app_to_use == APP_NUNCHUK || appconf.app_to_use == APP_NRF){ | |
+ buffer_append_int16(send_buffer, (int16_t) (appconf.app_chuk_conf.rpm_lim_end / 10), &ind); | |
+ }else{ | |
+ buffer_append_int16(send_buffer, (int16_t) (appconf.app_ppm_conf.rpm_lim_end / 10), &ind); | |
+ } | |
+ | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_battery_cut_start * 100), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_battery_cut_end * 100), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_temp_fet_start * 100), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_temp_fet_end * 100), &ind); | |
+ | |
+ send_buffer[ind++] = appconf.app_to_use; | |
+ | |
+ send_buffer[ind++] = appconf.app_throttle_conf.adjustable_throttle_enabled; | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y1_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y2_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y3_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x1_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x2_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x3_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.bezier_reduce_factor * 100.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y1_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y2_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y3_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x1_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x2_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x3_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.bezier_neg_reduce_factor * 100.0), &ind); | |
+ | |
+ send_buffer[ind++] = mcconf.s_pid_breaking_enabled; | |
+ buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_kp * 1000000.0), &ind); | |
+ buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_ki * 1000000.0), &ind); | |
+ buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_kd * 1000000.0), &ind); | |
+ | |
+ send_buffer[ind++] = mcconf.motor_type; | |
+ | |
+ commands_send_packet(send_buffer, ind); | |
+ } | |
} | |
void commands_printf(char* format, ...) { | |
@@ -721,7 +1469,7 @@ | |
len = vsnprintf(print_buffer+1, 254, format, arg); | |
va_end (arg); | |
- if(len>0) { | |
+ if(len > 0) { | |
commands_send_packet((unsigned char*)print_buffer, (len<254)? len+1: 255); | |
} | |
} | |
@@ -770,6 +1518,20 @@ | |
return display_position_mode; | |
} | |
+void commands_set_app_data_handler(void(*func)(unsigned char *data, unsigned int len)) { | |
+ appdata_func = func; | |
+} | |
+ | |
+void commands_send_app_data(unsigned char *data, unsigned int len) { | |
+ int32_t index = 0; | |
+ | |
+ send_buffer[index++] = COMM_CUSTOM_APP_DATA; | |
+ memcpy(send_buffer + index, data, len); | |
+ index += len; | |
+ | |
+ commands_send_packet(send_buffer, index); | |
+} | |
+ | |
static THD_FUNCTION(detect_thread, arg) { | |
(void)arg; | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/commands.h Raptor2 Sources/bldc-firmware_2_80/commands.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/commands.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/commands.h 2016-09-19 10:06:42.000000000 +0100 | |
@@ -37,5 +37,7 @@ | |
void commands_send_rotor_pos(float rotor_pos); | |
void commands_send_experiment_samples(float *samples, int len); | |
disp_pos_mode commands_get_disp_pos_mode(void); | |
+void commands_set_app_data_handler(void(*func)(unsigned char *data, unsigned int len)); | |
+void commands_send_app_data(unsigned char *data, unsigned int len); | |
#endif /* COMMANDS_H_ */ | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/conf_general.c Raptor2 Sources/bldc-firmware_2_80/conf_general.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/conf_general.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/conf_general.c 2017-04-15 03:04:20.000000000 +0100 | |
@@ -47,7 +47,7 @@ | |
memset(VirtAddVarTab, 0, sizeof(VirtAddVarTab)); | |
int ind = 0; | |
- for (unsigned int i = 0;i < (sizeof(app_configuration) / 2);i++) { | |
+ for (unsigned int i = 0;i < (sizeof(mc_configuration) / 2);i++) { | |
VirtAddVarTab[ind++] = EEPROM_BASE_MCCONF + i; | |
} | |
@@ -89,7 +89,7 @@ | |
conf->app_ppm_conf.multi_esc = APPCONF_PPM_MULTI_ESC; | |
conf->app_ppm_conf.tc = APPCONF_PPM_TC; | |
conf->app_ppm_conf.tc_max_diff = APPCONF_PPM_TC_MAX_DIFF; | |
- | |
+ | |
conf->app_adc_conf.ctrl_type = APPCONF_ADC_CTRL_TYPE; | |
conf->app_adc_conf.hyst = APPCONF_ADC_HYST; | |
conf->app_adc_conf.voltage_start = APPCONF_ADC_VOLTAGE_START; | |
@@ -118,6 +118,45 @@ | |
conf->app_chuk_conf.multi_esc = APPCONF_CHUK_MULTI_ESC; | |
conf->app_chuk_conf.tc = APPCONF_CHUK_TC; | |
conf->app_chuk_conf.tc_max_diff = APPCONF_CHUK_TC_MAX_DIFF; | |
+ | |
+ conf->app_nrf_conf.speed = APPCONF_NRF_SPEED; | |
+ conf->app_nrf_conf.power = APPCONF_NRF_POWER; | |
+ conf->app_nrf_conf.crc_type = APPCONF_NRF_CRC; | |
+ conf->app_nrf_conf.retry_delay = APPCONF_NRF_RETR_DELAY; | |
+ conf->app_nrf_conf.retries = APPCONF_NRF_RETRIES; | |
+ conf->app_nrf_conf.channel = APPCONF_NRF_CHANNEL; | |
+ conf->app_nrf_conf.address[0] = APPCONF_NRF_ADDR_B0; | |
+ conf->app_nrf_conf.address[1] = APPCONF_NRF_ADDR_B1; | |
+ conf->app_nrf_conf.address[2] = APPCONF_NRF_ADDR_B2; | |
+ conf->app_nrf_conf.send_crc_ack = APPCONF_NRF_SEND_CRC_ACK; | |
+ | |
+ //new config | |
+ conf->app_ppm_conf.pulse_center = APPCONF_PPM_PULSE_CENTER; | |
+ conf->app_ppm_conf.tc_offset = APPCONF_PPM_TC_OFFSET; | |
+ conf->app_ppm_conf.cruise_left = CRUISE_CONTROL_MOTOR_SETTINGS; | |
+ conf->app_ppm_conf.cruise_right = CRUISE_CONTROL_MOTOR_SETTINGS; | |
+ conf->app_ppm_conf.max_erpm_for_dir_active = APPCONF_PPM_MAX_ERPM_FOR_DIR_ACTIVE; | |
+ conf->app_ppm_conf.max_erpm_for_dir = APPCONF_PPM_MAX_ERPM_FOR_DIR; | |
+ | |
+ conf->app_chuk_conf.tc_offset = APPCONF_CHUK_TC_OFFSET; | |
+ conf->app_chuk_conf.buttons_mirrored = APPCONF_CHUK_BUTTONS_MIRRORED; | |
+ | |
+ conf->app_throttle_conf.adjustable_throttle_enabled = APPCONF_ADJUSTABLE_THROTTLE_ENABLED; | |
+ conf->app_throttle_conf.y1_throttle = APPCONF_Y1_THROTTLE; | |
+ conf->app_throttle_conf.y2_throttle = APPCONF_Y2_THROTTLE; | |
+ conf->app_throttle_conf.y3_throttle = APPCONF_Y3_THROTTLE; | |
+ conf->app_throttle_conf.x1_throttle = APPCONF_X1_THROTTLE; | |
+ conf->app_throttle_conf.x2_throttle = APPCONF_X2_THROTTLE; | |
+ conf->app_throttle_conf.x3_throttle = APPCONF_X3_THROTTLE; | |
+ conf->app_throttle_conf.bezier_reduce_factor = APPCONF_BEZIER_REDUCE_FACTOR; | |
+ conf->app_throttle_conf.y1_neg_throttle = APPCONF_Y1_NEG_THROTTLE; | |
+ conf->app_throttle_conf.y2_neg_throttle = APPCONF_Y2_NEG_THROTTLE; | |
+ conf->app_throttle_conf.y3_neg_throttle = APPCONF_Y3_NEG_THROTTLE; | |
+ conf->app_throttle_conf.x1_neg_throttle = APPCONF_X1_NEG_THROTTLE; | |
+ conf->app_throttle_conf.x2_neg_throttle = APPCONF_X2_NEG_THROTTLE; | |
+ conf->app_throttle_conf.x3_neg_throttle = APPCONF_X3_NEG_THROTTLE; | |
+ conf->app_throttle_conf.bezier_neg_reduce_factor = APPCONF_BEZIER_REDUCE_NEG_FACTOR; | |
+ //new config end | |
} | |
/** | |
@@ -168,6 +207,16 @@ | |
conf->sl_cycle_int_rpm_br = MCCONF_SL_CYCLE_INT_BR; | |
conf->sl_bemf_coupling_k = MCCONF_SL_BEMF_COUPLING_K; | |
+ conf->hall_table[0] = MCCONF_HALL_TAB_0; | |
+ conf->hall_table[1] = MCCONF_HALL_TAB_1; | |
+ conf->hall_table[2] = MCCONF_HALL_TAB_2; | |
+ conf->hall_table[3] = MCCONF_HALL_TAB_3; | |
+ conf->hall_table[4] = MCCONF_HALL_TAB_4; | |
+ conf->hall_table[5] = MCCONF_HALL_TAB_5; | |
+ conf->hall_table[6] = MCCONF_HALL_TAB_6; | |
+ conf->hall_table[7] = MCCONF_HALL_TAB_7; | |
+ conf->hall_sl_erpm = MCCONF_HALL_ERPM; | |
+ | |
conf->foc_current_kp = MCCONF_FOC_CURRENT_KP; | |
conf->foc_current_ki = MCCONF_FOC_CURRENT_KI; | |
conf->foc_f_sw = MCCONF_FOC_F_SW; | |
@@ -189,25 +238,26 @@ | |
conf->foc_sl_openloop_time = MCCONF_FOC_SL_OPENLOOP_TIME; | |
conf->foc_sl_d_current_duty = MCCONF_FOC_SL_D_CURRENT_DUTY; | |
conf->foc_sl_d_current_factor = MCCONF_FOC_SL_D_CURRENT_FACTOR; | |
- | |
- conf->hall_table[0] = MCCONF_HALL_TAB_0; | |
- conf->hall_table[1] = MCCONF_HALL_TAB_1; | |
- conf->hall_table[2] = MCCONF_HALL_TAB_2; | |
- conf->hall_table[3] = MCCONF_HALL_TAB_3; | |
- conf->hall_table[4] = MCCONF_HALL_TAB_4; | |
- conf->hall_table[5] = MCCONF_HALL_TAB_5; | |
- conf->hall_table[6] = MCCONF_HALL_TAB_6; | |
- conf->hall_table[7] = MCCONF_HALL_TAB_7; | |
- conf->hall_sl_erpm = MCCONF_HALL_ERPM; | |
+ conf->foc_hall_table[0] = MCCONF_FOC_HALL_TAB_0; | |
+ conf->foc_hall_table[1] = MCCONF_FOC_HALL_TAB_1; | |
+ conf->foc_hall_table[2] = MCCONF_FOC_HALL_TAB_2; | |
+ conf->foc_hall_table[3] = MCCONF_FOC_HALL_TAB_3; | |
+ conf->foc_hall_table[4] = MCCONF_FOC_HALL_TAB_4; | |
+ conf->foc_hall_table[5] = MCCONF_FOC_HALL_TAB_5; | |
+ conf->foc_hall_table[6] = MCCONF_FOC_HALL_TAB_6; | |
+ conf->foc_hall_table[7] = MCCONF_FOC_HALL_TAB_7; | |
+ conf->foc_sl_erpm = MCCONF_FOC_SL_ERPM; | |
conf->s_pid_kp = MCCONF_S_PID_KP; | |
conf->s_pid_ki = MCCONF_S_PID_KI; | |
conf->s_pid_kd = MCCONF_S_PID_KD; | |
conf->s_pid_min_erpm = MCCONF_S_PID_MIN_RPM; | |
+ conf->s_pid_breaking_enabled = MCCONF_S_PID_BREAKING_ENABLED; | |
conf->p_pid_kp = MCCONF_P_PID_KP; | |
conf->p_pid_ki = MCCONF_P_PID_KI; | |
conf->p_pid_kd = MCCONF_P_PID_KD; | |
+ conf->p_pid_ang_div = MCCONF_P_PID_ANG_DIV; | |
conf->cc_startup_boost_duty = MCCONF_CC_STARTUP_BOOST_DUTY; | |
conf->cc_min_current = MCCONF_CC_MIN_CURRENT; | |
@@ -219,6 +269,10 @@ | |
conf->m_duty_ramp_step_rpm_lim = MCCONF_M_RAMP_STEP_RPM_LIM; | |
conf->m_current_backoff_gain = MCCONF_M_CURRENT_BACKOFF_GAIN; | |
conf->m_encoder_counts = MCCONF_M_ENCODER_COUNTS; | |
+ conf->m_sensor_port_mode = MCCONF_M_SENSOR_PORT_MODE; | |
+ | |
+ conf->use_max_watt_limit = MCCONF_USE_MAX_WATT_LIMIT; | |
+ conf->watts_max = MCCONF_WATT_MAX; | |
} | |
/** | |
@@ -242,6 +296,32 @@ | |
} | |
} | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(app_configuration) / 2);i++) { | |
+ if (EE_ReadVariable(EEPROM_BASE_APPCONF + i, &var) == 0) { | |
+ conf_addr[2 * i] = (var >> 8) & 0xFF; | |
+ conf_addr[2 * i + 1] = var & 0xFF; | |
+ } else { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(app_configuration) / 2);i++) { | |
+ if (EE_ReadVariable(EEPROM_BASE_APPCONF + i, &var) == 0) { | |
+ conf_addr[2 * i] = (var >> 8) & 0xFF; | |
+ conf_addr[2 * i + 1] = var & 0xFF; | |
+ } else { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
// Set the default configuration | |
if (!is_ok) { | |
conf_general_get_default_app_configuration(conf); | |
@@ -277,6 +357,34 @@ | |
break; | |
} | |
} | |
+ | |
+ // try one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(app_configuration) / 2);i++) { | |
+ var = (conf_addr[2 * i] << 8) & 0xFF00; | |
+ var |= conf_addr[2 * i + 1] & 0xFF; | |
+ | |
+ if (EE_WriteVariable(EEPROM_BASE_APPCONF + i, var) != FLASH_COMPLETE) { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
+ // try again one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(app_configuration) / 2);i++) { | |
+ var = (conf_addr[2 * i] << 8) & 0xFF00; | |
+ var |= conf_addr[2 * i + 1] & 0xFF; | |
+ | |
+ if (EE_WriteVariable(EEPROM_BASE_APPCONF + i, var) != FLASH_COMPLETE) { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); | |
utils_sys_unlock_cnt(); | |
@@ -305,6 +413,34 @@ | |
} | |
} | |
+ // try one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(mc_configuration) / 2);i++) { | |
+ if (EE_ReadVariable(EEPROM_BASE_MCCONF + i, &var) == 0) { | |
+ conf_addr[2 * i] = (var >> 8) & 0xFF; | |
+ conf_addr[2 * i + 1] = var & 0xFF; | |
+ } else { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
+ // try another one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(mc_configuration) / 2);i++) { | |
+ if (EE_ReadVariable(EEPROM_BASE_MCCONF + i, &var) == 0) { | |
+ conf_addr[2 * i] = (var >> 8) & 0xFF; | |
+ conf_addr[2 * i + 1] = var & 0xFF; | |
+ } else { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
if (!is_ok) { | |
conf_general_get_default_mc_configuration(conf); | |
} | |
@@ -339,6 +475,34 @@ | |
break; | |
} | |
} | |
+ | |
+ // try one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(mc_configuration) / 2);i++) { | |
+ var = (conf_addr[2 * i] << 8) & 0xFF00; | |
+ var |= conf_addr[2 * i + 1] & 0xFF; | |
+ | |
+ if (EE_WriteVariable(EEPROM_BASE_MCCONF + i, var) != FLASH_COMPLETE) { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
+ // try again one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(mc_configuration) / 2);i++) { | |
+ var = (conf_addr[2 * i] << 8) & 0xFF00; | |
+ var |= conf_addr[2 * i + 1] & 0xFF; | |
+ | |
+ if (EE_WriteVariable(EEPROM_BASE_MCCONF + i, var) != FLASH_COMPLETE) { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); | |
utils_sys_unlock_cnt(); | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/conf_general.h Raptor2 Sources/bldc-firmware_2_80/conf_general.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/conf_general.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/conf_general.h 2017-04-17 04:06:52.000000000 +0100 | |
@@ -27,18 +27,18 @@ | |
// Firmware version | |
#define FW_VERSION_MAJOR 2 | |
-#define FW_VERSION_MINOR 8 | |
+#define FW_VERSION_MINOR 80 | |
#include "datatypes.h" | |
/* | |
* Settings | |
*/ | |
-#define AUTO_PRINT_FAULTS 0 | |
#define SYSTEM_CORE_CLOCK 168000000 | |
// Settings and parameters to override | |
//#define VIN_R1 33000.0 | |
+#define VIN_R1 39000.0 | |
//#define VIN_R2 2200.0 | |
//#define CURRENT_AMP_GAIN 10.0 | |
//#define CURRENT_SHUNT_RES 0.0005 | |
@@ -57,7 +57,7 @@ | |
//#define HW_VERSION_46 // Also for 4.7 | |
//#define HW_VERSION_48 | |
//#define HW_VERSION_49 | |
-#define HW_VERSION_410 // Also for 4.11 | |
+#define HW_VERSION_410 // Also for 4.11 and 4.12 | |
//#define HW_VERSION_R2 | |
//#define HW_VERSION_VICTOR_R1A | |
#endif | |
@@ -65,15 +65,15 @@ | |
/* | |
* Select default user motor configuration | |
*/ | |
-//#define MCCONF_DEFAULT_USER "mcconf_outrunner2.h" | |
//#define MCCONF_DEFAULT_USER "mcconf_sten.h" | |
-//#define MCCONF_DEFAULT_USER "mcconf_foc_erwin.h" | |
-//#define MCCONF_DEFAULT_USER "mcconf_foc_scorpion.h" | |
+//#define MCCONF_DEFAULT_USER "mcconf_sp_540kv.h" | |
+//#define MCCONF_DEFAULT_USER "mcconf_castle_2028.h" | |
/* | |
* Select default user app configuration | |
*/ | |
//#define APPCONF_DEFAULT_USER "appconf_example_ppm.h" | |
+//#define APPCONF_DEFAULT_USER "appconf_custom.h" | |
/* | |
* Select which custom application to use. To configure the default applications and | |
@@ -83,13 +83,6 @@ | |
//#define USE_APP_STEN | |
/* | |
- * Use encoder | |
- */ | |
-#ifndef ENCODER_ENABLE | |
-#define ENCODER_ENABLE 0 | |
-#endif | |
- | |
-/* | |
* Enable CAN-bus | |
*/ | |
#define CAN_ENABLE 1 | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/datatypes.h Raptor2 Sources/bldc-firmware_2_80/datatypes.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/datatypes.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/datatypes.h 2017-04-13 18:02:30.000000000 +0100 | |
@@ -38,6 +38,13 @@ | |
} mc_state; | |
typedef enum { | |
+ CRUISE_CONTROL_MOTOR_SETTINGS = 0, | |
+ CRUISE_CONTROL_BRAKING_DISABLED, | |
+ CRUISE_CONTROL_BRAKING_ENABLED, | |
+ CRUISE_CONTROL_INACTIVE | |
+} ppm_cruise; | |
+ | |
+typedef enum { | |
PWM_MODE_NONSYNCHRONOUS_HISW = 0, // This mode is not recommended | |
PWM_MODE_SYNCHRONOUS, // The recommended and most tested mode | |
PWM_MODE_BIPOLAR // Some glitches occasionally, can kill MOSFETs | |
@@ -56,7 +63,8 @@ | |
typedef enum { | |
FOC_SENSOR_MODE_SENSORLESS = 0, | |
- FOC_SENSOR_MODE_ENCODER | |
+ FOC_SENSOR_MODE_ENCODER, | |
+ FOC_SENSOR_MODE_HALL | |
} mc_foc_sensor_mode; | |
typedef enum { | |
@@ -89,10 +97,17 @@ | |
DISP_POS_MODE_INDUCTANCE, | |
DISP_POS_MODE_OBSERVER, | |
DISP_POS_MODE_ENCODER, | |
- DISP_POS_MODE_ENCODER_POS_ERROR, | |
+ DISP_POS_MODE_PID_POS, | |
+ DISP_POS_MODE_PID_POS_ERROR, | |
DISP_POS_MODE_ENCODER_OBSERVER_ERROR | |
} disp_pos_mode; | |
+typedef enum { | |
+ SENSOR_PORT_MODE_HALL = 0, | |
+ SENSOR_PORT_MODE_ABI, | |
+ SENSOR_PORT_MODE_AS5047_SPI | |
+} sensor_port_mode; | |
+ | |
typedef struct { | |
float cycle_int_limit; | |
float cycle_int_limit_running; | |
@@ -115,6 +130,8 @@ | |
float l_in_current_max; | |
float l_in_current_min; | |
float l_abs_current_max; | |
+ bool use_max_watt_limit; | |
+ float watts_max; | |
float l_min_erpm; | |
float l_max_erpm; | |
float l_max_erpm_fbrake; | |
@@ -169,15 +186,19 @@ | |
float foc_sl_d_current_duty; | |
float foc_sl_d_current_factor; | |
mc_foc_sensor_mode foc_sensor_mode; | |
+ uint8_t foc_hall_table[8]; | |
+ float foc_sl_erpm; | |
// Speed PID | |
float s_pid_kp; | |
float s_pid_ki; | |
float s_pid_kd; | |
float s_pid_min_erpm; | |
+ bool s_pid_breaking_enabled; | |
// Pos PID | |
float p_pid_kp; | |
float p_pid_ki; | |
float p_pid_kd; | |
+ float p_pid_ang_div; | |
// Current controller | |
float cc_startup_boost_duty; | |
float cc_min_current; | |
@@ -189,6 +210,7 @@ | |
float m_duty_ramp_step_rpm_lim; | |
float m_current_backoff_gain; | |
uint32_t m_encoder_counts; | |
+ sensor_port_mode m_sensor_port_mode; | |
} mc_configuration; | |
// Applications to use | |
@@ -213,7 +235,11 @@ | |
PPM_CTRL_TYPE_DUTY, | |
PPM_CTRL_TYPE_DUTY_NOREV, | |
PPM_CTRL_TYPE_PID, | |
- PPM_CTRL_TYPE_PID_NOREV | |
+ PPM_CTRL_TYPE_PID_NOREV, | |
+ PPM_CTRL_TYPE_WATT_NOREV_BRAKE, | |
+ PPM_CTRL_TYPE_PID_NOACCELERATION, | |
+ PPM_CTRL_TYPE_CRUISE_CONTROL_SECONDARY_CHANNEL, | |
+ PPM_CTRL_TYPE_WATT | |
} ppm_control_type; | |
typedef struct { | |
@@ -229,6 +255,12 @@ | |
bool multi_esc; | |
bool tc; | |
float tc_max_diff; | |
+ float pulse_center; | |
+ float tc_offset; | |
+ ppm_cruise cruise_left; | |
+ ppm_cruise cruise_right; | |
+ bool max_erpm_for_dir_active; | |
+ float max_erpm_for_dir; | |
} ppm_config; | |
// ADC control types | |
@@ -239,6 +271,7 @@ | |
ADC_CTRL_TYPE_CURRENT_REV_BUTTON, | |
ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_CENTER, | |
ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_BUTTON, | |
+ ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_ADC, | |
ADC_CTRL_TYPE_DUTY, | |
ADC_CTRL_TYPE_DUTY_REV_CENTER, | |
ADC_CTRL_TYPE_DUTY_REV_BUTTON | |
@@ -266,7 +299,9 @@ | |
typedef enum { | |
CHUK_CTRL_TYPE_NONE = 0, | |
CHUK_CTRL_TYPE_CURRENT, | |
- CHUK_CTRL_TYPE_CURRENT_NOREV | |
+ CHUK_CTRL_TYPE_CURRENT_NOREV, | |
+ CHUK_CTRL_TYPE_WATT, | |
+ CHUK_CTRL_TYPE_WATT_NOREV | |
} chuk_control_type; | |
typedef struct { | |
@@ -280,8 +315,84 @@ | |
bool multi_esc; | |
bool tc; | |
float tc_max_diff; | |
+ float tc_offset; | |
+ bool buttons_mirrored; | |
} chuk_config; | |
+// NRF Datatypes | |
+typedef enum { | |
+ NRF_SPEED_250K = 0, | |
+ NRF_SPEED_1M, | |
+ NRF_SPEED_2M | |
+} NRF_SPEED; | |
+ | |
+typedef enum { | |
+ NRF_POWER_M18DBM = 0, | |
+ NRF_POWER_M12DBM, | |
+ NRF_POWER_M6DBM, | |
+ NRF_POWER_0DBM | |
+} NRF_POWER; | |
+ | |
+typedef enum { | |
+ NRF_AW_3 = 0, | |
+ NRF_AW_4, | |
+ NRF_AW_5 | |
+} NRF_AW; | |
+ | |
+typedef enum { | |
+ NRF_CRC_DISABLED = 0, | |
+ NRF_CRC_1B, | |
+ NRF_CRC_2B | |
+} NRF_CRC; | |
+ | |
+typedef enum { | |
+ NRF_RETR_DELAY_250US = 0, | |
+ NRF_RETR_DELAY_500US, | |
+ NRF_RETR_DELAY_750US, | |
+ NRF_RETR_DELAY_1000US, | |
+ NRF_RETR_DELAY_1250US, | |
+ NRF_RETR_DELAY_1500US, | |
+ NRF_RETR_DELAY_1750US, | |
+ NRF_RETR_DELAY_2000US, | |
+ NRF_RETR_DELAY_2250US, | |
+ NRF_RETR_DELAY_2500US, | |
+ NRF_RETR_DELAY_2750US, | |
+ NRF_RETR_DELAY_3000US, | |
+ NRF_RETR_DELAY_3250US, | |
+ NRF_RETR_DELAY_3500US, | |
+ NRF_RETR_DELAY_3750US, | |
+ NRF_RETR_DELAY_4000US | |
+} NRF_RETR_DELAY; | |
+ | |
+typedef struct { | |
+ NRF_SPEED speed; | |
+ NRF_POWER power; | |
+ NRF_CRC crc_type; | |
+ NRF_RETR_DELAY retry_delay; | |
+ unsigned char retries; | |
+ unsigned char channel; | |
+ unsigned char address[3]; | |
+ bool send_crc_ack; | |
+} nrf_config; | |
+ | |
+typedef struct { | |
+ bool adjustable_throttle_enabled; | |
+ float y1_throttle; | |
+ float y2_throttle; | |
+ float y3_throttle; | |
+ float x1_throttle; | |
+ float x2_throttle; | |
+ float x3_throttle; | |
+ float bezier_reduce_factor; | |
+ float y1_neg_throttle; | |
+ float y2_neg_throttle; | |
+ float y3_neg_throttle; | |
+ float x1_neg_throttle; | |
+ float x2_neg_throttle; | |
+ float x3_neg_throttle; | |
+ float bezier_neg_reduce_factor; | |
+} throttle_config; | |
+ | |
typedef struct { | |
// Settings | |
uint8_t controller_id; | |
@@ -304,6 +415,11 @@ | |
// Nunchuk application settings | |
chuk_config app_chuk_conf; | |
+ | |
+ // NRF application settings | |
+ nrf_config app_nrf_conf; | |
+ | |
+ throttle_config app_throttle_conf; | |
} app_configuration; | |
// Communication commands | |
@@ -335,12 +451,20 @@ | |
COMM_DETECT_MOTOR_R_L, | |
COMM_DETECT_MOTOR_FLUX_LINKAGE, | |
COMM_DETECT_ENCODER, | |
+ COMM_DETECT_HALL_FOC, | |
COMM_REBOOT, | |
COMM_ALIVE, | |
COMM_GET_DECODED_PPM, | |
COMM_GET_DECODED_ADC, | |
COMM_GET_DECODED_CHUK, | |
- COMM_FORWARD_CAN | |
+ COMM_FORWARD_CAN, | |
+ COMM_SET_CHUCK_DATA, | |
+ COMM_CUSTOM_APP_DATA, | |
+ COMM_SET_SPEED_MODE, | |
+ COMM_CHANGE_SPEED_MODE, | |
+ COMM_GET_SPEED_MODE, | |
+ COMM_SET_CURRENT_CONF_AS_DEFAULT, | |
+ COMM_SET_MOTOR_TYPE | |
} COMM_PACKET_ID; | |
// CAN commands | |
@@ -354,7 +478,9 @@ | |
CAN_PACKET_FILL_RX_BUFFER_LONG, | |
CAN_PACKET_PROCESS_RX_BUFFER, | |
CAN_PACKET_PROCESS_SHORT_BUFFER, | |
- CAN_PACKET_STATUS | |
+ CAN_PACKET_STATUS, | |
+ CAN_PACKET_SET_SERVO, | |
+ CAN_PACKET_SET_BRAKE_SERVO | |
} CAN_PACKET_ID; | |
// Logged fault data | |
@@ -401,7 +527,8 @@ | |
systime_t rx_time; | |
float rpm; | |
float current; | |
- float duty; | |
+ int8_t duty; | |
+ ppm_cruise cruise_control_status; | |
} can_status_msg; | |
typedef struct { | |
@@ -429,20 +556,20 @@ | |
float temp_mos2; | |
float temp_mos3; | |
float temp_mos4; | |
- float temp_mos5; | |
- float temp_mos6; | |
- float temp_pcb; | |
- float current_motor; | |
- float current_in; | |
- float rpm; | |
- float duty_now; | |
- float amp_hours; | |
- float amp_hours_charged; | |
- float watt_hours; | |
- float watt_hours_charged; | |
- int tachometer; | |
- int tachometer_abs; | |
- mc_fault_code fault_code; | |
+ float temp_mos5; | |
+ float temp_mos6; | |
+ float temp_pcb; | |
+ float current_motor; | |
+ float current_in; | |
+ float rpm; | |
+ float duty_now; | |
+ float amp_hours; | |
+ float amp_hours_charged; | |
+ float watt_hours; | |
+ float watt_hours_charged; | |
+ int tachometer; | |
+ int tachometer_abs; | |
+ mc_fault_code fault_code; | |
} mc_values; | |
#endif /* DATATYPES_H_ */ | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/eeprom.h Raptor2 Sources/bldc-firmware_2_80/eeprom.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/eeprom.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/eeprom.h 2017-04-13 18:03:20.000000000 +0100 | |
@@ -69,7 +69,7 @@ | |
#define PAGE_FULL ((uint8_t)0x80) | |
/* Variables' number */ | |
-#define NB_OF_VAR ((uint8_t)160) | |
+#define NB_OF_VAR ((uint8_t)255) | |
/* Exported types ------------------------------------------------------------*/ | |
/* Exported macro ------------------------------------------------------------*/ | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/encoder.c Raptor2 Sources/bldc-firmware_2_80/encoder.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/encoder.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/encoder.c 2016-09-19 10:06:24.000000000 +0100 | |
@@ -1,5 +1,5 @@ | |
/* | |
- Copyright 2012-2015 Benjamin Vedder benjamin@vedder.se | |
+ Copyright 2012-2016 Benjamin Vedder benjamin@vedder.se | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
@@ -15,26 +15,64 @@ | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
-/* | |
- * encoder.c | |
- * | |
- * Created on: 7 mar 2015 | |
- * Author: benjamin | |
- */ | |
- | |
#include "encoder.h" | |
#include "ch.h" | |
#include "hal.h" | |
#include "stm32f4xx_conf.h" | |
#include "hw.h" | |
+#include "utils.h" | |
+ | |
+// Defines | |
+#define AS5047P_READ_ANGLECOM (0x3FFF | 0x4000 | 0x8000) // This is just ones | |
+#define AS5047_SAMPLE_RATE_HZ 20000 | |
+ | |
+#define SPI_SW_MISO_GPIO HW_HALL_ENC_GPIO2 | |
+#define SPI_SW_MISO_PIN HW_HALL_ENC_PIN2 | |
+#define SPI_SW_SCK_GPIO HW_HALL_ENC_GPIO1 | |
+#define SPI_SW_SCK_PIN HW_HALL_ENC_PIN1 | |
+#define SPI_SW_CS_GPIO HW_HALL_ENC_GPIO3 | |
+#define SPI_SW_CS_PIN HW_HALL_ENC_PIN3 | |
+ | |
+// Private types | |
+typedef enum { | |
+ ENCODER_MODE_NONE = 0, | |
+ ENCODER_MODE_ABI, | |
+ ENCODER_MODE_AS5047P_SPI | |
+} encoder_mode; | |
// Private variables | |
-static bool index_found; | |
+static bool index_found = false; | |
static uint32_t enc_counts = 10000; | |
+static encoder_mode mode = ENCODER_MODE_NONE; | |
+static float last_enc_angle = 0.0; | |
+ | |
+// Private functions | |
+uint16_t spi_exchange(uint16_t x); | |
+static void spi_transfer(uint16_t *in_buf, const uint16_t *out_buf, int length); | |
+static void spi_begin(void); | |
+static void spi_end(void); | |
+static void spi_delay(void); | |
+ | |
+void encoder_deinit(void) { | |
+ nvicDisableVector(HW_ENC_EXTI_CH); | |
+ nvicDisableVector(HW_ENC_TIM_ISR_CH); | |
+ | |
+ TIM_DeInit(HW_ENC_TIM); | |
+ | |
+ palSetPadMode(SPI_SW_MISO_GPIO, SPI_SW_MISO_PIN, PAL_MODE_INPUT_PULLUP); | |
+ palSetPadMode(SPI_SW_SCK_GPIO, SPI_SW_SCK_PIN, PAL_MODE_INPUT_PULLUP); | |
+ palSetPadMode(SPI_SW_CS_GPIO, SPI_SW_CS_PIN, PAL_MODE_INPUT_PULLUP); | |
-void encoder_init(uint32_t counts) { | |
+ palSetPadMode(HW_HALL_ENC_GPIO1, HW_HALL_ENC_PIN1, PAL_MODE_INPUT_PULLUP); | |
+ palSetPadMode(HW_HALL_ENC_GPIO2, HW_HALL_ENC_PIN2, PAL_MODE_INPUT_PULLUP); | |
+ | |
+ index_found = false; | |
+ mode = ENCODER_MODE_NONE; | |
+ last_enc_angle = 0.0; | |
+} | |
+ | |
+void encoder_init_abi(uint32_t counts) { | |
EXTI_InitTypeDef EXTI_InitStructure; | |
- NVIC_InitTypeDef NVIC_InitStructure; | |
// Initialize variables | |
index_found = false; | |
@@ -61,7 +99,7 @@ | |
TIM_ICPolarity_Rising); | |
TIM_SetAutoreload(HW_ENC_TIM, enc_counts - 1); | |
- TIM_Cmd (HW_ENC_TIM, ENABLE); | |
+ TIM_Cmd(HW_ENC_TIM, ENABLE); | |
// Interrupt on index pulse | |
@@ -76,15 +114,62 @@ | |
EXTI_Init(&EXTI_InitStructure); | |
// Enable and set EXTI Line Interrupt to the highest priority | |
- NVIC_InitStructure.NVIC_IRQChannel = HW_ENC_EXTI_CH; | |
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; | |
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; | |
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; | |
- NVIC_Init(&NVIC_InitStructure); | |
+ nvicEnableVector(HW_ENC_EXTI_CH, 0); | |
+ | |
+ mode = ENCODER_MODE_ABI; | |
+} | |
+ | |
+void encoder_init_as5047p_spi(void) { | |
+ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; | |
+ | |
+ palSetPadMode(SPI_SW_MISO_GPIO, SPI_SW_MISO_PIN, PAL_MODE_INPUT); | |
+ palSetPadMode(SPI_SW_SCK_GPIO, SPI_SW_SCK_PIN, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); | |
+ palSetPadMode(SPI_SW_CS_GPIO, SPI_SW_CS_PIN, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); | |
+ | |
+ // Enable timer clock | |
+ HW_ENC_TIM_CLK_EN(); | |
+ | |
+ // Time Base configuration | |
+ TIM_TimeBaseStructure.TIM_Prescaler = 0; | |
+ TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; | |
+ TIM_TimeBaseStructure.TIM_Period = ((168000000 / 2 / AS5047_SAMPLE_RATE_HZ) - 1); | |
+ TIM_TimeBaseStructure.TIM_ClockDivision = 0; | |
+ TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; | |
+ TIM_TimeBaseInit(HW_ENC_TIM, &TIM_TimeBaseStructure); | |
+ | |
+ // Enable overflow interrupt | |
+ TIM_ITConfig(HW_ENC_TIM, TIM_IT_Update, ENABLE); | |
+ | |
+ // Enable timer | |
+ TIM_Cmd(HW_ENC_TIM, ENABLE); | |
+ | |
+ nvicEnableVector(HW_ENC_TIM_ISR_CH, 6); | |
+ | |
+ mode = ENCODER_MODE_AS5047P_SPI; | |
+ index_found = true; | |
+} | |
+ | |
+bool encoder_is_configured(void) { | |
+ return mode != ENCODER_MODE_NONE; | |
} | |
float encoder_read_deg(void) { | |
- return ((float)HW_ENC_TIM->CNT * 360.0) / (float)enc_counts; | |
+ static float angle = 0.0; | |
+ | |
+ switch (mode) { | |
+ case ENCODER_MODE_ABI: | |
+ angle = ((float)HW_ENC_TIM->CNT * 360.0) / (float)enc_counts; | |
+ break; | |
+ | |
+ case ENCODER_MODE_AS5047P_SPI: | |
+ angle = last_enc_angle; | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+ | |
+ return angle; | |
} | |
/** | |
@@ -96,6 +181,20 @@ | |
} | |
/** | |
+ * Timer interrupt | |
+ */ | |
+void encoder_tim_isr(void) { | |
+ uint16_t pos; | |
+ | |
+ spi_begin(); | |
+ spi_transfer(&pos, 0, 1); | |
+ spi_end(); | |
+ | |
+ pos &= 0x3FFF; | |
+ last_enc_angle = ((float)pos * 360.0) / 16384.0; | |
+} | |
+ | |
+/** | |
* Set the number of encoder counts. | |
* | |
* @param counts | |
@@ -118,3 +217,53 @@ | |
bool encoder_index_found(void) { | |
return index_found; | |
} | |
+ | |
+// Software SPI | |
+uint16_t spi_exchange(uint16_t x) { | |
+ uint16_t rx; | |
+ spi_transfer(&rx, &x, 1); | |
+ return rx; | |
+} | |
+ | |
+static void spi_transfer(uint16_t *in_buf, const uint16_t *out_buf, int length) { | |
+ for (int i = 0;i < length;i++) { | |
+ uint16_t send = out_buf ? out_buf[i] : 0xFFFF; | |
+ uint16_t recieve = 0; | |
+ | |
+ for (int bit = 0;bit < 16;bit++) { | |
+ //palWritePad(HW_SPI_PORT_MOSI, HW_SPI_PIN_MOSI, send >> 15); | |
+ send <<= 1; | |
+ | |
+ spi_delay(); | |
+ palSetPad(SPI_SW_SCK_GPIO, SPI_SW_SCK_PIN); | |
+ spi_delay(); | |
+ | |
+ recieve <<= 1; | |
+ if (palReadPad(SPI_SW_MISO_GPIO, SPI_SW_MISO_PIN)) { | |
+ recieve |= 1; | |
+ } | |
+ | |
+ palClearPad(SPI_SW_SCK_GPIO, SPI_SW_SCK_PIN); | |
+ spi_delay(); | |
+ } | |
+ | |
+ if (in_buf) { | |
+ in_buf[i] = recieve; | |
+ } | |
+ } | |
+} | |
+ | |
+static void spi_begin(void) { | |
+ palClearPad(SPI_SW_CS_GPIO, SPI_SW_CS_PIN); | |
+} | |
+ | |
+static void spi_end(void) { | |
+ palSetPad(SPI_SW_CS_GPIO, SPI_SW_CS_PIN); | |
+} | |
+ | |
+static void spi_delay(void) { | |
+ __NOP(); | |
+ __NOP(); | |
+ __NOP(); | |
+ __NOP(); | |
+} | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/encoder.h Raptor2 Sources/bldc-firmware_2_80/encoder.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/encoder.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/encoder.h 2016-09-19 10:06:22.000000000 +0100 | |
@@ -28,9 +28,13 @@ | |
#include "conf_general.h" | |
// Functions | |
-void encoder_init(uint32_t counts); | |
+void encoder_deinit(void); | |
+void encoder_init_abi(uint32_t counts); | |
+void encoder_init_as5047p_spi(void); | |
+bool encoder_is_configured(void); | |
float encoder_read_deg(void); | |
void encoder_reset(void); | |
+void encoder_tim_isr(void); | |
void encoder_set_counts(uint32_t counts); | |
bool encoder_index_found(void); | |
Only in Raptor2 Sources/bldc-firmware_2_80: gpl.txt | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/halconf.h Raptor2 Sources/bldc-firmware_2_80/halconf.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/halconf.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/halconf.h 2016-09-19 10:06:16.000000000 +0100 | |
@@ -146,7 +146,7 @@ | |
* @brief Enables the SPI subsystem. | |
*/ | |
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) | |
-#define HAL_USE_SPI FALSE | |
+#define HAL_USE_SPI TRUE | |
#endif | |
/** | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_40.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_40.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_40.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_40.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -146,6 +146,8 @@ | |
#define HW_ENC_EXTI_CH EXTI9_5_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line8 | |
#define HW_ENC_EXTI_ISR_VEC EXTI9_5_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN HW_ICU_GPIO | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_410.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_410.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_410.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_410.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -148,6 +148,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN GPIOA | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_45.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_45.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_45.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_45.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -146,6 +146,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN HW_ICU_GPIO | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_46.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_46.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_46.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_46.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -154,6 +154,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN HW_ICU_GPIO | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_48.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_48.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_48.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_48.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -148,6 +148,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN GPIOB | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_49.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_49.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_49.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_49.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -148,6 +148,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN GPIOB | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_r2.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_r2.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_r2.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_r2.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -156,6 +156,8 @@ | |
#define HW_ENC_EXTI_CH EXTI9_5_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line8 | |
#define HW_ENC_EXTI_ISR_VEC EXTI9_5_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM3_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM3_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN HW_ICU_GPIO | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_victor_r1a.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_victor_r1a.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/hwconf/hw_victor_r1a.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_victor_r1a.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -146,6 +146,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN HW_ICU_GPIO | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/irq_handlers.c Raptor2 Sources/bldc-firmware_2_80/irq_handlers.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/irq_handlers.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/irq_handlers.c 2016-09-19 10:06:12.000000000 +0100 | |
@@ -19,7 +19,6 @@ | |
#include "hal.h" | |
#include "stm32f4xx_conf.h" | |
#include "isr_vector_table.h" | |
-#include "main.h" | |
#include "mc_interface.h" | |
#include "servo.h" | |
#include "hw.h" | |
@@ -49,3 +48,12 @@ | |
EXTI_ClearITPendingBit(HW_ENC_EXTI_LINE); | |
} | |
} | |
+ | |
+CH_IRQ_HANDLER(HW_ENC_TIM_ISR_VEC) { | |
+ if (TIM_GetITStatus(HW_ENC_TIM, TIM_IT_Update) != RESET) { | |
+ encoder_tim_isr(); | |
+ | |
+ // Clear the IT pending bit | |
+ TIM_ClearITPendingBit(HW_ENC_TIM, TIM_IT_Update); | |
+ } | |
+} | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/main.c Raptor2 Sources/bldc-firmware_2_80/main.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/main.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/main.c 2016-09-19 10:05:50.000000000 +0100 | |
@@ -24,7 +24,6 @@ | |
#include <string.h> | |
#include <stdlib.h> | |
-#include "main.h" | |
#include "mc_interface.h" | |
#include "mcpwm.h" | |
#include "mcpwm_foc.h" | |
@@ -68,55 +67,17 @@ | |
* | |
*/ | |
-/* | |
- * Notes: | |
- * | |
- * Disable USB VBUS sensing: | |
- * ChibiOS-RT-master/os/hal/platforms/STM32/OTGv1/usb_lld.c | |
- * | |
- * change | |
- * otgp->GCCFG = GCCFG_VBUSASEN | GCCFG_VBUSBSEN | GCCFG_PWRDWN; | |
- * to | |
- * otgp->GCCFG = GCCFG_NOVBUSSENS | GCCFG_PWRDWN; | |
- * | |
- * This should be handled automatically with the latest version of | |
- * ChibiOS since I have added an option to the makefile. | |
- * | |
- */ | |
- | |
// Private variables | |
-#define ADC_SAMPLE_MAX_LEN 2000 | |
-static volatile int16_t curr0_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t curr1_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t ph1_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t ph2_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t ph3_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t vzero_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile uint8_t status_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t curr_fir_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t f_sw_samples[ADC_SAMPLE_MAX_LEN]; | |
- | |
-static volatile int sample_len = 1000; | |
-static volatile int sample_int = 1; | |
-static volatile int sample_ready = 1; | |
-static volatile int sample_now = 0; | |
-static volatile int sample_at_start = 0; | |
-static volatile int start_comm = 0; | |
-static volatile float main_last_adc_duration = 0.0; | |
+ | |
static THD_WORKING_AREA(periodic_thread_wa, 1024); | |
-static THD_WORKING_AREA(sample_send_thread_wa, 1024); | |
static THD_WORKING_AREA(timer_thread_wa, 128); | |
-static thread_t *sample_send_tp; | |
- | |
static THD_FUNCTION(periodic_thread, arg) { | |
(void)arg; | |
chRegSetThreadName("Main periodic"); | |
- int fault_print = 0; | |
- | |
for(;;) { | |
if (mc_interface_get_state() == MC_STATE_RUNNING) { | |
ledpwm_set_intensity(LED_GREEN, 1.0); | |
@@ -126,12 +87,6 @@ | |
mc_fault_code fault = mc_interface_get_fault(); | |
if (fault != FAULT_CODE_NONE) { | |
- if (!fault_print && AUTO_PRINT_FAULTS) { | |
- fault_print = 1; | |
- commands_printf("%s\n", mc_interface_fault_to_string( | |
- mc_interface_get_fault())); | |
- } | |
- | |
for (int i = 0;i < (int)fault;i++) { | |
ledpwm_set_intensity(LED_RED, 1.0); | |
chThdSleepMilliseconds(250); | |
@@ -142,7 +97,6 @@ | |
chThdSleepMilliseconds(500); | |
} else { | |
ledpwm_set_intensity(LED_RED, 0.0); | |
- fault_print = 0; | |
} | |
if (mc_interface_get_state() == MC_STATE_DETECTING) { | |
@@ -156,8 +110,12 @@ | |
commands_send_rotor_pos(encoder_read_deg()); | |
break; | |
- case DISP_POS_MODE_ENCODER_POS_ERROR: | |
- commands_send_rotor_pos(utils_angle_difference(mc_interface_get_pos_set(), encoder_read_deg())); | |
+ case DISP_POS_MODE_PID_POS: | |
+ commands_send_rotor_pos(mc_interface_get_pid_pos_now()); | |
+ break; | |
+ | |
+ case DISP_POS_MODE_PID_POS_ERROR: | |
+ commands_send_rotor_pos(utils_angle_difference(mc_interface_get_pid_pos_set(), mc_interface_get_pid_pos_now())); | |
break; | |
default: | |
@@ -183,43 +141,6 @@ | |
} | |
} | |
-static THD_FUNCTION(sample_send_thread, arg) { | |
- (void)arg; | |
- | |
- chRegSetThreadName("Main sample"); | |
- | |
- sample_send_tp = chThdGetSelfX(); | |
- | |
- for(;;) { | |
- chEvtWaitAny((eventmask_t) 1); | |
- | |
- for (int i = 0;i < sample_len;i++) { | |
- uint8_t buffer[20]; | |
- int index = 0; | |
- | |
- buffer[index++] = curr0_samples[i] >> 8; | |
- buffer[index++] = curr0_samples[i]; | |
- buffer[index++] = curr1_samples[i] >> 8; | |
- buffer[index++] = curr1_samples[i]; | |
- buffer[index++] = ph1_samples[i] >> 8; | |
- buffer[index++] = ph1_samples[i]; | |
- buffer[index++] = ph2_samples[i] >> 8; | |
- buffer[index++] = ph2_samples[i]; | |
- buffer[index++] = ph3_samples[i] >> 8; | |
- buffer[index++] = ph3_samples[i]; | |
- buffer[index++] = vzero_samples[i] >> 8; | |
- buffer[index++] = vzero_samples[i]; | |
- buffer[index++] = status_samples[i]; | |
- buffer[index++] = curr_fir_samples[i] >> 8; | |
- buffer[index++] = curr_fir_samples[i]; | |
- buffer[index++] = f_sw_samples[i] >> 8; | |
- buffer[index++] = f_sw_samples[i]; | |
- | |
- commands_send_samples(buffer, index); | |
- } | |
- } | |
-} | |
- | |
static THD_FUNCTION(timer_thread, arg) { | |
(void)arg; | |
@@ -231,85 +152,6 @@ | |
} | |
} | |
-/* | |
- * Called every time new ADC values are available. Note that | |
- * the ADC is initialized from mcpwm.c | |
- */ | |
-void main_dma_adc_handler(void) { | |
- ledpwm_update_pwm(); | |
- | |
- if (sample_at_start && (mc_interface_get_state() == MC_STATE_RUNNING || | |
- start_comm != mcpwm_get_comm_step())) { | |
- sample_now = 0; | |
- sample_ready = 0; | |
- sample_at_start = 0; | |
- } | |
- | |
- static int a = 0; | |
- if (!sample_ready) { | |
- a++; | |
- if (a >= sample_int) { | |
- a = 0; | |
- | |
- if (mc_interface_get_state() == MC_STATE_DETECTING) { | |
- curr0_samples[sample_now] = (int16_t)mcpwm_detect_currents[mcpwm_get_comm_step() - 1]; | |
- curr1_samples[sample_now] = (int16_t)mcpwm_detect_currents_diff[mcpwm_get_comm_step() - 1]; | |
- | |
- ph1_samples[sample_now] = (int16_t)mcpwm_detect_voltages[0]; | |
- ph2_samples[sample_now] = (int16_t)mcpwm_detect_voltages[1]; | |
- ph3_samples[sample_now] = (int16_t)mcpwm_detect_voltages[2]; | |
- } else { | |
- curr0_samples[sample_now] = ADC_curr_norm_value[0]; | |
- curr1_samples[sample_now] = ADC_curr_norm_value[1]; | |
- | |
- ph1_samples[sample_now] = ADC_V_L1 - mcpwm_vzero; | |
- ph2_samples[sample_now] = ADC_V_L2 - mcpwm_vzero; | |
- ph3_samples[sample_now] = ADC_V_L3 - mcpwm_vzero; | |
- } | |
- | |
- vzero_samples[sample_now] = mcpwm_vzero; | |
- | |
- curr_fir_samples[sample_now] = (int16_t)(mc_interface_get_tot_current() * 100.0); | |
- f_sw_samples[sample_now] = (int16_t)(mc_interface_get_switching_frequency_now() / 10.0); | |
- | |
- status_samples[sample_now] = mcpwm_get_comm_step() | (mcpwm_read_hall_phase() << 3); | |
- | |
- sample_now++; | |
- | |
- if (sample_now == sample_len) { | |
- sample_ready = 1; | |
- sample_now = 0; | |
- chSysLockFromISR(); | |
- chEvtSignalI(sample_send_tp, (eventmask_t) 1); | |
- chSysUnlockFromISR(); | |
- } | |
- | |
- main_last_adc_duration = mcpwm_get_last_adc_isr_duration(); | |
- } | |
- } | |
-} | |
- | |
-float main_get_last_adc_isr_duration(void) { | |
- return main_last_adc_duration; | |
-} | |
- | |
-void main_sample_print_data(bool at_start, uint16_t len, uint8_t decimation) { | |
- if (len > ADC_SAMPLE_MAX_LEN) { | |
- len = ADC_SAMPLE_MAX_LEN; | |
- } | |
- | |
- sample_len = len; | |
- sample_int = decimation; | |
- | |
- if (at_start) { | |
- sample_at_start = 1; | |
- start_comm = mcpwm_get_comm_step(); | |
- } else { | |
- sample_now = 0; | |
- sample_ready = 0; | |
- } | |
-} | |
- | |
int main(void) { | |
halInit(); | |
chSysInit(); | |
@@ -325,11 +167,6 @@ | |
mc_configuration mcconf; | |
conf_general_read_mc_configuration(&mcconf); | |
- | |
-#if ENCODER_ENABLE | |
- encoder_init(mcconf.m_encoder_counts); | |
-#endif | |
- | |
mc_interface_init(&mcconf); | |
commands_init(); | |
@@ -361,14 +198,13 @@ | |
// Threads | |
chThdCreateStatic(periodic_thread_wa, sizeof(periodic_thread_wa), NORMALPRIO, periodic_thread, NULL); | |
- chThdCreateStatic(sample_send_thread_wa, sizeof(sample_send_thread_wa), NORMALPRIO - 1, sample_send_thread, NULL); | |
chThdCreateStatic(timer_thread_wa, sizeof(timer_thread_wa), NORMALPRIO, timer_thread, NULL); | |
for(;;) { | |
chThdSleepMilliseconds(10); | |
-#if ENCODER_ENABLE | |
-// comm_can_set_pos(0, encoder_read_deg()); | |
-#endif | |
+ if (encoder_is_configured()) { | |
+ // comm_can_set_pos(0, encoder_read_deg()); | |
+ } | |
} | |
} | |
Only in bldc-cc171422641a50c56452280575f2074f8a88aa45: main.h | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/mc_interface.c Raptor2 Sources/bldc-firmware_2_80/mc_interface.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/mc_interface.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mc_interface.c 2017-06-16 22:00:36.000000000 +0100 | |
@@ -25,13 +25,15 @@ | |
#include "mc_interface.h" | |
#include "mcpwm.h" | |
#include "mcpwm_foc.h" | |
-#include "main.h" | |
+#include "ledpwm.h" | |
#include "stm32f4xx_conf.h" | |
#include "hw.h" | |
#include "terminal.h" | |
#include "utils.h" | |
#include "ch.h" | |
#include "hal.h" | |
+#include "commands.h" | |
+#include "encoder.h" | |
#include <math.h> | |
// Global variables | |
@@ -39,21 +41,43 @@ | |
volatile int ADC_curr_norm_value[3]; | |
// Private variables | |
-static volatile mc_configuration conf; | |
-static mc_fault_code fault_now; | |
-static int ignore_iterations; | |
-static volatile unsigned int cycles_running; | |
-static volatile bool lock_enabled; | |
-static volatile bool lock_override_once; | |
-static volatile float motor_current_sum; | |
-static volatile float input_current_sum; | |
-static volatile float motor_current_iterations; | |
-static volatile float input_current_iterations; | |
-static volatile float amp_seconds; | |
-static volatile float amp_seconds_charged; | |
-static volatile float watt_seconds; | |
-static volatile float watt_seconds_charged; | |
-static volatile float position_set; | |
+static volatile mc_configuration m_conf; | |
+static volatile mc_configuration m_conf_original; | |
+static mc_fault_code m_fault_now; | |
+static int m_ignore_iterations; | |
+static volatile unsigned int m_cycles_running; | |
+static volatile bool m_lock_enabled; | |
+static volatile bool m_lock_override_once; | |
+static volatile float m_motor_current_sum; | |
+static volatile float m_input_current_sum; | |
+static volatile float m_motor_current_iterations; | |
+static volatile float m_input_current_iterations; | |
+static volatile float m_amp_seconds; | |
+static volatile float m_amp_seconds_charged; | |
+static volatile float m_watt_seconds; | |
+static volatile float m_watt_seconds_charged; | |
+static volatile float m_position_set; | |
+// new | |
+static volatile ppm_cruise cruise_control_status; | |
+ | |
+// Sampling variables | |
+#define ADC_SAMPLE_MAX_LEN 2000 | |
+static volatile int16_t m_curr0_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_curr1_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_ph1_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_ph2_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_ph3_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_vzero_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile uint8_t m_status_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_curr_fir_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_f_sw_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int m_sample_len; | |
+static volatile int m_sample_int; | |
+static volatile int m_sample_ready; | |
+static volatile int m_sample_now; | |
+static volatile int m_sample_at_start; | |
+static volatile int m_start_comm; | |
+static volatile float m_last_adc_duration_sample; | |
// Private functions | |
static void update_override_limits(volatile mc_configuration *conf); | |
@@ -64,36 +88,66 @@ | |
// Threads | |
static THD_WORKING_AREA(timer_thread_wa, 1024); | |
static THD_FUNCTION(timer_thread, arg); | |
+static THD_WORKING_AREA(sample_send_thread_wa, 1024); | |
+static THD_FUNCTION(sample_send_thread, arg); | |
+static thread_t *sample_send_tp; | |
void mc_interface_init(mc_configuration *configuration) { | |
- conf = *configuration; | |
- fault_now = FAULT_CODE_NONE; | |
- ignore_iterations = 0; | |
- cycles_running = 0; | |
- lock_enabled = false; | |
- lock_override_once = false; | |
- motor_current_sum = 0.0; | |
- input_current_sum = 0.0; | |
- motor_current_iterations = 0.0; | |
- input_current_iterations = 0.0; | |
- amp_seconds = 0.0; | |
- amp_seconds_charged = 0.0; | |
- watt_seconds = 0.0; | |
- watt_seconds_charged = 0.0; | |
- position_set = 0.0; | |
+ m_conf = *configuration; | |
+ m_conf_original = *configuration; | |
+ m_fault_now = FAULT_CODE_NONE; | |
+ m_ignore_iterations = 0; | |
+ m_cycles_running = 0; | |
+ m_lock_enabled = false; | |
+ m_lock_override_once = false; | |
+ m_motor_current_sum = 0.0; | |
+ m_input_current_sum = 0.0; | |
+ m_motor_current_iterations = 0.0; | |
+ m_input_current_iterations = 0.0; | |
+ m_amp_seconds = 0.0; | |
+ m_amp_seconds_charged = 0.0; | |
+ m_watt_seconds = 0.0; | |
+ m_watt_seconds_charged = 0.0; | |
+ m_position_set = 0.0; | |
+ m_last_adc_duration_sample = 0.0; | |
+ cruise_control_status = CRUISE_CONTROL_INACTIVE; | |
+ | |
+ m_sample_len = 1000; | |
+ m_sample_int = 1; | |
+ m_sample_ready = 1; | |
+ m_sample_now = 0; | |
+ m_sample_at_start = 0; | |
+ m_start_comm = 0; | |
// Start threads | |
chThdCreateStatic(timer_thread_wa, sizeof(timer_thread_wa), NORMALPRIO, timer_thread, NULL); | |
+ chThdCreateStatic(sample_send_thread_wa, sizeof(sample_send_thread_wa), NORMALPRIO - 1, sample_send_thread, NULL); | |
+ | |
+ // Initialize encoder | |
+#if !WS2811_ENABLE | |
+ switch (m_conf.m_sensor_port_mode) { | |
+ case SENSOR_PORT_MODE_ABI: | |
+ encoder_init_abi(m_conf.m_encoder_counts); | |
+ break; | |
+ | |
+ case SENSOR_PORT_MODE_AS5047_SPI: | |
+ encoder_init_as5047p_spi(); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+#endif | |
// Initialize selected implementation | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
- mcpwm_init(&conf); | |
+ mcpwm_init(&m_conf); | |
break; | |
case MOTOR_TYPE_FOC: | |
- mcpwm_foc_init(&conf); | |
+ mcpwm_foc_init(&m_conf); | |
break; | |
default: | |
@@ -102,34 +156,56 @@ | |
} | |
const volatile mc_configuration* mc_interface_get_configuration(void) { | |
- return &conf; | |
+ return &m_conf; | |
} | |
void mc_interface_set_configuration(mc_configuration *configuration) { | |
- if (conf.motor_type == MOTOR_TYPE_FOC | |
+#if !WS2811_ENABLE | |
+ if (m_conf.m_sensor_port_mode != configuration->m_sensor_port_mode) { | |
+ encoder_deinit(); | |
+ switch (configuration->m_sensor_port_mode) { | |
+ case SENSOR_PORT_MODE_ABI: | |
+ encoder_init_abi(configuration->m_encoder_counts); | |
+ break; | |
+ | |
+ case SENSOR_PORT_MODE_AS5047_SPI: | |
+ encoder_init_as5047p_spi(); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if (configuration->m_sensor_port_mode == SENSOR_PORT_MODE_ABI) { | |
+ encoder_set_counts(configuration->m_encoder_counts); | |
+ } | |
+#endif | |
+ | |
+ if (m_conf.motor_type == MOTOR_TYPE_FOC | |
&& configuration->motor_type != MOTOR_TYPE_FOC) { | |
mcpwm_foc_deinit(); | |
- conf = *configuration; | |
- mcpwm_init(&conf); | |
- } else if (conf.motor_type != MOTOR_TYPE_FOC | |
+ m_conf = *configuration; | |
+ mcpwm_init(&m_conf); | |
+ } else if (m_conf.motor_type != MOTOR_TYPE_FOC | |
&& configuration->motor_type == MOTOR_TYPE_FOC) { | |
mcpwm_deinit(); | |
- conf = *configuration; | |
- mcpwm_foc_init(&conf); | |
+ m_conf = *configuration; | |
+ mcpwm_foc_init(&m_conf); | |
} else { | |
- conf = *configuration; | |
+ m_conf = *configuration; | |
} | |
- update_override_limits(&conf); | |
+ update_override_limits(&m_conf); | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
- mcpwm_set_configuration(&conf); | |
+ mcpwm_set_configuration(&m_conf); | |
break; | |
case MOTOR_TYPE_FOC: | |
- mcpwm_foc_set_configuration(&conf); | |
+ mcpwm_foc_set_configuration(&m_conf); | |
break; | |
default: | |
@@ -139,7 +215,7 @@ | |
bool mc_interface_dccal_done(void) { | |
bool ret = false; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_is_dccal_done(); | |
@@ -170,25 +246,25 @@ | |
* Lock the control by disabling all control commands. | |
*/ | |
void mc_interface_lock(void) { | |
- lock_enabled = true; | |
+ m_lock_enabled = true; | |
} | |
/** | |
* Unlock all control commands. | |
*/ | |
void mc_interface_unlock(void) { | |
- lock_enabled = false; | |
+ m_lock_enabled = false; | |
} | |
/** | |
* Allow just one motor control command in the locked state. | |
*/ | |
void mc_interface_lock_override_once(void) { | |
- lock_override_once = true; | |
+ m_lock_override_once = true; | |
} | |
mc_fault_code mc_interface_get_fault(void) { | |
- return fault_now; | |
+ return m_fault_now; | |
} | |
const char* mc_interface_fault_to_string(mc_fault_code fault) { | |
@@ -206,7 +282,7 @@ | |
mc_state mc_interface_get_state(void) { | |
mc_state ret = MC_STATE_OFF; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_state(); | |
@@ -228,7 +304,7 @@ | |
return; | |
} | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_duty(dutyCycle); | |
@@ -248,7 +324,7 @@ | |
return; | |
} | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_duty_noramp(dutyCycle); | |
@@ -268,7 +344,7 @@ | |
return; | |
} | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_pid_speed(rpm); | |
@@ -283,14 +359,43 @@ | |
} | |
} | |
+void mc_interface_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status) { | |
+ if (mc_interface_try_input()) { | |
+ return; | |
+ } | |
+ | |
+ switch (m_conf.motor_type) { | |
+ case MOTOR_TYPE_BLDC: | |
+ case MOTOR_TYPE_DC: | |
+ mcpwm_set_pid_speed_with_cruise_status(rpm, cruise_status); | |
+ break; | |
+ | |
+ case MOTOR_TYPE_FOC: | |
+ mcpwm_foc_set_pid_speed_with_cruise_status(rpm, cruise_status); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+} | |
+ | |
+ppm_cruise mc_interface_get_cruise_control_status(void){ | |
+ return cruise_control_status; | |
+} | |
+ | |
+// true = active false = inactive | |
+void mc_interface_set_cruise_control_status(ppm_cruise status){ | |
+ cruise_control_status = status; | |
+} | |
+ | |
void mc_interface_set_pid_pos(float pos) { | |
if (mc_interface_try_input()) { | |
return; | |
} | |
- position_set = pos; | |
+ m_position_set = pos; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_pid_pos(pos); | |
@@ -310,7 +415,7 @@ | |
return; | |
} | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_current(current); | |
@@ -330,7 +435,75 @@ | |
return; | |
} | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
+ case MOTOR_TYPE_BLDC: | |
+ case MOTOR_TYPE_DC: | |
+ mcpwm_set_brake_current(current); | |
+ break; | |
+ | |
+ case MOTOR_TYPE_FOC: | |
+ mcpwm_foc_set_brake_current(current); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+} | |
+ | |
+void mc_interface_set_servo(float servo_val, bool use_min_current) { | |
+ if (mc_interface_try_input()) { | |
+ return; | |
+ } | |
+ | |
+ float current = 0.0; | |
+ | |
+ if (servo_val > 0.0){ | |
+ if (m_conf.use_max_watt_limit) { | |
+ current = utils_smallest_of_2(servo_val * m_conf.l_current_max, | |
+ servo_val * (m_conf.watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } else { | |
+ current = utils_smallest_of_2(servo_val * m_conf.l_current_max, | |
+ servo_val * m_conf.l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation()); | |
+ } | |
+ if (use_min_current) { | |
+ current = utils_highest_of_2(current, m_conf.cc_min_current); | |
+ } | |
+ } else if (servo_val < 0.0){ | |
+ if (m_conf.use_max_watt_limit) { | |
+ current = -utils_smallest_of_2(fabsf(servo_val * m_conf.l_current_min), | |
+ fabsf(servo_val * (m_conf.watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation()))); | |
+ } else { | |
+ current = -utils_smallest_of_2(fabsf(servo_val * m_conf.l_current_min), | |
+ fabsf(servo_val * m_conf.l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } | |
+ if (use_min_current) { | |
+ current = utils_smallest_of_2(current, -m_conf.cc_min_current); | |
+ } | |
+ } | |
+ | |
+ switch (m_conf.motor_type) { | |
+ case MOTOR_TYPE_BLDC: | |
+ case MOTOR_TYPE_DC: | |
+ mcpwm_set_current(current); | |
+ break; | |
+ | |
+ case MOTOR_TYPE_FOC: | |
+ mcpwm_foc_set_current(current); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+} | |
+ | |
+void mc_interface_set_brake_servo(float servo_val) { | |
+ if (mc_interface_try_input()) { | |
+ return; | |
+ } | |
+ | |
+ float current = servo_val * fabsf(m_conf.l_current_min); | |
+ | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_brake_current(current); | |
@@ -356,13 +529,34 @@ | |
mc_interface_set_current(0.0); | |
} | |
+float mc_interface_get_duty_cycle_for_watt_calculation(void) { | |
+ float actual_duty; | |
+ | |
+ if (m_conf.motor_type == MOTOR_TYPE_FOC) { | |
+ //float battery_current = mcpwm_foc_get_tot_current_in_filtered(); | |
+ //float motor_current = mcpwm_foc_get_tot_current_filtered(); | |
+ | |
+ //if (fabsf(battery_current) > 1.0 && fabsf(motor_current) > 1.0) { | |
+ // actual_duty = fabsf(battery_current / motor_current); | |
+ //} else { | |
+ actual_duty = fabsf(mcpwm_foc_get_duty_cycle_now()) * 0.86602540378; | |
+ //} | |
+ } else { | |
+ actual_duty = fabsf(mc_interface_get_duty_cycle_now()); | |
+ } | |
+ if (actual_duty < m_conf.l_min_duty) { | |
+ return m_conf.l_min_duty; | |
+ } | |
+ return actual_duty; | |
+} | |
+ | |
/** | |
* Stop the motor and use braking. | |
*/ | |
float mc_interface_get_duty_cycle_set(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_duty_cycle_set(); | |
@@ -382,7 +576,7 @@ | |
float mc_interface_get_duty_cycle_now(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_duty_cycle_now(); | |
@@ -399,17 +593,17 @@ | |
return ret; | |
} | |
-float mc_interface_get_switching_frequency_now(void) { | |
+float mc_interface_get_sampling_frequency_now(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_switching_frequency_now(); | |
break; | |
case MOTOR_TYPE_FOC: | |
- ret = mcpwm_foc_get_switching_frequency_now(); | |
+ ret = mcpwm_foc_get_switching_frequency_now() / 2.0; | |
break; | |
default: | |
@@ -422,7 +616,7 @@ | |
float mc_interface_get_rpm(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_rpm(); | |
@@ -449,10 +643,10 @@ | |
* The amount of amp hours drawn. | |
*/ | |
float mc_interface_get_amp_hours(bool reset) { | |
- float val = amp_seconds / 3600; | |
+ float val = m_amp_seconds / 3600; | |
if (reset) { | |
- amp_seconds = 0.0; | |
+ m_amp_seconds = 0.0; | |
} | |
return val; | |
@@ -468,10 +662,10 @@ | |
* The amount of amp hours fed back. | |
*/ | |
float mc_interface_get_amp_hours_charged(bool reset) { | |
- float val = amp_seconds_charged / 3600; | |
+ float val = m_amp_seconds_charged / 3600; | |
if (reset) { | |
- amp_seconds_charged = 0.0; | |
+ m_amp_seconds_charged = 0.0; | |
} | |
return val; | |
@@ -487,10 +681,10 @@ | |
* The amount of watt hours drawn. | |
*/ | |
float mc_interface_get_watt_hours(bool reset) { | |
- float val = watt_seconds / 3600; | |
+ float val = m_watt_seconds / 3600; | |
if (reset) { | |
- amp_seconds = 0.0; | |
+ m_amp_seconds = 0.0; | |
} | |
return val; | |
@@ -506,10 +700,10 @@ | |
* The amount of watt hours fed back. | |
*/ | |
float mc_interface_get_watt_hours_charged(bool reset) { | |
- float val = watt_seconds_charged / 3600; | |
+ float val = m_watt_seconds_charged / 3600; | |
if (reset) { | |
- watt_seconds_charged = 0.0; | |
+ m_watt_seconds_charged = 0.0; | |
} | |
return val; | |
@@ -518,7 +712,7 @@ | |
float mc_interface_get_tot_current(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current(); | |
@@ -538,7 +732,7 @@ | |
float mc_interface_get_tot_current_filtered(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current_filtered(); | |
@@ -558,7 +752,7 @@ | |
float mc_interface_get_tot_current_directional(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current_directional(); | |
@@ -578,7 +772,7 @@ | |
float mc_interface_get_tot_current_directional_filtered(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current_directional_filtered(); | |
@@ -598,7 +792,7 @@ | |
float mc_interface_get_tot_current_in(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current_in(); | |
@@ -618,7 +812,7 @@ | |
float mc_interface_get_tot_current_in_filtered(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current_in_filtered(); | |
@@ -638,7 +832,7 @@ | |
int mc_interface_get_tachometer_value(bool reset) { | |
int ret = 0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tachometer_value(reset); | |
@@ -658,7 +852,7 @@ | |
int mc_interface_get_tachometer_abs_value(bool reset) { | |
int ret = 0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tachometer_abs_value(reset); | |
@@ -678,7 +872,7 @@ | |
float mc_interface_get_last_inj_adc_isr_duration(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_last_inj_adc_isr_duration(); | |
@@ -696,21 +890,62 @@ | |
} | |
float mc_interface_read_reset_avg_motor_current(void) { | |
- float res = motor_current_sum / motor_current_iterations; | |
- motor_current_sum = 0; | |
- motor_current_iterations = 0; | |
+ float res = m_motor_current_sum / m_motor_current_iterations; | |
+ m_motor_current_sum = 0; | |
+ m_motor_current_iterations = 0; | |
return res; | |
} | |
float mc_interface_read_reset_avg_input_current(void) { | |
- float res = input_current_sum / input_current_iterations; | |
- input_current_sum = 0; | |
- input_current_iterations = 0; | |
+ float res = m_input_current_sum / m_input_current_iterations; | |
+ m_input_current_sum = 0; | |
+ m_input_current_iterations = 0; | |
return res; | |
} | |
-float mc_interface_get_pos_set(void) { | |
- return position_set; | |
+float mc_interface_get_pid_pos_set(void) { | |
+ return m_position_set; | |
+} | |
+ | |
+float mc_interface_get_pid_pos_now(void) { | |
+ float ret = 0.0; | |
+ | |
+ switch (m_conf.motor_type) { | |
+ case MOTOR_TYPE_BLDC: | |
+ case MOTOR_TYPE_DC: | |
+ ret = encoder_read_deg(); | |
+ break; | |
+ | |
+ case MOTOR_TYPE_FOC: | |
+ ret = mcpwm_foc_get_pid_pos_now(); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+ | |
+ return ret; | |
+} | |
+ | |
+float mc_interface_get_last_sample_adc_isr_duration(void) { | |
+ return m_last_adc_duration_sample; | |
+} | |
+ | |
+void mc_interface_sample_print_data(bool at_start, uint16_t len, uint8_t decimation) { | |
+ if (len > ADC_SAMPLE_MAX_LEN) { | |
+ len = ADC_SAMPLE_MAX_LEN; | |
+ } | |
+ | |
+ m_sample_len = len; | |
+ m_sample_int = decimation; | |
+ | |
+ if (at_start) { | |
+ m_sample_at_start = 1; | |
+ m_start_comm = mcpwm_get_comm_step(); | |
+ } else { | |
+ m_sample_now = 0; | |
+ m_sample_ready = 0; | |
+ } | |
} | |
// MC implementation functions | |
@@ -726,16 +961,16 @@ | |
// TODO: Remove this later | |
if (mc_interface_get_state() == MC_STATE_DETECTING) { | |
mcpwm_stop_pwm(); | |
- ignore_iterations = MCPWM_DETECT_STOP_TIME; | |
+ m_ignore_iterations = MCPWM_DETECT_STOP_TIME; | |
} | |
- int retval = ignore_iterations; | |
+ int retval = m_ignore_iterations; | |
- if (!ignore_iterations && lock_enabled) { | |
- if (!lock_override_once) { | |
+ if (!m_ignore_iterations && m_lock_enabled) { | |
+ if (!m_lock_override_once) { | |
retval = 1; | |
} else { | |
- lock_override_once = false; | |
+ m_lock_override_once = false; | |
} | |
} | |
@@ -743,7 +978,7 @@ | |
} | |
void mc_interface_fault_stop(mc_fault_code fault) { | |
- if (mc_interface_dccal_done() && fault_now == FAULT_CODE_NONE) { | |
+ if (mc_interface_dccal_done() && m_fault_now == FAULT_CODE_NONE) { | |
// Sent to terminal fault logger so that all faults and their conditions | |
// can be printed for debugging. | |
chSysLock(); | |
@@ -754,13 +989,18 @@ | |
fault_data fdata; | |
fdata.fault = fault; | |
- fdata.current = mc_interface_get_tot_current(); | |
- fdata.current_filtered = mc_interface_get_tot_current_filtered(); | |
+ if (m_conf.motor_type == MOTOR_TYPE_FOC) { | |
+ fdata.current = mcpwm_foc_get_abs_motor_current(); | |
+ fdata.current_filtered = mcpwm_foc_get_abs_motor_current_filtered(); | |
+ }else{ | |
+ fdata.current = mc_interface_get_tot_current(); | |
+ fdata.current_filtered = mc_interface_get_tot_current_filtered(); | |
+ } | |
fdata.voltage = GET_INPUT_VOLTAGE(); | |
fdata.duty = mc_interface_get_duty_cycle_now(); | |
fdata.rpm = mc_interface_get_rpm(); | |
fdata.tacho = mc_interface_get_tachometer_value(false); | |
- fdata.cycles_running = cycles_running; | |
+ fdata.cycles_running = m_cycles_running; | |
fdata.tim_val_samp = val_samp; | |
fdata.tim_current_samp = current_samp; | |
fdata.tim_top = tim_top; | |
@@ -769,9 +1009,9 @@ | |
terminal_add_fault_data(&fdata); | |
} | |
- ignore_iterations = conf.m_fault_stop_time_ms; | |
+ m_ignore_iterations = m_conf.m_fault_stop_time_ms; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_stop_pwm(); | |
@@ -785,20 +1025,22 @@ | |
break; | |
} | |
- fault_now = fault; | |
+ m_fault_now = fault; | |
} | |
void mc_interface_mc_timer_isr(void) { | |
+ ledpwm_update_pwm(); // LED PWM Driver update | |
+ | |
const float input_voltage = GET_INPUT_VOLTAGE(); | |
// Check for faults that should stop the motor | |
static int wrong_voltage_iterations = 0; | |
- if (input_voltage < conf.l_min_vin || | |
- input_voltage > conf.l_max_vin) { | |
+ if (input_voltage < m_conf.l_min_vin || | |
+ input_voltage > m_conf.l_max_vin) { | |
wrong_voltage_iterations++; | |
if ((wrong_voltage_iterations >= 8)) { | |
- mc_interface_fault_stop(input_voltage < conf.l_min_vin ? | |
+ mc_interface_fault_stop(input_voltage < m_conf.l_min_vin ? | |
FAULT_CODE_UNDER_VOLTAGE : FAULT_CODE_OVER_VOLTAGE); | |
} | |
} else { | |
@@ -806,70 +1048,119 @@ | |
} | |
if (mc_interface_get_state() == MC_STATE_RUNNING) { | |
- cycles_running++; | |
+ m_cycles_running++; | |
} else { | |
- cycles_running = 0; | |
+ m_cycles_running = 0; | |
} | |
- main_dma_adc_handler(); | |
- | |
if (pwn_done_func) { | |
pwn_done_func(); | |
} | |
const float current = mc_interface_get_tot_current_filtered(); | |
const float current_in = mc_interface_get_tot_current_in_filtered(); | |
- motor_current_sum += current; | |
- input_current_sum += current_in; | |
- motor_current_iterations++; | |
- input_current_iterations++; | |
+ m_motor_current_sum += current; | |
+ m_input_current_sum += current_in; | |
+ m_motor_current_iterations++; | |
+ m_input_current_iterations++; | |
float abs_current = mc_interface_get_tot_current(); | |
float abs_current_filtered = current; | |
- if (conf.motor_type == MOTOR_TYPE_FOC) { | |
+ if (m_conf.motor_type == MOTOR_TYPE_FOC) { | |
// TODO: Make this more general | |
abs_current = mcpwm_foc_get_abs_motor_current(); | |
abs_current_filtered = mcpwm_foc_get_abs_motor_current_filtered(); | |
} | |
// Current fault code | |
- if (conf.l_slow_abs_current) { | |
- if (fabsf(abs_current_filtered) > conf.l_abs_current_max) { | |
+ if (m_conf.l_slow_abs_current) { | |
+ if (fabsf(abs_current_filtered) > m_conf.l_abs_current_max) { | |
mc_interface_fault_stop(FAULT_CODE_ABS_OVER_CURRENT); | |
} | |
} else { | |
- if (fabsf(abs_current) > conf.l_abs_current_max) { | |
+ if (fabsf(abs_current) > m_conf.l_abs_current_max) { | |
mc_interface_fault_stop(FAULT_CODE_ABS_OVER_CURRENT); | |
} | |
} | |
// Watt and ah counters | |
- const float f_sw = mc_interface_get_switching_frequency_now(); | |
+ const float f_samp = mc_interface_get_sampling_frequency_now(); | |
if (fabsf(current) > 1.0) { | |
// Some extra filtering | |
static float curr_diff_sum = 0.0; | |
static float curr_diff_samples = 0; | |
- curr_diff_sum += current_in / f_sw; | |
- curr_diff_samples += 1.0 / f_sw; | |
+ curr_diff_sum += current_in / f_samp; | |
+ curr_diff_samples += 1.0 / f_samp; | |
if (curr_diff_samples >= 0.01) { | |
if (curr_diff_sum > 0.0) { | |
- amp_seconds += curr_diff_sum; | |
- watt_seconds += curr_diff_sum * input_voltage; | |
+ m_amp_seconds += curr_diff_sum; | |
+ m_watt_seconds += curr_diff_sum * input_voltage; | |
} else { | |
- amp_seconds_charged -= curr_diff_sum; | |
- watt_seconds_charged -= curr_diff_sum * input_voltage; | |
+ m_amp_seconds_charged -= curr_diff_sum; | |
+ m_watt_seconds_charged -= curr_diff_sum * input_voltage; | |
} | |
curr_diff_samples = 0.0; | |
curr_diff_sum = 0.0; | |
} | |
} | |
+ | |
+ // Sample collection | |
+ if (m_sample_at_start && (mc_interface_get_state() == MC_STATE_RUNNING || | |
+ m_start_comm != mcpwm_get_comm_step())) { | |
+ m_sample_now = 0; | |
+ m_sample_ready = 0; | |
+ m_sample_at_start = 0; | |
+ } | |
+ | |
+ static int a = 0; | |
+ if (!m_sample_ready) { | |
+ a++; | |
+ if (a >= m_sample_int) { | |
+ a = 0; | |
+ | |
+ if (mc_interface_get_state() == MC_STATE_DETECTING) { | |
+ m_curr0_samples[m_sample_now] = (int16_t)mcpwm_detect_currents[mcpwm_get_comm_step() - 1]; | |
+ m_curr1_samples[m_sample_now] = (int16_t)mcpwm_detect_currents_diff[mcpwm_get_comm_step() - 1]; | |
+ | |
+ m_ph1_samples[m_sample_now] = (int16_t)mcpwm_detect_voltages[0]; | |
+ m_ph2_samples[m_sample_now] = (int16_t)mcpwm_detect_voltages[1]; | |
+ m_ph3_samples[m_sample_now] = (int16_t)mcpwm_detect_voltages[2]; | |
+ } else { | |
+ m_curr0_samples[m_sample_now] = ADC_curr_norm_value[0]; | |
+ m_curr1_samples[m_sample_now] = ADC_curr_norm_value[1]; | |
+ | |
+ m_ph1_samples[m_sample_now] = ADC_V_L1 - mcpwm_vzero; | |
+ m_ph2_samples[m_sample_now] = ADC_V_L2 - mcpwm_vzero; | |
+ m_ph3_samples[m_sample_now] = ADC_V_L3 - mcpwm_vzero; | |
+ } | |
+ | |
+ m_vzero_samples[m_sample_now] = mcpwm_vzero; | |
+ | |
+ m_curr_fir_samples[m_sample_now] = (int16_t)(mc_interface_get_tot_current() * 100.0); | |
+ m_f_sw_samples[m_sample_now] = (int16_t)(f_samp / 10.0); | |
+ | |
+ m_status_samples[m_sample_now] = mcpwm_get_comm_step() | (mcpwm_read_hall_phase() << 3); | |
+ | |
+ m_sample_now++; | |
+ | |
+ if (m_sample_now == m_sample_len) { | |
+ m_sample_ready = 1; | |
+ m_sample_now = 0; | |
+ chSysLockFromISR(); | |
+ chEvtSignalI(sample_send_tp, (eventmask_t) 1); | |
+ chSysUnlockFromISR(); | |
+ } | |
+ | |
+ m_last_adc_duration_sample = mcpwm_get_last_adc_isr_duration(); | |
+ } | |
+ } | |
} | |
void mc_interface_adc_inj_int_handler(void) { | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_adc_inj_int_handler(); | |
@@ -891,7 +1182,7 @@ | |
* The configaration to update. | |
*/ | |
static void update_override_limits(volatile mc_configuration *conf) { | |
- const float temp = NTC_TEMP(ADC_IND_TEMP_MOS1); | |
+ const float temp = NTC_TEMP(ADC_IND_TEMP_MOS2); | |
const float v_in = GET_INPUT_VOLTAGE(); | |
// Temperature | |
@@ -944,16 +1235,53 @@ | |
} | |
// Decrease fault iterations | |
- if (ignore_iterations > 0) { | |
- ignore_iterations--; | |
+ if (m_ignore_iterations > 0) { | |
+ m_ignore_iterations--; | |
} else { | |
if (!IS_DRV_FAULT()) { | |
- fault_now = FAULT_CODE_NONE; | |
+ m_fault_now = FAULT_CODE_NONE; | |
} | |
} | |
- update_override_limits(&conf); | |
+ update_override_limits(&m_conf); | |
chThdSleepMilliseconds(1); | |
} | |
} | |
+ | |
+static THD_FUNCTION(sample_send_thread, arg) { | |
+ (void)arg; | |
+ | |
+ chRegSetThreadName("SampleSender"); | |
+ | |
+ sample_send_tp = chThdGetSelfX(); | |
+ | |
+ for(;;) { | |
+ chEvtWaitAny((eventmask_t) 1); | |
+ | |
+ for (int i = 0;i < m_sample_len;i++) { | |
+ uint8_t buffer[20]; | |
+ int index = 0; | |
+ | |
+ buffer[index++] = m_curr0_samples[i] >> 8; | |
+ buffer[index++] = m_curr0_samples[i]; | |
+ buffer[index++] = m_curr1_samples[i] >> 8; | |
+ buffer[index++] = m_curr1_samples[i]; | |
+ buffer[index++] = m_ph1_samples[i] >> 8; | |
+ buffer[index++] = m_ph1_samples[i]; | |
+ buffer[index++] = m_ph2_samples[i] >> 8; | |
+ buffer[index++] = m_ph2_samples[i]; | |
+ buffer[index++] = m_ph3_samples[i] >> 8; | |
+ buffer[index++] = m_ph3_samples[i]; | |
+ buffer[index++] = m_vzero_samples[i] >> 8; | |
+ buffer[index++] = m_vzero_samples[i]; | |
+ buffer[index++] = m_status_samples[i]; | |
+ buffer[index++] = m_curr_fir_samples[i] >> 8; | |
+ buffer[index++] = m_curr_fir_samples[i]; | |
+ buffer[index++] = m_f_sw_samples[i] >> 8; | |
+ buffer[index++] = m_f_sw_samples[i]; | |
+ | |
+ commands_send_samples(buffer, index); | |
+ } | |
+ } | |
+} | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/mc_interface.h Raptor2 Sources/bldc-firmware_2_80/mc_interface.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/mc_interface.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mc_interface.h 2017-04-13 18:05:06.000000000 +0100 | |
@@ -41,14 +41,20 @@ | |
void mc_interface_set_duty(float dutyCycle); | |
void mc_interface_set_duty_noramp(float dutyCycle); | |
void mc_interface_set_pid_speed(float rpm); | |
+void mc_interface_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status); | |
+ppm_cruise mc_interface_get_cruise_control_status(void); | |
+void mc_interface_set_cruise_control_status(ppm_cruise status); // 1 = active 0 = inactive | |
void mc_interface_set_pid_pos(float pos); | |
void mc_interface_set_current(float current); | |
void mc_interface_set_brake_current(float current); | |
+void mc_interface_set_servo(float servo_val, bool use_min_current); | |
+void mc_interface_set_brake_servo(float servo_val); | |
void mc_interface_brake_now(void); | |
void mc_interface_release_motor(void); | |
+float mc_interface_get_duty_cycle_for_watt_calculation(void); | |
float mc_interface_get_duty_cycle_set(void); | |
float mc_interface_get_duty_cycle_now(void); | |
-float mc_interface_get_switching_frequency_now(void); | |
+float mc_interface_get_sampling_frequency_now(void); | |
float mc_interface_get_rpm(void); | |
float mc_interface_get_amp_hours(bool reset); | |
float mc_interface_get_amp_hours_charged(bool reset); | |
@@ -65,7 +71,10 @@ | |
float mc_interface_get_last_inj_adc_isr_duration(void); | |
float mc_interface_read_reset_avg_motor_current(void); | |
float mc_interface_read_reset_avg_input_current(void); | |
-float mc_interface_get_pos_set(void); | |
+float mc_interface_get_pid_pos_set(void); | |
+float mc_interface_get_pid_pos_now(void); | |
+float mc_interface_get_last_sample_adc_isr_duration(void); | |
+void mc_interface_sample_print_data(bool at_start, uint16_t len, uint8_t decimation); | |
// MC implementation functions | |
void mc_interface_fault_stop(mc_fault_code fault); | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/mcconf/mcconf_default.h Raptor2 Sources/bldc-firmware_2_80/mcconf/mcconf_default.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/mcconf/mcconf_default.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcconf/mcconf_default.h 2018-08-28 19:44:30.000000000 +0100 | |
@@ -20,16 +20,16 @@ | |
// Default settings | |
#ifndef MCCONF_DEFAULT_MOTOR_TYPE | |
-#define MCCONF_DEFAULT_MOTOR_TYPE MOTOR_TYPE_BLDC | |
+#define MCCONF_DEFAULT_MOTOR_TYPE MOTOR_TYPE_FOC | |
#endif | |
#ifndef MCCONF_PWM_MODE | |
-#define MCCONF_PWM_MODE PWM_MODE_SYNCHRONOUS // Default PWM mode | |
+#define MCCONF_PWM_MODE PWM_MODE_SYNCHRONOUS // Default PWM mode | |
#endif | |
#ifndef MCCONF_SENSOR_MODE | |
-#define MCCONF_SENSOR_MODE SENSOR_MODE_SENSORLESS // Sensor mode | |
+#define MCCONF_SENSOR_MODE SENSOR_MODE_HYBRID // Sensor mode | |
#endif | |
#ifndef MCCONF_COMM_MODE | |
-#define MCCONF_COMM_MODE COMM_MODE_INTEGRATE // The commutation mode to use | |
+#define MCCONF_COMM_MODE COMM_MODE_INTEGRATE // The commutation mode to use | |
#endif | |
// Limits | |
@@ -37,13 +37,13 @@ | |
#define MCCONF_L_CURRENT_MAX 60.0 // Current limit in Amperes (Upper) | |
#endif | |
#ifndef MCCONF_L_CURRENT_MIN | |
-#define MCCONF_L_CURRENT_MIN -60.0 // Current limit in Amperes (Lower) | |
+#define MCCONF_L_CURRENT_MIN -50.0 // Current limit in Amperes (Lower) | |
#endif | |
#ifndef MCCONF_L_IN_CURRENT_MAX | |
-#define MCCONF_L_IN_CURRENT_MAX 60.0 // Input current limit in Amperes (Upper) | |
+#define MCCONF_L_IN_CURRENT_MAX 25.0 // Input current limit in Amperes (Upper) | |
#endif | |
#ifndef MCCONF_L_IN_CURRENT_MIN | |
-#define MCCONF_L_IN_CURRENT_MIN -20.0 // Input current limit in Amperes (Lower) | |
+#define MCCONF_L_IN_CURRENT_MIN -10.0 // Input current limit in Amperes (Lower) | |
#endif | |
#ifndef MCCONF_L_MAX_ABS_CURRENT | |
#define MCCONF_L_MAX_ABS_CURRENT 130.0 // The maximum absolute current above which a fault is generated | |
@@ -52,37 +52,37 @@ | |
#define MCCONF_L_MIN_VOLTAGE 8.0 // Minimum input voltage | |
#endif | |
#ifndef MCCONF_L_MAX_VOLTAGE | |
-#define MCCONF_L_MAX_VOLTAGE 50.0 // Maximum input voltage | |
+#define MCCONF_L_MAX_VOLTAGE 57.0 // Maximum input voltage | |
#endif | |
#ifndef MCCONF_L_BATTERY_CUT_START | |
-#define MCCONF_L_BATTERY_CUT_START 10.0 // Start limiting the positive current at this voltage | |
+#define MCCONF_L_BATTERY_CUT_START 33.5 // Start limiting the positive current at this voltage | |
#endif | |
#ifndef MCCONF_L_BATTERY_CUT_END | |
-#define MCCONF_L_BATTERY_CUT_END 8.0 // Limit the positive current completely at this voltage | |
+#define MCCONF_L_BATTERY_CUT_END 29.0 // Limit the positive current completely at this voltage | |
#endif | |
#ifndef MCCONF_L_RPM_MAX | |
-#define MCCONF_L_RPM_MAX 100000.0 // The motor speed limit (Upper) | |
+#define MCCONF_L_RPM_MAX 60000.0 // The motor speed limit (Upper) | |
#endif | |
#ifndef MCCONF_L_RPM_MIN | |
-#define MCCONF_L_RPM_MIN -100000.0 // The motor speed limit (Lower) | |
+#define MCCONF_L_RPM_MIN -60000.0 // The motor speed limit (Lower) | |
#endif | |
#ifndef MCCONF_L_SLOW_ABS_OVERCURRENT | |
-#define MCCONF_L_SLOW_ABS_OVERCURRENT true // Use the filtered (and hence slower) current for the overcurrent fault detection | |
+#define MCCONF_L_SLOW_ABS_OVERCURRENT true // Use the filtered (and hence slower) current for the overcurrent fault detection | |
#endif | |
#ifndef MCCONF_L_MIN_DUTY | |
-#define MCCONF_L_MIN_DUTY 0.005 // Minimum duty cycle | |
+#define MCCONF_L_MIN_DUTY 0.005 // Minimum duty cycle | |
#endif | |
#ifndef MCCONF_L_MAX_DUTY | |
-#define MCCONF_L_MAX_DUTY 0.95 // Maximum duty cycle | |
+#define MCCONF_L_MAX_DUTY 0.95 // Maximum duty cycle | |
#endif | |
#ifndef MCCONF_L_RPM_LIMIT_NEG_TORQUE | |
-#define MCCONF_L_RPM_LIMIT_NEG_TORQUE true // Use negative torque to limit the RPM | |
+#define MCCONF_L_RPM_LIMIT_NEG_TORQUE false // Use negative torque to limit the RPM | |
#endif | |
#ifndef MCCONF_L_CURR_MAX_RPM_FBRAKE | |
-#define MCCONF_L_CURR_MAX_RPM_FBRAKE 300 // Maximum electrical RPM to use full brake at | |
+#define MCCONF_L_CURR_MAX_RPM_FBRAKE 300 // Maximum electrical RPM to use full brake at | |
#endif | |
#ifndef MCCONF_L_CURR_MAX_RPM_FBRAKE_CC | |
-#define MCCONF_L_CURR_MAX_RPM_FBRAKE_CC 1500 // Maximum electrical RPM to use full brake at with current control | |
+#define MCCONF_L_CURR_MAX_RPM_FBRAKE_CC 1500 // Maximum electrical RPM to use full brake at with current control | |
#endif | |
#ifndef MCCONF_L_LIM_TEMP_FET_START | |
#define MCCONF_L_LIM_TEMP_FET_START 80.0 // MOSFET temperature where current limiting should begin | |
@@ -91,7 +91,7 @@ | |
#define MCCONF_L_LIM_TEMP_FET_END 100.0 // MOSFET temperature where everything should be shut off | |
#endif | |
#ifndef MCCONF_L_LIM_TEMP_MOTOR_START | |
-#define MCCONF_L_LIM_TEMP_MOTOR_START 80.0 // MOTOR temperature where current limiting should begin | |
+#define MCCONF_L_LIM_TEMP_MOTOR_START 80.0 // MOTOR temperature where current limiting should begin | |
#endif | |
#ifndef MCCONF_L_LIM_TEMP_MOTOR_END | |
#define MCCONF_L_LIM_TEMP_MOTOR_END 100.0 // MOTOR temperature where everything should be shut off | |
@@ -99,58 +99,64 @@ | |
// Speed PID parameters | |
#ifndef MCCONF_S_PID_KP | |
-#define MCCONF_S_PID_KP 0.0001 // Proportional gain | |
+#define MCCONF_S_PID_KP 0.003 // Proportional gain | |
#endif | |
#ifndef MCCONF_S_PID_KI | |
-#define MCCONF_S_PID_KI 0.015 // Integral gain | |
+#define MCCONF_S_PID_KI 0.003 // Integral gain | |
#endif | |
#ifndef MCCONF_S_PID_KD | |
-#define MCCONF_S_PID_KD 0.0 // Derivative gain | |
+#define MCCONF_S_PID_KD 0.0 // Derivative gain | |
#endif | |
#ifndef MCCONF_S_PID_MIN_RPM | |
#define MCCONF_S_PID_MIN_RPM 900.0 // Minimum allowed RPM | |
#endif | |
+#ifndef MCCONF_S_PID_BREAKING_ENABLED | |
+#define MCCONF_S_PID_BREAKING_ENABLED true // Break at PID speed mode (cruiso control) | |
+#endif | |
// Position PID parameters | |
#ifndef MCCONF_P_PID_KP | |
-#define MCCONF_P_PID_KP 0.03 // Proportional gain | |
+#define MCCONF_P_PID_KP 0.03 // Proportional gain | |
#endif | |
#ifndef MCCONF_P_PID_KI | |
-#define MCCONF_P_PID_KI 0.0 // Integral gain | |
+#define MCCONF_P_PID_KI 0.0 // Integral gain | |
#endif | |
#ifndef MCCONF_P_PID_KD | |
-#define MCCONF_P_PID_KD 0.0004 // Derivative gain | |
+#define MCCONF_P_PID_KD 0.0004 // Derivative gain | |
+#endif | |
+#ifndef MCCONF_P_PID_ANG_DIV | |
+#define MCCONF_P_PID_ANG_DIV 1.0 // Divide angle by this value | |
#endif | |
// Current control parameters | |
#ifndef MCCONF_CC_GAIN | |
-#define MCCONF_CC_GAIN 0.0046 // Current controller error gain | |
+#define MCCONF_CC_GAIN 0.0046 // Current controller error gain | |
#endif | |
#ifndef MCCONF_CC_MIN_CURRENT | |
-#define MCCONF_CC_MIN_CURRENT 1.0 // Minimum allowed current | |
+#define MCCONF_CC_MIN_CURRENT 0.5 // Minimum allowed current | |
#endif | |
#ifndef MCCONF_CC_STARTUP_BOOST_DUTY | |
-#define MCCONF_CC_STARTUP_BOOST_DUTY 0.01 // The lowest duty cycle to use in current control mode (has to be > MCPWM_MIN_DUTY_CYCLE) | |
+#define MCCONF_CC_STARTUP_BOOST_DUTY 0.01 // The lowest duty cycle to use in current control mode (has to be > MCPWM_MIN_DUTY_CYCLE) | |
#endif | |
#ifndef MCCONF_CC_RAMP_STEP | |
-#define MCCONF_CC_RAMP_STEP 0.04 // Maximum duty cycle ramping step in CC mode | |
+#define MCCONF_CC_RAMP_STEP 0.04 // Maximum duty cycle ramping step in CC mode | |
#endif | |
// BLDC | |
#ifndef MCCONF_SL_MIN_RPM | |
-#define MCCONF_SL_MIN_RPM 150 // Auto-commutate below this RPM | |
+#define MCCONF_SL_MIN_RPM 150 // Auto-commutate below this RPM | |
#endif | |
#ifndef MCCONF_SL_MIN_ERPM_CYCLE_INT_LIMIT | |
#define MCCONF_SL_MIN_ERPM_CYCLE_INT_LIMIT 1100.0 // Minimum RPM to calculate the BEMF coupling from | |
#endif | |
#ifndef MCCONF_SL_CYCLE_INT_LIMIT | |
-#define MCCONF_SL_CYCLE_INT_LIMIT 62.0 // Flux integrator limit 0 ERPM | |
+#define MCCONF_SL_CYCLE_INT_LIMIT 100.0 // Flux integrator limit 0 ERPM | |
#endif | |
#ifndef MCCONF_SL_BEMF_COUPLING_K | |
#define MCCONF_SL_BEMF_COUPLING_K 600.0 // Input voltage to bemf coupling constant | |
#endif | |
#ifndef MCCONF_SL_PHASE_ADVANCE_AT_BR | |
-#define MCCONF_SL_PHASE_ADVANCE_AT_BR 0.8 // Flux integrator limit percentage at MCPWM_CYCLE_INT_START_RPM_BR ERPM | |
+#define MCCONF_SL_PHASE_ADVANCE_AT_BR 0.8 // Flux integrator limit percentage at MCPWM_CYCLE_INT_START_RPM_BR ERPM | |
#endif | |
#ifndef MCCONF_SL_CYCLE_INT_BR | |
#define MCCONF_SL_CYCLE_INT_BR 80000.0 // RPM border between the START and LOW interval | |
@@ -159,18 +165,47 @@ | |
#define MCCONF_SL_MAX_FB_CURR_DIR_CHANGE 10.0 // Maximum current during full brake during which a direction change is allowed | |
#endif | |
+// BLDC hall sensor table | |
+#ifndef MCCONF_HALL_TAB_0 | |
+#define MCCONF_HALL_TAB_0 -1 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_1 | |
+#define MCCONF_HALL_TAB_1 1 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_2 | |
+#define MCCONF_HALL_TAB_2 3 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_3 | |
+#define MCCONF_HALL_TAB_3 2 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_4 | |
+#define MCCONF_HALL_TAB_4 5 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_5 | |
+#define MCCONF_HALL_TAB_5 6 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_6 | |
+#define MCCONF_HALL_TAB_6 4 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_7 | |
+#define MCCONF_HALL_TAB_7 -1 | |
+#endif | |
+#ifndef MCCONF_HALL_ERPM | |
+#define MCCONF_HALL_ERPM 5000.0 // ERPM above which sensorless commutation is used in hybrid mode | |
+#endif | |
+ | |
// FOC | |
#ifndef MCCONF_FOC_CURRENT_KP | |
-#define MCCONF_FOC_CURRENT_KP 0.03 | |
+#define MCCONF_FOC_CURRENT_KP 0.0215 //0.0255 | |
#endif | |
#ifndef MCCONF_FOC_CURRENT_KI | |
-#define MCCONF_FOC_CURRENT_KI 50.0 | |
+#define MCCONF_FOC_CURRENT_KI 47.80 //41.00 | |
#endif | |
#ifndef MCCONF_FOC_F_SW | |
-#define MCCONF_FOC_F_SW 25000.0 | |
+#define MCCONF_FOC_F_SW 20000.0 | |
#endif | |
#ifndef MCCONF_FOC_DT_US | |
-#define MCCONF_FOC_DT_US 0.15 // Microseconds for dead time compensation | |
+#define MCCONF_FOC_DT_US 0.08 // Microseconds for dead time compensation | |
#endif | |
#ifndef MCCONF_FOC_ENCODER_INVERTED | |
#define MCCONF_FOC_ENCODER_INVERTED false | |
@@ -182,25 +217,25 @@ | |
#define MCCONF_FOC_ENCODER_RATIO 7.0 | |
#endif | |
#ifndef MCCONF_FOC_SENSOR_MODE | |
-#define MCCONF_FOC_SENSOR_MODE FOC_SENSOR_MODE_SENSORLESS | |
+#define MCCONF_FOC_SENSOR_MODE FOC_SENSOR_MODE_HALL | |
#endif | |
#ifndef MCCONF_FOC_PLL_KP | |
-#define MCCONF_FOC_PLL_KP 40.0 | |
+#define MCCONF_FOC_PLL_KP 2000.0 | |
#endif | |
#ifndef MCCONF_FOC_PLL_KI | |
-#define MCCONF_FOC_PLL_KI 40000.0 | |
+#define MCCONF_FOC_PLL_KI 20000.0 | |
#endif | |
#ifndef MCCONF_FOC_MOTOR_L | |
-#define MCCONF_FOC_MOTOR_L 0.000007 | |
+#define MCCONF_FOC_MOTOR_L 0.0000215 //0.0000255 | |
#endif | |
#ifndef MCCONF_FOC_MOTOR_R | |
-#define MCCONF_FOC_MOTOR_R 0.015 | |
+#define MCCONF_FOC_MOTOR_R 0.04780 //0.04100 | |
#endif | |
#ifndef MCCONF_FOC_MOTOR_FLUX_LINKAGE | |
-#define MCCONF_FOC_MOTOR_FLUX_LINKAGE 0.00245 | |
+#define MCCONF_FOC_MOTOR_FLUX_LINKAGE 0.006278//0.004363 | |
#endif | |
#ifndef MCCONF_FOC_OBSERVER_GAIN | |
-#define MCCONF_FOC_OBSERVER_GAIN 9e7 // Can be something like 600 / L | |
+#define MCCONF_FOC_OBSERVER_GAIN 4.651e7 //3.922e7 // Can be something like 600 / L | |
#endif | |
#ifndef MCCONF_FOC_DUTY_DOWNRAMP_KP | |
#define MCCONF_FOC_DUTY_DOWNRAMP_KP 10.0 // PI controller for duty control when decreasing the duty | |
@@ -209,48 +244,46 @@ | |
#define MCCONF_FOC_DUTY_DOWNRAMP_KI 200.0 // PI controller for duty control when decreasing the duty | |
#endif | |
#ifndef MCCONF_FOC_OPENLOOP_RPM | |
-#define MCCONF_FOC_OPENLOOP_RPM 350.0 // Openloop RPM (sensorless low speed or when finding index pulse) | |
+#define MCCONF_FOC_OPENLOOP_RPM 1200.0 // Openloop RPM (sensorless low speed or when finding index pulse) | |
#endif | |
#ifndef MCCONF_FOC_SL_OPENLOOP_HYST | |
-#define MCCONF_FOC_SL_OPENLOOP_HYST 0.5 // Time below min RPM to activate openloop (s) | |
+#define MCCONF_FOC_SL_OPENLOOP_HYST 0.5 // Time below min RPM to activate openloop (s) | |
#endif | |
#ifndef MCCONF_FOC_SL_OPENLOOP_TIME | |
-#define MCCONF_FOC_SL_OPENLOOP_TIME 0.5 // Time to remain in openloop (s) | |
+#define MCCONF_FOC_SL_OPENLOOP_TIME 0.5 // Time to remain in openloop (s) | |
#endif | |
#ifndef MCCONF_FOC_SL_D_CURRENT_DUTY | |
-#define MCCONF_FOC_SL_D_CURRENT_DUTY 0.0 // Inject d-axis current below this duty cycle in sensorless more | |
+#define MCCONF_FOC_SL_D_CURRENT_DUTY 0.0 // Inject d-axis current below this duty cycle in sensorless more | |
#endif | |
#ifndef MCCONF_FOC_SL_D_CURRENT_FACTOR | |
-#define MCCONF_FOC_SL_D_CURRENT_FACTOR 0.0 // Maximum q-axis current factor | |
+#define MCCONF_FOC_SL_D_CURRENT_FACTOR 0.0 // Maximum q-axis current factor | |
#endif | |
- | |
-// Default hall sensor table | |
-#ifndef MCCONF_HALL_TAB_0 | |
-#define MCCONF_HALL_TAB_0 -1 | |
+#ifndef MCCONF_FOC_HALL_TAB_0 | |
+#define MCCONF_FOC_HALL_TAB_0 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_1 | |
-#define MCCONF_HALL_TAB_1 1 | |
+#ifndef MCCONF_FOC_HALL_TAB_1 | |
+#define MCCONF_FOC_HALL_TAB_1 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_2 | |
-#define MCCONF_HALL_TAB_2 3 | |
+#ifndef MCCONF_FOC_HALL_TAB_2 | |
+#define MCCONF_FOC_HALL_TAB_2 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_3 | |
-#define MCCONF_HALL_TAB_3 2 | |
+#ifndef MCCONF_FOC_HALL_TAB_3 | |
+#define MCCONF_FOC_HALL_TAB_3 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_4 | |
-#define MCCONF_HALL_TAB_4 5 | |
+#ifndef MCCONF_FOC_HALL_TAB_4 | |
+#define MCCONF_FOC_HALL_TAB_4 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_5 | |
-#define MCCONF_HALL_TAB_5 6 | |
+#ifndef MCCONF_FOC_HALL_TAB_5 | |
+#define MCCONF_FOC_HALL_TAB_5 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_6 | |
-#define MCCONF_HALL_TAB_6 4 | |
+#ifndef MCCONF_FOC_HALL_TAB_6 | |
+#define MCCONF_FOC_HALL_TAB_6 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_7 | |
-#define MCCONF_HALL_TAB_7 -1 | |
+#ifndef MCCONF_FOC_HALL_TAB_7 | |
+#define MCCONF_FOC_HALL_TAB_7 255 | |
#endif | |
-#ifndef MCCONF_HALL_ERPM | |
-#define MCCONF_HALL_ERPM 2000.0 // ERPM above which sensorless commutation is used in hybrid mode | |
+#ifndef MCCONF_FOC_SL_ERPM | |
+#define MCCONF_FOC_SL_ERPM 5000.0 // ERPM above which only the observer is used | |
#endif | |
// Misc | |
@@ -258,16 +291,25 @@ | |
#define MCCONF_M_FAULT_STOP_TIME 3000 // Ignore commands for this duration in msec when faults occur | |
#endif | |
#ifndef MCCONF_M_RAMP_STEP | |
-#define MCCONF_M_RAMP_STEP 0.02 // Duty cycle ramping step (1000 times/sec) at maximum duty cycle | |
+#define MCCONF_M_RAMP_STEP 0.02 // Duty cycle ramping step (1000 times/sec) at maximum duty cycle | |
#endif | |
#ifndef MCCONF_M_RAMP_STEP_RPM_LIM | |
#define MCCONF_M_RAMP_STEP_RPM_LIM 0.0005 // Ramping step when limiting the RPM | |
#endif | |
#ifndef MCCONF_M_CURRENT_BACKOFF_GAIN | |
-#define MCCONF_M_CURRENT_BACKOFF_GAIN 0.5 // The error gain of the current limiting algorithm | |
+#define MCCONF_M_CURRENT_BACKOFF_GAIN 0.5 // The error gain of the current limiting algorithm | |
#endif | |
#ifndef MCCONF_M_ENCODER_COUNTS | |
#define MCCONF_M_ENCODER_COUNTS 8192 // The number of encoder counts | |
#endif | |
+#ifndef MCCONF_M_SENSOR_PORT_MODE | |
+#define MCCONF_M_SENSOR_PORT_MODE SENSOR_PORT_MODE_HALL // The mode of the hall_encoder port | |
+#endif | |
+#ifndef MCCONF_USE_MAX_WATT_LIMIT | |
+#define MCCONF_USE_MAX_WATT_LIMIT false | |
+#endif | |
+#ifndef MCCONF_WATT_MAX | |
+#define MCCONF_WATT_MAX 1000.0 // Input current limit in Amperes (Upper) | |
+#endif | |
#endif /* MCCONF_DEFAULT_H_ */ | |
Only in Raptor2 Sources/bldc-firmware_2_80/mcconf: mcconf_default.h~ | |
Only in bldc-cc171422641a50c56452280575f2074f8a88aa45/mcconf: mcconf_foc_erwin.h | |
Only in bldc-cc171422641a50c56452280575f2074f8a88aa45/mcconf: mcconf_foc_scorpion.h | |
Only in bldc-cc171422641a50c56452280575f2074f8a88aa45/mcconf: mcconf_outrunner2.h | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/mcconf/mcconf_sten.h Raptor2 Sources/bldc-firmware_2_80/mcconf/mcconf_sten.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/mcconf/mcconf_sten.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcconf/mcconf_sten.h 2016-09-23 23:02:14.000000000 +0100 | |
@@ -26,43 +26,54 @@ | |
#define MCCONF_STEN_H_ | |
/* | |
+ * HW: 4.10 | |
+ */ | |
+ | |
+/* | |
* Parameters | |
*/ | |
+#define MCCONF_DEFAULT_MOTOR_TYPE MOTOR_TYPE_BLDC | |
#define MCCONF_L_CURRENT_MAX 35.0 // Current limit in Amperes (Upper) | |
#define MCCONF_L_CURRENT_MIN -30.0 // Current limit in Amperes (Lower) | |
-#define MCCONF_L_MAX_ABS_CURRENT 100.0 // The maximum absolute current above which a fault is generated | |
+#define MCCONF_L_MAX_ABS_CURRENT 130.0 // The maximum absolute current above which a fault is generated | |
#define MCCONF_L_SLOW_ABS_OVERCURRENT 1 // Use the filtered (and hence slower) current for the overcurrent fault detection | |
-#define MCCONF_L_IN_CURRENT_MAX 25.0 // Input current limit in Amperes (Upper) | |
-#define MCCONF_L_IN_CURRENT_MIN -20.0 // Input current limit in Amperes (Lower) | |
+#define MCCONF_L_IN_CURRENT_MAX 25.0 // Input current limit in Amperes (Upper) | |
+#define MCCONF_L_IN_CURRENT_MIN -20.0 // Input current limit in Amperes (Lower) | |
#define MCCONF_L_RPM_MAX 80000.0 // The motor speed limit (Upper) | |
#define MCCONF_L_RPM_MIN -80000.0 // The motor speed limit (Lower) | |
-#define MCCONF_L_MIN_VOLTAGE 20.0 // Minimum input voltage | |
-#define MCCONF_L_MAX_VOLTAGE 50.0 // Maximum input voltage | |
-#define MCCONF_CC_STARTUP_BOOST_DUTY 0.02 // The lowest duty cycle to use in current control mode (has to be > MCPWM_MIN_DUTY_CYCLE) | |
+#define MCCONF_L_MIN_VOLTAGE 10.0 // Minimum input voltage | |
+#define MCCONF_L_MAX_VOLTAGE 57.0 // Maximum input voltage | |
+#define MCCONF_CC_STARTUP_BOOST_DUTY 0.03 // The lowest duty cycle to use in current control mode (has to be > MCPWM_MIN_DUTY_CYCLE) | |
#define MCCONF_L_RPM_LIMIT_NEG_TORQUE 0 // Use negative torque to limit the RPM | |
#define MCCONF_L_CURR_MAX_RPM_FBRAKE 1500 // Maximum electrical RPM to use full brake at | |
+#define MCCONF_L_BATTERY_CUT_START 41.0 // Start limiting the positive current at this voltage | |
+#define MCCONF_L_BATTERY_CUT_END 39.0 // Limit the positive current completely at this voltage | |
+ | |
// Sensorless settings | |
#define MCCONF_SENSOR_MODE SENSOR_MODE_SENSORLESS // Sensor mode | |
#define MCCONF_SL_MIN_RPM 250 // Auto-commutate below this RPM | |
-#define MCCONF_SL_MIN_ERPM_CYCLE_INT_LIMIT 500.0 // Minimum RPM to calculate the BEMF coupling from | |
+#define MCCONF_SL_MIN_ERPM_CYCLE_INT_LIMIT 1100.0 // Minimum RPM to calculate the BEMF coupling from | |
#define MCCONF_SL_CYCLE_INT_LIMIT 80.0 // Flux integrator limit 0 ERPM | |
#define MCCONF_SL_PHASE_ADVANCE_AT_BR 0.8 // Flux integrator limit percentage at MCPWM_CYCLE_INT_START_RPM_BR ERPM | |
#define MCCONF_SL_BEMF_COUPLING_K 750.0 // Input voltage to bemf coupling constant | |
+// FOC settings | |
+#define MCCONF_FOC_CURRENT_KP 0.03 | |
+#define MCCONF_FOC_CURRENT_KI 50.0 | |
+#define MCCONF_FOC_F_SW 20000.0 | |
+#define MCCONF_FOC_MOTOR_L 0.000007 | |
+#define MCCONF_FOC_MOTOR_R 0.015 | |
+#define MCCONF_FOC_MOTOR_FLUX_LINKAGE 0.00245 | |
+#define MCCONF_FOC_OBSERVER_GAIN 9e7 | |
+#define MCCONF_FOC_OPENLOOP_RPM 600.0 | |
+#define MCCONF_FOC_SL_OPENLOOP_HYST 0.5 | |
+#define MCCONF_FOC_SL_OPENLOOP_TIME 0.5 | |
+ | |
// Speed PID parameters | |
#define MCCONF_S_PID_KP 0.0001 // Proportional gain | |
#define MCCONF_S_PID_KI 0.002 // Integral gain | |
#define MCCONF_S_PID_KD 0.0 // Derivative gain | |
-#define MCCONF_S_PID_MIN_RPM 1200.0 // Minimum allowed RPM | |
- | |
-// Position PID parameters | |
-#define MCCONF_P_PID_KP 0.0001 // Proportional gain | |
-#define MCCONF_P_PID_KI 0.002 // Integral gain | |
-#define MCCONF_P_PID_KD 0.0 // Derivative gain | |
- | |
-// Current control parameters | |
-#define MCCONF_CC_GAIN 0.0046 // Current controller error gain | |
-#define MCCONF_CC_MIN_CURRENT 0.05 // Minimum allowed current | |
- | |
+#define MCCONF_S_PID_MIN_RPM 1200.0 // Minimum allowed RPM | |
+#define MCCONF_S_PID_BREAKING_ENABLED 1 // enable braking at pid speed mode (cruise control) | |
#endif /* MCCONF_STEN_H_ */ | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/mcpwm.c Raptor2 Sources/bldc-firmware_2_80/mcpwm.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/mcpwm.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcpwm.c 2017-04-13 18:06:02.000000000 +0100 | |
@@ -56,6 +56,7 @@ | |
static volatile float dutycycle_now; | |
static volatile float rpm_now; | |
static volatile float speed_pid_set_rpm; | |
+static volatile ppm_cruise speed_pid_cruise_control_type; | |
static volatile float pos_pid_set_pos; | |
static volatile float current_set; | |
static volatile int tachometer; | |
@@ -90,6 +91,8 @@ | |
static volatile float last_pwm_cycles_sums[6]; | |
static volatile bool dccal_done; | |
static volatile bool sensorless_now; | |
+static volatile float sensor_hyst_min; | |
+static volatile float sensor_hyst_max; | |
static volatile int hall_detect_table[8][7]; | |
// KV FIR filter | |
@@ -174,6 +177,7 @@ | |
dutycycle_set = 0.0; | |
dutycycle_now = 0.0; | |
speed_pid_set_rpm = 0.0; | |
+ speed_pid_cruise_control_type = CRUISE_CONTROL_MOTOR_SETTINGS; | |
pos_pid_set_pos = 0.0; | |
current_set = 0.0; | |
tachometer = 0; | |
@@ -494,7 +498,7 @@ | |
* The commutations corresponding to the hall sensor states in the forward direction- | |
*/ | |
void mcpwm_init_hall_table(int8_t *table) { | |
- const int fwd_to_rev[7] = {-1,4,3,2,1,6,5}; | |
+ const int fwd_to_rev[7] = {-1,1,6,5,4,3,2}; | |
for (int i = 0;i < 8;i++) { | |
hall_to_phase_table[8 + i] = table[i]; | |
@@ -505,14 +509,16 @@ | |
continue; | |
} | |
- ind_now += 2; | |
- if (ind_now > 6) { | |
- ind_now -= 6; | |
- } | |
- ind_now = fwd_to_rev[ind_now]; | |
- | |
- hall_to_phase_table[i] = ind_now; | |
+ hall_to_phase_table[i] = fwd_to_rev[ind_now]; | |
+ } | |
+ | |
+ // init the sensor hyst | |
+ float sensor_hyst = conf->hall_sl_erpm * 0.10; | |
+ if(sensor_hyst > 500.0){ | |
+ sensor_hyst = 500.0; | |
} | |
+ sensor_hyst_min = conf->hall_sl_erpm - sensor_hyst; | |
+ sensor_hyst_max = conf->hall_sl_erpm + sensor_hyst; | |
} | |
static void do_dc_cal(void) { | |
@@ -571,8 +577,31 @@ | |
* The electrical RPM goal value to use. | |
*/ | |
void mcpwm_set_pid_speed(float rpm) { | |
+ if (fabsf(rpm) <conf->s_pid_min_erpm) { | |
+ mcpwm_set_duty(0.0); | |
+ return; | |
+ } | |
control_mode = CONTROL_MODE_SPEED; | |
speed_pid_set_rpm = rpm; | |
+ speed_pid_cruise_control_type = CRUISE_CONTROL_MOTOR_SETTINGS; | |
+ | |
+ if (state != MC_STATE_RUNNING) { | |
+ set_duty_cycle_hl(conf->l_min_duty); | |
+ } | |
+} | |
+ | |
+void mcpwm_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status) { | |
+ if (fabsf(rpm) <conf->s_pid_min_erpm) { | |
+ mcpwm_set_duty(0.0); | |
+ return; | |
+ } | |
+ control_mode = CONTROL_MODE_SPEED; | |
+ speed_pid_set_rpm = rpm; | |
+ speed_pid_cruise_control_type = cruise_status; | |
+ | |
+ if (state != MC_STATE_RUNNING) { | |
+ set_duty_cycle_hl(conf->l_min_duty); | |
+ } | |
} | |
/** | |
@@ -1064,23 +1093,23 @@ | |
} | |
static void run_pid_control_speed(void) { | |
- static float i_term = 0; | |
- static float prev_error = 0; | |
+ static float i_term = 0.0; | |
+ static float prev_error = 0.0; | |
float p_term; | |
float d_term; | |
// PID is off. Return. | |
if (control_mode != CONTROL_MODE_SPEED) { | |
- i_term = dutycycle_now; | |
- prev_error = 0; | |
+ i_term = 0.0; | |
+ prev_error = 0.0; | |
return; | |
} | |
- // Too low RPM set. Stop and return. | |
- if (fabsf(speed_pid_set_rpm) < conf->s_pid_min_erpm) { | |
- i_term = dutycycle_now; | |
+ // Too low RPM set. Reset state and return. | |
+ if (fabsf(speed_pid_set_rpm) <conf->s_pid_min_erpm) { | |
+ i_term = 0.0; | |
prev_error = 0; | |
- mcpwm_set_duty(0.0); | |
+ current_set = 0.0; | |
return; | |
} | |
@@ -1104,21 +1133,18 @@ | |
// Calculate output | |
float output = p_term + i_term + d_term; | |
- // Make sure that at least minimum output is used | |
- if (fabsf(output) < conf->l_min_duty) { | |
- output = SIGN(output) * conf->l_min_duty; | |
- } | |
- | |
- // Do not output in reverse direction to oppose too high rpm | |
- if (speed_pid_set_rpm > 0.0 && output < 0.0) { | |
- output = conf->l_min_duty; | |
- i_term = 0.0; | |
- } else if (speed_pid_set_rpm < 0.0 && output > 0.0) { | |
- output = -conf->l_min_duty; | |
- i_term = 0.0; | |
+ if ((speed_pid_cruise_control_type == CRUISE_CONTROL_MOTOR_SETTINGS && conf->s_pid_breaking_enabled) || speed_pid_cruise_control_type == CRUISE_CONTROL_BRAKING_ENABLED) { | |
+ utils_truncate_number(&output, -1.0, 1.0); | |
+ } else { | |
+ if(speed_pid_set_rpm < 0.0){ | |
+ utils_truncate_number(&output, -1.0, 0.0); | |
+ }else{ | |
+ utils_truncate_number(&output, 0.0, 1.0); | |
+ } | |
} | |
- | |
- set_duty_cycle_hl(output); | |
+ | |
+ current_set = output * conf->lo_current_max; | |
+ | |
} | |
static void run_pid_control_pos(float dt) { | |
@@ -1784,7 +1810,7 @@ | |
float dutycycle_now_tmp = dutycycle_now; | |
- if (control_mode == CONTROL_MODE_CURRENT || control_mode == CONTROL_MODE_POS) { | |
+ if (control_mode == CONTROL_MODE_CURRENT || control_mode == CONTROL_MODE_POS || control_mode == CONTROL_MODE_SPEED) { | |
// Compute error | |
const float error = current_set - (direction ? current_nofilter : -current_nofilter); | |
float step = error * conf->cc_gain * voltage_scale; | |
@@ -1922,7 +1948,7 @@ | |
mc_interface_mc_timer_isr(); | |
- if (ENCODER_ENABLE) { | |
+ if (encoder_is_configured()) { | |
run_pid_control_pos(1.0 / switching_frequency_now); | |
} | |
@@ -2051,7 +2077,7 @@ | |
int mcpwm_get_hall_detect_result(int8_t *table) { | |
if (WS2811_ENABLE) { | |
return -2; | |
- } else if (ENCODER_ENABLE) { | |
+ } else if (conf->m_sensor_port_mode != SENSOR_PORT_MODE_HALL) { | |
return -3; | |
} | |
@@ -2336,6 +2362,7 @@ | |
} | |
} | |
+/* | |
static void update_sensor_mode(void) { | |
if (conf->sensor_mode == SENSOR_MODE_SENSORLESS || | |
(conf->sensor_mode == SENSOR_MODE_HYBRID && | |
@@ -2345,6 +2372,26 @@ | |
sensorless_now = false; | |
} | |
} | |
+*/ | |
+ | |
+static void update_sensor_mode(void) { | |
+ if (conf->sensor_mode == SENSOR_MODE_SENSORLESS ) { | |
+ sensorless_now = true; | |
+ } else if (conf->sensor_mode == SENSOR_MODE_HYBRID) { | |
+ // Hysteresis 5 % of total speed | |
+ if (sensorless_now) { | |
+ if (fabsf(rpm_now) < sensor_hyst_min) { | |
+ sensorless_now = false; | |
+ } | |
+ } else { | |
+ if (fabsf(rpm_now) > sensor_hyst_max) { | |
+ sensorless_now = true; | |
+ } | |
+ } | |
+ }else{ | |
+ sensorless_now = false; | |
+ } | |
+} | |
static void commutate(int steps) { | |
last_pwm_cycles_sum = pwm_cycles_sum; | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/mcpwm.h Raptor2 Sources/bldc-firmware_2_80/mcpwm.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/mcpwm.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcpwm.h 2017-04-13 18:06:14.000000000 +0100 | |
@@ -35,6 +35,7 @@ | |
void mcpwm_set_duty(float dutyCycle); | |
void mcpwm_set_duty_noramp(float dutyCycle); | |
void mcpwm_set_pid_speed(float rpm); | |
+void mcpwm_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status); | |
void mcpwm_set_pid_pos(float pos); | |
void mcpwm_set_current(float current); | |
void mcpwm_set_brake_current(float current); | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/mcpwm_foc.c Raptor2 Sources/bldc-firmware_2_80/mcpwm_foc.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/mcpwm_foc.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcpwm_foc.c 2017-06-05 00:12:34.000000000 +0100 | |
@@ -51,6 +51,7 @@ | |
float i_abs; | |
float i_abs_filter; | |
float i_bus; | |
+ float i_bus_filter; | |
float v_bus; | |
float v_alpha; | |
float v_beta; | |
@@ -89,8 +90,9 @@ | |
static volatile float m_iq_set; | |
static volatile bool m_dccal_done; | |
static volatile bool m_output_on; | |
-static volatile float m_pos_pid_set_pos; | |
+static volatile float m_pos_pid_set; | |
static volatile float m_speed_pid_set_rpm; | |
+static volatile ppm_cruise m_speed_pid_cruise_control_type; | |
static volatile float m_phase_now_observer; | |
static volatile float m_phase_now_observer_override; | |
static volatile bool m_phase_observer_override; | |
@@ -101,9 +103,10 @@ | |
static volatile float m_pll_phase; | |
static volatile float m_pll_speed; | |
static volatile mc_sample_t m_samples; | |
-static volatile int m_tachometer; | |
-static volatile int m_tachometer_abs; | |
+static volatile float m_tachometer; | |
+static volatile float m_tachometer_abs; | |
static volatile float last_inj_adc_isr_duration; | |
+static volatile float m_pos_pid_now; | |
// Private functions | |
static void do_dc_cal(void); | |
@@ -114,10 +117,13 @@ | |
static void control_current(volatile motor_state_t *state_m, float dt); | |
static void svm(float alpha, float beta, uint32_t PWMHalfPeriod, | |
uint32_t* tAout, uint32_t* tBout, uint32_t* tCout); | |
-static void run_pid_control_pos(float dt); | |
+static void run_pid_control_pos(float angle_now, float angle_set, float dt); | |
static void run_pid_control_speed(float dt); | |
static void stop_pwm_hw(void); | |
static void start_pwm_hw(void); | |
+static int read_hall(void); | |
+static float correct_encoder(float obs_angle, float enc_angle, float speed); | |
+static float correct_hall(float angle, float speed, float dt); | |
// Threads | |
static THD_WORKING_AREA(timer_thread_wa, 2048); | |
@@ -199,8 +205,9 @@ | |
m_id_set = 0.0; | |
m_iq_set = 0.0; | |
m_output_on = false; | |
- m_pos_pid_set_pos = 0.0; | |
+ m_pos_pid_set = 0.0; | |
m_speed_pid_set_rpm = 0.0; | |
+ m_speed_pid_cruise_control_type = CRUISE_CONTROL_MOTOR_SETTINGS; | |
m_phase_now_observer = 0.0; | |
m_phase_now_observer_override = 0.0; | |
m_phase_observer_override = false; | |
@@ -210,9 +217,10 @@ | |
m_observer_x2 = 0.0; | |
m_pll_phase = 0.0; | |
m_pll_speed = 0.0; | |
- m_tachometer = 0; | |
- m_tachometer_abs = 0; | |
+ m_tachometer = 0.0; | |
+ m_tachometer_abs = 0.0; | |
last_inj_adc_isr_duration = 0; | |
+ m_pos_pid_now = 0.0; | |
memset((void*)&m_motor_state, 0, sizeof(motor_state_t)); | |
memset((void*)&m_samples, 0, sizeof(mc_sample_t)); | |
@@ -512,10 +520,30 @@ | |
* The electrical RPM goal value to use. | |
*/ | |
void mcpwm_foc_set_pid_speed(float rpm) { | |
+ // Too low RPM set. Reset state and return. | |
+ if (fabsf(rpm) < m_conf->s_pid_min_erpm) { | |
+ mcpwm_foc_set_duty(0.0); | |
+ return; | |
+ } | |
+ m_control_mode = CONTROL_MODE_SPEED; | |
+ m_speed_pid_set_rpm = rpm; | |
+ m_speed_pid_cruise_control_type = CRUISE_CONTROL_MOTOR_SETTINGS; | |
+ | |
+ if (m_state != MC_STATE_RUNNING) { | |
+ m_state = MC_STATE_RUNNING; | |
+ } | |
+} | |
+ | |
+void mcpwm_foc_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status) { | |
+ if (fabsf(rpm) < m_conf->s_pid_min_erpm) { | |
+ mcpwm_foc_set_duty(0.0); | |
+ return; | |
+ } | |
m_control_mode = CONTROL_MODE_SPEED; | |
m_speed_pid_set_rpm = rpm; | |
+ m_speed_pid_cruise_control_type = cruise_status; | |
- if (m_state != MC_STATE_RUNNING && fabsf(rpm) > m_conf->s_pid_min_erpm) { | |
+ if (m_state != MC_STATE_RUNNING) { | |
m_state = MC_STATE_RUNNING; | |
} | |
} | |
@@ -529,7 +557,7 @@ | |
*/ | |
void mcpwm_foc_set_pid_pos(float pos) { | |
m_control_mode = CONTROL_MODE_POS; | |
- m_pos_pid_set_pos = pos; | |
+ m_pos_pid_set = pos; | |
if (m_state != MC_STATE_RUNNING) { | |
m_state = MC_STATE_RUNNING; | |
@@ -577,7 +605,7 @@ | |
return; | |
} | |
- utils_truncate_number(¤t, m_conf->lo_current_min, m_conf->lo_current_max); | |
+ utils_truncate_number(¤t, m_conf->lo_current_min, fabsf(m_conf->lo_current_min)); | |
m_control_mode = CONTROL_MODE_CURRENT_BRAKE; | |
m_iq_set = current; | |
@@ -595,6 +623,14 @@ | |
return m_motor_state.duty_now; | |
} | |
+float mcpwm_foc_get_pid_pos_set(void) { | |
+ return m_pos_pid_set; | |
+} | |
+ | |
+float mcpwm_foc_get_pid_pos_now(void) { | |
+ return m_pos_pid_now; | |
+} | |
+ | |
/** | |
* Get the current switching frequency. | |
* | |
@@ -702,7 +738,7 @@ | |
* The filtered input current. | |
*/ | |
float mcpwm_foc_get_tot_current_in_filtered(void) { | |
- return m_motor_state.i_bus; // TODO: Calculate filtered current? | |
+ return m_motor_state.i_bus_filter; // TODO: Calculate filtered current? | |
} | |
/** | |
@@ -717,10 +753,10 @@ | |
* be this number divided by (3 * MOTOR_POLE_NUMBER). | |
*/ | |
int mcpwm_foc_get_tachometer_value(bool reset) { | |
- int val = m_tachometer; | |
+ int val = (int) m_tachometer; | |
if (reset) { | |
- m_tachometer = 0; | |
+ m_tachometer = 0.0; | |
} | |
return val; | |
@@ -737,10 +773,10 @@ | |
* be this number divided by (3 * MOTOR_POLE_NUMBER). | |
*/ | |
int mcpwm_foc_get_tachometer_abs_value(bool reset) { | |
- int val = m_tachometer_abs; | |
+ int val = (int) m_tachometer_abs; | |
if (reset) { | |
- m_tachometer_abs = 0; | |
+ m_tachometer_abs = 0.0; | |
} | |
return val; | |
@@ -806,6 +842,8 @@ | |
* The detected direction. | |
*/ | |
void mcpwm_foc_encoder_detect(float current, bool print, float *offset, float *ratio, bool *inverted) { | |
+ mc_interface_lock(); | |
+ | |
m_phase_override = true; | |
m_id_set = current; | |
m_iq_set = 0.0; | |
@@ -815,7 +853,7 @@ | |
// Disable timeout | |
systime_t tout = timeout_get_timeout_msec(); | |
float tout_c = timeout_get_brake_current(); | |
- timeout_configure(60000, 0.0); | |
+ timeout_configure(600000, 0.0); | |
// Save configuration | |
float offset_old = m_conf->foc_encoder_offset; | |
@@ -858,34 +896,68 @@ | |
// Inverted and ratio | |
chThdSleepMilliseconds(1000); | |
+ const int it_rat = 20; | |
float s_sum = 0.0; | |
float c_sum = 0.0; | |
- for (int i = 0; i < 10; i++) { | |
+ float first = m_phase_now_encoder; | |
+ | |
+ for (int i = 0; i < it_rat; i++) { | |
float phase_old = m_phase_now_encoder; | |
float phase_ovr_tmp = m_phase_now_override; | |
- for (float i = phase_ovr_tmp; i < phase_ovr_tmp + 0.8 * M_PI; | |
+ for (float i = phase_ovr_tmp; i < phase_ovr_tmp + (2.0 / 3.0) * M_PI; | |
i += (2.0 * M_PI) / 500.0) { | |
m_phase_now_override = i; | |
- chThdSleepMilliseconds(2); | |
+ chThdSleepMilliseconds(1); | |
+ } | |
+ utils_norm_angle_rad((float*)&m_phase_now_override); | |
+ chThdSleepMilliseconds(300); | |
+ float diff = utils_angle_difference_rad(m_phase_now_encoder, phase_old); | |
+ | |
+ float s, c; | |
+ sincosf(diff, &s, &c); | |
+ s_sum += s; | |
+ c_sum += c; | |
+ | |
+ if (print) { | |
+ commands_printf("%.2f", (double)(diff * 180.0 / M_PI)); | |
+ } | |
+ | |
+ if (i > 3 && fabsf(utils_angle_difference_rad(m_phase_now_encoder, first)) < fabsf(diff / 2.0)) { | |
+ break; | |
+ } | |
+ } | |
+ | |
+ first = m_phase_now_encoder; | |
+ | |
+ for (int i = 0; i < it_rat; i++) { | |
+ float phase_old = m_phase_now_encoder; | |
+ float phase_ovr_tmp = m_phase_now_override; | |
+ for (float i = phase_ovr_tmp; i > phase_ovr_tmp - (2.0 / 3.0) * M_PI; | |
+ i -= (2.0 * M_PI) / 500.0) { | |
+ m_phase_now_override = i; | |
+ chThdSleepMilliseconds(1); | |
} | |
- chThdSleepMilliseconds(1000); | |
- float diff = utils_angle_difference( | |
- m_phase_now_encoder * (180.0 / M_PI), | |
- phase_old * (180.0 / M_PI)); | |
+ utils_norm_angle_rad((float*)&m_phase_now_override); | |
+ chThdSleepMilliseconds(300); | |
+ float diff = utils_angle_difference_rad(phase_old, m_phase_now_encoder); | |
float s, c; | |
- sincosf(diff * M_PI / 180.0, &s, &c); | |
+ sincosf(diff, &s, &c); | |
s_sum += s; | |
c_sum += c; | |
if (print) { | |
- commands_printf("%.2f", (double)diff); | |
+ commands_printf("%.2f", (double)(diff * 180.0 / M_PI)); | |
+ } | |
+ | |
+ if (i > 3 && fabsf(utils_angle_difference_rad(m_phase_now_encoder, first)) < fabsf(diff / 2.0)) { | |
+ break; | |
} | |
} | |
float diff = atan2f(s_sum, c_sum) * 180.0 / M_PI; | |
*inverted = diff < 0.0; | |
- *ratio = roundf((0.8 * 180.0) / | |
+ *ratio = roundf(((2.0 / 3.0) * 180.0) / | |
fabsf(diff)); | |
m_conf->foc_encoder_inverted = *inverted; | |
@@ -906,33 +978,37 @@ | |
commands_printf("Enc: %.2f", (double)encoder_read_deg()); | |
} | |
+ const int it_ofs = m_conf->foc_encoder_ratio * 3.0; | |
s_sum = 0.0; | |
c_sum = 0.0; | |
- for (int i = 0;i < 5;i++) { | |
- m_phase_now_override = (float)i * M_PI / 5.0; | |
- chThdSleepMilliseconds(1000); | |
+ for (int i = 0;i < it_ofs;i++) { | |
+ m_phase_now_override = ((float)i * 2.0 * M_PI * m_conf->foc_encoder_ratio) / ((float)it_ofs); | |
+ chThdSleepMilliseconds(500); | |
+ | |
+ float diff = utils_angle_difference_rad(m_phase_now_encoder, m_phase_now_override); | |
float s, c; | |
- sincosf(m_phase_now_encoder - m_phase_now_override, &s, &c); | |
+ sincosf(diff, &s, &c); | |
s_sum += s; | |
c_sum += c; | |
if (print) { | |
- commands_printf("%.2f", (double)((m_phase_now_encoder - m_phase_now_override) * 180.0 / M_PI)); | |
+ commands_printf("%.2f", (double)(diff * 180.0 / M_PI)); | |
} | |
} | |
- for (int i = 3;i >= -1;i--) { | |
- m_phase_now_override = (float)i * M_PI / 5.0; | |
- chThdSleepMilliseconds(1000); | |
+ for (int i = it_ofs;i > 0;i--) { | |
+ m_phase_now_override = ((float)i * 2.0 * M_PI * m_conf->foc_encoder_ratio) / ((float)it_ofs); | |
+ chThdSleepMilliseconds(500); | |
+ float diff = utils_angle_difference_rad(m_phase_now_encoder, m_phase_now_override); | |
float s, c; | |
- sincosf(m_phase_now_encoder - m_phase_now_override, &s, &c); | |
+ sincosf(diff, &s, &c); | |
s_sum += s; | |
c_sum += c; | |
if (print) { | |
- commands_printf("%.2f", (double)((m_phase_now_encoder - m_phase_now_override) * 180.0 / M_PI)); | |
+ commands_printf("%.2f", (double)(diff * 180.0 / M_PI)); | |
} | |
} | |
@@ -962,6 +1038,8 @@ | |
// Enable timeout | |
timeout_configure(tout, tout_c); | |
+ | |
+ mc_interface_unlock(); | |
} | |
/** | |
@@ -1117,7 +1195,7 @@ | |
float res_tmp = 0.0; | |
float i_last = 0.0; | |
- for (float i = 2.0;i < 35.0;i *= 1.5) { | |
+ for (float i = 2.0;i < (m_conf->l_current_max / 2.0);i *= 1.5) { | |
res_tmp = mcpwm_foc_measure_resistance(i, 20); | |
if (i > (0.5 / res_tmp)) { | |
@@ -1127,7 +1205,7 @@ | |
} | |
if (i_last < 0.01) { | |
- i_last = 35.0; | |
+ i_last = (m_conf->l_current_max / 2.0); | |
} | |
*res = mcpwm_foc_measure_resistance(i_last, 500); | |
@@ -1137,7 +1215,7 @@ | |
TIMER_UPDATE_SAMP_TOP(top - 2, 5, top); | |
float duty_last = 0.0; | |
- for (float i = 0.02;i < 0.9;i *= 1.5) { | |
+ for (float i = 0.02;i < 0.5;i *= 1.5) { | |
float i_tmp; | |
mcpwm_foc_measure_inductance(i, 20, &i_tmp); | |
@@ -1159,6 +1237,101 @@ | |
return true; | |
} | |
+/** | |
+ * Run the motor in open loop and figure out at which angles the hall sensors are. | |
+ * | |
+ * @param current | |
+ * Current to use. | |
+ * | |
+ * @param hall_table | |
+ * Table to store the result to. | |
+ * | |
+ * @return | |
+ * true: Success | |
+ * false: Something went wrong | |
+ */ | |
+bool mcpwm_foc_hall_detect(float current, uint8_t *hall_table) { | |
+ mc_interface_lock(); | |
+ | |
+ m_phase_override = true; | |
+ m_id_set = current; | |
+ m_iq_set = 0.0; | |
+ m_control_mode = CONTROL_MODE_CURRENT; | |
+ m_state = MC_STATE_RUNNING; | |
+ | |
+ // Disable timeout | |
+ systime_t tout = timeout_get_timeout_msec(); | |
+ float tout_c = timeout_get_brake_current(); | |
+ timeout_configure(60000, 0.0); | |
+ | |
+ // Lock the motor | |
+ m_phase_now_override = 0; | |
+ chThdSleepMilliseconds(1000); | |
+ | |
+ float sin_hall[8]; | |
+ float cos_hall[8]; | |
+ int hall_iterations[8]; | |
+ memset(sin_hall, 0, sizeof(sin_hall)); | |
+ memset(cos_hall, 0, sizeof(cos_hall)); | |
+ memset(hall_iterations, 0, sizeof(hall_iterations)); | |
+ | |
+ // Forwards | |
+ for (int i = 0;i < 3;i++) { | |
+ for (int i = 0;i < 360;i++) { | |
+ m_phase_now_override = (float)i * M_PI / 180.0; | |
+ chThdSleepMilliseconds(5); | |
+ | |
+ int hall = read_hall(); | |
+ float s, c; | |
+ sincosf(m_phase_now_override, &s, &c); | |
+ sin_hall[hall] += s; | |
+ cos_hall[hall] += c; | |
+ hall_iterations[hall]++; | |
+ } | |
+ } | |
+ | |
+ // Reverse | |
+ for (int i = 0;i < 3;i++) { | |
+ for (int i = 360;i >= 0;i--) { | |
+ m_phase_now_override = (float)i * M_PI / 180.0; | |
+ chThdSleepMilliseconds(5); | |
+ | |
+ int hall = read_hall(); | |
+ float s, c; | |
+ sincosf(m_phase_now_override, &s, &c); | |
+ sin_hall[hall] += s; | |
+ cos_hall[hall] += c; | |
+ hall_iterations[hall]++; | |
+ } | |
+ } | |
+ | |
+ m_id_set = 0.0; | |
+ m_iq_set = 0.0; | |
+ m_phase_override = false; | |
+ m_control_mode = CONTROL_MODE_NONE; | |
+ m_state = MC_STATE_OFF; | |
+ stop_pwm_hw(); | |
+ | |
+ // Enable timeout | |
+ timeout_configure(tout, tout_c); | |
+ | |
+ int fails = 0; | |
+ for(int i = 0;i < 8;i++) { | |
+ if (hall_iterations[i] > 30) { | |
+ float ang = atan2f(sin_hall[i], cos_hall[i]) * 180.0 / M_PI; | |
+ utils_norm_angle(&ang); | |
+ hall_table[i] = (uint8_t)(ang * 200.0 / 360.0); | |
+ } else { | |
+ hall_table[i] = 255; | |
+ fails++; | |
+ } | |
+ } | |
+ | |
+ mc_interface_unlock(); | |
+ | |
+ return fails == 2; | |
+} | |
+ | |
void mcpwm_foc_print_state(void) { | |
commands_printf("Mod d: %.2f", (double)m_motor_state.mod_d); | |
commands_printf("Mod q: %.2f", (double)m_motor_state.mod_q); | |
@@ -1259,16 +1432,18 @@ | |
m_motor_state.v_bus = GET_INPUT_VOLTAGE(); | |
-#if ENCODER_ENABLE | |
- float phase_tmp = encoder_read_deg(); | |
- if (m_conf->foc_encoder_inverted) { | |
- phase_tmp = 360.0 - phase_tmp; | |
- } | |
- phase_tmp *= m_conf->foc_encoder_ratio; | |
- phase_tmp -= m_conf->foc_encoder_offset; | |
- utils_norm_angle((float*)&phase_tmp); | |
- m_phase_now_encoder = phase_tmp * (M_PI / 180.0); | |
-#endif | |
+ float enc_ang = 0; | |
+ if (encoder_is_configured()) { | |
+ enc_ang = encoder_read_deg(); | |
+ float phase_tmp = enc_ang; | |
+ if (m_conf->foc_encoder_inverted) { | |
+ phase_tmp = 360.0 - phase_tmp; | |
+ } | |
+ phase_tmp *= m_conf->foc_encoder_ratio; | |
+ phase_tmp -= m_conf->foc_encoder_offset; | |
+ utils_norm_angle((float*)&phase_tmp); | |
+ m_phase_now_encoder = phase_tmp * (M_PI / 180.0); | |
+ } | |
static float phase_before = 0.0; | |
const float phase_diff = utils_angle_difference_rad(m_motor_state.phase, phase_before); | |
@@ -1299,12 +1474,19 @@ | |
// observer has lost tracking. Use duty cycle control with the lowest duty cycle | |
// to get as smooth braking as possible. | |
if (m_control_mode == CONTROL_MODE_CURRENT_BRAKE | |
- && m_conf->foc_sensor_mode == FOC_SENSOR_MODE_SENSORLESS | |
+// && (m_conf->foc_sensor_mode != FOC_SENSOR_MODE_ENCODER) // Don't use this with encoderss | |
&& fabsf(duty_filtered) < 0.03) { | |
control_duty = true; | |
duty_set = 0.0; | |
} | |
+ // Brake when set ERPM is below min ERPM | |
+ if (m_control_mode == CONTROL_MODE_SPEED && | |
+ fabsf(m_speed_pid_set_rpm) < m_conf->s_pid_min_erpm) { | |
+ control_duty = true; | |
+ duty_set = 0.0; | |
+ } | |
+ | |
if (control_duty) { | |
// Duty cycle control | |
static float duty_i_term = 0.0; | |
@@ -1361,7 +1543,7 @@ | |
switch (m_conf->foc_sensor_mode) { | |
case FOC_SENSOR_MODE_ENCODER: | |
if (encoder_index_found()) { | |
- m_motor_state.phase = m_phase_now_encoder; | |
+ m_motor_state.phase = correct_encoder(m_phase_now_observer, m_phase_now_encoder, m_pll_speed); | |
} else { | |
// Rotate the motor in open loop if the index isn't found. | |
m_motor_state.phase = m_phase_now_encoder_no_index; | |
@@ -1371,6 +1553,14 @@ | |
id_set_tmp = 0.0; | |
} | |
break; | |
+ case FOC_SENSOR_MODE_HALL: | |
+ m_phase_now_observer = correct_hall(m_phase_now_observer, m_pll_speed, dt); | |
+ m_motor_state.phase = m_phase_now_observer; | |
+ | |
+ if (!m_phase_override) { | |
+ id_set_tmp = 0.0; | |
+ } | |
+ break; | |
case FOC_SENSOR_MODE_SENSORLESS: | |
if (m_phase_observer_override) { | |
m_motor_state.phase = m_phase_now_observer_override; | |
@@ -1400,7 +1590,12 @@ | |
// Apply current limits | |
const float mod_q = m_motor_state.mod_q; | |
utils_truncate_number(&iq_set_tmp, m_conf->lo_current_min, m_conf->lo_current_max); | |
- utils_saturate_vector_2d(&id_set_tmp, &iq_set_tmp, m_conf->lo_current_max); | |
+ if (iq_set_tmp < 0.0) { | |
+ utils_saturate_vector_2d(&id_set_tmp, &iq_set_tmp, m_conf->lo_current_min); | |
+ } else { | |
+ | |
+ utils_saturate_vector_2d(&id_set_tmp, &iq_set_tmp, m_conf->lo_current_max); | |
+ } | |
if (mod_q > 0.001) { | |
utils_truncate_number(&iq_set_tmp, m_conf->lo_in_current_min / mod_q, m_conf->lo_in_current_max / mod_q); | |
} else if (mod_q < -0.001) { | |
@@ -1411,7 +1606,6 @@ | |
m_motor_state.iq_target = iq_set_tmp; | |
control_current(&m_motor_state, dt); | |
- run_pid_control_pos(dt); | |
} else { | |
// Track back emf | |
float Va = ADC_VOLTS(ADC_IND_SENS1) * ((VIN_R1 + VIN_R2) / VIN_R2); | |
@@ -1440,6 +1634,7 @@ | |
m_motor_state.id_filter = 0.0; | |
m_motor_state.iq_filter = 0.0; | |
m_motor_state.i_bus = 0.0; | |
+ m_motor_state.i_bus_filter = 0.0; | |
m_motor_state.i_abs = 0.0; | |
m_motor_state.i_abs_filter = 0.0; | |
@@ -1449,8 +1644,16 @@ | |
&m_observer_x2, &m_phase_now_observer); | |
switch (m_conf->foc_sensor_mode) { | |
- case FOC_SENSOR_MODE_ENCODER: m_motor_state.phase = m_phase_now_encoder; break; | |
- case FOC_SENSOR_MODE_SENSORLESS: m_motor_state.phase = m_phase_now_observer; break; | |
+ case FOC_SENSOR_MODE_ENCODER: | |
+ m_motor_state.phase = correct_encoder(m_phase_now_observer, m_phase_now_encoder, m_pll_speed); | |
+ break; | |
+ case FOC_SENSOR_MODE_HALL: | |
+ m_phase_now_observer = correct_hall(m_phase_now_observer, m_pll_speed, dt); | |
+ m_motor_state.phase = m_phase_now_observer; | |
+ break; | |
+ case FOC_SENSOR_MODE_SENSORLESS: | |
+ m_motor_state.phase = m_phase_now_observer; | |
+ break; | |
} | |
} | |
@@ -1464,13 +1667,38 @@ | |
// Update tachometer | |
static float phase_last = 0.0; | |
- int diff = (int)((utils_angle_difference_rad(m_motor_state.phase, phase_last) * (180.0 / M_PI)) / 60.0); | |
- if (diff != 0) { | |
+ // int diff = (int)((utils_angle_difference_rad(m_motor_state.phase, phase_last) * (180.0 / M_PI)) / 60.0); | |
+ float diff = (utils_angle_difference_rad(m_motor_state.phase, phase_last) * (180.0 / M_PI)) / 60.0; | |
+ if ((int) diff != 0) { | |
m_tachometer += diff; | |
- m_tachometer_abs += abs(diff); | |
+ m_tachometer_abs += fabsf(diff); | |
phase_last = m_motor_state.phase; | |
} | |
+ // Track position control angle | |
+ // TODO: Have another look at this. | |
+ float angle_now = 0.0; | |
+ if (encoder_is_configured()) { | |
+ angle_now = enc_ang; | |
+ } else { | |
+ angle_now = m_motor_state.phase * (180.0 / M_PI); | |
+ } | |
+ | |
+ if (m_conf->p_pid_ang_div > 0.98 && m_conf->p_pid_ang_div < 1.02) { | |
+ m_pos_pid_now = angle_now; | |
+ } else { | |
+ static float angle_last = 0.0; | |
+ float diff_f = utils_angle_difference(angle_now, angle_last); | |
+ angle_last = angle_now; | |
+ m_pos_pid_now += diff_f / m_conf->p_pid_ang_div; | |
+ utils_norm_angle((float*)&m_pos_pid_now); | |
+ } | |
+ | |
+ // Run position control | |
+ if (m_state == MC_STATE_RUNNING) { | |
+ run_pid_control_pos(m_pos_pid_now, m_pos_pid_set, dt); | |
+ } | |
+ | |
// MCIF handler | |
mc_interface_mc_timer_isr(); | |
@@ -1490,8 +1718,12 @@ | |
return; | |
} | |
+ float openloop_rpm = utils_map(fabsf(m_motor_state.iq_target), | |
+ 0.0, m_conf->lo_current_max, | |
+ 0.0, m_conf->foc_openloop_rpm); | |
+ | |
const float dt = 0.001; | |
- const float min_rads = (m_conf->foc_openloop_rpm * 2.0 * M_PI) / 60.0; | |
+ const float min_rads = (openloop_rpm * 2.0 * M_PI) / 60.0; | |
static float min_rpm_hyst_timer = 0.0; | |
static float min_rpm_timer = 0.0; | |
@@ -1514,7 +1746,7 @@ | |
} | |
// Don't use this in brake mode. | |
- if (m_control_mode == CONTROL_MODE_CURRENT_BRAKE) { | |
+ if (m_control_mode == CONTROL_MODE_CURRENT_BRAKE || fabsf(m_motor_state.duty_now) < 0.001) { | |
min_rpm_hyst_timer = 0.0; | |
m_phase_observer_override = false; | |
} | |
@@ -1671,19 +1903,13 @@ | |
// TODO: Have a look at this? | |
state_m->i_bus = state_m->mod_d * state_m->id + state_m->mod_q * state_m->iq; | |
+ UTILS_LP_FAST(state_m->i_bus_filter, state_m->i_bus, MCPWM_FOC_I_FILTER_CONST); | |
state_m->i_abs = sqrtf(state_m->id * state_m->id + state_m->iq * state_m->iq); | |
state_m->i_abs_filter = sqrtf(state_m->id_filter * state_m->id_filter + state_m->iq_filter * state_m->iq_filter); | |
float mod_alpha = c * state_m->mod_d - s * state_m->mod_q; | |
float mod_beta = c * state_m->mod_q + s * state_m->mod_d; | |
- state_m->v_alpha = mod_alpha * (2.0 / 3.0) * state_m->v_bus; | |
- state_m->v_beta = mod_beta * (2.0 / 3.0) * state_m->v_bus; | |
- | |
- // Set output (HW Dependent) | |
- uint32_t duty1, duty2, duty3, top; | |
- top = TIM1->ARR; | |
- | |
// Deadtime compensation | |
const float i_alpha_set = c * state_m->id_target - s * state_m->iq_target; | |
const float i_beta_set = c * state_m->iq_target + s * state_m->id_target; | |
@@ -1692,10 +1918,20 @@ | |
const float ic_set = -0.5 * i_alpha_set - SQRT3_BY_2 * i_beta_set; | |
const float mod_alpha_set_sgn = (2.0 / 3.0) * SIGN(ia_set) - (1.0 / 3.0) * SIGN(ib_set) - (1.0 / 3.0) * SIGN(ic_set); | |
const float mod_beta_set_sgn = ONE_BY_SQRT3 * SIGN(ib_set) - ONE_BY_SQRT3 * SIGN(ic_set); | |
+ const float mod_comp_fact = m_conf->foc_dt_us * 1e-6 * m_conf->foc_f_sw; | |
+ const float mod_alpha_comp = mod_alpha_set_sgn * mod_comp_fact; | |
+ const float mod_beta_comp = mod_beta_set_sgn * mod_comp_fact; | |
+ | |
+// mod_alpha += mod_alpha_comp; | |
+// mod_beta += mod_beta_comp; | |
+ | |
+ // Apply compensation here so that 0 duty cyle has no glitches. | |
+ state_m->v_alpha = (mod_alpha - mod_alpha_comp) * (2.0 / 3.0) * state_m->v_bus; | |
+ state_m->v_beta = (mod_beta - mod_beta_comp) * (2.0 / 3.0) * state_m->v_bus; | |
- mod_alpha += mod_alpha_set_sgn * m_conf->foc_dt_us * 1e-6 * m_conf->foc_f_sw; | |
- mod_beta += mod_beta_set_sgn * m_conf->foc_dt_us * 1e-6 * m_conf->foc_f_sw; | |
- | |
+ // Set output (HW Dependent) | |
+ uint32_t duty1, duty2, duty3, top; | |
+ top = TIM1->ARR; | |
svm(-mod_alpha, -mod_beta, top, &duty1, &duty2, &duty3); | |
TIMER_UPDATE_DUTY(duty1, duty2, duty3); | |
@@ -1834,7 +2070,7 @@ | |
*tCout = tC; | |
} | |
-static void run_pid_control_pos(float dt) { | |
+static void run_pid_control_pos(float angle_now, float angle_set, float dt) { | |
static float i_term = 0; | |
static float prev_error = 0; | |
float p_term; | |
@@ -1847,19 +2083,30 @@ | |
return; | |
} | |
- // Compute error | |
- float angle = encoder_read_deg(); | |
- float error = utils_angle_difference(m_pos_pid_set_pos, angle); | |
+ // Compute parameters | |
+ float error = utils_angle_difference(angle_set, angle_now); | |
- if (m_conf->foc_encoder_inverted) { | |
- error = -error; | |
+ if (encoder_is_configured()) { | |
+ if (m_conf->foc_encoder_inverted) { | |
+ error = -error; | |
+ } | |
} | |
- | |
- // Compute parameters | |
p_term = error * m_conf->p_pid_kp; | |
i_term += error * (m_conf->p_pid_ki * dt); | |
- d_term = (error - prev_error) * (m_conf->p_pid_kd / dt); | |
+ | |
+ // Average DT for the D term when the error does not change. This likely | |
+ // happens at low speed when the position resolution is low and several | |
+ // control iterations run without position updates. | |
+ // TODO: Are there problems with this approach? | |
+ static float dt_int = 0.0; | |
+ dt_int += dt; | |
+ if (error == prev_error) { | |
+ d_term = 0.0; | |
+ } else { | |
+ d_term = (error - prev_error) * (m_conf->p_pid_kd / dt_int); | |
+ dt_int = 0.0; | |
+ } | |
// I-term wind-up protection | |
utils_truncate_number(&i_term, -1.0, 1.0); | |
@@ -1871,11 +2118,15 @@ | |
float output = p_term + i_term + d_term; | |
utils_truncate_number(&output, -1.0, 1.0); | |
- if (encoder_index_found()) { | |
- m_iq_set = output * m_conf->lo_current_max; | |
+ if (encoder_is_configured()) { | |
+ if (encoder_index_found()) { | |
+ m_iq_set = output * m_conf->lo_current_max; | |
+ } else { | |
+ // Rotate the motor with 40 % power until the encoder index is found. | |
+ m_iq_set = 0.4 * m_conf->lo_current_max; | |
+ } | |
} else { | |
- // Rotate the motor with 40 % power until the encoder index is found. | |
- m_iq_set = 0.4 * m_conf->lo_current_max; | |
+ m_iq_set = output * m_conf->lo_current_max; | |
} | |
} | |
@@ -1892,15 +2143,11 @@ | |
return; | |
} | |
- // Too low RPM set. Stop and return. | |
+ // Too low RPM set. Reset state and return. | |
if (fabsf(m_speed_pid_set_rpm) < m_conf->s_pid_min_erpm) { | |
i_term = 0.0; | |
prev_error = 0; | |
m_iq_set = 0.0; | |
- m_state = MC_STATE_OFF; | |
- if (m_output_on) { | |
- stop_pwm_hw(); | |
- } | |
return; | |
} | |
@@ -1923,8 +2170,17 @@ | |
// Calculate output | |
float output = p_term + i_term + d_term; | |
- utils_truncate_number(&output, -1.0, 1.0); | |
+ if ((m_speed_pid_cruise_control_type == CRUISE_CONTROL_MOTOR_SETTINGS && m_conf->s_pid_breaking_enabled) || m_speed_pid_cruise_control_type == CRUISE_CONTROL_BRAKING_ENABLED) { | |
+ utils_truncate_number(&output, -1.0, 1.0); | |
+ } else { | |
+ if(m_speed_pid_set_rpm < 0.0){ | |
+ utils_truncate_number(&output, -1.0, 0.0); | |
+ }else{ | |
+ utils_truncate_number(&output, 0.0, 1.0); | |
+ } | |
+ } | |
+ | |
m_iq_set = output * m_conf->lo_current_max; | |
} | |
@@ -1963,3 +2219,113 @@ | |
m_output_on = true; | |
} | |
+ | |
+static int read_hall(void) { | |
+ return READ_HALL1() | (READ_HALL2() << 1) | (READ_HALL3() << 2); | |
+} | |
+ | |
+static float correct_encoder(float obs_angle, float enc_angle, float speed) { | |
+ float rpm_abs = fabsf(speed / ((2.0 * M_PI) / 60.0)); | |
+ static bool using_encoder = true; | |
+ | |
+ // Hysteresis 5 % of total speed | |
+ float hyst = m_conf->foc_sl_erpm * 0.05; | |
+ if (using_encoder) { | |
+ if (rpm_abs > (m_conf->foc_sl_erpm + hyst)) { | |
+ using_encoder = false; | |
+ } | |
+ } else { | |
+ if (rpm_abs < (m_conf->foc_sl_erpm - hyst)) { | |
+ using_encoder = true; | |
+ } | |
+ } | |
+ | |
+ return using_encoder ? enc_angle : obs_angle; | |
+} | |
+ | |
+static float correct_hall(float angle, float speed, float dt) { | |
+ static int ang_hall_int_prev = -1; | |
+ float rpm_abs = fabsf(speed / ((2.0 * M_PI) / 60.0)); | |
+ static bool using_hall = true; | |
+ | |
+ // Hysteresis 10 % of total speed | |
+ float hyst = m_conf->foc_sl_erpm * 0.10; | |
+ if (using_hall) { | |
+ if (rpm_abs > (m_conf->foc_sl_erpm + hyst)) { | |
+ using_hall = false; | |
+ } | |
+ } else { | |
+ if (rpm_abs < (m_conf->foc_sl_erpm - hyst)) { | |
+ using_hall = true; | |
+ } | |
+ } | |
+ | |
+ if (using_hall) { | |
+ int ang_hall_int = m_conf->foc_hall_table[read_hall()]; | |
+ | |
+ // Only override the observer if the hall sensor value is valid. | |
+ if (ang_hall_int < 201) { | |
+ static float ang_hall = 0.0; | |
+ float ang_hall_now = (((float)ang_hall_int / 200.0) * 360.0) * M_PI / 180.0; | |
+ | |
+ if (ang_hall_int_prev < 0) { | |
+ // Previous angle not valid | |
+ ang_hall_int_prev = ang_hall_int; | |
+ | |
+ if (ang_hall_int_prev == -2) { | |
+ // Before was sensorless, initialize with the provided angle | |
+ ang_hall = angle; | |
+ } else { | |
+ // A boot or error has occurred. Use center of hall sensor angle. | |
+ ang_hall = ((ang_hall_int / 200.0) * 360.0) * M_PI / 180.0; | |
+ } | |
+ } else if (ang_hall_int != ang_hall_int_prev) { | |
+ // A transition was just made. The angle is in the middle of the new and old angle. | |
+ int ang_avg = abs(ang_hall_int - ang_hall_int_prev); | |
+ if (ang_avg < 100) { | |
+ ang_avg = (ang_hall_int + ang_hall_int_prev) / 2; | |
+ } else if (ang_avg != 100) { | |
+ ang_avg = (ang_hall_int + ang_hall_int_prev) / 2 + 100; | |
+ } | |
+ ang_avg %= 200; | |
+ ang_hall = (((float)ang_avg / 200.0) * 360.0) * M_PI / 180.0; | |
+ } | |
+ | |
+ ang_hall_int_prev = ang_hall_int; | |
+ | |
+ if (rpm_abs < 100) { | |
+ // Don't interpolate on very low speed, just use the closest hall sensor | |
+ ang_hall = ang_hall_now; | |
+ } else { | |
+ // Interpolate | |
+ float diff = utils_angle_difference_rad(ang_hall, ang_hall_now); | |
+ if (fabsf(diff) < ((2.0 * M_PI) / 12.0)) { | |
+ // Do interpolation | |
+ ang_hall += speed * dt; | |
+ } else { | |
+ // We are too far away with the interpolation | |
+ ang_hall -= diff / 100.0; | |
+ } | |
+ } | |
+ | |
+ utils_norm_angle_rad(&ang_hall); | |
+ | |
+ angle = ang_hall; | |
+ } else { | |
+ // Invalid hall reading. Don't update angle. | |
+ ang_hall_int_prev = -1; | |
+ | |
+ // Also allow open loop in order to behave like normal sensorless | |
+ // operation. Then the motor works even if the hall sensor cable | |
+ // gets disconnected (when the sensor spacing is 120 degrees). | |
+ if (m_phase_observer_override && m_state == MC_STATE_RUNNING) { | |
+ angle = m_phase_now_observer_override; | |
+ } | |
+ } | |
+ } else { | |
+ // We are running sensorless. | |
+ ang_hall_int_prev = -2; | |
+ } | |
+ | |
+ return angle; | |
+} | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/mcpwm_foc.h Raptor2 Sources/bldc-firmware_2_80/mcpwm_foc.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/mcpwm_foc.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcpwm_foc.h 2017-04-13 18:06:44.000000000 +0100 | |
@@ -39,11 +39,14 @@ | |
void mcpwm_foc_set_duty(float dutyCycle); | |
void mcpwm_foc_set_duty_noramp(float dutyCycle); | |
void mcpwm_foc_set_pid_speed(float rpm); | |
+void mcpwm_foc_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status); | |
void mcpwm_foc_set_pid_pos(float pos); | |
void mcpwm_foc_set_current(float current); | |
void mcpwm_foc_set_brake_current(float current); | |
float mcpwm_foc_get_duty_cycle_set(void); | |
float mcpwm_foc_get_duty_cycle_now(void); | |
+float mcpwm_foc_get_pid_pos_set(void); | |
+float mcpwm_foc_get_pid_pos_now(void); | |
float mcpwm_foc_get_switching_frequency_now(void); | |
float mcpwm_foc_get_rpm(void); | |
float mcpwm_foc_get_tot_current(void); | |
@@ -65,6 +68,7 @@ | |
float mcpwm_foc_measure_resistance(float current, int samples); | |
float mcpwm_foc_measure_inductance(float duty, int samples, float *curr); | |
bool mcpwm_foc_measure_res_ind(float *res, float *ind); | |
+bool mcpwm_foc_hall_detect(float current, uint8_t *hall_table); | |
void mcpwm_foc_print_state(void); | |
float mcpwm_foc_get_last_inj_adc_isr_duration(void); | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/mcuconf.h Raptor2 Sources/bldc-firmware_2_80/mcuconf.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/mcuconf.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcuconf.h 2016-09-19 10:05:44.000000000 +0100 | |
@@ -248,7 +248,7 @@ | |
/* | |
* SPI driver system settings. | |
*/ | |
-#define STM32_SPI_USE_SPI1 FALSE | |
+#define STM32_SPI_USE_SPI1 TRUE | |
#define STM32_SPI_USE_SPI2 FALSE | |
#define STM32_SPI_USE_SPI3 FALSE | |
#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/nrf/nrf_driver.c Raptor2 Sources/bldc-firmware_2_80/nrf/nrf_driver.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/nrf/nrf_driver.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/nrf/nrf_driver.c 2016-08-04 23:47:30.000000000 +0100 | |
@@ -34,44 +34,64 @@ | |
#include "packet.h" | |
// Settings | |
-#define MAX_PL_LEN 25 | |
-#define RX_BUFFER_SIZE PACKET_MAX_PL_LEN | |
+#define MAX_PL_LEN 25 | |
+#define RX_BUFFER_SIZE PACKET_MAX_PL_LEN | |
+ | |
+#define ALIVE_INTERVAL 50 // Send alive packets at this rate | |
+#define NRF_RESTART_TIMEOUT 500 // Restart the NRF if nothing has been received or acked for this time | |
// Variables | |
static THD_WORKING_AREA(rx_thread_wa, 2048); | |
static THD_WORKING_AREA(tx_thread_wa, 512); | |
static mote_state mstate; | |
static uint8_t rx_buffer[RX_BUFFER_SIZE]; | |
+static int nosend_cnt; | |
+static int nrf_restart_rx_time; | |
+static int nrf_restart_tx_time; | |
// Functions | |
static THD_FUNCTION(rx_thread, arg); | |
static THD_FUNCTION(tx_thread, arg); | |
+static int rf_tx_wrapper(char *data, int len); | |
void nrf_driver_init(void) { | |
- rf_init(); | |
rfhelp_init(); | |
- // Set RF address | |
- const char addr[5] = {0xC4, 0xC5, 0xC6, 0xC7, app_get_configuration()->controller_id}; | |
- rfhelp_set_rx_addr(0, addr, 5); | |
- rfhelp_set_tx_addr(addr, 5); | |
+ nosend_cnt = 0; | |
+ nrf_restart_rx_time = 0; | |
+ nrf_restart_tx_time = 0; | |
chThdCreateStatic(rx_thread_wa, sizeof(rx_thread_wa), NORMALPRIO - 1, rx_thread, NULL); | |
chThdCreateStatic(tx_thread_wa, sizeof(tx_thread_wa), NORMALPRIO - 1, tx_thread, NULL); | |
} | |
+static int rf_tx_wrapper(char *data, int len) { | |
+ int res = rfhelp_send_data_crc(data, len); | |
+ | |
+ if (res == 0) { | |
+ nrf_restart_tx_time = NRF_RESTART_TIMEOUT; | |
+ } | |
+ | |
+ return res; | |
+} | |
+ | |
static THD_FUNCTION(tx_thread, arg) { | |
(void)arg; | |
chRegSetThreadName("Nrf TX"); | |
for(;;) { | |
- uint8_t pl[6]; | |
- int32_t index = 0; | |
- pl[index++] = MOTE_PACKET_ALIVE; | |
- rfhelp_send_data_crc((char*)pl, index); | |
+ nosend_cnt++; | |
+ | |
+ if (nosend_cnt >= ALIVE_INTERVAL) { | |
+ uint8_t pl[2]; | |
+ int32_t index = 0; | |
+ pl[index++] = MOTE_PACKET_ALIVE; | |
+ rf_tx_wrapper((char*)pl, index); | |
+ nosend_cnt = 0; | |
+ } | |
- chThdSleepMilliseconds(50); | |
+ chThdSleepMilliseconds(1); | |
} | |
} | |
@@ -81,8 +101,6 @@ | |
chRegSetThreadName("Nrf RX"); | |
- int reset_cnt = 0; | |
- | |
for(;;) { | |
uint8_t buf[32]; | |
int len; | |
@@ -90,6 +108,7 @@ | |
for(;;) { | |
int res = rfhelp_read_rx_data_crc((char*)buf, &len, &pipe); | |
+ | |
chuck_data cdata; | |
int32_t ind = 0; | |
int buttons; | |
@@ -98,6 +117,8 @@ | |
if (res >= 0) { | |
MOTE_PACKET packet = buf[0]; | |
+ nrf_restart_rx_time = NRF_RESTART_TIMEOUT; | |
+ | |
switch (packet) { | |
case MOTE_PACKET_BATT_LEVEL: | |
// TODO! | |
@@ -146,10 +167,15 @@ | |
uint8_t crc_high = buf[ind++]; | |
uint8_t crc_low = buf[ind++]; | |
+ memcpy(rx_buffer + rxbuf_len - (len - ind), buf + ind, len - ind); | |
+ | |
if (crc16(rx_buffer, rxbuf_len) | |
== ((unsigned short) crc_high << 8 | |
| (unsigned short) crc_low)) { | |
+ // Wait a bit in case retries are still made | |
+ chThdSleepMilliseconds(2); | |
+ | |
commands_set_send_func(nrf_driver_send_buffer); | |
commands_process_packet(rx_buffer, rxbuf_len); | |
} | |
@@ -157,6 +183,9 @@ | |
break; | |
case MOTE_PACKET_PROCESS_SHORT_BUFFER: | |
+ // Wait a bit in case retries are still made | |
+ chThdSleepMilliseconds(2); | |
+ | |
commands_set_send_func(nrf_driver_send_buffer); | |
commands_process_packet(buf + 1, len - 1); | |
break; | |
@@ -177,11 +206,15 @@ | |
chThdSleepMilliseconds(5); | |
- // Restart the nrf every 500ms just in case | |
- reset_cnt++; | |
- if (reset_cnt > 100) { | |
- reset_cnt = 0; | |
+ // Restart the nrf if nothing has been received for a while | |
+ if (nrf_restart_rx_time > 0 && nrf_restart_tx_time > 0) { | |
+ nrf_restart_rx_time -= 5; | |
+ nrf_restart_tx_time -= 5; | |
+ } else { | |
+ rfhelp_power_up(); | |
rfhelp_restart(); | |
+ nrf_restart_rx_time = NRF_RESTART_TIMEOUT; | |
+ nrf_restart_tx_time = NRF_RESTART_TIMEOUT; | |
} | |
} | |
} | |
@@ -194,44 +227,49 @@ | |
send_buffer[ind++] = MOTE_PACKET_PROCESS_SHORT_BUFFER; | |
memcpy(send_buffer + ind, data, len); | |
ind += len; | |
- rfhelp_send_data_crc((char*)send_buffer, ind); | |
+ rf_tx_wrapper((char*)send_buffer, ind); | |
+ nosend_cnt = 0; | |
} else { | |
unsigned int end_a = 0; | |
- for (unsigned int i = 0;i < len;i += (MAX_PL_LEN - 2)) { | |
- end_a = i; | |
+ unsigned int len2 = len - (MAX_PL_LEN - 5); | |
+ for (unsigned int i = 0;i < len2;i += (MAX_PL_LEN - 2)) { | |
if (i > 255) { | |
break; | |
} | |
+ end_a = i + (MAX_PL_LEN - 2); | |
+ | |
uint8_t send_len = (MAX_PL_LEN - 2); | |
send_buffer[0] = MOTE_PACKET_FILL_RX_BUFFER; | |
send_buffer[1] = i; | |
- if ((i + (MAX_PL_LEN - 2)) <= len) { | |
+ if ((i + (MAX_PL_LEN - 2)) <= len2) { | |
memcpy(send_buffer + 2, data + i, send_len); | |
} else { | |
- send_len = len - i; | |
+ send_len = len2 - i; | |
memcpy(send_buffer + 2, data + i, send_len); | |
} | |
- rfhelp_send_data_crc((char*)send_buffer, send_len + 2); | |
+ rf_tx_wrapper((char*)send_buffer, send_len + 2); | |
+ nosend_cnt = 0; | |
} | |
- for (unsigned int i = end_a;i < len;i += (MAX_PL_LEN - 3)) { | |
+ for (unsigned int i = end_a;i < len2;i += (MAX_PL_LEN - 3)) { | |
uint8_t send_len = (MAX_PL_LEN - 3); | |
send_buffer[0] = MOTE_PACKET_FILL_RX_BUFFER_LONG; | |
send_buffer[1] = i >> 8; | |
send_buffer[2] = i & 0xFF; | |
- if ((i + (MAX_PL_LEN - 3)) <= len) { | |
+ if ((i + (MAX_PL_LEN - 3)) <= len2) { | |
memcpy(send_buffer + 3, data + i, send_len); | |
} else { | |
- send_len = len - i; | |
+ send_len = len2 - i; | |
memcpy(send_buffer + 3, data + i, send_len); | |
} | |
- rfhelp_send_data_crc((char*)send_buffer, send_len + 3); | |
+ rf_tx_wrapper((char*)send_buffer, send_len + 3); | |
+ nosend_cnt = 0; | |
} | |
uint32_t ind = 0; | |
@@ -241,7 +279,10 @@ | |
unsigned short crc = crc16(data, len); | |
send_buffer[ind++] = (uint8_t)(crc >> 8); | |
send_buffer[ind++] = (uint8_t)(crc & 0xFF); | |
+ memcpy(send_buffer + 5, data + len2, len - len2); | |
+ ind += len - len2; | |
- rfhelp_send_data_crc((char*)send_buffer, ind); | |
+ rf_tx_wrapper((char*)send_buffer, ind); | |
+ nosend_cnt = 0; | |
} | |
} | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/nrf/rf.c Raptor2 Sources/bldc-firmware_2_80/nrf/rf.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/nrf/rf.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/nrf/rf.c 2016-08-04 23:47:30.000000000 +0100 | |
@@ -22,32 +22,6 @@ | |
void rf_init(void) { | |
spi_sw_init(); | |
- | |
- rf_power_down(); | |
- | |
- // Set default register values (TODO for the rest) | |
- rf_write_reg_byte(NRF_REG_EN_RXADDR, 0); | |
- rf_write_reg_byte(NRF_REG_DYNPD, 0); | |
- | |
- rf_set_crc_type(NRF_CRC_1B); | |
- rf_set_retr_retries(2); | |
- rf_set_retr_delay(NRF_RETR_DELAY_500US); | |
- rf_set_power(NRF_POWER_0DBM); | |
- rf_set_speed(NRF_SPEED_250K); | |
- rf_set_address_width(NRF_AW_5); | |
- rf_set_frequency(2400 + 0x20); | |
- rf_enable_features(NRF_FEATURE_DPL | NRF_FEATURE_DYN_ACK); | |
- | |
- rf_enable_pipe_autoack(NRF_MASK_PIPE0); | |
- rf_enable_pipe_address(NRF_MASK_PIPE0); | |
- rf_enable_pipe_dlp(NRF_MASK_PIPE0); | |
- | |
- // Note: The address should be set by the application. | |
- | |
- rf_power_up(); | |
- rf_mode_rx(); | |
- rf_flush_all(); | |
- rf_clear_irq(); | |
} | |
void rf_set_speed(NRF_SPEED speed) { | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/nrf/rf.h Raptor2 Sources/bldc-firmware_2_80/nrf/rf.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/nrf/rf.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/nrf/rf.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -20,51 +20,7 @@ | |
#define RF_H_ | |
#include <stdint.h> | |
- | |
-// Data types | |
-typedef enum { | |
- NRF_SPEED_250K = 0, | |
- NRF_SPEED_1M, | |
- NRF_SPEED_2M | |
-} NRF_SPEED; | |
- | |
-typedef enum { | |
- NRF_POWER_M18DBM = 0, | |
- NRF_POWER_M12DBM, | |
- NRF_POWER_M6DBM, | |
- NRF_POWER_0DBM | |
-} NRF_POWER; | |
- | |
-typedef enum { | |
- NRF_AW_3 = 0, | |
- NRF_AW_4, | |
- NRF_AW_5 | |
-} NRF_AW; | |
- | |
-typedef enum { | |
- NRF_CRC_DISABLED = 0, | |
- NRF_CRC_1B, | |
- NRF_CRC_2B | |
-} NRF_CRC; | |
- | |
-typedef enum { | |
- NRF_RETR_DELAY_250US = 0, | |
- NRF_RETR_DELAY_500US, | |
- NRF_RETR_DELAY_750US, | |
- NRF_RETR_DELAY_1000US, | |
- NRF_RETR_DELAY_1250US, | |
- NRF_RETR_DELAY_1500US, | |
- NRF_RETR_DELAY_1750US, | |
- NRF_RETR_DELAY_2000US, | |
- NRF_RETR_DELAY_2250US, | |
- NRF_RETR_DELAY_2500US, | |
- NRF_RETR_DELAY_2750US, | |
- NRF_RETR_DELAY_3000US, | |
- NRF_RETR_DELAY_3250US, | |
- NRF_RETR_DELAY_3500US, | |
- NRF_RETR_DELAY_3750US, | |
- NRF_RETR_DELAY_4000US | |
-} NRF_RETR_DELAY; | |
+#include <datatypes.h> | |
// Status register masks | |
#define NRF_STATUS_TX_FULL (1<<0) | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/nrf/rfhelp.c Raptor2 Sources/bldc-firmware_2_80/nrf/rfhelp.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/nrf/rfhelp.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/nrf/rfhelp.c 2016-08-04 23:47:30.000000000 +0100 | |
@@ -21,7 +21,6 @@ | |
#include "hal.h" | |
#include "crc.h" | |
#include <string.h> | |
-#include <stdbool.h> | |
// Variables | |
static mutex_t rf_mutex; | |
@@ -30,25 +29,41 @@ | |
static bool rx_addr_set[6]; | |
static int address_length; | |
static bool tx_pipe0_addr_eq; | |
+static nrf_config nrf_conf; | |
+static bool init_done = false; | |
void rfhelp_init(void) { | |
chMtxObjectInit(&rf_mutex); | |
+ rf_init(); | |
// address_length = rf_get_address_width(); | |
- address_length = 5; // We assume length 5 | |
+ address_length = 3; // We assume length 3 | |
// This should not happen | |
if (address_length > 5 || address_length < 3) { | |
- address_length = 5; | |
+ address_length = 3; | |
} | |
for (int i = 0;i < 6;i++) { | |
rf_read_reg(NRF_REG_RX_ADDR_P0, rx_addr[i], address_length); | |
rx_addr_set[i] = false; | |
} | |
- rf_read_reg(NRF_REG_TX_ADDR, tx_addr, address_length); | |
+ rf_read_reg(NRF_REG_TX_ADDR, tx_addr, address_length); | |
tx_pipe0_addr_eq = memcmp(rx_addr[0], tx_addr, address_length) == 0; | |
+ | |
+ // TODO: fill nrf_conf with values from the nrf chip. For now we assume | |
+ // that nrf_conf is already set when rfhelp_restart is called. | |
+ | |
+ init_done = true; | |
+} | |
+ | |
+void rfhelp_update_conf(nrf_config *conf) { | |
+ nrf_conf = *conf; | |
+ | |
+ if (init_done) { | |
+ rfhelp_restart(); | |
+ } | |
} | |
/** | |
@@ -57,13 +72,38 @@ | |
void rfhelp_restart(void) { | |
chMtxLock(&rf_mutex); | |
- rf_init(); | |
+ rf_power_down(); | |
+ | |
+ // Set default register values. | |
+ // TODO: make this file consistent with multiple | |
+ // rx_addr and tx_addr, and the rest in general. | |
+ rf_write_reg_byte(NRF_REG_EN_RXADDR, 0); | |
+ rf_write_reg_byte(NRF_REG_DYNPD, 0); | |
+ | |
+ rf_set_crc_type(nrf_conf.crc_type); | |
+ rf_set_retr_retries(nrf_conf.retries); | |
+ rf_set_retr_delay(nrf_conf.retry_delay); | |
+ rf_set_power(nrf_conf.power); | |
+ rf_set_speed(nrf_conf.speed); | |
+ rf_set_address_width(NRF_AW_3); // Always use 3 byte address | |
+ rf_set_frequency(2400 + (unsigned int)nrf_conf.channel); | |
+ rf_enable_features(NRF_FEATURE_DPL | NRF_FEATURE_DYN_ACK); | |
+ | |
+ rf_enable_pipe_autoack(NRF_MASK_PIPE0); | |
+ rf_enable_pipe_address(NRF_MASK_PIPE0); | |
+ rf_enable_pipe_dlp(NRF_MASK_PIPE0); | |
+ | |
+ memcpy(tx_addr, nrf_conf.address, 3); | |
+ memcpy(rx_addr[0], nrf_conf.address, 3); | |
+ tx_pipe0_addr_eq = true; | |
+ | |
rf_set_tx_addr(tx_addr, address_length); | |
- for (int i = 0;i < 6;i++) { | |
- if (rx_addr_set[i]) { | |
- rf_set_rx_addr(i, rx_addr[i], address_length); | |
- } | |
- } | |
+ rf_set_rx_addr(0, rx_addr[0], address_length); | |
+ | |
+ rf_power_up(); | |
+ rf_mode_rx(); | |
+ rf_flush_all(); | |
+ rf_clear_irq(); | |
chMtxUnlock(&rf_mutex); | |
} | |
@@ -82,7 +122,7 @@ | |
* -1: Max RT. | |
* -2: Timeout | |
*/ | |
-int rfhelp_send_data(char *data, int len) { | |
+int rfhelp_send_data(char *data, int len, bool ack) { | |
int timeout = 60; | |
int retval = -1; | |
@@ -92,13 +132,17 @@ | |
rf_clear_irq(); | |
rf_flush_all(); | |
- rf_write_tx_payload(data, len); | |
- | |
// Pipe0-address and tx-address must be equal for ack to work. | |
- if (!tx_pipe0_addr_eq) { | |
+ if (!tx_pipe0_addr_eq && ack) { | |
rf_set_rx_addr(0, tx_addr, address_length); | |
} | |
+ if (ack) { | |
+ rf_write_tx_payload(data, len); | |
+ } else { | |
+ rf_write_tx_payload_no_ack(data, len); | |
+ } | |
+ | |
for(;;) { | |
int s = rf_status(); | |
@@ -119,7 +163,7 @@ | |
} | |
// Restore pipe0 address | |
- if (!tx_pipe0_addr_eq) { | |
+ if (!tx_pipe0_addr_eq && ack) { | |
rf_set_rx_addr(0, rx_addr[0], address_length); | |
} | |
@@ -154,7 +198,7 @@ | |
buffer[len] = (char)(crc >> 8); | |
buffer[len + 1] = (char)(crc & 0xFF); | |
- return rfhelp_send_data(buffer, len + 2); | |
+ return rfhelp_send_data(buffer, len + 2, nrf_conf.send_crc_ack); | |
} | |
/** | |
@@ -191,7 +235,7 @@ | |
if (*len <= 32 && *len >= 0) { | |
rf_read_rx_payload(data, *len); | |
rf_clear_rx_irq(); | |
- rf_flush_rx(); | |
+// rf_flush_rx(); | |
s = rf_status(); | |
if (NRF_STATUS_GET_RX_P_NO(s) == 7) { | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/nrf/rfhelp.h Raptor2 Sources/bldc-firmware_2_80/nrf/rfhelp.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/nrf/rfhelp.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/nrf/rfhelp.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -18,10 +18,14 @@ | |
#ifndef RFHELP_H_ | |
#define RFHELP_H_ | |
+#include <stdbool.h> | |
+#include "datatypes.h" | |
+ | |
// Functions | |
void rfhelp_init(void); | |
+void rfhelp_update_conf(nrf_config *conf); | |
void rfhelp_restart(void); | |
-int rfhelp_send_data(char *data, int len); | |
+int rfhelp_send_data(char *data, int len, bool ack); | |
int rfhelp_send_data_crc(char *data, int len); | |
int rfhelp_read_rx_data(char *data, int *len, int *pipe); | |
int rfhelp_read_rx_data_crc(char *data, int *len, int *pipe); | |
Only in Raptor2 Sources/bldc-firmware_2_80: oh5la4w3.ag1 | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/packet.h Raptor2 Sources/bldc-firmware_2_80/packet.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/packet.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/packet.h 2017-04-13 18:06:50.000000000 +0100 | |
@@ -28,7 +28,7 @@ | |
#include <stdint.h> | |
// Settings | |
-#define PACKET_RX_TIMEOUT 2 | |
+#define PACKET_RX_TIMEOUT 10 | |
#define PACKET_HANDLERS 2 | |
#define PACKET_MAX_PL_LEN 1024 | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/servo_dec.c Raptor2 Sources/bldc-firmware_2_80/servo_dec.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/servo_dec.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/servo_dec.c 2016-10-24 21:35:06.000000000 +0100 | |
@@ -39,6 +39,7 @@ | |
static volatile systime_t last_update_time; | |
static volatile float servo_pos[SERVO_NUM]; | |
static volatile float pulse_start = 1.0; | |
+static volatile float pulse_center = 1.5; | |
static volatile float pulse_end = 2.0; | |
static volatile float last_len_received[SERVO_NUM]; | |
static volatile bool use_median_filter = false; | |
@@ -68,8 +69,16 @@ | |
} | |
if (len >= 0.0) { | |
+ float len_to_center = len + pulse_start - pulse_center; | |
+ | |
if (use_median_filter) { | |
- float c = (len * 2.0 - len_set) / len_set; | |
+ float c; | |
+ if (len_to_center >= 0.0) { | |
+ c = (1.0 / (pulse_end - pulse_center)) * len_to_center; | |
+ } else { | |
+ c = (1.0 / (pulse_center - pulse_start)) * len_to_center; | |
+ } | |
+ //float c = (len * 2.0 - len_set) / len_set; | |
static float c1 = 0.5; | |
static float c2 = 0.5; | |
float med = utils_middle_of_3(c, c1, c2); | |
@@ -79,7 +88,12 @@ | |
servo_pos[0] = med; | |
} else { | |
- servo_pos[0] = (len * 2.0 - len_set) / len_set; | |
+ if (len_to_center >= 0.0) { | |
+ servo_pos[0] = (1 / (pulse_end - pulse_center)) * len_to_center; | |
+ } else { | |
+ servo_pos[0] = (1 / (pulse_center - pulse_start)) * len_to_center; | |
+ } | |
+ //servo_pos[0] = (len * 2.0 - len_set) / len_set; | |
} | |
last_update_time = chVTGetSystemTime(); | |
@@ -135,8 +149,9 @@ | |
* @param end | |
* he amount of milliseconds the pulse ends at (default is 2.0) | |
*/ | |
-void servodec_set_pulse_options(float start, float end, bool median_filter) { | |
+void servodec_set_pulse_options(float start, float center, float end, bool median_filter) { | |
pulse_start = start; | |
+ pulse_center = center; | |
pulse_end = end; | |
use_median_filter = median_filter; | |
} | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/servo_dec.h Raptor2 Sources/bldc-firmware_2_80/servo_dec.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/servo_dec.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/servo_dec.h 2016-10-24 16:46:32.000000000 +0100 | |
@@ -30,7 +30,7 @@ | |
// Functions | |
void servodec_init(void (*d_func)(void)); | |
-void servodec_set_pulse_options(float start, float end, bool median_filter); | |
+void servodec_set_pulse_options(float start, float center, float end, bool median_filter); | |
float servodec_get_servo(int servo_num); | |
uint32_t servodec_get_time_since_update(void); | |
float servodec_get_last_pulse_len(int servo_num); | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/terminal.c Raptor2 Sources/bldc-firmware_2_80/terminal.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/terminal.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/terminal.c 2017-04-13 18:07:08.000000000 +0100 | |
@@ -29,11 +29,12 @@ | |
#include "mcpwm_foc.h" | |
#include "mc_interface.h" | |
#include "commands.h" | |
-#include "main.h" | |
+#include "app.h" | |
#include "hw.h" | |
#include "comm_can.h" | |
#include "utils.h" | |
#include "timeout.h" | |
+#include "encoder.h" | |
#include <string.h> | |
#include <stdio.h> | |
@@ -73,7 +74,7 @@ | |
} else if (strcmp(argv[0], "last_adc_duration") == 0) { | |
commands_printf("Latest ADC duration: %.4f ms", (double)(mcpwm_get_last_adc_isr_duration() * 1000.0)); | |
commands_printf("Latest injected ADC duration: %.4f ms", (double)(mc_interface_get_last_inj_adc_isr_duration() * 1000.0)); | |
- commands_printf("Latest main ADC duration: %.4f ms\n", (double)(main_get_last_adc_isr_duration() * 1000.0)); | |
+ commands_printf("Latest sample ADC duration: %.4f ms\n", (double)(mc_interface_get_last_sample_adc_isr_duration() * 1000.0)); | |
} else if (strcmp(argv[0], "kv") == 0) { | |
commands_printf("Calculated KV: %.2f rpm/volt\n", (double)mcpwm_get_kv_filtered()); | |
} else if (strcmp(argv[0], "mem") == 0) { | |
@@ -98,6 +99,27 @@ | |
commands_printf(""); | |
} else if (strcmp(argv[0], "fault") == 0) { | |
commands_printf("%s\n", mc_interface_fault_to_string(mc_interface_get_fault())); | |
+ } else if (strcmp(argv[0], "faulta") == 0) { | |
+ if (fault_vec_write == 0) { | |
+ commands_printf("No faults"); | |
+ } else { | |
+ commands_printf("Fault: %s\nID: %i\nCurrent: %.1f\nCurrent filtered: %.1f\nVoltage: %.2f\nDuty: %.2f\nRPM: %.1f\nTacho: %d\nCycles running: %d\nTIM duty: %d\nTIM val samp: %d\nTIM current samp: %d\nTIM top: %d\nComm step: %d\nTemperature: %.2f", | |
+ mc_interface_fault_to_string(fault_vec[fault_vec_write - 1].fault), | |
+ app_get_configuration()->controller_id, | |
+ (double)fault_vec[fault_vec_write - 1].current, | |
+ (double)fault_vec[fault_vec_write - 1].current_filtered, | |
+ (double)fault_vec[fault_vec_write - 1].voltage, | |
+ (double)fault_vec[fault_vec_write - 1].duty, | |
+ (double)fault_vec[fault_vec_write - 1].rpm, | |
+ fault_vec[fault_vec_write - 1].tacho, | |
+ fault_vec[fault_vec_write - 1].cycles_running, | |
+ (int)((float)fault_vec[fault_vec_write - 1].tim_top * fault_vec[fault_vec_write - 1].duty), | |
+ fault_vec[fault_vec_write - 1].tim_val_samp, | |
+ fault_vec[fault_vec_write - 1].tim_current_samp, | |
+ fault_vec[fault_vec_write - 1].tim_top, | |
+ fault_vec[fault_vec_write - 1].comm_step, | |
+ (double)fault_vec[fault_vec_write - 1].temperature); | |
+ } | |
} else if (strcmp(argv[0], "faults") == 0) { | |
if (fault_vec_write == 0) { | |
commands_printf("No faults registered since startup\n"); | |
@@ -211,36 +233,66 @@ | |
commands_printf("ID : %i", msg->id); | |
commands_printf("RX Time : %i", msg->rx_time); | |
commands_printf("Age (milliseconds) : %.2f", (double)(UTILS_AGE_S(msg->rx_time) * 1000.0)); | |
- commands_printf("RPM : %.2f", (double)msg->rpm); | |
+ commands_printf("RPM : %.2f", (double)(msg->rpm)); | |
commands_printf("Current : %.2f", (double)msg->current); | |
- commands_printf("Duty : %.2f\n", (double)msg->duty); | |
+ commands_printf("Duty : %i", msg->duty); | |
+ commands_printf("Cruise Control : %i\n", msg->cruise_control_status); | |
+ } | |
+ } | |
+ } else if (strcmp(argv[0], "can_member") == 0) { | |
+ char controllerIds[100] = "CAN:\n"; | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1.0) { | |
+ char idArray[5]; | |
+ sprintf(idArray, "%i\n", msg->id); | |
+ strcat(controllerIds, idArray); | |
} | |
} | |
- } else if (strcmp(argv[0], "foc_encoder_detect") == 0) { | |
+ commands_printf(controllerIds); | |
+ } else if (strcmp(argv[0], "can_erpms") == 0) { | |
+ char controllerIds[100] = "CAN ERPMs:\n"; | |
+ | |
+ char rpmArrayMaster[15]; | |
+ sprintf(rpmArrayMaster, "M %6.2f\n", (double)mc_interface_get_rpm()); | |
+ strcat(controllerIds, rpmArrayMaster); | |
+ | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1.0) { | |
+ char rpmArray[15]; | |
+ sprintf(rpmArray, "%i %6.2f\n", msg->id, (double)(msg->rpm)); | |
+ strcat(controllerIds, rpmArray); | |
+ } | |
+ } | |
+ commands_printf(controllerIds); | |
+ }else if (strcmp(argv[0], "foc_encoder_detect") == 0) { | |
if (argc == 2) { | |
float current = -1.0; | |
sscanf(argv[1], "%f", ¤t); | |
if (current > 0.0 && current <= mcconf.l_current_max) { | |
-#if ENCODER_ENABLE | |
- mc_motor_type type_old = mcconf.motor_type; | |
- mcconf.motor_type = MOTOR_TYPE_FOC; | |
- mc_interface_set_configuration(&mcconf); | |
- | |
- float offset = 0.0; | |
- float ratio = 0.0; | |
- bool inverted = false; | |
- mcpwm_foc_encoder_detect(current, true, &offset, &ratio, &inverted); | |
- | |
- mcconf.motor_type = type_old; | |
- mc_interface_set_configuration(&mcconf); | |
- | |
- commands_printf("Offset : %.2f", (double)offset); | |
- commands_printf("Ratio : %.2f", (double)ratio); | |
- commands_printf("Inverted : %s\n", inverted ? "true" : "false"); | |
-#else | |
- commands_printf("Encoder not enabled.\n"); | |
-#endif | |
+ if (encoder_is_configured()) { | |
+ mc_motor_type type_old = mcconf.motor_type; | |
+ mcconf.motor_type = MOTOR_TYPE_FOC; | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ float offset = 0.0; | |
+ float ratio = 0.0; | |
+ bool inverted = false; | |
+ mcpwm_foc_encoder_detect(current, true, &offset, &ratio, &inverted); | |
+ | |
+ mcconf.motor_type = type_old; | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ commands_printf("Offset : %.2f", (double)offset); | |
+ commands_printf("Ratio : %.2f", (double)ratio); | |
+ commands_printf("Inverted : %s\n", inverted ? "true" : "false"); | |
+ } else { | |
+ commands_printf("Encoder not enabled.\n"); | |
+ } | |
} else { | |
commands_printf("Invalid argument(s).\n"); | |
} | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/utils.c Raptor2 Sources/bldc-firmware_2_80/utils.c | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/utils.c 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/utils.c 2017-04-13 18:07:16.000000000 +0100 | |
@@ -133,22 +133,28 @@ | |
* The difference between the angles | |
*/ | |
float utils_angle_difference(float angle1, float angle2) { | |
- utils_norm_angle(&angle1); | |
- utils_norm_angle(&angle2); | |
+// utils_norm_angle(&angle1); | |
+// utils_norm_angle(&angle2); | |
+// | |
+// if (fabsf(angle1 - angle2) > 180.0) { | |
+// if (angle1 < angle2) { | |
+// angle1 += 360.0; | |
+// } else { | |
+// angle2 += 360.0; | |
+// } | |
+// } | |
+// | |
+// return angle1 - angle2; | |
- if (fabsf(angle1 - angle2) > 180.0) { | |
- if (angle1 < angle2) { | |
- angle1 += 360.0; | |
- } else { | |
- angle2 += 360.0; | |
- } | |
- } | |
- | |
- return angle1 - angle2; | |
+ // Faster in most cases | |
+ float difference = angle1 - angle2; | |
+ while (difference < -180.0) difference += 2.0 * 180.0; | |
+ while (difference > 180.0) difference -= 2.0 * 180.0; | |
+ return difference; | |
} | |
/** | |
- * Get the difference between two angles. Will always be between -180 and +180 degrees. | |
+ * Get the difference between two angles. Will always be between -pi and +pi radians. | |
* @param angle1 | |
* The first angle in radians | |
* @param angle2 | |
@@ -221,6 +227,73 @@ | |
} | |
/** | |
+ * Get the smallest value of two values | |
+ * | |
+ * @param a | |
+ * First value | |
+ * | |
+ * @param b | |
+ * Second value | |
+ * | |
+ * @return | |
+ * The smallest value | |
+ */ | |
+float utils_smallest_of_2(float a, float b) { | |
+ if (b < a) { | |
+ return b; | |
+ } | |
+ return a; | |
+} | |
+ | |
+/** | |
+ * Get the smallest value of three values | |
+ * | |
+ * @param a | |
+ * First value | |
+ * | |
+ * @param b | |
+ * Second value | |
+ * | |
+ * @param c | |
+ * Third value | |
+ * | |
+ * @return | |
+ * The smallest value | |
+ */ | |
+float utils_smallest_of_3(float a, float b, float c) { | |
+ if (b < a) { | |
+ if (c < b) { | |
+ return c; | |
+ } | |
+ return b; | |
+ } else { | |
+ if (c < a) { | |
+ return c; | |
+ } | |
+ return a; | |
+ } | |
+} | |
+ | |
+/** | |
+ * Get the smallest value of two values | |
+ * | |
+ * @param a | |
+ * First value | |
+ * | |
+ * @param b | |
+ * Second value | |
+ * | |
+ * @return | |
+ * The smallest value | |
+ */ | |
+float utils_highest_of_2(float a, float b) { | |
+ if (b > a) { | |
+ return b; | |
+ } | |
+ return a; | |
+} | |
+ | |
+/** | |
* Get the middle value of three values | |
* | |
* @param a | |
diff -ru bldc-cc171422641a50c56452280575f2074f8a88aa45/utils.h Raptor2 Sources/bldc-firmware_2_80/utils.h | |
--- bldc-cc171422641a50c56452280575f2074f8a88aa45/utils.h 2015-12-29 01:37:09.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/utils.h 2017-04-13 18:07:22.000000000 +0100 | |
@@ -39,6 +39,9 @@ | |
float utils_angle_difference_rad(float angle1, float angle2); | |
float utils_avg_angles_rad_fast(float *angles, float *weights, int angles_num); | |
float utils_middle_of_3(float a, float b, float c); | |
+float utils_smallest_of_2(float a, float b); | |
+float utils_smallest_of_3(float a, float b, float c); | |
+float utils_highest_of_2(float a, float b); | |
int utils_middle_of_3_int(int a, int b, int c); | |
float utils_fast_inv_sqrt(float x); | |
float utils_fast_atan2(float y, float x); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Only in Raptor2 Sources/bldc-firmware_2_80: .dep | |
Only in bldc-90986c31defe50830b4795a388ee5b2687dc2516: .gitignore | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/Makefile Raptor2 Sources/bldc-firmware_2_80/Makefile | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/Makefile 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/Makefile 2016-09-19 10:07:06.000000000 +0100 | |
@@ -270,8 +270,8 @@ | |
# Program | |
upload: build/$(PROJECT).bin | |
#qstlink2 --cli --erase --write build/$(PROJECT).bin | |
- openocd -f interface/stlink-v2.cfg -c "set WORKAREASIZE 0x2000" -f target/stm32f4x_stlink.cfg -c "program build/$(PROJECT).elf verify reset" | |
- #openocd -f board/stm32f4discovery.cfg -c "reset_config trst_only combined" -c "program build/$(PROJECT).elf verify reset exit" # For openocd 0.9 | |
+ #openocd -f interface/stlink-v2.cfg -c "set WORKAREASIZE 0x2000" -f target/stm32f4x_stlink.cfg -c "program build/$(PROJECT).elf verify reset" # Older openocd | |
+ openocd -f board/stm32f4discovery.cfg -c "reset_config trst_only combined" -c "program build/$(PROJECT).elf verify reset exit" # For openocd 0.9 | |
#program with olimex arm-usb-tiny-h and jtag-swd adapter board. needs openocd>=0.9 | |
upload-olimex: build/$(PROJECT).bin | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/README.md Raptor2 Sources/bldc-firmware_2_80/README.md | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/README.md 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/README.md 2018-08-27 20:57:58.000000000 +0100 | |
@@ -1 +1,12 @@ | |
-This is the source code for my custom BLDC controller. A complete description and tutorial about how to use it can be found here: http://vedder.se/2015/01/vesc-open-source-esc/ | |
+A complete description and tutorial about how to use it can be found here: http://vedder.se/2015/01/vesc-open-source-esc/ | |
+ | |
+This is free software: you can redistribute it and/or modify | |
+it under the terms of the GNU General Public License as published by | |
+the Free Software Foundation, either version 3 of the License, or | |
+(at your option) any later version. | |
+The software is distributed in the hope that it will be useful, | |
+but WITHOUT ANY WARRANTY; without even the implied warranty of | |
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
+GNU General Public License for more details. | |
+You should have received a copy of the GNU General Public License | |
+along with this program. If not, see <http://www.gnu.org/licenses | |
\ No newline at end of file | |
Only in Raptor2 Sources/bldc-firmware_2_80/appconf: appconf_custom.h | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/appconf/appconf_default.h Raptor2 Sources/bldc-firmware_2_80/appconf/appconf_default.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/appconf/appconf_default.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/appconf/appconf_default.h 2017-05-31 20:43:38.000000000 +0100 | |
@@ -26,36 +26,39 @@ | |
#define APPCONF_TIMEOUT_MSEC 1000 | |
#endif | |
#ifndef APPCONF_TIMEOUT_BRAKE_CURRENT | |
-#define APPCONF_TIMEOUT_BRAKE_CURRENT 0.0 | |
+#define APPCONF_TIMEOUT_BRAKE_CURRENT 0.0 | |
#endif | |
#ifndef APPCONF_SEND_CAN_STATUS | |
#define APPCONF_SEND_CAN_STATUS false | |
#endif | |
#ifndef APPCONF_SEND_CAN_STATUS_RATE_HZ | |
-#define APPCONF_SEND_CAN_STATUS_RATE_HZ 500 | |
+#define APPCONF_SEND_CAN_STATUS_RATE_HZ 500 | |
#endif | |
// The default app is UART in case the UART port is used for | |
// firmware updates. | |
#ifndef APPCONF_APP_TO_USE | |
-#define APPCONF_APP_TO_USE APP_UART | |
+#define APPCONF_APP_TO_USE APP_PPM_UART | |
#endif | |
// PPM app | |
#ifndef APPCONF_PPM_CTRL_TYPE | |
-#define APPCONF_PPM_CTRL_TYPE PPM_CTRL_TYPE_NONE | |
+#define APPCONF_PPM_CTRL_TYPE PPM_CTRL_TYPE_NONE //PPM_CTRL_TYPE_WATT_NOREV_BRAKE | |
#endif | |
#ifndef APPCONF_PPM_PID_MAX_ERPM | |
-#define APPCONF_PPM_PID_MAX_ERPM 15000 | |
+#define APPCONF_PPM_PID_MAX_ERPM 60000 | |
#endif | |
#ifndef APPCONF_PPM_HYST | |
-#define APPCONF_PPM_HYST 0.15 | |
+#define APPCONF_PPM_HYST 0.05 | |
#endif | |
#ifndef APPCONF_PPM_PULSE_START | |
-#define APPCONF_PPM_PULSE_START 1.0 | |
+#define APPCONF_PPM_PULSE_START 1.04 | |
+#endif | |
+#ifndef APPCONF_PPM_PULSE_CENTER | |
+#define APPCONF_PPM_PULSE_CENTER 1.54 | |
#endif | |
#ifndef APPCONF_PPM_PULSE_END | |
-#define APPCONF_PPM_PULSE_END 2.0 | |
+#define APPCONF_PPM_PULSE_END 2.04 | |
#endif | |
#ifndef APPCONF_PPM_MEDIAN_FILTER | |
#define APPCONF_PPM_MEDIAN_FILTER true | |
@@ -64,19 +67,77 @@ | |
#define APPCONF_PPM_SAFE_START true | |
#endif | |
#ifndef APPCONF_PPM_RPM_LIM_START | |
-#define APPCONF_PPM_RPM_LIM_START 150000 | |
+#define APPCONF_PPM_RPM_LIM_START 55000 | |
#endif | |
#ifndef APPCONF_PPM_RPM_LIM_END | |
-#define APPCONF_PPM_RPM_LIM_END 200000 | |
+#define APPCONF_PPM_RPM_LIM_END 60000 | |
#endif | |
#ifndef APPCONF_PPM_MULTI_ESC | |
-#define APPCONF_PPM_MULTI_ESC false | |
+#define APPCONF_PPM_MULTI_ESC true | |
#endif | |
#ifndef APPCONF_PPM_TC | |
-#define APPCONF_PPM_TC false | |
+#define APPCONF_PPM_TC true | |
#endif | |
#ifndef APPCONF_PPM_TC_MAX_DIFF | |
-#define APPCONF_PPM_TC_MAX_DIFF 3000.0 | |
+#define APPCONF_PPM_TC_MAX_DIFF 5000.0 | |
+#endif | |
+#ifndef APPCONF_PPM_TC_OFFSET | |
+#define APPCONF_PPM_TC_OFFSET 3000.0 | |
+#endif | |
+#ifndef APPCONF_PPM_MAX_ERPM_FOR_DIR_ACTIVE | |
+#define APPCONF_PPM_MAX_ERPM_FOR_DIR_ACTIVE true | |
+#endif | |
+#ifndef APPCONF_PPM_MAX_ERPM_FOR_DIR | |
+#define APPCONF_PPM_MAX_ERPM_FOR_DIR 4000.0 | |
+#endif | |
+ | |
+#ifndef APPCONF_ADJUSTABLE_THROTTLE_ENABLED | |
+#define APPCONF_ADJUSTABLE_THROTTLE_ENABLED true | |
+#endif | |
+#ifndef APPCONF_Y1_THROTTLE | |
+#define APPCONF_Y1_THROTTLE 0.08 | |
+#endif | |
+#ifndef APPCONF_Y2_THROTTLE | |
+#define APPCONF_Y2_THROTTLE 0.225 | |
+#endif | |
+#ifndef APPCONF_Y3_THROTTLE | |
+#define APPCONF_Y3_THROTTLE 0.50 | |
+#endif | |
+#ifndef APPCONF_X1_THROTTLE | |
+#define APPCONF_X1_THROTTLE 0.25 | |
+#endif | |
+#ifndef APPCONF_X2_THROTTLE | |
+#define APPCONF_X2_THROTTLE 0.50 | |
+#endif | |
+#ifndef APPCONF_X3_THROTTLE | |
+#define APPCONF_X3_THROTTLE 0.75 | |
+#endif | |
+ | |
+#ifndef APPCONF_BEZIER_REDUCE_FACTOR | |
+#define APPCONF_BEZIER_REDUCE_FACTOR 0 | |
+#endif | |
+ | |
+#ifndef APPCONF_Y1_NEG_THROTTLE | |
+#define APPCONF_Y1_NEG_THROTTLE 0.125 | |
+#endif | |
+#ifndef APPCONF_Y2_NEG_THROTTLE | |
+#define APPCONF_Y2_NEG_THROTTLE 0.30 | |
+#endif | |
+#ifndef APPCONF_Y3_NEG_THROTTLE | |
+#define APPCONF_Y3_NEG_THROTTLE 0.60 | |
+#endif | |
+#ifndef APPCONF_X1_NEG_THROTTLE | |
+#define APPCONF_X1_NEG_THROTTLE 0.25 | |
+#endif | |
+#ifndef APPCONF_X2_NEG_THROTTLE | |
+#define APPCONF_X2_NEG_THROTTLE 0.50 | |
+#endif | |
+#ifndef APPCONF_X3_NEG_THROTTLE | |
+#define APPCONF_X3_NEG_THROTTLE 0.75 | |
+#endif | |
+ | |
+#ifndef APPCONF_BEZIER_REDUCE_NEG_FACTOR | |
+#define APPCONF_BEZIER_REDUCE_NEG_FACTOR 0 | |
#endif | |
// ADC app configureation | |
@@ -84,7 +145,7 @@ | |
#define APPCONF_ADC_CTRL_TYPE ADC_CTRL_TYPE_NONE | |
#endif | |
#ifndef APPCONF_ADC_HYST | |
-#define APPCONF_ADC_HYST 0.15 | |
+#define APPCONF_ADC_HYST 0.15 | |
#endif | |
#ifndef APPCONF_ADC_VOLTAGE_START | |
#define APPCONF_ADC_VOLTAGE_START 0.9 | |
@@ -99,25 +160,25 @@ | |
#define APPCONF_ADC_SAFE_START true | |
#endif | |
#ifndef APPCONF_ADC_CC_BUTTON_INVERTED | |
-#define APPCONF_ADC_CC_BUTTON_INVERTED false | |
+#define APPCONF_ADC_CC_BUTTON_INVERTED false | |
#endif | |
#ifndef APPCONF_ADC_REV_BUTTON_INVERTED | |
-#define APPCONF_ADC_REV_BUTTON_INVERTED false | |
+#define APPCONF_ADC_REV_BUTTON_INVERTED false | |
#endif | |
#ifndef APPCONF_ADC_VOLTAGE_INVERTED | |
-#define APPCONF_ADC_VOLTAGE_INVERTED false | |
+#define APPCONF_ADC_VOLTAGE_INVERTED false | |
#endif | |
#ifndef APPCONF_ADC_RPM_LIM_START | |
-#define APPCONF_ADC_RPM_LIM_START 150000.0 | |
+#define APPCONF_ADC_RPM_LIM_START 2.0 | |
#endif | |
#ifndef APPCONF_ADC_RPM_LIM_END | |
-#define APPCONF_ADC_RPM_LIM_END 200000.0 | |
+#define APPCONF_ADC_RPM_LIM_END 80.0 | |
#endif | |
#ifndef APPCONF_ADC_MULTI_ESC | |
#define APPCONF_ADC_MULTI_ESC false | |
#endif | |
#ifndef APPCONF_ADC_TC | |
-#define APPCONF_ADC_TC false | |
+#define APPCONF_ADC_TC false | |
#endif | |
#ifndef APPCONF_ADC_TC_MAX_DIFF | |
#define APPCONF_ADC_TC_MAX_DIFF 3000.0 | |
@@ -128,7 +189,7 @@ | |
// UART app | |
#ifndef APPCONF_UART_BAUDRATE | |
-#define APPCONF_UART_BAUDRATE 115200 | |
+#define APPCONF_UART_BAUDRATE 9600 | |
#endif | |
// Nunchuk app | |
@@ -136,7 +197,7 @@ | |
#define APPCONF_CHUK_CTRL_TYPE CHUK_CTRL_TYPE_CURRENT | |
#endif | |
#ifndef APPCONF_CHUK_HYST | |
-#define APPCONF_CHUK_HYST 0.15 | |
+#define APPCONF_CHUK_HYST 0.15 | |
#endif | |
#ifndef APPCONF_CHUK_RPM_LIM_START | |
#define APPCONF_CHUK_RPM_LIM_START 150000.0 | |
@@ -151,16 +212,54 @@ | |
#define APPCONF_CHUK_RAMP_TIME_NEG 0.3 | |
#endif | |
#ifndef APPCONF_STICK_ERPM_PER_S_IN_CC | |
-#define APPCONF_STICK_ERPM_PER_S_IN_CC 3000.0 | |
+#define APPCONF_STICK_ERPM_PER_S_IN_CC 3000.0 | |
#endif | |
#ifndef APPCONF_CHUK_MULTI_ESC | |
#define APPCONF_CHUK_MULTI_ESC false | |
#endif | |
#ifndef APPCONF_CHUK_TC | |
-#define APPCONF_CHUK_TC false | |
+#define APPCONF_CHUK_TC false | |
#endif | |
#ifndef APPCONF_CHUK_TC_MAX_DIFF | |
-#define APPCONF_CHUK_TC_MAX_DIFF 3000.0 | |
+#define APPCONF_CHUK_TC_MAX_DIFF 5000.0 | |
+#endif | |
+#ifndef APPCONF_CHUK_TC_OFFSET | |
+#define APPCONF_CHUK_TC_OFFSET 3000.0 | |
+#endif | |
+#ifndef APPCONF_CHUK_BUTTONS_MIRRORED | |
+#define APPCONF_CHUK_BUTTONS_MIRRORED false | |
+#endif | |
+ | |
+// NRF app | |
+#ifndef APPCONF_NRF_SPEED | |
+#define APPCONF_NRF_SPEED NRF_SPEED_2M | |
+#endif | |
+#ifndef APPCONF_NRF_POWER | |
+#define APPCONF_NRF_POWER NRF_POWER_0DBM | |
+#endif | |
+#ifndef APPCONF_NRF_CRC | |
+#define APPCONF_NRF_CRC NRF_CRC_1B | |
+#endif | |
+#ifndef APPCONF_NRF_RETR_DELAY | |
+#define APPCONF_NRF_RETR_DELAY NRF_RETR_DELAY_250US | |
+#endif | |
+#ifndef APPCONF_NRF_RETRIES | |
+#define APPCONF_NRF_RETRIES 3 | |
+#endif | |
+#ifndef APPCONF_NRF_CHANNEL | |
+#define APPCONF_NRF_CHANNEL 76 | |
+#endif | |
+#ifndef APPCONF_NRF_ADDR_B0 | |
+#define APPCONF_NRF_ADDR_B0 0xC6 | |
+#endif | |
+#ifndef APPCONF_NRF_ADDR_B1 | |
+#define APPCONF_NRF_ADDR_B1 0xC7 | |
+#endif | |
+#ifndef APPCONF_NRF_ADDR_B2 | |
+#define APPCONF_NRF_ADDR_B2 0x0 | |
+#endif | |
+#ifndef APPCONF_NRF_SEND_CRC_ACK | |
+#define APPCONF_NRF_SEND_CRC_ACK true | |
#endif | |
#endif /* APPCONF_DEFAULT_H_ */ | |
Only in Raptor2 Sources/bldc-firmware_2_80/appconf: appconf_default_master.h | |
Only in Raptor2 Sources/bldc-firmware_2_80/appconf: appconf_default_slave.h | |
Only in bldc-90986c31defe50830b4795a388ee5b2687dc2516/appconf: appconf_example_ppm.h | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app.c Raptor2 Sources/bldc-firmware_2_80/applications/app.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app.c 2016-11-16 19:08:14.000000000 +0000 | |
@@ -26,6 +26,7 @@ | |
#include "hal.h" | |
#include "hw.h" | |
#include "nrf_driver.h" | |
+#include "rfhelp.h" | |
// Private variables | |
static app_configuration appconf; | |
@@ -65,6 +66,7 @@ | |
case APP_NRF: | |
nrf_driver_init(); | |
+ rfhelp_restart(); | |
break; | |
case APP_CUSTOM: | |
@@ -92,8 +94,9 @@ | |
*/ | |
void app_set_configuration(app_configuration *conf) { | |
appconf = *conf; | |
- app_ppm_configure(&appconf.app_ppm_conf); | |
+ app_ppm_configure(&appconf.app_ppm_conf, &appconf.app_throttle_conf); | |
app_adc_configure(&appconf.app_adc_conf); | |
app_uartcomm_configure(appconf.app_uart_baudrate); | |
- app_nunchuk_configure(&appconf.app_chuk_conf); | |
+ app_nunchuk_configure(&appconf.app_chuk_conf, &appconf.app_throttle_conf); | |
+ rfhelp_update_conf(&appconf.app_nrf_conf); | |
} | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app.h Raptor2 Sources/bldc-firmware_2_80/applications/app.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app.h 2016-11-16 23:21:16.000000000 +0000 | |
@@ -34,15 +34,17 @@ | |
// Standard apps | |
void app_ppm_start(void); | |
-void app_ppm_configure(ppm_config *conf); | |
+void app_ppm_configure(ppm_config *conf, throttle_config *throt_config); | |
void app_adc_start(bool use_rx_tx); | |
void app_adc_configure(adc_config *conf); | |
float app_adc_get_decoded_level(void); | |
float app_adc_get_voltage(void); | |
+float app_adc_get_decoded_level2(void); | |
+float app_adc_get_voltage2(void); | |
void app_uartcomm_start(void); | |
void app_uartcomm_configure(uint32_t baudrate); | |
void app_nunchuk_start(void); | |
-void app_nunchuk_configure(chuk_config *conf); | |
+void app_nunchuk_configure(chuk_config *conf, throttle_config *throt_config); | |
float app_nunchuk_get_decoded_chuk(void); | |
void app_nunchuk_update_output(chuck_data *data); | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app_adc.c Raptor2 Sources/bldc-firmware_2_80/applications/app_adc.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app_adc.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app_adc.c 2016-09-19 10:07:22.000000000 +0100 | |
@@ -49,6 +49,8 @@ | |
static volatile float ms_without_power = 0; | |
static volatile float decoded_level = 0.0; | |
static volatile float read_voltage = 0.0; | |
+static volatile float decoded_level2 = 0.0; | |
+static volatile float read_voltage2 = 0.0; | |
static volatile bool use_rx_tx_as_buttons = false; | |
void app_adc_configure(adc_config *conf) { | |
@@ -69,6 +71,15 @@ | |
return read_voltage; | |
} | |
+float app_adc_get_decoded_level2(void) { | |
+ return decoded_level2; | |
+} | |
+ | |
+float app_adc_get_voltage2(void) { | |
+ return read_voltage2; | |
+} | |
+ | |
+ | |
static THD_FUNCTION(adc_thread, arg) { | |
(void)arg; | |
@@ -132,6 +143,46 @@ | |
decoded_level = pwr; | |
+ // Read the external ADC pin and convert the value to a voltage. | |
+#ifdef ADC_IND_EXT2 | |
+ float brake = (float)ADC_Value[ADC_IND_EXT2]; | |
+ brake /= 4095; | |
+ brake *= V_REG; | |
+#else | |
+ float brake = 0.0; | |
+#endif | |
+ | |
+ read_voltage2 = brake; | |
+ | |
+ // Optionally apply a mean value filter | |
+ if (config.use_filter) { | |
+ static float filter_buffer2[FILTER_SAMPLES]; | |
+ static int filter_ptr2 = 0; | |
+ | |
+ filter_buffer2[filter_ptr2++] = brake; | |
+ if (filter_ptr2 >= FILTER_SAMPLES) { | |
+ filter_ptr2 = 0; | |
+ } | |
+ | |
+ brake = 0.0; | |
+ for (int i = 0;i < FILTER_SAMPLES;i++) { | |
+ brake += filter_buffer2[i]; | |
+ } | |
+ brake /= FILTER_SAMPLES; | |
+ } | |
+ | |
+ // Map and truncate the read voltage | |
+ brake = utils_map(brake, config.voltage_start, config.voltage_end, 0.0, 1.0); | |
+ utils_truncate_number(&brake, 0.0, 1.0); | |
+ | |
+ // Optionally invert the read voltage | |
+ if (config.voltage_inverted) { | |
+ brake = 1.0 - brake; | |
+ } | |
+ | |
+ decoded_level2 = brake; | |
+ | |
+ | |
// Read the button pins | |
bool cc_button = false; | |
bool rev_button = false; | |
@@ -170,6 +221,13 @@ | |
pwr -= 1.0; | |
break; | |
+ case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_ADC: | |
+ if( brake > 0.01 ) { | |
+ pwr = -brake; | |
+ } | |
+ | |
+ break; | |
+ | |
case ADC_CTRL_TYPE_CURRENT_REV_BUTTON: | |
case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_BUTTON: | |
case ADC_CTRL_TYPE_DUTY_REV_BUTTON: | |
@@ -211,6 +269,7 @@ | |
case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_CENTER: | |
case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_BUTTON: | |
+ case ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_ADC: | |
current_mode = true; | |
if (pwr >= 0.0) { | |
current = pwr * mcconf->l_current_max; | |
@@ -232,7 +291,7 @@ | |
} | |
if (!(ms_without_power < MIN_MS_WITHOUT_POWER && config.safe_start)) { | |
- mc_interface_set_duty(pwr); | |
+ mc_interface_set_duty(utils_map(pwr, -1.0, 1.0, -mcconf->l_max_duty, mcconf->l_max_duty)); | |
send_duty = true; | |
} | |
break; | |
@@ -249,6 +308,17 @@ | |
} | |
pulses_without_power_before = ms_without_power; | |
mc_interface_set_brake_current(timeout_get_brake_current()); | |
+ | |
+ if (config.multi_esc) { | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
+ comm_can_set_current_brake(msg->id, timeout_get_brake_current()); | |
+ } | |
+ } | |
+ } | |
+ | |
continue; | |
} | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app_nunchuk.c Raptor2 Sources/bldc-firmware_2_80/applications/app_nunchuk.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app_nunchuk.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app_nunchuk.c 2017-04-13 18:12:14.000000000 +0100 | |
@@ -53,10 +53,71 @@ | |
static volatile chuck_data chuck_d; | |
static volatile int chuck_error = 0; | |
static volatile chuk_config config; | |
+static volatile throttle_config throt_config; | |
+ | |
static volatile bool output_running = false; | |
-void app_nunchuk_configure(chuk_config *conf) { | |
+static float px[5]; | |
+static float py[5]; | |
+static float nx[5]; | |
+static float ny[5]; | |
+ | |
+float calculate_throttle_curve_chuk(float *x, float *y, float bezier_reduce_factor, float t) { | |
+ | |
+ float directSteps; | |
+ if (t < x[1]){ | |
+ directSteps = (y[1] / x[1] * t); | |
+ } else if (t > x[3]) { | |
+ directSteps = ((y[4] - y[3]) / (x[4] - x[3]) * (t-x[3]) + y[3]); | |
+ } else if (t > x[2]) { | |
+ directSteps = ((y[3] - y[2]) / (x[3] - x[2]) * (t-x[2]) + y[2]); | |
+ } else if (t > x[1]) { | |
+ directSteps = ((y[2] - y[1]) / (x[2] - x[1]) * (t-x[1]) + y[1]); | |
+ } else { // (throttle == x[1]) | |
+ directSteps = y[1]; | |
+ }; | |
+ | |
+ float f[5]; | |
+ for (int i = 0; i < 5; i++) f[i] = y[i]; | |
+ | |
+ for (int j = 1; j < 5; j++ ) | |
+ for (int i = 4; i >= j; i--) | |
+ f[i] = ( (t - x[i-j]) * f[i] - (t - x[i]) * f[i-1]) / (x[i] - x[i-j]); | |
+ | |
+ float spline = f[4] - ((f[4] - directSteps) * bezier_reduce_factor); | |
+ | |
+ // safety when stupid values are entered for x and y | |
+ if (spline > 1.0) return 1.0; | |
+ if (spline < 0.0) return 0.0; | |
+ | |
+ return spline; | |
+} | |
+ | |
+void app_nunchuk_configure(chuk_config *conf, throttle_config *throttle_conf) { | |
config = *conf; | |
+ throt_config = *throttle_conf; | |
+ | |
+ px[0] = 0.0; | |
+ px[1] = throt_config.x1_throttle; | |
+ px[2] = throt_config.x2_throttle; | |
+ px[3] = throt_config.x3_throttle; | |
+ px[4] = 1.0; | |
+ py[0] = 0.0; | |
+ py[1] = throt_config.y1_throttle; | |
+ py[2] = throt_config.y2_throttle; | |
+ py[3] = throt_config.y3_throttle; | |
+ py[4] = 1.0; | |
+ | |
+ nx[0] = 0.0; | |
+ nx[1] = throt_config.x1_neg_throttle; | |
+ nx[2] = throt_config.x2_neg_throttle; | |
+ nx[3] = throt_config.x3_neg_throttle; | |
+ nx[4] = 1.0; | |
+ ny[0] = 0.0; | |
+ ny[1] = throt_config.y1_neg_throttle; | |
+ ny[2] = throt_config.y2_neg_throttle; | |
+ ny[3] = throt_config.y3_neg_throttle; | |
+ ny[4] = 1.0; | |
} | |
void app_nunchuk_start(void) { | |
@@ -191,7 +252,7 @@ | |
continue; | |
} | |
- if (chuck_d.bt_z && !was_z && config.ctrl_type == CHUK_CTRL_TYPE_CURRENT && | |
+ if ((config.buttons_mirrored ? chuck_d.bt_c : chuck_d.bt_z) && !was_z && (config.ctrl_type == CHUK_CTRL_TYPE_CURRENT || config.ctrl_type == CHUK_CTRL_TYPE_WATT) && | |
fabsf(current_now) < MAX_CURR_DIFFERENCE) { | |
if (is_reverse) { | |
is_reverse = false; | |
@@ -200,12 +261,20 @@ | |
} | |
} | |
- was_z = chuck_d.bt_z; | |
+ was_z = config.buttons_mirrored ? chuck_d.bt_c : chuck_d.bt_z; | |
led_external_set_reversed(is_reverse); | |
float out_val = app_nunchuk_get_decoded_chuk(); | |
utils_deadband(&out_val, config.hyst, 1.0); | |
+ | |
+ if (throt_config.adjustable_throttle_enabled && out_val != 0.0){ | |
+ if (out_val > 0.0) { | |
+ out_val = calculate_throttle_curve_chuk(px, py, throt_config.bezier_reduce_factor, out_val); | |
+ } else { | |
+ out_val = -calculate_throttle_curve_chuk(nx, ny, throt_config.bezier_neg_reduce_factor, -out_val); | |
+ } | |
+ } | |
// LEDs | |
float x_axis = ((float)chuck_d.js_x - 128.0) / 128.0; | |
@@ -245,7 +314,7 @@ | |
} | |
rpm_filtered /= RPM_FILTER_SAMPLES; | |
- if (chuck_d.bt_c) { | |
+ if (config.buttons_mirrored ? chuck_d.bt_z : chuck_d.bt_c) { | |
static float pid_rpm = 0.0; | |
if (!was_pid) { | |
@@ -277,8 +346,21 @@ | |
} | |
} | |
- mc_interface_set_pid_speed(pid_rpm); | |
- | |
+ // NEW | |
+ switch (config.ctrl_type) { | |
+ case CHUK_CTRL_TYPE_CURRENT: | |
+ case CHUK_CTRL_TYPE_CURRENT_NOREV: | |
+ mc_interface_set_pid_speed(pid_rpm); | |
+ break; | |
+ case CHUK_CTRL_TYPE_WATT: | |
+ case CHUK_CTRL_TYPE_WATT_NOREV: | |
+ mc_interface_set_pid_speed(pid_rpm); | |
+ break; | |
+ default: | |
+ break; | |
+ } | |
+ // END NEW | |
+ | |
// Send the same duty cycle to the other controllers | |
if (config.multi_esc) { | |
float duty = mc_interface_get_duty_cycle_now(); | |
@@ -302,12 +384,35 @@ | |
was_pid = false; | |
float current = 0; | |
- | |
- if (out_val >= 0.0) { | |
- current = out_val * mcconf->l_current_max; | |
- } else { | |
- current = out_val * fabsf(mcconf->l_current_min); | |
+ | |
+ // NEW | |
+ switch (config.ctrl_type) { | |
+ case CHUK_CTRL_TYPE_CURRENT: | |
+ case CHUK_CTRL_TYPE_CURRENT_NOREV: | |
+ if (out_val >= 0.0) { | |
+ current = out_val * mcconf->l_current_max; | |
+ } else { | |
+ current = out_val * fabsf(mcconf->l_current_min); | |
+ } | |
+ break; | |
+ case CHUK_CTRL_TYPE_WATT: | |
+ case CHUK_CTRL_TYPE_WATT_NOREV: | |
+ if (out_val >= 0.0) { | |
+ if (mcconf->use_max_watt_limit) { | |
+ current = utils_smallest_of_2(out_val * mcconf->l_current_max, | |
+ out_val * (mcconf->watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } else { | |
+ current = utils_smallest_of_2(out_val * mcconf->l_current_max, | |
+ out_val * mcconf->l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation()); | |
+ } | |
+ } else { | |
+ current = out_val * fabsf(mcconf->l_current_min); | |
+ } | |
+ break; | |
+ default: | |
+ break; | |
} | |
+ // END NEW | |
// Find lowest RPM and highest current | |
float rpm_local = mc_interface_get_rpm(); | |
@@ -334,7 +439,7 @@ | |
// Make the current directional | |
float msg_current = msg->current; | |
- if (msg->duty < 0.0) { | |
+ if (msg->duty < 0) { | |
msg_current = -msg_current; | |
} | |
@@ -344,12 +449,17 @@ | |
} | |
} | |
} | |
- | |
+ | |
// Apply ramping | |
const float current_range = mcconf->l_current_max + fabsf(mcconf->l_current_min); | |
const float ramp_time = fabsf(current) > fabsf(prev_current) ? config.ramp_time_pos : config.ramp_time_neg; | |
- | |
- if (ramp_time > 0.01) { | |
+ | |
+ if (ramp_time > 0.01 && current != 0.0) { | |
+ | |
+ if (prev_current * current < 0.0) { | |
+ prev_current = 0.0; | |
+ } | |
+ | |
const float ramp_step = ((float)OUTPUT_ITERATION_TIME_MS * current_range) / (ramp_time * 1000.0); | |
float current_goal = prev_current; | |
@@ -376,38 +486,55 @@ | |
current_goal = goal_tmp2; | |
} | |
+ out_val = out_val / current * current_goal; | |
+ | |
current = current_goal; | |
} | |
prev_current = current; | |
- | |
+ | |
if (current < 0.0) { | |
+ | |
mc_interface_set_brake_current(current); | |
- // Send brake command to all ESCs seen recently on the CAN bus | |
- for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
- can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ if (config.multi_esc) { | |
+ // Send brake command to all ESCs seen recently on the CAN bus | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
- if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
- comm_can_set_current_brake(msg->id, current); | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
+ if (config.ctrl_type == CHUK_CTRL_TYPE_WATT || config.ctrl_type == CHUK_CTRL_TYPE_WATT_NOREV) { | |
+ comm_can_set_brake_servo(msg->id, out_val); | |
+ } else { | |
+ comm_can_set_current_brake(msg->id, current); | |
+ } | |
+ } | |
} | |
} | |
} else { | |
+ | |
+ bool use_min_current = false; | |
// Apply soft RPM limit | |
- if (rpm_lowest > config.rpm_lim_end && current > 0.0) { | |
- current = mcconf->cc_min_current; | |
- } else if (rpm_lowest > config.rpm_lim_start && current > 0.0) { | |
- current = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, mcconf->cc_min_current); | |
- } else if (rpm_lowest < -config.rpm_lim_end && current < 0.0) { | |
- current = mcconf->cc_min_current; | |
- } else if (rpm_lowest < -config.rpm_lim_start && current < 0.0) { | |
- rpm_lowest = -rpm_lowest; | |
- current = -current; | |
- current = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, mcconf->cc_min_current); | |
- current = -current; | |
+ if (rpm_lowest > config.rpm_lim_end) { | |
+ if (out_val > 0.0) { | |
+ use_min_current = true; | |
+ out_val = 0.000001; // make sure min current ius used | |
+ } | |
+ if (current > 0.0) { | |
+ current = mcconf->cc_min_current; | |
+ } | |
+ } else if (rpm_lowest > config.rpm_lim_start) { | |
+ if (out_val > 0.0) { | |
+ use_min_current = true; | |
+ out_val = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, out_val, 0.000001); | |
+ } | |
+ if (current > 0.0) { | |
+ current = utils_highest_of_2(utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, 0.0), mcconf->cc_min_current); | |
+ } | |
} | |
float current_out = current; | |
+ float servo_val_out = out_val; | |
// Traction control | |
if (config.multi_esc) { | |
@@ -422,25 +549,39 @@ | |
} | |
float diff = rpm_tmp - rpm_lowest; | |
- current_out = utils_map(diff, 0.0, config.tc_max_diff, current, 0.0); | |
- if (current_out < mcconf->cc_min_current) { | |
- current_out = 0.0; | |
+ | |
+ if (diff > config.tc_offset) { | |
+ current_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, current, 0.0); | |
+ servo_val_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, out_val, 0.0); | |
+ } else { | |
+ current_out = current; | |
+ servo_val_out = out_val; | |
} | |
} | |
if (is_reverse) { | |
- comm_can_set_current(msg->id, -current_out); | |
+ if (config.ctrl_type == CHUK_CTRL_TYPE_WATT || config.ctrl_type == CHUK_CTRL_TYPE_WATT_NOREV) { | |
+ comm_can_set_servo(msg->id, -servo_val_out, use_min_current); | |
+ } else { | |
+ comm_can_set_current(msg->id, -current_out); | |
+ } | |
} else { | |
- comm_can_set_current(msg->id, current_out); | |
+ if (config.ctrl_type == CHUK_CTRL_TYPE_WATT || config.ctrl_type == CHUK_CTRL_TYPE_WATT_NOREV) { | |
+ comm_can_set_servo(msg->id, servo_val_out, use_min_current); | |
+ } else { | |
+ comm_can_set_current(msg->id, current_out); | |
+ } | |
} | |
} | |
} | |
if (config.tc) { | |
float diff = rpm_local - rpm_lowest; | |
- current_out = utils_map(diff, 0.0, config.tc_max_diff, current, 0.0); | |
- if (current_out < mcconf->cc_min_current) { | |
- current_out = 0.0; | |
+ | |
+ if (diff > config.tc_offset) { | |
+ current_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, current, 0.0); | |
+ } else { | |
+ current_out = current; | |
} | |
} | |
} | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app_ppm.c Raptor2 Sources/bldc-firmware_2_80/applications/app_ppm.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app_ppm.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app_ppm.c 2017-04-13 18:12:22.000000000 +0100 | |
@@ -26,6 +26,7 @@ | |
#include "ch.h" | |
#include "hal.h" | |
+#include "hw.h" | |
#include "stm32f4xx_conf.h" | |
#include "servo_dec.h" | |
#include "mc_interface.h" | |
@@ -33,13 +34,15 @@ | |
#include "utils.h" | |
#include "comm_can.h" | |
#include <math.h> | |
+//#include "commands.h" | |
// Only available if servo output is not active | |
#if !SERVO_OUT_ENABLE | |
// Settings | |
-#define MAX_CAN_AGE 0.1 | |
-#define MIN_PULSES_WITHOUT_POWER 50 | |
+#define MAX_CAN_AGE 0.1 | |
+#define MIN_PULSES_WITHOUT_POWER 50 | |
+#define RPM_FILTER_SAMPLES 8 | |
// Threads | |
static THD_FUNCTION(ppm_thread, arg); | |
@@ -52,21 +55,96 @@ | |
// Private variables | |
static volatile bool is_running = false; | |
+static volatile float pid_rpm = 0; | |
+//static volatile int mode_switch_pulses = 0; | |
static volatile ppm_config config; | |
+static volatile throttle_config throt_config; | |
static volatile int pulses_without_power = 0; | |
+//static volatile int count = 0; | |
+ | |
+static volatile float filter_buffer[RPM_FILTER_SAMPLES]; | |
+static volatile int filter_ptr = 0; | |
+static volatile bool has_enough_pid_filter_data = false; | |
+static volatile float direction_hyst = 0; | |
+ | |
+static float px[5]; | |
+static float py[5]; | |
+static float nx[5]; | |
+static float ny[5]; | |
+ | |
// Private functions | |
static void update(void *p); | |
#endif | |
-void app_ppm_configure(ppm_config *conf) { | |
+float calculate_throttle_curve_ppm(float *x, float *y, float bezier_reduce_factor, float t) { | |
+ | |
+ float directSteps; | |
+ if (t < x[1]){ | |
+ directSteps = (y[1] / x[1] * t); | |
+ } else if (t > x[3]) { | |
+ directSteps = ((y[4] - y[3]) / (x[4] - x[3]) * (t-x[3]) + y[3]); | |
+ } else if (t > x[2]) { | |
+ directSteps = ((y[3] - y[2]) / (x[3] - x[2]) * (t-x[2]) + y[2]); | |
+ } else if (t > x[1]) { | |
+ directSteps = ((y[2] - y[1]) / (x[2] - x[1]) * (t-x[1]) + y[1]); | |
+ } else { // (throttle == x[1]) | |
+ directSteps = y[1]; | |
+ }; | |
+ | |
+ float f[5]; | |
+ for (int i = 0; i < 5; i++) f[i] = y[i]; | |
+ | |
+ for (int j = 1; j < 5; j++ ) | |
+ for (int i = 4; i >= j; i--) | |
+ f[i] = ( (t - x[i-j]) * f[i] - (t - x[i]) * f[i-1]) / (x[i] - x[i-j]); | |
+ | |
+ float spline = f[4] - ((f[4] - directSteps) * bezier_reduce_factor); | |
+ | |
+ // safety when stupid values are entered for x and y | |
+ if (spline > 1.0) return 1.0; | |
+ if (spline < 0.0) return 0.0; | |
+ | |
+ return spline; | |
+} | |
+ | |
+void app_ppm_configure(ppm_config *conf, throttle_config *throttle_conf) { | |
#if !SERVO_OUT_ENABLE | |
config = *conf; | |
+ throt_config = *throttle_conf; | |
pulses_without_power = 0; | |
+ | |
+ has_enough_pid_filter_data = false; | |
+ filter_ptr = 0; | |
+ mc_interface_set_cruise_control_status(CRUISE_CONTROL_INACTIVE); | |
if (is_running) { | |
- servodec_set_pulse_options(config.pulse_start, config.pulse_end, config.median_filter); | |
+ servodec_set_pulse_options(config.pulse_start, config.pulse_center, config.pulse_end, config.median_filter); | |
} | |
+ | |
+ px[0] = 0.0; | |
+ px[1] = throt_config.x1_throttle; | |
+ px[2] = throt_config.x2_throttle; | |
+ px[3] = throt_config.x3_throttle; | |
+ px[4] = 1.0; | |
+ py[0] = 0.0; | |
+ py[1] = throt_config.y1_throttle; | |
+ py[2] = throt_config.y2_throttle; | |
+ py[3] = throt_config.y3_throttle; | |
+ py[4] = 1.0; | |
+ | |
+ nx[0] = 0.0; | |
+ nx[1] = throt_config.x1_neg_throttle; | |
+ nx[2] = throt_config.x2_neg_throttle; | |
+ nx[3] = throt_config.x3_neg_throttle; | |
+ nx[4] = 1.0; | |
+ ny[0] = 0.0; | |
+ ny[1] = throt_config.y1_neg_throttle; | |
+ ny[2] = throt_config.y2_neg_throttle; | |
+ ny[3] = throt_config.y3_neg_throttle; | |
+ ny[4] = 1.0; | |
+ | |
+ direction_hyst = config.max_erpm_for_dir * 0.20; | |
#else | |
(void)conf; | |
#endif | |
@@ -103,8 +181,9 @@ | |
chRegSetThreadName("APP_PPM"); | |
ppm_tp = chThdGetSelfX(); | |
- servodec_set_pulse_options(config.pulse_start, config.pulse_end, config.median_filter); | |
+ servodec_set_pulse_options(config.pulse_start, config.pulse_center, config.pulse_end, config.median_filter); | |
servodec_init(servodec_func); | |
+ | |
is_running = true; | |
for(;;) { | |
@@ -124,26 +203,99 @@ | |
case PPM_CTRL_TYPE_PID_NOREV: | |
servo_val += 1.0; | |
servo_val /= 2.0; | |
+ | |
+ utils_deadband(&servo_val, config.hyst, 1.0); | |
+ | |
+ servo_val = calculate_throttle_curve_ppm(px, py, throt_config.bezier_reduce_factor, servo_val); | |
+ | |
+ break; | |
+ //case PPM_CTRL_TYPE_CURRENT: | |
+ case PPM_CTRL_TYPE_WATT: | |
+ utils_deadband(&servo_val, config.hyst, 1.0); | |
+ | |
+ if (throt_config.adjustable_throttle_enabled && servo_val != 0.0){ | |
+ if (servo_val > 0.0) { | |
+ servo_val = calculate_throttle_curve_ppm(px, py, throt_config.bezier_reduce_factor, servo_val); | |
+ } else if (config.max_erpm_for_dir_active == false) { | |
+ servo_val = -calculate_throttle_curve_ppm(nx, ny, throt_config.bezier_neg_reduce_factor, -servo_val); | |
+ } | |
+ } | |
break; | |
- | |
default: | |
+ | |
+ utils_deadband(&servo_val, config.hyst, 1.0); | |
+ | |
+ if (throt_config.adjustable_throttle_enabled && servo_val != 0.0){ | |
+ if (servo_val > 0.0) { | |
+ servo_val = calculate_throttle_curve_ppm(px, py, throt_config.bezier_reduce_factor, servo_val); | |
+ } else { | |
+ servo_val = -calculate_throttle_curve_ppm(nx, ny, throt_config.bezier_neg_reduce_factor, -servo_val); | |
+ } | |
+ } | |
+ | |
break; | |
} | |
- utils_deadband(&servo_val, config.hyst, 1.0); | |
- | |
float current = 0; | |
+ //float desired_watt = 0; | |
bool current_mode = false; | |
bool current_mode_brake = false; | |
const volatile mc_configuration *mcconf = mc_interface_get_configuration(); | |
bool send_duty = false; | |
+ //bool send_watt = false; | |
+ bool send_pid = false; | |
+ | |
+ // Find lowest RPM and cruise control | |
+ float rpm_local = mc_interface_get_rpm(); | |
+ float rpm_lowest = rpm_local; | |
+ float mid_rpm = rpm_local; | |
+ int motor_count = 1; | |
+ ppm_cruise cruise_control_status = CRUISE_CONTROL_INACTIVE; | |
+ if (config.multi_esc) { | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
+ // add to middle rpm count | |
+ mid_rpm += msg->rpm; | |
+ motor_count += 1; | |
+ if (fabsf(msg->rpm) < fabsf(rpm_lowest)) { | |
+ rpm_lowest = msg->rpm; | |
+ } | |
+ | |
+ // if any controller (VESC) sends the cruise contol status | |
+ if (msg->cruise_control_status != CRUISE_CONTROL_INACTIVE) { | |
+ cruise_control_status = msg->cruise_control_status; | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ // get middle rpm | |
+ mid_rpm /= motor_count; | |
+ | |
switch (config.ctrl_type) { | |
case PPM_CTRL_TYPE_CURRENT: | |
- case PPM_CTRL_TYPE_CURRENT_NOREV: | |
current_mode = true; | |
if (servo_val >= 0.0) { | |
- current = servo_val * mcconf->l_current_max; | |
+ // check of can bus send cruise control command | |
+ if (cruise_control_status != CRUISE_CONTROL_INACTIVE && servo_val == 0.0) { | |
+ // is rpm in range for cruise control | |
+ if (rpm_lowest > mcconf->s_pid_min_erpm) { | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = rpm_lowest; | |
+ } | |
+ current_mode = false; | |
+ send_pid = true; | |
+ mc_interface_set_pid_speed_with_cruise_status(rpm_local + pid_rpm - mid_rpm, cruise_control_status); | |
+ } else { | |
+ pid_rpm = 0; | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ current = servo_val * mcconf->l_current_max; | |
+ } | |
} else { | |
current = servo_val * fabsf(mcconf->l_current_min); | |
} | |
@@ -152,21 +304,294 @@ | |
pulses_without_power++; | |
} | |
break; | |
- | |
+ case PPM_CTRL_TYPE_CURRENT_NOREV: | |
case PPM_CTRL_TYPE_CURRENT_NOREV_BRAKE: | |
current_mode = true; | |
+ | |
if (servo_val >= 0.0) { | |
- current = servo_val * mcconf->l_current_max; | |
+ // check of can bus send cruise control command | |
+ if (cruise_control_status != CRUISE_CONTROL_INACTIVE && servo_val == 0.0) { | |
+ // is rpm in range for cruise control | |
+ if (rpm_lowest > mcconf->s_pid_min_erpm) { | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = rpm_lowest; | |
+ } | |
+ current_mode = false; | |
+ send_pid = true; | |
+ mc_interface_set_pid_speed_with_cruise_status(rpm_local + pid_rpm - mid_rpm, cruise_control_status); | |
+ } else { | |
+ pid_rpm = 0; | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ current = servo_val * mcconf->l_current_max; | |
+ } | |
+ | |
} else { | |
current = fabsf(servo_val * mcconf->l_current_min); | |
current_mode_brake = true; | |
} | |
+ if (servo_val < 0.001) { | |
+ pulses_without_power++; | |
+ } | |
+ break; | |
+ case PPM_CTRL_TYPE_WATT: | |
+ current_mode = true; | |
+ | |
+ if (config.max_erpm_for_dir_active) { // advanced backwards | |
+ static bool force_brake = true; | |
+ | |
+ static int8_t did_idle_once = 0; | |
+ | |
+ // Hysteresis 20 % of actual RPM | |
+ if (force_brake) { | |
+ if (rpm_local < config.max_erpm_for_dir - direction_hyst) { // for 2500 it's 2000 | |
+ force_brake = false; | |
+ did_idle_once = 0; | |
+ } | |
+ } else { | |
+ if (rpm_local > config.max_erpm_for_dir + direction_hyst) { // for 2500 it's 3000 | |
+ force_brake = true; | |
+ did_idle_once = 0; | |
+ } | |
+ } | |
+ | |
+ if (servo_val >= 0.0) { | |
+ if (servo_val == 0.0) { | |
+ // if there was a idle in between then allow going backwards | |
+ if (did_idle_once == 1 && !force_brake) { | |
+ did_idle_once = 2; | |
+ } | |
+ }else{ | |
+ // accelerated forward or fast enough at least | |
+ if (rpm_local > -config.max_erpm_for_dir){ // for 2500 it's -2500 | |
+ did_idle_once = 0; | |
+ } | |
+ } | |
+ | |
+ // check of can bus send cruise control command | |
+ if (cruise_control_status != CRUISE_CONTROL_INACTIVE && servo_val == 0.0) { | |
+ // is rpm in range for cruise control | |
+ if (fabsf(rpm_lowest) > mcconf->s_pid_min_erpm) { | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = mid_rpm; | |
+ } | |
+ current_mode = false; | |
+ send_pid = true; | |
+ | |
+ mc_interface_set_pid_speed_with_cruise_status(rpm_local + pid_rpm - mid_rpm, cruise_control_status); | |
+ } else { | |
+ pid_rpm = 0; | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ if (mcconf->use_max_watt_limit) { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * (mcconf->watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } else { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * mcconf->l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation()); | |
+ } | |
+ } | |
+ } else { | |
+ | |
+ // too fast | |
+ if (force_brake){ | |
+ current_mode_brake = true; | |
+ }else{ | |
+ // not too fast backwards | |
+ if (rpm_local > -config.max_erpm_for_dir) { // for 2500 it's -2500 | |
+ // first time that we brake and we are not too fast | |
+ if (did_idle_once != 2) { | |
+ did_idle_once = 1; | |
+ current_mode_brake = true; | |
+ } | |
+ // too fast backwards | |
+ } else { | |
+ // if brake was active already | |
+ if (did_idle_once == 1) { | |
+ current_mode_brake = true; | |
+ } else { | |
+ // it's ok to go backwards now braking would be strange now | |
+ did_idle_once = 2; | |
+ } | |
+ } | |
+ } | |
+ | |
+ if (current_mode_brake) { | |
+ // braking | |
+ if (throt_config.adjustable_throttle_enabled) { | |
+ // negative calculation | |
+ servo_val = -calculate_throttle_curve_ppm(nx, ny, throt_config.bezier_neg_reduce_factor, -servo_val); | |
+ } | |
+ current = fabsf(servo_val * mcconf->l_current_min); | |
+ }else { | |
+ // reverse acceleration | |
+ if (throt_config.adjustable_throttle_enabled) { | |
+ // positive calculation | |
+ servo_val = -calculate_throttle_curve_ppm(px, py, throt_config.bezier_reduce_factor, -servo_val); | |
+ } | |
+ | |
+ if (mcconf->use_max_watt_limit) { | |
+ current = -utils_smallest_of_2(fabsf(servo_val * mcconf->l_current_min), | |
+ fabsf(servo_val * (mcconf->watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation()))); | |
+ } else { | |
+ current = -utils_smallest_of_2(fabsf(servo_val * mcconf->l_current_min), | |
+ fabsf(servo_val * mcconf->l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } | |
+ } | |
+ } | |
+ } else { // normal backwards | |
+ if (servo_val >= 0.0) { | |
+ // check of can bus send cruise control command | |
+ if (cruise_control_status != CRUISE_CONTROL_INACTIVE && servo_val == 0.0) { | |
+ // is rpm in range for cruise control | |
+ if (fabsf(rpm_lowest) > mcconf->s_pid_min_erpm) { | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = mid_rpm; | |
+ } | |
+ current_mode = false; | |
+ send_pid = true; | |
+ | |
+ mc_interface_set_pid_speed_with_cruise_status(rpm_local + pid_rpm - mid_rpm, cruise_control_status); | |
+ } else { | |
+ pid_rpm = 0; | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ if (mcconf->use_max_watt_limit) { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * (mcconf->watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } else { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * mcconf->l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation()); | |
+ } | |
+ } | |
+ } else { | |
+ current = servo_val * fabsf(mcconf->l_current_min); | |
+ } | |
+ } | |
if (servo_val < 0.001) { | |
pulses_without_power++; | |
} | |
break; | |
+ case PPM_CTRL_TYPE_WATT_NOREV_BRAKE: | |
+ current_mode = true; | |
+ | |
+ if (servo_val >= 0.0) { | |
+ // check of can bus send cruise control command | |
+ if (cruise_control_status != CRUISE_CONTROL_INACTIVE && servo_val == 0.0) { | |
+ // is rpm in range for cruise control | |
+ if (rpm_lowest > mcconf->s_pid_min_erpm) { | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = mid_rpm; | |
+ } | |
+ current_mode = false; | |
+ send_pid = true; | |
+ mc_interface_set_pid_speed_with_cruise_status(rpm_local + pid_rpm - mid_rpm, cruise_control_status); | |
+ | |
+ } else { | |
+ pid_rpm = 0; | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ if (mcconf->use_max_watt_limit) { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * (mcconf->watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } else { | |
+ current = utils_smallest_of_2(servo_val * mcconf->l_current_max, | |
+ servo_val * mcconf->l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation()); | |
+ } | |
+ } | |
+ } else { | |
+ | |
+ current_mode_brake = true; | |
+ | |
+ // brake as in current mode if not enabled. Calculating via Battery Voltage would brake far too hard | |
+ current = fabsf(servo_val * mcconf->l_current_min); | |
+ } | |
+ if (servo_val < 0.001) { | |
+ pulses_without_power++; | |
+ } | |
+ break; | |
+ case PPM_CTRL_TYPE_PID_NOACCELERATION: | |
+ current_mode = true; | |
+ | |
+ filter_buffer[filter_ptr++] = mid_rpm; | |
+ if (filter_ptr >= RPM_FILTER_SAMPLES) { | |
+ filter_ptr = 0; | |
+ has_enough_pid_filter_data = true; | |
+ } | |
+ | |
+ float rpm_filtered = 0.0; | |
+ // only send when enough values are collected | |
+ if (has_enough_pid_filter_data) { | |
+ for (int i = 0; i < RPM_FILTER_SAMPLES; i++) { | |
+ rpm_filtered += filter_buffer[i]; | |
+ } | |
+ rpm_filtered /= RPM_FILTER_SAMPLES; | |
+ } | |
+ | |
+ if (servo_val >= 0.0) { | |
+ // check if pid needs to be lowered | |
+ if (servo_val > 0.0) { | |
+ // needs to be set first ? | |
+ if (pid_rpm == 0) { | |
+ pid_rpm = rpm_filtered; | |
+ } | |
+ | |
+ if(rpm_filtered > 1000){ | |
+ float diff = pid_rpm - rpm_filtered; | |
+ if (diff > 1500) { | |
+ pid_rpm = pid_rpm - 10; | |
+ }else if(diff > 500 && rpm_filtered < 1500) { | |
+ pid_rpm = pid_rpm - 10; | |
+ } | |
+ }else{ | |
+ pid_rpm = 0; | |
+ } | |
+ | |
+ // if not too slow than set the pid | |
+ if(pid_rpm > 0 && pid_rpm < config.pid_max_erpm) { | |
+ current_mode = false; | |
+ | |
+ send_pid = true; | |
+ mc_interface_set_pid_speed(rpm_local + pid_rpm - rpm_filtered); | |
+ | |
+ // overwrite mid_rpm | |
+ mid_rpm = rpm_filtered; | |
+ } else { | |
+ current = 0.0; | |
+ } | |
+ }else{ | |
+ current = 0.0; | |
+ } | |
+ } else { | |
+ current = fabsf(servo_val * mcconf->l_current_min); | |
+ current_mode_brake = true; | |
+ } | |
+ | |
+ if (servo_val < 0.001) { | |
+ pulses_without_power++; | |
+ } | |
+ break; | |
+ case PPM_CTRL_TYPE_CRUISE_CONTROL_SECONDARY_CHANNEL: | |
+ if (servo_val < -0.3 && config.cruise_left != CRUISE_CONTROL_INACTIVE) { | |
+ mc_interface_set_cruise_control_status(config.cruise_left); | |
+ } else if (servo_val > 0.3 && config.cruise_right != CRUISE_CONTROL_INACTIVE) { | |
+ mc_interface_set_cruise_control_status(config.cruise_right); | |
+ } else { | |
+ mc_interface_set_cruise_control_status(CRUISE_CONTROL_INACTIVE); | |
+ } | |
+ // Run this loop at 500Hz | |
+ chThdSleepMilliseconds(2); | |
+ | |
+ // Reset the timeout | |
+ //timeout_reset(); | |
+ continue; | |
+ break; | |
case PPM_CTRL_TYPE_DUTY: | |
case PPM_CTRL_TYPE_DUTY_NOREV: | |
if (fabsf(servo_val) < 0.001) { | |
@@ -174,7 +599,7 @@ | |
} | |
if (!(pulses_without_power < MIN_PULSES_WITHOUT_POWER && config.safe_start)) { | |
- mc_interface_set_duty(servo_val); | |
+ mc_interface_set_duty(utils_map(servo_val, -1.0, 1.0, -mcconf->l_max_duty, mcconf->l_max_duty)); | |
send_duty = true; | |
} | |
break; | |
@@ -194,6 +619,17 @@ | |
default: | |
continue; | |
} | |
+ | |
+ // switch the mode | |
+ /*if (servo_val == -1.0){ | |
+ mode_switch_pulses++; | |
+ }else{ | |
+ if (mode_switch_pulses > 1000){ | |
+ //switch mode | |
+ //mc_interface_change_speed_mode(); // ??? | |
+ } | |
+ mode_switch_pulses = 0; | |
+ }*/ | |
if (pulses_without_power < MIN_PULSES_WITHOUT_POWER && config.safe_start) { | |
static int pulses_without_power_before = 0; | |
@@ -205,69 +641,99 @@ | |
continue; | |
} | |
- // Find lowest RPM | |
- float rpm_local = mc_interface_get_rpm(); | |
- float rpm_lowest = rpm_local; | |
- if (config.multi_esc) { | |
+ if (send_duty && config.multi_esc) { | |
+ float duty = mc_interface_get_duty_cycle_now(); | |
+ | |
for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
can_status_msg *msg = comm_can_get_status_msg_index(i); | |
if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
- float rpm_tmp = msg->rpm; | |
- | |
- if (fabsf(rpm_tmp) < fabsf(rpm_lowest)) { | |
- rpm_lowest = rpm_tmp; | |
- } | |
+ comm_can_set_duty(msg->id, duty); | |
} | |
} | |
} | |
- if (send_duty && config.multi_esc) { | |
- float duty = mc_interface_get_duty_cycle_now(); | |
- | |
+ if (send_pid && config.multi_esc) { | |
+ | |
for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
can_status_msg *msg = comm_can_get_status_msg_index(i); | |
if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
- comm_can_set_duty(msg->id, duty); | |
+ comm_can_set_rpm(msg->id, msg->rpm + pid_rpm - mid_rpm, cruise_control_status); | |
} | |
} | |
} | |
if (current_mode) { | |
+ | |
+ pid_rpm = 0; // always reset in current, not that something stupid happens | |
+ | |
if (current_mode_brake) { | |
mc_interface_set_brake_current(current); | |
- // Send brake command to all ESCs seen recently on the CAN bus | |
- for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
- can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ if (config.multi_esc) { | |
+ // Send brake command to all ESCs seen recently on the CAN bus | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
- if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
- comm_can_set_current_brake(msg->id, current); | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < MAX_CAN_AGE) { | |
+ if (config.ctrl_type == PPM_CTRL_TYPE_WATT_NOREV_BRAKE || config.ctrl_type == PPM_CTRL_TYPE_WATT) { | |
+ comm_can_set_brake_servo(msg->id, fabsf(servo_val)); | |
+ } else { | |
+ comm_can_set_current_brake(msg->id, current); | |
+ } | |
+ } | |
} | |
} | |
} else { | |
// Apply soft RPM limit | |
- if (rpm_lowest > config.rpm_lim_end && current > 0.0) { | |
- current = mcconf->cc_min_current; | |
- } else if (rpm_lowest > config.rpm_lim_start && current > 0.0) { | |
- current = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, mcconf->cc_min_current); | |
- } else if (rpm_lowest < -config.rpm_lim_end && current < 0.0) { | |
- current = mcconf->cc_min_current; | |
- } else if (rpm_lowest < -config.rpm_lim_start && current < 0.0) { | |
- rpm_lowest = -rpm_lowest; | |
- current = -current; | |
- current = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, mcconf->cc_min_current); | |
- current = -current; | |
- rpm_lowest = -rpm_lowest; | |
- } | |
+ bool use_min_current = false; | |
+ if (rpm_lowest > config.rpm_lim_end) { | |
+ if (servo_val > 0.0) { | |
+ use_min_current = true; | |
+ servo_val = 0.000001; // make sure min current ius used | |
+ } | |
+ if (current > 0.0) { | |
+ current = mcconf->cc_min_current; | |
+ } | |
+ | |
+ } else if (rpm_lowest > config.rpm_lim_start) { | |
+ if (servo_val > 0.0) { | |
+ use_min_current = true; | |
+ servo_val = utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, servo_val, 0.000001); | |
+ } | |
+ if (current > 0.0) { | |
+ current = utils_highest_of_2(utils_map(rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, current, 0.0), mcconf->cc_min_current); | |
+ } | |
+ } else if (rpm_lowest < -config.rpm_lim_end) { | |
+ if (servo_val < 0.0) { | |
+ use_min_current = true; | |
+ servo_val = -0.000001; // make sure min current ius used | |
+ } | |
+ if (current < 0.0) { | |
+ current = -mcconf->cc_min_current; // wrong in original | |
+ } | |
+ | |
+ } else if (rpm_lowest < -config.rpm_lim_start) { | |
+ if (servo_val < 0.0) { | |
+ use_min_current = true; | |
+ servo_val = -utils_map(-rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, -servo_val, 0.000001); | |
+ } | |
+ if (current < 0.0) { | |
+ current = utils_smallest_of_2(-utils_map(-rpm_lowest, config.rpm_lim_start, config.rpm_lim_end, -current, 0.0), -mcconf->cc_min_current); | |
+ } | |
+ } | |
+ | |
float current_out = current; | |
+ float servo_val_out = servo_val; | |
bool is_reverse = false; | |
- if (current_out < 0.0) { | |
+ if (servo_val < 0.0) { | |
is_reverse = true; | |
current_out = -current_out; | |
current = -current; | |
+ servo_val_out = -servo_val_out; | |
+ servo_val = -servo_val; | |
rpm_local = -rpm_local; | |
rpm_lowest = -rpm_lowest; | |
} | |
@@ -285,25 +751,38 @@ | |
} | |
float diff = rpm_tmp - rpm_lowest; | |
- current_out = utils_map(diff, 0.0, config.tc_max_diff, current, 0.0); | |
- if (current_out < mcconf->cc_min_current) { | |
- current_out = 0.0; | |
+ if (diff > config.tc_offset) { | |
+ current_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, current, 0.0); | |
+ servo_val_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, servo_val, 0.0); | |
+ } else { | |
+ current_out = current; | |
+ servo_val_out = servo_val; | |
} | |
} | |
if (is_reverse) { | |
- comm_can_set_current(msg->id, -current_out); | |
+ if (config.ctrl_type == PPM_CTRL_TYPE_WATT_NOREV_BRAKE || (config.ctrl_type == PPM_CTRL_TYPE_WATT && config.max_erpm_for_dir_active)) { // if not active you want real brakes | |
+ comm_can_set_servo(msg->id, -servo_val_out, use_min_current); | |
+ } else { | |
+ comm_can_set_current(msg->id, -current_out); | |
+ } | |
} else { | |
- comm_can_set_current(msg->id, current_out); | |
+ if (config.ctrl_type == PPM_CTRL_TYPE_WATT_NOREV_BRAKE || config.ctrl_type == PPM_CTRL_TYPE_WATT) { | |
+ comm_can_set_servo(msg->id, servo_val_out, use_min_current); | |
+ } else { | |
+ comm_can_set_current(msg->id, current_out); | |
+ } | |
} | |
} | |
} | |
if (config.tc) { | |
+ | |
float diff = rpm_local - rpm_lowest; | |
- current_out = utils_map(diff, 0.0, config.tc_max_diff, current, 0.0); | |
- if (current_out < mcconf->cc_min_current) { | |
- current_out = 0.0; | |
+ if (diff > config.tc_offset) { | |
+ current_out = utils_map(diff - config.tc_offset, 0.0, config.tc_max_diff - config.tc_offset, current, 0.0); | |
+ } else { | |
+ current_out = current; | |
} | |
} | |
} | |
@@ -315,7 +794,6 @@ | |
} | |
} | |
} | |
- | |
} | |
} | |
#endif | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app_sten.c Raptor2 Sources/bldc-firmware_2_80/applications/app_sten.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/applications/app_sten.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/applications/app_sten.c 2016-09-19 10:07:18.000000000 +0100 | |
@@ -32,6 +32,8 @@ | |
#include "utils.h" | |
#include "hw.h" | |
#include "timeout.h" | |
+#include "comm_can.h" | |
+ | |
#include <math.h> | |
// Settings | |
@@ -147,15 +149,7 @@ | |
} | |
static void set_output(float output) { | |
- output /= (1.0 - HYST); | |
- | |
- if (output > HYST) { | |
- output -= HYST; | |
- } else if (output < -HYST) { | |
- output += HYST; | |
- } else { | |
- output = 0.0; | |
- } | |
+ utils_deadband(&output, HYST, 1.0); | |
const float rpm = mc_interface_get_rpm(); | |
@@ -182,13 +176,11 @@ | |
current_p2 = current_p1; | |
current_p1 = current; | |
- if (fabsf(current) < mc_interface_get_configuration()->cc_min_current) { | |
- current = -mc_interface_get_configuration()->cc_min_current; | |
- } | |
- | |
mc_interface_set_current(current); | |
+ comm_can_set_current(255, current); | |
} else { | |
mc_interface_set_brake_current(output * mc_interface_get_configuration()->l_current_min); | |
+ comm_can_set_current_brake(255, output * mc_interface_get_configuration()->l_current_min); | |
} | |
} | |
Only in Raptor2 Sources/bldc-firmware_2_80: build | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/comm_can.c Raptor2 Sources/bldc-firmware_2_80/comm_can.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/comm_can.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/comm_can.c 2017-04-13 17:59:58.000000000 +0100 | |
@@ -23,6 +23,7 @@ | |
*/ | |
#include <string.h> | |
+#include <math.h> | |
#include "comm_can.h" | |
#include "ch.h" | |
#include "hal.h" | |
@@ -179,7 +180,19 @@ | |
case CAN_PACKET_SET_RPM: | |
ind = 0; | |
- mc_interface_set_pid_speed((float)buffer_get_int32(rxmsg.data8, &ind)); | |
+ mc_interface_set_pid_speed_with_cruise_status((float)buffer_get_int32(rxmsg.data8, &ind), rxmsg.data8[ind++]); | |
+ timeout_reset(); | |
+ break; | |
+ | |
+ case CAN_PACKET_SET_SERVO: | |
+ ind = 0; | |
+ mc_interface_set_servo((float)buffer_get_int32(rxmsg.data8, &ind) / 1000000.0, rxmsg.data8[ind++]); | |
+ timeout_reset(); | |
+ break; | |
+ | |
+ case CAN_PACKET_SET_BRAKE_SERVO: | |
+ ind = 0; | |
+ mc_interface_set_brake_servo((float)buffer_get_int32(rxmsg.data8, &ind) / 1000000.0); | |
timeout_reset(); | |
break; | |
@@ -256,7 +269,8 @@ | |
stat_tmp->rx_time = chVTGetSystemTime(); | |
stat_tmp->rpm = (float)buffer_get_int32(rxmsg.data8, &ind); | |
stat_tmp->current = (float)buffer_get_int16(rxmsg.data8, &ind) / 10.0; | |
- stat_tmp->duty = (float)buffer_get_int16(rxmsg.data8, &ind) / 1000.0; | |
+ stat_tmp->duty = rxmsg.data8[ind++]; | |
+ stat_tmp->cruise_control_status = rxmsg.data8[ind++]; | |
break; | |
} | |
} | |
@@ -285,7 +299,9 @@ | |
uint8_t buffer[8]; | |
buffer_append_int32(buffer, (int32_t)mc_interface_get_rpm(), &send_index); | |
buffer_append_int16(buffer, (int16_t)(mc_interface_get_tot_current() * 10.0), &send_index); | |
- buffer_append_int16(buffer, (int16_t)(mc_interface_get_duty_cycle_now() * 1000.0), &send_index); | |
+ buffer[send_index++] = (int8_t) floor(mc_interface_get_duty_cycle_now() * 100); | |
+ buffer[send_index++] = mc_interface_get_cruise_control_status(); | |
+ | |
comm_can_transmit(app_get_configuration()->controller_id | ((uint32_t)CAN_PACKET_STATUS << 8), buffer, send_index); | |
} | |
@@ -410,6 +426,21 @@ | |
comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_SET_CURRENT << 8), buffer, send_index); | |
} | |
+void comm_can_set_servo(uint8_t controller_id, float servo_val, bool use_min_current) { | |
+ int32_t send_index = 0; | |
+ uint8_t buffer[5]; | |
+ buffer_append_int32(buffer, (int32_t)(servo_val * 1000000.0), &send_index); | |
+ buffer[send_index++] = use_min_current; | |
+ comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_SET_SERVO << 8), buffer, send_index); | |
+} | |
+ | |
+void comm_can_set_brake_servo(uint8_t controller_id, float servo_val) { | |
+ int32_t send_index = 0; | |
+ uint8_t buffer[4]; | |
+ buffer_append_int32(buffer, (int32_t)(servo_val * 1000000.0), &send_index); | |
+ comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_SET_BRAKE_SERVO << 8), buffer, send_index); | |
+} | |
+ | |
void comm_can_set_current_brake(uint8_t controller_id, float current) { | |
int32_t send_index = 0; | |
uint8_t buffer[4]; | |
@@ -417,10 +448,12 @@ | |
comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_SET_CURRENT_BRAKE << 8), buffer, send_index); | |
} | |
-void comm_can_set_rpm(uint8_t controller_id, float rpm) { | |
+void comm_can_set_rpm(uint8_t controller_id, float rpm, ppm_cruise cruise_status) { | |
int32_t send_index = 0; | |
- uint8_t buffer[4]; | |
+ uint8_t buffer[5]; | |
buffer_append_int32(buffer, (int32_t)rpm, &send_index); | |
+ buffer[send_index++] = cruise_status; | |
+ | |
comm_can_transmit(controller_id | ((uint32_t)CAN_PACKET_SET_RPM << 8), buffer, send_index); | |
} | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/comm_can.h Raptor2 Sources/bldc-firmware_2_80/comm_can.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/comm_can.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/comm_can.h 2017-04-13 18:00:08.000000000 +0100 | |
@@ -29,7 +29,7 @@ | |
// Settings | |
#define CAN_STATUS_MSG_INT_MS 1 | |
-#define CAN_STATUS_MSGS_TO_STORE 10 | |
+#define CAN_STATUS_MSGS_TO_STORE 3 | |
// Functions | |
void comm_can_init(void); | |
@@ -38,7 +38,9 @@ | |
void comm_can_set_duty(uint8_t controller_id, float duty); | |
void comm_can_set_current(uint8_t controller_id, float current); | |
void comm_can_set_current_brake(uint8_t controller_id, float current); | |
-void comm_can_set_rpm(uint8_t controller_id, float rpm); | |
+void comm_can_set_servo(uint8_t controller_id, float servo_val, bool use_min_current); | |
+void comm_can_set_brake_servo(uint8_t controller_id, float servo_val); | |
+void comm_can_set_rpm(uint8_t controller_id, float rpm, ppm_cruise cruise_status); | |
void comm_can_set_pos(uint8_t controller_id, float pos); | |
can_status_msg *comm_can_get_status_msg_index(int index); | |
can_status_msg *comm_can_get_status_msg_id(int id); | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/commands.c Raptor2 Sources/bldc-firmware_2_80/commands.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/commands.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/commands.c 2017-06-16 22:45:08.000000000 +0100 | |
@@ -25,7 +25,7 @@ | |
#include "commands.h" | |
#include "ch.h" | |
#include "hal.h" | |
-#include "main.h" | |
+#include "mc_interface.h" | |
#include "stm32f4xx_conf.h" | |
#include "servo.h" | |
#include "servo_simple.h" | |
@@ -67,8 +67,11 @@ | |
static void(*appdata_func)(unsigned char *data, unsigned int len) = 0; | |
static disp_pos_mode display_position_mode; | |
+static uint8_t remote_Mode; | |
+ | |
void commands_init(void) { | |
chThdCreateStatic(detect_thread_wa, sizeof(detect_thread_wa), NORMALPRIO, detect_thread, NULL); | |
+ remote_Mode = 0; | |
} | |
/** | |
@@ -120,6 +123,8 @@ | |
uint16_t flash_res; | |
uint32_t new_app_offset; | |
chuck_data chuck_d_tmp; | |
+ | |
+ bool sendActualSpeedMode = false; | |
packet_id = data[0]; | |
data++; | |
@@ -173,7 +178,7 @@ | |
buffer_append_float32(send_buffer, mc_interface_read_reset_avg_input_current(), 1e2, &ind); | |
buffer_append_float16(send_buffer, mc_interface_get_duty_cycle_now(), 1e3, &ind); | |
buffer_append_float32(send_buffer, mc_interface_get_rpm(), 1e0, &ind); | |
- buffer_append_float16(send_buffer, GET_INPUT_VOLTAGE(), 1e1, &ind); | |
+ buffer_append_float16(send_buffer, GET_INPUT_VOLTAGE(), 1e2, &ind); | |
buffer_append_float32(send_buffer, mc_interface_get_amp_hours(false), 1e4, &ind); | |
buffer_append_float32(send_buffer, mc_interface_get_amp_hours_charged(false), 1e4, &ind); | |
buffer_append_float32(send_buffer, mc_interface_get_watt_hours(false), 1e4, &ind); | |
@@ -245,6 +250,7 @@ | |
case COMM_SET_MCCONF: | |
mcconf = *mc_interface_get_configuration(); | |
+ appconf = *app_get_configuration(); | |
ind = 0; | |
mcconf.pwm_mode = data[ind++]; | |
@@ -253,22 +259,61 @@ | |
mcconf.sensor_mode = data[ind++]; | |
mcconf.l_current_max = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_current_max > 80.0){ | |
+ mcconf.l_current_max = 80.0; | |
+ } | |
+ | |
mcconf.l_current_min = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_current_min < -80.0){ | |
+ mcconf.l_current_min = -80.0; | |
+ } | |
+ | |
mcconf.l_in_current_max = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_in_current_max > 40.0){ | |
+ mcconf.l_in_current_max = 40.0; | |
+ } | |
+ | |
mcconf.l_in_current_min = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_in_current_min < -12.0){ | |
+ mcconf.l_in_current_min = -12.0; | |
+ } | |
+ | |
mcconf.l_abs_current_max = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_min_erpm = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_max_erpm = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_max_erpm_fbrake = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_max_erpm_fbrake_cc = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_min_vin = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_min_vin < 8.0){ | |
+ mcconf.l_min_vin = 8.0; | |
+ } | |
+ | |
mcconf.l_max_vin = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_max_vin > 57.0){ | |
+ mcconf.l_max_vin = 57.0; | |
+ } | |
+ | |
mcconf.l_battery_cut_start = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_battery_cut_start < 31.0){ | |
+ mcconf.l_battery_cut_start = 31.0; | |
+ } | |
+ | |
mcconf.l_battery_cut_end = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_battery_cut_end < 29.0){ | |
+ mcconf.l_battery_cut_end = 29.0; | |
+ } | |
mcconf.l_slow_abs_current = data[ind++]; | |
mcconf.l_rpm_lim_neg_torque = data[ind++]; | |
mcconf.l_temp_fet_start = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_temp_fet_start > 80.0){ | |
+ mcconf.l_temp_fet_start = 80.0; | |
+ } | |
+ | |
mcconf.l_temp_fet_end = buffer_get_float32(data, 1000.0, &ind); | |
+ if (mcconf.l_temp_fet_end > 100.0){ | |
+ mcconf.l_temp_fet_end = 100.0; | |
+ } | |
+ | |
mcconf.l_temp_motor_start = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_temp_motor_end = buffer_get_float32(data, 1000.0, &ind); | |
mcconf.l_min_duty = buffer_get_float32(data, 1000000.0, &ind); | |
@@ -282,17 +327,32 @@ | |
mcconf.sl_min_erpm = (float)buffer_get_int32(data, &ind) / 1000.0; | |
mcconf.sl_min_erpm_cycle_int_limit = (float)buffer_get_int32(data, &ind) / 1000.0; | |
mcconf.sl_max_fullbreak_current_dir_change = (float)buffer_get_int32(data, &ind) / 1000.0; | |
- mcconf.sl_cycle_int_limit = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ mcconf.sl_cycle_int_limit = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ }else{ | |
+ ind += 4; | |
+ } | |
mcconf.sl_phase_advance_at_br = (float)buffer_get_int32(data, &ind) / 1000.0; | |
mcconf.sl_cycle_int_rpm_br = (float)buffer_get_int32(data, &ind) / 1000.0; | |
- mcconf.sl_bemf_coupling_k = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ mcconf.sl_bemf_coupling_k = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ }else{ | |
+ ind += 4; | |
+ } | |
- memcpy(mcconf.hall_table, data + ind, 8); | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ memcpy(mcconf.hall_table, data + ind, 8); | |
+ } | |
ind += 8; | |
+ | |
mcconf.hall_sl_erpm = (float)buffer_get_int32(data, &ind) / 1000.0; | |
- mcconf.foc_current_kp = buffer_get_float32(data, 1e5, &ind); | |
- mcconf.foc_current_ki = buffer_get_float32(data, 1e5, &ind); | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ mcconf.foc_current_kp = buffer_get_float32(data, 1e5, &ind); | |
+ mcconf.foc_current_ki = buffer_get_float32(data, 1e5, &ind); | |
+ } else { | |
+ ind += 8; | |
+ } | |
mcconf.foc_f_sw = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_dt_us = buffer_get_float32(data, 1e6, &ind); | |
mcconf.foc_encoder_inverted = data[ind++]; | |
@@ -301,10 +361,15 @@ | |
mcconf.foc_sensor_mode = data[ind++]; | |
mcconf.foc_pll_kp = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_pll_ki = buffer_get_float32(data, 1e3, &ind); | |
- mcconf.foc_motor_l = buffer_get_float32(data, 1e8, &ind); | |
- mcconf.foc_motor_r = buffer_get_float32(data, 1e5, &ind); | |
- mcconf.foc_motor_flux_linkage = buffer_get_float32(data, 1e5, &ind); | |
- mcconf.foc_observer_gain = buffer_get_float32(data, 1e0, &ind); | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ mcconf.foc_motor_l = buffer_get_float32(data, 1e8, &ind); | |
+ mcconf.foc_motor_r = buffer_get_float32(data, 1e5, &ind); | |
+ mcconf.foc_motor_flux_linkage = buffer_get_float32(data, 1e5, &ind); | |
+ mcconf.foc_observer_gain = buffer_get_float32(data, 1e0, &ind); | |
+ }else{ | |
+ ind += 16; | |
+ } | |
+ | |
mcconf.foc_duty_dowmramp_kp = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_duty_dowmramp_ki = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_openloop_rpm = buffer_get_float32(data, 1e3, &ind); | |
@@ -312,33 +377,64 @@ | |
mcconf.foc_sl_openloop_time = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_sl_d_current_duty = buffer_get_float32(data, 1e3, &ind); | |
mcconf.foc_sl_d_current_factor = buffer_get_float32(data, 1e3, &ind); | |
+ | |
+ if (!appconf.send_can_status || mcconf.l_temp_motor_end == 101.0) { | |
+ memcpy(mcconf.foc_hall_table, data + ind, 8); | |
+ } | |
+ ind += 8; | |
+ | |
+ mcconf.foc_sl_erpm = (float)buffer_get_int32(data, &ind) / 1000.0; | |
mcconf.s_pid_kp = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.s_pid_ki = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.s_pid_kd = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.s_pid_min_erpm = (float)buffer_get_int32(data, &ind) / 1000.0; | |
- | |
+ | |
mcconf.p_pid_kp = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.p_pid_ki = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.p_pid_kd = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
+ mcconf.p_pid_ang_div = (float)buffer_get_int32(data, &ind) / 100000.0; | |
mcconf.cc_startup_boost_duty = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
mcconf.cc_min_current = (float)buffer_get_int32(data, &ind) / 1000.0; | |
mcconf.cc_gain = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
- mcconf.cc_ramp_step_max = (float)buffer_get_int32(data, &ind) / 1000000.0; | |
+ mcconf.cc_ramp_step_max = buffer_get_float32(data, 1e6, &ind); | |
mcconf.m_fault_stop_time_ms = buffer_get_int32(data, &ind); | |
mcconf.m_duty_ramp_step = (float)buffer_get_float32(data, 1000000.0, &ind); | |
mcconf.m_duty_ramp_step_rpm_lim = (float)buffer_get_float32(data, 1000000.0, &ind); | |
mcconf.m_current_backoff_gain = (float)buffer_get_float32(data, 1000000.0, &ind); | |
mcconf.m_encoder_counts = buffer_get_uint32(data, &ind); | |
+ mcconf.m_sensor_port_mode = data[ind++]; | |
+ | |
+ // new config | |
+ mcconf.s_pid_breaking_enabled = data[ind++]; | |
+ mcconf.use_max_watt_limit = data[ind++]; | |
+ mcconf.watts_max = (float)buffer_get_int16(data, &ind); | |
+ // new config end | |
conf_general_store_mc_configuration(&mcconf); | |
mc_interface_set_configuration(&mcconf); | |
- | |
-#if ENCODER_ENABLE | |
- encoder_set_counts(mcconf.m_encoder_counts); | |
-#endif | |
+ | |
+ if (!appconf.send_can_status) { | |
+ | |
+ ind = 0; | |
+ // send to all others | |
+ uint8_t send_buffer_can[PACKET_MAX_PL_LEN]; | |
+ | |
+ send_buffer_can[ind++] = packet_id; | |
+ for(unsigned int i = 0; i < len; i++){ | |
+ send_buffer_can[ind++] = data[i]; | |
+ } | |
+ | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1) { | |
+ comm_can_send_buffer(msg->id, send_buffer_can, len + 1, false); | |
+ } | |
+ } | |
+ } | |
ind = 0; | |
send_buffer[ind++] = packet_id; | |
@@ -416,15 +512,19 @@ | |
buffer_append_float32(send_buffer, mcconf.foc_sl_openloop_time, 1e3, &ind); | |
buffer_append_float32(send_buffer, mcconf.foc_sl_d_current_duty, 1e3, &ind); | |
buffer_append_float32(send_buffer, mcconf.foc_sl_d_current_factor, 1e3, &ind); | |
+ memcpy(send_buffer + ind, mcconf.foc_hall_table, 8); | |
+ ind += 8; | |
+ buffer_append_int32(send_buffer, (int32_t)(mcconf.foc_sl_erpm * 1000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_kp * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_ki * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_kd * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_min_erpm * 1000.0), &ind); | |
- | |
+ | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.p_pid_kp * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.p_pid_ki * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.p_pid_kd * 1000000.0), &ind); | |
+ buffer_append_float32(send_buffer, mcconf.p_pid_ang_div, 1e5, &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.cc_startup_boost_duty * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(mcconf.cc_min_current * 1000.0), &ind); | |
@@ -436,6 +536,13 @@ | |
buffer_append_float32(send_buffer, mcconf.m_duty_ramp_step_rpm_lim, 1000000.0, &ind); | |
buffer_append_float32(send_buffer, mcconf.m_current_backoff_gain, 1000000.0, &ind); | |
buffer_append_uint32(send_buffer, mcconf.m_encoder_counts, &ind); | |
+ send_buffer[ind++] = mcconf.m_sensor_port_mode; | |
+ | |
+ // new config | |
+ send_buffer[ind++] = mcconf.s_pid_breaking_enabled; | |
+ send_buffer[ind++] = mcconf.use_max_watt_limit; | |
+ buffer_append_int16(send_buffer, (int16_t)(mcconf.watts_max), &ind); | |
+ // new config end | |
commands_send_packet(send_buffer, ind); | |
break; | |
@@ -464,7 +571,7 @@ | |
appconf.app_ppm_conf.multi_esc = data[ind++]; | |
appconf.app_ppm_conf.tc = data[ind++]; | |
appconf.app_ppm_conf.tc_max_diff = (float)buffer_get_int32(data, &ind) / 1000.0; | |
- | |
+ | |
appconf.app_adc_conf.ctrl_type = data[ind++]; | |
appconf.app_adc_conf.hyst = (float)buffer_get_int32(data, &ind) / 1000.0; | |
appconf.app_adc_conf.voltage_start = (float)buffer_get_int32(data, &ind) / 1000.0; | |
@@ -493,7 +600,45 @@ | |
appconf.app_chuk_conf.multi_esc = data[ind++]; | |
appconf.app_chuk_conf.tc = data[ind++]; | |
appconf.app_chuk_conf.tc_max_diff = buffer_get_float32(data, 1000.0, &ind); | |
- | |
+ | |
+ appconf.app_nrf_conf.speed = data[ind++]; | |
+ appconf.app_nrf_conf.power = data[ind++]; | |
+ appconf.app_nrf_conf.crc_type = data[ind++]; | |
+ appconf.app_nrf_conf.retry_delay = data[ind++]; | |
+ appconf.app_nrf_conf.retries = data[ind++]; | |
+ appconf.app_nrf_conf.channel = data[ind++]; | |
+ memcpy(appconf.app_nrf_conf.address, data + ind, 3); | |
+ ind += 3; | |
+ appconf.app_nrf_conf.send_crc_ack = data[ind++]; | |
+ | |
+ // new config | |
+ appconf.app_ppm_conf.pulse_center = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ appconf.app_ppm_conf.tc_offset = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ appconf.app_ppm_conf.cruise_left = data[ind++]; | |
+ appconf.app_ppm_conf.cruise_right = data[ind++]; | |
+ appconf.app_ppm_conf.max_erpm_for_dir_active = data[ind++]; | |
+ appconf.app_ppm_conf.max_erpm_for_dir = buffer_get_float32(data, 1000.0, &ind); | |
+ | |
+ appconf.app_chuk_conf.tc_offset = (float)buffer_get_int32(data, &ind) / 1000.0; | |
+ appconf.app_chuk_conf.buttons_mirrored = data[ind++]; | |
+ | |
+ appconf.app_throttle_conf.adjustable_throttle_enabled = data[ind++]; | |
+ appconf.app_throttle_conf.y1_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.y2_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.y3_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x1_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x2_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x3_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.bezier_reduce_factor = (float)buffer_get_int16(data, &ind) / 100.0; | |
+ appconf.app_throttle_conf.y1_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.y2_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.y3_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x1_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x2_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.x3_neg_throttle = (float)buffer_get_int16(data, &ind) / 1000.0; | |
+ appconf.app_throttle_conf.bezier_neg_reduce_factor = (float)buffer_get_int16(data, &ind) / 100.0; | |
+ // new config end | |
+ | |
conf_general_store_app_configuration(&appconf); | |
app_set_configuration(&appconf); | |
timeout_configure(appconf.timeout_msec, appconf.timeout_brake_current); | |
@@ -533,7 +678,7 @@ | |
send_buffer[ind++] = appconf.app_ppm_conf.multi_esc; | |
send_buffer[ind++] = appconf.app_ppm_conf.tc; | |
buffer_append_int32(send_buffer, (int32_t)(appconf.app_ppm_conf.tc_max_diff * 1000.0), &ind); | |
- | |
+ | |
send_buffer[ind++] = appconf.app_adc_conf.ctrl_type; | |
buffer_append_int32(send_buffer, (int32_t)(appconf.app_adc_conf.hyst * 1000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(appconf.app_adc_conf.voltage_start * 1000.0), &ind); | |
@@ -562,7 +707,45 @@ | |
send_buffer[ind++] = appconf.app_chuk_conf.multi_esc; | |
send_buffer[ind++] = appconf.app_chuk_conf.tc; | |
buffer_append_int32(send_buffer, (int32_t)(appconf.app_chuk_conf.tc_max_diff * 1000.0), &ind); | |
- | |
+ | |
+ send_buffer[ind++] = appconf.app_nrf_conf.speed; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.power; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.crc_type; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.retry_delay; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.retries; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.channel; | |
+ memcpy(send_buffer + ind, appconf.app_nrf_conf.address, 3); | |
+ ind += 3; | |
+ send_buffer[ind++] = appconf.app_nrf_conf.send_crc_ack; | |
+ | |
+ // new config | |
+ buffer_append_int32(send_buffer, (int32_t)(appconf.app_ppm_conf.pulse_center * 1000.0), &ind); | |
+ buffer_append_int32(send_buffer, (int32_t)(appconf.app_ppm_conf.tc_offset * 1000.0), &ind); | |
+ send_buffer[ind++] = appconf.app_ppm_conf.cruise_left; | |
+ send_buffer[ind++] = appconf.app_ppm_conf.cruise_right; | |
+ send_buffer[ind++] = appconf.app_ppm_conf.max_erpm_for_dir_active; | |
+ buffer_append_float32(send_buffer, appconf.app_ppm_conf.max_erpm_for_dir, 1000.0, &ind); | |
+ | |
+ buffer_append_int32(send_buffer, (int32_t)(appconf.app_chuk_conf.tc_offset * 1000.0), &ind); | |
+ send_buffer[ind++] = appconf.app_chuk_conf.buttons_mirrored; | |
+ | |
+ send_buffer[ind++] = appconf.app_throttle_conf.adjustable_throttle_enabled; | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y1_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y2_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y3_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x1_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x2_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x3_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.bezier_reduce_factor * 100.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y1_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y2_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y3_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x1_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x2_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x3_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.bezier_neg_reduce_factor * 100.0), &ind); | |
+ // end new config | |
+ | |
commands_send_packet(send_buffer, ind); | |
break; | |
@@ -571,7 +754,7 @@ | |
at_start = data[ind++]; | |
sample_len = buffer_get_uint16(data, &ind); | |
decimation = data[ind++]; | |
- main_sample_print_data(at_start, sample_len, decimation); | |
+ mc_interface_sample_print_data(at_start, sample_len, decimation); | |
break; | |
case COMM_TERMINAL_CMD: | |
@@ -635,39 +818,74 @@ | |
break; | |
case COMM_DETECT_ENCODER: { | |
-#if ENCODER_ENABLE | |
- mcconf = *mc_interface_get_configuration(); | |
- mcconf_old = mcconf; | |
+ if (encoder_is_configured()) { | |
+ mcconf = *mc_interface_get_configuration(); | |
+ mcconf_old = mcconf; | |
- ind = 0; | |
- float current = buffer_get_float32(data, 1e3, &ind); | |
+ ind = 0; | |
+ float current = buffer_get_float32(data, 1e3, &ind); | |
- mcconf.motor_type = MOTOR_TYPE_FOC; | |
- mcconf.foc_f_sw = 10000.0; | |
- mcconf.foc_current_kp = 0.01; | |
- mcconf.foc_current_ki = 10.0; | |
- mc_interface_set_configuration(&mcconf); | |
+ mcconf.motor_type = MOTOR_TYPE_FOC; | |
+ mcconf.foc_f_sw = 10000.0; | |
+ mcconf.foc_current_kp = 0.01; | |
+ mcconf.foc_current_ki = 10.0; | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ float offset = 0.0; | |
+ float ratio = 0.0; | |
+ bool inverted = false; | |
+ mcpwm_foc_encoder_detect(current, false, &offset, &ratio, &inverted); | |
+ mc_interface_set_configuration(&mcconf_old); | |
+ | |
+ ind = 0; | |
+ send_buffer[ind++] = COMM_DETECT_ENCODER; | |
+ buffer_append_float32(send_buffer, offset, 1e6, &ind); | |
+ buffer_append_float32(send_buffer, ratio, 1e6, &ind); | |
+ send_buffer[ind++] = inverted; | |
+ commands_send_packet(send_buffer, ind); | |
+ } else { | |
+ ind = 0; | |
+ send_buffer[ind++] = COMM_DETECT_ENCODER; | |
+ buffer_append_float32(send_buffer, 1001.0, 1e6, &ind); | |
+ buffer_append_float32(send_buffer, 0.0, 1e6, &ind); | |
+ send_buffer[ind++] = false; | |
+ commands_send_packet(send_buffer, ind); | |
+ } | |
+ } | |
+ break; | |
- float offset = 0.0; | |
- float ratio = 0.0; | |
- bool inverted = false; | |
- mcpwm_foc_encoder_detect(current, false, &offset, &ratio, &inverted); | |
- mc_interface_set_configuration(&mcconf_old); | |
+ case COMM_DETECT_HALL_FOC: { | |
+ mcconf = *mc_interface_get_configuration(); | |
- ind = 0; | |
- send_buffer[ind++] = COMM_DETECT_ENCODER; | |
- buffer_append_float32(send_buffer, offset, 1e6, &ind); | |
- buffer_append_float32(send_buffer, ratio, 1e6, &ind); | |
- send_buffer[ind++] = inverted; | |
- commands_send_packet(send_buffer, ind); | |
-#else | |
- ind = 0; | |
- send_buffer[ind++] = COMM_DETECT_ENCODER; | |
- buffer_append_float32(send_buffer, 1001.0, 1e6, &ind); | |
- buffer_append_float32(send_buffer, 0.0, 1e6, &ind); | |
- send_buffer[ind++] = false; | |
- commands_send_packet(send_buffer, ind); | |
-#endif | |
+ if (mcconf.m_sensor_port_mode == SENSOR_PORT_MODE_HALL) { | |
+ mcconf_old = mcconf; | |
+ ind = 0; | |
+ float current = buffer_get_float32(data, 1e3, &ind); | |
+ | |
+ mcconf.motor_type = MOTOR_TYPE_FOC; | |
+ mcconf.foc_f_sw = 10000.0; | |
+ mcconf.foc_current_kp = 0.01; | |
+ mcconf.foc_current_ki = 10.0; | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ uint8_t hall_tab[8]; | |
+ bool res = mcpwm_foc_hall_detect(current, hall_tab); | |
+ mc_interface_set_configuration(&mcconf_old); | |
+ | |
+ ind = 0; | |
+ send_buffer[ind++] = COMM_DETECT_HALL_FOC; | |
+ memcpy(send_buffer + ind, hall_tab, 8); | |
+ ind += 8; | |
+ send_buffer[ind++] = res ? 0 : 1; | |
+ | |
+ commands_send_packet(send_buffer, ind); | |
+ } else { | |
+ ind = 0; | |
+ send_buffer[ind++] = COMM_DETECT_HALL_FOC; | |
+ memset(send_buffer, 255, 8); | |
+ ind += 8; | |
+ send_buffer[ind++] = 0; | |
+ } | |
} | |
break; | |
@@ -694,6 +912,8 @@ | |
send_buffer[ind++] = COMM_GET_DECODED_ADC; | |
buffer_append_int32(send_buffer, (int32_t)(app_adc_get_decoded_level() * 1000000.0), &ind); | |
buffer_append_int32(send_buffer, (int32_t)(app_adc_get_voltage() * 1000000.0), &ind); | |
+ buffer_append_int32(send_buffer, (int32_t)(app_adc_get_decoded_level2() * 1000000.0), &ind); | |
+ buffer_append_int32(send_buffer, (int32_t)(app_adc_get_voltage2() * 1000000.0), &ind); | |
commands_send_packet(send_buffer, ind); | |
break; | |
@@ -725,10 +945,518 @@ | |
appdata_func(data, len); | |
} | |
break; | |
+ | |
+ case COMM_SET_SPEED_MODE: | |
+ ind = 0; | |
+ uint8_t new_remote_Mode = data[ind++]; | |
+ uint8_t new_speed_mode_int = data[ind++]; | |
+ bool use_max_watt = data[ind++]; | |
+ float watts_max = buffer_get_float16(data, 1, &ind); | |
+ float cur_mot_max = buffer_get_float16(data, 10, &ind); | |
+ float cur_bat_max = buffer_get_float16(data, 10, &ind); | |
+ float cur_mot_min = buffer_get_float16(data, 10, &ind); | |
+ float cur_bat_min = buffer_get_float16(data, 10, &ind); | |
+ float max_erpm = buffer_get_float16(data, 0.1, &ind); | |
+ | |
+ bool useSpecialThrottleCurve = data[ind++]; | |
+ float newY1 = 0.0, newY2 = 0.0, newY3 = 0.0, newX1 = 0.0, newX2 = 0.0, newX3 = 0.0, newBezier_pos = 0.0, newY1_neg = 0.0, newY2_neg = 0.0, newY3_neg = 0.0, newX1_neg = 0.0, newX2_neg = 0.0, newX3_neg = 0.0, newBezier_neg = 0.0; | |
+ if (useSpecialThrottleCurve) { | |
+ newY1 = buffer_get_float16(data, 1000, &ind); | |
+ newY2 = buffer_get_float16(data, 1000, &ind); | |
+ newY3 = buffer_get_float16(data, 1000, &ind); | |
+ newX1 = buffer_get_float16(data, 1000, &ind); | |
+ newX2 = buffer_get_float16(data, 1000, &ind); | |
+ newX3 = buffer_get_float16(data, 1000, &ind); | |
+ newBezier_pos = buffer_get_float16(data, 100, &ind); | |
+ newY1_neg = buffer_get_float16(data, 1000, &ind); | |
+ newY2_neg = buffer_get_float16(data, 1000, &ind); | |
+ newY3_neg = buffer_get_float16(data, 1000, &ind); | |
+ newX1_neg = buffer_get_float16(data, 1000, &ind); | |
+ newX2_neg = buffer_get_float16(data, 1000, &ind); | |
+ newX3_neg = buffer_get_float16(data, 1000, &ind); | |
+ newBezier_neg = buffer_get_float16(data, 100, &ind); | |
+ } | |
+ | |
+ bool useSpecialPIDBrakingEnabled = data[ind++]; | |
+ bool pidBrakingEnabled = false; | |
+ if (useSpecialPIDBrakingEnabled) { | |
+ pidBrakingEnabled = data[ind++]; | |
+ } | |
+ | |
+ bool useSpecialSpeedPID = data[ind++]; | |
+ float speed_pid_kp = 0.0, speed_pid_ki = 0.0, speed_pid_kd = 0.0; | |
+ if (useSpecialSpeedPID) { | |
+ speed_pid_kp = buffer_get_float32(data, 1000000.0, &ind); | |
+ speed_pid_ki = buffer_get_float32(data, 1000000.0, &ind); | |
+ speed_pid_kd = buffer_get_float32(data, 1000000.0, &ind); | |
+ } | |
+ | |
+ uint8_t front_controller_first = data[ind++]; | |
+ uint8_t front_controller_second = data[ind++]; | |
+ bool front_use_max_watt = false; | |
+ float front_watts_max = 0.0, front_cur_mot_max = 0.0, front_cur_bat_max = 0.0, front_cur_mot_min = 0.0, front_cur_bat_min = 0.0; | |
+ if (front_controller_first != 9 || front_controller_second != 9) { | |
+ front_use_max_watt = data[ind++]; | |
+ front_watts_max = buffer_get_float16(data, 1, &ind); | |
+ front_cur_mot_max = buffer_get_float16(data, 10, &ind); | |
+ front_cur_bat_max = buffer_get_float16(data, 10, &ind); | |
+ front_cur_mot_min = buffer_get_float16(data, 10, &ind); | |
+ front_cur_bat_min = buffer_get_float16(data, 10, &ind); | |
+ } | |
+ | |
+ appconf = *app_get_configuration(); | |
+ | |
+ if (appconf.app_to_use == APP_PPM_UART | |
+ || appconf.app_to_use == APP_PPM | |
+ || appconf.app_to_use == APP_NONE | |
+ || appconf.app_to_use == APP_UART | |
+ || appconf.app_to_use == APP_NUNCHUK | |
+ || appconf.app_to_use == APP_NRF) { | |
+ | |
+ app_configuration saved_appconf; | |
+ | |
+ conf_general_read_app_configuration(&saved_appconf); | |
+ | |
+ mcconf = *mc_interface_get_configuration(); | |
+ | |
+ mc_configuration saved_mcconf; | |
+ // gett base settings for motor | |
+ conf_general_read_mc_configuration(&saved_mcconf); | |
+ | |
+ // reset app ppm | |
+ appconf.app_ppm_conf.ctrl_type = saved_appconf.app_ppm_conf.ctrl_type; | |
+ appconf.app_ppm_conf.pid_max_erpm = saved_appconf.app_ppm_conf.pid_max_erpm; | |
+ appconf.app_ppm_conf.rpm_lim_end = saved_appconf.app_ppm_conf.rpm_lim_end; | |
+ appconf.app_ppm_conf.rpm_lim_start = saved_appconf.app_ppm_conf.rpm_lim_start; | |
+ | |
+ // reset app chuk | |
+ appconf.app_chuk_conf.ctrl_type = saved_appconf.app_chuk_conf.ctrl_type; | |
+ appconf.app_chuk_conf.rpm_lim_end = saved_appconf.app_chuk_conf.rpm_lim_end; | |
+ appconf.app_chuk_conf.rpm_lim_start = saved_appconf.app_chuk_conf.rpm_lim_start; | |
+ | |
+ // reset throttle curve | |
+ appconf.app_throttle_conf.adjustable_throttle_enabled = saved_appconf.app_throttle_conf.adjustable_throttle_enabled; | |
+ appconf.app_throttle_conf.y1_throttle = saved_appconf.app_throttle_conf.y1_throttle; | |
+ appconf.app_throttle_conf.y2_throttle = saved_appconf.app_throttle_conf.y2_throttle; | |
+ appconf.app_throttle_conf.y3_throttle = saved_appconf.app_throttle_conf.y3_throttle; | |
+ appconf.app_throttle_conf.x1_throttle = saved_appconf.app_throttle_conf.x1_throttle; | |
+ appconf.app_throttle_conf.x2_throttle = saved_appconf.app_throttle_conf.x2_throttle; | |
+ appconf.app_throttle_conf.x3_throttle = saved_appconf.app_throttle_conf.x3_throttle; | |
+ appconf.app_throttle_conf.bezier_reduce_factor = saved_appconf.app_throttle_conf.bezier_reduce_factor; | |
+ appconf.app_throttle_conf.y1_neg_throttle = saved_appconf.app_throttle_conf.y1_neg_throttle; | |
+ appconf.app_throttle_conf.y2_neg_throttle = saved_appconf.app_throttle_conf.y2_neg_throttle; | |
+ appconf.app_throttle_conf.y3_neg_throttle = saved_appconf.app_throttle_conf.y3_neg_throttle; | |
+ appconf.app_throttle_conf.x1_neg_throttle = saved_appconf.app_throttle_conf.x1_neg_throttle; | |
+ appconf.app_throttle_conf.x2_neg_throttle = saved_appconf.app_throttle_conf.x2_neg_throttle; | |
+ appconf.app_throttle_conf.x3_neg_throttle = saved_appconf.app_throttle_conf.x3_neg_throttle; | |
+ appconf.app_throttle_conf.bezier_neg_reduce_factor = saved_appconf.app_throttle_conf.bezier_neg_reduce_factor; | |
+ | |
+ // reset motor | |
+ mcconf.l_current_max = saved_mcconf.l_current_max; | |
+ mcconf.l_current_min = saved_mcconf.l_current_min; | |
+ mcconf.l_in_current_max = saved_mcconf.l_in_current_max; | |
+ mcconf.l_in_current_min = saved_mcconf.l_in_current_min; | |
+ | |
+ mcconf.use_max_watt_limit = saved_mcconf.use_max_watt_limit; | |
+ mcconf.watts_max = saved_mcconf.watts_max; | |
+ | |
+ mcconf.s_pid_breaking_enabled = saved_mcconf.s_pid_breaking_enabled; | |
+ | |
+ mcconf.s_pid_kp = saved_mcconf.s_pid_kp; | |
+ mcconf.s_pid_ki = saved_mcconf.s_pid_ki; | |
+ mcconf.s_pid_kd = saved_mcconf.s_pid_kd; | |
+ | |
+ if (new_remote_Mode == 0){ | |
+ remote_Mode = new_remote_Mode; | |
+ } else { | |
+ if (appconf.app_to_use == APP_NONE || appconf.app_to_use == APP_UART) { | |
+ if (appconf.send_can_status) { | |
+ remote_Mode = new_remote_Mode; | |
+ } | |
+ } | |
+ | |
+ if (appconf.app_to_use == APP_PPM_UART || appconf.app_to_use == APP_PPM) { | |
+ switch (new_speed_mode_int) { | |
+ case PPM_CTRL_TYPE_PID_NOACCELERATION: | |
+ case PPM_CTRL_TYPE_NONE: | |
+ case PPM_CTRL_TYPE_CURRENT: | |
+ case PPM_CTRL_TYPE_CURRENT_NOREV: | |
+ case PPM_CTRL_TYPE_CURRENT_NOREV_BRAKE: | |
+ case PPM_CTRL_TYPE_DUTY: | |
+ case PPM_CTRL_TYPE_DUTY_NOREV: | |
+ case PPM_CTRL_TYPE_PID: | |
+ case PPM_CTRL_TYPE_PID_NOREV: | |
+ case PPM_CTRL_TYPE_WATT_NOREV_BRAKE: | |
+ case PPM_CTRL_TYPE_WATT: | |
+ if (!appconf.send_can_status) { | |
+ appconf.app_ppm_conf.ctrl_type = new_speed_mode_int; | |
+ | |
+ if (max_erpm > 0 && max_erpm <= 100000.0) { | |
+ appconf.app_ppm_conf.pid_max_erpm = max_erpm; | |
+ appconf.app_ppm_conf.rpm_lim_end = max_erpm; | |
+ appconf.app_ppm_conf.rpm_lim_start = max_erpm - ((int16_t)(max_erpm / 10)); // 10% off | |
+ } | |
+ } | |
+ | |
+ remote_Mode = new_remote_Mode; | |
+ break; | |
+ default: | |
+ //only the basic settings which are defined by the bldc-tool | |
+ remote_Mode = 0; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if (appconf.app_to_use == APP_NUNCHUK || appconf.app_to_use == APP_NRF) { | |
+ switch (new_speed_mode_int) { | |
+ case CHUK_CTRL_TYPE_NONE: | |
+ case CHUK_CTRL_TYPE_CURRENT: | |
+ case CHUK_CTRL_TYPE_CURRENT_NOREV: | |
+ case CHUK_CTRL_TYPE_WATT: | |
+ case CHUK_CTRL_TYPE_WATT_NOREV: | |
+ if (!appconf.send_can_status) { | |
+ appconf.app_chuk_conf.ctrl_type = new_speed_mode_int; | |
+ | |
+ if (max_erpm > 0 && max_erpm <= 100000.0) { | |
+ appconf.app_chuk_conf.rpm_lim_end = max_erpm; | |
+ appconf.app_chuk_conf.rpm_lim_start = max_erpm - ((int16_t)(max_erpm / 10)); // 10% off | |
+ } | |
+ | |
+ } | |
+ | |
+ remote_Mode = new_remote_Mode; | |
+ break; | |
+ default: | |
+ //only the basic settings which are defined by the bldc-tool | |
+ remote_Mode = 0; | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if(remote_Mode != 0){ | |
+ if (!appconf.send_can_status) { | |
+ if (useSpecialThrottleCurve) { | |
+ appconf.app_throttle_conf.adjustable_throttle_enabled = true; | |
+ appconf.app_throttle_conf.y1_throttle = newY1; | |
+ appconf.app_throttle_conf.y2_throttle = newY2; | |
+ appconf.app_throttle_conf.y3_throttle = newY3; | |
+ appconf.app_throttle_conf.x1_throttle = newX1; | |
+ appconf.app_throttle_conf.x2_throttle = newX2; | |
+ appconf.app_throttle_conf.x3_throttle = newX3; | |
+ appconf.app_throttle_conf.bezier_reduce_factor = newBezier_pos; | |
+ appconf.app_throttle_conf.y1_neg_throttle = newY1_neg; | |
+ appconf.app_throttle_conf.y2_neg_throttle = newY2_neg; | |
+ appconf.app_throttle_conf.y3_neg_throttle = newY3_neg; | |
+ appconf.app_throttle_conf.x1_neg_throttle = newX1_neg; | |
+ appconf.app_throttle_conf.x2_neg_throttle = newX2_neg; | |
+ appconf.app_throttle_conf.x3_neg_throttle = newX3_neg; | |
+ appconf.app_throttle_conf.bezier_neg_reduce_factor = newBezier_neg; | |
+ } | |
+ } | |
+ | |
+ if (useSpecialPIDBrakingEnabled) { | |
+ mcconf.s_pid_breaking_enabled = pidBrakingEnabled; | |
+ } | |
+ | |
+ if (useSpecialSpeedPID) { | |
+ mcconf.s_pid_kp = speed_pid_kp; | |
+ mcconf.s_pid_ki = speed_pid_ki; | |
+ mcconf.s_pid_kd = speed_pid_kd; | |
+ } | |
+ | |
+ if ((front_controller_first != 9 && appconf.controller_id == front_controller_first) | |
+ || (front_controller_second != 9 && appconf.controller_id == front_controller_second)) { // or last position | |
+ | |
+ mcconf.use_max_watt_limit = front_use_max_watt; | |
+ mcconf.watts_max = front_watts_max; | |
+ | |
+ if (front_cur_mot_max >= mcconf.cc_min_current && front_cur_mot_max <= 80) mcconf.l_current_max = front_cur_mot_max; | |
+ | |
+ if (front_cur_bat_max >= mcconf.cc_min_current && front_cur_bat_max <= 40) mcconf.l_in_current_max = front_cur_bat_max; | |
+ | |
+ if (front_cur_mot_min <= -mcconf.cc_min_current && front_cur_mot_min >= -80) mcconf.l_current_min = front_cur_mot_min; | |
+ | |
+ if (front_cur_bat_min <= -mcconf.cc_min_current && front_cur_bat_min >= -12) mcconf.l_in_current_min = front_cur_bat_min; | |
+ | |
+ } else { // normal or rear setup | |
+ mcconf.use_max_watt_limit = use_max_watt; | |
+ mcconf.watts_max = watts_max; | |
+ | |
+ if (cur_mot_max >= mcconf.cc_min_current && cur_mot_max <= 80) mcconf.l_current_max = cur_mot_max; | |
+ | |
+ if (cur_bat_max >= mcconf.cc_min_current && cur_bat_max <= 40) mcconf.l_in_current_max = cur_bat_max; | |
+ | |
+ if (cur_mot_min <= -mcconf.cc_min_current && cur_mot_min >= -80) mcconf.l_current_min = cur_mot_min; | |
+ | |
+ if (cur_bat_min <= -mcconf.cc_min_current && cur_bat_min >= -12) mcconf.l_in_current_min = cur_bat_min; | |
+ } | |
+ } | |
+ } | |
+ | |
+ if (!appconf.send_can_status) { | |
+ sendActualSpeedMode = true; | |
+ | |
+ ind = 0; | |
+ // send to all others | |
+ uint8_t send_buffer_can[PACKET_MAX_PL_LEN]; | |
+ | |
+ send_buffer_can[ind++] = packet_id; | |
+ send_buffer_can[ind++] = remote_Mode; | |
+ | |
+ for(unsigned int i = 1; i < len; i++){ | |
+ send_buffer_can[ind++] = data[i]; | |
+ } | |
+ | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1) { | |
+ comm_can_send_buffer(msg->id, send_buffer_can, len + 1, false); | |
+ } | |
+ } | |
+ } | |
+ | |
+ mc_interface_set_configuration(&mcconf); | |
+ app_set_configuration(&appconf); | |
+ | |
+ timeout_configure(appconf.timeout_msec, appconf.timeout_brake_current); | |
+ | |
+ timeout_reset(); | |
+ } | |
+ | |
+ break; | |
+ case COMM_CHANGE_SPEED_MODE: | |
+/* | |
+ ind = 0; | |
+ | |
+ app_configuration saved_appconf2; | |
+ | |
+ conf_general_read_app_configuration(&saved_appconf2); | |
+ | |
+ appconf = *app_get_configuration(); | |
+ | |
+ appconf.app_ppm_conf.ctrl_type = saved_appconf2.app_ppm_conf.ctrl_type; | |
+ | |
+ mcconf = *mc_interface_get_configuration(); | |
+ | |
+ mc_configuration saved_mcconf2; | |
+ // gett base settings for motor | |
+ conf_general_read_mc_configuration(&saved_mcconf2); | |
+ | |
+ mcconf.l_current_max = saved_mcconf2.l_current_max; | |
+ mcconf.l_in_current_max = saved_mcconf2.l_in_current_max; | |
+ | |
+ if (appconf.app_to_use == APP_PPM_UART || appconf.app_to_use == APP_PPM) { | |
+ if (appconf.app_ppm_conf.ctrl_type == PPM_CTRL_TYPE_WATT_NOREV_BRAKE) { | |
+ appconf.app_ppm_conf.ctrl_type = PPM_CTRL_TYPE_PID_NOACCELERATION; | |
+ float watt = 250 / 0.9; | |
+ } else if (appconf.app_ppm_conf.ctrl_type == PPM_CTRL_TYPE_PID_NOACCELERATION) { | |
+ appconf.app_ppm_conf.ctrl_type = PPM_CTRL_TYPE_WATT_NOREV_BRAKE; | |
+ *//*} else if (new_speed_mode_int == PPM_CTRL_TYPE_CURRENT_NOREV_BRAKE) { | |
+ appconf.app_ppm_conf.ctrl_type = new_speed_mode_int; | |
+ | |
+ if (current_motor >= mcconf.cc_min_current && current_motor <= mcconf.l_current_max){ | |
+ mcconf.l_current_max = current_motor; | |
+ } | |
+ | |
+ if (current_battery >= mcconf.cc_min_current && current_battery <= mcconf.l_in_current_max){ | |
+ mcconf.l_in_current_max = current_battery; | |
+ }*/ | |
+/* | |
+ } else if (appconf.app_ppm_conf.ctrl_type == PPM_CTRL_TYPE_WATT_NOREV_BRAKE) { | |
+ appconf.app_ppm_conf.ctrl_type = PPM_CTRL_TYPE_CURRENT_NOREV_BRAKE; | |
+ //currents will be the default values | |
+ } else{ | |
+ //only the basic settings which are defined by the bldc-tool | |
+ } | |
+ } | |
+ | |
+ mc_interface_set_configuration(&mcconf); | |
+ app_set_configuration(&appconf); | |
+ timeout_configure(appconf.timeout_msec, appconf.timeout_brake_current); | |
+ | |
+ timeout_reset(); | |
+ sendActualSpeedMode = true; | |
+*/ | |
+ break; | |
+ case COMM_GET_SPEED_MODE: | |
+ sendActualSpeedMode = true; | |
+ break; | |
+ case COMM_SET_CURRENT_CONF_AS_DEFAULT: | |
+ | |
+ mcconf = *mc_interface_get_configuration(); | |
+ | |
+ appconf = *app_get_configuration(); | |
+ | |
+ if (!appconf.send_can_status) { | |
+ sendActualSpeedMode = true; | |
+ | |
+ ind = 0; | |
+ // send to all others | |
+ uint8_t send_buffer_can[PACKET_MAX_PL_LEN]; | |
+ | |
+ send_buffer_can[ind++] = packet_id; | |
+ | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1) { | |
+ comm_can_send_buffer(msg->id, send_buffer_can, len + 1, false); | |
+ } | |
+ } | |
+ } | |
+ | |
+ conf_general_store_mc_configuration(&mcconf); | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ conf_general_store_app_configuration(&appconf); | |
+ app_set_configuration(&appconf); | |
+ | |
+ timeout_configure(appconf.timeout_msec, appconf.timeout_brake_current); | |
+ | |
+ remote_Mode = 0; | |
+ break; | |
+ case COMM_SET_MOTOR_TYPE: | |
+ appconf = *app_get_configuration(); | |
+ | |
+ bool change_allowed = false; | |
+ | |
+ ind = 0; | |
+ uint8_t new_motor_type = data[ind++]; | |
+ | |
+ if (new_motor_type == MOTOR_TYPE_FOC || new_motor_type == MOTOR_TYPE_BLDC) { | |
+ | |
+ mcconf = *mc_interface_get_configuration(); | |
+ | |
+ if (mcconf.motor_type != new_motor_type) { | |
+ | |
+ mc_configuration default_mcconf; | |
+ //get default settings | |
+ conf_general_get_default_mc_configuration(&default_mcconf); | |
+ | |
+ change_allowed = true; | |
+ | |
+ /*if (new_motor_type == MOTOR_TYPE_FOC && | |
+ (mcconf.foc_motor_l != default_mcconf.foc_motor_l | |
+ || mcconf.foc_motor_r != default_mcconf.foc_motor_r | |
+ || mcconf.foc_motor_flux_linkage != default_mcconf.foc_motor_flux_linkage)) { | |
+ change_allowed = true; | |
+ } | |
+ | |
+ if (new_motor_type == MOTOR_TYPE_BLDC && | |
+ (mcconf.sl_cycle_int_limit != default_mcconf.sl_cycle_int_limit | |
+ || mcconf.sl_bemf_coupling_k != default_mcconf.sl_bemf_coupling_k)) { | |
+ change_allowed = true; | |
+ }*/ | |
+ | |
+ | |
+ if (change_allowed) { | |
+ if (!appconf.send_can_status) { | |
+ ind = 0; | |
+ // send to all others | |
+ uint8_t send_buffer_can[PACKET_MAX_PL_LEN]; | |
+ | |
+ send_buffer_can[ind++] = packet_id; | |
+ send_buffer_can[ind++] = new_motor_type; | |
+ | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1) { | |
+ comm_can_send_buffer(msg->id, send_buffer_can, len + 1, false); | |
+ } | |
+ } | |
+ } | |
+ | |
+ //change motor config | |
+ mcconf.motor_type = new_motor_type; | |
+ | |
+ //write motor config | |
+ //conf_general_store_mc_configuration(&saved_mcconf); | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ if (!appconf.send_can_status) { | |
+ int32_t ind_motor_type = 0; | |
+ uint8_t send_buffer_motor_type[PACKET_MAX_PL_LEN]; | |
+ | |
+ send_buffer_motor_type[ind_motor_type++] = packet_id; | |
+ send_buffer_motor_type[ind_motor_type++] = new_motor_type; | |
+ commands_send_packet(send_buffer_motor_type, ind_motor_type); | |
+ } | |
+ } | |
+ } | |
+ } | |
+ | |
+ //if (change_allowed == false && !appconf.send_can_status) { | |
+ if (!appconf.send_can_status) { | |
+ sendActualSpeedMode = true; | |
+ } | |
+ | |
+ break; | |
default: | |
break; | |
} | |
+ | |
+ if (sendActualSpeedMode) { | |
+ appconf = *app_get_configuration(); | |
+ mcconf = *mc_interface_get_configuration(); | |
+ | |
+ ind = 0; | |
+ send_buffer[ind++] = COMM_GET_SPEED_MODE; | |
+ send_buffer[ind++] = remote_Mode; | |
+ if(appconf.app_to_use == APP_NUNCHUK || appconf.app_to_use == APP_NRF){ | |
+ send_buffer[ind++] = appconf.app_chuk_conf.ctrl_type; | |
+ }else{ | |
+ send_buffer[ind++] = appconf.app_ppm_conf.ctrl_type; | |
+ } | |
+ | |
+ send_buffer[ind++] = mcconf.use_max_watt_limit; | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.watts_max), &ind); | |
+ | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_current_max * 10), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_in_current_max * 10), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_current_min * 10), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_in_current_min * 10), &ind); | |
+ | |
+ if(appconf.app_to_use == APP_NUNCHUK || appconf.app_to_use == APP_NRF){ | |
+ buffer_append_int16(send_buffer, (int16_t) (appconf.app_chuk_conf.rpm_lim_end / 10), &ind); | |
+ }else{ | |
+ buffer_append_int16(send_buffer, (int16_t) (appconf.app_ppm_conf.rpm_lim_end / 10), &ind); | |
+ } | |
+ | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_battery_cut_start * 100), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_battery_cut_end * 100), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_temp_fet_start * 100), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t) (mcconf.l_temp_fet_end * 100), &ind); | |
+ | |
+ send_buffer[ind++] = appconf.app_to_use; | |
+ | |
+ send_buffer[ind++] = appconf.app_throttle_conf.adjustable_throttle_enabled; | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y1_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y2_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y3_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x1_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x2_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x3_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.bezier_reduce_factor * 100.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y1_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y2_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.y3_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x1_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x2_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.x3_neg_throttle * 1000.0), &ind); | |
+ buffer_append_int16(send_buffer, (int16_t)(appconf.app_throttle_conf.bezier_neg_reduce_factor * 100.0), &ind); | |
+ | |
+ send_buffer[ind++] = mcconf.s_pid_breaking_enabled; | |
+ buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_kp * 1000000.0), &ind); | |
+ buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_ki * 1000000.0), &ind); | |
+ buffer_append_int32(send_buffer, (int32_t)(mcconf.s_pid_kd * 1000000.0), &ind); | |
+ | |
+ send_buffer[ind++] = mcconf.motor_type; | |
+ | |
+ commands_send_packet(send_buffer, ind); | |
+ } | |
} | |
void commands_printf(char* format, ...) { | |
@@ -798,7 +1526,7 @@ | |
int32_t index = 0; | |
send_buffer[index++] = COMM_CUSTOM_APP_DATA; | |
- memcpy(send_buffer, data, len); | |
+ memcpy(send_buffer + index, data, len); | |
index += len; | |
commands_send_packet(send_buffer, index); | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/commands.h Raptor2 Sources/bldc-firmware_2_80/commands.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/commands.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/commands.h 2016-09-19 10:06:42.000000000 +0100 | |
@@ -38,5 +38,6 @@ | |
void commands_send_experiment_samples(float *samples, int len); | |
disp_pos_mode commands_get_disp_pos_mode(void); | |
void commands_set_app_data_handler(void(*func)(unsigned char *data, unsigned int len)); | |
+void commands_send_app_data(unsigned char *data, unsigned int len); | |
#endif /* COMMANDS_H_ */ | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/conf_general.c Raptor2 Sources/bldc-firmware_2_80/conf_general.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/conf_general.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/conf_general.c 2017-04-15 03:04:20.000000000 +0100 | |
@@ -47,7 +47,7 @@ | |
memset(VirtAddVarTab, 0, sizeof(VirtAddVarTab)); | |
int ind = 0; | |
- for (unsigned int i = 0;i < (sizeof(app_configuration) / 2);i++) { | |
+ for (unsigned int i = 0;i < (sizeof(mc_configuration) / 2);i++) { | |
VirtAddVarTab[ind++] = EEPROM_BASE_MCCONF + i; | |
} | |
@@ -89,7 +89,7 @@ | |
conf->app_ppm_conf.multi_esc = APPCONF_PPM_MULTI_ESC; | |
conf->app_ppm_conf.tc = APPCONF_PPM_TC; | |
conf->app_ppm_conf.tc_max_diff = APPCONF_PPM_TC_MAX_DIFF; | |
- | |
+ | |
conf->app_adc_conf.ctrl_type = APPCONF_ADC_CTRL_TYPE; | |
conf->app_adc_conf.hyst = APPCONF_ADC_HYST; | |
conf->app_adc_conf.voltage_start = APPCONF_ADC_VOLTAGE_START; | |
@@ -118,6 +118,45 @@ | |
conf->app_chuk_conf.multi_esc = APPCONF_CHUK_MULTI_ESC; | |
conf->app_chuk_conf.tc = APPCONF_CHUK_TC; | |
conf->app_chuk_conf.tc_max_diff = APPCONF_CHUK_TC_MAX_DIFF; | |
+ | |
+ conf->app_nrf_conf.speed = APPCONF_NRF_SPEED; | |
+ conf->app_nrf_conf.power = APPCONF_NRF_POWER; | |
+ conf->app_nrf_conf.crc_type = APPCONF_NRF_CRC; | |
+ conf->app_nrf_conf.retry_delay = APPCONF_NRF_RETR_DELAY; | |
+ conf->app_nrf_conf.retries = APPCONF_NRF_RETRIES; | |
+ conf->app_nrf_conf.channel = APPCONF_NRF_CHANNEL; | |
+ conf->app_nrf_conf.address[0] = APPCONF_NRF_ADDR_B0; | |
+ conf->app_nrf_conf.address[1] = APPCONF_NRF_ADDR_B1; | |
+ conf->app_nrf_conf.address[2] = APPCONF_NRF_ADDR_B2; | |
+ conf->app_nrf_conf.send_crc_ack = APPCONF_NRF_SEND_CRC_ACK; | |
+ | |
+ //new config | |
+ conf->app_ppm_conf.pulse_center = APPCONF_PPM_PULSE_CENTER; | |
+ conf->app_ppm_conf.tc_offset = APPCONF_PPM_TC_OFFSET; | |
+ conf->app_ppm_conf.cruise_left = CRUISE_CONTROL_MOTOR_SETTINGS; | |
+ conf->app_ppm_conf.cruise_right = CRUISE_CONTROL_MOTOR_SETTINGS; | |
+ conf->app_ppm_conf.max_erpm_for_dir_active = APPCONF_PPM_MAX_ERPM_FOR_DIR_ACTIVE; | |
+ conf->app_ppm_conf.max_erpm_for_dir = APPCONF_PPM_MAX_ERPM_FOR_DIR; | |
+ | |
+ conf->app_chuk_conf.tc_offset = APPCONF_CHUK_TC_OFFSET; | |
+ conf->app_chuk_conf.buttons_mirrored = APPCONF_CHUK_BUTTONS_MIRRORED; | |
+ | |
+ conf->app_throttle_conf.adjustable_throttle_enabled = APPCONF_ADJUSTABLE_THROTTLE_ENABLED; | |
+ conf->app_throttle_conf.y1_throttle = APPCONF_Y1_THROTTLE; | |
+ conf->app_throttle_conf.y2_throttle = APPCONF_Y2_THROTTLE; | |
+ conf->app_throttle_conf.y3_throttle = APPCONF_Y3_THROTTLE; | |
+ conf->app_throttle_conf.x1_throttle = APPCONF_X1_THROTTLE; | |
+ conf->app_throttle_conf.x2_throttle = APPCONF_X2_THROTTLE; | |
+ conf->app_throttle_conf.x3_throttle = APPCONF_X3_THROTTLE; | |
+ conf->app_throttle_conf.bezier_reduce_factor = APPCONF_BEZIER_REDUCE_FACTOR; | |
+ conf->app_throttle_conf.y1_neg_throttle = APPCONF_Y1_NEG_THROTTLE; | |
+ conf->app_throttle_conf.y2_neg_throttle = APPCONF_Y2_NEG_THROTTLE; | |
+ conf->app_throttle_conf.y3_neg_throttle = APPCONF_Y3_NEG_THROTTLE; | |
+ conf->app_throttle_conf.x1_neg_throttle = APPCONF_X1_NEG_THROTTLE; | |
+ conf->app_throttle_conf.x2_neg_throttle = APPCONF_X2_NEG_THROTTLE; | |
+ conf->app_throttle_conf.x3_neg_throttle = APPCONF_X3_NEG_THROTTLE; | |
+ conf->app_throttle_conf.bezier_neg_reduce_factor = APPCONF_BEZIER_REDUCE_NEG_FACTOR; | |
+ //new config end | |
} | |
/** | |
@@ -168,6 +207,16 @@ | |
conf->sl_cycle_int_rpm_br = MCCONF_SL_CYCLE_INT_BR; | |
conf->sl_bemf_coupling_k = MCCONF_SL_BEMF_COUPLING_K; | |
+ conf->hall_table[0] = MCCONF_HALL_TAB_0; | |
+ conf->hall_table[1] = MCCONF_HALL_TAB_1; | |
+ conf->hall_table[2] = MCCONF_HALL_TAB_2; | |
+ conf->hall_table[3] = MCCONF_HALL_TAB_3; | |
+ conf->hall_table[4] = MCCONF_HALL_TAB_4; | |
+ conf->hall_table[5] = MCCONF_HALL_TAB_5; | |
+ conf->hall_table[6] = MCCONF_HALL_TAB_6; | |
+ conf->hall_table[7] = MCCONF_HALL_TAB_7; | |
+ conf->hall_sl_erpm = MCCONF_HALL_ERPM; | |
+ | |
conf->foc_current_kp = MCCONF_FOC_CURRENT_KP; | |
conf->foc_current_ki = MCCONF_FOC_CURRENT_KI; | |
conf->foc_f_sw = MCCONF_FOC_F_SW; | |
@@ -189,25 +238,26 @@ | |
conf->foc_sl_openloop_time = MCCONF_FOC_SL_OPENLOOP_TIME; | |
conf->foc_sl_d_current_duty = MCCONF_FOC_SL_D_CURRENT_DUTY; | |
conf->foc_sl_d_current_factor = MCCONF_FOC_SL_D_CURRENT_FACTOR; | |
- | |
- conf->hall_table[0] = MCCONF_HALL_TAB_0; | |
- conf->hall_table[1] = MCCONF_HALL_TAB_1; | |
- conf->hall_table[2] = MCCONF_HALL_TAB_2; | |
- conf->hall_table[3] = MCCONF_HALL_TAB_3; | |
- conf->hall_table[4] = MCCONF_HALL_TAB_4; | |
- conf->hall_table[5] = MCCONF_HALL_TAB_5; | |
- conf->hall_table[6] = MCCONF_HALL_TAB_6; | |
- conf->hall_table[7] = MCCONF_HALL_TAB_7; | |
- conf->hall_sl_erpm = MCCONF_HALL_ERPM; | |
+ conf->foc_hall_table[0] = MCCONF_FOC_HALL_TAB_0; | |
+ conf->foc_hall_table[1] = MCCONF_FOC_HALL_TAB_1; | |
+ conf->foc_hall_table[2] = MCCONF_FOC_HALL_TAB_2; | |
+ conf->foc_hall_table[3] = MCCONF_FOC_HALL_TAB_3; | |
+ conf->foc_hall_table[4] = MCCONF_FOC_HALL_TAB_4; | |
+ conf->foc_hall_table[5] = MCCONF_FOC_HALL_TAB_5; | |
+ conf->foc_hall_table[6] = MCCONF_FOC_HALL_TAB_6; | |
+ conf->foc_hall_table[7] = MCCONF_FOC_HALL_TAB_7; | |
+ conf->foc_sl_erpm = MCCONF_FOC_SL_ERPM; | |
conf->s_pid_kp = MCCONF_S_PID_KP; | |
conf->s_pid_ki = MCCONF_S_PID_KI; | |
conf->s_pid_kd = MCCONF_S_PID_KD; | |
conf->s_pid_min_erpm = MCCONF_S_PID_MIN_RPM; | |
+ conf->s_pid_breaking_enabled = MCCONF_S_PID_BREAKING_ENABLED; | |
conf->p_pid_kp = MCCONF_P_PID_KP; | |
conf->p_pid_ki = MCCONF_P_PID_KI; | |
conf->p_pid_kd = MCCONF_P_PID_KD; | |
+ conf->p_pid_ang_div = MCCONF_P_PID_ANG_DIV; | |
conf->cc_startup_boost_duty = MCCONF_CC_STARTUP_BOOST_DUTY; | |
conf->cc_min_current = MCCONF_CC_MIN_CURRENT; | |
@@ -219,6 +269,10 @@ | |
conf->m_duty_ramp_step_rpm_lim = MCCONF_M_RAMP_STEP_RPM_LIM; | |
conf->m_current_backoff_gain = MCCONF_M_CURRENT_BACKOFF_GAIN; | |
conf->m_encoder_counts = MCCONF_M_ENCODER_COUNTS; | |
+ conf->m_sensor_port_mode = MCCONF_M_SENSOR_PORT_MODE; | |
+ | |
+ conf->use_max_watt_limit = MCCONF_USE_MAX_WATT_LIMIT; | |
+ conf->watts_max = MCCONF_WATT_MAX; | |
} | |
/** | |
@@ -242,6 +296,32 @@ | |
} | |
} | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(app_configuration) / 2);i++) { | |
+ if (EE_ReadVariable(EEPROM_BASE_APPCONF + i, &var) == 0) { | |
+ conf_addr[2 * i] = (var >> 8) & 0xFF; | |
+ conf_addr[2 * i + 1] = var & 0xFF; | |
+ } else { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(app_configuration) / 2);i++) { | |
+ if (EE_ReadVariable(EEPROM_BASE_APPCONF + i, &var) == 0) { | |
+ conf_addr[2 * i] = (var >> 8) & 0xFF; | |
+ conf_addr[2 * i + 1] = var & 0xFF; | |
+ } else { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
// Set the default configuration | |
if (!is_ok) { | |
conf_general_get_default_app_configuration(conf); | |
@@ -277,6 +357,34 @@ | |
break; | |
} | |
} | |
+ | |
+ // try one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(app_configuration) / 2);i++) { | |
+ var = (conf_addr[2 * i] << 8) & 0xFF00; | |
+ var |= conf_addr[2 * i + 1] & 0xFF; | |
+ | |
+ if (EE_WriteVariable(EEPROM_BASE_APPCONF + i, var) != FLASH_COMPLETE) { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
+ // try again one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(app_configuration) / 2);i++) { | |
+ var = (conf_addr[2 * i] << 8) & 0xFF00; | |
+ var |= conf_addr[2 * i + 1] & 0xFF; | |
+ | |
+ if (EE_WriteVariable(EEPROM_BASE_APPCONF + i, var) != FLASH_COMPLETE) { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); | |
utils_sys_unlock_cnt(); | |
@@ -305,6 +413,34 @@ | |
} | |
} | |
+ // try one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(mc_configuration) / 2);i++) { | |
+ if (EE_ReadVariable(EEPROM_BASE_MCCONF + i, &var) == 0) { | |
+ conf_addr[2 * i] = (var >> 8) & 0xFF; | |
+ conf_addr[2 * i + 1] = var & 0xFF; | |
+ } else { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
+ // try another one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(mc_configuration) / 2);i++) { | |
+ if (EE_ReadVariable(EEPROM_BASE_MCCONF + i, &var) == 0) { | |
+ conf_addr[2 * i] = (var >> 8) & 0xFF; | |
+ conf_addr[2 * i + 1] = var & 0xFF; | |
+ } else { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
if (!is_ok) { | |
conf_general_get_default_mc_configuration(conf); | |
} | |
@@ -339,6 +475,34 @@ | |
break; | |
} | |
} | |
+ | |
+ // try one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(mc_configuration) / 2);i++) { | |
+ var = (conf_addr[2 * i] << 8) & 0xFF00; | |
+ var |= conf_addr[2 * i + 1] & 0xFF; | |
+ | |
+ if (EE_WriteVariable(EEPROM_BASE_MCCONF + i, var) != FLASH_COMPLETE) { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
+ | |
+ // try again one more time | |
+ if(is_ok == false){ | |
+ chThdSleepMilliseconds(10); | |
+ for (unsigned int i = 0;i < (sizeof(mc_configuration) / 2);i++) { | |
+ var = (conf_addr[2 * i] << 8) & 0xFF00; | |
+ var |= conf_addr[2 * i + 1] & 0xFF; | |
+ | |
+ if (EE_WriteVariable(EEPROM_BASE_MCCONF + i, var) != FLASH_COMPLETE) { | |
+ is_ok = false; | |
+ break; | |
+ } | |
+ } | |
+ } | |
RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); | |
utils_sys_unlock_cnt(); | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/conf_general.h Raptor2 Sources/bldc-firmware_2_80/conf_general.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/conf_general.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/conf_general.h 2017-04-17 04:06:52.000000000 +0100 | |
@@ -27,7 +27,7 @@ | |
// Firmware version | |
#define FW_VERSION_MAJOR 2 | |
-#define FW_VERSION_MINOR 9 | |
+#define FW_VERSION_MINOR 80 | |
#include "datatypes.h" | |
@@ -38,6 +38,7 @@ | |
// Settings and parameters to override | |
//#define VIN_R1 33000.0 | |
+#define VIN_R1 39000.0 | |
//#define VIN_R2 2200.0 | |
//#define CURRENT_AMP_GAIN 10.0 | |
//#define CURRENT_SHUNT_RES 0.0005 | |
@@ -56,7 +57,7 @@ | |
//#define HW_VERSION_46 // Also for 4.7 | |
//#define HW_VERSION_48 | |
//#define HW_VERSION_49 | |
-#define HW_VERSION_410 // Also for 4.11 | |
+#define HW_VERSION_410 // Also for 4.11 and 4.12 | |
//#define HW_VERSION_R2 | |
//#define HW_VERSION_VICTOR_R1A | |
#endif | |
@@ -64,15 +65,15 @@ | |
/* | |
* Select default user motor configuration | |
*/ | |
-//#define MCCONF_DEFAULT_USER "mcconf_outrunner2.h" | |
//#define MCCONF_DEFAULT_USER "mcconf_sten.h" | |
-//#define MCCONF_DEFAULT_USER "mcconf_foc_erwin.h" | |
-//#define MCCONF_DEFAULT_USER "mcconf_foc_scorpion.h" | |
+//#define MCCONF_DEFAULT_USER "mcconf_sp_540kv.h" | |
+//#define MCCONF_DEFAULT_USER "mcconf_castle_2028.h" | |
/* | |
* Select default user app configuration | |
*/ | |
//#define APPCONF_DEFAULT_USER "appconf_example_ppm.h" | |
+//#define APPCONF_DEFAULT_USER "appconf_custom.h" | |
/* | |
* Select which custom application to use. To configure the default applications and | |
@@ -82,13 +83,6 @@ | |
//#define USE_APP_STEN | |
/* | |
- * Use encoder | |
- */ | |
-#ifndef ENCODER_ENABLE | |
-#define ENCODER_ENABLE 0 | |
-#endif | |
- | |
-/* | |
* Enable CAN-bus | |
*/ | |
#define CAN_ENABLE 1 | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/datatypes.h Raptor2 Sources/bldc-firmware_2_80/datatypes.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/datatypes.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/datatypes.h 2017-04-13 18:02:30.000000000 +0100 | |
@@ -38,6 +38,13 @@ | |
} mc_state; | |
typedef enum { | |
+ CRUISE_CONTROL_MOTOR_SETTINGS = 0, | |
+ CRUISE_CONTROL_BRAKING_DISABLED, | |
+ CRUISE_CONTROL_BRAKING_ENABLED, | |
+ CRUISE_CONTROL_INACTIVE | |
+} ppm_cruise; | |
+ | |
+typedef enum { | |
PWM_MODE_NONSYNCHRONOUS_HISW = 0, // This mode is not recommended | |
PWM_MODE_SYNCHRONOUS, // The recommended and most tested mode | |
PWM_MODE_BIPOLAR // Some glitches occasionally, can kill MOSFETs | |
@@ -56,7 +63,8 @@ | |
typedef enum { | |
FOC_SENSOR_MODE_SENSORLESS = 0, | |
- FOC_SENSOR_MODE_ENCODER | |
+ FOC_SENSOR_MODE_ENCODER, | |
+ FOC_SENSOR_MODE_HALL | |
} mc_foc_sensor_mode; | |
typedef enum { | |
@@ -89,10 +97,17 @@ | |
DISP_POS_MODE_INDUCTANCE, | |
DISP_POS_MODE_OBSERVER, | |
DISP_POS_MODE_ENCODER, | |
- DISP_POS_MODE_ENCODER_POS_ERROR, | |
+ DISP_POS_MODE_PID_POS, | |
+ DISP_POS_MODE_PID_POS_ERROR, | |
DISP_POS_MODE_ENCODER_OBSERVER_ERROR | |
} disp_pos_mode; | |
+typedef enum { | |
+ SENSOR_PORT_MODE_HALL = 0, | |
+ SENSOR_PORT_MODE_ABI, | |
+ SENSOR_PORT_MODE_AS5047_SPI | |
+} sensor_port_mode; | |
+ | |
typedef struct { | |
float cycle_int_limit; | |
float cycle_int_limit_running; | |
@@ -115,6 +130,8 @@ | |
float l_in_current_max; | |
float l_in_current_min; | |
float l_abs_current_max; | |
+ bool use_max_watt_limit; | |
+ float watts_max; | |
float l_min_erpm; | |
float l_max_erpm; | |
float l_max_erpm_fbrake; | |
@@ -169,15 +186,19 @@ | |
float foc_sl_d_current_duty; | |
float foc_sl_d_current_factor; | |
mc_foc_sensor_mode foc_sensor_mode; | |
+ uint8_t foc_hall_table[8]; | |
+ float foc_sl_erpm; | |
// Speed PID | |
float s_pid_kp; | |
float s_pid_ki; | |
float s_pid_kd; | |
float s_pid_min_erpm; | |
+ bool s_pid_breaking_enabled; | |
// Pos PID | |
float p_pid_kp; | |
float p_pid_ki; | |
float p_pid_kd; | |
+ float p_pid_ang_div; | |
// Current controller | |
float cc_startup_boost_duty; | |
float cc_min_current; | |
@@ -189,6 +210,7 @@ | |
float m_duty_ramp_step_rpm_lim; | |
float m_current_backoff_gain; | |
uint32_t m_encoder_counts; | |
+ sensor_port_mode m_sensor_port_mode; | |
} mc_configuration; | |
// Applications to use | |
@@ -213,7 +235,11 @@ | |
PPM_CTRL_TYPE_DUTY, | |
PPM_CTRL_TYPE_DUTY_NOREV, | |
PPM_CTRL_TYPE_PID, | |
- PPM_CTRL_TYPE_PID_NOREV | |
+ PPM_CTRL_TYPE_PID_NOREV, | |
+ PPM_CTRL_TYPE_WATT_NOREV_BRAKE, | |
+ PPM_CTRL_TYPE_PID_NOACCELERATION, | |
+ PPM_CTRL_TYPE_CRUISE_CONTROL_SECONDARY_CHANNEL, | |
+ PPM_CTRL_TYPE_WATT | |
} ppm_control_type; | |
typedef struct { | |
@@ -229,6 +255,12 @@ | |
bool multi_esc; | |
bool tc; | |
float tc_max_diff; | |
+ float pulse_center; | |
+ float tc_offset; | |
+ ppm_cruise cruise_left; | |
+ ppm_cruise cruise_right; | |
+ bool max_erpm_for_dir_active; | |
+ float max_erpm_for_dir; | |
} ppm_config; | |
// ADC control types | |
@@ -239,6 +271,7 @@ | |
ADC_CTRL_TYPE_CURRENT_REV_BUTTON, | |
ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_CENTER, | |
ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_BUTTON, | |
+ ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_ADC, | |
ADC_CTRL_TYPE_DUTY, | |
ADC_CTRL_TYPE_DUTY_REV_CENTER, | |
ADC_CTRL_TYPE_DUTY_REV_BUTTON | |
@@ -266,7 +299,9 @@ | |
typedef enum { | |
CHUK_CTRL_TYPE_NONE = 0, | |
CHUK_CTRL_TYPE_CURRENT, | |
- CHUK_CTRL_TYPE_CURRENT_NOREV | |
+ CHUK_CTRL_TYPE_CURRENT_NOREV, | |
+ CHUK_CTRL_TYPE_WATT, | |
+ CHUK_CTRL_TYPE_WATT_NOREV | |
} chuk_control_type; | |
typedef struct { | |
@@ -280,8 +315,84 @@ | |
bool multi_esc; | |
bool tc; | |
float tc_max_diff; | |
+ float tc_offset; | |
+ bool buttons_mirrored; | |
} chuk_config; | |
+// NRF Datatypes | |
+typedef enum { | |
+ NRF_SPEED_250K = 0, | |
+ NRF_SPEED_1M, | |
+ NRF_SPEED_2M | |
+} NRF_SPEED; | |
+ | |
+typedef enum { | |
+ NRF_POWER_M18DBM = 0, | |
+ NRF_POWER_M12DBM, | |
+ NRF_POWER_M6DBM, | |
+ NRF_POWER_0DBM | |
+} NRF_POWER; | |
+ | |
+typedef enum { | |
+ NRF_AW_3 = 0, | |
+ NRF_AW_4, | |
+ NRF_AW_5 | |
+} NRF_AW; | |
+ | |
+typedef enum { | |
+ NRF_CRC_DISABLED = 0, | |
+ NRF_CRC_1B, | |
+ NRF_CRC_2B | |
+} NRF_CRC; | |
+ | |
+typedef enum { | |
+ NRF_RETR_DELAY_250US = 0, | |
+ NRF_RETR_DELAY_500US, | |
+ NRF_RETR_DELAY_750US, | |
+ NRF_RETR_DELAY_1000US, | |
+ NRF_RETR_DELAY_1250US, | |
+ NRF_RETR_DELAY_1500US, | |
+ NRF_RETR_DELAY_1750US, | |
+ NRF_RETR_DELAY_2000US, | |
+ NRF_RETR_DELAY_2250US, | |
+ NRF_RETR_DELAY_2500US, | |
+ NRF_RETR_DELAY_2750US, | |
+ NRF_RETR_DELAY_3000US, | |
+ NRF_RETR_DELAY_3250US, | |
+ NRF_RETR_DELAY_3500US, | |
+ NRF_RETR_DELAY_3750US, | |
+ NRF_RETR_DELAY_4000US | |
+} NRF_RETR_DELAY; | |
+ | |
+typedef struct { | |
+ NRF_SPEED speed; | |
+ NRF_POWER power; | |
+ NRF_CRC crc_type; | |
+ NRF_RETR_DELAY retry_delay; | |
+ unsigned char retries; | |
+ unsigned char channel; | |
+ unsigned char address[3]; | |
+ bool send_crc_ack; | |
+} nrf_config; | |
+ | |
+typedef struct { | |
+ bool adjustable_throttle_enabled; | |
+ float y1_throttle; | |
+ float y2_throttle; | |
+ float y3_throttle; | |
+ float x1_throttle; | |
+ float x2_throttle; | |
+ float x3_throttle; | |
+ float bezier_reduce_factor; | |
+ float y1_neg_throttle; | |
+ float y2_neg_throttle; | |
+ float y3_neg_throttle; | |
+ float x1_neg_throttle; | |
+ float x2_neg_throttle; | |
+ float x3_neg_throttle; | |
+ float bezier_neg_reduce_factor; | |
+} throttle_config; | |
+ | |
typedef struct { | |
// Settings | |
uint8_t controller_id; | |
@@ -304,6 +415,11 @@ | |
// Nunchuk application settings | |
chuk_config app_chuk_conf; | |
+ | |
+ // NRF application settings | |
+ nrf_config app_nrf_conf; | |
+ | |
+ throttle_config app_throttle_conf; | |
} app_configuration; | |
// Communication commands | |
@@ -335,6 +451,7 @@ | |
COMM_DETECT_MOTOR_R_L, | |
COMM_DETECT_MOTOR_FLUX_LINKAGE, | |
COMM_DETECT_ENCODER, | |
+ COMM_DETECT_HALL_FOC, | |
COMM_REBOOT, | |
COMM_ALIVE, | |
COMM_GET_DECODED_PPM, | |
@@ -342,7 +459,12 @@ | |
COMM_GET_DECODED_CHUK, | |
COMM_FORWARD_CAN, | |
COMM_SET_CHUCK_DATA, | |
- COMM_CUSTOM_APP_DATA | |
+ COMM_CUSTOM_APP_DATA, | |
+ COMM_SET_SPEED_MODE, | |
+ COMM_CHANGE_SPEED_MODE, | |
+ COMM_GET_SPEED_MODE, | |
+ COMM_SET_CURRENT_CONF_AS_DEFAULT, | |
+ COMM_SET_MOTOR_TYPE | |
} COMM_PACKET_ID; | |
// CAN commands | |
@@ -356,7 +478,9 @@ | |
CAN_PACKET_FILL_RX_BUFFER_LONG, | |
CAN_PACKET_PROCESS_RX_BUFFER, | |
CAN_PACKET_PROCESS_SHORT_BUFFER, | |
- CAN_PACKET_STATUS | |
+ CAN_PACKET_STATUS, | |
+ CAN_PACKET_SET_SERVO, | |
+ CAN_PACKET_SET_BRAKE_SERVO | |
} CAN_PACKET_ID; | |
// Logged fault data | |
@@ -403,7 +527,8 @@ | |
systime_t rx_time; | |
float rpm; | |
float current; | |
- float duty; | |
+ int8_t duty; | |
+ ppm_cruise cruise_control_status; | |
} can_status_msg; | |
typedef struct { | |
@@ -431,20 +556,20 @@ | |
float temp_mos2; | |
float temp_mos3; | |
float temp_mos4; | |
- float temp_mos5; | |
- float temp_mos6; | |
- float temp_pcb; | |
- float current_motor; | |
- float current_in; | |
- float rpm; | |
- float duty_now; | |
- float amp_hours; | |
- float amp_hours_charged; | |
- float watt_hours; | |
- float watt_hours_charged; | |
- int tachometer; | |
- int tachometer_abs; | |
- mc_fault_code fault_code; | |
+ float temp_mos5; | |
+ float temp_mos6; | |
+ float temp_pcb; | |
+ float current_motor; | |
+ float current_in; | |
+ float rpm; | |
+ float duty_now; | |
+ float amp_hours; | |
+ float amp_hours_charged; | |
+ float watt_hours; | |
+ float watt_hours_charged; | |
+ int tachometer; | |
+ int tachometer_abs; | |
+ mc_fault_code fault_code; | |
} mc_values; | |
#endif /* DATATYPES_H_ */ | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/eeprom.h Raptor2 Sources/bldc-firmware_2_80/eeprom.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/eeprom.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/eeprom.h 2017-04-13 18:03:20.000000000 +0100 | |
@@ -69,7 +69,7 @@ | |
#define PAGE_FULL ((uint8_t)0x80) | |
/* Variables' number */ | |
-#define NB_OF_VAR ((uint8_t)160) | |
+#define NB_OF_VAR ((uint8_t)255) | |
/* Exported types ------------------------------------------------------------*/ | |
/* Exported macro ------------------------------------------------------------*/ | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/encoder.c Raptor2 Sources/bldc-firmware_2_80/encoder.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/encoder.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/encoder.c 2016-09-19 10:06:24.000000000 +0100 | |
@@ -1,5 +1,5 @@ | |
/* | |
- Copyright 2012-2015 Benjamin Vedder benjamin@vedder.se | |
+ Copyright 2012-2016 Benjamin Vedder benjamin@vedder.se | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
@@ -15,26 +15,64 @@ | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
-/* | |
- * encoder.c | |
- * | |
- * Created on: 7 mar 2015 | |
- * Author: benjamin | |
- */ | |
- | |
#include "encoder.h" | |
#include "ch.h" | |
#include "hal.h" | |
#include "stm32f4xx_conf.h" | |
#include "hw.h" | |
+#include "utils.h" | |
+ | |
+// Defines | |
+#define AS5047P_READ_ANGLECOM (0x3FFF | 0x4000 | 0x8000) // This is just ones | |
+#define AS5047_SAMPLE_RATE_HZ 20000 | |
+ | |
+#define SPI_SW_MISO_GPIO HW_HALL_ENC_GPIO2 | |
+#define SPI_SW_MISO_PIN HW_HALL_ENC_PIN2 | |
+#define SPI_SW_SCK_GPIO HW_HALL_ENC_GPIO1 | |
+#define SPI_SW_SCK_PIN HW_HALL_ENC_PIN1 | |
+#define SPI_SW_CS_GPIO HW_HALL_ENC_GPIO3 | |
+#define SPI_SW_CS_PIN HW_HALL_ENC_PIN3 | |
+ | |
+// Private types | |
+typedef enum { | |
+ ENCODER_MODE_NONE = 0, | |
+ ENCODER_MODE_ABI, | |
+ ENCODER_MODE_AS5047P_SPI | |
+} encoder_mode; | |
// Private variables | |
-static bool index_found; | |
+static bool index_found = false; | |
static uint32_t enc_counts = 10000; | |
+static encoder_mode mode = ENCODER_MODE_NONE; | |
+static float last_enc_angle = 0.0; | |
+ | |
+// Private functions | |
+uint16_t spi_exchange(uint16_t x); | |
+static void spi_transfer(uint16_t *in_buf, const uint16_t *out_buf, int length); | |
+static void spi_begin(void); | |
+static void spi_end(void); | |
+static void spi_delay(void); | |
+ | |
+void encoder_deinit(void) { | |
+ nvicDisableVector(HW_ENC_EXTI_CH); | |
+ nvicDisableVector(HW_ENC_TIM_ISR_CH); | |
+ | |
+ TIM_DeInit(HW_ENC_TIM); | |
+ | |
+ palSetPadMode(SPI_SW_MISO_GPIO, SPI_SW_MISO_PIN, PAL_MODE_INPUT_PULLUP); | |
+ palSetPadMode(SPI_SW_SCK_GPIO, SPI_SW_SCK_PIN, PAL_MODE_INPUT_PULLUP); | |
+ palSetPadMode(SPI_SW_CS_GPIO, SPI_SW_CS_PIN, PAL_MODE_INPUT_PULLUP); | |
-void encoder_init(uint32_t counts) { | |
+ palSetPadMode(HW_HALL_ENC_GPIO1, HW_HALL_ENC_PIN1, PAL_MODE_INPUT_PULLUP); | |
+ palSetPadMode(HW_HALL_ENC_GPIO2, HW_HALL_ENC_PIN2, PAL_MODE_INPUT_PULLUP); | |
+ | |
+ index_found = false; | |
+ mode = ENCODER_MODE_NONE; | |
+ last_enc_angle = 0.0; | |
+} | |
+ | |
+void encoder_init_abi(uint32_t counts) { | |
EXTI_InitTypeDef EXTI_InitStructure; | |
- NVIC_InitTypeDef NVIC_InitStructure; | |
// Initialize variables | |
index_found = false; | |
@@ -61,7 +99,7 @@ | |
TIM_ICPolarity_Rising); | |
TIM_SetAutoreload(HW_ENC_TIM, enc_counts - 1); | |
- TIM_Cmd (HW_ENC_TIM, ENABLE); | |
+ TIM_Cmd(HW_ENC_TIM, ENABLE); | |
// Interrupt on index pulse | |
@@ -76,15 +114,62 @@ | |
EXTI_Init(&EXTI_InitStructure); | |
// Enable and set EXTI Line Interrupt to the highest priority | |
- NVIC_InitStructure.NVIC_IRQChannel = HW_ENC_EXTI_CH; | |
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00; | |
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; | |
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; | |
- NVIC_Init(&NVIC_InitStructure); | |
+ nvicEnableVector(HW_ENC_EXTI_CH, 0); | |
+ | |
+ mode = ENCODER_MODE_ABI; | |
+} | |
+ | |
+void encoder_init_as5047p_spi(void) { | |
+ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; | |
+ | |
+ palSetPadMode(SPI_SW_MISO_GPIO, SPI_SW_MISO_PIN, PAL_MODE_INPUT); | |
+ palSetPadMode(SPI_SW_SCK_GPIO, SPI_SW_SCK_PIN, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); | |
+ palSetPadMode(SPI_SW_CS_GPIO, SPI_SW_CS_PIN, PAL_MODE_OUTPUT_PUSHPULL | PAL_STM32_OSPEED_HIGHEST); | |
+ | |
+ // Enable timer clock | |
+ HW_ENC_TIM_CLK_EN(); | |
+ | |
+ // Time Base configuration | |
+ TIM_TimeBaseStructure.TIM_Prescaler = 0; | |
+ TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; | |
+ TIM_TimeBaseStructure.TIM_Period = ((168000000 / 2 / AS5047_SAMPLE_RATE_HZ) - 1); | |
+ TIM_TimeBaseStructure.TIM_ClockDivision = 0; | |
+ TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; | |
+ TIM_TimeBaseInit(HW_ENC_TIM, &TIM_TimeBaseStructure); | |
+ | |
+ // Enable overflow interrupt | |
+ TIM_ITConfig(HW_ENC_TIM, TIM_IT_Update, ENABLE); | |
+ | |
+ // Enable timer | |
+ TIM_Cmd(HW_ENC_TIM, ENABLE); | |
+ | |
+ nvicEnableVector(HW_ENC_TIM_ISR_CH, 6); | |
+ | |
+ mode = ENCODER_MODE_AS5047P_SPI; | |
+ index_found = true; | |
+} | |
+ | |
+bool encoder_is_configured(void) { | |
+ return mode != ENCODER_MODE_NONE; | |
} | |
float encoder_read_deg(void) { | |
- return ((float)HW_ENC_TIM->CNT * 360.0) / (float)enc_counts; | |
+ static float angle = 0.0; | |
+ | |
+ switch (mode) { | |
+ case ENCODER_MODE_ABI: | |
+ angle = ((float)HW_ENC_TIM->CNT * 360.0) / (float)enc_counts; | |
+ break; | |
+ | |
+ case ENCODER_MODE_AS5047P_SPI: | |
+ angle = last_enc_angle; | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+ | |
+ return angle; | |
} | |
/** | |
@@ -96,6 +181,20 @@ | |
} | |
/** | |
+ * Timer interrupt | |
+ */ | |
+void encoder_tim_isr(void) { | |
+ uint16_t pos; | |
+ | |
+ spi_begin(); | |
+ spi_transfer(&pos, 0, 1); | |
+ spi_end(); | |
+ | |
+ pos &= 0x3FFF; | |
+ last_enc_angle = ((float)pos * 360.0) / 16384.0; | |
+} | |
+ | |
+/** | |
* Set the number of encoder counts. | |
* | |
* @param counts | |
@@ -118,3 +217,53 @@ | |
bool encoder_index_found(void) { | |
return index_found; | |
} | |
+ | |
+// Software SPI | |
+uint16_t spi_exchange(uint16_t x) { | |
+ uint16_t rx; | |
+ spi_transfer(&rx, &x, 1); | |
+ return rx; | |
+} | |
+ | |
+static void spi_transfer(uint16_t *in_buf, const uint16_t *out_buf, int length) { | |
+ for (int i = 0;i < length;i++) { | |
+ uint16_t send = out_buf ? out_buf[i] : 0xFFFF; | |
+ uint16_t recieve = 0; | |
+ | |
+ for (int bit = 0;bit < 16;bit++) { | |
+ //palWritePad(HW_SPI_PORT_MOSI, HW_SPI_PIN_MOSI, send >> 15); | |
+ send <<= 1; | |
+ | |
+ spi_delay(); | |
+ palSetPad(SPI_SW_SCK_GPIO, SPI_SW_SCK_PIN); | |
+ spi_delay(); | |
+ | |
+ recieve <<= 1; | |
+ if (palReadPad(SPI_SW_MISO_GPIO, SPI_SW_MISO_PIN)) { | |
+ recieve |= 1; | |
+ } | |
+ | |
+ palClearPad(SPI_SW_SCK_GPIO, SPI_SW_SCK_PIN); | |
+ spi_delay(); | |
+ } | |
+ | |
+ if (in_buf) { | |
+ in_buf[i] = recieve; | |
+ } | |
+ } | |
+} | |
+ | |
+static void spi_begin(void) { | |
+ palClearPad(SPI_SW_CS_GPIO, SPI_SW_CS_PIN); | |
+} | |
+ | |
+static void spi_end(void) { | |
+ palSetPad(SPI_SW_CS_GPIO, SPI_SW_CS_PIN); | |
+} | |
+ | |
+static void spi_delay(void) { | |
+ __NOP(); | |
+ __NOP(); | |
+ __NOP(); | |
+ __NOP(); | |
+} | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/encoder.h Raptor2 Sources/bldc-firmware_2_80/encoder.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/encoder.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/encoder.h 2016-09-19 10:06:22.000000000 +0100 | |
@@ -28,9 +28,13 @@ | |
#include "conf_general.h" | |
// Functions | |
-void encoder_init(uint32_t counts); | |
+void encoder_deinit(void); | |
+void encoder_init_abi(uint32_t counts); | |
+void encoder_init_as5047p_spi(void); | |
+bool encoder_is_configured(void); | |
float encoder_read_deg(void); | |
void encoder_reset(void); | |
+void encoder_tim_isr(void); | |
void encoder_set_counts(uint32_t counts); | |
bool encoder_index_found(void); | |
Only in Raptor2 Sources/bldc-firmware_2_80: gpl.txt | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/halconf.h Raptor2 Sources/bldc-firmware_2_80/halconf.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/halconf.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/halconf.h 2016-09-19 10:06:16.000000000 +0100 | |
@@ -146,7 +146,7 @@ | |
* @brief Enables the SPI subsystem. | |
*/ | |
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) | |
-#define HAL_USE_SPI FALSE | |
+#define HAL_USE_SPI TRUE | |
#endif | |
/** | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_40.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_40.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_40.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_40.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -146,6 +146,8 @@ | |
#define HW_ENC_EXTI_CH EXTI9_5_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line8 | |
#define HW_ENC_EXTI_ISR_VEC EXTI9_5_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN HW_ICU_GPIO | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_410.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_410.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_410.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_410.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -148,6 +148,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN GPIOA | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_45.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_45.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_45.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_45.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -146,6 +146,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN HW_ICU_GPIO | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_46.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_46.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_46.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_46.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -154,6 +154,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN HW_ICU_GPIO | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_48.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_48.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_48.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_48.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -148,6 +148,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN GPIOB | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_49.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_49.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_49.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_49.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -148,6 +148,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN GPIOB | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_r2.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_r2.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_r2.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_r2.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -156,6 +156,8 @@ | |
#define HW_ENC_EXTI_CH EXTI9_5_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line8 | |
#define HW_ENC_EXTI_ISR_VEC EXTI9_5_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM3_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM3_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN HW_ICU_GPIO | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_victor_r1a.h Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_victor_r1a.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/hwconf/hw_victor_r1a.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/hwconf/hw_victor_r1a.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -146,6 +146,8 @@ | |
#define HW_ENC_EXTI_CH EXTI15_10_IRQn | |
#define HW_ENC_EXTI_LINE EXTI_Line11 | |
#define HW_ENC_EXTI_ISR_VEC EXTI15_10_IRQHandler | |
+#define HW_ENC_TIM_ISR_CH TIM4_IRQn | |
+#define HW_ENC_TIM_ISR_VEC TIM4_IRQHandler | |
// NRF pins | |
#define NRF_PORT_CSN HW_ICU_GPIO | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/irq_handlers.c Raptor2 Sources/bldc-firmware_2_80/irq_handlers.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/irq_handlers.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/irq_handlers.c 2016-09-19 10:06:12.000000000 +0100 | |
@@ -19,7 +19,6 @@ | |
#include "hal.h" | |
#include "stm32f4xx_conf.h" | |
#include "isr_vector_table.h" | |
-#include "main.h" | |
#include "mc_interface.h" | |
#include "servo.h" | |
#include "hw.h" | |
@@ -49,3 +48,12 @@ | |
EXTI_ClearITPendingBit(HW_ENC_EXTI_LINE); | |
} | |
} | |
+ | |
+CH_IRQ_HANDLER(HW_ENC_TIM_ISR_VEC) { | |
+ if (TIM_GetITStatus(HW_ENC_TIM, TIM_IT_Update) != RESET) { | |
+ encoder_tim_isr(); | |
+ | |
+ // Clear the IT pending bit | |
+ TIM_ClearITPendingBit(HW_ENC_TIM, TIM_IT_Update); | |
+ } | |
+} | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/main.c Raptor2 Sources/bldc-firmware_2_80/main.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/main.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/main.c 2016-09-19 10:05:50.000000000 +0100 | |
@@ -24,7 +24,6 @@ | |
#include <string.h> | |
#include <stdlib.h> | |
-#include "main.h" | |
#include "mc_interface.h" | |
#include "mcpwm.h" | |
#include "mcpwm_foc.h" | |
@@ -68,48 +67,12 @@ | |
* | |
*/ | |
-/* | |
- * Notes: | |
- * | |
- * Disable USB VBUS sensing: | |
- * ChibiOS-RT-master/os/hal/platforms/STM32/OTGv1/usb_lld.c | |
- * | |
- * change | |
- * otgp->GCCFG = GCCFG_VBUSASEN | GCCFG_VBUSBSEN | GCCFG_PWRDWN; | |
- * to | |
- * otgp->GCCFG = GCCFG_NOVBUSSENS | GCCFG_PWRDWN; | |
- * | |
- * This should be handled automatically with the latest version of | |
- * ChibiOS since I have added an option to the makefile. | |
- * | |
- */ | |
- | |
// Private variables | |
-#define ADC_SAMPLE_MAX_LEN 2000 | |
-static volatile int16_t curr0_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t curr1_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t ph1_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t ph2_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t ph3_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t vzero_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile uint8_t status_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t curr_fir_samples[ADC_SAMPLE_MAX_LEN]; | |
-static volatile int16_t f_sw_samples[ADC_SAMPLE_MAX_LEN]; | |
- | |
-static volatile int sample_len = 1000; | |
-static volatile int sample_int = 1; | |
-static volatile int sample_ready = 1; | |
-static volatile int sample_now = 0; | |
-static volatile int sample_at_start = 0; | |
-static volatile int start_comm = 0; | |
-static volatile float main_last_adc_duration = 0.0; | |
+ | |
static THD_WORKING_AREA(periodic_thread_wa, 1024); | |
-static THD_WORKING_AREA(sample_send_thread_wa, 1024); | |
static THD_WORKING_AREA(timer_thread_wa, 128); | |
-static thread_t *sample_send_tp; | |
- | |
static THD_FUNCTION(periodic_thread, arg) { | |
(void)arg; | |
@@ -147,8 +110,12 @@ | |
commands_send_rotor_pos(encoder_read_deg()); | |
break; | |
- case DISP_POS_MODE_ENCODER_POS_ERROR: | |
- commands_send_rotor_pos(utils_angle_difference(mc_interface_get_pos_set(), encoder_read_deg())); | |
+ case DISP_POS_MODE_PID_POS: | |
+ commands_send_rotor_pos(mc_interface_get_pid_pos_now()); | |
+ break; | |
+ | |
+ case DISP_POS_MODE_PID_POS_ERROR: | |
+ commands_send_rotor_pos(utils_angle_difference(mc_interface_get_pid_pos_set(), mc_interface_get_pid_pos_now())); | |
break; | |
default: | |
@@ -174,43 +141,6 @@ | |
} | |
} | |
-static THD_FUNCTION(sample_send_thread, arg) { | |
- (void)arg; | |
- | |
- chRegSetThreadName("Main sample"); | |
- | |
- sample_send_tp = chThdGetSelfX(); | |
- | |
- for(;;) { | |
- chEvtWaitAny((eventmask_t) 1); | |
- | |
- for (int i = 0;i < sample_len;i++) { | |
- uint8_t buffer[20]; | |
- int index = 0; | |
- | |
- buffer[index++] = curr0_samples[i] >> 8; | |
- buffer[index++] = curr0_samples[i]; | |
- buffer[index++] = curr1_samples[i] >> 8; | |
- buffer[index++] = curr1_samples[i]; | |
- buffer[index++] = ph1_samples[i] >> 8; | |
- buffer[index++] = ph1_samples[i]; | |
- buffer[index++] = ph2_samples[i] >> 8; | |
- buffer[index++] = ph2_samples[i]; | |
- buffer[index++] = ph3_samples[i] >> 8; | |
- buffer[index++] = ph3_samples[i]; | |
- buffer[index++] = vzero_samples[i] >> 8; | |
- buffer[index++] = vzero_samples[i]; | |
- buffer[index++] = status_samples[i]; | |
- buffer[index++] = curr_fir_samples[i] >> 8; | |
- buffer[index++] = curr_fir_samples[i]; | |
- buffer[index++] = f_sw_samples[i] >> 8; | |
- buffer[index++] = f_sw_samples[i]; | |
- | |
- commands_send_samples(buffer, index); | |
- } | |
- } | |
-} | |
- | |
static THD_FUNCTION(timer_thread, arg) { | |
(void)arg; | |
@@ -222,85 +152,6 @@ | |
} | |
} | |
-/* | |
- * Called every time new ADC values are available. Note that | |
- * the ADC is initialized from mcpwm.c | |
- */ | |
-void main_dma_adc_handler(void) { | |
- ledpwm_update_pwm(); | |
- | |
- if (sample_at_start && (mc_interface_get_state() == MC_STATE_RUNNING || | |
- start_comm != mcpwm_get_comm_step())) { | |
- sample_now = 0; | |
- sample_ready = 0; | |
- sample_at_start = 0; | |
- } | |
- | |
- static int a = 0; | |
- if (!sample_ready) { | |
- a++; | |
- if (a >= sample_int) { | |
- a = 0; | |
- | |
- if (mc_interface_get_state() == MC_STATE_DETECTING) { | |
- curr0_samples[sample_now] = (int16_t)mcpwm_detect_currents[mcpwm_get_comm_step() - 1]; | |
- curr1_samples[sample_now] = (int16_t)mcpwm_detect_currents_diff[mcpwm_get_comm_step() - 1]; | |
- | |
- ph1_samples[sample_now] = (int16_t)mcpwm_detect_voltages[0]; | |
- ph2_samples[sample_now] = (int16_t)mcpwm_detect_voltages[1]; | |
- ph3_samples[sample_now] = (int16_t)mcpwm_detect_voltages[2]; | |
- } else { | |
- curr0_samples[sample_now] = ADC_curr_norm_value[0]; | |
- curr1_samples[sample_now] = ADC_curr_norm_value[1]; | |
- | |
- ph1_samples[sample_now] = ADC_V_L1 - mcpwm_vzero; | |
- ph2_samples[sample_now] = ADC_V_L2 - mcpwm_vzero; | |
- ph3_samples[sample_now] = ADC_V_L3 - mcpwm_vzero; | |
- } | |
- | |
- vzero_samples[sample_now] = mcpwm_vzero; | |
- | |
- curr_fir_samples[sample_now] = (int16_t)(mc_interface_get_tot_current() * 100.0); | |
- f_sw_samples[sample_now] = (int16_t)(mc_interface_get_switching_frequency_now() / 10.0); | |
- | |
- status_samples[sample_now] = mcpwm_get_comm_step() | (mcpwm_read_hall_phase() << 3); | |
- | |
- sample_now++; | |
- | |
- if (sample_now == sample_len) { | |
- sample_ready = 1; | |
- sample_now = 0; | |
- chSysLockFromISR(); | |
- chEvtSignalI(sample_send_tp, (eventmask_t) 1); | |
- chSysUnlockFromISR(); | |
- } | |
- | |
- main_last_adc_duration = mcpwm_get_last_adc_isr_duration(); | |
- } | |
- } | |
-} | |
- | |
-float main_get_last_adc_isr_duration(void) { | |
- return main_last_adc_duration; | |
-} | |
- | |
-void main_sample_print_data(bool at_start, uint16_t len, uint8_t decimation) { | |
- if (len > ADC_SAMPLE_MAX_LEN) { | |
- len = ADC_SAMPLE_MAX_LEN; | |
- } | |
- | |
- sample_len = len; | |
- sample_int = decimation; | |
- | |
- if (at_start) { | |
- sample_at_start = 1; | |
- start_comm = mcpwm_get_comm_step(); | |
- } else { | |
- sample_now = 0; | |
- sample_ready = 0; | |
- } | |
-} | |
- | |
int main(void) { | |
halInit(); | |
chSysInit(); | |
@@ -316,11 +167,6 @@ | |
mc_configuration mcconf; | |
conf_general_read_mc_configuration(&mcconf); | |
- | |
-#if ENCODER_ENABLE | |
- encoder_init(mcconf.m_encoder_counts); | |
-#endif | |
- | |
mc_interface_init(&mcconf); | |
commands_init(); | |
@@ -352,14 +198,13 @@ | |
// Threads | |
chThdCreateStatic(periodic_thread_wa, sizeof(periodic_thread_wa), NORMALPRIO, periodic_thread, NULL); | |
- chThdCreateStatic(sample_send_thread_wa, sizeof(sample_send_thread_wa), NORMALPRIO - 1, sample_send_thread, NULL); | |
chThdCreateStatic(timer_thread_wa, sizeof(timer_thread_wa), NORMALPRIO, timer_thread, NULL); | |
for(;;) { | |
chThdSleepMilliseconds(10); | |
-#if ENCODER_ENABLE | |
-// comm_can_set_pos(0, encoder_read_deg()); | |
-#endif | |
+ if (encoder_is_configured()) { | |
+ // comm_can_set_pos(0, encoder_read_deg()); | |
+ } | |
} | |
} | |
Only in bldc-90986c31defe50830b4795a388ee5b2687dc2516: main.h | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/mc_interface.c Raptor2 Sources/bldc-firmware_2_80/mc_interface.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/mc_interface.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mc_interface.c 2017-06-16 22:00:36.000000000 +0100 | |
@@ -25,13 +25,15 @@ | |
#include "mc_interface.h" | |
#include "mcpwm.h" | |
#include "mcpwm_foc.h" | |
-#include "main.h" | |
+#include "ledpwm.h" | |
#include "stm32f4xx_conf.h" | |
#include "hw.h" | |
#include "terminal.h" | |
#include "utils.h" | |
#include "ch.h" | |
#include "hal.h" | |
+#include "commands.h" | |
+#include "encoder.h" | |
#include <math.h> | |
// Global variables | |
@@ -39,21 +41,43 @@ | |
volatile int ADC_curr_norm_value[3]; | |
// Private variables | |
-static volatile mc_configuration conf; | |
-static mc_fault_code fault_now; | |
-static int ignore_iterations; | |
-static volatile unsigned int cycles_running; | |
-static volatile bool lock_enabled; | |
-static volatile bool lock_override_once; | |
-static volatile float motor_current_sum; | |
-static volatile float input_current_sum; | |
-static volatile float motor_current_iterations; | |
-static volatile float input_current_iterations; | |
-static volatile float amp_seconds; | |
-static volatile float amp_seconds_charged; | |
-static volatile float watt_seconds; | |
-static volatile float watt_seconds_charged; | |
-static volatile float position_set; | |
+static volatile mc_configuration m_conf; | |
+static volatile mc_configuration m_conf_original; | |
+static mc_fault_code m_fault_now; | |
+static int m_ignore_iterations; | |
+static volatile unsigned int m_cycles_running; | |
+static volatile bool m_lock_enabled; | |
+static volatile bool m_lock_override_once; | |
+static volatile float m_motor_current_sum; | |
+static volatile float m_input_current_sum; | |
+static volatile float m_motor_current_iterations; | |
+static volatile float m_input_current_iterations; | |
+static volatile float m_amp_seconds; | |
+static volatile float m_amp_seconds_charged; | |
+static volatile float m_watt_seconds; | |
+static volatile float m_watt_seconds_charged; | |
+static volatile float m_position_set; | |
+// new | |
+static volatile ppm_cruise cruise_control_status; | |
+ | |
+// Sampling variables | |
+#define ADC_SAMPLE_MAX_LEN 2000 | |
+static volatile int16_t m_curr0_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_curr1_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_ph1_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_ph2_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_ph3_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_vzero_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile uint8_t m_status_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_curr_fir_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int16_t m_f_sw_samples[ADC_SAMPLE_MAX_LEN]; | |
+static volatile int m_sample_len; | |
+static volatile int m_sample_int; | |
+static volatile int m_sample_ready; | |
+static volatile int m_sample_now; | |
+static volatile int m_sample_at_start; | |
+static volatile int m_start_comm; | |
+static volatile float m_last_adc_duration_sample; | |
// Private functions | |
static void update_override_limits(volatile mc_configuration *conf); | |
@@ -64,36 +88,66 @@ | |
// Threads | |
static THD_WORKING_AREA(timer_thread_wa, 1024); | |
static THD_FUNCTION(timer_thread, arg); | |
+static THD_WORKING_AREA(sample_send_thread_wa, 1024); | |
+static THD_FUNCTION(sample_send_thread, arg); | |
+static thread_t *sample_send_tp; | |
void mc_interface_init(mc_configuration *configuration) { | |
- conf = *configuration; | |
- fault_now = FAULT_CODE_NONE; | |
- ignore_iterations = 0; | |
- cycles_running = 0; | |
- lock_enabled = false; | |
- lock_override_once = false; | |
- motor_current_sum = 0.0; | |
- input_current_sum = 0.0; | |
- motor_current_iterations = 0.0; | |
- input_current_iterations = 0.0; | |
- amp_seconds = 0.0; | |
- amp_seconds_charged = 0.0; | |
- watt_seconds = 0.0; | |
- watt_seconds_charged = 0.0; | |
- position_set = 0.0; | |
+ m_conf = *configuration; | |
+ m_conf_original = *configuration; | |
+ m_fault_now = FAULT_CODE_NONE; | |
+ m_ignore_iterations = 0; | |
+ m_cycles_running = 0; | |
+ m_lock_enabled = false; | |
+ m_lock_override_once = false; | |
+ m_motor_current_sum = 0.0; | |
+ m_input_current_sum = 0.0; | |
+ m_motor_current_iterations = 0.0; | |
+ m_input_current_iterations = 0.0; | |
+ m_amp_seconds = 0.0; | |
+ m_amp_seconds_charged = 0.0; | |
+ m_watt_seconds = 0.0; | |
+ m_watt_seconds_charged = 0.0; | |
+ m_position_set = 0.0; | |
+ m_last_adc_duration_sample = 0.0; | |
+ cruise_control_status = CRUISE_CONTROL_INACTIVE; | |
+ | |
+ m_sample_len = 1000; | |
+ m_sample_int = 1; | |
+ m_sample_ready = 1; | |
+ m_sample_now = 0; | |
+ m_sample_at_start = 0; | |
+ m_start_comm = 0; | |
// Start threads | |
chThdCreateStatic(timer_thread_wa, sizeof(timer_thread_wa), NORMALPRIO, timer_thread, NULL); | |
+ chThdCreateStatic(sample_send_thread_wa, sizeof(sample_send_thread_wa), NORMALPRIO - 1, sample_send_thread, NULL); | |
+ | |
+ // Initialize encoder | |
+#if !WS2811_ENABLE | |
+ switch (m_conf.m_sensor_port_mode) { | |
+ case SENSOR_PORT_MODE_ABI: | |
+ encoder_init_abi(m_conf.m_encoder_counts); | |
+ break; | |
+ | |
+ case SENSOR_PORT_MODE_AS5047_SPI: | |
+ encoder_init_as5047p_spi(); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+#endif | |
// Initialize selected implementation | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
- mcpwm_init(&conf); | |
+ mcpwm_init(&m_conf); | |
break; | |
case MOTOR_TYPE_FOC: | |
- mcpwm_foc_init(&conf); | |
+ mcpwm_foc_init(&m_conf); | |
break; | |
default: | |
@@ -102,34 +156,56 @@ | |
} | |
const volatile mc_configuration* mc_interface_get_configuration(void) { | |
- return &conf; | |
+ return &m_conf; | |
} | |
void mc_interface_set_configuration(mc_configuration *configuration) { | |
- if (conf.motor_type == MOTOR_TYPE_FOC | |
+#if !WS2811_ENABLE | |
+ if (m_conf.m_sensor_port_mode != configuration->m_sensor_port_mode) { | |
+ encoder_deinit(); | |
+ switch (configuration->m_sensor_port_mode) { | |
+ case SENSOR_PORT_MODE_ABI: | |
+ encoder_init_abi(configuration->m_encoder_counts); | |
+ break; | |
+ | |
+ case SENSOR_PORT_MODE_AS5047_SPI: | |
+ encoder_init_as5047p_spi(); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+ } | |
+ | |
+ if (configuration->m_sensor_port_mode == SENSOR_PORT_MODE_ABI) { | |
+ encoder_set_counts(configuration->m_encoder_counts); | |
+ } | |
+#endif | |
+ | |
+ if (m_conf.motor_type == MOTOR_TYPE_FOC | |
&& configuration->motor_type != MOTOR_TYPE_FOC) { | |
mcpwm_foc_deinit(); | |
- conf = *configuration; | |
- mcpwm_init(&conf); | |
- } else if (conf.motor_type != MOTOR_TYPE_FOC | |
+ m_conf = *configuration; | |
+ mcpwm_init(&m_conf); | |
+ } else if (m_conf.motor_type != MOTOR_TYPE_FOC | |
&& configuration->motor_type == MOTOR_TYPE_FOC) { | |
mcpwm_deinit(); | |
- conf = *configuration; | |
- mcpwm_foc_init(&conf); | |
+ m_conf = *configuration; | |
+ mcpwm_foc_init(&m_conf); | |
} else { | |
- conf = *configuration; | |
+ m_conf = *configuration; | |
} | |
- update_override_limits(&conf); | |
+ update_override_limits(&m_conf); | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
- mcpwm_set_configuration(&conf); | |
+ mcpwm_set_configuration(&m_conf); | |
break; | |
case MOTOR_TYPE_FOC: | |
- mcpwm_foc_set_configuration(&conf); | |
+ mcpwm_foc_set_configuration(&m_conf); | |
break; | |
default: | |
@@ -139,7 +215,7 @@ | |
bool mc_interface_dccal_done(void) { | |
bool ret = false; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_is_dccal_done(); | |
@@ -170,25 +246,25 @@ | |
* Lock the control by disabling all control commands. | |
*/ | |
void mc_interface_lock(void) { | |
- lock_enabled = true; | |
+ m_lock_enabled = true; | |
} | |
/** | |
* Unlock all control commands. | |
*/ | |
void mc_interface_unlock(void) { | |
- lock_enabled = false; | |
+ m_lock_enabled = false; | |
} | |
/** | |
* Allow just one motor control command in the locked state. | |
*/ | |
void mc_interface_lock_override_once(void) { | |
- lock_override_once = true; | |
+ m_lock_override_once = true; | |
} | |
mc_fault_code mc_interface_get_fault(void) { | |
- return fault_now; | |
+ return m_fault_now; | |
} | |
const char* mc_interface_fault_to_string(mc_fault_code fault) { | |
@@ -206,7 +282,7 @@ | |
mc_state mc_interface_get_state(void) { | |
mc_state ret = MC_STATE_OFF; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_state(); | |
@@ -228,7 +304,7 @@ | |
return; | |
} | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_duty(dutyCycle); | |
@@ -248,7 +324,7 @@ | |
return; | |
} | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_duty_noramp(dutyCycle); | |
@@ -268,7 +344,7 @@ | |
return; | |
} | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_pid_speed(rpm); | |
@@ -283,14 +359,43 @@ | |
} | |
} | |
+void mc_interface_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status) { | |
+ if (mc_interface_try_input()) { | |
+ return; | |
+ } | |
+ | |
+ switch (m_conf.motor_type) { | |
+ case MOTOR_TYPE_BLDC: | |
+ case MOTOR_TYPE_DC: | |
+ mcpwm_set_pid_speed_with_cruise_status(rpm, cruise_status); | |
+ break; | |
+ | |
+ case MOTOR_TYPE_FOC: | |
+ mcpwm_foc_set_pid_speed_with_cruise_status(rpm, cruise_status); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+} | |
+ | |
+ppm_cruise mc_interface_get_cruise_control_status(void){ | |
+ return cruise_control_status; | |
+} | |
+ | |
+// true = active false = inactive | |
+void mc_interface_set_cruise_control_status(ppm_cruise status){ | |
+ cruise_control_status = status; | |
+} | |
+ | |
void mc_interface_set_pid_pos(float pos) { | |
if (mc_interface_try_input()) { | |
return; | |
} | |
- position_set = pos; | |
+ m_position_set = pos; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_pid_pos(pos); | |
@@ -310,7 +415,7 @@ | |
return; | |
} | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_current(current); | |
@@ -330,7 +435,75 @@ | |
return; | |
} | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
+ case MOTOR_TYPE_BLDC: | |
+ case MOTOR_TYPE_DC: | |
+ mcpwm_set_brake_current(current); | |
+ break; | |
+ | |
+ case MOTOR_TYPE_FOC: | |
+ mcpwm_foc_set_brake_current(current); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+} | |
+ | |
+void mc_interface_set_servo(float servo_val, bool use_min_current) { | |
+ if (mc_interface_try_input()) { | |
+ return; | |
+ } | |
+ | |
+ float current = 0.0; | |
+ | |
+ if (servo_val > 0.0){ | |
+ if (m_conf.use_max_watt_limit) { | |
+ current = utils_smallest_of_2(servo_val * m_conf.l_current_max, | |
+ servo_val * (m_conf.watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } else { | |
+ current = utils_smallest_of_2(servo_val * m_conf.l_current_max, | |
+ servo_val * m_conf.l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation()); | |
+ } | |
+ if (use_min_current) { | |
+ current = utils_highest_of_2(current, m_conf.cc_min_current); | |
+ } | |
+ } else if (servo_val < 0.0){ | |
+ if (m_conf.use_max_watt_limit) { | |
+ current = -utils_smallest_of_2(fabsf(servo_val * m_conf.l_current_min), | |
+ fabsf(servo_val * (m_conf.watts_max / GET_INPUT_VOLTAGE() / mc_interface_get_duty_cycle_for_watt_calculation()))); | |
+ } else { | |
+ current = -utils_smallest_of_2(fabsf(servo_val * m_conf.l_current_min), | |
+ fabsf(servo_val * m_conf.l_in_current_max / mc_interface_get_duty_cycle_for_watt_calculation())); | |
+ } | |
+ if (use_min_current) { | |
+ current = utils_smallest_of_2(current, -m_conf.cc_min_current); | |
+ } | |
+ } | |
+ | |
+ switch (m_conf.motor_type) { | |
+ case MOTOR_TYPE_BLDC: | |
+ case MOTOR_TYPE_DC: | |
+ mcpwm_set_current(current); | |
+ break; | |
+ | |
+ case MOTOR_TYPE_FOC: | |
+ mcpwm_foc_set_current(current); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+} | |
+ | |
+void mc_interface_set_brake_servo(float servo_val) { | |
+ if (mc_interface_try_input()) { | |
+ return; | |
+ } | |
+ | |
+ float current = servo_val * fabsf(m_conf.l_current_min); | |
+ | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_set_brake_current(current); | |
@@ -356,13 +529,34 @@ | |
mc_interface_set_current(0.0); | |
} | |
+float mc_interface_get_duty_cycle_for_watt_calculation(void) { | |
+ float actual_duty; | |
+ | |
+ if (m_conf.motor_type == MOTOR_TYPE_FOC) { | |
+ //float battery_current = mcpwm_foc_get_tot_current_in_filtered(); | |
+ //float motor_current = mcpwm_foc_get_tot_current_filtered(); | |
+ | |
+ //if (fabsf(battery_current) > 1.0 && fabsf(motor_current) > 1.0) { | |
+ // actual_duty = fabsf(battery_current / motor_current); | |
+ //} else { | |
+ actual_duty = fabsf(mcpwm_foc_get_duty_cycle_now()) * 0.86602540378; | |
+ //} | |
+ } else { | |
+ actual_duty = fabsf(mc_interface_get_duty_cycle_now()); | |
+ } | |
+ if (actual_duty < m_conf.l_min_duty) { | |
+ return m_conf.l_min_duty; | |
+ } | |
+ return actual_duty; | |
+} | |
+ | |
/** | |
* Stop the motor and use braking. | |
*/ | |
float mc_interface_get_duty_cycle_set(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_duty_cycle_set(); | |
@@ -382,7 +576,7 @@ | |
float mc_interface_get_duty_cycle_now(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_duty_cycle_now(); | |
@@ -399,17 +593,17 @@ | |
return ret; | |
} | |
-float mc_interface_get_switching_frequency_now(void) { | |
+float mc_interface_get_sampling_frequency_now(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_switching_frequency_now(); | |
break; | |
case MOTOR_TYPE_FOC: | |
- ret = mcpwm_foc_get_switching_frequency_now(); | |
+ ret = mcpwm_foc_get_switching_frequency_now() / 2.0; | |
break; | |
default: | |
@@ -422,7 +616,7 @@ | |
float mc_interface_get_rpm(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_rpm(); | |
@@ -449,10 +643,10 @@ | |
* The amount of amp hours drawn. | |
*/ | |
float mc_interface_get_amp_hours(bool reset) { | |
- float val = amp_seconds / 3600; | |
+ float val = m_amp_seconds / 3600; | |
if (reset) { | |
- amp_seconds = 0.0; | |
+ m_amp_seconds = 0.0; | |
} | |
return val; | |
@@ -468,10 +662,10 @@ | |
* The amount of amp hours fed back. | |
*/ | |
float mc_interface_get_amp_hours_charged(bool reset) { | |
- float val = amp_seconds_charged / 3600; | |
+ float val = m_amp_seconds_charged / 3600; | |
if (reset) { | |
- amp_seconds_charged = 0.0; | |
+ m_amp_seconds_charged = 0.0; | |
} | |
return val; | |
@@ -487,10 +681,10 @@ | |
* The amount of watt hours drawn. | |
*/ | |
float mc_interface_get_watt_hours(bool reset) { | |
- float val = watt_seconds / 3600; | |
+ float val = m_watt_seconds / 3600; | |
if (reset) { | |
- amp_seconds = 0.0; | |
+ m_amp_seconds = 0.0; | |
} | |
return val; | |
@@ -506,10 +700,10 @@ | |
* The amount of watt hours fed back. | |
*/ | |
float mc_interface_get_watt_hours_charged(bool reset) { | |
- float val = watt_seconds_charged / 3600; | |
+ float val = m_watt_seconds_charged / 3600; | |
if (reset) { | |
- watt_seconds_charged = 0.0; | |
+ m_watt_seconds_charged = 0.0; | |
} | |
return val; | |
@@ -518,7 +712,7 @@ | |
float mc_interface_get_tot_current(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current(); | |
@@ -538,7 +732,7 @@ | |
float mc_interface_get_tot_current_filtered(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current_filtered(); | |
@@ -558,7 +752,7 @@ | |
float mc_interface_get_tot_current_directional(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current_directional(); | |
@@ -578,7 +772,7 @@ | |
float mc_interface_get_tot_current_directional_filtered(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current_directional_filtered(); | |
@@ -598,7 +792,7 @@ | |
float mc_interface_get_tot_current_in(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current_in(); | |
@@ -618,7 +812,7 @@ | |
float mc_interface_get_tot_current_in_filtered(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tot_current_in_filtered(); | |
@@ -638,7 +832,7 @@ | |
int mc_interface_get_tachometer_value(bool reset) { | |
int ret = 0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tachometer_value(reset); | |
@@ -658,7 +852,7 @@ | |
int mc_interface_get_tachometer_abs_value(bool reset) { | |
int ret = 0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_tachometer_abs_value(reset); | |
@@ -678,7 +872,7 @@ | |
float mc_interface_get_last_inj_adc_isr_duration(void) { | |
float ret = 0.0; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
ret = mcpwm_get_last_inj_adc_isr_duration(); | |
@@ -696,21 +890,62 @@ | |
} | |
float mc_interface_read_reset_avg_motor_current(void) { | |
- float res = motor_current_sum / motor_current_iterations; | |
- motor_current_sum = 0; | |
- motor_current_iterations = 0; | |
+ float res = m_motor_current_sum / m_motor_current_iterations; | |
+ m_motor_current_sum = 0; | |
+ m_motor_current_iterations = 0; | |
return res; | |
} | |
float mc_interface_read_reset_avg_input_current(void) { | |
- float res = input_current_sum / input_current_iterations; | |
- input_current_sum = 0; | |
- input_current_iterations = 0; | |
+ float res = m_input_current_sum / m_input_current_iterations; | |
+ m_input_current_sum = 0; | |
+ m_input_current_iterations = 0; | |
return res; | |
} | |
-float mc_interface_get_pos_set(void) { | |
- return position_set; | |
+float mc_interface_get_pid_pos_set(void) { | |
+ return m_position_set; | |
+} | |
+ | |
+float mc_interface_get_pid_pos_now(void) { | |
+ float ret = 0.0; | |
+ | |
+ switch (m_conf.motor_type) { | |
+ case MOTOR_TYPE_BLDC: | |
+ case MOTOR_TYPE_DC: | |
+ ret = encoder_read_deg(); | |
+ break; | |
+ | |
+ case MOTOR_TYPE_FOC: | |
+ ret = mcpwm_foc_get_pid_pos_now(); | |
+ break; | |
+ | |
+ default: | |
+ break; | |
+ } | |
+ | |
+ return ret; | |
+} | |
+ | |
+float mc_interface_get_last_sample_adc_isr_duration(void) { | |
+ return m_last_adc_duration_sample; | |
+} | |
+ | |
+void mc_interface_sample_print_data(bool at_start, uint16_t len, uint8_t decimation) { | |
+ if (len > ADC_SAMPLE_MAX_LEN) { | |
+ len = ADC_SAMPLE_MAX_LEN; | |
+ } | |
+ | |
+ m_sample_len = len; | |
+ m_sample_int = decimation; | |
+ | |
+ if (at_start) { | |
+ m_sample_at_start = 1; | |
+ m_start_comm = mcpwm_get_comm_step(); | |
+ } else { | |
+ m_sample_now = 0; | |
+ m_sample_ready = 0; | |
+ } | |
} | |
// MC implementation functions | |
@@ -726,16 +961,16 @@ | |
// TODO: Remove this later | |
if (mc_interface_get_state() == MC_STATE_DETECTING) { | |
mcpwm_stop_pwm(); | |
- ignore_iterations = MCPWM_DETECT_STOP_TIME; | |
+ m_ignore_iterations = MCPWM_DETECT_STOP_TIME; | |
} | |
- int retval = ignore_iterations; | |
+ int retval = m_ignore_iterations; | |
- if (!ignore_iterations && lock_enabled) { | |
- if (!lock_override_once) { | |
+ if (!m_ignore_iterations && m_lock_enabled) { | |
+ if (!m_lock_override_once) { | |
retval = 1; | |
} else { | |
- lock_override_once = false; | |
+ m_lock_override_once = false; | |
} | |
} | |
@@ -743,7 +978,7 @@ | |
} | |
void mc_interface_fault_stop(mc_fault_code fault) { | |
- if (mc_interface_dccal_done() && fault_now == FAULT_CODE_NONE) { | |
+ if (mc_interface_dccal_done() && m_fault_now == FAULT_CODE_NONE) { | |
// Sent to terminal fault logger so that all faults and their conditions | |
// can be printed for debugging. | |
chSysLock(); | |
@@ -754,13 +989,18 @@ | |
fault_data fdata; | |
fdata.fault = fault; | |
- fdata.current = mc_interface_get_tot_current(); | |
- fdata.current_filtered = mc_interface_get_tot_current_filtered(); | |
+ if (m_conf.motor_type == MOTOR_TYPE_FOC) { | |
+ fdata.current = mcpwm_foc_get_abs_motor_current(); | |
+ fdata.current_filtered = mcpwm_foc_get_abs_motor_current_filtered(); | |
+ }else{ | |
+ fdata.current = mc_interface_get_tot_current(); | |
+ fdata.current_filtered = mc_interface_get_tot_current_filtered(); | |
+ } | |
fdata.voltage = GET_INPUT_VOLTAGE(); | |
fdata.duty = mc_interface_get_duty_cycle_now(); | |
fdata.rpm = mc_interface_get_rpm(); | |
fdata.tacho = mc_interface_get_tachometer_value(false); | |
- fdata.cycles_running = cycles_running; | |
+ fdata.cycles_running = m_cycles_running; | |
fdata.tim_val_samp = val_samp; | |
fdata.tim_current_samp = current_samp; | |
fdata.tim_top = tim_top; | |
@@ -769,9 +1009,9 @@ | |
terminal_add_fault_data(&fdata); | |
} | |
- ignore_iterations = conf.m_fault_stop_time_ms; | |
+ m_ignore_iterations = m_conf.m_fault_stop_time_ms; | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_stop_pwm(); | |
@@ -785,20 +1025,22 @@ | |
break; | |
} | |
- fault_now = fault; | |
+ m_fault_now = fault; | |
} | |
void mc_interface_mc_timer_isr(void) { | |
+ ledpwm_update_pwm(); // LED PWM Driver update | |
+ | |
const float input_voltage = GET_INPUT_VOLTAGE(); | |
// Check for faults that should stop the motor | |
static int wrong_voltage_iterations = 0; | |
- if (input_voltage < conf.l_min_vin || | |
- input_voltage > conf.l_max_vin) { | |
+ if (input_voltage < m_conf.l_min_vin || | |
+ input_voltage > m_conf.l_max_vin) { | |
wrong_voltage_iterations++; | |
if ((wrong_voltage_iterations >= 8)) { | |
- mc_interface_fault_stop(input_voltage < conf.l_min_vin ? | |
+ mc_interface_fault_stop(input_voltage < m_conf.l_min_vin ? | |
FAULT_CODE_UNDER_VOLTAGE : FAULT_CODE_OVER_VOLTAGE); | |
} | |
} else { | |
@@ -806,70 +1048,119 @@ | |
} | |
if (mc_interface_get_state() == MC_STATE_RUNNING) { | |
- cycles_running++; | |
+ m_cycles_running++; | |
} else { | |
- cycles_running = 0; | |
+ m_cycles_running = 0; | |
} | |
- main_dma_adc_handler(); | |
- | |
if (pwn_done_func) { | |
pwn_done_func(); | |
} | |
const float current = mc_interface_get_tot_current_filtered(); | |
const float current_in = mc_interface_get_tot_current_in_filtered(); | |
- motor_current_sum += current; | |
- input_current_sum += current_in; | |
- motor_current_iterations++; | |
- input_current_iterations++; | |
+ m_motor_current_sum += current; | |
+ m_input_current_sum += current_in; | |
+ m_motor_current_iterations++; | |
+ m_input_current_iterations++; | |
float abs_current = mc_interface_get_tot_current(); | |
float abs_current_filtered = current; | |
- if (conf.motor_type == MOTOR_TYPE_FOC) { | |
+ if (m_conf.motor_type == MOTOR_TYPE_FOC) { | |
// TODO: Make this more general | |
abs_current = mcpwm_foc_get_abs_motor_current(); | |
abs_current_filtered = mcpwm_foc_get_abs_motor_current_filtered(); | |
} | |
// Current fault code | |
- if (conf.l_slow_abs_current) { | |
- if (fabsf(abs_current_filtered) > conf.l_abs_current_max) { | |
+ if (m_conf.l_slow_abs_current) { | |
+ if (fabsf(abs_current_filtered) > m_conf.l_abs_current_max) { | |
mc_interface_fault_stop(FAULT_CODE_ABS_OVER_CURRENT); | |
} | |
} else { | |
- if (fabsf(abs_current) > conf.l_abs_current_max) { | |
+ if (fabsf(abs_current) > m_conf.l_abs_current_max) { | |
mc_interface_fault_stop(FAULT_CODE_ABS_OVER_CURRENT); | |
} | |
} | |
// Watt and ah counters | |
- const float f_sw = mc_interface_get_switching_frequency_now(); | |
+ const float f_samp = mc_interface_get_sampling_frequency_now(); | |
if (fabsf(current) > 1.0) { | |
// Some extra filtering | |
static float curr_diff_sum = 0.0; | |
static float curr_diff_samples = 0; | |
- curr_diff_sum += current_in / f_sw; | |
- curr_diff_samples += 1.0 / f_sw; | |
+ curr_diff_sum += current_in / f_samp; | |
+ curr_diff_samples += 1.0 / f_samp; | |
if (curr_diff_samples >= 0.01) { | |
if (curr_diff_sum > 0.0) { | |
- amp_seconds += curr_diff_sum; | |
- watt_seconds += curr_diff_sum * input_voltage; | |
+ m_amp_seconds += curr_diff_sum; | |
+ m_watt_seconds += curr_diff_sum * input_voltage; | |
} else { | |
- amp_seconds_charged -= curr_diff_sum; | |
- watt_seconds_charged -= curr_diff_sum * input_voltage; | |
+ m_amp_seconds_charged -= curr_diff_sum; | |
+ m_watt_seconds_charged -= curr_diff_sum * input_voltage; | |
} | |
curr_diff_samples = 0.0; | |
curr_diff_sum = 0.0; | |
} | |
} | |
+ | |
+ // Sample collection | |
+ if (m_sample_at_start && (mc_interface_get_state() == MC_STATE_RUNNING || | |
+ m_start_comm != mcpwm_get_comm_step())) { | |
+ m_sample_now = 0; | |
+ m_sample_ready = 0; | |
+ m_sample_at_start = 0; | |
+ } | |
+ | |
+ static int a = 0; | |
+ if (!m_sample_ready) { | |
+ a++; | |
+ if (a >= m_sample_int) { | |
+ a = 0; | |
+ | |
+ if (mc_interface_get_state() == MC_STATE_DETECTING) { | |
+ m_curr0_samples[m_sample_now] = (int16_t)mcpwm_detect_currents[mcpwm_get_comm_step() - 1]; | |
+ m_curr1_samples[m_sample_now] = (int16_t)mcpwm_detect_currents_diff[mcpwm_get_comm_step() - 1]; | |
+ | |
+ m_ph1_samples[m_sample_now] = (int16_t)mcpwm_detect_voltages[0]; | |
+ m_ph2_samples[m_sample_now] = (int16_t)mcpwm_detect_voltages[1]; | |
+ m_ph3_samples[m_sample_now] = (int16_t)mcpwm_detect_voltages[2]; | |
+ } else { | |
+ m_curr0_samples[m_sample_now] = ADC_curr_norm_value[0]; | |
+ m_curr1_samples[m_sample_now] = ADC_curr_norm_value[1]; | |
+ | |
+ m_ph1_samples[m_sample_now] = ADC_V_L1 - mcpwm_vzero; | |
+ m_ph2_samples[m_sample_now] = ADC_V_L2 - mcpwm_vzero; | |
+ m_ph3_samples[m_sample_now] = ADC_V_L3 - mcpwm_vzero; | |
+ } | |
+ | |
+ m_vzero_samples[m_sample_now] = mcpwm_vzero; | |
+ | |
+ m_curr_fir_samples[m_sample_now] = (int16_t)(mc_interface_get_tot_current() * 100.0); | |
+ m_f_sw_samples[m_sample_now] = (int16_t)(f_samp / 10.0); | |
+ | |
+ m_status_samples[m_sample_now] = mcpwm_get_comm_step() | (mcpwm_read_hall_phase() << 3); | |
+ | |
+ m_sample_now++; | |
+ | |
+ if (m_sample_now == m_sample_len) { | |
+ m_sample_ready = 1; | |
+ m_sample_now = 0; | |
+ chSysLockFromISR(); | |
+ chEvtSignalI(sample_send_tp, (eventmask_t) 1); | |
+ chSysUnlockFromISR(); | |
+ } | |
+ | |
+ m_last_adc_duration_sample = mcpwm_get_last_adc_isr_duration(); | |
+ } | |
+ } | |
} | |
void mc_interface_adc_inj_int_handler(void) { | |
- switch (conf.motor_type) { | |
+ switch (m_conf.motor_type) { | |
case MOTOR_TYPE_BLDC: | |
case MOTOR_TYPE_DC: | |
mcpwm_adc_inj_int_handler(); | |
@@ -891,7 +1182,7 @@ | |
* The configaration to update. | |
*/ | |
static void update_override_limits(volatile mc_configuration *conf) { | |
- const float temp = NTC_TEMP(ADC_IND_TEMP_MOS1); | |
+ const float temp = NTC_TEMP(ADC_IND_TEMP_MOS2); | |
const float v_in = GET_INPUT_VOLTAGE(); | |
// Temperature | |
@@ -944,16 +1235,53 @@ | |
} | |
// Decrease fault iterations | |
- if (ignore_iterations > 0) { | |
- ignore_iterations--; | |
+ if (m_ignore_iterations > 0) { | |
+ m_ignore_iterations--; | |
} else { | |
if (!IS_DRV_FAULT()) { | |
- fault_now = FAULT_CODE_NONE; | |
+ m_fault_now = FAULT_CODE_NONE; | |
} | |
} | |
- update_override_limits(&conf); | |
+ update_override_limits(&m_conf); | |
chThdSleepMilliseconds(1); | |
} | |
} | |
+ | |
+static THD_FUNCTION(sample_send_thread, arg) { | |
+ (void)arg; | |
+ | |
+ chRegSetThreadName("SampleSender"); | |
+ | |
+ sample_send_tp = chThdGetSelfX(); | |
+ | |
+ for(;;) { | |
+ chEvtWaitAny((eventmask_t) 1); | |
+ | |
+ for (int i = 0;i < m_sample_len;i++) { | |
+ uint8_t buffer[20]; | |
+ int index = 0; | |
+ | |
+ buffer[index++] = m_curr0_samples[i] >> 8; | |
+ buffer[index++] = m_curr0_samples[i]; | |
+ buffer[index++] = m_curr1_samples[i] >> 8; | |
+ buffer[index++] = m_curr1_samples[i]; | |
+ buffer[index++] = m_ph1_samples[i] >> 8; | |
+ buffer[index++] = m_ph1_samples[i]; | |
+ buffer[index++] = m_ph2_samples[i] >> 8; | |
+ buffer[index++] = m_ph2_samples[i]; | |
+ buffer[index++] = m_ph3_samples[i] >> 8; | |
+ buffer[index++] = m_ph3_samples[i]; | |
+ buffer[index++] = m_vzero_samples[i] >> 8; | |
+ buffer[index++] = m_vzero_samples[i]; | |
+ buffer[index++] = m_status_samples[i]; | |
+ buffer[index++] = m_curr_fir_samples[i] >> 8; | |
+ buffer[index++] = m_curr_fir_samples[i]; | |
+ buffer[index++] = m_f_sw_samples[i] >> 8; | |
+ buffer[index++] = m_f_sw_samples[i]; | |
+ | |
+ commands_send_samples(buffer, index); | |
+ } | |
+ } | |
+} | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/mc_interface.h Raptor2 Sources/bldc-firmware_2_80/mc_interface.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/mc_interface.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mc_interface.h 2017-04-13 18:05:06.000000000 +0100 | |
@@ -41,14 +41,20 @@ | |
void mc_interface_set_duty(float dutyCycle); | |
void mc_interface_set_duty_noramp(float dutyCycle); | |
void mc_interface_set_pid_speed(float rpm); | |
+void mc_interface_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status); | |
+ppm_cruise mc_interface_get_cruise_control_status(void); | |
+void mc_interface_set_cruise_control_status(ppm_cruise status); // 1 = active 0 = inactive | |
void mc_interface_set_pid_pos(float pos); | |
void mc_interface_set_current(float current); | |
void mc_interface_set_brake_current(float current); | |
+void mc_interface_set_servo(float servo_val, bool use_min_current); | |
+void mc_interface_set_brake_servo(float servo_val); | |
void mc_interface_brake_now(void); | |
void mc_interface_release_motor(void); | |
+float mc_interface_get_duty_cycle_for_watt_calculation(void); | |
float mc_interface_get_duty_cycle_set(void); | |
float mc_interface_get_duty_cycle_now(void); | |
-float mc_interface_get_switching_frequency_now(void); | |
+float mc_interface_get_sampling_frequency_now(void); | |
float mc_interface_get_rpm(void); | |
float mc_interface_get_amp_hours(bool reset); | |
float mc_interface_get_amp_hours_charged(bool reset); | |
@@ -65,7 +71,10 @@ | |
float mc_interface_get_last_inj_adc_isr_duration(void); | |
float mc_interface_read_reset_avg_motor_current(void); | |
float mc_interface_read_reset_avg_input_current(void); | |
-float mc_interface_get_pos_set(void); | |
+float mc_interface_get_pid_pos_set(void); | |
+float mc_interface_get_pid_pos_now(void); | |
+float mc_interface_get_last_sample_adc_isr_duration(void); | |
+void mc_interface_sample_print_data(bool at_start, uint16_t len, uint8_t decimation); | |
// MC implementation functions | |
void mc_interface_fault_stop(mc_fault_code fault); | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcconf/mcconf_default.h Raptor2 Sources/bldc-firmware_2_80/mcconf/mcconf_default.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcconf/mcconf_default.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcconf/mcconf_default.h 2018-08-28 19:44:30.000000000 +0100 | |
@@ -20,16 +20,16 @@ | |
// Default settings | |
#ifndef MCCONF_DEFAULT_MOTOR_TYPE | |
-#define MCCONF_DEFAULT_MOTOR_TYPE MOTOR_TYPE_BLDC | |
+#define MCCONF_DEFAULT_MOTOR_TYPE MOTOR_TYPE_FOC | |
#endif | |
#ifndef MCCONF_PWM_MODE | |
-#define MCCONF_PWM_MODE PWM_MODE_SYNCHRONOUS // Default PWM mode | |
+#define MCCONF_PWM_MODE PWM_MODE_SYNCHRONOUS // Default PWM mode | |
#endif | |
#ifndef MCCONF_SENSOR_MODE | |
-#define MCCONF_SENSOR_MODE SENSOR_MODE_SENSORLESS // Sensor mode | |
+#define MCCONF_SENSOR_MODE SENSOR_MODE_HYBRID // Sensor mode | |
#endif | |
#ifndef MCCONF_COMM_MODE | |
-#define MCCONF_COMM_MODE COMM_MODE_INTEGRATE // The commutation mode to use | |
+#define MCCONF_COMM_MODE COMM_MODE_INTEGRATE // The commutation mode to use | |
#endif | |
// Limits | |
@@ -37,13 +37,13 @@ | |
#define MCCONF_L_CURRENT_MAX 60.0 // Current limit in Amperes (Upper) | |
#endif | |
#ifndef MCCONF_L_CURRENT_MIN | |
-#define MCCONF_L_CURRENT_MIN -60.0 // Current limit in Amperes (Lower) | |
+#define MCCONF_L_CURRENT_MIN -50.0 // Current limit in Amperes (Lower) | |
#endif | |
#ifndef MCCONF_L_IN_CURRENT_MAX | |
-#define MCCONF_L_IN_CURRENT_MAX 60.0 // Input current limit in Amperes (Upper) | |
+#define MCCONF_L_IN_CURRENT_MAX 25.0 // Input current limit in Amperes (Upper) | |
#endif | |
#ifndef MCCONF_L_IN_CURRENT_MIN | |
-#define MCCONF_L_IN_CURRENT_MIN -20.0 // Input current limit in Amperes (Lower) | |
+#define MCCONF_L_IN_CURRENT_MIN -10.0 // Input current limit in Amperes (Lower) | |
#endif | |
#ifndef MCCONF_L_MAX_ABS_CURRENT | |
#define MCCONF_L_MAX_ABS_CURRENT 130.0 // The maximum absolute current above which a fault is generated | |
@@ -52,37 +52,37 @@ | |
#define MCCONF_L_MIN_VOLTAGE 8.0 // Minimum input voltage | |
#endif | |
#ifndef MCCONF_L_MAX_VOLTAGE | |
-#define MCCONF_L_MAX_VOLTAGE 50.0 // Maximum input voltage | |
+#define MCCONF_L_MAX_VOLTAGE 57.0 // Maximum input voltage | |
#endif | |
#ifndef MCCONF_L_BATTERY_CUT_START | |
-#define MCCONF_L_BATTERY_CUT_START 10.0 // Start limiting the positive current at this voltage | |
+#define MCCONF_L_BATTERY_CUT_START 33.5 // Start limiting the positive current at this voltage | |
#endif | |
#ifndef MCCONF_L_BATTERY_CUT_END | |
-#define MCCONF_L_BATTERY_CUT_END 8.0 // Limit the positive current completely at this voltage | |
+#define MCCONF_L_BATTERY_CUT_END 29.0 // Limit the positive current completely at this voltage | |
#endif | |
#ifndef MCCONF_L_RPM_MAX | |
-#define MCCONF_L_RPM_MAX 100000.0 // The motor speed limit (Upper) | |
+#define MCCONF_L_RPM_MAX 60000.0 // The motor speed limit (Upper) | |
#endif | |
#ifndef MCCONF_L_RPM_MIN | |
-#define MCCONF_L_RPM_MIN -100000.0 // The motor speed limit (Lower) | |
+#define MCCONF_L_RPM_MIN -60000.0 // The motor speed limit (Lower) | |
#endif | |
#ifndef MCCONF_L_SLOW_ABS_OVERCURRENT | |
-#define MCCONF_L_SLOW_ABS_OVERCURRENT true // Use the filtered (and hence slower) current for the overcurrent fault detection | |
+#define MCCONF_L_SLOW_ABS_OVERCURRENT true // Use the filtered (and hence slower) current for the overcurrent fault detection | |
#endif | |
#ifndef MCCONF_L_MIN_DUTY | |
-#define MCCONF_L_MIN_DUTY 0.005 // Minimum duty cycle | |
+#define MCCONF_L_MIN_DUTY 0.005 // Minimum duty cycle | |
#endif | |
#ifndef MCCONF_L_MAX_DUTY | |
-#define MCCONF_L_MAX_DUTY 0.95 // Maximum duty cycle | |
+#define MCCONF_L_MAX_DUTY 0.95 // Maximum duty cycle | |
#endif | |
#ifndef MCCONF_L_RPM_LIMIT_NEG_TORQUE | |
-#define MCCONF_L_RPM_LIMIT_NEG_TORQUE true // Use negative torque to limit the RPM | |
+#define MCCONF_L_RPM_LIMIT_NEG_TORQUE false // Use negative torque to limit the RPM | |
#endif | |
#ifndef MCCONF_L_CURR_MAX_RPM_FBRAKE | |
-#define MCCONF_L_CURR_MAX_RPM_FBRAKE 300 // Maximum electrical RPM to use full brake at | |
+#define MCCONF_L_CURR_MAX_RPM_FBRAKE 300 // Maximum electrical RPM to use full brake at | |
#endif | |
#ifndef MCCONF_L_CURR_MAX_RPM_FBRAKE_CC | |
-#define MCCONF_L_CURR_MAX_RPM_FBRAKE_CC 1500 // Maximum electrical RPM to use full brake at with current control | |
+#define MCCONF_L_CURR_MAX_RPM_FBRAKE_CC 1500 // Maximum electrical RPM to use full brake at with current control | |
#endif | |
#ifndef MCCONF_L_LIM_TEMP_FET_START | |
#define MCCONF_L_LIM_TEMP_FET_START 80.0 // MOSFET temperature where current limiting should begin | |
@@ -91,7 +91,7 @@ | |
#define MCCONF_L_LIM_TEMP_FET_END 100.0 // MOSFET temperature where everything should be shut off | |
#endif | |
#ifndef MCCONF_L_LIM_TEMP_MOTOR_START | |
-#define MCCONF_L_LIM_TEMP_MOTOR_START 80.0 // MOTOR temperature where current limiting should begin | |
+#define MCCONF_L_LIM_TEMP_MOTOR_START 80.0 // MOTOR temperature where current limiting should begin | |
#endif | |
#ifndef MCCONF_L_LIM_TEMP_MOTOR_END | |
#define MCCONF_L_LIM_TEMP_MOTOR_END 100.0 // MOTOR temperature where everything should be shut off | |
@@ -99,58 +99,64 @@ | |
// Speed PID parameters | |
#ifndef MCCONF_S_PID_KP | |
-#define MCCONF_S_PID_KP 0.0001 // Proportional gain | |
+#define MCCONF_S_PID_KP 0.003 // Proportional gain | |
#endif | |
#ifndef MCCONF_S_PID_KI | |
-#define MCCONF_S_PID_KI 0.015 // Integral gain | |
+#define MCCONF_S_PID_KI 0.003 // Integral gain | |
#endif | |
#ifndef MCCONF_S_PID_KD | |
-#define MCCONF_S_PID_KD 0.0 // Derivative gain | |
+#define MCCONF_S_PID_KD 0.0 // Derivative gain | |
#endif | |
#ifndef MCCONF_S_PID_MIN_RPM | |
#define MCCONF_S_PID_MIN_RPM 900.0 // Minimum allowed RPM | |
#endif | |
+#ifndef MCCONF_S_PID_BREAKING_ENABLED | |
+#define MCCONF_S_PID_BREAKING_ENABLED true // Break at PID speed mode (cruiso control) | |
+#endif | |
// Position PID parameters | |
#ifndef MCCONF_P_PID_KP | |
-#define MCCONF_P_PID_KP 0.03 // Proportional gain | |
+#define MCCONF_P_PID_KP 0.03 // Proportional gain | |
#endif | |
#ifndef MCCONF_P_PID_KI | |
-#define MCCONF_P_PID_KI 0.0 // Integral gain | |
+#define MCCONF_P_PID_KI 0.0 // Integral gain | |
#endif | |
#ifndef MCCONF_P_PID_KD | |
-#define MCCONF_P_PID_KD 0.0004 // Derivative gain | |
+#define MCCONF_P_PID_KD 0.0004 // Derivative gain | |
+#endif | |
+#ifndef MCCONF_P_PID_ANG_DIV | |
+#define MCCONF_P_PID_ANG_DIV 1.0 // Divide angle by this value | |
#endif | |
// Current control parameters | |
#ifndef MCCONF_CC_GAIN | |
-#define MCCONF_CC_GAIN 0.0046 // Current controller error gain | |
+#define MCCONF_CC_GAIN 0.0046 // Current controller error gain | |
#endif | |
#ifndef MCCONF_CC_MIN_CURRENT | |
-#define MCCONF_CC_MIN_CURRENT 1.0 // Minimum allowed current | |
+#define MCCONF_CC_MIN_CURRENT 0.5 // Minimum allowed current | |
#endif | |
#ifndef MCCONF_CC_STARTUP_BOOST_DUTY | |
-#define MCCONF_CC_STARTUP_BOOST_DUTY 0.01 // The lowest duty cycle to use in current control mode (has to be > MCPWM_MIN_DUTY_CYCLE) | |
+#define MCCONF_CC_STARTUP_BOOST_DUTY 0.01 // The lowest duty cycle to use in current control mode (has to be > MCPWM_MIN_DUTY_CYCLE) | |
#endif | |
#ifndef MCCONF_CC_RAMP_STEP | |
-#define MCCONF_CC_RAMP_STEP 0.04 // Maximum duty cycle ramping step in CC mode | |
+#define MCCONF_CC_RAMP_STEP 0.04 // Maximum duty cycle ramping step in CC mode | |
#endif | |
// BLDC | |
#ifndef MCCONF_SL_MIN_RPM | |
-#define MCCONF_SL_MIN_RPM 150 // Auto-commutate below this RPM | |
+#define MCCONF_SL_MIN_RPM 150 // Auto-commutate below this RPM | |
#endif | |
#ifndef MCCONF_SL_MIN_ERPM_CYCLE_INT_LIMIT | |
#define MCCONF_SL_MIN_ERPM_CYCLE_INT_LIMIT 1100.0 // Minimum RPM to calculate the BEMF coupling from | |
#endif | |
#ifndef MCCONF_SL_CYCLE_INT_LIMIT | |
-#define MCCONF_SL_CYCLE_INT_LIMIT 62.0 // Flux integrator limit 0 ERPM | |
+#define MCCONF_SL_CYCLE_INT_LIMIT 100.0 // Flux integrator limit 0 ERPM | |
#endif | |
#ifndef MCCONF_SL_BEMF_COUPLING_K | |
#define MCCONF_SL_BEMF_COUPLING_K 600.0 // Input voltage to bemf coupling constant | |
#endif | |
#ifndef MCCONF_SL_PHASE_ADVANCE_AT_BR | |
-#define MCCONF_SL_PHASE_ADVANCE_AT_BR 0.8 // Flux integrator limit percentage at MCPWM_CYCLE_INT_START_RPM_BR ERPM | |
+#define MCCONF_SL_PHASE_ADVANCE_AT_BR 0.8 // Flux integrator limit percentage at MCPWM_CYCLE_INT_START_RPM_BR ERPM | |
#endif | |
#ifndef MCCONF_SL_CYCLE_INT_BR | |
#define MCCONF_SL_CYCLE_INT_BR 80000.0 // RPM border between the START and LOW interval | |
@@ -159,18 +165,47 @@ | |
#define MCCONF_SL_MAX_FB_CURR_DIR_CHANGE 10.0 // Maximum current during full brake during which a direction change is allowed | |
#endif | |
+// BLDC hall sensor table | |
+#ifndef MCCONF_HALL_TAB_0 | |
+#define MCCONF_HALL_TAB_0 -1 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_1 | |
+#define MCCONF_HALL_TAB_1 1 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_2 | |
+#define MCCONF_HALL_TAB_2 3 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_3 | |
+#define MCCONF_HALL_TAB_3 2 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_4 | |
+#define MCCONF_HALL_TAB_4 5 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_5 | |
+#define MCCONF_HALL_TAB_5 6 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_6 | |
+#define MCCONF_HALL_TAB_6 4 | |
+#endif | |
+#ifndef MCCONF_HALL_TAB_7 | |
+#define MCCONF_HALL_TAB_7 -1 | |
+#endif | |
+#ifndef MCCONF_HALL_ERPM | |
+#define MCCONF_HALL_ERPM 5000.0 // ERPM above which sensorless commutation is used in hybrid mode | |
+#endif | |
+ | |
// FOC | |
#ifndef MCCONF_FOC_CURRENT_KP | |
-#define MCCONF_FOC_CURRENT_KP 0.03 | |
+#define MCCONF_FOC_CURRENT_KP 0.0215 //0.0255 | |
#endif | |
#ifndef MCCONF_FOC_CURRENT_KI | |
-#define MCCONF_FOC_CURRENT_KI 50.0 | |
+#define MCCONF_FOC_CURRENT_KI 47.80 //41.00 | |
#endif | |
#ifndef MCCONF_FOC_F_SW | |
-#define MCCONF_FOC_F_SW 20000.0 | |
+#define MCCONF_FOC_F_SW 20000.0 | |
#endif | |
#ifndef MCCONF_FOC_DT_US | |
-#define MCCONF_FOC_DT_US 0.15 // Microseconds for dead time compensation | |
+#define MCCONF_FOC_DT_US 0.08 // Microseconds for dead time compensation | |
#endif | |
#ifndef MCCONF_FOC_ENCODER_INVERTED | |
#define MCCONF_FOC_ENCODER_INVERTED false | |
@@ -182,25 +217,25 @@ | |
#define MCCONF_FOC_ENCODER_RATIO 7.0 | |
#endif | |
#ifndef MCCONF_FOC_SENSOR_MODE | |
-#define MCCONF_FOC_SENSOR_MODE FOC_SENSOR_MODE_SENSORLESS | |
+#define MCCONF_FOC_SENSOR_MODE FOC_SENSOR_MODE_HALL | |
#endif | |
#ifndef MCCONF_FOC_PLL_KP | |
-#define MCCONF_FOC_PLL_KP 40.0 | |
+#define MCCONF_FOC_PLL_KP 2000.0 | |
#endif | |
#ifndef MCCONF_FOC_PLL_KI | |
-#define MCCONF_FOC_PLL_KI 40000.0 | |
+#define MCCONF_FOC_PLL_KI 20000.0 | |
#endif | |
#ifndef MCCONF_FOC_MOTOR_L | |
-#define MCCONF_FOC_MOTOR_L 0.000007 | |
+#define MCCONF_FOC_MOTOR_L 0.0000215 //0.0000255 | |
#endif | |
#ifndef MCCONF_FOC_MOTOR_R | |
-#define MCCONF_FOC_MOTOR_R 0.015 | |
+#define MCCONF_FOC_MOTOR_R 0.04780 //0.04100 | |
#endif | |
#ifndef MCCONF_FOC_MOTOR_FLUX_LINKAGE | |
-#define MCCONF_FOC_MOTOR_FLUX_LINKAGE 0.00245 | |
+#define MCCONF_FOC_MOTOR_FLUX_LINKAGE 0.006278//0.004363 | |
#endif | |
#ifndef MCCONF_FOC_OBSERVER_GAIN | |
-#define MCCONF_FOC_OBSERVER_GAIN 9e7 // Can be something like 600 / L | |
+#define MCCONF_FOC_OBSERVER_GAIN 4.651e7 //3.922e7 // Can be something like 600 / L | |
#endif | |
#ifndef MCCONF_FOC_DUTY_DOWNRAMP_KP | |
#define MCCONF_FOC_DUTY_DOWNRAMP_KP 10.0 // PI controller for duty control when decreasing the duty | |
@@ -209,48 +244,46 @@ | |
#define MCCONF_FOC_DUTY_DOWNRAMP_KI 200.0 // PI controller for duty control when decreasing the duty | |
#endif | |
#ifndef MCCONF_FOC_OPENLOOP_RPM | |
-#define MCCONF_FOC_OPENLOOP_RPM 350.0 // Openloop RPM (sensorless low speed or when finding index pulse) | |
+#define MCCONF_FOC_OPENLOOP_RPM 1200.0 // Openloop RPM (sensorless low speed or when finding index pulse) | |
#endif | |
#ifndef MCCONF_FOC_SL_OPENLOOP_HYST | |
-#define MCCONF_FOC_SL_OPENLOOP_HYST 0.5 // Time below min RPM to activate openloop (s) | |
+#define MCCONF_FOC_SL_OPENLOOP_HYST 0.5 // Time below min RPM to activate openloop (s) | |
#endif | |
#ifndef MCCONF_FOC_SL_OPENLOOP_TIME | |
-#define MCCONF_FOC_SL_OPENLOOP_TIME 0.5 // Time to remain in openloop (s) | |
+#define MCCONF_FOC_SL_OPENLOOP_TIME 0.5 // Time to remain in openloop (s) | |
#endif | |
#ifndef MCCONF_FOC_SL_D_CURRENT_DUTY | |
-#define MCCONF_FOC_SL_D_CURRENT_DUTY 0.0 // Inject d-axis current below this duty cycle in sensorless more | |
+#define MCCONF_FOC_SL_D_CURRENT_DUTY 0.0 // Inject d-axis current below this duty cycle in sensorless more | |
#endif | |
#ifndef MCCONF_FOC_SL_D_CURRENT_FACTOR | |
-#define MCCONF_FOC_SL_D_CURRENT_FACTOR 0.0 // Maximum q-axis current factor | |
+#define MCCONF_FOC_SL_D_CURRENT_FACTOR 0.0 // Maximum q-axis current factor | |
#endif | |
- | |
-// Default hall sensor table | |
-#ifndef MCCONF_HALL_TAB_0 | |
-#define MCCONF_HALL_TAB_0 -1 | |
+#ifndef MCCONF_FOC_HALL_TAB_0 | |
+#define MCCONF_FOC_HALL_TAB_0 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_1 | |
-#define MCCONF_HALL_TAB_1 1 | |
+#ifndef MCCONF_FOC_HALL_TAB_1 | |
+#define MCCONF_FOC_HALL_TAB_1 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_2 | |
-#define MCCONF_HALL_TAB_2 3 | |
+#ifndef MCCONF_FOC_HALL_TAB_2 | |
+#define MCCONF_FOC_HALL_TAB_2 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_3 | |
-#define MCCONF_HALL_TAB_3 2 | |
+#ifndef MCCONF_FOC_HALL_TAB_3 | |
+#define MCCONF_FOC_HALL_TAB_3 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_4 | |
-#define MCCONF_HALL_TAB_4 5 | |
+#ifndef MCCONF_FOC_HALL_TAB_4 | |
+#define MCCONF_FOC_HALL_TAB_4 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_5 | |
-#define MCCONF_HALL_TAB_5 6 | |
+#ifndef MCCONF_FOC_HALL_TAB_5 | |
+#define MCCONF_FOC_HALL_TAB_5 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_6 | |
-#define MCCONF_HALL_TAB_6 4 | |
+#ifndef MCCONF_FOC_HALL_TAB_6 | |
+#define MCCONF_FOC_HALL_TAB_6 255 | |
#endif | |
-#ifndef MCCONF_HALL_TAB_7 | |
-#define MCCONF_HALL_TAB_7 -1 | |
+#ifndef MCCONF_FOC_HALL_TAB_7 | |
+#define MCCONF_FOC_HALL_TAB_7 255 | |
#endif | |
-#ifndef MCCONF_HALL_ERPM | |
-#define MCCONF_HALL_ERPM 2000.0 // ERPM above which sensorless commutation is used in hybrid mode | |
+#ifndef MCCONF_FOC_SL_ERPM | |
+#define MCCONF_FOC_SL_ERPM 5000.0 // ERPM above which only the observer is used | |
#endif | |
// Misc | |
@@ -258,16 +291,25 @@ | |
#define MCCONF_M_FAULT_STOP_TIME 3000 // Ignore commands for this duration in msec when faults occur | |
#endif | |
#ifndef MCCONF_M_RAMP_STEP | |
-#define MCCONF_M_RAMP_STEP 0.02 // Duty cycle ramping step (1000 times/sec) at maximum duty cycle | |
+#define MCCONF_M_RAMP_STEP 0.02 // Duty cycle ramping step (1000 times/sec) at maximum duty cycle | |
#endif | |
#ifndef MCCONF_M_RAMP_STEP_RPM_LIM | |
#define MCCONF_M_RAMP_STEP_RPM_LIM 0.0005 // Ramping step when limiting the RPM | |
#endif | |
#ifndef MCCONF_M_CURRENT_BACKOFF_GAIN | |
-#define MCCONF_M_CURRENT_BACKOFF_GAIN 0.5 // The error gain of the current limiting algorithm | |
+#define MCCONF_M_CURRENT_BACKOFF_GAIN 0.5 // The error gain of the current limiting algorithm | |
#endif | |
#ifndef MCCONF_M_ENCODER_COUNTS | |
#define MCCONF_M_ENCODER_COUNTS 8192 // The number of encoder counts | |
#endif | |
+#ifndef MCCONF_M_SENSOR_PORT_MODE | |
+#define MCCONF_M_SENSOR_PORT_MODE SENSOR_PORT_MODE_HALL // The mode of the hall_encoder port | |
+#endif | |
+#ifndef MCCONF_USE_MAX_WATT_LIMIT | |
+#define MCCONF_USE_MAX_WATT_LIMIT false | |
+#endif | |
+#ifndef MCCONF_WATT_MAX | |
+#define MCCONF_WATT_MAX 1000.0 // Input current limit in Amperes (Upper) | |
+#endif | |
#endif /* MCCONF_DEFAULT_H_ */ | |
Only in Raptor2 Sources/bldc-firmware_2_80/mcconf: mcconf_default.h~ | |
Only in bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcconf: mcconf_foc_erwin.h | |
Only in bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcconf: mcconf_foc_scorpion.h | |
Only in bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcconf: mcconf_outrunner2.h | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcconf/mcconf_sten.h Raptor2 Sources/bldc-firmware_2_80/mcconf/mcconf_sten.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcconf/mcconf_sten.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcconf/mcconf_sten.h 2016-09-23 23:02:14.000000000 +0100 | |
@@ -26,43 +26,54 @@ | |
#define MCCONF_STEN_H_ | |
/* | |
+ * HW: 4.10 | |
+ */ | |
+ | |
+/* | |
* Parameters | |
*/ | |
+#define MCCONF_DEFAULT_MOTOR_TYPE MOTOR_TYPE_BLDC | |
#define MCCONF_L_CURRENT_MAX 35.0 // Current limit in Amperes (Upper) | |
#define MCCONF_L_CURRENT_MIN -30.0 // Current limit in Amperes (Lower) | |
-#define MCCONF_L_MAX_ABS_CURRENT 100.0 // The maximum absolute current above which a fault is generated | |
+#define MCCONF_L_MAX_ABS_CURRENT 130.0 // The maximum absolute current above which a fault is generated | |
#define MCCONF_L_SLOW_ABS_OVERCURRENT 1 // Use the filtered (and hence slower) current for the overcurrent fault detection | |
-#define MCCONF_L_IN_CURRENT_MAX 25.0 // Input current limit in Amperes (Upper) | |
-#define MCCONF_L_IN_CURRENT_MIN -20.0 // Input current limit in Amperes (Lower) | |
+#define MCCONF_L_IN_CURRENT_MAX 25.0 // Input current limit in Amperes (Upper) | |
+#define MCCONF_L_IN_CURRENT_MIN -20.0 // Input current limit in Amperes (Lower) | |
#define MCCONF_L_RPM_MAX 80000.0 // The motor speed limit (Upper) | |
#define MCCONF_L_RPM_MIN -80000.0 // The motor speed limit (Lower) | |
-#define MCCONF_L_MIN_VOLTAGE 20.0 // Minimum input voltage | |
-#define MCCONF_L_MAX_VOLTAGE 50.0 // Maximum input voltage | |
-#define MCCONF_CC_STARTUP_BOOST_DUTY 0.02 // The lowest duty cycle to use in current control mode (has to be > MCPWM_MIN_DUTY_CYCLE) | |
+#define MCCONF_L_MIN_VOLTAGE 10.0 // Minimum input voltage | |
+#define MCCONF_L_MAX_VOLTAGE 57.0 // Maximum input voltage | |
+#define MCCONF_CC_STARTUP_BOOST_DUTY 0.03 // The lowest duty cycle to use in current control mode (has to be > MCPWM_MIN_DUTY_CYCLE) | |
#define MCCONF_L_RPM_LIMIT_NEG_TORQUE 0 // Use negative torque to limit the RPM | |
#define MCCONF_L_CURR_MAX_RPM_FBRAKE 1500 // Maximum electrical RPM to use full brake at | |
+#define MCCONF_L_BATTERY_CUT_START 41.0 // Start limiting the positive current at this voltage | |
+#define MCCONF_L_BATTERY_CUT_END 39.0 // Limit the positive current completely at this voltage | |
+ | |
// Sensorless settings | |
#define MCCONF_SENSOR_MODE SENSOR_MODE_SENSORLESS // Sensor mode | |
#define MCCONF_SL_MIN_RPM 250 // Auto-commutate below this RPM | |
-#define MCCONF_SL_MIN_ERPM_CYCLE_INT_LIMIT 500.0 // Minimum RPM to calculate the BEMF coupling from | |
+#define MCCONF_SL_MIN_ERPM_CYCLE_INT_LIMIT 1100.0 // Minimum RPM to calculate the BEMF coupling from | |
#define MCCONF_SL_CYCLE_INT_LIMIT 80.0 // Flux integrator limit 0 ERPM | |
#define MCCONF_SL_PHASE_ADVANCE_AT_BR 0.8 // Flux integrator limit percentage at MCPWM_CYCLE_INT_START_RPM_BR ERPM | |
#define MCCONF_SL_BEMF_COUPLING_K 750.0 // Input voltage to bemf coupling constant | |
+// FOC settings | |
+#define MCCONF_FOC_CURRENT_KP 0.03 | |
+#define MCCONF_FOC_CURRENT_KI 50.0 | |
+#define MCCONF_FOC_F_SW 20000.0 | |
+#define MCCONF_FOC_MOTOR_L 0.000007 | |
+#define MCCONF_FOC_MOTOR_R 0.015 | |
+#define MCCONF_FOC_MOTOR_FLUX_LINKAGE 0.00245 | |
+#define MCCONF_FOC_OBSERVER_GAIN 9e7 | |
+#define MCCONF_FOC_OPENLOOP_RPM 600.0 | |
+#define MCCONF_FOC_SL_OPENLOOP_HYST 0.5 | |
+#define MCCONF_FOC_SL_OPENLOOP_TIME 0.5 | |
+ | |
// Speed PID parameters | |
#define MCCONF_S_PID_KP 0.0001 // Proportional gain | |
#define MCCONF_S_PID_KI 0.002 // Integral gain | |
#define MCCONF_S_PID_KD 0.0 // Derivative gain | |
-#define MCCONF_S_PID_MIN_RPM 1200.0 // Minimum allowed RPM | |
- | |
-// Position PID parameters | |
-#define MCCONF_P_PID_KP 0.0001 // Proportional gain | |
-#define MCCONF_P_PID_KI 0.002 // Integral gain | |
-#define MCCONF_P_PID_KD 0.0 // Derivative gain | |
- | |
-// Current control parameters | |
-#define MCCONF_CC_GAIN 0.0046 // Current controller error gain | |
-#define MCCONF_CC_MIN_CURRENT 0.05 // Minimum allowed current | |
- | |
+#define MCCONF_S_PID_MIN_RPM 1200.0 // Minimum allowed RPM | |
+#define MCCONF_S_PID_BREAKING_ENABLED 1 // enable braking at pid speed mode (cruise control) | |
#endif /* MCCONF_STEN_H_ */ | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcpwm.c Raptor2 Sources/bldc-firmware_2_80/mcpwm.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcpwm.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcpwm.c 2017-04-13 18:06:02.000000000 +0100 | |
@@ -56,6 +56,7 @@ | |
static volatile float dutycycle_now; | |
static volatile float rpm_now; | |
static volatile float speed_pid_set_rpm; | |
+static volatile ppm_cruise speed_pid_cruise_control_type; | |
static volatile float pos_pid_set_pos; | |
static volatile float current_set; | |
static volatile int tachometer; | |
@@ -90,6 +91,8 @@ | |
static volatile float last_pwm_cycles_sums[6]; | |
static volatile bool dccal_done; | |
static volatile bool sensorless_now; | |
+static volatile float sensor_hyst_min; | |
+static volatile float sensor_hyst_max; | |
static volatile int hall_detect_table[8][7]; | |
// KV FIR filter | |
@@ -174,6 +177,7 @@ | |
dutycycle_set = 0.0; | |
dutycycle_now = 0.0; | |
speed_pid_set_rpm = 0.0; | |
+ speed_pid_cruise_control_type = CRUISE_CONTROL_MOTOR_SETTINGS; | |
pos_pid_set_pos = 0.0; | |
current_set = 0.0; | |
tachometer = 0; | |
@@ -494,7 +498,7 @@ | |
* The commutations corresponding to the hall sensor states in the forward direction- | |
*/ | |
void mcpwm_init_hall_table(int8_t *table) { | |
- const int fwd_to_rev[7] = {-1,4,3,2,1,6,5}; | |
+ const int fwd_to_rev[7] = {-1,1,6,5,4,3,2}; | |
for (int i = 0;i < 8;i++) { | |
hall_to_phase_table[8 + i] = table[i]; | |
@@ -505,14 +509,16 @@ | |
continue; | |
} | |
- ind_now += 2; | |
- if (ind_now > 6) { | |
- ind_now -= 6; | |
- } | |
- ind_now = fwd_to_rev[ind_now]; | |
- | |
- hall_to_phase_table[i] = ind_now; | |
+ hall_to_phase_table[i] = fwd_to_rev[ind_now]; | |
+ } | |
+ | |
+ // init the sensor hyst | |
+ float sensor_hyst = conf->hall_sl_erpm * 0.10; | |
+ if(sensor_hyst > 500.0){ | |
+ sensor_hyst = 500.0; | |
} | |
+ sensor_hyst_min = conf->hall_sl_erpm - sensor_hyst; | |
+ sensor_hyst_max = conf->hall_sl_erpm + sensor_hyst; | |
} | |
static void do_dc_cal(void) { | |
@@ -571,8 +577,31 @@ | |
* The electrical RPM goal value to use. | |
*/ | |
void mcpwm_set_pid_speed(float rpm) { | |
+ if (fabsf(rpm) <conf->s_pid_min_erpm) { | |
+ mcpwm_set_duty(0.0); | |
+ return; | |
+ } | |
control_mode = CONTROL_MODE_SPEED; | |
speed_pid_set_rpm = rpm; | |
+ speed_pid_cruise_control_type = CRUISE_CONTROL_MOTOR_SETTINGS; | |
+ | |
+ if (state != MC_STATE_RUNNING) { | |
+ set_duty_cycle_hl(conf->l_min_duty); | |
+ } | |
+} | |
+ | |
+void mcpwm_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status) { | |
+ if (fabsf(rpm) <conf->s_pid_min_erpm) { | |
+ mcpwm_set_duty(0.0); | |
+ return; | |
+ } | |
+ control_mode = CONTROL_MODE_SPEED; | |
+ speed_pid_set_rpm = rpm; | |
+ speed_pid_cruise_control_type = cruise_status; | |
+ | |
+ if (state != MC_STATE_RUNNING) { | |
+ set_duty_cycle_hl(conf->l_min_duty); | |
+ } | |
} | |
/** | |
@@ -1064,23 +1093,23 @@ | |
} | |
static void run_pid_control_speed(void) { | |
- static float i_term = 0; | |
- static float prev_error = 0; | |
+ static float i_term = 0.0; | |
+ static float prev_error = 0.0; | |
float p_term; | |
float d_term; | |
// PID is off. Return. | |
if (control_mode != CONTROL_MODE_SPEED) { | |
- i_term = dutycycle_now; | |
- prev_error = 0; | |
+ i_term = 0.0; | |
+ prev_error = 0.0; | |
return; | |
} | |
- // Too low RPM set. Stop and return. | |
- if (fabsf(speed_pid_set_rpm) < conf->s_pid_min_erpm) { | |
- i_term = dutycycle_now; | |
+ // Too low RPM set. Reset state and return. | |
+ if (fabsf(speed_pid_set_rpm) <conf->s_pid_min_erpm) { | |
+ i_term = 0.0; | |
prev_error = 0; | |
- mcpwm_set_duty(0.0); | |
+ current_set = 0.0; | |
return; | |
} | |
@@ -1104,21 +1133,18 @@ | |
// Calculate output | |
float output = p_term + i_term + d_term; | |
- // Make sure that at least minimum output is used | |
- if (fabsf(output) < conf->l_min_duty) { | |
- output = SIGN(output) * conf->l_min_duty; | |
- } | |
- | |
- // Do not output in reverse direction to oppose too high rpm | |
- if (speed_pid_set_rpm > 0.0 && output < 0.0) { | |
- output = conf->l_min_duty; | |
- i_term = 0.0; | |
- } else if (speed_pid_set_rpm < 0.0 && output > 0.0) { | |
- output = -conf->l_min_duty; | |
- i_term = 0.0; | |
+ if ((speed_pid_cruise_control_type == CRUISE_CONTROL_MOTOR_SETTINGS && conf->s_pid_breaking_enabled) || speed_pid_cruise_control_type == CRUISE_CONTROL_BRAKING_ENABLED) { | |
+ utils_truncate_number(&output, -1.0, 1.0); | |
+ } else { | |
+ if(speed_pid_set_rpm < 0.0){ | |
+ utils_truncate_number(&output, -1.0, 0.0); | |
+ }else{ | |
+ utils_truncate_number(&output, 0.0, 1.0); | |
+ } | |
} | |
- | |
- set_duty_cycle_hl(output); | |
+ | |
+ current_set = output * conf->lo_current_max; | |
+ | |
} | |
static void run_pid_control_pos(float dt) { | |
@@ -1784,7 +1810,7 @@ | |
float dutycycle_now_tmp = dutycycle_now; | |
- if (control_mode == CONTROL_MODE_CURRENT || control_mode == CONTROL_MODE_POS) { | |
+ if (control_mode == CONTROL_MODE_CURRENT || control_mode == CONTROL_MODE_POS || control_mode == CONTROL_MODE_SPEED) { | |
// Compute error | |
const float error = current_set - (direction ? current_nofilter : -current_nofilter); | |
float step = error * conf->cc_gain * voltage_scale; | |
@@ -1922,7 +1948,7 @@ | |
mc_interface_mc_timer_isr(); | |
- if (ENCODER_ENABLE) { | |
+ if (encoder_is_configured()) { | |
run_pid_control_pos(1.0 / switching_frequency_now); | |
} | |
@@ -2051,7 +2077,7 @@ | |
int mcpwm_get_hall_detect_result(int8_t *table) { | |
if (WS2811_ENABLE) { | |
return -2; | |
- } else if (ENCODER_ENABLE) { | |
+ } else if (conf->m_sensor_port_mode != SENSOR_PORT_MODE_HALL) { | |
return -3; | |
} | |
@@ -2336,6 +2362,7 @@ | |
} | |
} | |
+/* | |
static void update_sensor_mode(void) { | |
if (conf->sensor_mode == SENSOR_MODE_SENSORLESS || | |
(conf->sensor_mode == SENSOR_MODE_HYBRID && | |
@@ -2345,6 +2372,26 @@ | |
sensorless_now = false; | |
} | |
} | |
+*/ | |
+ | |
+static void update_sensor_mode(void) { | |
+ if (conf->sensor_mode == SENSOR_MODE_SENSORLESS ) { | |
+ sensorless_now = true; | |
+ } else if (conf->sensor_mode == SENSOR_MODE_HYBRID) { | |
+ // Hysteresis 5 % of total speed | |
+ if (sensorless_now) { | |
+ if (fabsf(rpm_now) < sensor_hyst_min) { | |
+ sensorless_now = false; | |
+ } | |
+ } else { | |
+ if (fabsf(rpm_now) > sensor_hyst_max) { | |
+ sensorless_now = true; | |
+ } | |
+ } | |
+ }else{ | |
+ sensorless_now = false; | |
+ } | |
+} | |
static void commutate(int steps) { | |
last_pwm_cycles_sum = pwm_cycles_sum; | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcpwm.h Raptor2 Sources/bldc-firmware_2_80/mcpwm.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcpwm.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcpwm.h 2017-04-13 18:06:14.000000000 +0100 | |
@@ -35,6 +35,7 @@ | |
void mcpwm_set_duty(float dutyCycle); | |
void mcpwm_set_duty_noramp(float dutyCycle); | |
void mcpwm_set_pid_speed(float rpm); | |
+void mcpwm_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status); | |
void mcpwm_set_pid_pos(float pos); | |
void mcpwm_set_current(float current); | |
void mcpwm_set_brake_current(float current); | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcpwm_foc.c Raptor2 Sources/bldc-firmware_2_80/mcpwm_foc.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcpwm_foc.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcpwm_foc.c 2017-06-05 00:12:34.000000000 +0100 | |
@@ -51,6 +51,7 @@ | |
float i_abs; | |
float i_abs_filter; | |
float i_bus; | |
+ float i_bus_filter; | |
float v_bus; | |
float v_alpha; | |
float v_beta; | |
@@ -89,8 +90,9 @@ | |
static volatile float m_iq_set; | |
static volatile bool m_dccal_done; | |
static volatile bool m_output_on; | |
-static volatile float m_pos_pid_set_pos; | |
+static volatile float m_pos_pid_set; | |
static volatile float m_speed_pid_set_rpm; | |
+static volatile ppm_cruise m_speed_pid_cruise_control_type; | |
static volatile float m_phase_now_observer; | |
static volatile float m_phase_now_observer_override; | |
static volatile bool m_phase_observer_override; | |
@@ -101,9 +103,10 @@ | |
static volatile float m_pll_phase; | |
static volatile float m_pll_speed; | |
static volatile mc_sample_t m_samples; | |
-static volatile int m_tachometer; | |
-static volatile int m_tachometer_abs; | |
+static volatile float m_tachometer; | |
+static volatile float m_tachometer_abs; | |
static volatile float last_inj_adc_isr_duration; | |
+static volatile float m_pos_pid_now; | |
// Private functions | |
static void do_dc_cal(void); | |
@@ -114,10 +117,13 @@ | |
static void control_current(volatile motor_state_t *state_m, float dt); | |
static void svm(float alpha, float beta, uint32_t PWMHalfPeriod, | |
uint32_t* tAout, uint32_t* tBout, uint32_t* tCout); | |
-static void run_pid_control_pos(float dt); | |
+static void run_pid_control_pos(float angle_now, float angle_set, float dt); | |
static void run_pid_control_speed(float dt); | |
static void stop_pwm_hw(void); | |
static void start_pwm_hw(void); | |
+static int read_hall(void); | |
+static float correct_encoder(float obs_angle, float enc_angle, float speed); | |
+static float correct_hall(float angle, float speed, float dt); | |
// Threads | |
static THD_WORKING_AREA(timer_thread_wa, 2048); | |
@@ -199,8 +205,9 @@ | |
m_id_set = 0.0; | |
m_iq_set = 0.0; | |
m_output_on = false; | |
- m_pos_pid_set_pos = 0.0; | |
+ m_pos_pid_set = 0.0; | |
m_speed_pid_set_rpm = 0.0; | |
+ m_speed_pid_cruise_control_type = CRUISE_CONTROL_MOTOR_SETTINGS; | |
m_phase_now_observer = 0.0; | |
m_phase_now_observer_override = 0.0; | |
m_phase_observer_override = false; | |
@@ -210,9 +217,10 @@ | |
m_observer_x2 = 0.0; | |
m_pll_phase = 0.0; | |
m_pll_speed = 0.0; | |
- m_tachometer = 0; | |
- m_tachometer_abs = 0; | |
+ m_tachometer = 0.0; | |
+ m_tachometer_abs = 0.0; | |
last_inj_adc_isr_duration = 0; | |
+ m_pos_pid_now = 0.0; | |
memset((void*)&m_motor_state, 0, sizeof(motor_state_t)); | |
memset((void*)&m_samples, 0, sizeof(mc_sample_t)); | |
@@ -512,10 +520,30 @@ | |
* The electrical RPM goal value to use. | |
*/ | |
void mcpwm_foc_set_pid_speed(float rpm) { | |
+ // Too low RPM set. Reset state and return. | |
+ if (fabsf(rpm) < m_conf->s_pid_min_erpm) { | |
+ mcpwm_foc_set_duty(0.0); | |
+ return; | |
+ } | |
+ m_control_mode = CONTROL_MODE_SPEED; | |
+ m_speed_pid_set_rpm = rpm; | |
+ m_speed_pid_cruise_control_type = CRUISE_CONTROL_MOTOR_SETTINGS; | |
+ | |
+ if (m_state != MC_STATE_RUNNING) { | |
+ m_state = MC_STATE_RUNNING; | |
+ } | |
+} | |
+ | |
+void mcpwm_foc_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status) { | |
+ if (fabsf(rpm) < m_conf->s_pid_min_erpm) { | |
+ mcpwm_foc_set_duty(0.0); | |
+ return; | |
+ } | |
m_control_mode = CONTROL_MODE_SPEED; | |
m_speed_pid_set_rpm = rpm; | |
+ m_speed_pid_cruise_control_type = cruise_status; | |
- if (m_state != MC_STATE_RUNNING && fabsf(rpm) > m_conf->s_pid_min_erpm) { | |
+ if (m_state != MC_STATE_RUNNING) { | |
m_state = MC_STATE_RUNNING; | |
} | |
} | |
@@ -529,7 +557,7 @@ | |
*/ | |
void mcpwm_foc_set_pid_pos(float pos) { | |
m_control_mode = CONTROL_MODE_POS; | |
- m_pos_pid_set_pos = pos; | |
+ m_pos_pid_set = pos; | |
if (m_state != MC_STATE_RUNNING) { | |
m_state = MC_STATE_RUNNING; | |
@@ -577,7 +605,7 @@ | |
return; | |
} | |
- utils_truncate_number(¤t, m_conf->lo_current_min, m_conf->lo_current_max); | |
+ utils_truncate_number(¤t, m_conf->lo_current_min, fabsf(m_conf->lo_current_min)); | |
m_control_mode = CONTROL_MODE_CURRENT_BRAKE; | |
m_iq_set = current; | |
@@ -595,6 +623,14 @@ | |
return m_motor_state.duty_now; | |
} | |
+float mcpwm_foc_get_pid_pos_set(void) { | |
+ return m_pos_pid_set; | |
+} | |
+ | |
+float mcpwm_foc_get_pid_pos_now(void) { | |
+ return m_pos_pid_now; | |
+} | |
+ | |
/** | |
* Get the current switching frequency. | |
* | |
@@ -702,7 +738,7 @@ | |
* The filtered input current. | |
*/ | |
float mcpwm_foc_get_tot_current_in_filtered(void) { | |
- return m_motor_state.i_bus; // TODO: Calculate filtered current? | |
+ return m_motor_state.i_bus_filter; // TODO: Calculate filtered current? | |
} | |
/** | |
@@ -717,10 +753,10 @@ | |
* be this number divided by (3 * MOTOR_POLE_NUMBER). | |
*/ | |
int mcpwm_foc_get_tachometer_value(bool reset) { | |
- int val = m_tachometer; | |
+ int val = (int) m_tachometer; | |
if (reset) { | |
- m_tachometer = 0; | |
+ m_tachometer = 0.0; | |
} | |
return val; | |
@@ -737,10 +773,10 @@ | |
* be this number divided by (3 * MOTOR_POLE_NUMBER). | |
*/ | |
int mcpwm_foc_get_tachometer_abs_value(bool reset) { | |
- int val = m_tachometer_abs; | |
+ int val = (int) m_tachometer_abs; | |
if (reset) { | |
- m_tachometer_abs = 0; | |
+ m_tachometer_abs = 0.0; | |
} | |
return val; | |
@@ -806,6 +842,8 @@ | |
* The detected direction. | |
*/ | |
void mcpwm_foc_encoder_detect(float current, bool print, float *offset, float *ratio, bool *inverted) { | |
+ mc_interface_lock(); | |
+ | |
m_phase_override = true; | |
m_id_set = current; | |
m_iq_set = 0.0; | |
@@ -815,7 +853,7 @@ | |
// Disable timeout | |
systime_t tout = timeout_get_timeout_msec(); | |
float tout_c = timeout_get_brake_current(); | |
- timeout_configure(60000, 0.0); | |
+ timeout_configure(600000, 0.0); | |
// Save configuration | |
float offset_old = m_conf->foc_encoder_offset; | |
@@ -858,34 +896,68 @@ | |
// Inverted and ratio | |
chThdSleepMilliseconds(1000); | |
+ const int it_rat = 20; | |
float s_sum = 0.0; | |
float c_sum = 0.0; | |
- for (int i = 0; i < 10; i++) { | |
+ float first = m_phase_now_encoder; | |
+ | |
+ for (int i = 0; i < it_rat; i++) { | |
float phase_old = m_phase_now_encoder; | |
float phase_ovr_tmp = m_phase_now_override; | |
- for (float i = phase_ovr_tmp; i < phase_ovr_tmp + 0.8 * M_PI; | |
+ for (float i = phase_ovr_tmp; i < phase_ovr_tmp + (2.0 / 3.0) * M_PI; | |
i += (2.0 * M_PI) / 500.0) { | |
m_phase_now_override = i; | |
- chThdSleepMilliseconds(2); | |
+ chThdSleepMilliseconds(1); | |
+ } | |
+ utils_norm_angle_rad((float*)&m_phase_now_override); | |
+ chThdSleepMilliseconds(300); | |
+ float diff = utils_angle_difference_rad(m_phase_now_encoder, phase_old); | |
+ | |
+ float s, c; | |
+ sincosf(diff, &s, &c); | |
+ s_sum += s; | |
+ c_sum += c; | |
+ | |
+ if (print) { | |
+ commands_printf("%.2f", (double)(diff * 180.0 / M_PI)); | |
+ } | |
+ | |
+ if (i > 3 && fabsf(utils_angle_difference_rad(m_phase_now_encoder, first)) < fabsf(diff / 2.0)) { | |
+ break; | |
+ } | |
+ } | |
+ | |
+ first = m_phase_now_encoder; | |
+ | |
+ for (int i = 0; i < it_rat; i++) { | |
+ float phase_old = m_phase_now_encoder; | |
+ float phase_ovr_tmp = m_phase_now_override; | |
+ for (float i = phase_ovr_tmp; i > phase_ovr_tmp - (2.0 / 3.0) * M_PI; | |
+ i -= (2.0 * M_PI) / 500.0) { | |
+ m_phase_now_override = i; | |
+ chThdSleepMilliseconds(1); | |
} | |
- chThdSleepMilliseconds(1000); | |
- float diff = utils_angle_difference( | |
- m_phase_now_encoder * (180.0 / M_PI), | |
- phase_old * (180.0 / M_PI)); | |
+ utils_norm_angle_rad((float*)&m_phase_now_override); | |
+ chThdSleepMilliseconds(300); | |
+ float diff = utils_angle_difference_rad(phase_old, m_phase_now_encoder); | |
float s, c; | |
- sincosf(diff * M_PI / 180.0, &s, &c); | |
+ sincosf(diff, &s, &c); | |
s_sum += s; | |
c_sum += c; | |
if (print) { | |
- commands_printf("%.2f", (double)diff); | |
+ commands_printf("%.2f", (double)(diff * 180.0 / M_PI)); | |
+ } | |
+ | |
+ if (i > 3 && fabsf(utils_angle_difference_rad(m_phase_now_encoder, first)) < fabsf(diff / 2.0)) { | |
+ break; | |
} | |
} | |
float diff = atan2f(s_sum, c_sum) * 180.0 / M_PI; | |
*inverted = diff < 0.0; | |
- *ratio = roundf((0.8 * 180.0) / | |
+ *ratio = roundf(((2.0 / 3.0) * 180.0) / | |
fabsf(diff)); | |
m_conf->foc_encoder_inverted = *inverted; | |
@@ -906,33 +978,37 @@ | |
commands_printf("Enc: %.2f", (double)encoder_read_deg()); | |
} | |
+ const int it_ofs = m_conf->foc_encoder_ratio * 3.0; | |
s_sum = 0.0; | |
c_sum = 0.0; | |
- for (int i = 0;i < 5;i++) { | |
- m_phase_now_override = (float)i * M_PI / 5.0; | |
- chThdSleepMilliseconds(1000); | |
+ for (int i = 0;i < it_ofs;i++) { | |
+ m_phase_now_override = ((float)i * 2.0 * M_PI * m_conf->foc_encoder_ratio) / ((float)it_ofs); | |
+ chThdSleepMilliseconds(500); | |
+ | |
+ float diff = utils_angle_difference_rad(m_phase_now_encoder, m_phase_now_override); | |
float s, c; | |
- sincosf(m_phase_now_encoder - m_phase_now_override, &s, &c); | |
+ sincosf(diff, &s, &c); | |
s_sum += s; | |
c_sum += c; | |
if (print) { | |
- commands_printf("%.2f", (double)((m_phase_now_encoder - m_phase_now_override) * 180.0 / M_PI)); | |
+ commands_printf("%.2f", (double)(diff * 180.0 / M_PI)); | |
} | |
} | |
- for (int i = 3;i >= -1;i--) { | |
- m_phase_now_override = (float)i * M_PI / 5.0; | |
- chThdSleepMilliseconds(1000); | |
+ for (int i = it_ofs;i > 0;i--) { | |
+ m_phase_now_override = ((float)i * 2.0 * M_PI * m_conf->foc_encoder_ratio) / ((float)it_ofs); | |
+ chThdSleepMilliseconds(500); | |
+ float diff = utils_angle_difference_rad(m_phase_now_encoder, m_phase_now_override); | |
float s, c; | |
- sincosf(m_phase_now_encoder - m_phase_now_override, &s, &c); | |
+ sincosf(diff, &s, &c); | |
s_sum += s; | |
c_sum += c; | |
if (print) { | |
- commands_printf("%.2f", (double)((m_phase_now_encoder - m_phase_now_override) * 180.0 / M_PI)); | |
+ commands_printf("%.2f", (double)(diff * 180.0 / M_PI)); | |
} | |
} | |
@@ -962,6 +1038,8 @@ | |
// Enable timeout | |
timeout_configure(tout, tout_c); | |
+ | |
+ mc_interface_unlock(); | |
} | |
/** | |
@@ -1117,7 +1195,7 @@ | |
float res_tmp = 0.0; | |
float i_last = 0.0; | |
- for (float i = 2.0;i < 35.0;i *= 1.5) { | |
+ for (float i = 2.0;i < (m_conf->l_current_max / 2.0);i *= 1.5) { | |
res_tmp = mcpwm_foc_measure_resistance(i, 20); | |
if (i > (0.5 / res_tmp)) { | |
@@ -1127,7 +1205,7 @@ | |
} | |
if (i_last < 0.01) { | |
- i_last = 35.0; | |
+ i_last = (m_conf->l_current_max / 2.0); | |
} | |
*res = mcpwm_foc_measure_resistance(i_last, 500); | |
@@ -1137,7 +1215,7 @@ | |
TIMER_UPDATE_SAMP_TOP(top - 2, 5, top); | |
float duty_last = 0.0; | |
- for (float i = 0.02;i < 0.9;i *= 1.5) { | |
+ for (float i = 0.02;i < 0.5;i *= 1.5) { | |
float i_tmp; | |
mcpwm_foc_measure_inductance(i, 20, &i_tmp); | |
@@ -1159,6 +1237,101 @@ | |
return true; | |
} | |
+/** | |
+ * Run the motor in open loop and figure out at which angles the hall sensors are. | |
+ * | |
+ * @param current | |
+ * Current to use. | |
+ * | |
+ * @param hall_table | |
+ * Table to store the result to. | |
+ * | |
+ * @return | |
+ * true: Success | |
+ * false: Something went wrong | |
+ */ | |
+bool mcpwm_foc_hall_detect(float current, uint8_t *hall_table) { | |
+ mc_interface_lock(); | |
+ | |
+ m_phase_override = true; | |
+ m_id_set = current; | |
+ m_iq_set = 0.0; | |
+ m_control_mode = CONTROL_MODE_CURRENT; | |
+ m_state = MC_STATE_RUNNING; | |
+ | |
+ // Disable timeout | |
+ systime_t tout = timeout_get_timeout_msec(); | |
+ float tout_c = timeout_get_brake_current(); | |
+ timeout_configure(60000, 0.0); | |
+ | |
+ // Lock the motor | |
+ m_phase_now_override = 0; | |
+ chThdSleepMilliseconds(1000); | |
+ | |
+ float sin_hall[8]; | |
+ float cos_hall[8]; | |
+ int hall_iterations[8]; | |
+ memset(sin_hall, 0, sizeof(sin_hall)); | |
+ memset(cos_hall, 0, sizeof(cos_hall)); | |
+ memset(hall_iterations, 0, sizeof(hall_iterations)); | |
+ | |
+ // Forwards | |
+ for (int i = 0;i < 3;i++) { | |
+ for (int i = 0;i < 360;i++) { | |
+ m_phase_now_override = (float)i * M_PI / 180.0; | |
+ chThdSleepMilliseconds(5); | |
+ | |
+ int hall = read_hall(); | |
+ float s, c; | |
+ sincosf(m_phase_now_override, &s, &c); | |
+ sin_hall[hall] += s; | |
+ cos_hall[hall] += c; | |
+ hall_iterations[hall]++; | |
+ } | |
+ } | |
+ | |
+ // Reverse | |
+ for (int i = 0;i < 3;i++) { | |
+ for (int i = 360;i >= 0;i--) { | |
+ m_phase_now_override = (float)i * M_PI / 180.0; | |
+ chThdSleepMilliseconds(5); | |
+ | |
+ int hall = read_hall(); | |
+ float s, c; | |
+ sincosf(m_phase_now_override, &s, &c); | |
+ sin_hall[hall] += s; | |
+ cos_hall[hall] += c; | |
+ hall_iterations[hall]++; | |
+ } | |
+ } | |
+ | |
+ m_id_set = 0.0; | |
+ m_iq_set = 0.0; | |
+ m_phase_override = false; | |
+ m_control_mode = CONTROL_MODE_NONE; | |
+ m_state = MC_STATE_OFF; | |
+ stop_pwm_hw(); | |
+ | |
+ // Enable timeout | |
+ timeout_configure(tout, tout_c); | |
+ | |
+ int fails = 0; | |
+ for(int i = 0;i < 8;i++) { | |
+ if (hall_iterations[i] > 30) { | |
+ float ang = atan2f(sin_hall[i], cos_hall[i]) * 180.0 / M_PI; | |
+ utils_norm_angle(&ang); | |
+ hall_table[i] = (uint8_t)(ang * 200.0 / 360.0); | |
+ } else { | |
+ hall_table[i] = 255; | |
+ fails++; | |
+ } | |
+ } | |
+ | |
+ mc_interface_unlock(); | |
+ | |
+ return fails == 2; | |
+} | |
+ | |
void mcpwm_foc_print_state(void) { | |
commands_printf("Mod d: %.2f", (double)m_motor_state.mod_d); | |
commands_printf("Mod q: %.2f", (double)m_motor_state.mod_q); | |
@@ -1259,16 +1432,18 @@ | |
m_motor_state.v_bus = GET_INPUT_VOLTAGE(); | |
-#if ENCODER_ENABLE | |
- float phase_tmp = encoder_read_deg(); | |
- if (m_conf->foc_encoder_inverted) { | |
- phase_tmp = 360.0 - phase_tmp; | |
- } | |
- phase_tmp *= m_conf->foc_encoder_ratio; | |
- phase_tmp -= m_conf->foc_encoder_offset; | |
- utils_norm_angle((float*)&phase_tmp); | |
- m_phase_now_encoder = phase_tmp * (M_PI / 180.0); | |
-#endif | |
+ float enc_ang = 0; | |
+ if (encoder_is_configured()) { | |
+ enc_ang = encoder_read_deg(); | |
+ float phase_tmp = enc_ang; | |
+ if (m_conf->foc_encoder_inverted) { | |
+ phase_tmp = 360.0 - phase_tmp; | |
+ } | |
+ phase_tmp *= m_conf->foc_encoder_ratio; | |
+ phase_tmp -= m_conf->foc_encoder_offset; | |
+ utils_norm_angle((float*)&phase_tmp); | |
+ m_phase_now_encoder = phase_tmp * (M_PI / 180.0); | |
+ } | |
static float phase_before = 0.0; | |
const float phase_diff = utils_angle_difference_rad(m_motor_state.phase, phase_before); | |
@@ -1299,12 +1474,19 @@ | |
// observer has lost tracking. Use duty cycle control with the lowest duty cycle | |
// to get as smooth braking as possible. | |
if (m_control_mode == CONTROL_MODE_CURRENT_BRAKE | |
- && m_conf->foc_sensor_mode == FOC_SENSOR_MODE_SENSORLESS | |
+// && (m_conf->foc_sensor_mode != FOC_SENSOR_MODE_ENCODER) // Don't use this with encoderss | |
&& fabsf(duty_filtered) < 0.03) { | |
control_duty = true; | |
duty_set = 0.0; | |
} | |
+ // Brake when set ERPM is below min ERPM | |
+ if (m_control_mode == CONTROL_MODE_SPEED && | |
+ fabsf(m_speed_pid_set_rpm) < m_conf->s_pid_min_erpm) { | |
+ control_duty = true; | |
+ duty_set = 0.0; | |
+ } | |
+ | |
if (control_duty) { | |
// Duty cycle control | |
static float duty_i_term = 0.0; | |
@@ -1361,7 +1543,7 @@ | |
switch (m_conf->foc_sensor_mode) { | |
case FOC_SENSOR_MODE_ENCODER: | |
if (encoder_index_found()) { | |
- m_motor_state.phase = m_phase_now_encoder; | |
+ m_motor_state.phase = correct_encoder(m_phase_now_observer, m_phase_now_encoder, m_pll_speed); | |
} else { | |
// Rotate the motor in open loop if the index isn't found. | |
m_motor_state.phase = m_phase_now_encoder_no_index; | |
@@ -1371,6 +1553,14 @@ | |
id_set_tmp = 0.0; | |
} | |
break; | |
+ case FOC_SENSOR_MODE_HALL: | |
+ m_phase_now_observer = correct_hall(m_phase_now_observer, m_pll_speed, dt); | |
+ m_motor_state.phase = m_phase_now_observer; | |
+ | |
+ if (!m_phase_override) { | |
+ id_set_tmp = 0.0; | |
+ } | |
+ break; | |
case FOC_SENSOR_MODE_SENSORLESS: | |
if (m_phase_observer_override) { | |
m_motor_state.phase = m_phase_now_observer_override; | |
@@ -1400,7 +1590,12 @@ | |
// Apply current limits | |
const float mod_q = m_motor_state.mod_q; | |
utils_truncate_number(&iq_set_tmp, m_conf->lo_current_min, m_conf->lo_current_max); | |
- utils_saturate_vector_2d(&id_set_tmp, &iq_set_tmp, m_conf->lo_current_max); | |
+ if (iq_set_tmp < 0.0) { | |
+ utils_saturate_vector_2d(&id_set_tmp, &iq_set_tmp, m_conf->lo_current_min); | |
+ } else { | |
+ | |
+ utils_saturate_vector_2d(&id_set_tmp, &iq_set_tmp, m_conf->lo_current_max); | |
+ } | |
if (mod_q > 0.001) { | |
utils_truncate_number(&iq_set_tmp, m_conf->lo_in_current_min / mod_q, m_conf->lo_in_current_max / mod_q); | |
} else if (mod_q < -0.001) { | |
@@ -1411,7 +1606,6 @@ | |
m_motor_state.iq_target = iq_set_tmp; | |
control_current(&m_motor_state, dt); | |
- run_pid_control_pos(dt); | |
} else { | |
// Track back emf | |
float Va = ADC_VOLTS(ADC_IND_SENS1) * ((VIN_R1 + VIN_R2) / VIN_R2); | |
@@ -1440,6 +1634,7 @@ | |
m_motor_state.id_filter = 0.0; | |
m_motor_state.iq_filter = 0.0; | |
m_motor_state.i_bus = 0.0; | |
+ m_motor_state.i_bus_filter = 0.0; | |
m_motor_state.i_abs = 0.0; | |
m_motor_state.i_abs_filter = 0.0; | |
@@ -1449,8 +1644,16 @@ | |
&m_observer_x2, &m_phase_now_observer); | |
switch (m_conf->foc_sensor_mode) { | |
- case FOC_SENSOR_MODE_ENCODER: m_motor_state.phase = m_phase_now_encoder; break; | |
- case FOC_SENSOR_MODE_SENSORLESS: m_motor_state.phase = m_phase_now_observer; break; | |
+ case FOC_SENSOR_MODE_ENCODER: | |
+ m_motor_state.phase = correct_encoder(m_phase_now_observer, m_phase_now_encoder, m_pll_speed); | |
+ break; | |
+ case FOC_SENSOR_MODE_HALL: | |
+ m_phase_now_observer = correct_hall(m_phase_now_observer, m_pll_speed, dt); | |
+ m_motor_state.phase = m_phase_now_observer; | |
+ break; | |
+ case FOC_SENSOR_MODE_SENSORLESS: | |
+ m_motor_state.phase = m_phase_now_observer; | |
+ break; | |
} | |
} | |
@@ -1464,13 +1667,38 @@ | |
// Update tachometer | |
static float phase_last = 0.0; | |
- int diff = (int)((utils_angle_difference_rad(m_motor_state.phase, phase_last) * (180.0 / M_PI)) / 60.0); | |
- if (diff != 0) { | |
+ // int diff = (int)((utils_angle_difference_rad(m_motor_state.phase, phase_last) * (180.0 / M_PI)) / 60.0); | |
+ float diff = (utils_angle_difference_rad(m_motor_state.phase, phase_last) * (180.0 / M_PI)) / 60.0; | |
+ if ((int) diff != 0) { | |
m_tachometer += diff; | |
- m_tachometer_abs += abs(diff); | |
+ m_tachometer_abs += fabsf(diff); | |
phase_last = m_motor_state.phase; | |
} | |
+ // Track position control angle | |
+ // TODO: Have another look at this. | |
+ float angle_now = 0.0; | |
+ if (encoder_is_configured()) { | |
+ angle_now = enc_ang; | |
+ } else { | |
+ angle_now = m_motor_state.phase * (180.0 / M_PI); | |
+ } | |
+ | |
+ if (m_conf->p_pid_ang_div > 0.98 && m_conf->p_pid_ang_div < 1.02) { | |
+ m_pos_pid_now = angle_now; | |
+ } else { | |
+ static float angle_last = 0.0; | |
+ float diff_f = utils_angle_difference(angle_now, angle_last); | |
+ angle_last = angle_now; | |
+ m_pos_pid_now += diff_f / m_conf->p_pid_ang_div; | |
+ utils_norm_angle((float*)&m_pos_pid_now); | |
+ } | |
+ | |
+ // Run position control | |
+ if (m_state == MC_STATE_RUNNING) { | |
+ run_pid_control_pos(m_pos_pid_now, m_pos_pid_set, dt); | |
+ } | |
+ | |
// MCIF handler | |
mc_interface_mc_timer_isr(); | |
@@ -1490,8 +1718,12 @@ | |
return; | |
} | |
+ float openloop_rpm = utils_map(fabsf(m_motor_state.iq_target), | |
+ 0.0, m_conf->lo_current_max, | |
+ 0.0, m_conf->foc_openloop_rpm); | |
+ | |
const float dt = 0.001; | |
- const float min_rads = (m_conf->foc_openloop_rpm * 2.0 * M_PI) / 60.0; | |
+ const float min_rads = (openloop_rpm * 2.0 * M_PI) / 60.0; | |
static float min_rpm_hyst_timer = 0.0; | |
static float min_rpm_timer = 0.0; | |
@@ -1514,7 +1746,7 @@ | |
} | |
// Don't use this in brake mode. | |
- if (m_control_mode == CONTROL_MODE_CURRENT_BRAKE) { | |
+ if (m_control_mode == CONTROL_MODE_CURRENT_BRAKE || fabsf(m_motor_state.duty_now) < 0.001) { | |
min_rpm_hyst_timer = 0.0; | |
m_phase_observer_override = false; | |
} | |
@@ -1671,19 +1903,13 @@ | |
// TODO: Have a look at this? | |
state_m->i_bus = state_m->mod_d * state_m->id + state_m->mod_q * state_m->iq; | |
+ UTILS_LP_FAST(state_m->i_bus_filter, state_m->i_bus, MCPWM_FOC_I_FILTER_CONST); | |
state_m->i_abs = sqrtf(state_m->id * state_m->id + state_m->iq * state_m->iq); | |
state_m->i_abs_filter = sqrtf(state_m->id_filter * state_m->id_filter + state_m->iq_filter * state_m->iq_filter); | |
float mod_alpha = c * state_m->mod_d - s * state_m->mod_q; | |
float mod_beta = c * state_m->mod_q + s * state_m->mod_d; | |
- state_m->v_alpha = mod_alpha * (2.0 / 3.0) * state_m->v_bus; | |
- state_m->v_beta = mod_beta * (2.0 / 3.0) * state_m->v_bus; | |
- | |
- // Set output (HW Dependent) | |
- uint32_t duty1, duty2, duty3, top; | |
- top = TIM1->ARR; | |
- | |
// Deadtime compensation | |
const float i_alpha_set = c * state_m->id_target - s * state_m->iq_target; | |
const float i_beta_set = c * state_m->iq_target + s * state_m->id_target; | |
@@ -1692,10 +1918,20 @@ | |
const float ic_set = -0.5 * i_alpha_set - SQRT3_BY_2 * i_beta_set; | |
const float mod_alpha_set_sgn = (2.0 / 3.0) * SIGN(ia_set) - (1.0 / 3.0) * SIGN(ib_set) - (1.0 / 3.0) * SIGN(ic_set); | |
const float mod_beta_set_sgn = ONE_BY_SQRT3 * SIGN(ib_set) - ONE_BY_SQRT3 * SIGN(ic_set); | |
+ const float mod_comp_fact = m_conf->foc_dt_us * 1e-6 * m_conf->foc_f_sw; | |
+ const float mod_alpha_comp = mod_alpha_set_sgn * mod_comp_fact; | |
+ const float mod_beta_comp = mod_beta_set_sgn * mod_comp_fact; | |
+ | |
+// mod_alpha += mod_alpha_comp; | |
+// mod_beta += mod_beta_comp; | |
+ | |
+ // Apply compensation here so that 0 duty cyle has no glitches. | |
+ state_m->v_alpha = (mod_alpha - mod_alpha_comp) * (2.0 / 3.0) * state_m->v_bus; | |
+ state_m->v_beta = (mod_beta - mod_beta_comp) * (2.0 / 3.0) * state_m->v_bus; | |
- mod_alpha += mod_alpha_set_sgn * m_conf->foc_dt_us * 1e-6 * m_conf->foc_f_sw; | |
- mod_beta += mod_beta_set_sgn * m_conf->foc_dt_us * 1e-6 * m_conf->foc_f_sw; | |
- | |
+ // Set output (HW Dependent) | |
+ uint32_t duty1, duty2, duty3, top; | |
+ top = TIM1->ARR; | |
svm(-mod_alpha, -mod_beta, top, &duty1, &duty2, &duty3); | |
TIMER_UPDATE_DUTY(duty1, duty2, duty3); | |
@@ -1834,7 +2070,7 @@ | |
*tCout = tC; | |
} | |
-static void run_pid_control_pos(float dt) { | |
+static void run_pid_control_pos(float angle_now, float angle_set, float dt) { | |
static float i_term = 0; | |
static float prev_error = 0; | |
float p_term; | |
@@ -1847,19 +2083,30 @@ | |
return; | |
} | |
- // Compute error | |
- float angle = encoder_read_deg(); | |
- float error = utils_angle_difference(m_pos_pid_set_pos, angle); | |
+ // Compute parameters | |
+ float error = utils_angle_difference(angle_set, angle_now); | |
- if (m_conf->foc_encoder_inverted) { | |
- error = -error; | |
+ if (encoder_is_configured()) { | |
+ if (m_conf->foc_encoder_inverted) { | |
+ error = -error; | |
+ } | |
} | |
- | |
- // Compute parameters | |
p_term = error * m_conf->p_pid_kp; | |
i_term += error * (m_conf->p_pid_ki * dt); | |
- d_term = (error - prev_error) * (m_conf->p_pid_kd / dt); | |
+ | |
+ // Average DT for the D term when the error does not change. This likely | |
+ // happens at low speed when the position resolution is low and several | |
+ // control iterations run without position updates. | |
+ // TODO: Are there problems with this approach? | |
+ static float dt_int = 0.0; | |
+ dt_int += dt; | |
+ if (error == prev_error) { | |
+ d_term = 0.0; | |
+ } else { | |
+ d_term = (error - prev_error) * (m_conf->p_pid_kd / dt_int); | |
+ dt_int = 0.0; | |
+ } | |
// I-term wind-up protection | |
utils_truncate_number(&i_term, -1.0, 1.0); | |
@@ -1871,11 +2118,15 @@ | |
float output = p_term + i_term + d_term; | |
utils_truncate_number(&output, -1.0, 1.0); | |
- if (encoder_index_found()) { | |
- m_iq_set = output * m_conf->lo_current_max; | |
+ if (encoder_is_configured()) { | |
+ if (encoder_index_found()) { | |
+ m_iq_set = output * m_conf->lo_current_max; | |
+ } else { | |
+ // Rotate the motor with 40 % power until the encoder index is found. | |
+ m_iq_set = 0.4 * m_conf->lo_current_max; | |
+ } | |
} else { | |
- // Rotate the motor with 40 % power until the encoder index is found. | |
- m_iq_set = 0.4 * m_conf->lo_current_max; | |
+ m_iq_set = output * m_conf->lo_current_max; | |
} | |
} | |
@@ -1892,15 +2143,11 @@ | |
return; | |
} | |
- // Too low RPM set. Stop and return. | |
+ // Too low RPM set. Reset state and return. | |
if (fabsf(m_speed_pid_set_rpm) < m_conf->s_pid_min_erpm) { | |
i_term = 0.0; | |
prev_error = 0; | |
m_iq_set = 0.0; | |
- m_state = MC_STATE_OFF; | |
- if (m_output_on) { | |
- stop_pwm_hw(); | |
- } | |
return; | |
} | |
@@ -1923,8 +2170,17 @@ | |
// Calculate output | |
float output = p_term + i_term + d_term; | |
- utils_truncate_number(&output, -1.0, 1.0); | |
+ if ((m_speed_pid_cruise_control_type == CRUISE_CONTROL_MOTOR_SETTINGS && m_conf->s_pid_breaking_enabled) || m_speed_pid_cruise_control_type == CRUISE_CONTROL_BRAKING_ENABLED) { | |
+ utils_truncate_number(&output, -1.0, 1.0); | |
+ } else { | |
+ if(m_speed_pid_set_rpm < 0.0){ | |
+ utils_truncate_number(&output, -1.0, 0.0); | |
+ }else{ | |
+ utils_truncate_number(&output, 0.0, 1.0); | |
+ } | |
+ } | |
+ | |
m_iq_set = output * m_conf->lo_current_max; | |
} | |
@@ -1963,3 +2219,113 @@ | |
m_output_on = true; | |
} | |
+ | |
+static int read_hall(void) { | |
+ return READ_HALL1() | (READ_HALL2() << 1) | (READ_HALL3() << 2); | |
+} | |
+ | |
+static float correct_encoder(float obs_angle, float enc_angle, float speed) { | |
+ float rpm_abs = fabsf(speed / ((2.0 * M_PI) / 60.0)); | |
+ static bool using_encoder = true; | |
+ | |
+ // Hysteresis 5 % of total speed | |
+ float hyst = m_conf->foc_sl_erpm * 0.05; | |
+ if (using_encoder) { | |
+ if (rpm_abs > (m_conf->foc_sl_erpm + hyst)) { | |
+ using_encoder = false; | |
+ } | |
+ } else { | |
+ if (rpm_abs < (m_conf->foc_sl_erpm - hyst)) { | |
+ using_encoder = true; | |
+ } | |
+ } | |
+ | |
+ return using_encoder ? enc_angle : obs_angle; | |
+} | |
+ | |
+static float correct_hall(float angle, float speed, float dt) { | |
+ static int ang_hall_int_prev = -1; | |
+ float rpm_abs = fabsf(speed / ((2.0 * M_PI) / 60.0)); | |
+ static bool using_hall = true; | |
+ | |
+ // Hysteresis 10 % of total speed | |
+ float hyst = m_conf->foc_sl_erpm * 0.10; | |
+ if (using_hall) { | |
+ if (rpm_abs > (m_conf->foc_sl_erpm + hyst)) { | |
+ using_hall = false; | |
+ } | |
+ } else { | |
+ if (rpm_abs < (m_conf->foc_sl_erpm - hyst)) { | |
+ using_hall = true; | |
+ } | |
+ } | |
+ | |
+ if (using_hall) { | |
+ int ang_hall_int = m_conf->foc_hall_table[read_hall()]; | |
+ | |
+ // Only override the observer if the hall sensor value is valid. | |
+ if (ang_hall_int < 201) { | |
+ static float ang_hall = 0.0; | |
+ float ang_hall_now = (((float)ang_hall_int / 200.0) * 360.0) * M_PI / 180.0; | |
+ | |
+ if (ang_hall_int_prev < 0) { | |
+ // Previous angle not valid | |
+ ang_hall_int_prev = ang_hall_int; | |
+ | |
+ if (ang_hall_int_prev == -2) { | |
+ // Before was sensorless, initialize with the provided angle | |
+ ang_hall = angle; | |
+ } else { | |
+ // A boot or error has occurred. Use center of hall sensor angle. | |
+ ang_hall = ((ang_hall_int / 200.0) * 360.0) * M_PI / 180.0; | |
+ } | |
+ } else if (ang_hall_int != ang_hall_int_prev) { | |
+ // A transition was just made. The angle is in the middle of the new and old angle. | |
+ int ang_avg = abs(ang_hall_int - ang_hall_int_prev); | |
+ if (ang_avg < 100) { | |
+ ang_avg = (ang_hall_int + ang_hall_int_prev) / 2; | |
+ } else if (ang_avg != 100) { | |
+ ang_avg = (ang_hall_int + ang_hall_int_prev) / 2 + 100; | |
+ } | |
+ ang_avg %= 200; | |
+ ang_hall = (((float)ang_avg / 200.0) * 360.0) * M_PI / 180.0; | |
+ } | |
+ | |
+ ang_hall_int_prev = ang_hall_int; | |
+ | |
+ if (rpm_abs < 100) { | |
+ // Don't interpolate on very low speed, just use the closest hall sensor | |
+ ang_hall = ang_hall_now; | |
+ } else { | |
+ // Interpolate | |
+ float diff = utils_angle_difference_rad(ang_hall, ang_hall_now); | |
+ if (fabsf(diff) < ((2.0 * M_PI) / 12.0)) { | |
+ // Do interpolation | |
+ ang_hall += speed * dt; | |
+ } else { | |
+ // We are too far away with the interpolation | |
+ ang_hall -= diff / 100.0; | |
+ } | |
+ } | |
+ | |
+ utils_norm_angle_rad(&ang_hall); | |
+ | |
+ angle = ang_hall; | |
+ } else { | |
+ // Invalid hall reading. Don't update angle. | |
+ ang_hall_int_prev = -1; | |
+ | |
+ // Also allow open loop in order to behave like normal sensorless | |
+ // operation. Then the motor works even if the hall sensor cable | |
+ // gets disconnected (when the sensor spacing is 120 degrees). | |
+ if (m_phase_observer_override && m_state == MC_STATE_RUNNING) { | |
+ angle = m_phase_now_observer_override; | |
+ } | |
+ } | |
+ } else { | |
+ // We are running sensorless. | |
+ ang_hall_int_prev = -2; | |
+ } | |
+ | |
+ return angle; | |
+} | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcpwm_foc.h Raptor2 Sources/bldc-firmware_2_80/mcpwm_foc.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcpwm_foc.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcpwm_foc.h 2017-04-13 18:06:44.000000000 +0100 | |
@@ -39,11 +39,14 @@ | |
void mcpwm_foc_set_duty(float dutyCycle); | |
void mcpwm_foc_set_duty_noramp(float dutyCycle); | |
void mcpwm_foc_set_pid_speed(float rpm); | |
+void mcpwm_foc_set_pid_speed_with_cruise_status(float rpm, ppm_cruise cruise_status); | |
void mcpwm_foc_set_pid_pos(float pos); | |
void mcpwm_foc_set_current(float current); | |
void mcpwm_foc_set_brake_current(float current); | |
float mcpwm_foc_get_duty_cycle_set(void); | |
float mcpwm_foc_get_duty_cycle_now(void); | |
+float mcpwm_foc_get_pid_pos_set(void); | |
+float mcpwm_foc_get_pid_pos_now(void); | |
float mcpwm_foc_get_switching_frequency_now(void); | |
float mcpwm_foc_get_rpm(void); | |
float mcpwm_foc_get_tot_current(void); | |
@@ -65,6 +68,7 @@ | |
float mcpwm_foc_measure_resistance(float current, int samples); | |
float mcpwm_foc_measure_inductance(float duty, int samples, float *curr); | |
bool mcpwm_foc_measure_res_ind(float *res, float *ind); | |
+bool mcpwm_foc_hall_detect(float current, uint8_t *hall_table); | |
void mcpwm_foc_print_state(void); | |
float mcpwm_foc_get_last_inj_adc_isr_duration(void); | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcuconf.h Raptor2 Sources/bldc-firmware_2_80/mcuconf.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/mcuconf.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/mcuconf.h 2016-09-19 10:05:44.000000000 +0100 | |
@@ -248,7 +248,7 @@ | |
/* | |
* SPI driver system settings. | |
*/ | |
-#define STM32_SPI_USE_SPI1 FALSE | |
+#define STM32_SPI_USE_SPI1 TRUE | |
#define STM32_SPI_USE_SPI2 FALSE | |
#define STM32_SPI_USE_SPI3 FALSE | |
#define STM32_SPI_SPI1_RX_DMA_STREAM STM32_DMA_STREAM_ID(2, 0) | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/nrf/nrf_driver.c Raptor2 Sources/bldc-firmware_2_80/nrf/nrf_driver.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/nrf/nrf_driver.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/nrf/nrf_driver.c 2016-08-04 23:47:30.000000000 +0100 | |
@@ -37,9 +37,6 @@ | |
#define MAX_PL_LEN 25 | |
#define RX_BUFFER_SIZE PACKET_MAX_PL_LEN | |
-#define NOACK 0 | |
-#define TX_RESENDS 1 | |
- | |
#define ALIVE_INTERVAL 50 // Send alive packets at this rate | |
#define NRF_RESTART_TIMEOUT 500 // Restart the NRF if nothing has been received or acked for this time | |
@@ -58,28 +55,18 @@ | |
static int rf_tx_wrapper(char *data, int len); | |
void nrf_driver_init(void) { | |
- rf_init(); | |
rfhelp_init(); | |
nosend_cnt = 0; | |
nrf_restart_rx_time = 0; | |
nrf_restart_tx_time = 0; | |
- // Set RF address | |
- const char addr[3] = {0xC6, 0xC7, app_get_configuration()->controller_id}; | |
- rfhelp_set_rx_addr(0, addr, 3); | |
- rfhelp_set_tx_addr(addr, 3); | |
- | |
chThdCreateStatic(rx_thread_wa, sizeof(rx_thread_wa), NORMALPRIO - 1, rx_thread, NULL); | |
chThdCreateStatic(tx_thread_wa, sizeof(tx_thread_wa), NORMALPRIO - 1, tx_thread, NULL); | |
} | |
static int rf_tx_wrapper(char *data, int len) { | |
-#if NOACK | |
- int res = rfhelp_send_data_crc_noack(data, len, TX_RESENDS); | |
-#else | |
int res = rfhelp_send_data_crc(data, len); | |
-#endif | |
if (res == 0) { | |
nrf_restart_tx_time = NRF_RESTART_TIMEOUT; | |
@@ -120,11 +107,7 @@ | |
int pipe; | |
for(;;) { | |
-#if NOACK | |
- int res = rfhelp_read_rx_data_crc_noack((char*)buf, &len, &pipe); | |
-#else | |
int res = rfhelp_read_rx_data_crc((char*)buf, &len, &pipe); | |
-#endif | |
chuck_data cdata; | |
int32_t ind = 0; | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/nrf/rf.c Raptor2 Sources/bldc-firmware_2_80/nrf/rf.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/nrf/rf.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/nrf/rf.c 2016-08-04 23:47:30.000000000 +0100 | |
@@ -22,32 +22,6 @@ | |
void rf_init(void) { | |
spi_sw_init(); | |
- | |
- rf_power_down(); | |
- | |
- // Set default register values (TODO for the rest) | |
- rf_write_reg_byte(NRF_REG_EN_RXADDR, 0); | |
- rf_write_reg_byte(NRF_REG_DYNPD, 0); | |
- | |
- rf_set_crc_type(NRF_CRC_1B); | |
- rf_set_retr_retries(3); | |
- rf_set_retr_delay(NRF_RETR_DELAY_250US); | |
- rf_set_power(NRF_POWER_0DBM); | |
- rf_set_speed(NRF_SPEED_2M); | |
- rf_set_address_width(NRF_AW_3); | |
- rf_set_frequency(2400 + 76); | |
- rf_enable_features(NRF_FEATURE_DPL | NRF_FEATURE_DYN_ACK); | |
- | |
- rf_enable_pipe_autoack(NRF_MASK_PIPE0); | |
- rf_enable_pipe_address(NRF_MASK_PIPE0); | |
- rf_enable_pipe_dlp(NRF_MASK_PIPE0); | |
- | |
- // Note: The address should be set by the application. | |
- | |
- rf_power_up(); | |
- rf_mode_rx(); | |
- rf_flush_all(); | |
- rf_clear_irq(); | |
} | |
void rf_set_speed(NRF_SPEED speed) { | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/nrf/rf.h Raptor2 Sources/bldc-firmware_2_80/nrf/rf.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/nrf/rf.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/nrf/rf.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -20,51 +20,7 @@ | |
#define RF_H_ | |
#include <stdint.h> | |
- | |
-// Data types | |
-typedef enum { | |
- NRF_SPEED_250K = 0, | |
- NRF_SPEED_1M, | |
- NRF_SPEED_2M | |
-} NRF_SPEED; | |
- | |
-typedef enum { | |
- NRF_POWER_M18DBM = 0, | |
- NRF_POWER_M12DBM, | |
- NRF_POWER_M6DBM, | |
- NRF_POWER_0DBM | |
-} NRF_POWER; | |
- | |
-typedef enum { | |
- NRF_AW_3 = 0, | |
- NRF_AW_4, | |
- NRF_AW_5 | |
-} NRF_AW; | |
- | |
-typedef enum { | |
- NRF_CRC_DISABLED = 0, | |
- NRF_CRC_1B, | |
- NRF_CRC_2B | |
-} NRF_CRC; | |
- | |
-typedef enum { | |
- NRF_RETR_DELAY_250US = 0, | |
- NRF_RETR_DELAY_500US, | |
- NRF_RETR_DELAY_750US, | |
- NRF_RETR_DELAY_1000US, | |
- NRF_RETR_DELAY_1250US, | |
- NRF_RETR_DELAY_1500US, | |
- NRF_RETR_DELAY_1750US, | |
- NRF_RETR_DELAY_2000US, | |
- NRF_RETR_DELAY_2250US, | |
- NRF_RETR_DELAY_2500US, | |
- NRF_RETR_DELAY_2750US, | |
- NRF_RETR_DELAY_3000US, | |
- NRF_RETR_DELAY_3250US, | |
- NRF_RETR_DELAY_3500US, | |
- NRF_RETR_DELAY_3750US, | |
- NRF_RETR_DELAY_4000US | |
-} NRF_RETR_DELAY; | |
+#include <datatypes.h> | |
// Status register masks | |
#define NRF_STATUS_TX_FULL (1<<0) | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/nrf/rfhelp.c Raptor2 Sources/bldc-firmware_2_80/nrf/rfhelp.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/nrf/rfhelp.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/nrf/rfhelp.c 2016-08-04 23:47:30.000000000 +0100 | |
@@ -29,25 +29,41 @@ | |
static bool rx_addr_set[6]; | |
static int address_length; | |
static bool tx_pipe0_addr_eq; | |
+static nrf_config nrf_conf; | |
+static bool init_done = false; | |
void rfhelp_init(void) { | |
chMtxObjectInit(&rf_mutex); | |
+ rf_init(); | |
// address_length = rf_get_address_width(); | |
address_length = 3; // We assume length 3 | |
// This should not happen | |
if (address_length > 5 || address_length < 3) { | |
- address_length = 5; | |
+ address_length = 3; | |
} | |
for (int i = 0;i < 6;i++) { | |
rf_read_reg(NRF_REG_RX_ADDR_P0, rx_addr[i], address_length); | |
rx_addr_set[i] = false; | |
} | |
- rf_read_reg(NRF_REG_TX_ADDR, tx_addr, address_length); | |
+ rf_read_reg(NRF_REG_TX_ADDR, tx_addr, address_length); | |
tx_pipe0_addr_eq = memcmp(rx_addr[0], tx_addr, address_length) == 0; | |
+ | |
+ // TODO: fill nrf_conf with values from the nrf chip. For now we assume | |
+ // that nrf_conf is already set when rfhelp_restart is called. | |
+ | |
+ init_done = true; | |
+} | |
+ | |
+void rfhelp_update_conf(nrf_config *conf) { | |
+ nrf_conf = *conf; | |
+ | |
+ if (init_done) { | |
+ rfhelp_restart(); | |
+ } | |
} | |
/** | |
@@ -56,13 +72,38 @@ | |
void rfhelp_restart(void) { | |
chMtxLock(&rf_mutex); | |
- rf_init(); | |
+ rf_power_down(); | |
+ | |
+ // Set default register values. | |
+ // TODO: make this file consistent with multiple | |
+ // rx_addr and tx_addr, and the rest in general. | |
+ rf_write_reg_byte(NRF_REG_EN_RXADDR, 0); | |
+ rf_write_reg_byte(NRF_REG_DYNPD, 0); | |
+ | |
+ rf_set_crc_type(nrf_conf.crc_type); | |
+ rf_set_retr_retries(nrf_conf.retries); | |
+ rf_set_retr_delay(nrf_conf.retry_delay); | |
+ rf_set_power(nrf_conf.power); | |
+ rf_set_speed(nrf_conf.speed); | |
+ rf_set_address_width(NRF_AW_3); // Always use 3 byte address | |
+ rf_set_frequency(2400 + (unsigned int)nrf_conf.channel); | |
+ rf_enable_features(NRF_FEATURE_DPL | NRF_FEATURE_DYN_ACK); | |
+ | |
+ rf_enable_pipe_autoack(NRF_MASK_PIPE0); | |
+ rf_enable_pipe_address(NRF_MASK_PIPE0); | |
+ rf_enable_pipe_dlp(NRF_MASK_PIPE0); | |
+ | |
+ memcpy(tx_addr, nrf_conf.address, 3); | |
+ memcpy(rx_addr[0], nrf_conf.address, 3); | |
+ tx_pipe0_addr_eq = true; | |
+ | |
rf_set_tx_addr(tx_addr, address_length); | |
- for (int i = 0;i < 6;i++) { | |
- if (rx_addr_set[i]) { | |
- rf_set_rx_addr(i, rx_addr[i], address_length); | |
- } | |
- } | |
+ rf_set_rx_addr(0, rx_addr[0], address_length); | |
+ | |
+ rf_power_up(); | |
+ rf_mode_rx(); | |
+ rf_flush_all(); | |
+ rf_clear_irq(); | |
chMtxUnlock(&rf_mutex); | |
} | |
@@ -157,48 +198,7 @@ | |
buffer[len] = (char)(crc >> 8); | |
buffer[len + 1] = (char)(crc & 0xFF); | |
- return rfhelp_send_data(buffer, len + 2, true); | |
-} | |
- | |
-/** | |
- * Same as rfhelp_send_data_crc, but without ack. A counter is included for | |
- * duplicate packets and a number of resends can be specified. | |
- * | |
- * @param data | |
- * The data to be sent. | |
- * | |
- * @param len | |
- * Length of the data. Should be no more than 29 bytes. | |
- * | |
- * @param resends | |
- * The amount of resends for this packet. Should be at least 1. | |
- * | |
- * @return | |
- * 0: Send OK. | |
- * -1: Max RT. (Should not happen) | |
- * -2: Timeout | |
- */ | |
-int rfhelp_send_data_crc_noack(char *data, int len, int resends) { | |
- char buffer[len + 3]; | |
- static unsigned char counter = 0; | |
- | |
- memcpy(buffer, data, len); | |
- buffer[len] = counter++; | |
- | |
- unsigned short crc = crc16((unsigned char*)buffer, len + 1); | |
- | |
- buffer[len + 1] = (char)(crc >> 8); | |
- buffer[len + 2] = (char)(crc & 0xFF); | |
- | |
- int res = 0; | |
- for (int i = 0;i < resends;i++) { | |
- res = rfhelp_send_data(buffer, len + 3, false); | |
- if (res != 0) { | |
- break; | |
- } | |
- } | |
- | |
- return res; | |
+ return rfhelp_send_data(buffer, len + 2, nrf_conf.send_crc_ack); | |
} | |
/** | |
@@ -290,51 +290,6 @@ | |
return res; | |
} | |
-/** | |
- * Same as rfhelp_read_rx_data_crc, but for use with the corresponding | |
- * nocak send function. | |
- * | |
- * @param data | |
- * Pointer to the array in which to store the data. | |
- * | |
- * @param len | |
- * Pointer to variable storing the data length. | |
- * | |
- * @param pipe | |
- * Pointer to the pipe on which the data was received. Can be 0. | |
- * | |
- * @return | |
- * 1: Read OK, more data to read. | |
- * 0: Read OK | |
- * -1: No RX data | |
- * -2: Wrong length read. Something is likely wrong. | |
- * -3: Data read, but CRC does not match. | |
- * -4: Duplicate packet received. | |
- */ | |
-int rfhelp_read_rx_data_crc_noack(char *data, int *len, int *pipe) { | |
- int res = rfhelp_read_rx_data(data, len, pipe); | |
- static unsigned char counter = 0; | |
- | |
- if (res >= 0 && *len > 3) { | |
- unsigned short crc = crc16((unsigned char*)data, *len - 2); | |
- | |
- if (crc != ((unsigned short) data[*len - 2] << 8 | (unsigned short) data[*len - 1])) { | |
- res = -3; | |
- } else { | |
- unsigned char cnt = data[*len - 3]; | |
- if (cnt == counter) { | |
- res = -4; | |
- } | |
- | |
- counter = cnt; | |
- } | |
- } | |
- | |
- *len -= 3; | |
- | |
- return res; | |
-} | |
- | |
int rfhelp_rf_status(void) { | |
chMtxLock(&rf_mutex); | |
int s = rf_status(); | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/nrf/rfhelp.h Raptor2 Sources/bldc-firmware_2_80/nrf/rfhelp.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/nrf/rfhelp.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/nrf/rfhelp.h 2016-08-04 23:47:30.000000000 +0100 | |
@@ -19,16 +19,16 @@ | |
#define RFHELP_H_ | |
#include <stdbool.h> | |
+#include "datatypes.h" | |
// Functions | |
void rfhelp_init(void); | |
+void rfhelp_update_conf(nrf_config *conf); | |
void rfhelp_restart(void); | |
int rfhelp_send_data(char *data, int len, bool ack); | |
int rfhelp_send_data_crc(char *data, int len); | |
-int rfhelp_send_data_crc_noack(char *data, int len, int resends); | |
int rfhelp_read_rx_data(char *data, int *len, int *pipe); | |
int rfhelp_read_rx_data_crc(char *data, int *len, int *pipe); | |
-int rfhelp_read_rx_data_crc_noack(char *data, int *len, int *pipe); | |
int rfhelp_rf_status(void); | |
void rfhelp_set_tx_addr(const char *addr, int addr_len); | |
void rfhelp_set_rx_addr(int pipe, const char *addr, int addr_len); | |
Only in Raptor2 Sources/bldc-firmware_2_80: oh5la4w3.ag1 | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/packet.h Raptor2 Sources/bldc-firmware_2_80/packet.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/packet.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/packet.h 2017-04-13 18:06:50.000000000 +0100 | |
@@ -28,7 +28,7 @@ | |
#include <stdint.h> | |
// Settings | |
-#define PACKET_RX_TIMEOUT 2 | |
+#define PACKET_RX_TIMEOUT 10 | |
#define PACKET_HANDLERS 2 | |
#define PACKET_MAX_PL_LEN 1024 | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/servo_dec.c Raptor2 Sources/bldc-firmware_2_80/servo_dec.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/servo_dec.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/servo_dec.c 2016-10-24 21:35:06.000000000 +0100 | |
@@ -39,6 +39,7 @@ | |
static volatile systime_t last_update_time; | |
static volatile float servo_pos[SERVO_NUM]; | |
static volatile float pulse_start = 1.0; | |
+static volatile float pulse_center = 1.5; | |
static volatile float pulse_end = 2.0; | |
static volatile float last_len_received[SERVO_NUM]; | |
static volatile bool use_median_filter = false; | |
@@ -68,8 +69,16 @@ | |
} | |
if (len >= 0.0) { | |
+ float len_to_center = len + pulse_start - pulse_center; | |
+ | |
if (use_median_filter) { | |
- float c = (len * 2.0 - len_set) / len_set; | |
+ float c; | |
+ if (len_to_center >= 0.0) { | |
+ c = (1.0 / (pulse_end - pulse_center)) * len_to_center; | |
+ } else { | |
+ c = (1.0 / (pulse_center - pulse_start)) * len_to_center; | |
+ } | |
+ //float c = (len * 2.0 - len_set) / len_set; | |
static float c1 = 0.5; | |
static float c2 = 0.5; | |
float med = utils_middle_of_3(c, c1, c2); | |
@@ -79,7 +88,12 @@ | |
servo_pos[0] = med; | |
} else { | |
- servo_pos[0] = (len * 2.0 - len_set) / len_set; | |
+ if (len_to_center >= 0.0) { | |
+ servo_pos[0] = (1 / (pulse_end - pulse_center)) * len_to_center; | |
+ } else { | |
+ servo_pos[0] = (1 / (pulse_center - pulse_start)) * len_to_center; | |
+ } | |
+ //servo_pos[0] = (len * 2.0 - len_set) / len_set; | |
} | |
last_update_time = chVTGetSystemTime(); | |
@@ -135,8 +149,9 @@ | |
* @param end | |
* he amount of milliseconds the pulse ends at (default is 2.0) | |
*/ | |
-void servodec_set_pulse_options(float start, float end, bool median_filter) { | |
+void servodec_set_pulse_options(float start, float center, float end, bool median_filter) { | |
pulse_start = start; | |
+ pulse_center = center; | |
pulse_end = end; | |
use_median_filter = median_filter; | |
} | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/servo_dec.h Raptor2 Sources/bldc-firmware_2_80/servo_dec.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/servo_dec.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/servo_dec.h 2016-10-24 16:46:32.000000000 +0100 | |
@@ -30,7 +30,7 @@ | |
// Functions | |
void servodec_init(void (*d_func)(void)); | |
-void servodec_set_pulse_options(float start, float end, bool median_filter); | |
+void servodec_set_pulse_options(float start, float center, float end, bool median_filter); | |
float servodec_get_servo(int servo_num); | |
uint32_t servodec_get_time_since_update(void); | |
float servodec_get_last_pulse_len(int servo_num); | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/terminal.c Raptor2 Sources/bldc-firmware_2_80/terminal.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/terminal.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/terminal.c 2017-04-13 18:07:08.000000000 +0100 | |
@@ -29,11 +29,12 @@ | |
#include "mcpwm_foc.h" | |
#include "mc_interface.h" | |
#include "commands.h" | |
-#include "main.h" | |
+#include "app.h" | |
#include "hw.h" | |
#include "comm_can.h" | |
#include "utils.h" | |
#include "timeout.h" | |
+#include "encoder.h" | |
#include <string.h> | |
#include <stdio.h> | |
@@ -73,7 +74,7 @@ | |
} else if (strcmp(argv[0], "last_adc_duration") == 0) { | |
commands_printf("Latest ADC duration: %.4f ms", (double)(mcpwm_get_last_adc_isr_duration() * 1000.0)); | |
commands_printf("Latest injected ADC duration: %.4f ms", (double)(mc_interface_get_last_inj_adc_isr_duration() * 1000.0)); | |
- commands_printf("Latest main ADC duration: %.4f ms\n", (double)(main_get_last_adc_isr_duration() * 1000.0)); | |
+ commands_printf("Latest sample ADC duration: %.4f ms\n", (double)(mc_interface_get_last_sample_adc_isr_duration() * 1000.0)); | |
} else if (strcmp(argv[0], "kv") == 0) { | |
commands_printf("Calculated KV: %.2f rpm/volt\n", (double)mcpwm_get_kv_filtered()); | |
} else if (strcmp(argv[0], "mem") == 0) { | |
@@ -98,6 +99,27 @@ | |
commands_printf(""); | |
} else if (strcmp(argv[0], "fault") == 0) { | |
commands_printf("%s\n", mc_interface_fault_to_string(mc_interface_get_fault())); | |
+ } else if (strcmp(argv[0], "faulta") == 0) { | |
+ if (fault_vec_write == 0) { | |
+ commands_printf("No faults"); | |
+ } else { | |
+ commands_printf("Fault: %s\nID: %i\nCurrent: %.1f\nCurrent filtered: %.1f\nVoltage: %.2f\nDuty: %.2f\nRPM: %.1f\nTacho: %d\nCycles running: %d\nTIM duty: %d\nTIM val samp: %d\nTIM current samp: %d\nTIM top: %d\nComm step: %d\nTemperature: %.2f", | |
+ mc_interface_fault_to_string(fault_vec[fault_vec_write - 1].fault), | |
+ app_get_configuration()->controller_id, | |
+ (double)fault_vec[fault_vec_write - 1].current, | |
+ (double)fault_vec[fault_vec_write - 1].current_filtered, | |
+ (double)fault_vec[fault_vec_write - 1].voltage, | |
+ (double)fault_vec[fault_vec_write - 1].duty, | |
+ (double)fault_vec[fault_vec_write - 1].rpm, | |
+ fault_vec[fault_vec_write - 1].tacho, | |
+ fault_vec[fault_vec_write - 1].cycles_running, | |
+ (int)((float)fault_vec[fault_vec_write - 1].tim_top * fault_vec[fault_vec_write - 1].duty), | |
+ fault_vec[fault_vec_write - 1].tim_val_samp, | |
+ fault_vec[fault_vec_write - 1].tim_current_samp, | |
+ fault_vec[fault_vec_write - 1].tim_top, | |
+ fault_vec[fault_vec_write - 1].comm_step, | |
+ (double)fault_vec[fault_vec_write - 1].temperature); | |
+ } | |
} else if (strcmp(argv[0], "faults") == 0) { | |
if (fault_vec_write == 0) { | |
commands_printf("No faults registered since startup\n"); | |
@@ -211,36 +233,66 @@ | |
commands_printf("ID : %i", msg->id); | |
commands_printf("RX Time : %i", msg->rx_time); | |
commands_printf("Age (milliseconds) : %.2f", (double)(UTILS_AGE_S(msg->rx_time) * 1000.0)); | |
- commands_printf("RPM : %.2f", (double)msg->rpm); | |
+ commands_printf("RPM : %.2f", (double)(msg->rpm)); | |
commands_printf("Current : %.2f", (double)msg->current); | |
- commands_printf("Duty : %.2f\n", (double)msg->duty); | |
+ commands_printf("Duty : %i", msg->duty); | |
+ commands_printf("Cruise Control : %i\n", msg->cruise_control_status); | |
+ } | |
+ } | |
+ } else if (strcmp(argv[0], "can_member") == 0) { | |
+ char controllerIds[100] = "CAN:\n"; | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1.0) { | |
+ char idArray[5]; | |
+ sprintf(idArray, "%i\n", msg->id); | |
+ strcat(controllerIds, idArray); | |
} | |
} | |
- } else if (strcmp(argv[0], "foc_encoder_detect") == 0) { | |
+ commands_printf(controllerIds); | |
+ } else if (strcmp(argv[0], "can_erpms") == 0) { | |
+ char controllerIds[100] = "CAN ERPMs:\n"; | |
+ | |
+ char rpmArrayMaster[15]; | |
+ sprintf(rpmArrayMaster, "M %6.2f\n", (double)mc_interface_get_rpm()); | |
+ strcat(controllerIds, rpmArrayMaster); | |
+ | |
+ for (int i = 0;i < CAN_STATUS_MSGS_TO_STORE;i++) { | |
+ can_status_msg *msg = comm_can_get_status_msg_index(i); | |
+ | |
+ if (msg->id >= 0 && UTILS_AGE_S(msg->rx_time) < 1.0) { | |
+ char rpmArray[15]; | |
+ sprintf(rpmArray, "%i %6.2f\n", msg->id, (double)(msg->rpm)); | |
+ strcat(controllerIds, rpmArray); | |
+ } | |
+ } | |
+ commands_printf(controllerIds); | |
+ }else if (strcmp(argv[0], "foc_encoder_detect") == 0) { | |
if (argc == 2) { | |
float current = -1.0; | |
sscanf(argv[1], "%f", ¤t); | |
if (current > 0.0 && current <= mcconf.l_current_max) { | |
-#if ENCODER_ENABLE | |
- mc_motor_type type_old = mcconf.motor_type; | |
- mcconf.motor_type = MOTOR_TYPE_FOC; | |
- mc_interface_set_configuration(&mcconf); | |
- | |
- float offset = 0.0; | |
- float ratio = 0.0; | |
- bool inverted = false; | |
- mcpwm_foc_encoder_detect(current, true, &offset, &ratio, &inverted); | |
- | |
- mcconf.motor_type = type_old; | |
- mc_interface_set_configuration(&mcconf); | |
- | |
- commands_printf("Offset : %.2f", (double)offset); | |
- commands_printf("Ratio : %.2f", (double)ratio); | |
- commands_printf("Inverted : %s\n", inverted ? "true" : "false"); | |
-#else | |
- commands_printf("Encoder not enabled.\n"); | |
-#endif | |
+ if (encoder_is_configured()) { | |
+ mc_motor_type type_old = mcconf.motor_type; | |
+ mcconf.motor_type = MOTOR_TYPE_FOC; | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ float offset = 0.0; | |
+ float ratio = 0.0; | |
+ bool inverted = false; | |
+ mcpwm_foc_encoder_detect(current, true, &offset, &ratio, &inverted); | |
+ | |
+ mcconf.motor_type = type_old; | |
+ mc_interface_set_configuration(&mcconf); | |
+ | |
+ commands_printf("Offset : %.2f", (double)offset); | |
+ commands_printf("Ratio : %.2f", (double)ratio); | |
+ commands_printf("Inverted : %s\n", inverted ? "true" : "false"); | |
+ } else { | |
+ commands_printf("Encoder not enabled.\n"); | |
+ } | |
} else { | |
commands_printf("Invalid argument(s).\n"); | |
} | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/utils.c Raptor2 Sources/bldc-firmware_2_80/utils.c | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/utils.c 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/utils.c 2017-04-13 18:07:16.000000000 +0100 | |
@@ -133,22 +133,28 @@ | |
* The difference between the angles | |
*/ | |
float utils_angle_difference(float angle1, float angle2) { | |
- utils_norm_angle(&angle1); | |
- utils_norm_angle(&angle2); | |
+// utils_norm_angle(&angle1); | |
+// utils_norm_angle(&angle2); | |
+// | |
+// if (fabsf(angle1 - angle2) > 180.0) { | |
+// if (angle1 < angle2) { | |
+// angle1 += 360.0; | |
+// } else { | |
+// angle2 += 360.0; | |
+// } | |
+// } | |
+// | |
+// return angle1 - angle2; | |
- if (fabsf(angle1 - angle2) > 180.0) { | |
- if (angle1 < angle2) { | |
- angle1 += 360.0; | |
- } else { | |
- angle2 += 360.0; | |
- } | |
- } | |
- | |
- return angle1 - angle2; | |
+ // Faster in most cases | |
+ float difference = angle1 - angle2; | |
+ while (difference < -180.0) difference += 2.0 * 180.0; | |
+ while (difference > 180.0) difference -= 2.0 * 180.0; | |
+ return difference; | |
} | |
/** | |
- * Get the difference between two angles. Will always be between -180 and +180 degrees. | |
+ * Get the difference between two angles. Will always be between -pi and +pi radians. | |
* @param angle1 | |
* The first angle in radians | |
* @param angle2 | |
@@ -221,6 +227,73 @@ | |
} | |
/** | |
+ * Get the smallest value of two values | |
+ * | |
+ * @param a | |
+ * First value | |
+ * | |
+ * @param b | |
+ * Second value | |
+ * | |
+ * @return | |
+ * The smallest value | |
+ */ | |
+float utils_smallest_of_2(float a, float b) { | |
+ if (b < a) { | |
+ return b; | |
+ } | |
+ return a; | |
+} | |
+ | |
+/** | |
+ * Get the smallest value of three values | |
+ * | |
+ * @param a | |
+ * First value | |
+ * | |
+ * @param b | |
+ * Second value | |
+ * | |
+ * @param c | |
+ * Third value | |
+ * | |
+ * @return | |
+ * The smallest value | |
+ */ | |
+float utils_smallest_of_3(float a, float b, float c) { | |
+ if (b < a) { | |
+ if (c < b) { | |
+ return c; | |
+ } | |
+ return b; | |
+ } else { | |
+ if (c < a) { | |
+ return c; | |
+ } | |
+ return a; | |
+ } | |
+} | |
+ | |
+/** | |
+ * Get the smallest value of two values | |
+ * | |
+ * @param a | |
+ * First value | |
+ * | |
+ * @param b | |
+ * Second value | |
+ * | |
+ * @return | |
+ * The smallest value | |
+ */ | |
+float utils_highest_of_2(float a, float b) { | |
+ if (b > a) { | |
+ return b; | |
+ } | |
+ return a; | |
+} | |
+ | |
+/** | |
* Get the middle value of three values | |
* | |
* @param a | |
diff -ru bldc-90986c31defe50830b4795a388ee5b2687dc2516/utils.h Raptor2 Sources/bldc-firmware_2_80/utils.h | |
--- bldc-90986c31defe50830b4795a388ee5b2687dc2516/utils.h 2016-01-24 12:44:51.000000000 +0000 | |
+++ Raptor2 Sources/bldc-firmware_2_80/utils.h 2017-04-13 18:07:22.000000000 +0100 | |
@@ -39,6 +39,9 @@ | |
float utils_angle_difference_rad(float angle1, float angle2); | |
float utils_avg_angles_rad_fast(float *angles, float *weights, int angles_num); | |
float utils_middle_of_3(float a, float b, float c); | |
+float utils_smallest_of_2(float a, float b); | |
+float utils_smallest_of_3(float a, float b, float c); | |
+float utils_highest_of_2(float a, float b); | |
int utils_middle_of_3_int(int a, int b, int c); | |
float utils_fast_inv_sqrt(float x); | |
float utils_fast_atan2(float y, float x); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment