目录
三,接线图:(本例使用了三个ntc,分别读取三个温度,图中只画出一个)
一,硬件:
- Arduino UNO 开发板
- 50K NTC 热敏电阻(参数:R值是50k,B值是3950)
- 10K电阻
二,原理:
通过读取串联电阻电压值,计算出NTC的阻值,然后根据NTC热敏电阻阻值与温度之间的转换公式,计算出当前的温度。但实际读取的温度会存在干扰,温度波动很大,所以要用滤波器,让输出的温度平稳。
三,接线图:(本例使用了三个ntc,分别读取三个温度,图中只画出一个)
四,代码:
//NTC温度计,通过10k电阻串联,adruino 10bit 读取电压,通过欧姆定律计算NTC的阻值,再通过公式计算出温度,该程序有滤波,是输出的值更稳定。
//精度为 0.26°C 满足正常使用
//动态滤波算法
#include <Arduino.h>
#define Threshold_1 5 //阈值1用于一阶带参滤波器,AD大于此值时,计数值 增加
#define Threshold_2 10 //阈值2用于一阶带参滤波器,计数值 大于此值时,增大参数K,增强滤波跟随
//二阶卡尔曼滤波器对象
class KLM_filter
{
public:
int TR_NEW_DATA = 0; //新值
int TR_OLD_DATA = 85; //旧值
int NTC_yinjiao=A0; //定义NTC引脚
void temp_filter();
KLM_filter(int yinjiao);
private:
float K = 0.0; //滤波系数
uint8_t num_x = 0; //滤波计数器
boolean flag = 0; //数据增减趋势
int trsd_num0 = 0;
};
KLM_filter::KLM_filter(int yinjiao)
{
NTC_yinjiao=yinjiao;
TR_OLD_DATA=analogRead(NTC_yinjiao);
}
void KLM_filter::temp_filter()
{
TR_NEW_DATA = analogRead(NTC_yinjiao);
//判断变化方向是否一致 flag=1为一致,flag=0为不一致
if (TR_NEW_DATA >= TR_OLD_DATA)
{
TR_NEW_DATA = analogRead(NTC_yinjiao);
if (TR_NEW_DATA >= TR_OLD_DATA) flag = 1;
else flag = 0;
}
else if (TR_NEW_DATA < TR_OLD_DATA)
{
TR_NEW_DATA = analogRead(NTC_yinjiao);
if (TR_NEW_DATA < TR_OLD_DATA) flag = 1;
else flag = 0;
}
if (flag) //变化方向一致时执行
{
num_x++;
if (abs(TR_NEW_DATA - TR_OLD_DATA) > Threshold_1) //当变化大于Threshold_1的时候,进行计数器num快速增加,以达到快速增大K值,提高跟随性
{
num_x++;
}
if (num_x > Threshold_2) //计数阈值设置,当递增或递减速度达到一定速率时,增大K值
{
K = K + 0.1; //0.1为K的增长值,看实际需要修改
num_x = 0;
}
}
else
{
num_x = 0;
K = 0.05; //变化稳定时K值,看实际修改
}
TR_OLD_DATA = float((1 - K) * TR_OLD_DATA + K * TR_NEW_DATA);
}
KLM_filter ntc1KLM(A0);
KLM_filter ntc2KLM(A1);
KLM_filter ntc3KLM(A2);
//NTC 计算相关
const float balanceR[3] = { 9950, 10100, 10049 }; //参考电阻阻值,即与NTC串联的电阻,越精确越好
const float ADC_max = 1023.0;
/*使用beta方程计算阻值。*/
const float beta = 3950.0; //商家给出的电阻对应25°C下的bata值
const float roomTemp = 298.15; //以开尔文为单位的室温25°C
const float roomTempR = 50000.0; //NTC热敏电阻在室温25°C下具有典型的电阻
//传入ADC的值,返回温度
float readThermistor(int adc_value,int rb_index)
{
float rThermistor = 0; //保存热敏电阻的电阻值
float tKelvin = 0; //以开尔文温度保存温度
float tCelsius = 0; //以摄氏温度保存温度
switch(rb_index)
{
case 1:
rThermistor = balanceR[0] * ((ADC_max / adc_value) - 1);
break;
case 2:
rThermistor = balanceR[1] * ((ADC_max / adc_value) - 1);
break;
case 3:
rThermistor = balanceR[2] * ((ADC_max / adc_value) - 1);
break;
}
tKelvin = (beta * roomTemp) / (beta + (roomTemp * log(rThermistor / roomTempR)));
tCelsius = tKelvin - 273.15; //将开尔文转换为摄氏温度
return tCelsius;
}
void setup()
{
Serial.begin(115200);
}
void loop()
{
ntc1KLM.temp_filter();
ntc2KLM.temp_filter();
ntc3KLM.temp_filter();
Serial.print("a:");
Serial.print(readThermistor(ntc1KLM.TR_OLD_DATA,1));
Serial.print("; ");
Serial.print("b:");
Serial.print(readThermistor(ntc2KLM.TR_OLD_DATA,1));
Serial.print("; ");
Serial.print("C:");
Serial.print(readThermistor(ntc3KLM.TR_OLD_DATA,1));
Serial.println(";");
delay(100);
}
五,实际效果:
温度稳定,能迅速响应温度变化。精度为0.26°C.