1.材料清单

STM32F103C8T6开发板(黑色板)、NTC热敏电阻、12864OLED显示屏(四脚)、microUSB数据线、导线及面包板

2.电路连接

NTC热敏电阻连接电路:GND->10k电阻->PB1->NTC热敏电阻->3.3V
OLED显示屏连接电路:
 * GND->GND
 * VCC->3.3V
 * SCL->PB6
 * SDA->PB7

STM32配置Arduino环境:https://blog.csdn.net/weixin_42101470/article/details/103411081

3.NTC热敏电阻测温

连接好电路后,先来读取热敏电阻的阻值,并发送到串口。

以上是NTC热敏电阻的接口电路,其中输出电压V_out连接PB1,VCC=3.3V。每次热敏电阻检测到温度变化时,输出电压都会随之变化。通常,我们使用分压器,其公式如下:

V_out = VCC ⋅[R_平衡 / (R_NTC + R_平衡)]

但是,我们不希望V_out作为答案,我们想要热敏电阻的阻值R_NTC。对上式整理得:

R_NTC = R_平衡 ⋅ (VCC / V_out - 1)

从上式可以看出我们需要测量电压输出和电源电压,这就是ADC的用武之地。ADC可以将电压表示为一定范围内的数字,所以上式最终结果如下:

R_NTC = R_平衡 ⋅(D_max / D_测量 - 1)

这在数学上是成功的,因为无论我们如何表示电压(以伏特或数字为单位),这些单位抵消了分数中的分子和分母,留下无量纲数。在那之后,乘以一个阻值,以欧姆为单位得出答案。

在STM32F103C8T6中ADC的范围是0~4095,所以D_max=4095,D_测量为PB1引脚读取到的值,R_平衡可通过万用表精准测得,由此我们便可以求得R_NTC的值。那么,R_NTC与温度的关系是怎样的呢?

幸运的是我们可以查得NTC热敏电阻的拟合曲线方程如下:

其中,R0为T0温度(单位:K)下的阻值,beta为常数,三个变量均由厂家给出。

所以如果已知热敏电阻阻值,我们便可以通过上式求得对应的温度。

Let's get started!

/* ===热敏电阻演示代码===为了消除噪声读数,采样ADC几次,然后平均样本以获得更稳定的测量值,用readThermistor函数实现。http://www.thermistors.cn/news/293.html
*/
const int sampleNumber = 10; //采样次数
const double balanceR = 9700.0; //参考电阻阻值,越精确越好
const double ADC_max = 4095.0;
/*使用beta方程计算阻值。*/
const double beta = 3950.0; //商家给出的电阻对应25°C下的bata值
const double roomTemp = 298.15; //以开尔文为单位的室温25°C
const double roomTempR = 10000.0; //NTC热敏电阻在室温25°C下具有典型的电阻
double currentTemperature = 0; //保存当前温度const int thermistorPin = PB1; // ADC采样电阻分压器的输出引脚void setup(){//设置串口窗口消息的端口速度Serial.begin(9600);
}
void loop(){ currentTemperature = readThermistor();
//  Serial.print("当前温度:"); Serial.println(currentTemperature);
//  Serial.println("°C");delay(3000);
} /* 函数功能:读取模拟引脚,如下所示。通过模数转换将电压信号转换为数字表示。但是,这样做了多次,因此我们可以对其进行平均以消除测量误差。然后使用该平均数来计算热敏电阻的电阻。此后,电阻用于计算热敏电阻的温度。最后,温度转换为摄氏度。有关此过程的详细信息和一般理论,请参阅allaboutcircuits.com文章。原理图:(地面)----====-------  | ---------====--------3.3V R_balance      |      R_thermistor | ADC引脚
*/ double readThermistor(){double rThermistor = 0; //保存热敏电阻的电阻值double tKelvin = 0; //以开尔文温度保存温度double tCelsius = 0; //以摄氏温度保存温度double adcAverage = 0; //保存平均电压测量值double adcSamplesi = 0 ;//保存当前采样值for(int i = 0; i<sampleNumber; i ++){ adcSamplesi = analogRead(thermistorPin); //从引脚和存储
//     Serial.println(adcSamplesi);delay(10); //等待10毫秒adcAverage += adcSamplesi; //添加所有样本}adcAverage /= sampleNumber; //平均值w= sum/sampleNumber
//  Serial.println(adcAverage);/*公式计算热敏电阻的电阻。*/ rThermistor = balanceR *((ADC_max / adcAverage) -  1); tKelvin =(beta * roomTemp)/ (beta +(roomTemp * log(rThermistor / roomTempR)));  tCelsius = tKelvin  -  273.15; //将开尔文转换为摄氏温度return tCelsius;//以摄氏度返回温度
}

串口输出效果:

由于ADC的偶然误差,每次测得的数值会有变化,将测得结果绘制图像如下:

故采用均值滤波来平滑所测的结果,由readThermistor中for循环实现。

MATLAB均值滤波代码

clear;clc;
load('tempData.mat');
n=length(data);
sum = 0;
% res = zeros(n,1);
x=1:n-100;
for i =1:n-100for j=1:100sum = sum+data(i+j);endres(i,1)=sum/100;sum=0;
end
figure(1);
clf
plot(x, data(1:n-100), '.-b', x, res, '-.r','linewidth',3);
set(gca,'FontSize',12); set(gcf,'Color','White');
xlabel('时间'); ylabel('温度(℃)');
legend('滤波前', '滤波后');

滤波前后对比图如下,可见均值滤波可以很好的去除噪点,能够提高OLED显示的稳定性!

4.OLED显示温度

温度℃的显示用zimoV2.2软件取模,软件下载网盘链接:

链接:https://pan.baidu.com/s/1G7McxB00iCCCeBg9yUUg5w
提取码:qg3d

这里还需要下载Adafruit GFX和Adafruit SSD1306两个库。

Arduino IDE操作方法:项目>>加载库>>管理库...,查找安装

加上OLED显示屏的完整程序:

/*NTC OLED显示屏制作温度计* NTC热敏电阻连接:GND->10k电阻->PB1->NTC热敏电阻->3.3V* OLED屏连接:* GND->GND* VCC->3.3V* SCL->PB6* SDA->PB7
*/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306_STM32.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);const int sampleNumber = 100; //采样次数,const对象放在只读内存中
const double balanceR = 9982.0; //参考电阻阻值,越精确越好
const double ADC_max = 4095.0;
/*使用beta方程计算阻值。*/
const double beta = 3950.0; //商家给出的电阻对应25°C下的bata值
const double roomTemp = 298.15; //以开尔文为单位的室温25°C
const double roomTempR = 10000.0; //NTC热敏电阻在室温25°C下具有典型的电阻
double currentTemperature = 0; //保存当前温度const int thermistorPin = PB1; // ADC采样电阻分压器的输出引脚//*--文字: ℃--*/
static const unsigned char PROGMEM strC[] =
{/*--  宽度x高度=40x35  --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x07,0xC0,0x0C,0x00,0x00,0x0F,0xC0,0xFF,0xC0,0x00,0x1C,0xE3,
0xFF,0xE4,0x00,0x1C,0xE7,0xC0,0x7E,0x00,0x1C,0xE7,0x00,0x3E,0x00,0x0F,0xCF,0x00,
0x1E,0x00,0x07,0x9E,0x00,0x0E,0x00,0x00,0x1E,0x00,0x0E,0x00,0x00,0x3C,0x00,0x0E,
0x00,0x00,0x3C,0x00,0x0E,0x00,0x00,0x3C,0x00,0x04,0x00,0x00,0x3C,0x00,0x00,0x00,
0x00,0x3C,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,
0x3C,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x00,0x1C,
0x00,0x00,0x00,0x00,0x1E,0x00,0x06,0x00,0x00,0x1E,0x00,0x0C,0x00,0x00,0x0F,0x00,
0x1C,0x00,0x00,0x07,0x80,0x78,0x00,0x00,0x07,0xE1,0xF0,0x00,0x00,0x01,0xFF,0xE0,
0x00,0x00,0x00,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endifvoid setup()
{Serial.begin(9600);display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3D (for the 128x64)display.display();delay(1000);display.begin(SSD1306_SWITCHCAPVCC, 0x3C);display.display();// init donedelay(1000);
}
void loop()
{//*-- 以下开始显示内容 --*///清理1306屏幕,准备显示:display.clearDisplay();// temp&Duty 显示://display.setTextSize(3);               //设置字体大小display.setTextColor(WHITE);          //设置字体颜色白色//中文字符显示display.setCursor(2,25);            //设置字体的起始位置currentTemperature = readThermistor();display.println(currentTemperature);                  //输出字符display.drawBitmap(98,18, strC, 40, 35, 1);    //℃,宽*高点阵display.display();                   //把缓存都显示
}double readThermistor(){double rThermistor = 0; //保存热敏电阻的电阻值double tKelvin = 0; //以开尔文温度保存温度double tCelsius = 0; //以摄氏温度保存温度double adcAverage = 0; //保存平均电压测量值double adcSamplesi = 0 ;//保存当前采样值for(int i = 0; i<sampleNumber; i ++){ adcSamplesi = analogRead(thermistorPin); //从引脚和存储
//     Serial.println(adcSamplesi);delay(10); //等待10毫秒adcAverage += adcSamplesi; //添加所有样本}adcAverage /= sampleNumber; //平均值w= sum/sampleNumber
//  Serial.println(ADC_max / adcAverage -  1);/*公式计算热敏电阻的电阻。*/ rThermistor = balanceR *((ADC_max / adcAverage) -  1); tKelvin =(beta * roomTemp)/ (beta +(roomTemp * log(rThermistor / roomTempR)));  tCelsius = tKelvin  -  273.15; //将开尔文转换为摄氏温度return tCelsius;//以摄氏度返回温度
}

5.实现效果

6.误差分析

由于beta值、R0、T0、ADC测量值、R_平衡均会有测量误差 ,所以需要对参数进行校准。又因为R_平衡为个人测量结果,测量误差较大,对结果影响最大。这里笔者采用体温计对体温测量,得到较精确的体温36.8℃,再用STM32得到此时的R_NTC值,通过上面的公式反推出R_平衡。

参考链接

http://www.thermistors.cn/news/293.html

Arduino STM32用NTC热敏电阻 OLED显示屏制作温度计相关推荐

  1. STM32 ADC NTC热敏电阻二分(折半)查表法实现测温功能

    本文主要描述 - STM32 ADC NTC热敏电阻二分(折半)查表法测温功能的思路和代码实现 NTC的相关属性:R25=10K±3% B25/50=4100K±3% 10K上拉 STM32 ADC实 ...

  2. 四针角oled屏连接arduino_使用Arduino开发板连接OLED显示屏制作一款智能手表

    我们大多数人都比较熟悉1602点阵液晶显示屏,它在许多项目中用于向用户显示一些信息.但是这些LCD显示器在他们能做的事情上有很多限制.在本篇文章中,我们将使用OLED显示Android智能手机的一些基 ...

  3. esp8266加0.91寸oled显示屏制作天气时钟

    前言 上两周做了个客制化键盘,将esp8266改在键盘里面了显示始终天气等信息,演示视频看我B站视频:200块改的键盘,没错,你是来听歌的,五分钟剪的视频. 键盘制作教程在最后的参考资料里,自行查看. ...

  4. Arduino与Proteus仿真实例-OLED显示屏(SSD1306)I2C驱动仿真

    OLED显示屏(SSD1306)I2C驱动仿真 首字母缩写词"OLED"代表有机发光二极管 - 一种使用 LED 的技术,其中的光由有机分子产生. 这些有机 LED 用于制造被认为 ...

  5. [记录]小破站一键三连动画基于STM32 cubemx hal库函数OLED显示屏

    开学前和朋友整了个活,帧数比较低哈哈 目的: 熟练掌握OLED的使用方法 材料 1.STM32最小系统板一块(我的是F103VET6) 2.0.96寸OLED屏幕一块 3.SWD程序下载模块(我用的是 ...

  6. GC0053-STM32单片机NTC热敏电阻温度采集及控制LCD1602

    实践制作DIY- GC0053-NTC热敏电阻温度采集 一.功能说明: 基于STM32单片机设计-NTC热敏电阻温度采集 二.功能介绍: STM32单片机+LCD1602显示器+NTC热敏电阻温度传感 ...

  7. android蓝牙通信_使用Arduino构建OLED显示屏与Android手机接口的智能手表

    背景知识视频教程 Arduino 训练营:通过项目学习​viadean.com 通过制作Arduino UNO FM收音机接收器学习Arduino I2C​viadean.com 通过构建实际应用程序 ...

  8. android 环形时间显示_使用Arduino构建OLED显示屏与Android手机接口的智能手表

    背景知识视频教程 Arduino 训练营:通过项目学习​viadean.com 通过制作Arduino UNO FM收音机接收器学习Arduino I2C​viadean.com 通过构建实际应用程序 ...

  9. # **Arduino开发NTC热敏电阻实验**

    Arduino开发NTC热敏电阻实验 哈喽, 大家好呀我是一名初次学习Arduino的一名初学者,很高兴跟大家分享这次的学习经验,秉承着互相学习,互相进步的原则,我将这次项目的经验分享给大家. 1.这 ...

最新文章

  1. 脚本调用后台代码 asp.net ajax
  2. SpringMVC响应Restful风格请求404
  3. pycharm使用_后端开发使用pycharm的技巧
  4. Emlog博客MetBlogm主题-博客开源主题源码
  5. 微软05年面临的10大挑战
  6. SQL语句中的rank () over , row_number() over ,rank_dense ()
  7. 2020年最新 java JDK 11 下载、安装与环境变量配置教程
  8. python调用手机蓝牙_python bluetooth蓝牙信息获取蓝牙设备类型的方法
  9. python优化网站_小旋风网站优化 - 致力于Python高品质站群系统的产品研发
  10. 给你的服务器建立动态域名服务
  11. Python的Excel/Word库
  12. Floodlight模块分析:forwarding模块
  13. 输入两个正整数m和n,输出m到n之间每个整数的自然对数
  14. 对称加密算法、非对称加密算法、散列函数与数字签名的介绍
  15. OPENCV实现色带检测
  16. 视频剪辑教程,视频加图片,图片加视频,教你制作画中画特效
  17. 【AD小知识】PCB快速开窗的方法
  18. java获取emf中的文字_一键提取图片中的文字的5种方法!
  19. 卡方分布和卡方验证的关系理解,以及Python实现
  20. 建筑施工管理得心应手:智慧工地推动数字城市智能化前进

热门文章

  1. 计算机前沿技术云论文,计算机前沿技术论文.doc
  2. chrome android 85,终于!安卓版Chrome 85将升级到原生64位:支持Android 10及以上系统...
  3. 四级英语测试软件,英语四级学习软件都有哪些好用啊
  4. 弘辽科技:淘宝宝贝访问量低该如何解决?影响访问量低的原因有?
  5. XML-DTD解析(转载的)
  6. 交换机的116个知识点 (1)
  7. PCA Whitening ZCA Whitening
  8. 机器学期第一学期小结
  9. html 鼠标经过出现文字,CSS实现鼠标滑过文字弹出一段说明文字无JS代码
  10. 基于JAVAWEB技术的网上珠宝系统的设计与实现