PROGCONT.RU

Форма входа







Регистрпция Вход/

STM8S ADC и TM1638 создание терморегулятора с использованием термистора NTC-MF52AT.

Ссылка на видео в YouTube Не отходя далеко от темы ADC в контроллерах STM8S решил создать что то нужное в быту( контроллер температуры) да и изучить как работают датчики температуры термисторы NTC-MF52AT, работают они просто с увеличением температуры уменьшают свое сопротивление соответственно уменьшая температуру уменьшают сопротивление.
 Вроде нет нечего сложно в работе NTC-MF52AT но когда с ними столкнешься то придется поискать подходящий datasheet которого нет, понять что в нем к чему, вспомнить математику и покопаться во внутренних библиотеках IAR, я для вас попробую создать более короткий путь в изучении этой темы чем был у меня.
нет рисунка  О датчике, заказывал на aliexpress готовый вместе с проводом и в металлической колбе вот такой как справа, все что я о нем знаю NTC термистор точность Температура Сенсор 10К 1% 3950 повторюсь datasheet я на него не смог найти но в принципе и этой информации достаточно. И что же означают эти данные которые дал китайский продавец первое что это термистор, второе 10К его сопротивление при 25 градусах, третье погрешность 1% и последний очень важный параметр 3950 это коэффициент который определяет зависимость сопротивления от температуры при определенных температурах.
 С начало я думал вычислять температуру полученную с датчика будет просто как напряжение но не тут то было для этого нужна специальная формула выглядит вот так
   T1 = 1 / ((ln(R1) – ln(R2)) / B + 1 / T2)
описание параметров:
T1-искомая температура в Кельвин.
R1-сопротивления термистора при измеряемой температуры.
R2-сопротивления термистора при 25 градусах, в нашем случае 10000 Ом.
B-константа для вычислений зависит от модели термистора у нас 3950.
T2-температура 25 градусов в Кельвин будет 25+273.15=298.15 .
ln-натуральный логарифм кто не знает изучаем математику.

 Ещё две формулы для вычисления коэффициента B и обратного нахождения сопротивления от температуры. B коэффициент рассчитывается на основе значений сопротивления при двух конкретных значениях температур обычно 25°С и 100°С и указываются в datasheet например B25/100, измеряется в Кельвин и вычисляется по следующей формуле
   B = (ln(R1) – ln(R2)) / (1 / T1 - 1 / T2) .
 Формула нахождение сопротивления
R1 = R2 * e^(B * (1 / T1 - 1 / T2))
e^-экспонента( число Эйлера ≈2,718) в степени.


 После нахождения нужной формулы и её изучения пришлось копаться в библиотеках компилятора IAR искать функцию вычисляющую натуральный логарифм, что как вы поняли закончилось успехом, иначе пришлось создавать большую таблицу температур и сопротивлений.


 Схема и рабочий проект контроллера температуры.

 Прибор будет работать на контроллере STM8S903K3 управлять будем с помощью модуля индикатора на микросхеме TM1638, диапазон температур минимум ноль градусов максимум 100.
 

нет рисунка


 Из особенности схемы, у меня питание контроллера идет через фильтр это индуктивность 200uH и два конденсатора 10uF электролит, 1uF керамический также питание индикатора идет через похожий фильтр но индуктивность намного больше 3mH, если этого не сделать то индикатор будет наводить большие помехи на ADC что приведет к неточным данным преобразования в виде быстрых изменений показаний в разных направлениях.


 Работает это устройство следующим образом первые три цифры это будет устанавливаемая температура изменяется первыми двумя кнопками, если она будет меньше реальной последние три цифры то на выводе контроллера GPIOD, GPIO_PIN_1 будет высокий уровень( включен нагреватель) иначе низкий.
 Ну и код самой программы которую можете сами усовершенствовать дополнительными функциями.
 

#include "stm8s.h"
//Внутренняя функция IAR так мы добавляем её в проект.
float log1pf(float x);
//Функции для работы с дисплеем.
void send_command(uint8_t com);
void send_data(uint8_t *send_data_display);
void display_data(uint32_t multiplier);
uint8_t scan_button(void);
uint8_t result_button;
void pause(uint32_t p);
//Параметры и переменные для вычисления температуры.
float Om_float;//Переменная для вычисления сопротивления термистора.
float B_formula=3950;//Коэффициент для формулы.
float R_formula=10000;//Сопротивление в омах при 25 градусах.
float T_formula=298.15;//25 градусов в Кельвин.
float Temp_formula;
float Temp_adjustment=-3;//Корректировка температуры 1=0.1 градуса может быть отрицательным.
float Resultat_ADC;
uint32_t Temp_disp;
float Temp_thermistor_On_Off=0;//Переменные для вычисления сопротивления термистора.
uint8_t send_data_display[16];//Массив для отправки данных.
uint8_t symbol[10]={63,6,91,79,102,109,125,7,127,111};//Массив наших символы для индикации 1,2,3 и так далее.
int main( void ){
CLK_HSIPrescalerConfig( CLK_PRESCALER_HSIDIV1);
//Настраиваем порты для SPI.
GPIO_Init(GPIOC, GPIO_PIN_5, GPIO_MODE_OUT_OD_HIZ_FAST);
GPIO_Init(GPIOC, GPIO_PIN_4, GPIO_MODE_OUT_OD_HIZ_FAST);
SPI_Init( SPI_FIRSTBIT_LSB, SPI_BAUDRATEPRESCALER_16, SPI_MODE_MASTER, SPI_CLOCKPOLARITY_LOW, SPI_CLOCKPHASE_1EDGE, SPI_DATADIRECTION_1LINE_TX, SPI_NSS_SOFT, 0x07);
SPI_Cmd(ENABLE);
//Вывод для включение и выключения нагревателя.
GPIO_Init( GPIOD, GPIO_PIN_1, GPIO_MODE_OUT_PP_LOW_SLOW); //Настройка ADC и его вывода.
GPIO_Init( GPIOB, GPIO_PIN_3, GPIO_MODE_IN_FL_NO_IT);
ADC1_Init( ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_3, ADC1_PRESSEL_FCPU_D18, ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_CHANNEL3, DISABLE);
ADC1_DataBufferCmd( ENABLE);

while(1){
send_command( 138);
send_command( 64);
//Выводим информацию на индикатор.
display_data( Temp_disp+(uint32_t)(Temp_thermistor_On_Off*10)*100000);
pause( 8000);
result_button= scan_button();
pause( 100);
if( result_button!=scan_button()){result_button=0;}
if(result_button!=0){
if(result_button==1){if( Temp_thermistor_On_Off<50){ Temp_thermistor_On_Off+=0.1;};}
if(result_button==2){if( Temp_thermistor_On_Off>0){ Temp_thermistor_On_Off-=0.1;};}
if(result_button==4){}
if(result_button==8){}
if(result_button==16){}
if(result_button==32){}
if(result_button==64){}
if(result_button==128){}
}
//Запуск преобразования ADC.
pause( 10000);
ADC1_ClearFlag( ADC1_FLAG_EOC);
ADC1_ConversionConfig( ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_3, ADC1_ALIGN_RIGHT);
ADC1_StartConversion();
while( !ADC1_GetFlagStatus( ADC1_FLAG_EOC));
ADC1_Cmd( DISABLE);
//Вычисляем средний результат из 10 преобразований который находится в буфере ADC.
Resultat_ADC=0;
for( uint8_t i=0; i<10; i++){ Resultat_ADC+= ADC1_GetBufferValue( i);}
Resultat_ADC/=10;
//Вычисление сопротивление датчика.
Om_float= Resultat_ADC/((1024-Resultat_ADC)/10000);
//Вычисляем по формуле T1 = 1 / ((ln(R1) – ln(R2)) / B + 1 / T2) температуру.
Temp_formula=(1/( (log1pf( Om_float) - log1pf( R_formula))/B_formula+1/ T_formula));
//Конвертируем Кельвин в градусы и отнимаем поправку температуры.
Temp_disp=(uint32_t)((Temp_formula-273.15)*10+Temp_adjustment);
//Включаем или выключаем нагрев.
if( (uint32_t)(Temp_thermistor_On_Off*10)>Temp_disp){ GPIO_WriteHigh( GPIOD, GPIO_PIN_1);}else{ GPIO_WriteLow( GPIOD, GPIO_PIN_1);}
}
}

