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

MKR1000 多模态环境传感器平台:闪电、气体、紫外、温湿度、气压全监测

组件与物料清单

组件 数量
Arduino MKR1000 1
MOD-1016 闪电探测器 (AS3935) 1
DFRobot MQ-9 可燃气体传感器 1
Adafruit HTU21D-F 温湿度传感器 1
Adafruit BMP085/BMP180 气压/海拔/温度传感器 1
SparkFun ML8511 紫外线传感器 1
ChronoDot RTC 实时时钟模块 1
SparkFun Photon Weather Shield(备用扩展板) 1
Adafruit NeoPixel 灯珠 1
面包板、跳线若干 1

项目背景

我热爱观测天气,想自建一套能长期记录、绘图分析的气象站。普通气象站只能看 "当下" 或过去一小时数据,我要做更多。MKR1000 拥有 8 个硬件中断引脚,解决了传统 Arduino 中断资源不足的痛点,让我能同时接入:雨量计、风速计、闪电探测器等中断型传感器。

MKR1000 多模态环境传感器平台:闪电、气体、紫外、温湿度、气压全监测

传感器分类与选型建议

MKR1000 丰富的 I/O 可同时满足以上所有类型。注意电压兼容: MKR1000 为 3.3V 逻辑,若传感器为 5V 需加电平转换模块。

引脚分配规划

建议先在纸上规划,再写入代码注释备忘。我的分配方案:

入门建议:逐个调试传感器

新手建议:一次只接一个传感器,跑通官方例程并读出串口数据后,再接入下一个。所有传感器单独验证通过后,再集成到主程序。

笔者保留了 I²C 接口的 ChronoDot RTC(DS3231),因为 MKR1000 自带 RTC 电池供电下走时不准。面包板上橙色跳线分别给各传感器供电,调试时拔掉即可屏蔽该传感器,非常方便。

MKR1000 多模态环境传感器平台:闪电、气体、紫外、温湿度、气压全监测

库兼容性避坑指南

部分老旧库在新版 Arduino IDE (1.6.5+) 中因 ATOMIC_* 宏被移除而编译报错。遇到橙色报错先判断是库还是自身代码问题,搜索 "arduino + 报错信息" 通常能找到修补方案。推荐优先购买 Adafruit/SparkFun 官方模块,其库维护及时。

WiFi 与加密提示

MKR1000 内置加密引擎可保障物联网数据传输安全,但本项目暂未实现上云。关键提示: 必须使用最新版 WiFi101 库,否则无法识别板载 WiFi 模块。

模拟传感器读数技巧

I²C 总线使用技巧

MKR1000 多模态环境传感器平台:闪电、气体、紫外、温湿度、气压全监测

数据可视化构想

目前仅串口输出。未来可接 LCD、SD 卡记录,或利用板载 WiFi 上传云端。设想部署多台设备,通过闪电探测器读数三角定位闪电击中点!

灵感来源:IKEA SODERSVIK 落地灯替换为 NeoPixel 灯珠 + IR 遥控,用灯光可视化风速(云卷云舒)、温度(色温)、12h 温差等气象要素。

MKR1000 多模态环境传感器平台:闪电、气体、紫外、温湿度、气压全监测

核心代码片段

完整监测主程序 (节选关键部分)

/* RTC-Weather-Sensors_v6_MKR1000 by Zonker Harris */
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
#include <Adafruit_HTU21DF.h>
// NeoPixel 与闪电库因中断向量冲突暂注释,待 IDE 更新后恢复
//#include <Adafruit_NeoPixel.h>

Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10180);
Adafruit_HTU21DF htu = Adafruit_HTU21DF();

// 引脚定义
int UVOUT = A1, lightOut = A2, tmp36out = A3, mq9out = A4;
int sounderPin = 6, neopixelPin = 7;

// ChronoDot RTC 变量 (地址 0x68)
int addrRTC = 0x68;
int seconds, minutes, hours, day, date, month, years;
int temprtc, tempfrtc;

void setup() {
  Serial.begin(9600); delay(1000);
  pinMode(UVOUT, INPUT); pinMode(lightOut, INPUT); pinMode(tmp36out, INPUT);
  pinMode(sounderPin, OUTPUT); pinMode(neopixelPin, OUTPUT);
  if (!bmp.begin()) { Serial.println("BMP180 not found"); while(1); }
  if (!htu.begin()) { Serial.println("HTU21D not found"); while(1); }
  // RTC 首次设置时间后注释掉
  // seconds=0; minutes=41; hours=20; day=7; date=3; month=1; years=16; initChrono();
}

