Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 56 additions & 40 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,50 +17,65 @@ if(ESP_PLATFORM)

idf_build_get_property(target IDF_TARGET)

set(requires esp_driver_uart esp_driver_pcnt esp_driver_gpio esp_driver_mcpwm driver freertos esp_system esp_timer nvs_flash esp_hw_support efuse)
# esp_tinyusb is fetched conditionally for USB-capable targets via
# idf_component.yml; declare the priv require eagerly here so the bridge
# source file finds tinyusb.h on those targets even when the user has not
# enabled CONFIG_ESP_FOC_BRIDGE_USBCDC at component-graph resolution time.
if(target STREQUAL "esp32s2" OR target STREQUAL "esp32s3" OR target STREQUAL "esp32p4")
list(APPEND requires espressif__esp_tinyusb)
endif()
list(APPEND includes "source/drivers" "source/drivers/cali")
list(APPEND srcs "source/drivers/inverter_3pwm_mcpwm.c"
"source/drivers/inverter_6pwm_mcpwm.c"
"source/drivers/rotor_sensor_as5600.c"
"source/drivers/rotor_sensor_as5048.c"
"source/drivers/rotor_sensor_pcnt.c"
"source/drivers/rotor_sensor_simu.c"
"source/drivers/current_sensor_adc.c"
"source/drivers/esp_foc_adc_cali_lut.c"
"source/drivers/cali/esp_foc_adc_cali_curve.c"
"source/drivers/cali/esp_foc_adc_range_extend.c"
"source/osal/os_interface_idf.c")
set(requires driver freertos esp_system esp_timer nvs_flash esp_hw_support efuse)

if(target STREQUAL "esp32")
list(APPEND srcs "source/drivers/cali/esp_foc_adc_cali_line_esp32.c")
elseif(target STREQUAL "esp32s2")
list(APPEND srcs "source/drivers/cali/esp_foc_adc_cali_line_esp32s2.c")
elseif(target STREQUAL "esp32c2")
list(APPEND srcs "source/drivers/cali/esp_foc_adc_cali_line_esp32c2.c")
elseif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/source/drivers/cali/coeff/esp_foc_curve_coeff_${target}.c")
list(APPEND srcs "source/drivers/cali/coeff/esp_foc_curve_coeff_${target}.c")
endif()
if(CONFIG_ESP_FOC_FITL)
list(APPEND srcs "source/motor_control/foc_in_the_loop/esp_foc_itl_plant.c"
"source/motor_control/foc_in_the_loop/esp_foc_in_the_loop.c")
list(APPEND includes "source/motor_control/foc_in_the_loop"
"source/drivers/foc_in_the_loop")
list(APPEND srcs "source/osal/os_interface_idf.c")

if(CONFIG_FOC_ITL_TICK_MCPWM)
list(APPEND srcs "source/drivers/foc_in_the_loop/esp_foc_itl_tick_mcpwm.c")
list(APPEND requires esp_driver_mcpwm)
elseif(CONFIG_FOC_ITL_TICK_GPTIMER)
list(APPEND srcs "source/drivers/foc_in_the_loop/esp_foc_itl_tick_gptimer.c")
list(APPEND requires esp_driver_gptimer)
endif()
else()
list(APPEND requires esp_driver_uart esp_driver_pcnt esp_driver_gpio esp_driver_mcpwm)
list(APPEND includes "source/drivers" "source/drivers/cali")
list(APPEND srcs "source/drivers/inverter_3pwm_mcpwm.c"
"source/drivers/inverter_6pwm_mcpwm.c"
"source/drivers/rotor_sensor_as5600.c"
"source/drivers/rotor_sensor_as5048.c"
"source/drivers/rotor_sensor_pcnt.c"
"source/drivers/rotor_sensor_simu.c"
"source/drivers/current_sensor_adc.c"
"source/drivers/esp_foc_adc_cali_lut.c"
"source/drivers/cali/esp_foc_adc_cali_curve.c"
"source/drivers/cali/esp_foc_adc_range_extend.c"
"source/osal/os_interface_idf.c")

