摘要
利用ESP32设计一款八通道热敏电阻采集方案,并使用SD卡采集及OLED显示,通过Arduino_IDE编写。本产品在淘宝店Begabung发售,型号:TC250。
安装环境准备
ArduinoIDE中ESP首选项修改
开发板及端口选择
头文件下载
内容
零件准备:ESP32芯片、OLED模块、SD卡模块,NTC热敏电阻
所需资料
接线参考安信可NodeMCU-32管脚示意图
SD卡模块
OLED模块,可直接查看数据及SD卡采集情况
本产品自定义管脚包括SD卡所需的CS、SCK、MOSI、MISO;OLED模块所需的SCL、SDA模块;此为还接出TEST开关,CAN通讯接口及天线接口。
CS | 14 |
SCK | 27 |
MOSI | 26 |
MISO | 25 |
SCL | 19 |
SDA | 22 |
Button | 21 |
CAN_TX | 10 |
CAN_RX | 9 |
天线 |
八位ADC采集模拟信号量
ADC0 | 36 |
ADC1 | 37 |
ADC2 | 38 |
ADC3 | 39 |
ADC4 | 32 |
ADC5 | 33 |
ADC6 | 34 |
ADC7 | 35 |
管脚定义代码,可根据设计需求自行更改
// define adc pin
#define ADC0 36
#define ADC1 37
#define ADC2 38
#define ADC3 39
#define ADC4 32
#define ADC5 33
#define ADC6 34
#define ADC7 35
// define IIC pin
#define SCL 19
#define SDA 22
// define led pin
#define INDICATOR 23
// define SPI pin
#define CS 14
#define MISO 25
#define MOSI 26
#define SCK 27
// define CAN pin
#define CAN_TX 10
#define CAN_RX 9
// define test button pin
#define BUTTON 21
原理
热敏电阻NTC与10K电阻对3.3V电源分压,ADC接口采集热敏电阻电压接入ESP32进行处理。NTC热敏电阻阻值范围为1034.600KΩ至0.337KΩ,测温范围为-55°C至125°C,精度±1%。
电压换算公式修改数值后对其他传感器同样适用
//电压换算成温度
float temp_cacu(float a)
{
float Rt=0;
float Rp=10000;
float T2=273.15+25;
float Bx=3950;
float Ka=273.15;
float vol=0.0;
float temp = 0.0;
vol=(float)(a * 3.3 / 4096);
Rt=vol*Rp/(3.3-vol);
temp=(float)1/(1/T2+log(Rt/Rp)/Bx)-Ka+0.5;
return temp;
}
总代码
近日重装系统后发现上述代码在运行过程中存在错误,对标错代码段经行注释处理即可
新代码如下所示
#include <Wire.h>
#include <Arduino.h>
#include <SPI.h>
#include <SD.h>
//读取RS485
#include <SoftwareSerial.h>
// 引入驱动OLED0.96所需的库
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// define IIC pin
#define SCL 19
#define SDA 22
// define SPI pin
#define CS 14
#define MISO 25
#define MOSI 26
#define SCK 27
// define CAN pin
#define CAN_TX 10
#define CAN_RX 9
// define test button pin
#define BUTTON 21
// define led pin
#define INDICATOR 23
// 自定义重置引脚,虽然教程未使用,但却是Adafruit_SSD1306库文件所必需的
#define OLED_RESET 4
#define SCREEN_WIDTH 132 // 设置OLED宽度,单位:像素
#define SCREEN_HEIGHT 64 // 设置OLED高度,单位:像素
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
File dataFile;
unsigned char item[8] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A}; //16进制测温命令
String data = ""; // 接收到的16进制字符串
SoftwareSerial pressureSerial(16, 17); // RX, TX
float getpressure(String pressureerature); // 函数声明
float p1 =0;
void setup()
{
pressureSerial.begin(9600);
Serial.begin(9600);
// 初始化Wire库
//Wire.begin(SDA, SCL);
// 初始化OLED并设置其IIC地址为 0x3C
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
pinMode(INDICATOR, OUTPUT);
digitalWrite(INDICATOR, LOW);
pinMode(CS, OUTPUT);//定义
//SPI.begin(SCK,MISO,MOSI,CS);
sd_card_init();
if(!BUTTON){
dataFile = SD.open("/TC250.txt", FILE_WRITE);
}
dataFile = SD.open("/TC250.txt", FILE_WRITE);
// uint8_t cardType=SD.cardType();
// if(cardType==CARD_NONE){
// Serial.println("No SD card attached");
// return;
// }
dataFile = SD.open("/TC250.txt", FILE_WRITE);//sd卡
}
void loop()
{
delay(10); // 放慢输出频率
for (int i = 0 ; i < 8; i++) { // 发送测温命令
pressureSerial.write(item[i]); // write输出
}
delay(100); // 等待测气压数据返回
data = "";
while (pressureSerial.available()) {//从串口中读取数据
unsigned char in = (unsigned char)pressureSerial.read(); // read读取
// Serial.print(in, HEX);//问询帧打印
// Serial.print(',');
data += in;
data += ',';
}
p1=(getpressure(data));
//oled
words_display();
display.display();
String dataString = "";
dataString += String(p1);
dataString += ",";
//p1=analogRead(getpressure(data));
if(dataFile)
{
dataFile.println(dataString);
dataFile.flush();
// digitalWrite(INDICATOR, LOW);
Serial.println(dataString);
}else
{
Serial.println("Fail to open 'TC250.txt' .");
}
//digitalWrite(INDICATOR, HIGH);
if (data.length() > 0) { //先输出一下接收到的数据
// Serial.println(); //应答帧打印
// Serial.println(data);
Serial.print(p1);
Serial.println("m/s");
}
}
void sd_card_init()
{
if(!SD.begin(CS))
{
Serial.println("Fail to init sd card.");
while(1);
}
}
void words_display()
{
// 清除屏幕
display.clearDisplay();
// 设置字体颜色,白色可见
display.setTextColor(WHITE);
//设置字体大小
display.setTextSize(2);
//设置光标位置
display.setCursor(35, 0);
display.print("TC250");
if(dataFile){
display.setTextSize(1.5);
display.setCursor(35, 17);
display.print("(SD:ready) ");
}else{
display.setTextSize(1.5);
display.setCursor(35, 17);
display.print("(SD:error) ");
}
display.setTextSize(1.5);
//打印自开发板重置以来的秒数;
//display.print(millis() / 1000);
display.setCursor(5,27);
display.print("d1=");
display.print(p1);
}
float getpressure(String pressure) {
int commaPosition = -1;
String info[9]; // 用字符串数组存储
for (int i = 0; i < 9; i++) {
commaPosition = pressure.indexOf(',');
if (commaPosition != -1)
{
info[i] = pressure.substring(0, commaPosition);
pressure = pressure.substring(commaPosition + 1, pressure.length());
}
else {
if (pressure.length() > 0) { // 最后一个会执行这个
info[i] = pressure.substring(0, commaPosition);
}
}
}
return (info[3].toInt() + info[4].toInt()) / 10.0;
}