Commit 0db580c5 authored by Antoine Boche's avatar Antoine Boche
Browse files

Added a feature to choose the controlled switch.

 * The duty cycle will be applied according to the convention chosen in initialization with upper_switch_convention. In hrtim_cmpl_pwm_out() if it is set to "true" then the duty cycle will be applied on the upper switch and the lower switch will complement the PWM and vice versa for "false".
 * The dead time of the PWMs is now transferred to the complementary switch of the switching cell. As the dead time is by default centered on the two signals of the switch cell, it has been compensated on the main switch to be controlled at the duty cycle requested in leg_set()
 * A correction has been made on the PWMs specific to the actual power board. The signals of the first switching cell are inverted, so this has been corrected in the initialization of HRTIM in hrtim_cmpl_pwm_out()
parent 3735c771
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
* *
* @author Hugues Larrive <hugues.larrive@laas.fr> * @author Hugues Larrive <hugues.larrive@laas.fr>
* @author Clément Foucher <clement.foucher@laas.fr> * @author Clément Foucher <clement.foucher@laas.fr>
* @author Antoine Boche <antoine.boche@laas.fr>
*/ */
#ifndef HRTIM_H #ifndef HRTIM_H
...@@ -359,14 +360,15 @@ typedef enum { ...@@ -359,14 +360,15 @@ typedef enum {
* @brief Initialize an HRTIM device and all these timing units for * @brief Initialize an HRTIM device and all these timing units for
* complementary pwm outputs with a dead time. * complementary pwm outputs with a dead time.
* *
* @param[in] dev HRTIM device to initialize * @param[in] dev HRTIM device to initialize
* @param[inout] freq HRTIM frequency in Hz * @param[inout] freq HRTIM frequency in Hz
* @param[in] dt Desired dead time in ns * @param[in] dt Desired dead time in ns
* @param[in] switch_convention Choice of the switch convention
* *
* @return actual HRTIM resolution on success * @return actual HRTIM resolution on success
* @return 0 on error * @return 0 on error
*/ */
uint16_t hrtim_init(hrtim_t dev, uint32_t *freq, uint16_t dt); uint16_t hrtim_init(hrtim_t dev, uint32_t *freq, uint16_t dt, uint8_t switch_convention);
/** /**
* @brief Set the duty-cycle, dead-time and phase shift for a given * @brief Set the duty-cycle, dead-time and phase shift for a given
...@@ -450,10 +452,11 @@ void hrtim_rst_cb_unset(hrtim_t dev, hrtim_tu_t tu, hrtim_out_t out, ...@@ -450,10 +452,11 @@ void hrtim_rst_cb_unset(hrtim_t dev, hrtim_tu_t tu, hrtim_out_t out,
* @brief Full timing unit outputs set/reset crossbars setting for * @brief Full timing unit outputs set/reset crossbars setting for
* complementary pwm. * complementary pwm.
* *
* @param[in] dev HRTIM device * @param[in] dev HRTIM device
* @param[in] tu Timing unit * @param[in] tu Timing unit
* @param[in] switch_convention Choice of the switch convention
*/ */
void hrtim_cmpl_pwm_out(hrtim_t dev, hrtim_tu_t tu); void hrtim_cmpl_pwm_out(hrtim_t dev, hrtim_tu_t tu, bool switch_convention);
/** /**
* @brief Set a period value * @brief Set a period value
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
* *
* @author Hugues Larrive <hugues.larrive@laas.fr> * @author Hugues Larrive <hugues.larrive@laas.fr>
* @author Clément Foucher <clement.foucher@laas.fr> * @author Clément Foucher <clement.foucher@laas.fr>
* @author Antoine Boche <antoine.boche@laas.fr>
*/ */
#include "hrtim.h" #include "hrtim.h"
...@@ -127,7 +128,7 @@ static inline uint32_t _period_ckpsc(hrtim_t hrtim, uint32_t freq, ...@@ -127,7 +128,7 @@ static inline uint32_t _period_ckpsc(hrtim_t hrtim, uint32_t freq,
return frequency; return frequency;
} }
uint16_t hrtim_init(hrtim_t hrtim, uint32_t *freq, uint16_t dt) uint16_t hrtim_init(hrtim_t hrtim, uint32_t *freq, uint16_t dt, uint8_t upper_switch_convention)
{ {
/* Master timer initialization */ /* Master timer initialization */
uint16_t period = hrtim_init_master(hrtim, freq); uint16_t period = hrtim_init_master(hrtim, freq);
...@@ -144,7 +145,7 @@ uint16_t hrtim_init(hrtim_t hrtim, uint32_t *freq, uint16_t dt) ...@@ -144,7 +145,7 @@ uint16_t hrtim_init(hrtim_t hrtim, uint32_t *freq, uint16_t dt)
hrtim_cnt_en(hrtim, (1 << (HRTIM_MCR_TACEN_Pos + tu))); hrtim_cnt_en(hrtim, (1 << (HRTIM_MCR_TACEN_Pos + tu)));
/* Setup outputs */ /* Setup outputs */
hrtim_cmpl_pwm_out(hrtim, tu); hrtim_cmpl_pwm_out(hrtim, tu, upper_switch_convention);
/* Reset on master timer period event */ /* Reset on master timer period event */
hrtim_rst_evt_en(hrtim, tu, RST_MSTPER); hrtim_rst_evt_en(hrtim, tu, RST_MSTPER);
...@@ -342,12 +343,53 @@ void hrtim_rst_cb_unset(hrtim_t hrtim, hrtim_tu_t tu, hrtim_out_t out, ...@@ -342,12 +343,53 @@ void hrtim_rst_cb_unset(hrtim_t hrtim, hrtim_tu_t tu, hrtim_out_t out,
} }
} }
void hrtim_cmpl_pwm_out(hrtim_t hrtim, hrtim_tu_t tu) void hrtim_cmpl_pwm_out(hrtim_t hrtim, hrtim_tu_t tu, uint8_t upper_switch_convention)
{ {
dev(hrtim)->sTimerxRegs[tu].SETx1R = PER; //Configuration for the upper switch convention
dev(hrtim)->sTimerxRegs[tu].RSTx1R = CMP1; if (upper_switch_convention == true)
dev(hrtim)->sTimerxRegs[tu].SETx2R = CMP1; {
dev(hrtim)->sTimerxRegs[tu].RSTx2R = PER; //Configuration for the TIMA that is not correctly mounted in the hardware
//It is actually inversed that is why TIMA has a different configuration
//To be changed for the new booard
if(tu==0)
{
dev(hrtim)->sTimerxRegs[tu].SETx1R = CMP1;
dev(hrtim)->sTimerxRegs[tu].RSTx1R = PER;
dev(hrtim)->sTimerxRegs[tu].SETx2R = PER;
dev(hrtim)->sTimerxRegs[tu].RSTx2R = CMP1;
}
else
{
dev(hrtim)->sTimerxRegs[tu].SETx1R = PER;
dev(hrtim)->sTimerxRegs[tu].RSTx1R = CMP1;
dev(hrtim)->sTimerxRegs[tu].SETx2R = CMP1;
dev(hrtim)->sTimerxRegs[tu].RSTx2R = PER;
}
}
//Configuration for the lower switch convention
else if (upper_switch_convention == false)
{
//Configuration for the TIMA that is not correctly mounted in the hardware
//It is actually inversed that is why TIMA has a different configuration
//To be changed for the new booard
if(tu==0)
{
dev(hrtim)->sTimerxRegs[tu].SETx1R = PER;
dev(hrtim)->sTimerxRegs[tu].RSTx1R = CMP1;
dev(hrtim)->sTimerxRegs[tu].SETx2R = CMP1;
dev(hrtim)->sTimerxRegs[tu].RSTx2R = PER;
}
else
{
dev(hrtim)->sTimerxRegs[tu].SETx1R = CMP1;
dev(hrtim)->sTimerxRegs[tu].RSTx1R = PER;
dev(hrtim)->sTimerxRegs[tu].SETx2R = PER;
dev(hrtim)->sTimerxRegs[tu].RSTx2R = CMP1;
}
}
} }
void hrtim_period_set(hrtim_t hrtim, hrtim_tu_t tu, uint16_t value) void hrtim_period_set(hrtim_t hrtim, hrtim_tu_t tu, uint16_t value)
...@@ -431,6 +473,10 @@ void hrtim_out_dis(hrtim_t hrtim, hrtim_tu_t tu, hrtim_out_t out) ...@@ -431,6 +473,10 @@ void hrtim_out_dis(hrtim_t hrtim, hrtim_tu_t tu, hrtim_out_t out)
dev(hrtim)->sCommonRegs.ODISR |= (out << (tu * 2)); dev(hrtim)->sCommonRegs.ODISR |= (out << (tu * 2));
} }
/* Note : The dead time is configured centered by default,
* there are no options available to modify this, so the dead time
* must be taken into account when calculating the PWM duty cycle */
void hrtim_pwm_dt(hrtim_t hrtim, hrtim_tu_t tu, uint16_t ns) void hrtim_pwm_dt(hrtim_t hrtim, hrtim_tu_t tu, uint16_t ns)
{ {
uint32_t ps = ns * 1000; uint32_t ps = ns * 1000;
...@@ -444,9 +490,9 @@ void hrtim_pwm_dt(hrtim_t hrtim, hrtim_tu_t tu, uint16_t ns) ...@@ -444,9 +490,9 @@ void hrtim_pwm_dt(hrtim_t hrtim, hrtim_tu_t tu, uint16_t ns)
#warning "unsupported stm32XX family" #warning "unsupported stm32XX family"
#endif #endif
uint8_t dtpsc = 0; uint8_t dtpsc = 0; // Deadtime clock prescaler set at xx
uint32_t t_dtg_ps = (1 << dtpsc) * 1000000 / ((f_hrtim * 8) / 1000000); uint32_t t_dtg_ps = (1 << dtpsc) * 1000000 / ((f_hrtim * 8) / 1000000); // intermediate gain for dead time calculation
uint16_t dt = ps / t_dtg_ps; uint16_t dt = ps / t_dtg_ps; // calculate the register value based on desired deadtime in picoseconds
while (dt > 511 && dtpsc < 7) { while (dt > 511 && dtpsc < 7) {
dtpsc++; dtpsc++;
t_dtg_ps = (1 << dtpsc) * 1000000 / ((f_hrtim * 8) / 1000000); t_dtg_ps = (1 << dtpsc) * 1000000 / ((f_hrtim * 8) / 1000000);
...@@ -458,9 +504,11 @@ void hrtim_pwm_dt(hrtim_t hrtim, hrtim_tu_t tu, uint16_t ns) ...@@ -458,9 +504,11 @@ void hrtim_pwm_dt(hrtim_t hrtim, hrtim_tu_t tu, uint16_t ns)
dev(hrtim)->sTimerxRegs[tu].DTxR &= ~(HRTIM_DTR_DTPRSC_Msk dev(hrtim)->sTimerxRegs[tu].DTxR &= ~(HRTIM_DTR_DTPRSC_Msk
| HRTIM_DTR_DTF_Msk | HRTIM_DTR_DTF_Msk
| HRTIM_DTR_DTR); | HRTIM_DTR_DTR);
dev(hrtim)->sTimerxRegs[tu].DTxR |= (dtpsc << HRTIM_DTR_DTPRSC_Pos); dev(hrtim)->sTimerxRegs[tu].DTxR |= (dtpsc << HRTIM_DTR_DTPRSC_Pos); // Deadtime clock prescaler
dev(hrtim)->sTimerxRegs[tu].DTxR |= (dt << HRTIM_DTR_DTF_Pos); dev(hrtim)->sTimerxRegs[tu].DTxR |= (dt << HRTIM_DTR_DTF_Pos); // Deadtime falling edge value
dev(hrtim)->sTimerxRegs[tu].DTxR |= (dt << HRTIM_DTR_DTR_Pos); dev(hrtim)->sTimerxRegs[tu].DTxR |= (dt << HRTIM_DTR_DTR_Pos); // Deadtime rising edge value
// dev(hrtim)->sTimerxRegs[tu].DTxR |= HRTIM_DTR_SDTF; //change the behavior of the deadtime insertion by overlapping the signals (negative falling edge)
// dev(hrtim)->sTimerxRegs[tu].DTxR |= HRTIM_DTR_SDTR; //change the behavior of the deadtime insertion by overlapping the signals (positive falling edge)
dev(hrtim)->sTimerxRegs[tu].OUTxR |= HRTIM_OUTR_DTEN; /* Note: This dev(hrtim)->sTimerxRegs[tu].OUTxR |= HRTIM_OUTR_DTEN; /* Note: This
* parameter cannot be changed once the timer is operating (TxEN bit * parameter cannot be changed once the timer is operating (TxEN bit
* set) or if its outputs are enabled and set/reset by another timer. */ * set) or if its outputs are enabled and set/reset by another timer. */
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
* @brief PWM management layer by inverter leg interface definitions * @brief PWM management layer by inverter leg interface definitions
* @date 2020 * @date 2020
* @author Hugues Larrive <hugues.larrive@laas.fr> * @author Hugues Larrive <hugues.larrive@laas.fr>
* @author Antoine Boche <antoine.boche@laas.fr>
*/ */
#ifndef LEG_H #ifndef LEG_H
...@@ -52,9 +53,13 @@ typedef struct { ...@@ -52,9 +53,13 @@ typedef struct {
} leg_conf_t; } leg_conf_t;
/** /**
* @brief Initializes all the configured devices * @brief Initializes all the configured devices with the chosen switch convention
*
* @param[in] upper_switch_convention Choice of the switch convention
*
* @return HRTIM period
*/ */
void leg_init(void); uint16_t leg_init(bool upper_switch_convention);
/** /**
* @brief Set the PWM pulse width for a given leg device * @brief Set the PWM pulse width for a given leg device
......
...@@ -23,39 +23,55 @@ ...@@ -23,39 +23,55 @@
* @brief PWM management layer by inverter leg * @brief PWM management layer by inverter leg
* @date 2020 * @date 2020
* @author Hugues Larrive <hugues.larrive@laas.fr> * @author Hugues Larrive <hugues.larrive@laas.fr>
* @author Antoine Boche <antoine.boche@laas.fr>
*/ */
#include "leg.h" #include "leg.h"
#include "owntech_leg_driver.h" #include "owntech_leg_driver.h"
static uint16_t period, min_pw, max_pw; static uint16_t period, min_pw, max_pw, dead_time;
static leg_conf_t leg_conf[6]; /* a copy of leg_config with index static leg_conf_t leg_conf[6]; /* a copy of leg_config with index
* corresponding to timing unit */ * corresponding to timing unit */
void leg_init(void) /**
* This function Initialize the hrtim and all the legs
* with the chosen convention for the switch controlled
* on the power converter to a frequency of 200kHz
* Must be initialized in first position
*/
uint16_t leg_init(bool upper_switch_convention)
{ {
uint32_t freq = LEG_FREQ; uint32_t freq = LEG_FREQ;
/* ensures that timing_unit can be used as leg identifier */ /* ensures that timing_unit can be used as leg identifier */
for (int i = 0; i < LEG_NUMOF; i++) { for (int i = 0; i < LEG_NUMOF; i++)
{
leg_conf[leg_config[i].timing_unit] = leg_config[i]; leg_conf[leg_config[i].timing_unit] = leg_config[i];
} }
period = hrtim_init(0, &freq, LEG_DEFAULT_DT); period = hrtim_init(0, &freq, LEG_DEFAULT_DT,upper_switch_convention);
min_pw = period / 10; dead_time = (period*LEG_DEFAULT_DT*leg_get_freq())/1000000;
max_pw = period - min_pw; min_pw = (period * 0.1) + dead_time;
max_pw = (period * 0.9) + dead_time;
return period;
} }
void leg_set(hrtim_tu_t timing_unit, uint16_t pulse_width, uint16_t phase_shift) void leg_set(hrtim_tu_t timing_unit, uint16_t pulse_width, uint16_t phase_shift)
{ {
if (pulse_width < min_pw) { //addition of the dead time for the rectification of the centered dead time configuration cf:hrtim_pwm_dt()
pulse_width = min_pw; pulse_width = pulse_width+dead_time;
//Second check for duty cycle saturation
if (pulse_width<min_pw)
{
pulse_width = max_pw;
} }
if (pulse_width > max_pw) { else if (pulse_width > max_pw)
{
pulse_width = max_pw; pulse_width = max_pw;
} }
hrtim_pwm_set( leg_conf[timing_unit].hrtim, hrtim_pwm_set( leg_conf[timing_unit].hrtim,
timing_unit, timing_unit,
pulse_width, pulse_width,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment