# 物聯網 ## 報告 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)