cancel
Showing results for 
Search instead for 
Did you mean: 

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

MJame.1
Associate

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++ ; 
    
    
  }
  
}

2 REPLIES 2

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
Up vote any posts that you find helpful, it shows what's working..

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.