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

智能室内空气质量与垃圾监测系统

组件与物料

Raspberry Pi 3 Model B ×1
Arduino UNO ×1
NodeMCU ESP8266 开发板 ×1
DHT11 温湿度传感器 (4针) ×1
Seeed Grove - 气体传感器 (MQ2) ×1
MQ-7 一氧化碳气体传感器 ×1
超声波测距模块 HC-SR04 ×1
树莓派电源适配器 ×1
HDMI 线 ×1
USB-A 转 B 线 ×1
杜邦线 (若干) ×1
5V 电池 ×1

应用与在线服务

项目简介

1. 简介

楼宇自动化 是通过楼宇管理系统 (BAS) 对供暖、通风、空调、照明等系统进行集中自动控制,目标是提升居住舒适度、提高系统运行效率、降低能耗和运营成本、延长设备寿命。

智能室内空气质量与垃圾监测系统

IOTA 是面向物联网的开源分布式记账技术,旨在实现安全的数据与价值交换。其核心创新是用有向无环图 (DAG) 架构的 Tangle 替代传统区块链,实现零手续费、低延迟、更好扩展性。IOTA 正在开发中,预计 2019 年大规模落地。

智能室内空气质量与垃圾监测系统
智能室内空气质量与垃圾监测系统

树莓派 3B 规格: 四核 64 位 ARM Cortex-A53 @1.2GHz,GPU VideoCore IV @400MHz,1GB LPDDR2 内存,4 个 USB、HDMI、复合视频输出,百兆以太网 + 802.11n WiFi。

智能室内空气质量与垃圾监测系统

Arduino UNO 特性: ATmega328 主控,5V 工作电压,建议 7-12V 输入,14 个数字 IO (6 路 PWM),6 个模拟输入,IO 口最大 40mA,3.3V 引脚 50mA。

智能室内空气质量与垃圾监测系统

NodeMCU (ESP8266) 特性: 可编程 WiFi 模块,Arduino 风格硬件 IO,支持 Arduino IDE 开发,板载 USB-TTL,10 个 GPIO (D0-D10),支持 PWM、I2C、SPI、1-Wire、ADC 等。

本项目分三个版本,章节如下:

  1. 简介
  2. 软件安装
  3. 室内空气质量监测系统 v1
  4. 室内空气质量监测系统 v2
  5. 垃圾监测系统
  6. 总结

2. 软件安装

a) 在树莓派安装 Raspbian

使用 NOOBS 安装,下载地址:官网

b) 安装 Node.js

$ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
$ sudo apt-get install -y nodejs

c) 下载并编译 BCM2835 库 (用于驱动 DHT11)

$ wget https://www.airspayce.com/mikem/bcm2835/bcm2835-1.56.tar.gz
$ tar zxvf bcm2835-1.56.tar.gz
$ cd bcm2835-1.56
$ ./configure
$ make
$ sudo make check
$ sudo make install

d) 下载并安装 indoor-air-quality-iota 项目

$ cd ~
$ git clone https://github.com/guillengap/indoor-air-quality-and-garbage-monitoring-system.git
$ cd indoor-air-quality-and-garbage-monitoring-system
$ npm install

e) 安装 serialport 模块

$ npm install serialport

f) 安装 Arduino IDE

官网下载

3. 室内空气质量监测系统 v1

读取 DHT11 数据并通过 MAM (Masked Authenticated Messaging) 发布到 IOTA Tangle。

工作原理

a) 项目包含 3 个 JS 文件:

b) 全节点端点和侧链密钥硬编码在 JS 文件中。按 CTRL+Z 停止脚本。

c) 连接 Arduino UNO 与 DHT11 传感器

智能室内空气质量与垃圾监测系统

d) 运行 node sensor.js 测试树莓派能否读取 DHT11 数据

$ node sensor.js

若正常显示温湿度,进入下一步。

e) 运行 node mam_sensor.js 将数据存入 Tangle

$ node mam_sensor.js
智能室内空气质量与垃圾监测系统

测试节点:https://potato.iotasalad.org:14265 (更多节点见 iotasalad.org/nodes)

发送数据示例:

f) 另开终端运行 node mam_receive.js <your_root> 查看存储数据

$ node mam_receive.js AMBTIKZKEVEEQFCUGIDUOLDOXL9OZQ9GOMNBFYHVRAUCAMHDQQJBSNAMFZYRLTUVAHFDINHTTFKIPELIG
智能室内空气质量与垃圾监测系统