if(CONFIG_SOC_ETM_SUPPORTED)
list(APPEND srcs "source/drivers/isensor_adc_etm.c")
if(target STREQUAL "esp32")
list(APPEND srcs "source/drivers/cali/esp_foc_adc_cali_line_esp32.c")
elseif(target STREQUAL "esp32s2")
list(APPEND srcs "source/drivers/cali/esp_foc_adc_cali_line_esp32s2.c")
elseif(target STREQUAL "esp32c2")
list(APPEND srcs "source/drivers/cali/esp_foc_adc_cali_line_esp32c2.c")
elseif(EXISTS "${CMAKE_CURRENT_LIST_DIR}/source/drivers/cali/coeff/esp_foc_curve_coeff_${target}.c")
list(APPEND srcs "source/drivers/cali/coeff/esp_foc_curve_coeff_${target}.c")
endif()

if(CONFIG_SOC_ETM_SUPPORTED)
list(APPEND srcs "source/drivers/isensor_adc_etm.c")
endif()

if(target STREQUAL "esp32")
list(APPEND srcs "source/drivers/isensor_adc_dma_esp32.c")
list(APPEND requires esp_driver_i2s)
elseif(target STREQUAL "esp32s2")
list(APPEND srcs "source/drivers/isensor_adc_dma_esp32s2.c")
list(APPEND requires esp_driver_spi)
else()
list(APPEND srcs "source/drivers/isensor_adc_dma_gdma.c")
list(APPEND requires esp_mm)
endif()
endif()

if(target STREQUAL "esp32")
list(APPEND srcs "source/drivers/isensor_adc_dma_esp32.c")
list(APPEND requires esp_driver_i2s)
elseif(target STREQUAL "esp32s2")
list(APPEND srcs "source/drivers/isensor_adc_dma_esp32s2.c")
list(APPEND requires esp_driver_spi)
else()
list(APPEND srcs "source/drivers/isensor_adc_dma_gdma.c")
list(APPEND requires esp_mm)
if(target STREQUAL "esp32s2" OR target STREQUAL "esp32s3" OR target STREQUAL "esp32p4")
list(APPEND requires espressif__esp_tinyusb)
endif()

if(CONFIG_ESP_FOC_TUNER_ENABLE)
Expand All @@ -69,6 +84,7 @@ if(CONFIG_ESP_FOC_TUNER_ENABLE)
endif()
if(CONFIG_ESP_FOC_BRIDGE_UART)
list(APPEND srcs "source/drivers/gui_link/esp_foc_bridge_uart.c")
list(APPEND requires esp_driver_uart)
endif()
if(CONFIG_ESP_FOC_BRIDGE_USBCDC)
list(APPEND srcs "source/drivers/gui_link/esp_foc_bridge_usbcdc.c")
Expand Down
73 changes: 73 additions & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -186,4 +186,77 @@ menu "espFoC Settings"
default y
endmenu

menu "FOC-in-the-loop (simulated plant)"
config ESP_FOC_FITL
bool "FOC-in-the-loop: simulated motor plant (exclusive with HW drivers)"
default n
help
When enabled, espFoC builds the in-the-loop plant factory instead
of MCPWM inverter, ADC shunt, and hardware rotor drivers.

if ESP_FOC_FITL

config FOC_ITL_PWM_10KHZ
bool "Use 10 kHz PWM tick (default 20 kHz)"
default n

config FOC_ITL_USE_RK2
bool "Plant integrator: RK2 instead of RK4"
default n

config FOC_ITL_MOTOR_DELTA
bool "Motor windings: delta (D1 star-equivalent conversion)"
default n

choice FOC_ITL_TICK_SOURCE
prompt "PWM tick backend"
default FOC_ITL_TICK_MCPWM if SOC_MCPWM_SUPPORTED
default FOC_ITL_TICK_GPTIMER

config FOC_ITL_TICK_MCPWM
bool "MCPWM timer (device)"
depends on SOC_MCPWM_SUPPORTED

