Skip to content
Snippets Groups Projects
Commit f1e6ddf4 authored by Luiz Fernando Lavado Villa's avatar Luiz Fernando Lavado Villa :speech_balloon:
Browse files

Patch to control the min-max duty cycle and the frequency of the Hrtim

It is necessary to properly control the min and max duty cycle of the hrtim. Our code already does that, but it is not efficient neither does it give the possibility for the user to dynamically set other min/max values. This patch solves that.

It is also necessary to give the user the possibility of setting the frequency of the HRTIM. This patch solves that at the leg driver level and provides the user with an access point.

Both the frequency and the min/max duty cycles are set by default at 200kHz and 0.1/0.9 respectively.
parent ed7c45df
No related branches found
No related tags found
1 merge request!34Patch to control the min-max duty cycle and the frequency of the Hrtim
......@@ -289,6 +289,27 @@ void HardwareConfiguration::setLeg2PhaseShiftCenterAligned(float32_t phase_shift
hrtim_leg2_phase_shift_update_center_aligned(phase_shift);
}
void HardwareConfiguration::setHrtimFrequency(uint32_t frequency_Hz)
{
hrtim_set_frequency(frequency_Hz);
}
uint32_t HardwareConfiguration::getHrtimFrequency()
{
return hrtim_get_frequency();
}
void HardwareConfiguration::setHrtimMinDutyCycle(float32_t duty_cycle)
{
hrtim_set_min_duty_cycle(duty_cycle);
}
void HardwareConfiguration::setHrtimMaxDutyCycle(float32_t duty_cycle)
{
hrtim_set_max_duty_cycle(duty_cycle);
}
void HardwareConfiguration::setInterleavedOn()
{
power_driver_interleaved_on();
......
......@@ -120,6 +120,10 @@ public:
static void setLeg1DeadTime(uint16_t rise_ns, uint16_t fall_ns);
static void setLeg2DeadTime(uint16_t rise_ns, uint16_t fall_ns);
static void setHrtimFrequency(uint32_t frequency_Hz);
static uint32_t getHrtimFrequency();
static void setHrtimMinDutyCycle(float32_t duty_cycle);
static void setHrtimMaxDutyCycle(float32_t duty_cycle);
static void setInterleavedOn();
static void setFullBridgeBuckOn();
......
......@@ -36,10 +36,6 @@
/////
// Defines
// Saturation values used for the PWM duty cycle
#define LOW_DUTY 0.1
#define HIGH_DUTY 0.9
/////
// Local variables
static uint16_t pwm_period;
......@@ -74,8 +70,6 @@ void hrtim_init_interleaved_buck_mode()
pwm_period = leg_period();
pwm_phase_shift = pwm_period / 2;
pwm_low_pulse_width = pwm_period * LOW_DUTY;
pwm_high_pulse_width = pwm_period * HIGH_DUTY;
}
/**
......@@ -87,8 +81,6 @@ void hrtim_init_interleaved_buck_mode_center_aligned()
pwm_period = leg_period();
pwm_phase_shift = pwm_period;
pwm_low_pulse_width = pwm_period * LOW_DUTY;
pwm_high_pulse_width = pwm_period * HIGH_DUTY;
}
/**
......@@ -100,8 +92,6 @@ void hrtim_init_interleaved_boost_mode()
pwm_period = leg_period();
pwm_phase_shift = pwm_period / 2;
pwm_low_pulse_width = pwm_period * LOW_DUTY;
pwm_high_pulse_width = pwm_period * HIGH_DUTY;
}
void hrtim_init_interleaved_boost_mode_center_aligned()
......@@ -110,8 +100,6 @@ void hrtim_init_interleaved_boost_mode_center_aligned()
pwm_period = leg_period();
pwm_phase_shift = pwm_period;
pwm_low_pulse_width = pwm_period * LOW_DUTY;
pwm_high_pulse_width = pwm_period * HIGH_DUTY;
}
/**
......@@ -137,8 +125,6 @@ void hrtim_init_independent_mode(bool leg1_buck_mode, bool leg2_buck_mode)
pwm_phase_shift_leg1 = 0;
pwm_phase_shift_leg2 = pwm_period / 2;
pwm_phase_shift = pwm_period/2;
pwm_low_pulse_width = pwm_period * LOW_DUTY;
pwm_high_pulse_width = pwm_period * HIGH_DUTY;
}
/**
......@@ -163,8 +149,6 @@ void hrtim_init_independent_mode_center_aligned(bool leg1_buck_mode, bool leg2_b
pwm_period = leg_period();
pwm_phase_shift = pwm_period;
pwm_low_pulse_width = pwm_period * LOW_DUTY;
pwm_high_pulse_width = pwm_period * HIGH_DUTY;
}
/**
......@@ -180,9 +164,6 @@ void hrtim_init_full_bridge_buck_mode(bool SPIN_board_V_1_1_2)
full_bridge_bipolar_mode = false; //left-aligned inverter is always on unipolar mode
pwm_period = leg_period();
pwm_low_pulse_width = pwm_period * LOW_DUTY;
pwm_high_pulse_width = pwm_period * HIGH_DUTY;
pwm_phase_shift = pwm_period / 2;
}
......@@ -201,8 +182,6 @@ void hrtim_init_full_bridge_buck_mode_center_aligned(bool bipolar_mode,bool SPIN
full_bridge_bipolar_mode = bipolar_mode;
pwm_period = leg_period();
pwm_low_pulse_width = pwm_period * LOW_DUTY;
pwm_high_pulse_width = pwm_period * HIGH_DUTY;
if (bipolar_mode){
pwm_phase_shift = 0;
......@@ -223,29 +202,9 @@ void hrtim_interleaved_pwm_update(float32_t pwm_duty_cycle)
{
uint16_t pwm_pulse_width;
// TESTING PWM VALUE TO AVOID OVERFLOW AND PWM UPDATE//
if (pwm_duty_cycle > HIGH_DUTY) // SATURATION CONDITIONS TO AVOID DIVERGENCE.
{
pwm_duty_cycle = HIGH_DUTY;
pwm_pulse_width = pwm_high_pulse_width;
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_pulse_width, pwm_phase_shift);
}
else if (pwm_duty_cycle < LOW_DUTY) // SATURATION CONDITIONS TO AVOID DIVERGENCE.
{
pwm_duty_cycle = LOW_DUTY;
pwm_pulse_width = pwm_low_pulse_width;
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_pulse_width, pwm_phase_shift);
}
else
{
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_pulse_width, pwm_phase_shift);
}
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_pulse_width, pwm_phase_shift);
}
......@@ -263,55 +222,17 @@ void hrtim_full_bridge_buck_pwm_update(float32_t pwm_duty_cycle)
// TESTING PWM VALUE TO AVOID OVERFLOW AND PWM UPDATE//
if(full_bridge_bipolar_mode)
{
if (pwm_duty_cycle > HIGH_DUTY) // SATURATION CONDITIONS TO AVOID DIVERGENCE.
{
pwm_duty_cycle = HIGH_DUTY;
pwm_pulse_width = pwm_high_pulse_width;
pwm_reverse_pulse_width = (1-pwm_duty_cycle) * pwm_period;
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_reverse_pulse_width, pwm_period*pwm_duty_cycle);
}
else if (pwm_duty_cycle < LOW_DUTY) // SATURATION CONDITIONS TO AVOID DIVERGENCE.
{
pwm_duty_cycle = LOW_DUTY;
pwm_pulse_width = pwm_low_pulse_width;
pwm_reverse_pulse_width = (1-pwm_duty_cycle) * pwm_period;
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_reverse_pulse_width, pwm_period*pwm_duty_cycle);
}
else
{
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
pwm_reverse_pulse_width = (1-pwm_duty_cycle) * pwm_period;
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_reverse_pulse_width, pwm_period*pwm_duty_cycle);
}
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
pwm_reverse_pulse_width = (1-pwm_duty_cycle) * pwm_period;
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_reverse_pulse_width, pwm_period*pwm_duty_cycle);
}
else
{
if (pwm_duty_cycle > HIGH_DUTY) // SATURATION CONDITIONS TO AVOID DIVERGENCE.
{
pwm_duty_cycle = HIGH_DUTY;
pwm_pulse_width = pwm_high_pulse_width;
pwm_reverse_pulse_width = (1-pwm_duty_cycle) * pwm_period;
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_reverse_pulse_width, pwm_phase_shift);
}
else if (pwm_duty_cycle < LOW_DUTY) // SATURATION CONDITIONS TO AVOID DIVERGENCE.
{
pwm_duty_cycle = LOW_DUTY;
pwm_pulse_width = pwm_low_pulse_width;
pwm_reverse_pulse_width = (1-pwm_duty_cycle) * pwm_period;
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_reverse_pulse_width, pwm_phase_shift);
}
else
{
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
pwm_reverse_pulse_width = (1-pwm_duty_cycle) * pwm_period;
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_reverse_pulse_width, pwm_phase_shift);
}
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
pwm_reverse_pulse_width = (1-pwm_duty_cycle) * pwm_period;
leg_set(leg1_tu, pwm_pulse_width, 0);
leg_set(leg2_tu, pwm_reverse_pulse_width, pwm_phase_shift);
}
}
......@@ -325,26 +246,8 @@ void hrtim_leg1_pwm_update(float32_t pwm_duty_cycle)
{
uint16_t pwm_pulse_width;
// TESTING PWM VALUE TO AVOID OVERFLOW AND PWM UPDATE//
if (pwm_duty_cycle > HIGH_DUTY) // SATURATION CONDITIONS TO AVOID DIVERGENCE.
{
pwm_duty_cycle = HIGH_DUTY;
pwm_pulse_width = pwm_high_pulse_width;
leg_set(leg1_tu, pwm_pulse_width, pwm_phase_shift_leg1);
}
else if (pwm_duty_cycle < LOW_DUTY) // SATURATION CONDITIONS TO AVOID DIVERGENCE.
{
pwm_duty_cycle = LOW_DUTY;
pwm_pulse_width = pwm_low_pulse_width;
leg_set(leg1_tu, pwm_pulse_width, pwm_phase_shift_leg1);
}
else
{
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
leg_set(leg1_tu, pwm_pulse_width, pwm_phase_shift_leg1);
}
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
leg_set(leg1_tu, pwm_pulse_width, pwm_phase_shift_leg1);
}
/**
......@@ -356,26 +259,8 @@ void hrtim_leg2_pwm_update(float32_t pwm_duty_cycle)
{
uint16_t pwm_pulse_width;
// TESTING PWM VALUE TO AVOID OVERFLOW AND PWM UPDATE//
if (pwm_duty_cycle > HIGH_DUTY) // SATURATION CONDITIONS TO AVOID DIVERGENCE.
{
pwm_duty_cycle = HIGH_DUTY;
pwm_pulse_width = pwm_high_pulse_width;
leg_set(leg2_tu, pwm_pulse_width, pwm_phase_shift_leg2);
}
else if (pwm_duty_cycle < LOW_DUTY) // SATURATION CONDITIONS TO AVOID DIVERGENCE.
{
pwm_duty_cycle = LOW_DUTY;
pwm_pulse_width = pwm_low_pulse_width;
leg_set(leg2_tu, pwm_pulse_width, pwm_phase_shift_leg2);
}
else
{
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
leg_set(leg2_tu, pwm_pulse_width, pwm_phase_shift_leg2);
}
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
leg_set(leg2_tu, pwm_pulse_width, pwm_phase_shift_leg2);
}
/**
......@@ -511,6 +396,7 @@ void hrtim_set_dead_time_leg1(uint16_t rise_ns, uint16_t fall_ns)
{
leg_set_dt(leg1_tu, rise_ns, fall_ns);
}
/**
* This updates the dead time of the leg 2
*/
......@@ -518,3 +404,36 @@ void hrtim_set_dead_time_leg2(uint16_t rise_ns, uint16_t fall_ns)
{
leg_set_dt(leg2_tu, rise_ns, fall_ns);
}
/**
* This sets the frequency of the HRTIMER
*/
void hrtim_set_frequency(uint32_t frequency_Hz)
{
leg_set_freq(frequency_Hz);
}
/**
* This gets the frequency of the HRTIMER
*/
uint32_t hrtim_get_frequency()
{
return leg_get_freq();
}
/**
* This updates the minimum duty cycle of both legs
*/
void hrtim_set_min_duty_cycle(float32_t duty_cycle)
{
leg_set_min_duty_cycle(duty_cycle);
}
/**
* This updates the minimum duty cycle of both legs
*/
void hrtim_set_max_duty_cycle(float32_t duty_cycle)
{
leg_set_max_duty_cycle(duty_cycle);
}
......@@ -221,5 +221,26 @@ void hrtim_set_dead_time_leg1(uint16_t rise_ns, uint16_t fall_ns);
*/
void hrtim_set_dead_time_leg2(uint16_t rise_ns, uint16_t fall_ns);
/**
* @brief Sets the frequency of the HRTIMER
*/
void hrtim_set_frequency(uint32_t frequency_Hz);
/**
* @brief Gets the frequency of the HRTIMER
*/
uint32_t hrtim_get_frequency();
/**
* @brief Updates the minimum duty cycle of both legs
*/
void hrtim_set_min_duty_cycle(float32_t duty_cycle);
/**
* @brief This updates the minimum duty cycle of both legs
*/
void hrtim_set_max_duty_cycle(float32_t duty_cycle);
#endif // HRTIM_CONFIGURATION_H_
......@@ -37,6 +37,7 @@
#include <assert.h>
#include <stdint.h>
#include "arm_math.h"
#include <zephyr.h>
......@@ -46,8 +47,8 @@
extern "C" {
#endif
#define LEG_DEFAULT_DT (100U) /**< dead-time in ns */
#define LEG_FREQ KHZ(200U) /**< frequency in Hz*/
#define LEG_DEFAULT_DT (100U) /**< dead-time in ns */
#define LEG_DEFAULT_FREQ KHZ(200U) /**< frequency in Hz*/
/**
* @brief Inverter leg configuration data structure
......@@ -115,7 +116,7 @@ void leg_start(hrtim_tu_t timing_unit);
/**
* @brief period getter
*
* @return period value returned by leg_init()
* @return period in micro-seconds value returned by leg_init()
*/
uint16_t leg_period(void);
......@@ -136,11 +137,26 @@ uint8_t leg_numof(void);
leg_conf_t leg_get_conf(uint8_t leg);
/**
* @brief LEG_FREQ getter
*
* @return value of LEG_FREQ in KHz
* @brief Gets the frequency in Hz
*/
uint32_t leg_get_freq(void);
/**
* @brief Sets the frequency in Hz
*/
void leg_set_freq(uint32_t frequency_Hz);
/**
* @brief Minimum duty cycle setter. Minimum of 0.02.
*/
void leg_set_min_duty_cycle(float32_t duty_cycle);
/**
* @brief Maximum duty cycle setter. Maximum of 0.98.
*/
uint16_t leg_get_freq(void);
void leg_set_max_duty_cycle(float32_t duty_cycle);
#ifdef __cplusplus
}
......
......@@ -32,8 +32,19 @@
#include "owntech_leg_driver.h"
#include "hrtim_voltage_mode.h"
// Saturation values used for the PWM duty cycle
#define LOW_DUTY 0.03
#define HIGH_DUTY 0.97
static uint16_t period, min_pw, max_pw, dead_time;
// default configurations of the HRTIMER
static uint32_t frequency = 200000;
static float32_t min_duty_cycle = 0.1;
static float32_t max_duty_cycle = 0.9;
static leg_conf_t leg_conf[6]; /* a copy of leg_config with index
* corresponding to timing unit */
......@@ -73,16 +84,14 @@ static uint8_t _TU_num(hrtim_tu_t tu){
*/
uint16_t leg_init(bool leg1_upper_switch_convention, bool leg2_upper_switch_convention, hrtim_tu_t leg1_tu, hrtim_tu_t leg2_tu)
{
uint32_t freq = LEG_FREQ;
/* ensures that timing_unit can be used as leg identifier */
for (unsigned int i = 0; i < LEG_NUMOF; i++)
{
leg_conf[_TU_num(leg_config[i].timing_unit)] = leg_config[i];
}
period = hrtim_init(0, &freq, LEG_DEFAULT_DT,leg1_upper_switch_convention,leg2_upper_switch_convention, leg1_tu, leg2_tu);
dead_time = (period*LEG_DEFAULT_DT*leg_get_freq())/1000000;
period = hrtim_init(0, &frequency, LEG_DEFAULT_DT,leg1_upper_switch_convention,leg2_upper_switch_convention, leg1_tu, leg2_tu);
dead_time = (uint16_t)((((double)period)*LEG_DEFAULT_DT*((double)frequency))/1000000000.0); //this line is overflow safe
min_pw = (period * 0.1) + dead_time;
max_pw = (period * 0.9) + dead_time;
return period;
......@@ -97,18 +106,16 @@ uint16_t leg_init(bool leg1_upper_switch_convention, bool leg2_upper_switch_conv
*/
uint16_t leg_init_center_aligned(bool leg1_upper_switch_convention, bool leg2_upper_switch_convention,hrtim_tu_t leg1_tu, hrtim_tu_t leg2_tu)
{
uint32_t freq = LEG_FREQ;
/* ensures that timing_unit can be used as leg identifier */
for (unsigned int i = 0; i < LEG_NUMOF; i++)
{
leg_conf[_TU_num(leg_config[i].timing_unit)] = leg_config[i];
}
period = hrtim_init_updwn(0, &freq, LEG_DEFAULT_DT,leg1_upper_switch_convention,leg2_upper_switch_convention, leg1_tu, leg2_tu);
dead_time = (period*LEG_DEFAULT_DT*leg_get_freq())/1000000;
min_pw = (period * 0.1) + dead_time;
max_pw = (period * 0.9) + dead_time;
period = hrtim_init_updwn(0, &frequency, LEG_DEFAULT_DT,leg1_upper_switch_convention,leg2_upper_switch_convention, leg1_tu, leg2_tu);
dead_time = (uint16_t)((((double)period)*LEG_DEFAULT_DT*((double)frequency))/1000000000.0); //this line is overflow safe
min_pw = (period * min_duty_cycle) + dead_time;
max_pw = (period * max_duty_cycle) + dead_time;
return period;
}
......@@ -120,7 +127,7 @@ void leg_set(hrtim_tu_t timing_unit, uint16_t pulse_width, uint16_t phase_shift)
//Second check for duty cycle saturation
if (pulse_width<min_pw)
{
pulse_width = max_pw;
pulse_width = min_pw;
}
else if (pulse_width > max_pw)
{
......@@ -172,7 +179,30 @@ leg_conf_t leg_get_conf(uint8_t leg)
return leg_conf[leg_config[leg].timing_unit];
}
uint16_t leg_get_freq(void)
uint32_t leg_get_freq(void)
{
return frequency;
}
void leg_set_freq(uint32_t frequency_Hz)
{
frequency = frequency_Hz;
}
void leg_set_min_duty_cycle(float32_t duty_cycle)
{
return LEG_FREQ / 1000;
if (duty_cycle>=LOW_DUTY) {
min_duty_cycle = duty_cycle;
}else{
min_duty_cycle = LOW_DUTY;
}
}
void leg_set_max_duty_cycle(float32_t duty_cycle)
{
if (duty_cycle<=HIGH_DUTY) {
max_duty_cycle = duty_cycle;
}else{
max_duty_cycle = HIGH_DUTY;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment