#ifndef ESP32_DRIVER_MCPWM_H #define ESP32_DRIVER_MCPWM_H #include "../../hardware_api.h" #if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(SIMPLEFOC_ESP32_USELEDC) #include "driver/mcpwm_prelude.h" #include "soc/mcpwm_reg.h" #include "soc/mcpwm_struct.h" #include "esp_idf_version.h" // version check - this mcpwm driver is specific for ESP-IDF 5.x and arduino-esp32 3.x #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) #error SimpleFOC: ESP-IDF version 4 or lower detected. Please update to ESP-IDF 5.x and Arduino-esp32 3.0 (or higher) #endif #ifndef SIMPLEFOC_ESP32_HW_DEADTIME #define SIMPLEFOC_ESP32_HW_DEADTIME true // TODO: Change to false when sw-deadtime & phase_state is approved ready for general use. #endif //!< ESP32 MCPWM driver parameters typedef struct ESP32MCPWMDriverParams { long pwm_frequency; //!< frequency of the pwm signal int group_id; //!< group of the mcpwm mcpwm_timer_handle_t timers[2]; //!< timers of the mcpwm mcpwm_oper_handle_t oper[3]; //!< operators of the mcpwm mcpwm_cmpr_handle_t comparator[6]; //!< comparators of the mcpwm mcpwm_gen_handle_t generator[6]; //!< generators of the mcpwm uint32_t mcpwm_period; //!< period of the pwm signal float dead_zone; //!< dead zone of the pwm signal } ESP32MCPWMDriverParams; #ifndef SIMPLEFOC_DISABLE_DEBUG #define SIMPLEFOC_ESP32_DEBUG(tag, str)\ SimpleFOCDebug::println( "ESP32-"+String(tag)+ ": "+ String(str)); #else #define SIMPLEFOC_ESP32_DEBUG(tag, str) #endif #define SIMPLEFOC_ESP32_DRV_DEBUG(str)\ SIMPLEFOC_ESP32_DEBUG("DRV", str);\ // macro for checking the error of the mcpwm functions // if the function returns an error the function will return SIMPLEFOC_DRIVER_INIT_FAILED #define CHECK_ERR(func_call, message) \ if ((func_call) != ESP_OK) { \ SIMPLEFOC_ESP32_DRV_DEBUG("ERROR - " + String(message)); \ return SIMPLEFOC_DRIVER_INIT_FAILED; \ } // ABI bus frequency - would be better to take it from somewhere // but I did nto find a good exposed variable #define _MCPWM_FREQ 160e6f #define _PWM_TIMEBASE_RESOLUTION_HZ (_MCPWM_FREQ) /*!< Resolution of MCPWM */ // pwm frequency settings #define _PWM_FREQUENCY 25000 // 25khz #define _PWM_FREQUENCY_MAX 50000 // 50kHz // low-level configuration API /** * checking if group has pins available * @param group - group of the mcpwm * @param no_pins - number of pins * @returns true if pins are available, false otherwise */ bool _hasAvailablePins(int group, int no_pins); /** * function finding the last timer in the group * @param group - group of the mcpwm * @returns index of the last timer in the group * -1 if no timer instantiated yet */ uint8_t _findLastTimer(int group); /** * function finding the next timer in the group * @param group - group of the mcpwm * @returns index of the next timer in the group * -1 if all timers are used */ uint8_t _findNextTimer(int group); /** * function finding the best group and timer for the pwm signals * * @param no_pins - number of pins * @param pwm_freq - frequency of the pwm signal * @param group - pointer to the group * @param timer - pointer to the timer * @returns * 1 if solution found in one group * 2 if solution requires using both groups * 0 if no solution possible */ int _findBestGroup(int no_pins, long pwm_freq, int* group, int* timer); /** * function configuring the center alignement and inversion of a pwm signal * @param gena - mcpwm generator handle * @param cmpa - mcpwm comparator handle * @param inverted - true if the signal is inverted, false otherwise */ int _configureCenterAlign(mcpwm_gen_handle_t gena, mcpwm_cmpr_handle_t cmpa, bool inverted); /** * function calculating the pwm period * @param pwm_frequency - frequency of the pwm signal * @return uint32_t - period of the pwm signal */ uint32_t _calcPWMPeriod(long pwm_frequency); /** * function calculating the pwm frequency * @param pwm_period - period of the pwm signal * @return long - frequency of the pwm signal */ long _calcPWMFreq(long pwm_period); /** * function configuring the MCPWM for 6pwm * @param pwm_frequency - frequency of the pwm signal * @param mcpwm_group - group of the mcpwm * @param timer_no - timer number * @param dead_zone - dead zone of the pwm signal * @param pins - array of pins * @return ESP32MCPWMDriverParams* - pointer to the driver parameters if successful, -1 if failed */ void* _configure6PWMPinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no, float dead_zone, int* pins); /** * function configuring the MCPWM for pwm generation * @param pwm_frequency - frequency of the pwm signal * @param mcpwm_group - group of the mcpwm * @param timer_no - timer number * @param no_pins - number of pins * @param pins - array of pins * @return ESP32MCPWMDriverParams* - pointer to the driver parameters if successful, -1 if failed */ void* _configurePinsMCPWM(long pwm_frequency, int mcpwm_group, int timer_no, int no_pins, int* pins); /** * function setting the duty cycle to the MCPWM channel * @param cmpr - mcpwm channel handle * @param mcpwm_period - period of the pwm signal * @param duty_cycle - duty cycle of the pwm signal */ void _setDutyCycle(mcpwm_cmpr_handle_t cmpr, uint32_t mcpwm_period, float duty_cycle); /** * function setting the phase state * @param generator_high - mcpwm generator handle for the high side * @param generator_low - mcpwm generator handle for the low side * @param phase_state - phase state */ void _forcePhaseState(mcpwm_gen_handle_t generator_high, mcpwm_gen_handle_t generator_low, PhaseState phase_state); /** * function notifying the driver that low side is used with comparator * @param group_id - mcpwm group id */ void _notifyLowSideUsingComparator(int group_id); #endif #endif