基于 PT100 传感器与 Arduino UNO 的精密恒温样本运输容器
组件与材料
- PT100 温度传感器 × 1
- Arduino UNO × 1
- 锂离子电池(10400 mAh)× 1
- 聚苯乙烯保温箱(回收自样品/化学品包装)× 1
- 铜块(约 80×50×10mm,两块,需加工散热片与帕尔贴安装孔、热管孔)× 1套
- 可调升压电源模块(ULS)× 1
- 热管散热器 × 1
- 数字电位器 × 1
- 导热凝胶 × 1
- DC-DC 转换器 × 1
- 帕尔贴模块 × 1
- 3.3μF 电容 × 1
- 热管 × 1
- 市电电源适配器 × 1
- DC 分流器 × 1
- Adafruit LCD 屏幕 × 1
- 加热垫 × 1
- 接线端子 × 1
- 塑料外壳(内部)× 1
- 面板安装 DC 插座 × 1
- 四刀双掷开关 × 1
- 单刀双掷开关 × 1
- 塑料外壳(外部电子仓)× 1
- 3路接线端子 × 1
- 5路接线端子 × 1
- 魔术贴 DualLock 胶带 × 1
- Adafruit Proto-screwshield × 1
- Adafruit 锂离子 USB 充电板 × 1
- Adafruit PT100 信号放大板 × 1
所需工具
- 电烙铁
- Dremel 4000 旋转工具
- 台钳
- 电钻
- 剥线钳、钳子、剪刀
- 手动铣床(加工铜件用)
软件与在线服务
- GitHub(使用 sleemanj 的 MCP41100 数字电位器库、Adafruit 各模块库)
- Arduino IDE
项目简介
Mr ThermoParcel:用于样本运输的恒温容器
本项目旨在开发一种恒温容器,可通过普通邮政服务安全运输对温度敏感的生物样本。原型机“Mr ThermoParcel”工作温度范围 4–37°C,可由市电适配器、内置电池或其他 12V 电源(如车载点烟器、笔记本电源适配器)供电。
项目起因
源于学术研究中面临的真实问题:与合作者安全交换对温度敏感的生物样本(如疟疾研究中的血液样本)。若运输过程中温度失控,样本易降解失效,尤其珍贵的特殊血型样本更是如此。传统方案是冻干后用冷链快递,再按协议复温,但冻融过程会损伤样本,且校园快递站的存储条件差、通知延迟常导致样本失效。
设计理念
将温控系统集成到常规聚苯乙烯包装箱(小包裹尺寸,化学品配送回收箱)中。经血液样本优化测试,同样适用于细胞、培养基、温敏化学品、乳剂、酶等生物材料,也可改造用于固体物品。
系统原理如图1所示:制冷侧用帕尔贴模块,冷端贴合箱内小样本盒,热端经三根铜热管连接外部散热铜块与 CPU 散热器;加热侧在样本盒内放置加热垫。PT100 传感器贴合样本实时监测温度,Arduino 通过 PID 闭环调节加热/制冷功率。

实施细节
容器硬件设计
外箱为 250×250×250mm、壁厚 45mm 的聚苯乙烯箱。内部放置 125×70×40mm 塑料外壳,内装两个 50mL 离心管(符合 UN3373 类别 B 生物感染性物质包装规范)。主样本为六个 2mL 离心管,用吸水纸隔开防漏。若将硬质二级包装改为柔性袋,可容纳 50mL 液体样本(如 3-4 支 15mL 管)。为提高内部加热/制冷均匀性并保证铜片、样本、温度传感器的热接触,在样本周围灌注电绝缘固化凝胶。内部样本盒见图2。

制冷与加热系统
内部温度由贴合样本的 100Ω 铂电阻(PT100 RTD)监测,通过 PID 控制帕尔贴制冷或加热垫加热。帕尔贴热端经三根铜热管与外部铜块、CPU 散热器热联;冷端贴合穿过箱壁的薄铜片,均匀冷却样本。热联细节见图3。加热垫置于内盒内,与传感器和样本接触。



