From 27b03c35c596c901550ffd9fe3f8aa9d1ddf1773 Mon Sep 17 00:00:00 2001 From: rnovikov Date: Fri, 3 Apr 2020 15:22:05 +0200 Subject: [PATCH] Experimental torque-only high-RPM hack --- src/controller/TSDZ2_controller.cflags | 1 + src/controller/TSDZ2_controller.config | 2 + src/controller/TSDZ2_controller.creator | 1 + src/controller/TSDZ2_controller.cxxflags | 1 + src/controller/TSDZ2_controller.files | 31 + src/controller/TSDZ2_controller.includes | 4 + src/controller/ebike_app.c | 17 +- src/controller/main.bin | Bin 21610 -> 0 bytes src/controller/main.hex | 1356 ---------------------- src/controller/motor.c | 12 +- 10 files changed, 54 insertions(+), 1371 deletions(-) create mode 100644 src/controller/TSDZ2_controller.cflags create mode 100644 src/controller/TSDZ2_controller.config create mode 100644 src/controller/TSDZ2_controller.creator create mode 100644 src/controller/TSDZ2_controller.cxxflags create mode 100644 src/controller/TSDZ2_controller.files create mode 100644 src/controller/TSDZ2_controller.includes delete mode 100755 src/controller/main.bin delete mode 100644 src/controller/main.hex diff --git a/src/controller/TSDZ2_controller.cflags b/src/controller/TSDZ2_controller.cflags new file mode 100644 index 00000000..68d51653 --- /dev/null +++ b/src/controller/TSDZ2_controller.cflags @@ -0,0 +1 @@ +-std=c17 \ No newline at end of file diff --git a/src/controller/TSDZ2_controller.config b/src/controller/TSDZ2_controller.config new file mode 100644 index 00000000..e0284f42 --- /dev/null +++ b/src/controller/TSDZ2_controller.config @@ -0,0 +1,2 @@ +// Add predefined macros for your project here. For example: +// #define THE_ANSWER 42 diff --git a/src/controller/TSDZ2_controller.creator b/src/controller/TSDZ2_controller.creator new file mode 100644 index 00000000..e94cbbd3 --- /dev/null +++ b/src/controller/TSDZ2_controller.creator @@ -0,0 +1 @@ +[General] diff --git a/src/controller/TSDZ2_controller.cxxflags b/src/controller/TSDZ2_controller.cxxflags new file mode 100644 index 00000000..6435dfce --- /dev/null +++ b/src/controller/TSDZ2_controller.cxxflags @@ -0,0 +1 @@ +-std=c++17 \ No newline at end of file diff --git a/src/controller/TSDZ2_controller.files b/src/controller/TSDZ2_controller.files new file mode 100644 index 00000000..0b820312 --- /dev/null +++ b/src/controller/TSDZ2_controller.files @@ -0,0 +1,31 @@ +adc.c +adc.h +brake.c +brake.h +config.h +ebike_app.c +ebike_app.h +interrupts.h +lights.c +lights.h +main.c +main.h +motor.c +motor.h +pas.c +pas.h +pins.h +pwm.c +pwm.h +timers.c +timers.h +torque_sensor.c +torque_sensor.h +uart.c +uart.h +utils.c +utils.h +watchdog.c +watchdog.h +wheel_speed_sensor.c +wheel_speed_sensor.h diff --git a/src/controller/TSDZ2_controller.includes b/src/controller/TSDZ2_controller.includes new file mode 100644 index 00000000..0a5d3f4f --- /dev/null +++ b/src/controller/TSDZ2_controller.includes @@ -0,0 +1,4 @@ +. +.. +/usr/local/Cellar/sdcc/3.9.0/share/sdcc/include/ +../common/STM8S_StdPeriph_Lib/inc diff --git a/src/controller/ebike_app.c b/src/controller/ebike_app.c index 11875472..5493efbe 100755 --- a/src/controller/ebike_app.c +++ b/src/controller/ebike_app.c @@ -225,17 +225,9 @@ static void ebike_control_motor(void) { ui32_assist_level_factor_x1000 = (uint32_t) m_config_vars.ui16_assist_level_factor_x1000; // force a min of 10 RPM cadence - ui32_pedal_power_no_cadence_x10 = (((uint32_t) ui16_m_pedal_torque_x100 * 10) / (uint32_t) 96); + ui32_pedal_power_no_cadence_x10 = (((uint32_t) ui16_m_pedal_torque_x100 * 10) / 50U); - if (m_config_vars.ui8_motor_assistance_startup_without_pedal_rotation == 0 || - ui8_pas_cadence_rpm) - { - ui32_current_amps_x10 = ((uint32_t) ui16_m_pedal_power_x10 * ui32_assist_level_factor_x1000) / 1000; - } - else - { - ui32_current_amps_x10 = (ui32_pedal_power_no_cadence_x10 * ui32_assist_level_factor_x1000) / 1000; - } + ui32_current_amps_x10 = (ui32_pedal_power_no_cadence_x10 * ui32_assist_level_factor_x1000) / 1000; // 6.410 = 1 / 0.156 (each ADC step for current) // 6.410 * 8 = ~51 @@ -252,6 +244,7 @@ static void ebike_control_motor(void) ui16_m_adc_target_current = ui16_adc_current; // now calculate the current for BOOST + /* we don't need the BOOST anymore if (m_config_vars.ui16_startup_motor_power_boost_assist_level > 0) { ui32_current_amps_x10 = (ui32_pedal_power_no_cadence_x10 * (uint32_t) m_config_vars.ui16_startup_motor_power_boost_assist_level) / 100; @@ -270,6 +263,7 @@ static void ebike_control_motor(void) ui16_adc_max_current_boost_state = ui16_adc_current; } + */ } else { @@ -682,7 +676,8 @@ static void communications_process_packages(uint8_t ui8_frame_type) } // calculate current step for ramp up - ui32_temp = ((uint32_t) 24375) / ((uint32_t) m_config_vars.ui8_ramp_up_amps_per_second_x10); // see note below +// ui32_temp = ((uint32_t) 24375) / ((uint32_t) m_config_vars.ui8_ramp_up_amps_per_second_x10); // see note below + ui32_temp = ((uint32_t) 10000) / ((uint32_t) m_config_vars.ui8_ramp_up_amps_per_second_x10); // see note below ui16_g_current_ramp_up_inverse_step = (uint16_t) ui32_temp; /*--------------------------------------------------------- diff --git a/src/controller/main.bin b/src/controller/main.bin deleted file mode 100755 index a22cc8671da28263049f6c53a61ef56a2df33616..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21610 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 Ik{kN|8