亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

DIY Arduino 冷镜露点仪:高精度温湿度监测

组件与材料

所需工具

软件与在线服务

项目简介

背景

测量湿度常用电容式传感器,但长期高湿环境下易漂移失准。冷镜露点仪无此缺陷,且高湿段精度更高,只是商用设备动辄数千美元。原理简单,自制虽达不到商用级 0.1°C 精度,但对大多数用途足够,且优于电容式传感器。

本项目为概念验证,非量产就绪,仍有大量改进空间,但已证明可行。

工作原理

帕尔贴制冷镜面至露点产生凝露,光源与光传感器检测凝露出现瞬间,记录镜面温度即为露点温度。结合环境温度,通过露点公式计算相对湿度。

简化与妥协

制作步骤

  1. 清洁帕尔贴两面,热侧涂导热胶贴散热片(无导热胶可用导热硅脂+边缘点滴瞬干胶),晾干。
  2. 冷侧同样清洁涂胶贴镜片,确保导热膏均匀无气泡,否则镜面温度不均。
  3. 粘贴风扇(热熔胶固定),风扇需风量足以压制散热片发热。
  4. DIY Arduino 冷镜露点仪:高精度温湿度监测
  5. 通电测试:短暂通电观察镜面凝露初现位置(勿久通电致均匀凝露)。拍照标记凝露同时出现的区域,此处为光传感器与测温传感器安装位。DIY Arduino 冷镜露点仪:高精度温湿度监测
  6. DIY Arduino 冷镜露点仪:高精度温湿度监测
  7. 作者导热膏涂布不均导致凝露分布不规则(见上图)。
  8. 安装 Si7021(镜面温度):温度传感器芯片大面涂非导电导热膏,PCB 也涂防凝露,四角大量热熔胶快速压贴镜面标记位置。需横向放置、压实。可用美工刀撬开重贴。PCB 凝露用热熔胶或喷胶绝缘。DIY Arduino 冷镜露点仪:高精度温湿度监测
  9. 风扇由 IRF520 MOSFET 模块驱动。
  10. 光传感器用 OPT101(灵敏、低噪、易用)。光源可用低功率激光二极管或聚光 LED,激光响应好但难对准,LED 易对准但响应平坦。需串联电阻降低亮度,避免 PWM 干扰传感器。
  11. LED/激光与 OPT101 用铜线扭绞固定,热熔胶封死,仅适合实验室原型。建议 3D 打印固定座并集成避光罩。DIY Arduino 冷镜露点仪:高精度温湿度监测
  12. 帕尔贴驱动用 BTS7960 电机驱动板。最优驱动方式是变电流非 PWM,但帕尔贴专用驱动难买,本概念验证不考虑功耗。DIY Arduino 冷镜露点仪:高精度温湿度监测
  13. 上传代码,调节电位器设定 OPT101 灵敏度(参考数据手册 Figure 3)。调试可对着镜面吹气制造凝露,或开关空调观察湿度变化。下图为温度(蓝)、光学读数(红)、测得露点(绿)曲线,关空调后露点上升。DIY Arduino 冷镜露点仪:高精度温湿度监测

安全提示

硬件支持反向驱动帕尔贴加热镜面(快速除露、闪蒸污染物),但镜面无散热片,若代码卡死在加热模式,轻则融化热熔胶脱落传感器,重则引发短路起火。代码未启用加热功能,请勿自行启用除非加完善保护。

精度分析

Arduino 代码

#include <math.h>
#include <avr/wdt.h>
#include "Si7021.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include "timer.h"
#include "timerManager.h"

#define coolingPWM 6
#define heatingPWM 5
#define coolingEnable 13
#define heatingEnable 12
#define tecFan 7
#define opticalSensor 0
#define oneWireBus A3

#define COOLING 0
#define HEATING 1
#define OFF 2

Timer timerMainLoop;
Timer timerTecCooling;
Timer timerSampleNoise;

Si7021 si7021;
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);

float humidity = 0;
float ambientTemp = 0;
float opticalDewpoint = 0;
float mirrorTemp = 30;
float optical = 30;
float dewPoint = 15;
float relativeHumidity = 30;
int tecState = OFF;
bool cooling = false;
int intervalTecCooling = 200;
float opticalThreshold = 0.5f;
int pwmIncrement = 1;
int startPwm = 100;
int maxPwm = 255;
int intervalMainLoop = 200;
int tecPwm = 0;
int noiseSampleIndex = 0;
int noiseSampleAmount = 10;
float noiseSampleHighest = 0;
float noiseSampleLowest = 10000;
bool noiseSampling = false;

float calculateHumidity(float TD, float T) {
  if (TD > T) TD = T;
  float rh = 100 * (exp((17.625 * TD) / (243.04 + TD)) / exp((17.625 * T) / (243.04 + T)));
  return rh;
}

