Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
GIOVANNI MIGLIAZZA
Published © GPL3+

Intelligent AC Solid State Switch

Bipolar solid state power relay, capable of commutation without arcing and/or overcurrent events.

ExpertFull instructions providedOver 12 days1,810

Things used in this project

Hardware components

CoolMOS C7 Gold SJ MOSFET
Infineon CoolMOS C7 Gold SJ MOSFET
Mosfet used
×4
STM32 Nucleo-64 Board
STMicroelectronics STM32 Nucleo-64 Board
Logic control unit
×1
ACS720
Galvanically isolated Current sensor
×1
ACPL-335J
Opto Gate Driver
×1

Software apps and online services

Autodesk Eagle CAD
PCB design software
STMicroelectronics STM32Cube
STM32 microcontroller configuration tool

Story

Read more

Schematics

Schematics of the application.

The file attached contains the schematics of the application developed. The file is in pdf format.

Gerber-Drills

This folder contains the gerbers and drills files in zip format.

PDF 3D

This is the 3D pdf of the board.

Bill Of Materials

BOM with DigiKey codes.

Code

Application Code

C#
Code developed for stm32f446re with uVision Keil 5.23V
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  ** This notice applies to any and all portions of this file
  * that are not between comment pairs USER CODE BEGIN and
  * USER CODE END. Other portions of this file, whether 
  * inserted by the user or by software development tools
  * are owned by their respective copyright owners.
  *
  * COPYRIGHT(c) 2019 STMicroelectronics
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "dac.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stm32f4xx.h"
#include "DWT_Delay.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* 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 ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
uint8_t Fault = DISABLE;
uint32_t Value_ADC1[2];
//Global structure
 typedef struct
{
	float ADC1_val;										//ADC1 Value
	float ADC2_val;										//ADC2 Value
	float I_IN;                       //Grid Current
	double V_IN;                      //Grid Voltage
	float Cor_ADC1;                   //Correction factor ADC1
	float Cor_ADC2;										//Correction factor ADC2
	float V_IN_Peak_MAX;              //Peak Grid Voltage
	uint8_t Status_Switch;            //OPERATING Status
	uint8_t Tick_TIM;                 //Time peak voltage detection
	uint8_t Fault;                    //State Faults
	uint8_t Start_conversion;         //Start peak voltage detection
	uint8_t OPERATING_MODE;           //OPERATING MODE
	uint16_t V_IN_Limit;              //Voltage limit
	uint8_t I_IN_Limit;               //Current limit
}t_SystemStruct;


t_SystemStruct SysStruct;
t_SystemStruct *p = &SysStruct;
#define INDUCTIVE_MODE 0  //INDUCTIVE MODE
#define CAPACITIVE_MODE 1 //CAPACITIVE MODE
#define IDLE  0           // State of System
#define START 1           // State of System
#define STOP  2           // State of System


/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(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_ADC1_Init();
  MX_USART2_UART_Init();
  MX_ADC2_Init();
  MX_DAC_Init();
  MX_TIM6_Init();
  MX_TIM7_Init();
  /* USER CODE BEGIN 2 */
	HAL_ADC_Start(&hadc1);
	HAL_ADC_Start(&hadc2);
  HAL_DAC_Start(&hdac,DAC1_CHANNEL_1);	
  InitParameter();
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  if(p->Start_conversion == ENABLE)
    { // Start conversion
     if(HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK) //timeout di 100ms
       {//I_in
       p->ADC1_val= HAL_ADC_GetValue(&hadc1);	
       p->I_IN = ((p->ADC1_val*0.00081)-1.65)*(p->Cor_ADC1); //Logic Volt -> Grid Current
       }
    	   
    if(HAL_ADC_PollForConversion(&hadc2, 100) == HAL_OK) //timeout di 100ms
      {	//Vin
       p->ADC2_val = HAL_ADC_GetValue(&hadc2);
       p->V_IN = (p->ADC2_val*0.00081)*(p->Cor_ADC2); //Logic Volt -> Grid Volt 
      }
    if(p->V_IN_Peak_MAX < p->V_IN)
      {
       p->V_IN_Peak_MAX=p->V_IN;
      }
    }
   if((p->V_IN_Peak_MAX >=p->V_IN_Limit || p->V_IN_Peak_MAX <=-(p->V_IN_Limit) ) || (p->I_IN>= p->I_IN_Limit|| p->I_IN<= -(p->I_IN_Limit))) 
    {// Over Current & Over Voltage Fault
    p->Fault=ENABLE; 	
		HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(PWM_1_GPIO_Port, PWM_1_Pin,GPIO_PIN_RESET);
		HAL_GPIO_WritePin(PWM_2_GPIO_Port, PWM_2_Pin,GPIO_PIN_RESET);
		HAL_TIM_Base_Stop_IT(&htim6);
		HAL_TIM_Base_Start_IT(&htim7);
    }
	switch (p->Status_Switch)
				{
					case START: //Enable Switch
									if (p->V_IN>=p->V_IN_Peak_MAX )
								{
									if(p->OPERATING_MODE == CAPACITIVE_MODE)
										{
											HAL_Delay(12);  // Delay ms
											DWT_Delay(500); // Delay us
									  }
									HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin,GPIO_PIN_SET);
									HAL_GPIO_WritePin(PWM_1_GPIO_Port, PWM_1_Pin,GPIO_PIN_SET);
									HAL_GPIO_WritePin(PWM_2_GPIO_Port, PWM_2_Pin,GPIO_PIN_SET);
									
								}	
					break;
					case STOP: //Disable Switch
									if (p->I_IN <= 0.1 && p->I_IN >= -0.1 )
								{
									HAL_TIM_Base_Stop_IT(&htim6);
									HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin,GPIO_PIN_RESET);
									HAL_GPIO_WritePin(PWM_1_GPIO_Port, PWM_1_Pin,GPIO_PIN_RESET);
									HAL_GPIO_WritePin(PWM_2_GPIO_Port, PWM_2_Pin,GPIO_PIN_RESET);
									InitParameter();
									
								}	  		
					break;
				}
  }
		
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /**Configure the main internal regulator output voltage 
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
  /**Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 16;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /**Initializes the CPU, AHB and APB busses clocks 
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */


void InitParameter(void)
{
  p->Cor_ADC1 =58;          				// Correction Number for ADC1
  p->Cor_ADC2 =10;          				// Correction Number for ADC2
  p->V_IN_Peak_MAX=0;       				// Reset Voltage Peak Detection
  p->Status_Switch=DISABLE; 				// Reset Status Switch
  p->Tick_TIM=0;           			    // Reset Tick Timer
  p->Fault=DISABLE;       				  // Reset Faults
  p->Start_conversion =DISABLE;   	// Reset Status Conversion
  p->V_IN_Limit = 300;      				// Max peak Voltage
  p->I_IN_Limit =20;	       				// Max peak Current
  
  if((HAL_GPIO_ReadPin(Mode_Selector_GPIO_Port,Mode_Selector_Pin)))
   {
     p->OPERATING_MODE = INDUCTIVE_MODE;
   }
  else
   {
     p->OPERATING_MODE = CAPACITIVE_MODE;
   }
}


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim->Instance == TIM6)
    {
     p->Start_conversion = ENABLE; //Start peack voltage detection
     if(p->Tick_TIM<=3)
       {
        p->Tick_TIM++;
       }
     if(p->Tick_TIM==2)
       {
          p->Status_Switch = START; //Enable Switch
       }
    }
 if (htim->Instance == TIM7)
    {
     HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); // LED Blink
     if(p->Status_Switch==START)
       {
        p->Status_Switch = STOP;} // -> State STOP
       }
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
  if((GPIO_Pin==B1_Pin) && (p->Status_Switch==START) )
		{		
			//STOP			
			p->Status_Switch = STOP;
		}
	else if((GPIO_Pin==B1_Pin) && (p->Status_Switch==IDLE) && p->Fault==DISABLE)
		{		
			//Start
			HAL_TIM_Base_Start_IT(&htim6);
			HAL_TIM_Base_Stop_IT(&htim7);
		}
  if(((HAL_GPIO_ReadPin(FAULT_N_GPIO_Port,FAULT_N_Pin))== RESET || (HAL_GPIO_ReadPin(UVLO_N_GPIO_Port,UVLO_N_Pin))== RESET ||(HAL_GPIO_ReadPin(FAULT_L_GPIO_Port,FAULT_L_Pin))== RESET || (HAL_GPIO_ReadPin(UVLO_L_GPIO_Port,UVLO_L_Pin))== RESET ) )
		{
      // Faults & Diable Switch
      p->Fault=ENABLE; 	
			HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(PWM_1_GPIO_Port, PWM_1_Pin,GPIO_PIN_RESET);
      HAL_GPIO_WritePin(PWM_2_GPIO_Port, PWM_2_Pin,GPIO_PIN_RESET);
      HAL_TIM_Base_Stop_IT(&htim6);
      HAL_TIM_Base_Start_IT(&htim7); //Active LED
			  
		}
}
/* USER CODE END 4 */

Credits

GIOVANNI MIGLIAZZA

GIOVANNI MIGLIAZZA

2 projects • 3 followers
I'm Mechatronic Engineering, PhD Student at the University of Modena and Reggio Emilia, Department of science and methods for engineering.

Comments