电子与接线
制冷/加热调节
帕尔贴额定 3.9A、7.6V。功率由 PTN78020W 降压开关稳压器电子调节:输入 7–36V,输出 2.5–12.6V(输出不得超输入减 2V)。输出电压按数据手册通过两调节脚间电阻设定。本项目用 MCP41100 100kΩ 数字电位器由 Arduino 控制,根据温度读数电子调节输出。因 PTN78020W 全输出范围需 >1MΩ 电阻变化,数字电位器满量程 100kΩ 时仍有电压输出,故不能仅靠电位器完全关断帕尔贴。加热垫同理,调节电压即控制功率。
电源系统
市电时用 12V 直流电源直接供电 PTN78020W,输出可达 10V,足以驱动帕尔贴满功率及加热垫。得益于 7–36V 宽输入范围,也可用笔记本电源适配器、车载点烟器等。无市电时由 3.7V 10400mAh 锂电池供电,经 XL6019 升压模块升至 10–12V 后再接入 PTN78020W。
Arduino 接线
Arduino 由 12V 外部输入经板载 DC 插座供电;电池模式下由 XL6019 输出经同一插座供电。Arduino 通过控制数字电位器电阻调节帕尔贴/加热垫功率,接线参考 sleemanj 的 MCP41 系列库(可变电阻模式)。同时接入 Adafruit MAX31865 PT100 放大板读取温度,及 Adafruit RGB LCD Shield 显示数据与操作,均按官方文档接线。
软件设计
所有 Adafruit 模块用对应库驱动,数字电位器用 sleemanj 库。核心功能为 PID 闭环温控:用户通过 LCD 按键设定目标温度,每次测温计算偏差得出 PID 值驱动数字电位器调节功率。外部拨码开关切换帕尔贴(制冷)或加热垫(加热)输出路径。因无电子开关,代码区分制冷/加热模式并由用户通过 LCD 按键选择,确保 PID 符号正确。测试中发现仅 P 项即可在大多数情况下将温度控制在设定点 ±0.5°C 内,故移除 I、D 项。这归因于样本与凝胶盒热容大,温变慢(最快约 0.02°C/s)。
性能表现
市电供电时:室温 21–23°C 起降至 4°C 约需 1 小时,20 分钟内达 8–10°C;加热至 37°C 约 10 分钟。全程温度稳定在设定点 ±0.5°C。
仅电池供电时:最低约 10°C,需 1.5–2 小时;加热至 37°C 需 40–60 分钟。受限于电池放电率:该锂电池最大放电 7A@3.7V,升压至 10–12V 后需更大电流才能维持帕尔贴最大功率,电池自带过流保护会切断输出。软件已限制电池模式下功耗至安全水平。此为所用电池限制,大倍率电池或 3串 11.1V 锂电池可解决,后者还可省去升压模块。


未来展望
当前原型因 CPU 散热器体积大、活动部件多、结构强度不足,尚不能直接邮寄。若将散热器改为被动散热、采用 95kPa 二级包装,装入合适刚性外箱,即可满足航空及各种运输方式的标准快递要求。
核心目标达成后,可扩展功能:本地存储运输温度曲线供事后核验,或通过 GSM 模块定时发送短信;增加 GPS 接收器实现独立包裹追踪与及时收件。
Arduino 代码
#include <Adafruit_MAX31865.h>
#include <MCP41_Simple.h>
#include <Adafruit_RGBLCDShield.h>
#include <utility/Adafruit_MCP23017.h>
#include <Wire.h>
MCP41_Simple digitalPotentiometer;
const uint8_t digitalPotentiometer_CS = 10;
Adafruit_MAX31865 PT100amplifier = Adafruit_MAX31865(2, 3, 4, 5);
#define RREF 430.0
#define RNOMINAL 100.0
Adafruit_RGBLCDShield LCD_shield = Adafruit_RGBLCDShield();
int powerMode = 1; // 1=电池, -1=市电
int operationMode = 1; // 1=制冷, -1=加热
float PT100ratio;
uint8_t buttonsPressed = 0;
float kp = 500.0;
int ki = 5, kd = 3.9;
float PID_p = 0.0;
float Tmeasured = -1.0;
float Tsetpoint = 22.0;
float PID_error = 5;
float PID_value = 0;
static char TsetpointString[3];
void print_Tsetpoint(int T) {
LCD_shield.setCursor(10, 0);
dtostrf(T, 3, 0, TsetpointString);
LCD_shield.print(TsetpointString);
}
static char TmeasuredString[4];
void print_Tmeasured(float T) {
LCD_shield.setCursor(8, 1);
dtostrf(T, 5, 1, TmeasuredString);
LCD_shield.print(TmeasuredString);
}
void print_powerMode() {
LCD_shield.setCursor(15, 0);
LCD_shield.print(powerMode == 1 ? "B" : "M");
}
void print_operationMode() {
LCD_shield.setCursor(15, 1);
LCD_shield.print(operationMode == 1 ? "C" : "H");
}
void setup() {
Serial.begin(115200);
Serial.println("Mr ThermoParcel, starting operation...");
PT100amplifier.begin(MAX31865_4WIRE);
digitalPotentiometer.begin(digitalPotentiometer_CS);
digitalPotentiometer.setWiper(200);
LCD_shield.begin(16, 2);
LCD_shield.print("Tsetpoint: C");
LCD_shield.setCursor(0, 1);
LCD_shield.print("Tsample: C");
}
void loop() {
uint16_t rtd = PT100amplifier.readRTD();
PT100ratio = rtd / 32768.0;
Tmeasured = PT100amplifier.temperature(RNOMINAL, RREF);
Serial.print("Setpoint Temperature = "); Serial.println(Tsetpoint);
Serial.print("Temperature = "); Serial.println(Tmeasured);
print_Tsetpoint(Tsetpoint);
print_Tmeasured(Tmeasured);
print_powerMode();
print_operationMode();
PID_error = Tmeasured - Tsetpoint;
PID_p = operationMode * kp * PID_error;
PID_value = (int)PID_p;
Serial.print("PID_p = "); Serial.println(PID_p);
Serial.print("powerMode = "); Serial.println(powerMode);
Serial.print("operationMode = "); Serial.println(operationMode);
Serial.print("PID_error = "); Serial.println(PID_error);
Serial.print("PID_value = "); Serial.println(PID_value);
if (powerMode == 1) {
if (PID_value < 0) PID_value = 0;
if (PID_value > 120) PID_value = 120;
} else if (powerMode == -1) {
if (PID_value < 0) PID_value = 0;
if (PID_value > 255) PID_value = 255;
}
Serial.print("Adjusted PID_value = "); Serial.println(PID_value);
digitalPotentiometer.setWiper(255 - PID_value);
delay(1000);
buttonsPressed = LCD_shield.readButtons();
if (buttonsPressed & BUTTON_SELECT) {
LCD_shield.setCursor(14, 0);
LCD_shield.blink();
delay(1000);
buttonsPressed = 0;
while (!(buttonsPressed & BUTTON_SELECT)) {
buttonsPressed = LCD_shield.readButtons();
if (buttonsPressed & BUTTON_UP) Tsetpoint += 1;
if (buttonsPressed & BUTTON_DOWN) Tsetpoint -= 1;
if (buttonsPressed & BUTTON_RIGHT) { powerMode *= -1; print_powerMode(); }
if (buttonsPressed & BUTTON_LEFT) { operationMode *= -1; print_operationMode(); }
print_Tsetpoint(Tsetpoint);
LCD_shield.setCursor(14, 0);
delay(500);
}
LCD_shield.noBlink();
buttonsPressed = 0;
}
Serial.println();
}
原理图
主电路原理图:
接线原理图(社区用户请求,实际装配用,较乱):
电位器接线图:
制造工艺