Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
![]() |
| |||||
Hand tools and fabrication machines | ||||||
![]() |
|
One of the most important thing in the automation application is controlling heat, each factory has a system which is needed to control the temperature.
There is a special device to do this process depending on the PID controller algorithm but why we should buy those stuff whereas we can make it by myself.
STEPS:
1_ Make an equation for your NTC sensor to get the right reading for temperature.
(note: maybe you have to follow more than one equation because of nonlinear for NTC)
2_ Make your controller using the main equation PD:
3_ Create a suitable chamber for heating the required material, pay attention to isolate the cold part from the heat part.
4_ Finally put all components together then write the code with Keil uVision.
note: I added a sensor on the port 2 Tx(top) this pin is connected to ADC channel 2 instead of UART.
I talked a sample per second using timer3 that will trigger the ADC.
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
rawValues=HAL_ADC_GetValue(hadc);
c_temp=calc_ntc(rawValues);
error_t=d_temp-c_temp;
pwm_ntc=pd_ntc(error_t);
Relay_PWM(pwm_ntc);
//IND_toggle();
}
_USE Voltage divider to read thermistor NTC between 0 to 3V3.
main.c
C/C++/**
******************************************************************************
* File Name : main.c
* Description : Main program body
******************************************************************************
*
* COPYRIGHT(c) 2015 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.
*
******************************************************************************
*/
/*
MODIFIED by Hexabitz for BitzOS (BOS) V0.2.3 - Copyright (C) 2017-2020 Hexabitz
All rights reserved
*/
/* Includes ------------------------------------------------------------------*/
#include "BOS.h"
/* Private variables ---------------------------------------------------------*/
uint32_t rawValues;
float c_temp,error_t;
float d_temp=40;
uint8_t pwm_ntc;
//uint32_t fr=1000;
uint8_t pwm_ntc1=50;
uint8_t out;
/* Private function prototypes -----------------------------------------------*/
void MX_ADC_Init(void);
void MX_TIM1_Init(void);
void Error_Handler(void);
ADC_HandleTypeDef hadc;
TIM_HandleTypeDef htim1;
float calc_ntc(int x);
uint8_t pd_ntc(float e);
/* Main functions ------------------------------------------------------------*/
int main(void)
{
/* MCU Configuration----------------------------------------------------------*/
/* Reset all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all user peripherals */
/* Initialize BitzOS */
BOS_Init();
MX_ADC_Init();
MX_TIM1_Init();
/* Call init function for freertos objects (in freertos.c) */
MX_FREERTOS_Init();
/* Start scheduler */
osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
while (1)
{
}
}
/*-----------------------------------------------------------*/
/* User Task */
void UserTask(void * argument)
{
HAL_TIM_Base_Start(&htim1);
HAL_ADC_Start_IT(&hadc);
/* Infinite loop */
for(;;)
{
}
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
rawValues=HAL_ADC_GetValue(hadc);
c_temp=calc_ntc(rawValues);
error_t=d_temp-c_temp;
pwm_ntc=pd_ntc(error_t);
Relay_PWM(pwm_ntc);
//IND_toggle();
}
float calc_ntc(int x)
{
float rout=20000,vin=3.3,a=13,b=-1762,c=0,creal;
float dec,vout,rth,del,cc;
dec=(float) x;
vout=dec*(3.3/4095);
rth=rout*((vin/vout)-1);
if(dec<2100) c=57000;
else if(dec>2100 && dec<3000) c=59128;
else if(dec>3000) { c=60000; }
else c=59128;
cc=c-rth;
del=(b*b)-4*a*cc;
//if(del<0) {del=-del; }
creal=(-b-sqrt(del))/(2*a);
if(dec>3500)
creal=creal+7;
return creal;
}
uint8_t pd_ntc(float e)
{
float e_1=0,del_e;
float p=500,d=10;
del_e=e-e_1;
if(e>0 && del_e<0)
out=e*p+del_e*d;
else if(e<0)
out=0;
else
out=e*p;
e_1=e;
if(out<1) out=0;
else if(out>100) out=100;
return out;
}
/*-----------------------------------------------------------*/
/************************ (C) COPYRIGHT HEXABITZ *****END OF FILE****/
/* ADC init function */
void MX_ADC_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
/** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
*/
hadc.Instance = ADC1;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
hadc.Init.ContinuousConvMode = DISABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_TRGO;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel to be converted.
*/
sConfig.Channel = ADC_CHANNEL_2;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
sConfig.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* adcHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
/* ADC1 clock enable */
__HAL_RCC_ADC1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**ADC GPIO Configuration
PA0 ------> ADC_IN0
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* ADC1 interrupt Init */
HAL_NVIC_SetPriority(ADC1_COMP_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(ADC1_COMP_IRQn);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
}
void HAL_ADC_MspDeInit(ADC_HandleTypeDef* adcHandle)
{
if(adcHandle->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspDeInit 0 */
/* USER CODE END ADC1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ADC1_CLK_DISABLE();
/**ADC GPIO Configuration
PA0 ------> ADC_IN0
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_0);
/* ADC1 interrupt Deinit */
HAL_NVIC_DisableIRQ(ADC1_COMP_IRQn);
/* USER CODE BEGIN ADC1_MspDeInit 1 */
/* USER CODE END ADC1_MspDeInit 1 */
}
}
//////////////////////
/* TIM1 init function */
void MX_TIM1_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 24000-1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 2000-1;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
//htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM1_MspInit 0 */
/* TIM1 clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
/* TIM1 interrupt Init */
HAL_NVIC_SetPriority(TIM1_CC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
/* USER CODE BEGIN TIM1_MspInit 1 */
/* USER CODE END TIM1_MspInit 1 */
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspDeInit 0 */
/* USER CODE END TIM1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM1_CLK_DISABLE();
/* TIM1 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM1_CC_IRQn);
/* USER CODE BEGIN TIM1_MspDeInit 1 */
/* USER CODE END TIM1_MspDeInit 1 */
}
}
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
/* USER CODE END Error_Handler_Debug */
}
Comments
Please log in or sign up to comment.