# 物聯網
## 報告
1. ==**Description**==
為了隔天能夠有精神的上課,前一天睡得早
然而上課時還是感覺昏昏欲睡,甚至有點頭暈
導致我們沒辦法好好吸收上課內容
寶貴的知識就這樣被浪費掉了!
根據國內環保署所發布之室內空氣品質管理法
在室內連續測量8小時所獲得的平均值不得高於1000ppm
當二氧化碳的濃度達到1000 ppm時
人們會感到沉悶,注意力開始不集中,心悸
如果在不透氣的臥室里二氧化碳達到1000 PPM
而即使我們連續睡覺8個小時
早上起床時我們仍會感覺沒有休息好,不想起床
如果辦公室的空氣中CO2含量達到1000PPM
員工們的工作效率會下降
![](https://i.imgur.com/v8gbPvc.png)
此專案將在教室置入二氧化碳濃度感測器
監測學生上課時教室的二氧化碳濃度
透過sensor連接arduino 再將資料上傳至OM2M
雖然是內空氣品質管理法是以1000ppm為主
但我們要超前部署,在濃度到達1000ppm前就先控制
當二氧化碳濃度高於850ppm,就自動將冷氣機打開
而低於650ppm時,就自動將冷氣機關閉
2. ==**Related work**==
現在市面上的應用大多是直接將二氧化碳感測器嵌入冷氣機裡
若感測到室內二氧化碳濃度過高,才引進外部空氣
如此一來可以達到節能的效果
![](https://i.imgur.com/P2LAyk1.png)
此專案與市面上冷氣機的差別為
一開始不需要開冷氣,直到二氧化碳濃度過高再將冷氣機開啟
就像老師上課說的,學校其實開銷很大的一部份便是用電
常常沒有人在教室,但冷氣機卻是開著的
而我們的設計可以解決這種困擾
也不需要擔心無人卻自動開啟冷氣
因為在無人的室內二氧化碳濃度值約在500~700ppm
而我們設定開啟的標準為850ppm
與此同時,若我們又使用這種冷氣機,便可以更好的達到節能節電
3. ==**Actors**==
* **M2M Device**
使用設備為二氧化碳感測器(型號:MG811),它可以測量所在環境的二氧化碳濃度。
* **M2M Area Network**
連接M2M Device 和 M2M Service Platform之間的網路
* **M2M Gateway**
可以從二氧化碳感測器設備接收濃度數據並將資料傳送至OM2M
* **M2M Service Platform**
管理服務器所在的平台,Application Server使用該平台與M2M Gateway進行通訊
* **Application Server**
用來服務二氧化碳濃度感測器的Server
4. ==**Pre-conditions(前提)**==
二氧化碳感測器能夠確實偵測到濃度
並且將偵測到的資料傳送給arduino
同時arduino要可以開關冷氣機
`原本的: 健康傳感器設備能夠建立與移動設備的連接,以便將健康數據發送到M2M服務平台或應用服務器。這是第一次將移動設備與健康傳感器設備相關聯`
5. ==**Triggers**==
系統
當使用者購買產品部署於室內環境中並嘗試與arduino連線
冷氣
1. 當二氧化碳濃度>850,arduino開啟冷氣機
2. 當二氧化碳濃度<650,arduino關閉冷氣機
6. ==**Normal flow(正常流程)**==
step1. 二氧化碳濃度感測器與arduino連線
step2. 二氧化碳濃度感測器每分鐘更新一次檢測資料
並將資料傳送至arduino
step3. 用arduino將資料傳送至OM2M做紀錄
step4. 根據檢測結果的數值用arduino做出對應的動作
7. ==**Alternative flow(替代流程)**==
無
原因:
1.一次只會有一個感測器
2.每次都需要重新連線[](https://)
3.除非手動結束否則不會停止
8. High level Illustration
## Arduino的程式碼
``` c
#include <SoftwareSerial.h> //libaray of I2C
#include <SimpleDHT.h>
//正常情況下的值(接5V)
//輸出電壓 1.87~2.多
//MG_PIN 600~700
#define DH11_pin 4
#define MG_PIN A0 //定義 MG811 的 Aout 是插在哪個腳位
#define BOOL_PIN 2
#define DC_GAIN 8.5 //輸出電壓/輸入電壓 = DC_GAIN
//也就是放大率(電壓增益)
//https://www.rohm.com.tw/electronics-basics/opamps/op_what3
//因為註解跟MG_READ有點衝突,所以先以註解的內容為主
#define READ_SAMPLE_INTERVAL 50 //define how many samples you are going to take in normal operation
#define READ_SAMPLE_TIMES 5 //define the time interval(in milisecond) between each samples in
//normal operation
//當CO2濃度開始大於400ppm之後,其EMF(介於100-200mv)便開始與其濃度呈現線性的比例關係
//這裡寫得還不錯~~ 雖然我不是很懂電動式是甚麼
//https://chtseng.wordpress.com/2016/03/04/%E7%92%B0%E6%8E%A7%E7%B3%BB%E7%B5%B1v2-%E6%84%9F%E6%B8%AC%E5%99%A8%E6%A0%A1%E6%AD%A3%EF%BC%88%E4%BA%94%EF%BC%89/
#define ZERO_POINT_VOLTAGE 0.220
//當CO2濃度為400ppm時 輸入電壓的值
//因為測出來的是放大完的電壓(輸出電壓/輸入電壓 = DC_GAIN)
//所以測出的電壓/DC_GAIN = ZERO_POINT_VOLTAGE
//這個是我們自己測完以後要調的
#define REACTION_VOLTGAE (0.030) //define the voltage drop of the sensor when move the sensor from air into 1000ppm CO2
SimpleDHT11 dht11;
//int time = millis(); //millisceond
float CO2Curve[3] = {2.602, ZERO_POINT_VOLTAGE, (REACTION_VOLTGAE/(2.602-3))};
//官網給的數據圖的某的點 先叫他point1
//雖然數據圖的線是曲線,但算出來的直線會跟曲線很接近
//CO2Curve[0]: point1的x座標
//CO2Curve[1]: point1的y座標(這裡要放你真正算出來的輸入電壓)
//CO2Curve[2]: 取兩個點,算出來的斜率,slope = ( reaction voltage ) / (log400 –log1000)
//point1: (log400, 0.324),log400 = 2.602
//point2: (log1000, ?)
//原本註解寫point2: (lg4000, 0.280),但這樣的話跟上面程式碼對不起來,應該是註解寫錯
//官網的數據圖:http://image.dfrobot.com/image/data/SEN0159/CO2b%20MG811%20datasheet.pdf:
//這裡面有推倒過程,只是取的點point2跟官方給的不太一樣
//http://a-chien.blogspot.com/2016/03/arduino-mg811.html
void setup()
{
Serial.begin(9600); //UART setup, baudrate = 9600bps
//類似初始化
pinMode(DH11_pin, OUTPUT);
//設定DH11要使用的腳位
pinMode(BOOL_PIN, INPUT); //set pin to input
digitalWrite(BOOL_PIN, HIGH); //turn on pullup resistors
Serial.print("MG-811 Demostration\n");
}
void loop()
{
///// DH11 /////
byte temperature = 0;
byte humidity = 0;
if (dht11.read(DH11_pin, &temperature, &humidity, NULL)) {
//Serial.println("Read DHT11 failed.");
return;
}
Serial.print("DH11: \n");
Serial.print("溫度: ");
Serial.print(temperature);
Serial.print(" 度C\n");
Serial.print("濕度: ");
Serial.print(humidity);
Serial.println(" %\n");
///// CO2 /////
int percentage;
float volts;
// Serial.print("A0的值: ");
// Serial.print(analogRead(MG_PIN));
// Serial.print("\n");
volts = MGRead(MG_PIN);
//回推電壓的值
Serial.print( "轉回電壓: " );
Serial.print(volts);
Serial.print( "V\n" );
percentage = MGGetPercentage(volts, CO2Curve);
//回傳二氧化碳的濃度(單位是ppm)
Serial.print("CO2:");
if (percentage == -1) {
Serial.print( "<400" );
} else {
Serial.print(percentage);
}
Serial.print( "ppm" );
Serial.print("\n");
if (digitalRead(BOOL_PIN) ){
Serial.print( "=====BOOL is HIGH======" );
} else {
Serial.print( "=====BOOL is LOW======" );
}
Serial.print("\n\n\n");
delay(500);
}
float MGRead(int mg_pin)
{
int i;
float v=0;
for (i=0;i<READ_SAMPLE_INTERVAL;i++) {
v += analogRead(mg_pin); //170+
// Serial.print("A0的值: ");
// Serial.print(analogRead(mg_pin));
// Serial.print("\n");
//analogRead
//將5V的電壓 分成1024等分
//也就是將0~5V的電壓 轉換成0~1023
//0V -> 0
//5V -> 1023
delay(READ_SAMPLE_TIMES);
}
v = (v/READ_SAMPLE_INTERVAL) *5/1023 ;
// 我們讀出來的值大約是170多,假設是175
// 5:1023 = x:175
// x = 175*5 / 1023
// 轉換成公式就是 x = 讀出來的平均值*5 / 1023;
return v;
}
int MGGetPercentage(float volts, float *pcurve)
{
if ((volts/DC_GAIN )>=ZERO_POINT_VOLTAGE) {
//vlots: 測到的電壓(輸出電壓)
//DC_GAIN: 放大率
//volts/DC_GAIN: 輸入電壓
//ZERO_POINT_VOLTAGE: 400ppm時,輸入的電壓
return -1;
//因為電壓跟濃度成反比
//假設400ppm時,輸入電壓為x
//若<400ppm,輸入電壓必須>x
//所以return -1,代表濃度<400ppm
} else {
return pow(10, ((volts/DC_GAIN)-pcurve[1])/pcurve[2]+pcurve[0]);
//否則就根據公式 算出二氧化碳的濃度 並回傳
}
}
```
MG811
![](https://i.imgur.com/SViswJ8.png)
![](https://i.imgur.com/7xJq8Nr.png)
正常來講
![](https://i.imgur.com/j0Pr3SA.png)
空無一人的空間
![](https://i.imgur.com/KA3Q3G2.jpg)
充滿二氧化碳的空氣
![](https://i.imgur.com/EMqkcHu.jpg)