void loop() {
  beep(50, 2);  // 蜂鸣器提示循环开始

  // 1. 读取 ChronoDot RTC 时间
  Wire.beginTransmission(0x68); Wire.write(0); Wire.endTransmission();
  Wire.requestFrom(0x68, 13);
  // ... 解析 BCD 码获取时分秒、日期、温度 ...
  get_date();
  Serial.print("ChronoDot - "); Serial.print(hours); Serial.print(":"); Serial.print(minutes); Serial.print(":"); Serial.println(seconds);

  // 2. BMP180 气压/温度/海拔
  sensors_event_t event; bmp.getEvent(&event);
  float BMPtemperature; bmp.getTemperature(&BMPtemperature);
  if (event.pressure) {
    Serial.print("BMP180 - Pres: "); Serial.print(event.pressure); Serial.print(" hPa");
    float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
    Serial.print(" Alt: "); Serial.print(bmp.pressureToAltitude(seaLevelPressure, event.pressure)); Serial.println(" m");
  }

  // 3. HTU21D 温湿度
  float HTUtemperature = htu.readTemperature();
  Serial.print("HTU21D - Temp: "); Serial.print(HTUtemperature); Serial.print(" C  Hum: "); Serial.print(htu.readHumidity()); Serial.println("%");

  // 4. TMP36 模拟温度
  int reading = averageAnalogRead(tmp36out);
  float voltage = 0.0032258064516129 * reading;  // 3.3V/1023
  float tempC = (voltage - 0.5) * 100;
  Serial.print("TMP36 - temp: "); Serial.print(tempC); Serial.println(" C");

  // 5. TEMT6000 可见光
  int vLevel = averageAnalogRead(lightOut);
  Serial.print("TEMT6000 out: "); Serial.println(vLevel);

  // 6. ML8511 UV 强度
  int uvLevel = averageAnalogRead(UVOUT);
  float uvVolts = 0.0032258064516129 * uvLevel;
  float uvIntensity = mapfloat(uvVolts, 0.99, 2.8, 0.0, 15.0);  // mW/cm²
  Serial.print("ML8511 UV: "); Serial.print(uvLevel); Serial.print(" / UV Intensity: "); Serial.println(uvIntensity);

  // 7. MQ-9 可燃气体
  int MQ9volts = analogRead(mq9out);
  Serial.print("MQ-9 Gas: "); Serial.println(MQ9volts);

  Serial.println(); delay(3500);  // 约 5 秒一个循环
}

// 多次采样平均滤波
int averageAnalogRead(int pin) {
  byte n = 8; unsigned int sum = 0;
  for (byte i = 0; i < n; i++) sum += analogRead(pin);
  return sum / n;
}

// float 版 map()
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void beep(int dur, int cnt) {
  for (int i = 0; i < cnt; i++) { digitalWrite(sounderPin, HIGH); delay(dur); digitalWrite(sounderPin, LOW); delay(dur); }
}

// RTC 辅助函数: initChrono, set_date, get_date, set_time, get_time, decToBcd, bcdToDec 等省略

通用模拟读数平均值函数 (Beerware License)

int averageAnalogRead(int pinToRead) {
  byte numberOfReadings = 8;
  unsigned int runningValue = 0;
  for (byte x = 0; x < numberOfReadings; x++) runningValue += analogRead(pinToRead);
  runningValue /= numberOfReadings;
  return runningValue;
}

I²C 总线扫描器 (自动识别设备地址)

#include <Wire.h>
void setup() { Wire.begin(); Serial.begin(9600); Serial.println("I2C Scanner"); }
void loop() {
  byte error, address; int nDevices = 0;
  Serial.println("Scanning...");
  for (address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0) {
      Serial.print("I2C device at 0x"); if (address < 16) Serial.print("0"); Serial.print(address, HEX);
      // 已知设备标注
      if (address == 0x03) Serial.print(" - AS3935 Lightning");
      if (address == 0x40) Serial.print(" - HTU21D Temp/Hum");
      if (address == 0x68) Serial.print(" - DS3231 RTC");
      if (address == 0x77) Serial.print(" - BMP180 Pressure");
      Serial.println(); nDevices++;
    }
  }
  if (nDevices == 0) Serial.println("No I2C devices");
  Serial.println("done"); delay(5000);
}

ML8511 UV 传感器演示代码 (3.3V 系统适配版)

int UVOUT = A1;
void setup() { Serial.begin(9600); pinMode(UVOUT, INPUT); Serial.println("ML8511 example"); }
void loop() {
  int uvLevel = averageAnalogRead(UVOUT);
  float uvVolts = 0.0032258064516129 * uvLevel;
  float uvIntensity = mapfloat(uvVolts, 0.99, 2.8, 0.0, 15.0);
  Serial.print("ML8511: "); Serial.print(uvLevel); Serial.print(" / UV: "); Serial.println(uvIntensity);
  delay(100);
}
// averageAnalogRead 与 mapfloat 同前

原理图

因 Fritzing 库缺件,绘制了简化连接示意图:

MKR1000 多模态环境传感器平台:闪电、气体、紫外、温湿度、气压全监测

制造工艺

  1. 树莓派传感器数据融合实战:GPS 与 MPU‑9150 IMU 的 I²C 与 UART 接入
  2. 树莓派接 KY‑033 循迹/门状态传感器:简易 Python 实现
  3. 树莓派构建稳健传感器 API:基于 GY‑91 多功能模块的 Flask 实现
  4. 树莓派自动化气雾栽培系统:湿度传感器智能控制
  5. 掌握树莓派 GPIO:在 B+/Model 2 上接入 PIR 运动传感器
  6. 将 Acconeer A111 脉冲雷达与树莓派集成:实用指南
  7. HC‑SR501 PIR 运动传感器与树莓派接线、校准与 Python 编程全指南
  8. Python/MicroPython 传感器记录仪:无缝写入 Google Sheets
  9. 树莓派 2 (Windows 10 IoT Core) 采集 Adafruit 10DOF IMU 数据上传 Azure Event Hubs
  10. 树莓派优雅关机与休眠模式:DIY电源管理电路
  11. Portenta H7 对接 MAX6675 热电偶温度传感器教程
  12. 传感器融合如何提升自主系统的可靠性、安全性与效率