Commit fd429280 authored by Clément Foucher's avatar Clément Foucher
Browse files

Integrate power conversion API as a module.

parent b8a73032
......@@ -10,6 +10,5 @@
[env]
lib_deps=
peripherals = https://gitlab.laas.fr/owntech/power-api/opalib-peripherals.git
control_pid = https://gitlab.laas.fr/owntech/power-api/opalib-control-pid.git
power_conversion = https://gitlab.laas.fr/owntech/power-api/opalib-power-conversion.git
peripherals = https://gitlab.laas.fr/owntech/power-api/opalib-peripherals.git
control_pid = https://gitlab.laas.fr/owntech/power-api/opalib-control-pid.git
......@@ -2,6 +2,12 @@ description: GPIO-controllable device
compatible: "gpio-device"
properties:
label:
required: true
type: string
description: Name of the peripheral (used as device_get_binding() argument)
child-binding:
description: GPIO node
properties:
......@@ -11,4 +17,4 @@ child-binding:
label:
required: true
type: string
description: Human readable string describing the device (used as device_get_binding() argument)
description: Human-readable string describing the pin function
......@@ -5,11 +5,11 @@ compatible: "hrtim"
include: base.yaml
properties:
pinctrl-0:
type: phandles
required: false
description: |
GPIO pin configuration for HRTIM outputs. We expect that the
phandles will reference pinctrl nodes, e.g.
pinctrl-0 = <&hrtim1_cha1_pa8 &hrtim1_cha2_pa9>;
pinctrl-0:
type: phandles
required: false
description: |
GPIO pin configuration for HRTIM outputs.
The phandles have to reference pinctrl nodes, e.g.
pinctrl-0 = <&hrtim1_cha1_pa8 &hrtim1_cha2_pa9>;
......@@ -142,11 +142,6 @@ static inline void dac_stop(const struct device* dev, uint8_t channel)
api->stop(dev, channel);
}
/////
// Owntech-specific config
void owntech_dac_dac1_dac3_current_mode_init();
#ifdef __cplusplus
}
......
......@@ -12,6 +12,8 @@ if(CONFIG_OWNTECH_HARDWARE_CONFIGURATION)
src/ngnd_configuration.cpp
src/led_configuration.cpp
src/timer_configuration.cpp
src/hrtim_configuration.cpp
src/uart_configuration.cpp
public_api/HardwareConfiguration.cpp
)
endif()
......@@ -28,6 +28,8 @@
#include "../src/ngnd_configuration.h"
#include "../src/led_configuration.h"
#include "../src/timer_configuration.h"
#include "../src/hrtim_configuration.h"
#include "../src/uart_configuration.h"
// Current class header
#include "HardwareConfiguration.h"
......@@ -43,6 +45,24 @@ HardwareConfiguration hwConfig;
// Public static configuration functions
/////
// Common
/**
* @brief Sets the version of the underlying hardware.
* Depending on the hardware version, some software
* configuration, such as pinout, has to be tweaked.
* @param hardware_version Enum representing the hardware version.
*/
void HardwareConfiguration::setBoardVersion(hardware_version_t hardware_version)
{
if (hardware_version == v_1_1_2)
{
uart_lpuart1_swap_rx_tx();
}
}
/////
// DAC
......@@ -65,6 +85,7 @@ void HardwareConfiguration::setNgndOff()
ngnd_config_off();
}
/////
// LED
......@@ -83,6 +104,8 @@ void HardwareConfiguration::setLedToggle()
led_config_toggle();
}
/////
// Incremental encoder
void HardwareConfiguration::startLoggingIncrementalEncoder()
......@@ -94,3 +117,111 @@ uint32_t HardwareConfiguration::getIncrementalEncoderValue()
{
return timer_incremental_encoder_tim4_get_step();
}
/////
// Power converter
void HardwareConfiguration::initInterleavedBuckMode()
{
hrtim_init_interleaved_buck_mode();
}
void HardwareConfiguration::initInterleavedBoostMode()
{
hrtim_init_interleaved_boost_mode();
}
void HardwareConfiguration::initFullBridgeBuckMode()
{
hrtim_init_interleaved_buck_mode();
}
void HardwareConfiguration::initFullBridgeBoostMode()
{
hrtim_init_interleaved_boost_mode();
}
void HardwareConfiguration::initIndependentMode(bool leg1_buck_mode, bool leg2_buck_mode)
{
hrtim_init_independent_mode(leg1_buck_mode, leg2_buck_mode);
}
void HardwareConfiguration::setInterleavedDutyCycle(float32_t duty_cycle)
{
hrtim_interleaved_pwm_update(duty_cycle);
}
void HardwareConfiguration::setFullBridgeDutyCycle(float32_t duty_cycle)
{
hrtim_hbridge_pwm_update(duty_cycle);
}
void HardwareConfiguration::setLeg1DutyCycle(float32_t duty_cycle)
{
hrtim_leg1_pwm_update(duty_cycle);
}
void HardwareConfiguration::setLeg2DutyCycle(float32_t duty_cycle)
{
hrtim_leg2_pwm_update(duty_cycle);
}
void HardwareConfiguration::setInterleavedOn()
{
hrtim_start_interleaved();
}
void HardwareConfiguration::setFullBridgeOn()
{
hrtim_start_interleaved();
}
void HardwareConfiguration::setLeg1On()
{
hrtim_start_leg1();
}
void HardwareConfiguration::setLeg2On()
{
hrtim_start_leg2();
}
void HardwareConfiguration::setInterleavedOff()
{
hrtim_stop_interleaved();
}
void HardwareConfiguration::setFullBridgeOff()
{
hrtim_stop_interleaved();
}
void HardwareConfiguration::setLeg1Off()
{
hrtim_stop_leg1();
}
void HardwareConfiguration::setLeg2Off()
{
hrtim_stop_leg2();
}
/////
// Extra UART
void HardwareConfiguration::extraUartInit()
{
uart_usart1_init();
}
char HardwareConfiguration::extraUartReadChar()
{
return uart_usart1_get_data();
}
void HardwareConfiguration::extraUartWriteChar(char data)
{
uart_usart1_write_single(data);
}
......@@ -28,6 +28,19 @@
#include <stdint.h>
#include <arm_math.h>
/** Hardware version. See
* https://gitlab.laas.fr/owntech/1leg/-/wikis/Releases
* for the list and specificities of versions.
*/
typedef enum
{
v_0_0, // No power converter attached, the software is running on Nucleo G474RE
v_0_9,
v_1_1_2
} hardware_version_t;
/////
......@@ -37,6 +50,9 @@ class HardwareConfiguration
{
public:
// Common
void setBoardVersion(hardware_version_t hardware_version);
// DAC
void initDac1Dac3CurrentMode();
......@@ -53,6 +69,33 @@ public:
void startLoggingIncrementalEncoder();
uint32_t getIncrementalEncoderValue();
// Power converter
void initInterleavedBuckMode();
void initInterleavedBoostMode();
void initFullBridgeBuckMode();
void initFullBridgeBoostMode();
void initIndependentMode(bool leg1_buck_mode, bool leg2_buck_mode);
void setInterleavedDutyCycle(float32_t duty_cycle);
void setFullBridgeDutyCycle(float32_t duty_cycle);
void setLeg1DutyCycle(float32_t duty_cycle);
void setLeg2DutyCycle(float32_t duty_cycle);
void setInterleavedOn();
void setFullBridgeOn();
void setLeg1On();
void setLeg2On();
void setInterleavedOff();
void setFullBridgeOff();
void setLeg1Off();
void setLeg2Off();
// Extra UART
void extraUartInit();
char extraUartReadChar();
void extraUartWriteChar(char data);
};
......
/*
* Copyright (c) 2021-2022 LAAS-CNRS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: LGLPV2.1
*/
/**
* @date 2022
* @author Luiz Villa <luiz.villa@laas.fr>
* @author Clément Foucher <clement.foucher@laas.fr>
*/
// OwnTech Power API
#include "leg.h" // PWM management layer by inverter leg interface
#include "hrtim.h"
// Current file header
#include "hrtim_configuration.h"
/////
// 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;
static uint16_t pwm_phase_shift;
static uint16_t pwm_low_pulse_width;
static uint16_t pwm_high_pulse_width;
/**
* This function initializes both legs in buck mode
*/
void hrtim_init_interleaved_buck_mode()
{
hrtim_init_voltage_buck();
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;
}
/**
* This function initializes both legs in boost mode
*/
void hrtim_init_interleaved_boost_mode()
{
hrtim_init_voltage_boost();
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;
}
/**
* This leg initializes each leg independently. It receives the modes of each leg and triggers them accordingly.
*/
void hrtim_init_independent_mode(bool leg1_buck_mode, bool leg2_buck_mode)
{
// High resolution timer initialization
if (leg1_buck_mode && !leg2_buck_mode){
hrtim_init_voltage_leg1_buck_leg2_boost();
}
else if (!leg1_buck_mode && leg2_buck_mode){
hrtim_init_voltage_leg1_boost_leg2_buck();
}
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;
}
/**
* This function transfer the calculated PWM value to the
* HRTIM peripheral and make sure it is between saturation
* bounds
*/
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(TIMA, pwm_pulse_width, 0);
leg_set(TIMB, 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(TIMA, pwm_pulse_width, 0);
leg_set(TIMB, pwm_pulse_width, pwm_phase_shift);
}
else
{
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
leg_set(TIMA, pwm_pulse_width, 0);
leg_set(TIMB, pwm_pulse_width, pwm_phase_shift);
}
}
/**
* This function transfer the calculated PWM value to the
* HRTIM peripheral and make sure it is between saturation
* bounds
*/
void hrtim_hbridge_pwm_update(float32_t pwm_duty_cycle)
{
uint16_t pwm_pulse_width;
uint16_t pwm_reverse_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;
pwm_reverse_pulse_width = (1-pwm_duty_cycle) * pwm_period;
leg_set(TIMA, pwm_pulse_width, 0);
leg_set(TIMB, 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(TIMA, pwm_pulse_width, 0);
leg_set(TIMB, 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(TIMA, pwm_pulse_width, 0);
leg_set(TIMB, pwm_reverse_pulse_width, pwm_period*pwm_duty_cycle);
}
}
/**
* This function transfer the calculated PWM value of leg_1 to the
* HRTIM peripheral and make sure it is between saturation
* bounds
*/
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(TIMA, pwm_pulse_width, 0);
}
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(TIMA, pwm_pulse_width, 0);
}
else
{
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
leg_set(TIMA, pwm_pulse_width, 0);
}
}
/**
* This function transfer the calculated PWM value of leg_2 to the
* HRTIM peripheral and make sure it is between saturation
* bounds
*/
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(TIMB, 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(TIMB, pwm_pulse_width, pwm_phase_shift);
}
else
{
pwm_pulse_width = (pwm_duty_cycle * pwm_period);
leg_set(TIMB, pwm_pulse_width, pwm_phase_shift);
}
}
/**
* This stops the converter by putting both timing
* units outputs low
*/
void hrtim_stop_interleaved()
{
leg_stop(TIMA);
leg_stop(TIMB);
}
/**
* This stops only leg 1
*/
void hrtim_stop_leg1()
{
leg_stop(TIMA);
}
/**
* This stops only leg 2
*/
void hrtim_stop_leg2()
{
leg_stop(TIMB);
}
/**
* This stops the converter by putting both timing
* units outputs low
*/
void hrtim_start_interleaved()
{
leg_start(TIMA);
leg_start(TIMB);
}
/**
* This stops the converter by putting both timing
* units outputs low
*/
void hrtim_start_leg1()
{
leg_start(TIMA);
}
/**
* This stops the converter by putting both timing
* units outputs low
*/
void hrtim_start_leg2()
{
leg_start(TIMB);
}
/*
* Copyright (c) 2021-2022 LAAS-CNRS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the