测试图片

智能室内空气质量与垃圾监测系统
智能室内空气质量与垃圾监测系统

4. 室内空气质量监测系统 v2

读取 DHT11、MQ-2 (液化气)、MQ-7 (一氧化碳) 三传感器数据,通过 MAM 发布到 Tangle。

工作原理

a) 项目包含 5 个文件:

b) 节点端点和侧链密钥硬编码。按 CTRL+Z 停止脚本。

c) 连接 Arduino UNO 与 DHT11、MQ-2、MQ-7 传感器

智能室内空气质量与垃圾监测系统

d) 安装传感器库 (DHT11、MQ-2、MQ7) 到 Arduino IDE

e) 上传 sensorArduino.ino 到 Arduino UNO,选择正确串口 (如 /dev/ttyACM0)

f) 运行 node listportsArduino.js 验证串口

$ node listportsArduino.js
智能室内空气质量与垃圾监测系统

g) 运行 node mam_sensorArduino.js 存储数据到 Tangle

$ node mam_sensorArduino.js
智能室内空气质量与垃圾监测系统

发送数据示例:

h) 另开终端运行 node mam_receiveArduino.js <your_root> 查看数据

智能室内空气质量与垃圾监测系统

测试图片

智能室内空气质量与垃圾监测系统
智能室内空气质量与垃圾监测系统

5. 垃圾监测系统

用 NodeMCU 读取 SRF05 超声波传感器数据,通过 MQTT 发送到树莓派,再经 MAM 存入 IOTA Tangle。

工作原理

a) 项目包含 3 个文件:

b) 节点端点和侧链密钥硬编码。按 CTRL+Z 停止脚本。

c) 连接 NodeMCU 与 SRF05 超声波传感器

智能室内空气质量与垃圾监测系统

d) 在 Arduino IDE 安装 ESP8266 开发板包

附加开发板管理器网址: https://arduino.esp8266.com/stable/package_esp8266com_index.json
工具 -> 开发板 -> 开发板管理器 -> 搜索 esp8266 -> 安装最新版
智能室内空气质量与垃圾监测系统

e) 安装 PubSubClient 库 (MQTT 客户端)

f) 在树莓派安装 Mosquitto (MQTT Broker)

$ cd ~
$ wget https://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
$ apt-key add mosquitto-repo.gpg.key
$ cd /etc/apt/sources.list.d/
$ wget https://repo.mosquitto.org/debian/mosquitto-stretch.list
$ cd ~
$ wget https://security.debian.org/debian-security/pool/updates/main/o/openssl/libssl1.0.0_1.0.1t-1+deb8u11_armhf.deb
$ sudo dpkg -i libssl1.0.0_1.0.1t-1+deb8u11_armhf.deb
$ wget https://ftp.nz.debian.org/debian/pool/main/libw/libwebsockets/libwebsockets3_1.2.2-1_armhf.deb
$ sudo dpkg -i libwebsockets3_1.2.2-1_armhf.deb
$ sudo apt-get install mosquitto mosquitto-clients
# 若出错可尝试: npm install mqtt --save
$ sudo reboot
$ mosquitto -v  # 验证版本
$ sudo /etc/init.d/mosquitto start/stop  # 启动/停止
$ ifconfig  # 查看树莓派 IP

g) 上传 trashcan.ino 到 NodeMCU,配置关键参数:

智能室内空气质量与垃圾监测系统

h) 运行 node nodemcu_mqtt_mam.js 存储数据到 Tangle

$ node nodemcu_mqtt_mam.js
智能室内空气质量与垃圾监测系统

发送数据示例:

i) 另开终端运行 node mam_receiveArduino.js <your_root> 查看数据

智能室内空气质量与垃圾监测系统

可用节点示例:https://durian.iotasalad.org:14265 (更多见 iotasalad.org/nodes)

测试图片

智能室内空气质量与垃圾监测系统
智能室内空气质量与垃圾监测系统

6. 总结

室内空气质量监测系统 v1: 运行良好,在墨西哥城某楼宇监测温湿度,使用树莓派 3B + DHT11 + JavaScript + IOTA 协议完成基础测试。

室内空气质量监测系统 v2: 增加 MQ-2 (LPG) 和 MQ-7 (CO) 传感器,模拟纽约某楼宇数据,通过 Arduino UNO + 树莓派经 MAM 上传 Tangle。适用于使用液化气场所及火灾产生一氧化碳的工业环境。