config FOC_ITL_TICK_GPTIMER
bool "GPTimer (QEMU / generic)"
endchoice

config FOC_ITL_DEFAULT_R_MILLIOHM
int "Default phase R [milli-ohm]"
range 1 1000000
default 1000

config FOC_ITL_DEFAULT_L_UH
int "Default phase L [micro-henry]"
range 1 1000000
default 2000

config FOC_ITL_DEFAULT_J_X1E7
int "Default inertia J * 1e7 [kg·m²]"
range 1 1000000
default 500

config FOC_ITL_DEFAULT_B_X1E7
int "Default viscous B * 1e7 [N·m·s/rad]"
range 0 1000000
default 100

config FOC_ITL_DEFAULT_KT_X1E7
int "Default torque constant Kt * 1e7 [N·m/A]"
range 1 1000000
default 1000

config FOC_ITL_DEFAULT_POLE_PAIRS
int "Default pole pairs"
range 1 64
default 13

config FOC_ITL_DEFAULT_I_MAX_MA
int "Default phase current limit [mA]"
range 100 100000
default 10000

endif
endmenu

endmenu
31 changes: 26 additions & 5 deletions examples/axis_tuning/main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,23 @@

#include "esp_log.h"
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "espFoC/esp_foc.h"
#include "espFoC/gui_link/esp_foc_tuner.h"
#include "espFoC/utils/esp_foc_q16.h"

#if defined(CONFIG_ESP_FOC_FITL) && CONFIG_ESP_FOC_FITL
#include "espFoC/esp_foc_in_the_loop.h"
#else
#include "espFoC/inverter_6pwm_mcpwm.h"
#if defined(CONFIG_AXIS_TUNING_ROTOR_AS5600)
#include "espFoC/rotor_sensor_as5600.h"
#elif defined(CONFIG_AXIS_TUNING_ROTOR_SIMU)
#include "espFoC/rotor_sensor_simu.h"
#endif
#include "espFoC/current_sensor_adc.h"
#include "espFoC/utils/esp_foc_q16.h"
#include "soc/soc_caps.h"
#endif

static const char *TAG = "axis_tuning";

Expand Down Expand Up @@ -83,6 +86,7 @@ static void pump_scope_idle(void)
}
#endif

#if !defined(CONFIG_ESP_FOC_FITL) || !CONFIG_ESP_FOC_FITL
static int pwm_enable_gpio(void)
{
if (CONFIG_AXIS_TUNING_PWM_EN_PIN < 0) {
Expand All @@ -95,11 +99,27 @@ static int pwm_enable_gpio(void)
#endif
return CONFIG_AXIS_TUNING_PWM_EN_PIN;
}
#endif

void app_main(void)
{
ESP_LOGI(TAG, "boot — axis_tuning");

#if defined(CONFIG_ESP_FOC_FITL) && CONFIG_ESP_FOC_FITL
esp_foc_in_the_loop_config_t fitl_cfg = {
.pole_pairs = CONFIG_AXIS_TUNING_POLE_PAIRS,
.vdc_q16 = q16_from_float((float)CONFIG_AXIS_TUNING_DC_LINK_V),
.pwm_hz = 0,
};
esp_foc_in_the_loop_handles_t fitl = {0};
if (esp_foc_in_the_loop_create(&fitl_cfg, &fitl) != ESP_FOC_OK) {
ESP_LOGE(TAG, "FITL init failed");
return;
}
s_inverter = fitl.inverter;
s_rotor = fitl.rotor;
s_shunts = fitl.isensor;
#else
s_inverter = inverter_6pwm_mpcwm_new(
CONFIG_AXIS_TUNING_PWM_U_HI,
CONFIG_AXIS_TUNING_PWM_U_LO,
Expand Down Expand Up @@ -156,6 +176,7 @@ void app_main(void)
ESP_LOGE(TAG, "current sensor init failed");
return;
}
#endif

esp_foc_motor_control_settings_t settings = {
.motor_pole_pairs = CONFIG_AXIS_TUNING_POLE_PAIRS,
Expand All @@ -170,7 +191,7 @@ void app_main(void)
return;
}

#if defined(CONFIG_AXIS_TUNING_ROTOR_SIMU)
#if defined(CONFIG_AXIS_TUNING_ROTOR_SIMU) && (!defined(CONFIG_ESP_FOC_FITL) || !CONFIG_ESP_FOC_FITL)
rotor_sensor_simu_wire_ud_uq(s_rotor, &s_axis.u_d.raw, &s_axis.u_q.raw);
#endif

Expand All @@ -190,6 +211,6 @@ void app_main(void)
pump_scope_idle();
}
#endif
vTaskDelay(pdMS_TO_TICKS(200));
esp_foc_sleep_ms(200);
}
}
3 changes: 3 additions & 0 deletions examples/axis_tuning/sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ CONFIG_ESP_FOC_SCOPE_BUFFER_SIZE=512
CONFIG_ESP_FOC_CALIBRATION_NVS=y
CONFIG_ESP_FOC_PWM_RATE_HZ=20000

CONFIG_ESP_FOC_FITL=y
CONFIG_FOC_ITL_TICK_MCPWM=y

CONFIG_COMPILER_OPTIMIZATION_PERF=y
CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE=y
7 changes: 2 additions & 5 deletions examples/test_drivers/test_encoder/main/test_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

#include "esp_log.h"
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "espFoC/esp_foc.h"
#include "espFoC/gui_link/esp_foc_tuner.h"
Expand Down Expand Up @@ -113,10 +111,9 @@ static void pump_scope_idle(void)
static void encoder_task(void *arg)
{
(void)arg;
const TickType_t period = pdMS_TO_TICKS(1);
while (1) {
encoder_axis_poll(&s_axis);
vTaskDelay(period);
esp_foc_sleep_ms(1);
}
}

Expand Down Expand Up @@ -170,6 +167,6 @@ void app_main(void)
#if defined(CONFIG_ESP_FOC_SCOPE)
pump_scope_idle();
#endif
vTaskDelay(pdMS_TO_TICKS(200));
esp_foc_sleep_ms(200);
}
}
7 changes: 2 additions & 5 deletions examples/test_drivers/test_isensor_characterize/main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@

#include "esp_log.h"
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#include "espFoC/esp_foc.h"
#include "espFoC/gui_link/esp_foc_tuner.h"
Expand Down Expand Up @@ -81,12 +79,11 @@ static void pump_scope_idle(void)
static void bench_task(void *arg)
{
(void)arg;
const TickType_t period = pdMS_TO_TICKS(1);
while (1) {
if (s_axis.state == ESP_FOC_AXIS_STATE_BENCH) {
esp_foc_bench_step(&s_axis);
}
vTaskDelay(period);
esp_foc_sleep_ms(1);
}
}

Expand Down Expand Up @@ -168,6 +165,6 @@ void app_main(void)
pump_scope_idle();
}
#endif
vTaskDelay(pdMS_TO_TICKS(200));
esp_foc_sleep_ms(200);
}
}
2 changes: 1 addition & 1 deletion examples/unit_test_runner/run_unit_tests_qemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def main() -> int:
child.sendline(TEST_FILTER)

try:
child.expect(RESULT_RE, timeout=600)
child.expect(RESULT_RE, timeout=120)
except pexpect.TIMEOUT:
print("Timeout waiting for Unity summary (tests still running or hung).")
return 1
Expand Down
4 changes: 4 additions & 0 deletions examples/unit_test_runner/sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ CONFIG_ESP_FOC_TUNER_ENABLE=y

# Enable NVS calibration overlay for unit tests
CONFIG_ESP_FOC_CALIBRATION_NVS=y

# FOC-in-the-loop plant + GPTimer tick for QEMU CI
CONFIG_ESP_FOC_FITL=y
CONFIG_FOC_ITL_TICK_GPTIMER=y
Loading
Loading