Skip to main content
MJame.1
Visitor II
Aug 26, 2022 9:28 PM UTC
Question

Does this code work correctly to control a dc-dc converter?

Hi guys

I want to control a DC-DC converter with a PI controller and STM2F103 MCU; first, the ADC unit reads input and output voltage and inductor current, then we have two control loops; voltage control loop and current control loop. 

For the PI controller i use this Lib :

github.com>Majid-Derhambakhsh>PID-Library

This is my main.c :

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
 
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
 
#include "pid.h"
//#include <stdlib.h>
#include <math.h>
 
/* USER CODE END Includes */
 
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
 
long int k_Ds; 
 
 PID_TypeDef PID_Gvd;
 PID_TypeDef PID_Gid;
 
unsigned char flag_1uS ; 
 
uint32_t ADC_Value [3] ;
double V_High , V_Low , I_Lm ; 
double V_High_ADC , V_Low_ADC , I_Lm_ADC , Duty_M , Duty_S ;
 
/** Boost Controller **/
 
/* Gvd PI Param. */ 
double I_Ref, V_High_Ref = 100, Kp_Gvd = 0.013 , Ki_Gvd = 200/0.00001 ; 
 
/* Gid PI Param. */ 
double Duty_PI , Kp_Gid = 0.27 , Ki_Gid = 3218/0.00001 ;
 
double Duty_aux ;
 
/* USER CODE END PTD */
 
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
 
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
 
/* USER CODE END PM */
 
/* Private variables ---------------------------------------------------------*/
 ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
 
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim4;
 
/* USER CODE BEGIN PV */
 
/* USER CODE END PV */
 
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM1_Init(void);
static void MX_TIM2_Init(void);
static void MX_TIM4_Init(void);
/* USER CODE BEGIN PFP */
 
/* USER CODE END PFP */
 
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
 
/* USER CODE END 0 */
 
/**
 * @brief The application entry point.
 * @retval int
 */
int main(void)
{
 /* USER CODE BEGIN 1 */
 
 /* USER CODE END 1 */
 
 /* MCU Configuration--------------------------------------------------------*/
 
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();
 
 /* USER CODE BEGIN Init */
 
 /* USER CODE END Init */
 
 /* Configure the system clock */
 SystemClock_Config();
 
 /* USER CODE BEGIN SysInit */
 
 /* USER CODE END SysInit */
 
 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_ADC1_Init();
 MX_TIM1_Init();
 MX_TIM2_Init();
 MX_TIM4_Init();
 /* USER CODE BEGIN 2 */
 
 HAL_TIM_Base_Start_IT(&htim1) ;
 
 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
 HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
 
 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
 
 HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
 
 HAL_TIM_Base_Start_IT(&htim2) ;
 
 
 HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4) ;
 
 /******** ********/
 
 
 
 /*PID(PID_TypeDef *uPID, *Input, *Output, *Setpoint, Kp, Ki, Kd, PIDPON_TypeDef POn, PIDCD_TypeDef ControllerDirection); */
 /** Gvd PI Setting **/
 PID(&PID_Gvd , &V_High , &I_Ref , &V_High_Ref , Kp_Gvd , Ki_Gvd , 0, _PID_P_ON_E , _PID_CD_DIRECT);
 PID_SetMode(&PID_Gvd, _PID_MODE_AUTOMATIC);
 PID_SetSampleTime(&PID_Gvd, 0.01);
 PID_SetOutputLimits(&PID_Gvd, 0, 10.8);
 
 
 /** Gid PI Setting **/
 PID(&PID_Gid , &I_Lm , &Duty_PI , &I_Ref , Kp_Gid , Ki_Gid , 0, _PID_P_ON_E , _PID_CD_DIRECT);
 PID_SetMode(&PID_Gid, _PID_MODE_AUTOMATIC);
 PID_SetSampleTime(&PID_Gid, 0.01);
 PID_SetOutputLimits(&PID_Gid, 0.4, 0.9);
 
 
 // calibrate ADC for better accuracy and start it w/ interrupt
 HAL_ADCEx_Calibration_Start(&hadc1) ;
 
 HAL_ADC_Start_IT(&hadc1) ;
 
 HAL_ADC_Start_DMA(&hadc1, (uint32_t*)ADC_Value, 3) ; /* Start ADC DMA */ 
 
 /* USER CODE END 2 */
 
 /* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 
 
 PID_Compute(&PID_Gvd); /* Calculation of Gvd PI Controller */ 
 
 PID_Compute(&PID_Gid);	 /* Calculation of Gid PI Controller */ 
 
 Duty_M = ( 1 - Duty_PI ) * 719 ; 
 
 Aux_Switch_cal() ; 
 
 
 
 /* USER CODE END WHILE */
 
 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}
 
 
