本文用ESP32来制作一个简单的温控器,功能包括:可以检测并显示当前温度,可以设置最高温度和最低温度,设置升(如电热炉,电水壶)降(如冷水机,冰箱)温功能,可以显示当前设置的最高温度和最低温度。
电路连接图
所需硬件
ESP32 * 1
NTC-3950-10K热敏电阻 * 1
轻触开关 * 3
SSD1306-分辨率128*64-OLED屏 * 1
所需要的库
Ticker-esp32(该库ESP32默认已安装,如果自行下载需要改动部份代码)
下载:https://github.com/bertmelis/Ticker-esp32
OneButton by Matthias Hertel
下载:https://github.com/mathertel/OneButton
NTC_Thermistor by Mr. Alex
下载:https://github.com/YuriiSalimov/NTC_Thermistor
esp8266 and ESP32 OLED driver for SSD1306 displays by ThingPulse
下载:https://github.com/ThingPulse/esp8266-oled-ssd1306
程序文件
本例程开机后读取EEPROM中的最大和最小温度设置,后每60秒检测一次温度来设置2号引脚的高低电平状态
esp32_temp_control.ino
#include <Ticker.h>
Ticker readTempTimer; //更新温度定时
Ticker controlSwitchTimer; //检测温度并决定开关机状态定时
float temperature; //温度
int maxTemp = 6; //最高温度
int minTemp = 2; //最低温度
bool temperatureDescendState=0; //0为降温状态,1为升温状态,
int setState = 0; //设置状态
int pin = 02; //开关引脚
void setup() {
pinMode(pin, OUTPUT); // 将引脚设置为输出模式
Serial.begin(115200);
beginSSD();
buttonSetup();
//EEPROMsetup();
readTempSetData(); //读取EEPROM中的最大温度和最小温度
readTempTimer.attach(5, showSSD); //每5秒更新一次温度显示
controlSwitchTimer.attach(5,ContolSwitch); //每60秒检测一次温度来判定是否开机
}
void loop() {
buttonLoop();
}
ControlSwitch.ino
void ContolSwitch(){
if(temperatureDescendState){ //如果为降温状态
if(temperature>maxTemp){ //如果当前温度大于设置的最大温度
if(digitalRead(pin)!=HIGH){
digitalWrite(pin, HIGH); // 设置引脚状态为高(开机)
Serial.println("开机");
}
}else if(temperature<minTemp){ //如果当前温度小于设置的最小温度
if(digitalRead(pin)!=LOW){
digitalWrite(pin, LOW); // 设置引脚状态为低
Serial.println("关机");
}
}
}else{ //如果为升温状态
if(temperature<maxTemp){ //如果当前温度小于设置的最大温度
if(digitalRead(pin)!=HIGH){
digitalWrite(pin, HIGH); // 设置引脚状态为高(开机)
Serial.println("开机");
}
}else if(temperature>minTemp){ //如果当前温度大于设置的最小温度
if(digitalRead(pin)!=LOW){
digitalWrite(pin, LOW); // 设置引脚状态为低
Serial.println("关机");
}
}
}
}
bnt.ino
#include <OneButton.h>
OneButton buttonSet(04,true); //16号引脚低电平触发
OneButton buttonUp(16,true);
OneButton buttonDown(17,true);
//设置按键按下时的回调函数
void setClick() {
Serial.println("设置键按下");
if(setState<3){
setState = setState + 1;
}else{
setState = 0 ;
}
showSSD();
writeTempSetData(); //把最大温度和最小温度设置保存到EEPROM
}
//上按键按下时的回调函数
void upClick(){
if(setState==1){
maxTemp = maxTemp + 1; //最大温度+1
}else if(setState==2){
minTemp = minTemp + 1; //最小温度+1
if(minTemp>=maxTemp){ //如果最小温度大于最大温度
maxTemp = minTemp + 1; //最大温度等于最小温度+1
}
}else if(setState==3){
temperatureDescendState = !temperatureDescendState;
}
showSSD();
}
//下按键按下时的回调函数
void downClick(){
if(setState==1){
maxTemp = maxTemp - 1;
if(maxTemp<=minTemp){
minTemp = maxTemp -1;
}
}else if(setState==2){
minTemp = minTemp - 1;
}else if(setState==3){
temperatureDescendState = !temperatureDescendState;
}
showSSD();
}
void buttonSetup(){
buttonSet.attachClick(setClick); //初始化当设置按键按下时调用setClick函数
buttonUp.attachClick(upClick);
buttonDown.attachClick(downClick);
}
void buttonLoop(){
buttonSet.tick();
buttonUp.tick();
buttonDown.tick();
}
get_temp.ino
#include <Thermistor.h>
#include <NTC_Thermistor.h>
#define SENSOR_PIN 33
#define REFERENCE_RESISTANCE 10000
#define NOMINAL_RESISTANCE 10000
#define NOMINAL_TEMPERATURE 25
#define B_VALUE 3950
Thermistor* thermistor;
float readNTCTemperature() {
thermistor = new NTC_Thermistor(
SENSOR_PIN,
REFERENCE_RESISTANCE,
NOMINAL_RESISTANCE,
NOMINAL_TEMPERATURE,
B_VALUE,
4095
);
double celsius = 0;
for(int i = 0; i <20; i ++){
celsius = celsius + thermistor->readCelsius();
}
celsius = celsius / 20;
return celsius;
}
String getTemp(){
temperature = readNTCTemperature(); //获取当前温度
Serial.println(temperature);
String temp;
temp = Convert(temperature);
temp = "TEMP:" + temp;
return temp;
}
saveData.ino
#include <EEPROM.h>
void EEPROMsetup(){
EEPROM.begin(200);
}
void readTempSetData(){
EEPROM.begin(200);
maxTemp = EEPROM.read(100);
minTemp = EEPROM.read(101);
EEPROM.end();
}
void writeTempSetData(){
EEPROM.begin(200);
EEPROM.put(100, maxTemp);
EEPROM.commit();
EEPROM.put(101, minTemp);
EEPROM.commit();
EEPROM.end();
}
showSSD1306.ino
#include "Wire.h"
#include "SSD1306.h"
#define SDA 21 //SDA引脚
#define SCL 22 //SCL引脚
SSD1306 display(0x3c, SDA, SCL); //初始化显示屏
/***************************************
* 初始化显示
**************************************/
void beginSSD(){
display.init(); //初始化显示
display.flipScreenVertically(); //把显示器倒过来
display.setFont(ArialMT_Plain_16);
}
/***************************************
* float转String函数
**************************************/
String Convert(float Num){
char strff[20];
sprintf(strff,"%.2f",Num);
String str = strff;
return str;
}
/***************************************
* 把温度显示在屏幕上
**************************************/
void showSSD(){
display.clear(); //清屏
display.setFont(ArialMT_Plain_10);
display.drawString(0, 0, getTemp()); //显示当前温度
display.setFont(ArialMT_Plain_16);
if(digitalRead(pin)==HIGH){
display.drawString(95, 0, "ON"); //显示当前开关机状态
}else{
display.drawString(95, 0, "OFF"); //显示当前开关机状态
}
if(temperatureDescendState){
display.drawString(95, 60, "+"); //显示当前升降温状态
}else{
display.drawString(95, 60, "-"); //显示当前升降温状态
}
if(setState == 0){
display.setFont(ArialMT_Plain_10);
String maxSetStr = "MAXTEMP:";
maxSetStr = maxSetStr + maxTemp;
display.drawString(0, 20, maxSetStr); //在指定位置绘制字符串,返回已写入的字符数
String minSetStr = "MINTEMP:";
minSetStr = minSetStr + minTemp;
display.drawString(0, 40, minSetStr); //在指定位置绘制字符串,返回已写入的字符数
}else if(setState == 1){
display.setFont(ArialMT_Plain_16);
String maxSetStr = "SETMAX:";
maxSetStr = maxSetStr + maxTemp;
display.drawString(0, 40, maxSetStr); //在指定位置绘制字符串,返回已写入的字符数
}else if(setState == 2){
display.setFont(ArialMT_Plain_16);
String minSetStr = "SETMIN:";
minSetStr = minSetStr + minTemp;
display.drawString(0, 40, minSetStr); //在指定位置绘制字符串,返回已写入的字符数
}else if(setState == 3){
String TDSStr;
if(temperatureDescendState){
TDSStr = "Rise +";
}else{
TDSStr = "Decline -";
}
display.setFont(ArialMT_Plain_16);
String TDSSetStr = "SETTDS:";
TDSSetStr = TDSSetStr+TDSStr;
display.drawString(0, 40, TDSSetStr); //在指定位置绘制字符串,返回已写入的字符数
}
display.display(); //将缓冲区写入显示存储器
}