void SetTEC(int state, int amount) {
  tecState = state;
  switch (state) {
    case COOLING:
      digitalWrite(heatingEnable, HIGH);
      analogWrite(heatingPWM, 0);
      digitalWrite(coolingEnable, HIGH);
      analogWrite(coolingPWM, amount);
      break;
    case HEATING:
      digitalWrite(coolingEnable, HIGH);
      analogWrite(coolingPWM, 0);
      digitalWrite(heatingEnable, HIGH);
      analogWrite(heatingPWM, amount);
      break;
    case OFF:
    default:
      digitalWrite(coolingEnable, LOW);
      analogWrite(coolingPWM, 0);
      digitalWrite(heatingEnable, LOW);
      analogWrite(heatingPWM, 0);
  }
}

void setup() {
  wdt_enable(WDTO_2S);
  Serial.begin(9600);
  pinMode(coolingPWM, OUTPUT);
  pinMode(heatingPWM, OUTPUT);
  pinMode(coolingEnable, OUTPUT);
  pinMode(heatingEnable, OUTPUT);
  pinMode(tecFan, OUTPUT);
  pinMode(opticalSensor, INPUT);

  timerMainLoop.setInterval(intervalMainLoop);
  timerMainLoop.setCallback(mainLoop);
  timerMainLoop.start();
  timerTecCooling.setInterval(intervalTecCooling);
  timerTecCooling.setCallback(tecCoolingCallback);
  timerSampleNoise.setInterval(intervalTecCooling);
  timerSampleNoise.setCallback(sampleNoiseCallback);

  uint64_t serialNumber = 0ULL;
  si7021.begin();
  serialNumber = si7021.getSerialNumber();
  sensors.begin();
  startNoiseSampling();
}

float getOptical() {
  int opt = analogRead(opticalSensor);
  return (float)opt / 30.0f;
}

void tecCoolingCallback() {
  digitalWrite(tecFan, HIGH);
  tecPwm += pwmIncrement;
  if (tecPwm > maxPwm) tecPwm = maxPwm;
  SetTEC(COOLING, tecPwm);
  if (optical <= (noiseSampleLowest - opticalThreshold)) {
    dewPoint = mirrorTemp;
    opticalDewpoint = optical;
    stopTec();
  }
}

void startNoiseSampling() {
  noiseSampling = true;
  noiseSampleHighest = 0;
  noiseSampleLowest = 10000;
  timerSampleNoise.start();
}

void sampleNoiseReset() {
  timerSampleNoise.stop();
  noiseSampleIndex = 0;
  noiseSampling = false;
}

void sampleNoiseCallback() {
  if (noiseSampleIndex > noiseSampleAmount) {
    sampleNoiseReset();
    startTecCooling();
  } else {
    if (optical > noiseSampleHighest) noiseSampleHighest = optical;
    if (optical < noiseSampleLowest) noiseSampleLowest = optical;
  }
  noiseSampleIndex++;
}

void startTecCooling() {
  cooling = true;
  digitalWrite(tecFan, HIGH);
  tecPwm = startPwm;
  timerTecCooling.start();
}

void stopTec() {
  cooling = false;
  digitalWrite(tecFan, LOW);
  timerTecCooling.stop();
  SetTEC(OFF, 0);
}

void mainLoop() {
  sensors.setResolution(10);
  sensors.requestTemperatures();
  ambientTemp = sensors.getTempCByIndex(0);
  mirrorTemp = si7021.measureTemperature();
  optical = getOptical();
  relativeHumidity = calculateHumidity(dewPoint, ambientTemp);

  Serial.print(mirrorTemp, 2); Serial.print(" ");
  Serial.print(optical, 2); Serial.print(" ");
  Serial.println(dewPoint, 2);

  if (!cooling && !noiseSampling && (optical >= noiseSampleLowest)) {
    startNoiseSampling();
  }
}

void loop() {
  wdt_reset();
  TimerManager::instance().update();
}

原理图

DIY Arduino 冷镜露点仪:高精度温湿度监测

制造工艺

  1. 现代镜子的科学与工艺
  2. DIY 蓝牙控制 Arduino 间谍小车
  3. FlickMote:基于手势的智能家居红外遥控器
  4. DIY Arduino TV-B-Gone:万能关机遥控器
  5. DIY 万花筒无限镜 — 打造震撼的 LED 灯光艺术装置
  6. 自制大尺寸LED主时钟带闹钟功能 — 12米外清晰可见
  7. Find Me:基于 Arduino 与蓝牙的智能寻物器制作指南
  8. Arduino 项目优化供电方案:从按键开关到电池监测与数据记录
  9. Arduino 井字棋游戏:MAX7219 点阵屏 + 纸板外壳 DIY
  10. 从零构建智能 Arduino 四足机器人:完整指南
  11. DIY Arduino 手柄方向盘 - 游戏竞速模拟器自制指南
  12. 利用 Arduino Nano R3 自制全功能 CNC 雕刻机