/********** My Functions *********/
 
/** Timer Flag **/ 
void System_timeTable(void)
{
 flag_1uS = 1;
}
 
/** Aux Switch calculations **/
void Aux_Switch_cal(void)
{
 
 
 Duty_aux = ( fabs(I_Lm) * 33 * 0.000001 * 1.2 ) / ( V_High * 0.00001 ) ;
 
 if (Duty_aux > 0.48 ) 
 {
 Duty_aux = 0.48 ; 
 }
 
 else if (Duty_aux < 0 ) 
 {
 Duty_aux = 0 ; 
 }
 
 
 
 Duty_S = Duty_aux * 719 ; 
 
 k_Ds++;
}

This is my interrupt routines code :

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
 
 
 if(htim->Instance == TIM1)
 {
 __HAL_TIM_SET_COMPARE(&htim1 , TIM_CHANNEL_1 , round(Duty_M) );
 
 k_pwm++ ; 
 
 __HAL_TIM_SET_COMPARE(&htim1 , TIM_CHANNEL_3 , round(Duty_S) );
 
 }
 
 if (htim->Instance == TIM2) 
 {
 System_timeTable() ; 
 
 k_flag++ ;
 }
 
}
 
 
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
 if (hadc->Instance == ADC1) 
 {
 // PID_TypeDef PID_Gvd;
 // PID_TypeDef PID_Gid;
 
 /* ADC Values */
 V_High_ADC = ( ( ADC_Value[0] * 3.3)/4059 ) ;
 V_Low_ADC = ( ( ADC_Value[1] * 3.3)/4059 ) ;
 I_Lm_ADC = ( ( ADC_Value[2] * 3.3)/4059 ) ;
 
 
 /* Real Values of Measurments */ 
 V_High = (( V_High_ADC / 16 ) * 150235) / 235 ; /* HCPL Gain = 8 , Voltage Divider: R1 = 150 KOhm , Rsens = 235 Ohm */ 
 V_Low = (( V_Low_ADC / 16 ) * 150470) / 470 ; /* HCPL Gain = 8 , LM358 Gain = 2 , Voltage Divider: R1 = 150 KOhm , Rsens = 470 Ohm */
 I_Lm = ( I_Lm_ADC - 2.5 ) / 0.04 ; /* Offset of ASC758 = 2.5 V , Sens of ASC758 = 40mV/A */ 
 
 k_adc++ ; 
 
 
 }
 
}

This topic has been closed for replies.

2 replies

Tesla DeLorean
Guru
Aug 26, 2022 9:41 PM UTC

V_High_ADC = ( ( ADC_Value[0] * 3.3)/4059 ) ;

I'd imagine that should be 4096.0 or 4095.0

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Piranha
Principal III
Aug 27, 2022 1:19 PM UTC

4096 is the correct one. 4095 is popular only because people have some subjective wish to get the full VREF+ voltage, which the ADC cannot even measure...

Seems that a more efficient 32-bit float math should be enough for this purpose.