垃圾监测系统: 目标是监控柏林等智能建筑的垃圾堆积情况,通过超声波测量填充率,及时清运避免异味和卫生隐患。

代码文件

sensor.js (JavaScript) - v1 测试 DHT11
const sensor = require('node-dht-sensor');
const TIMEINTERVAL = 10; // 秒
const SENSORTYPE = 11; // DHT11
const GPIOPIN = 4; // 树莓派 GPIO 引脚

function readSensor() {
  sensor.read(SENSORTYPE, GPIOPIN, function(err, temperature, humidity) {
    if (!err) {
      console.log('temp: ' + temperature.toFixed(1) + 'C, ' + 'humidity: ' + humidity.toFixed(1) + '%');
    } else {
      console.log(err);
    }
  });
}
readSensor();
setInterval(readSensor, TIMEINTERVAL * 1000);
mam_sensor.js (JavaScript) - v1 发布到 Tangle
const sensor = require('node-dht-sensor');
const Mam = require('./lib/mam.client.js');
const IOTA = require('iota.lib.js');
const moment = require('moment');

const iota = new IOTA({ provider: 'https://potato.iotasalad.org:14265' });
const MODE = 'restricted';
const SIDEKEY = 'mysecret';
const SECURITYLEVEL = 3;
const TIMEINTERVAL = 30;
const SENSORTYPE = 11;
const GPIOPIN = 14;

let mamState = Mam.init(iota, undefined, SECURITYLEVEL);
if (MODE == 'restricted') {
  const key = iota.utils.toTrytes(SIDEKEY);
  mamState = Mam.changeMode(mamState, MODE, key);
} else {
  mamState = Mam.changeMode(mamState, MODE);
}

const publish = async function(packet) {
  const trytes = iota.utils.toTrytes(JSON.stringify(packet));
  const message = Mam.create(mamState, trytes);
  mamState = message.state;
  console.log('Root: ', message.root);
  console.log('Address: ', message.address);
  await Mam.attach(message.payload, message.address);
  return message.root;
}

function readSensor() {
  sensor.read(SENSORTYPE, GPIOPIN, async function(err, temperature, humidity) {
    if (!err) {
      const city = 'MEXICO';
      const building = '65';
      const dateTime = moment().utc().format('YYYY/MM/DD hh:mm:ss');
      const data = `{Temperature: ${temperature.toFixed(1)}°C (${(temperature.toFixed(1)*1.8)+32}°F), Humidity: ${humidity.toFixed(1)}%}`;
      const json = {"data": data, "dateTime": dateTime, "building": building, "city": city};
      const root = await publish(json);
      console.log(`City: ${json.city}, Building: ${json.building}, Time: ${json.dateTime} UTC, Data: ${json.data}, root: ${root}`);
    } else {
      console.log(err);
    }
  });
}
readSensor();
setInterval(readSensor, TIMEINTERVAL * 1000);
mam_receive.js (JavaScript) - v1 接收数据
const Mam = require('./lib/mam.client.js');
const IOTA = require('iota.lib.js');
const iota = new IOTA({ provider: 'https://potato.iotasalad.org:14265' });
const MODE = 'restricted';
const SIDEKEY = 'mysecret';

let root, key;
const args = process.argv;
if (args.length != 3) {
  console.log('Missing root as argument: node mam_receive.js ');
  process.exit();
} else if (!iota.valid.isAddress(args[2])) {
  console.log('You have entered an invalid root: ' + args[2]);
  process.exit();
} else {
  root = args[2];
}

let mamState = Mam.init(iota);
if (MODE == 'restricted') {
  key = iota.utils.toTrytes(SIDEKEY);
  mamState = Mam.changeMode(mamState, MODE, key);
} else {
  mamState = Mam.changeMode(mamState, MODE);
}

const executeDataRetrieval = async function(rootVal, keyVal) {
  let resp = await Mam.fetch(rootVal, MODE, keyVal, function(data) {
    let json = JSON.parse(iota.utils.fromTrytes(data));
    console.log(`City: ${json.city}, Building: ${json.building}, Time: ${json.dateTime} UTC, Data: ${json.data}`);
  });
}
executeDataRetrieval(root, key);
mam_sensorArduino.js (JavaScript) - v2 发布多传感器数据
const SerialPort = require('serialport');
const moment = require('moment');
const IOTA = require('iota.lib.js');
const Mam = require('./lib/mam.client.js');

