怎麼會想做這個呢?因為一直很好奇冰箱裡的溫度是怎麼變的,先前有跟小p一起買了sensordrone,是可以測溫然後紀錄的。我就把機器直接放在冰箱裡,人在冰箱外用藍牙連線,用手機收紀錄,但是冰箱溫度太低,放進去沒多久,儀器就昏死了。
於是我現在用arduino加上一些模組來測溫囉,只有把sensor牽線放在冰箱裡,主機則都是在冰箱外,這樣就避免了機器昏死的問題。
這張圖可以看到什麼現象呢?溫度起伏得好大喔,其實因為時間軸壓縮了,所以起伏看起來就很大,如果只看幾分鐘的範圍,不太會察覺溫度有起伏喔。
就像下面這張是用手機的app來收藍牙的資料,然後即時繪圖出來的。底部的藍線一個尖峰測的是光照,一個尖峰就代表照到很短暫的光,這光哪來的呢?其實就是用一個測光的模組放在冰箱裡,只要一開門,冰箱裡的燈就會亮,我就可以記錄下來。所以就等於用測光模組去紀錄開門時間點與時間長度。
綠色的線段代表門架底部(通常拿來放牛奶)的地方,紅線則是冷藏庫上層。很明顯就看出,一開門,門架底部的溫度就上升了,但在一兩分鐘之內就會降回來。不過這前提是開門沒有開很久,最上面那張圖就可以告訴我們一些故事。開門開太久,連冷藏庫上層的溫度也會變化呢!
再來看看細部一點的圖,溫度的波動週期大約是一小時,起伏溫度大約是一兩度
有些情況,冷藏庫的溫度可能會降得更低。以致於提高了溫差。就以這兩處的溫差變化來看,小則0.5度,大則3度。看到這圖引發我更進一步想研究的興趣,我想知道壓縮機到底是在哪個時間點啟動的?這日後再作,應該可用壓電片貼在冰箱上來偵測壓縮機的振動。另外不同天的時候,溫度起伏也不太一樣,我推測跟冰箱內的食物量有關係。
這是手機和arduino連線的畫面
接出來的線就是這樣的,我相信對想做的人一點幫助也沒有,我只是想呈現一種高度亂線的美感。
除了arduino以外,用到的模組包含這些:
藍牙模組:用來將資料送出給手機接收,即時繪圖用
SD卡模組:紀錄各時間點的環境變化
RTC模組:輸出實際時間給記錄器,才知道收到的資料是什麼時間點
液晶螢幕模組:在機器上直接呈現資訊
測光模組:用來確認開門時間點和時間長
DS18B20:測溫,放冰箱冷藏庫上層和門架底部。
以下就是接線方式
溫度感測器DS18B20
函式庫
<OneWire.h> http://playground.arduino.cc/Learning/OneWire
<DallasTemperature.h> https://github.com/milesburton/Arduino-Temperature-Control-Library
接線方式
DS18B20--Arduino
Data-D2
VCC-5V
GND-GND
DATA和VCC之間再加一個4.7k的電阻
RTC時間模組ds1302
<DallasTemperature.h> https://github.com/milesburton/Arduino-Temperature-Control-Library
接線方式
DS18B20--Arduino
Data-D2
VCC-5V
GND-GND
DATA和VCC之間再加一個4.7k的電阻
RTC時間模組ds1302
函式庫
https://github.com/msparks/arduino-ds1302
https://github.com/msparks/arduino-ds1302
接線方式
ds1302--Arduino
VCC-5V
GND-GND
藍牙
HC05、HC06--Arduino
VCC-5v
GND-GND
RXD-D1
TXD-D0
CLK(sclk)--D6
DAT(IO)--D7
RST(CE)-D8
藍牙
HC05、HC06--Arduino
VCC-5v
GND-GND
RXD-D1
TXD-D0
SD卡
SD Module--Arduino
GND--GND
3V3---不接
5V--5V
CS--D10
MOSI--D11
SCK--D13
MISO--D12
GND--不用接
光線感測
VCC-5V
GND-GND
Vout-A0
液晶螢幕
函式庫 https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
接線方式
LCD--Arduino
GND--GND
VCC--5V
SDA--A4
SCL--A5
液晶螢幕
函式庫 https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
接線方式
LCD--Arduino
GND--GND
VCC--5V
SDA--A4
SCL--A5
arduino的程式
---
// 匯入程式庫標頭檔
//from http://playground.arduino.cc/Learning/OneWire
#include <OneWire.h>
//from https://github.com/milesburton/Arduino-Temperature-Control-Library
#include <DallasTemperature.h>
#include <Wire.h>
//https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <stdio.h>
//from https://github.com/msparks/arduino-ds1302
#include <DS1302.h>
const int kCePin = 8; //RST
const int kIoPin = 7; //DAT
const int kSclkPin = 6; //CLK
DS1302 rtc(kCePin, kIoPin, kSclkPin);
String printTime() {//顯示日期時間的函式
Time t = rtc.time();
char buf[30];
snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d",
t.yr, t.mon, t.date,
t.hr, t.min, t.sec);
//Serial.print(buf);
return buf;
}
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Arduino數位腳位2接到1-Wire裝置
#define ONE_WIRE_BUS 2
// 運用程式庫建立物件
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
unsigned long time;
void setup()
{
Serial.begin(9600);
pinMode(10, OUTPUT);
rtc.writeProtect(false);// 是否防止寫入 (日期時間設定成功後即可改成true)
rtc.halt(false);// 是否停止計時
Time t(2016, 06, 18, 22, 32, 00, Time::kSaturday); //年 月 日 時 分 秒 星期幾 (日期時間設定成功後即可註解掉)
//rtc.time(t);//設定日期時間 (日期時間設定成功後即可註解掉)
if (!SD.begin(10)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
sensors.begin();
//lcd.begin(16,2);
lcd.begin();
lcd.backlight();
// 初始化
}
void loop(void)
{
// 要求匯流排上的所有感測器進行溫度轉換
time = millis();
sensors.requestTemperatures();
int light = analogRead(A0);
// 參數0代表匯流排上第0個1-Wire裝置
//Serial.print(printTime());
//Serial.print(",");
//Serial.print(time/1000);
//Serial.print(",");
Serial.print("E");
Serial.print(sensors.getTempCByIndex(0));
Serial.print(",");
Serial.print(sensors.getTempCByIndex(1));
Serial.print(",");
int lightSmall = map(light,0,1023,-30,30);
Serial.println(lightSmall);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(sensors.getTempCByIndex(0));
lcd.print("C");
lcd.setCursor(0, 1);
//lcd.print("Sensor2:");
lcd.print(sensors.getTempCByIndex(1));
lcd.print("C");
lcd.setCursor(7, 0);
lcd.print(lightSmall);
lcd.setCursor(7, 1);
lcd.print(time/1000);
File dataFile = SD.open("Data.TXT", FILE_WRITE);
if (dataFile) {
dataFile.print(printTime());
dataFile.print(",");
dataFile.print(time);
dataFile.print(",");
dataFile.print(lightSmall);
dataFile.print(",");
dataFile.print(sensors.getTempCByIndex(0));
dataFile.print(",");
dataFile.println(sensors.getTempCByIndex(1));
}
dataFile.close();
delay(1000);
}
--
取出資料和繪圖時,用了文字列的awk和gnuplot
awk的目的只是為了將得到的文字檔,裡頭有個毫秒紀錄,把這個轉成比較容易理解的單位,就是小時,然後再輸出成新的文字檔。
awk 'BEGIN{FS=","};{print ($2-612823)/3600000,$3, $4 }' DATA.TXT >newData.txt
gnuPlot則是用來畫出圖形的,用了這些
set xtics ("Day0" 0,"" 12 1 ,"Day1" 24, "" 36 1 ,"Day2" 48, "" 60 1,"Day3" 72)
set xlabel "Time(Hour)"
set xrange[0:72]
set yrange[0:25]
plot "newData.txt" using 1:2 with lines lt rgb "blue" title "Top", "newData.txt" using 1:3 with lines lt rgb "red" title "Door"