PT100/PT1000 工业级温度传感器
来自Jack's Lab
目录 |
1 概述
工业和医学应用中,如果在 -200°C ~ +800°C 范围内对温度测量的绝对精度和可重复性要求非常高,最好选择铂电阻温度 (RT) 检测器,即 PRTD。铂元素非常稳定,且不容易腐蚀或氧化
常见的 PRTD 包括 PT100、PT500 和 PT1000,0°C下分别呈现100Ω、500Ω和1000Ω阻值,其阻值会随温度变化 (PT1000 Table)。也有成本稍高的大阻值传感器,例如 PT10000
PRTD 传统测量方法是采用电流源激励:
对于较高阻值的 PRTD,应采用高精度电压源激励 PRTD,可以利用 ADC 的电压基准为 PRTD 提供偏压。PRTD 可直接连接到 ADC,ADC 基准通过一个高精度电阻提供 PRTD 偏置电流。ADC即可以高精度比例测量温度:
2 PT1000 Table
3 ESP8266 ADC
硬件连接:
VCC33 ---> PT1000 <-- (A0) --> 300R 1% ---> GND
void setup()
{
Serial.begin(115200);
}
void loop() {
int vd = analogRead(A0);
Serial.print("vd = ");
Serial.println(vd);
uint32_t rtd = (1024 - vd) * 300 / vd;
Serial.print("rtd = ");
Serial.println(rtd);
delay(1000);
}
4 MCP3421
- 快速测试:
#include <Wire.h>
#define MCP3421_ADDRESS 0X68
void setup()
{
Serial.begin(115200);
Wire.begin();
}
void loop()
{
Wire.requestFrom(MCP3421_ADDRESS, 4);
if (Wire.available() != 4) {
Serial.println("Wire.available failed");
while(1);
}
int16_t v = (Wire.read() << 8);
v |= Wire.read();
// read but ignore status
uint8_t s = Wire.read();
//print voltage from channel one in millivolts
Serial.print(v);Serial.println(" mv");
delay(1500);
}
- 改进:
#include <Wire.h>
// I2C address for MCP3422 - base address for MCP3424 = 0x68
#define MCP342X_ADDRESS 0X68
// fields in configuration register
#define MCP342X_GAIN_FIELD 0X03 // PGA field
#define MCP342X_GAIN_X1 0X00 // PGA gain X1, 12 bits, 1 mV
#define MCP342X_GAIN_X2 0X01 // PGA gain X2, 14 bits, 250 uV
#define MCP342X_GAIN_X4 0X02 // PGA gain X4, 16 bits, 62.5 uV
#define MCP342X_GAIN_X8 0X03 // PGA gain X8, 18 bits, 15.625 uV
#define MCP342X_RES_FIELD 0X0C // resolution/rate field
#define MCP342X_RES_SHIFT 0X02 // shift to low bits
#define MCP342X_12_BIT 0X00 // 12-bit 240 SPS
#define MCP342X_14_BIT 0X04 // 14-bit 60 SPS
#define MCP342X_16_BIT 0X08 // 16-bit 15 SPS
#define MCP342X_18_BIT 0X0C // 18-bit 3.75 SPS
#define MCP342X_CONTINUOUS 0X10 // 1 = continuous, 0 = one-shot
#define MCP342X_CHAN_FIELD 0X60 // channel field
#define MCP342X_CHANNEL_1 0X00 // select MUX channel 1
#define MCP342X_CHANNEL_2 0X20 // select MUX channel 2
#define MCP342X_CHANNEL_3 0X40 // select MUX channel 3
#define MCP342X_CHANNEL_4 0X60 // select MUX channel 4
#define MCP342X_START 0X80 // write: start a conversion
#define MCP342X_BUSY 0X80 // read: output not ready
uint8_t chan = 0XFF, gain = 0XFF, res = 0XFF;
//------------------------------------------------------------------------
// default adc configuration register - resolution and gain added in setup()
uint8_t adcConfig = MCP342X_START | MCP342X_CHANNEL_1 | MCP342X_CONTINUOUS;
// divisor to convert ADC reading to milivolts
uint32_t mvDivisor;
void halt(void)
{
Serial.println("Halted - check address and wiring");
while(1);
}
// read mcp342x data - updated 10mar11/wbp
uint8_t mcp342xRead(int32_t &data)
{
// pointer used to form int32 data
uint8_t *p = (uint8_t *)&data;
// timeout - not really needed?
uint32_t start = millis();
if ((adcConfig & MCP342X_RES_FIELD) == MCP342X_18_BIT) // in 18 bit mode?
{
do { // 18-bit mode
Wire.requestFrom(MCP342X_ADDRESS, 4);
if (Wire.available() != 4) {
Serial.println("read failed");
return false;
}
for (int8_t i = 2; i >= 0; i--) {
p[i] = Wire.read();
}
// extend sign bits
p[3] = p[2] & 0X80 ? 0XFF : 0;
// read config/status byte
uint8_t s = Wire.read();
if ((s & MCP342X_BUSY) == 0) return true; // escape here
} while (millis() - start < 500); // allows rollover of millis()
} else {
do { // 12-bit to 16-bit mode
Wire.requestFrom(MCP342X_ADDRESS, 3);
if (Wire.available() != 3) {
Serial.println("read failed");
return false;
}
p[1] = Wire.read();
p[0] = Wire.read();
// extend sign bits
p[2] = p[1] & 0X80 ? 0XFF : 0;
p[3] = p[2];
// read config/status byte
uint8_t s = Wire.read();
if ((s & MCP342X_BUSY) == 0) return true; // or escape here
} while (millis() - start < 500); // allows rollover of millis()
}
Serial.println("read timeout"); // dang it
return false;
}
// write mcp342x configuration byte
uint8_t mcp342xWrite(uint8_t config)
{
Wire.beginTransmission(MCP342X_ADDRESS);
Wire.write(config);
Wire.endTransmission();
}
void setup()
{
Serial.begin(115200);
pinMode(D4, OUTPUT);
digitalWrite(D4, LOW);
Wire.begin();
do {
Serial.println();
Serial.flush();
Serial.print("Enter gain (1, 2, 4, or 8): ");
while(Serial.available() < 1);
switch (Serial.read()) {
case '1': // ACSCII number received
gain = MCP342X_GAIN_X1;
break;
case '2':
gain = MCP342X_GAIN_X2;
break;
case '4':
gain = MCP342X_GAIN_X4;
break;
case '8':
gain = MCP342X_GAIN_X8;
break;
}
}
while (gain > 3);
Serial.println(1 << gain, DEC);
do {
Serial.flush();
Serial.println();
Serial.print("Enter resolution (12, 14, 16, or 18): ");
while (Serial.available() < 2);
if (Serial.read() != '1') continue;
switch (Serial.read()) {
case '2':
res = 0;
break;
case '4':
res = 1;
break;
case '6':
res = 2;
break;
case '8':
res = 3;
break;
}
}
while (res > 3);
Serial.println(12 + 2*res, DEC);
adcConfig |= res << 2 | gain | MCP342X_START;
// divisor to convert ADC reading to millivolts
mvDivisor = 1 << (11 + 2*res);
Serial.print("md = ");
Serial.println(mvDivisor);
}
void loop()
{
int32_t data;
mcp342xWrite(adcConfig);
if (!mcp342xRead(data)) halt();
Serial.print("data = ");
Serial.println(data);
// voltage in millivolts
double mv = (double)data * 2048 / mvDivisor;
// uncomment line below to convert reading to microvolts
uint32_t uv = mv * 1000;
Serial.print("V = ");
Serial.print(mv);
Serial.print(" mV");
Serial.print(" , ");
Serial.print(uv);
Serial.println(" uV");
delay(2000); // 5 seconds + conversion time x 4
}
5 专用芯片
选型: Temperature Sensor Tutorial
5.1 MAX31865
5.2 MAX6603
6 资源
- http://openenergymonitor.org/emon/buildingblocks/rtd-temperature-sensing
- http://forum.arduino.cc/index.php?topic=16731.0
- http://stackoverflow.com/questions/21644642/how-to-connect-pt-1000
- http://41j.com/blog/2015/01/esp8266-analogue-input/