const iota = new IOTA({ provider: 'https://potato.iotasalad.org:14265' });
const MODE = 'restricted';
const SIDEKEY = 'mysecret';
const SECURITYLEVEL = 3;
const PORTNAME = '/dev/ttyACM1';

const port = new SerialPort(PORTNAME, { baudRate: 9600, autoOpen: true });
const Readline = SerialPort.parsers.Readline;
const parser = port.pipe(new Readline({ delimiter: '\r\n' }));

let mamState = Mam.init(iota, undefined, SECURITYLEVEL);
if (MODE == 'restricted') {
  const key = iota.utils.toTrytes(SIDEKEY);
  mamState = Mam.changeMode(mamState, MODE, key);
} else {
  mamState = Mam.changeMode(mamState, MODE);
}

const publish = async function(packet) {
  const trytes = iota.utils.toTrytes(JSON.stringify(packet));
  const message = Mam.create(mamState, trytes);
  mamState = message.state;
  console.log('Root: ', message.root);
  console.log('Address: ', message.address);
  await Mam.attach(message.payload, message.address);
  return message.root;
}

port.on('open', showPortOpen);
parser.on('data', readSerialData);
port.on('close', showPortClose);
port.on('error', showError);

function showPortOpen() {
  console.log('Serial port open. Data rate: ' + port.baudRate);
}

async function readSerialData(data) {
  let json = {};
  const time = moment().utc().format('YYYY/MM/DD hh:mm:ss');
  const city = 'NY';
  const building = '13';
  json['time'] = time;
  json['city'] = city;
  json['building'] = building;
  json['data'] = `{${data}}`;
  console.log('json = ', json);
  const root = await publish(json);
}

function showPortClose() { console.log('Serial port closed.'); }
function showError(error) { console.log('Serial port error: ' + error); }
mam_receiveArduino.js (JavaScript) - v2 接收数据
const Mam = require('./lib/mam.client.js');
const IOTA = require('iota.lib.js');
const iota = new IOTA({ provider: 'https://potato.iotasalad.org:14265' });
const MODE = 'restricted';
const SIDEKEY = 'mysecret';

let root, key;
const args = process.argv;
if (args.length != 3) {
  console.log('Missing root as argument: node mam_receive.js ');
  process.exit();
} else if (!iota.valid.isAddress(args[2])) {
  console.log('You have entered an invalid root: ' + args[2]);
  process.exit();
} else {
  root = args[2];
}

let mamState = Mam.init(iota);
if (MODE == 'restricted') {
  key = iota.utils.toTrytes(SIDEKEY);
  mamState = Mam.changeMode(mamState, MODE, key);
} else {
  mamState = Mam.changeMode(mamState, MODE);
}

const executeDataRetrieval = async function(rootVal, keyVal) {
  let resp = await Mam.fetch(rootVal, MODE, keyVal, function(data) {
    let json = JSON.parse(iota.utils.fromTrytes(data));
    console.log(`City: ${json.city}, Building: ${json.building}, Time: ${json.time} UTC, Data: ${json.data}`);
  });
  executeDataRetrieval(resp.nextRoot, keyVal);
}
executeDataRetrieval(root, key);

原理图

原理图

智能室内空气质量与垃圾监测系统

原理图

智能室内空气质量与垃圾监测系统

原理图

智能室内空气质量与垃圾监测系统

制造工艺

  1. 树莓派打造空气质量与气象站:InfluxDB+Grafana可视化
  2. 树莓派+Nagios高效监控机房温度
  3. 树莓派与 Python 构建远程温度传感器:分步实战指南
  4. 家庭能源中心:树莓派与 Moteino 监测光伏、光热与室温
  5. 树莓派 DIY 红外运动传感器:从原理到代码的完整指南
  6. 树莓派光敏电阻日志与报警系统:低功耗光照传感器 Python 实现
  7. 树莓派多传感器温度光照监测系统:DS18B20 实战构建
  8. 基于树莓派的卫生间占用传感器:通过 Twilio 实现语音与短信提醒
  9. 树莓派传感器与执行器控制实战:加速度计、舵机与数据流
  10. 树莓派自动化气雾栽培系统:湿度传感器智能控制
  11. 树莓派家庭安防系统:PIR 运动检测 + 摄像头邮件报警
  12. 基于 Helium 网络的太阳能供电空气质量监测站:设计与部署全指南