//Функция для отправки команды.
void send_command(uint8_t com){
GPIO_WriteLow(GPIOC, GPIO_PIN_4);
SPI_SendData(com);
while( (SPI->SR & SPI_FLAG_BSY) );
GPIO_WriteHigh(GPIOC, GPIO_PIN_4);
}
//Функция для опроса кнопок.
uint8_t scan_button(void){
uint8_t scan_result;
GPIO_WriteLow(GPIOC, GPIO_PIN_4);
SPI_SendData(66);
while( (SPI->SR & SPI_FLAG_BSY) );
SPI_BiDirectionalLineConfig(SPI_DIRECTION_RX);
while( !(SPI->SR & SPI_FLAG_RXNE) );
scan_result=SPI->DR;
while( !(SPI->SR & SPI_FLAG_RXNE) );
scan_result|=(SPI->DR<<1);
while( !(SPI->SR & SPI_FLAG_RXNE) );
scan_result|=(SPI->DR<<2);
while( !(SPI->SR & SPI_FLAG_RXNE) );
scan_result|=(SPI->DR<<3);
GPIO_WriteHigh(GPIOC, GPIO_PIN_4);
SPI_BiDirectionalLineConfig(SPI_DIRECTION_TX);
return scan_result;
}
//Функция для отправки данных.
void send_data(uint8_t *send_data_display){
GPIO_WriteLow(GPIOC, GPIO_PIN_4);
SPI_SendData(192);
while( (SPI->SR & SPI_FLAG_BSY) );
for( uint8_t i=0;i<16;i++){
SPI_SendData(send_data_display[i]);
while( !(SPI->SR & SPI_FLAG_TXE) );
}
while( (SPI->SR & SPI_FLAG_BSY) );
GPIO_WriteHigh(GPIOC, GPIO_PIN_4);
}
//Вычисляем значения и заполняем ими массив для отправки в модуль для отображения.
void display_data(uint32_t multiplier){
send_data_display[0]= symbol[multiplier/10000000];
multiplier= multiplier-(multiplier/10000000*10000000);
send_data_display[2]= symbol[multiplier/1000000]|128;
multiplier=multiplier-(multiplier/1000000*1000000);
send_data_display[4]= symbol[multiplier/100000];
multiplier= multiplier-(multiplier/100000*100000);
//send_data_display[6]= symbol[multiplier/10000];
multiplier= multiplier-(multiplier/10000*10000);
//send_data_display[8]= symbol[multiplier/1000];
multiplier= multiplier-(multiplier/1000*1000);
send_data_display[10]= symbol[multiplier/100];
multiplier= (multiplier-multiplier/100*100);
send_data_display[12]= symbol[multiplier/10]|128;
multiplier= multiplier-(multiplier/10*10);
send_data_display[14]= symbol[multiplier];
send_data(send_data_display);
}
void pause(uint32_t p){
for(uint32_t i=0; i<p; i++){}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{ while (1){}
}
#endif

Комментарии  Только зарегистрированные пользователи могут оставлять комментарии!

NOserg   2019-10-31 20:14:26
где то на просторах инета попалась вот такая формула, пользуюсь несколько лет float voltage = 0.0; float r1 = 0.0; float temperature = 0.0; float ptemperature = 0.0; voltage = adc_result * 5 / 1024.0; r1 = voltage / (5 - voltage); temperature = 1./( 1./3950*log(r1)+1./(25. + 273.) ) - 273; /* adc_result - получаем из ADC. делитель +5В--10Ком--MF52--GND | | ------- ADC_mcu */

NOteseiaaw   2019-10-31 22:09:32
Спасибо, попробуем.