2013/01/06

Arduino練習:溫度感測DS18B20

Arduino自從在2011年底釋出板子Uno(義大利文之意為數字1)與開發環境1.0版之後,並沒有停下腳步,仍然持續不斷更新。(之前的版本編號從0001到0023。)

2012年7月,新板子Leonardo,比Uno更強更便宜,開發環境版本需1.0.1,開發環境開始支援多國語言(我也幫忙翻譯正體中文的部份),已經編譯過而沒改變的程式檔不會重新編譯。

2012年10月,新板子Due,這是由Arduino推出第一片以32位元ARM為核心的微控制器開發板。注意,需下載不同的軟體開發環境

2012年11月,新板子Micro,尺寸小,與Adafruit共同開發,開發環境版本需1.0.2,加入WiFi程式庫。

2012年12月,新板子Esplora,內建各種感測器與聲光輸出,包括搖桿、溫度感測器、加速度感測器、麥克風、光源感測器、等等,開發環境需版本1.0.3。

閒話說完,這篇的主角是溫度感測器DS18B20。我用的板子是Arduino Uno R3,軟體開發環境版本為1.0.3、Windows版。

這顆感測器是Dallas半導體公司的產品,Dallas公司於2001年成為Maxim的子公司,所以有些產品的品牌標誌改為Maxim,但有些仍保留Dallas的商標。

我去某電子材料行花了新台幣120元,不過到各拍賣網站會更便宜。價格差很多,有些拍賣網站要價不到50,有些網站賣的大概是改良後的新產品,居然要價兩三百。


先講講DS18B20的特色,首先,它不僅感測溫度,還會將資料數位化,這麼一來,即使DS18B20與Arduino板子離很遠,也不會影響準確度。

第二,它使用1-Wire(One-Wire)資料傳輸協定,顧名思義,資料傳輸只需一條線即可,所以在一般狀況下,需要三個腳位(電源、資料、接地),但不僅如此,1-Wire裝置裡含有電容,可經由資料線充電,所以僅需兩個腳位即可(資料+電源、接地)。前者稱為normal mode或powered mode,後者稱為parasite mode。不過既然只使用一條線進行傳輸,其中必定有複雜的技術,還好,別人已經寫好方便易用的程式庫了。

第三,每個1-Wire裝置擁有一個獨一無二的序號,所以在同一條線(匯流排)上連接多個1-Wire仍可分別彼此。(但我只有一個DS18B20。)

第四,溫度感測範圍-55°C到+125°C,一般來說夠了。

電路圖:

從Arduino板子的5V與GND接到麵包板。

DS18B20有三支接腳,根據下圖可知,當針腳朝下、我們面向平平的那一邊時(另一邊為半圓凸起),從左到右為1接地、2資料、3電源。
(如果用parasite mode,就不需要區分腳位1與3了,因為都要接地。)


底下是parasite mode的接法:

DS18B20腳位1,接地。
DS18B20腳位3,接地。

5V串聯一個4.7K ohm的上拉電阻(pull-up resistor),然後接到DS18B20腳位2。

從Arduino的數位腳位2接到DS18B20腳位2。



底下是normal mode的接法:
DS18B20腳位1,接地。
DS18B20腳位3,接5V
5V串聯一個4.7K ohm的上拉電阻(pull-up resistor),然後接到DS18B20腳位2。
從Arduino的數位腳位2接到DS18B20腳位2。



接下來在撰寫程式前,先安裝兩個程式庫OneWire與DallasTemperature。

OneWire可到此下載,我下載的是版本2.1,解壓縮後得到目錄OneWire,放到Arduino的sketchbook目錄下的libraries目錄裡。

DallasTemperature可到此下載,我下載的是版本3.7.2 Beta,解壓縮後得到目錄dallas-temperature-control,請改名為DallasTemperature,放到Arduino的sketchbook目錄下的libraries目錄裡。

註:sketchbook目錄的路徑可從「Arduino軟體開發環境-File-Preferences-Sketchbook location:」得知。若裡頭無libraries這個目錄,請自行建立。

然後重新啟動Arduino軟體開發環境,應該就能在「Sketch-Import Library...」裡看到OneWire與DallasTemperature。
底下是程式碼:

// 匯入程式庫標頭檔
#include <OneWire.h>
#include <DallasTemperature.h>

// Arduino數位腳位2接到1-Wire裝置
#define ONE_WIRE_BUS 2

// 運用程式庫建立物件
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup(void)
{
  Serial.begin(115200);
  Serial.println("Temperature Sensor");
  // 初始化
  sensors.begin();
}

void loop(void)
{
  // 要求匯流排上的所有感測器進行溫度轉換(不過我只有一個)
  sensors.requestTemperatures();

  // 取得溫度讀數(攝氏)並輸出,
  // 參數0代表匯流排上第0個1-Wire裝置
  Serial.println(sensors.getTempCByIndex(0));

  delay(1000);
}

輸出結果如下,可對著DS18B20呵氣讓溫度上升。


DallasTemperature程式庫裡還有其他功能可用:

uint8_t getDeviceCount(void),回傳1-Wire匯流排上有多少個裝置。

typedef uint8_t DeviceAddress[8],裝置的位址。
bool getAddress(uint8_t*, const uint8_t),回傳某個裝置的位址。

uint8_t getResolution(uint8_t*),取得某裝置的溫度解析度(9~12 bits,分別對應 0.5°C、0.25°C、0.125°C、0.0625°C),參數為位址。
bool setResolution(uint8_t*, uint8_t),設定某裝置的溫度解析度。

bool requestTemperaturesByAddress(uint8_t*),命令某感測器進行溫度轉換,參數為位址。
bool requestTemperaturesByIndex(uint8_t),同上,參數為索引值。

float getTempC(uint8_t*),取得溫度讀數,參數為位址。
float getTempCByIndex(uint8_t),取得溫度讀數,參數為索引值。

另有兩個靜態成員函式可作攝氏華氏轉換。
static float toFahrenheit(const float)
static float toCelsius(const float)

還可以設定警報(溫度上限、溫度下限),但我就沒試了。

有興趣的話,可看看其他我寫的關於Arduino的文章

參考資料:

184 comments:

  1. 請問
    我想把溫度顯示在七段顯示器上
    需要怎麼做

    ReplyDelete
    Replies
    1. 取得溫度後,是個float,譬如27.11,抽取出每一個位數2 7 1 1,
      然後逐一顯示在各別的七段顯示器上,

      七段顯示器可參考
      Arduino練習:seven-segment display七段顯示器與時鐘
      http://yehnan.blogspot.tw/2012/02/arduinoseven-segment-display.html

      Arduino練習:四合一的七段顯示器
      http://yehnan.blogspot.tw/2013/08/arduino_26.html


      Delete
    2. 請問 那麼void setup().void loop()是否會有兩個 還是說 直接和溫度程式碼寫在一起 因為前面是照這篇溫文章去做溫度感測的

      謝謝

      Delete
    3. setup與loop都只能有一個。必須想辦法合併。

      Delete
  2. 恩 謝謝 有問題還會來請教你

    ReplyDelete
  3. 請問一下
    我參考這網頁的程式碼
    http://et84121.blogspot.tw/2012/02/arduino.html
    同樣也適用DS18B20的
    可是我RUN都會卡在
    tempSensor.begin(2); // DS18B20接在数字I/O第12号引脚上

    有哪裡需要更改?

    謝謝

    ReplyDelete
    Replies
    1. 他用的程式庫DallasTemperature是哪一套?
      我用的必須搭配OneWire程式庫,
      #include
      #include
      // Arduino數位腳位2接到1-Wire裝置
      #define ONE_WIRE_BUS 2

      // 運用程式庫建立物件
      OneWire oneWire(ONE_WIRE_BUS);
      DallasTemperature sensors(&oneWire);

      sensors.begin(); // 此處沒有參數

      但你的程式碼是:
      tempSensor.begin(2);

      所以問題是,他用的程式庫DallasTemperature是哪一套?

      Delete
  4. 恩 謝謝
    請問
    DallasTemperature tempSensor;改成DallasTemperature sensors(&oneWire);
    那麼
    switch(tempSensor.isValid())是否改成 switch(Sensor.isValid());

    ReplyDelete
    Replies
    1. switch(Sensor.isValid());的Sensor是什麼?

      isValid是DallasTemperature物件提供的方法。

      Delete
  5. 請問可以寫一個如何讓七段顯示器顯示溫度

    照這樣一邊RUN一邊更改一邊測試的結果,我查到的那篇因該是整個都有問題吧

    ReplyDelete
    Replies
    1. 呼叫getTempCByIndex回傳攝氏溫度後,是個float,譬如27.11,抽取出每一個位數2 7 1 1,
      然後逐一顯示在各別的七段顯示器上,
      七段顯示器可參考

      Arduino練習:seven-segment display七段顯示器與時鐘
      http://yehnan.blogspot.tw/2012/02/arduinoseven-segment-display.html
      Arduino練習:四合一的七段顯示器
      http://yehnan.blogspot.tw/2013/08/arduino_26.html

      Delete
  6. switch(Sensor.isValid());不是溫度senser呼叫嗎?

    ReplyDelete
    Replies
    1. 啊,我檢查後,發現我用的DallasTemperature程式庫,並沒有isValid這個方法。

      http://et84121.blogspot.tw/2012/02/arduino.html,他的程式碼裡的reset與getTemperature,我用的DallasTemperature程式庫也都沒有。

      我猜想他的DallasTemperature程式庫可能是舊版本。

      Delete
  7. 那麼 那部份需要怎麼修改?

    裡面沒有reset與getTemperature

    需要怎麼那些?

    ReplyDelete
    Replies
    1. 呃,請你向http://et84121.blogspot.tw/2012/02/arduino.html詢問,要他的程式庫,這樣不就好了。

      如果是我用的DallasTemperature程式庫,那麼,
      因為他的程式碼會將溫度放在temp = int(tempSensor.getTemperature());裡,然後用/跟%取出每個位數,
      如果是我用的程式庫,呼叫getTempCByIndex得到float,可以乘上100,然後就可以使用他其餘關於七段顯示器的程式碼。

      Delete
  8. 恩 那可以請問一下

    float t = tempSens.getTempCByIndex(0);

    這段是什麼意思嗎?
    0代表是腳位還是別的

    ReplyDelete
    Replies
    1. 每個1-Wire裝置擁有一個獨一無二的序號,所以在同一條線(匯流排)上連接多個1-Wire仍可分別彼此。
      0代表第0個裝置,我這篇範例裡只有一個1-Wire裝置。

      Delete
  9. 請問
    是這樣嗎?
    這是我參考別人寫的
    void loop()
    sensors.requestTemperatures();

    float t = sensors.getTempCByIndex(0);
    Serial.println(t);

    int rT = (int)t;

    int units = rT % 10;

    rT = rT/10;
    int tens = rT % 10;


    delay(100);

    ReplyDelete
    Replies
    1. 呼叫Serial.print輸出就知道了。

      Delete
  10. 請問 照你的流程做了一次 可是我的溫度出現的數值都是 -35~ -33之間
    請問我是不是有漏做甚麼?

    ReplyDelete
    Replies
    1. 咳咳,我沒有千里眼,沒辦法知道有沒有漏掉什麼。:D

      Delete
  11. 不好意思
    能麻煩你看一下我的程式碼
    #include
    #include
    // Arduino數位腳位2接到1-Wire裝置
    #define ONE_WIRE_BUS 2

    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    // Lab15 使用四位數七段顯示器當計數器 V2

    // 定義七段顯示器各節段與 Arduino 的腳位對應關係
    #define A 5
    #define B 7
    #define C 4
    #define D 11
    #define E 10
    #define F 3
    #define G 6

    // 定義共陽極與 Arduino 的腳位對應關係
    #define CA1 13
    #define CA2 12
    #define CA3 9
    #define CA4 8

    // 定義七個節段的腳位,將 A, B, C, D, E, F, G 依序放入陣列
    byte segs[7] = { A, B, C, D, E, F, G };

    // 定義共陽極七段顯示器的字型(digit pattern)
    // define the LED digit patterns, from 0 - 9
    // 0 = LED on, 1 = LED off, in this order:
    // Mapping to a,b,c,d,e,f,g of Seven-Segment LED
    byte seven_seg_digits[10][7] = { { 0,0,0,0,0,0,1 }, // = 0
    { 1,0,0,1,1,1,1 }, // = 1
    { 0,0,1,0,0,1,0 }, // = 2
    { 0,0,0,0,1,1,0 }, // = 3
    { 1,0,0,1,1,0,0 }, // = 4
    { 0,1,0,0,1,0,0 }, // = 5
    { 0,1,0,0,0,0,0 }, // = 6
    { 0,0,0,1,1,1,1 }, // = 7
    { 0,0,0,0,0,0,0 }, // = 8
    { 0,0,0,1,1,0,0 } // = 9
    };

    // 定義每個七段顯示器顯示的時間 (延遲時間), 預設 1ms
    int delay_time = 1;

    int temp;

    void setup() {
    Serial.begin(9600);
    sensors.begin(); // 此處沒有參數 // DS18B20接在数字I/O第12号引脚上
    pinMode(A, OUTPUT);
    pinMode(B, OUTPUT);
    pinMode(C, OUTPUT);
    pinMode(D, OUTPUT);
    pinMode(E, OUTPUT);
    pinMode(F, OUTPUT);
    pinMode(G, OUTPUT);
    pinMode(CA1, OUTPUT);
    pinMode(CA2, OUTPUT);
    pinMode(CA3, OUTPUT);
    pinMode(CA4, OUTPUT);
    }

    void loop() {
    sensors.requestTemperatures();

    float t = sensors.getTempCByIndex(0);
    Serial.println(t);

    // cast to float (only have 2 digits to use on display)
    int rT = (int)t;

    // get units of temp
    int units = rT % 10;

    // get tens value of temp
    rT = rT/10;
    int tens = rT % 10;


    delay(100);

    }

    // 从DS18B20读取温度值
    Serial.print(tempersensors.getTemperature());
    Serial.print("C");
    Serial.println();

    temp = int(tempSensor.getTemperature());
    unsigned long startTime = millis();

    for (unsigned long elapsed=0; elapsed < 1000; elapsed = millis() - startTime) {

    // 多工掃瞄,輪流點亮個、十、百、以及千位數的七段顯示器

    // 顯示個位數
    lightDigit1(temp%10);
    delay(delay_time);
    // 顯示十位數
    lightDigit2((temp/10)%10);
    delay(delay_time);
    // 顯示百位數
    lightDigit3((temp/100)%10);
    delay(delay_time);
    // 顯示千位數
    lightDigit4((temp/1000)%10);
    delay(delay_time);

    }
    }

    // 選擇顯示的位數 (4:千、3:百、2:十、或 1:個位數)
    void pickDigit(int x) {
    digitalWrite(CA1, HIGH);
    digitalWrite(CA2, HIGH);
    digitalWrite(CA3, HIGH);
    digitalWrite(CA4, HIGH);

    switch(x) {
    case 1: digitalWrite(CA1, LOW); break;
    case 2: digitalWrite(CA2, LOW); break;
    case 3: digitalWrite(CA3, LOW); break;
    case 4: digitalWrite(CA4, LOW); break;
    }
    }

    // 點亮個位數
    void lightDigit1(byte number) {
    pickDigit(1);
    lightSegments(number);
    }

    // 點亮十位數
    void lightDigit2(byte number) {
    pickDigit(2);
    lightSegments(number);
    }

    // 點亮百位數
    void lightDigit3(byte number) {
    pickDigit(3);
    lightSegments(number);
    }

    // 點亮千位數
    void lightDigit4(byte number) {
    pickDigit(4);
    lightSegments(number);
    }

    // 點亮七段顯示器
    void lightSegments(byte number) {
    for (int i = 0; i < 7; i++) {
    digitalWrite(segs[i], seven_seg_digits[number][i]);
    }
    }
    float是截取一篇文章來的
    可是我還是run不過

    ReplyDelete
    Replies
    1. 請問run不過是什麼意思?什麼錯誤訊息?執行結果如何?

      四合一的七段顯示器,腳位很多,請檢查一下有無接錯。

      新的DallasTemperature程式庫裡應該沒有getTemperature這支方法了。

      getTempCByIndex(0)回傳的溫度是float,譬如21.22,想要顯示四個數字的話,先乘上100再轉為int,然後用%與/拿出四個位數。你的程式裡沒有乘100,

      Delete
    2. 請問
      因為我想把溫度用wifi送到手機
      是不是也要經過文字的處理?

      Delete
    3. 不懂你的意思。

      傳輸時,可選擇任何你想要的資料格式,只要兩端互相講好即可。
      譬如溫度28,可以傳一個byte代表整數,也可以傳兩個byte、分別以ASCII編碼成文字。

      Delete
    4. 因為我目前燈亮燈暗的部分
      回傳都只是純文字
      譬如說 pinState="The lights are ON !";
      然後利用 wiflyUart.print(pinState); 回傳

      但現在溫度是一個變數
      應該不能直接pinState="getTempCByIndex(0)"; 吧?
      所以想問問怎麼處理getTempCByIndex(0) ?

      您說可以傳一個byte代表整數,也可以傳兩個byte、分別以ASCII編碼成文字。
      有舉例讓我參考嗎~
      非常謝謝您耐心回答

      Delete
    5. 譬如
      uint8_t x = 32;
      那麼
      wiflyUart.write(x);
      應會送出一個byte,裡頭的值會是0x20。

      wiflyUart.print(x);
      應會送出兩個byte(以ASCII編碼),分別是0x33 0x32。

      嗯,getTempCByIndex回傳的是浮點數。

      Delete
    6. 好像有點懂,但還是不知道要怎麼處理
      假如我今天得到21.22度
      那我是應該要分別一個一個字編碼嗎?

      "getTempCByIndex(0)回傳的溫度是float,譬如21.22,想要顯示四個數字的話,先乘上100再轉為int,然後用%與/拿出四個位數。"

      如您上面所說的那樣嗎?
      那能以21.22度示範一次給我看嗎..
      抱歉對於這塊還是新手不太懂
      謝謝您

      Delete
    7. > 要分別一個一個字編碼嗎?
      由你決定。一個兩位數的整數(例32),可以採用一個位元組的整數格式來儲存、傳輸,也可以採用兩個位元組的ASCII文字編碼。浮點數也可類推。

      > 以21.22度示範
      找float與字串的轉換函式,把浮點數轉成字串,然後就能呼叫wifly.print印出、輸出、傳輸了吧。另一端收到字串後,則要逆轉回浮點數。

      Delete
  12. 那個,我直接複製貼上你的程式碼,接法是用parasite mode,可是顯示出來的數值一直是-127.0?不管用摸的還是用吹的都還是-127??有那麼冷嗎

    ReplyDelete
    Replies
    1. DS18B20的溫度感測範圍是-55°C到+125°C,不應該出現-127,很奇怪。

      嗯,哪裡出問題了呢?

      Delete
    2. 阿...剛又重新檢查了一次 原來是電阻接成4.7歐姆了 抱歉打擾了^ ^"q
      謝謝您的網誌,有很多很有用的資訊,受益良多:D

      Delete
    3. 解決了。恭喜。

      Delete
  13. 你好,我再匯入DallasTemperature的時候發生問題
    我的程式碼就只有
    #include

    但是卻跑出一堆error
    In file included from sketch_may14a.ino:1:
    C:\Program Files (x86)\Arduino\libraries\DallasTemperature/DallasTemperature.h:64: error: expected `)' before '*' token
    C:\Program Files (x86)\Arduino\libraries\DallasTemperature/DallasTemperature.h:222: error: ISO C++ forbids declaration of 'OneWire' with no type
    C:\Program Files (x86)\Arduino\libraries\DallasTemperature/DallasTemperature.h:222: error: expected ';' before '*' token
    請問是為甚麼啊??

    ReplyDelete
  14. 試試加入
    #include OneWire.h
    #include DallasTemperature.h
    (標頭檔要以角括號包起來)

    ReplyDelete
  15. Anonymous26/5/14 19:23

    請問這溫度感測準嗎? 因為DHT11很不準,再想要買哪個
    或是您建議一個?

    ReplyDelete
    Replies
    1. DHT22比DHT11更好,DS18B20屬於數位溫度感測器,
      很不準?都要自己試試看才知道符不符合需求吧。
      Good luck.

      Delete
    2. 聽說MCP9808很準,但我沒用過。

      Delete
  16. 您好,我嘗試要做一個溫度感測器,並將數值顯示在LCD及網頁上,但是顯示出來的數值一直是-127.0,可以請您幫我看一下問題出在哪好嗎? 我的程式放在下面的聯結,感謝Orz ~ https://www.facebook.com/notes/%E9%99%B3%E4%BF%8A%E8%88%88/18b20-%E6%BA%AB%E5%BA%A6%E6%84%9F%E6%B8%ACfor-arduino-mega-2560/733717286695942

    ReplyDelete
    Replies
    1. 呼叫DallasTemperature::getTempC時,若沒辦法讀取、發生錯誤,它會回傳「-127」。所以,你應該檢查溫度感測器的線路是否正確、程式碼裡API的用法與參數是否對了。
      可以的話,把LCD與Ethernet的部份通通先拿掉,先搞定溫度感測器。

      另外,
      void getTemperature(DeviceAddress DeviceAddress) { ... }
      為什麼參數型別與名稱都是DeviceAddress呢?這樣會搞混吧。

      Delete
    2. 謝謝您,溫度感測器的線路,我測試過並在另一個程式跑過確定沒問題且溫度都可以讀出來,但是整合在一起的時候就讀不出來了.請問void getTemperature(DeviceAddress DeviceAddress) { ... } 這邊我要如何修改比較好呢? 很抱歉,我對程式的部分真的一知半解,請您指導~

      Delete
    3. 可以的話,把LCD與Ethernet的部份通通先拿掉,先搞定溫度感測器,然後再逐一加入。
      譬如http://pastebin.com/fbizk3Ze

      你的程式我看了,光用看的看不出問題。(沒真正跑,不敢肯定。)

      另一支程式?跟這支有何不同?確定兩支程式裡關於溫度感測器的部份是一樣的嗎?

      void getTemperature(DeviceAddress DeviceAddress) { ... }的部份沒問題,只是建議而已。

      Delete
    4. 謝謝您,我是用底下這程式跑過,可以正確讀到溫度數值,我也會依照您的建議在試試看,非常感謝~

      #include
      #include

      OneWire oneWire (46);
      DallasTemperature sensors(&oneWire);


      void setup()
      {
      // start serial port
      sensors.begin();
      Serial.begin(57600);
      }

      void loop ()
      {
      sensors.requestTemperatures();
      float currentTemp0;
      currentTemp0 = sensors.getTempCByIndex(0);
      float currentTemp1;
      currentTemp1 = sensors.getTempCByIndex(1);

      Serial.print("Temp0 = ");
      Serial.print("\t");
      Serial.println(currentTemp0,2);

      Serial.print("Temp1 = ");
      Serial.print("\t");
      Serial.println(currentTemp1,2);

      delay(1000);
      }

      Delete
    5. 你這份程式跟之前的不太一樣,使用getTempCByIndex。

      Delete
    6. 您真的太神了,馬上抓到問題,我嘗試用您的程式去執行,果然問題發生在溫度讀取這一段,監控視窗一直跑出-127.00,可以請您指導我這一段要如何寫嗎?

      Delete
    7. 原本程式使用
      DeviceAddress insideThermometer = { 0x28, 0x98, 0x10, 0x4E, 0x05, 0x00, 0x00, 0xB2 };
      DeviceAddress outsideThermometer = { 0x28, 0xB9, 0xDD, 0x4D, 0x05, 0x00, 0x00, 0x75};
      或許這些是錯的吧。

      既然另一個程式可以正常抓到溫度,那麼就改用它的寫法吧。
      要改寫原本程式的void getTemperature(DeviceAddress DeviceAddress){...}部分,原本程式使用getTempC,現在需要改寫、改用getTempCByIndex。

      Delete
    8. 問題以解決了,原來每一顆DS18B20都有一組code需要工具程式去把它讀出來,再放到程式跑.真的很謝謝您的耐心指導~

      Delete
    9. 那是OneWire裝置的識別碼。
      在程式裡寫死識別碼的話,不太好吧,換新的感測器的話,不就還要改程式。
      還是改用getTempCByIndex之類的API比較好。

      Delete
  17. 請問 :

    看了版主輸出畫面其溫度讀取值可以精確到小數2位
    但是我的輸出結果卻是以0.25增減 (程式碼為版主的)
    若以 dallas_temperature_control\examples\Multiple的程式碼跑
    則以0.5增減
    請問為何會有此差異呢?
    抱歉因我是 Arduino 的初學者所以提此問題

    ReplyDelete
    Replies
    1. DS18B20可以設定解析度,可設為9, 10, 11, or 12 bits,預設是12 bits。
      分別對應到0.5°C, 0.25°C, 0.125°C, and 0.0625°C。

      Multiple的解析度設為9 bits,所以是0.5°C。

      至於你的輸出結果以0.25增減,為何如此我就不知道了。

      Delete
    2. 感謝 yehnan 回覆

      問題解決了
      我加了以下設定
      sensors.setResolution(DS18B20 Address, 12)
      解析度終於可以達到 0.0625°C。

      Delete
  18. C:\Program Files (x86)\Arduino\libraries\DallasTemperature\DallasTemperature.cpp:9:26: error: WConstants.h: No such file or directory
    請問這是甚麼地方出了差錯呢?

    ReplyDelete
  19. WConstants.h是Arduino 1.0版之前才有的檔案。

    原因大概是...,你沒有使用Arduino IDE?

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. 我如果要有溫度上限警報 要如何撰寫程式

      Delete
    3. 請參考拙作
      Arduino輕鬆入門:範例分析與實作設計
      http://yehnan.blogspot.tw/2014/02/arduino_21.html
      的第7章第1節 數位溫度感測器DS18B20,
      裡頭有設定溫度的上限與下限,超過時便發出警報。
      其中的程式檔在
      https://github.com/yehnan/arduino_book_yehnan/tree/master/sketchbook/ch07_DS18B20_alarm

      Delete
  20. 謝謝喔 小弟我只是個高工生 還有點看不懂

    ReplyDelete
  21. 你好 我想請問如果不用onewaire 可以寫得出來嗎?
    我目前使用的是energia 搭配launchpad msp430

    ReplyDelete
    Replies
    1. PS 我沒用過MSP430、Energia。

      DS18B20的溝通介面就是One Wire,你應該要找出MSP430+Energia平台上的One Wire程式庫。上網搜尋後,http://forum.43oh.com/topic/2799-onewire-energia-library/ 好像是有,但又好像有問題,不清楚。

      也有人自己搞,http://www.smallbulb.net/2012/238-1-wire-and-msp430 ,等於是自己實作One Wire介面、自己寫程式與DS18B20溝通。

      Delete
  22. 請問一下如果我要把溫控開關跟風扇結合該如何設定在某一個溫度以上轉動某一個溫度已下關閉?

    ReplyDelete
    Replies
    1. 你說的溫控開關是?

      DS18B20可以設定溫度上下限,若超過便執行某函式,
      請參考拙作 Arduino輕鬆入門:範例分析與實作設計
      http://yehnan.blogspot.tw/2014/02/arduino_21.html
      的7.1節,裡頭有使用此功能。

      風扇的話,應該要使用繼電器作為電子開關。

      Delete
  23. 請問一下我要設定溫度上限,然後啟動繼電器使無熔絲開關跳脫該加入什麼程式碼?
    我要做的是溫度上限攝氏40度,然後啟動繼電器使無熔絲開關跳脫。

    ReplyDelete
    Replies
    1. 請參考拙作 Arduino輕鬆入門:範例分析與實作設計
      http://yehnan.blogspot.tw/2014/02/arduino_21.html
      裡的7.1小節,程式碼7.2會設定溫度上下限,超過便從蜂鳴器發出警告聲響。

      Delete
  24. 你好,我與前面某位一樣遇到了溫度是-35度的問題
    程式碼與線的接法都是按照上面所說
    想請問可能是什麼地方出了問題?

    ReplyDelete
    Replies
    1. 可能出問題的地方就是接線、零件、程式碼。:D

      隔空抓藥甚為困難,允許的話請提供電路接線的照片、完整的程式碼。

      Delete
  25. This comment has been removed by the author.

    ReplyDelete
  26. Anonymous10/6/15 08:39

    你好,我手上目前的溫度感測器是MAX6675
    http://ecx.images-amazon.com/images/I/51MvTN21MzL._SY355_.jpg

    我用的是這個 library:https://github.com/adafruit/MAX6675-library

    我是想用在LinkIt ONE上,可是讀到的 bit 都是1,造成感測出來的溫度都是1023度
    但是我在Arduino上用就很正常,不知道是什麼問題。

    請問 DS18B20 可以用在LinkIt ONE上嗎?

    謝謝

    ReplyDelete
    Replies
    1. > 請問 DS18B20 可以用在LinkIt ONE上嗎?
      不知道。這幾天大概也沒時間測試。

      連讀取DHT11都會出問題了,
      https://labs.mediatek.com/forums/posts/list/461.page
      我猜想DS18B20(1-Wire)、MAX6675(SPI),應該也會出現類似的問題。

      如果官方論壇沒回應的話,到facebook試試看,有些MTK的工程師在上面。

      Delete
    2. This comment has been removed by the author.

      Delete
    3. 我自製的library LinkIt One for DHT11, DHT21, DHT22 可以測試看看
      https://labs.mediatek.com/forums/posts/list/3389.page#p6359
      GitHub: https://github.com/LinWeiTing/LDHT

      Delete
    4. 太棒啦。
      謝謝。

      Delete
    5. 最近在整理 linkit one DS18B20 系列溫控的library 到時還請葉老師幫忙測試推廣。

      Delete
  27. This comment has been removed by the author.

    ReplyDelete
  28. 葉難 老師你好
    想請問一下有關於kepad輸入的問題
    我想利用kepad輸入一個3位數的數值
    但是目前寫出來的程式
    char key = keypad.getKey();
    我在 kepad 上按下任一鍵 LCD 就會馬上顯示出來
    我想設置一個變數,能儲存3位數再print 或是當我按下#就完成輸入

    有試著更改程式(如下)但始終無效,還望老師能撥空幫忙,感激不盡,3Q
    int key1 = keypad.getKey( );
    int key2 = keypad.getKey( );
    int key3 = keypad.getKey( );
    int keyin = (key1*100 + key2*10 + key3) ;
    char key = keyin ;

    ReplyDelete
    Replies
    1. char key = keypad.getKey();
      根據key的值可判斷按下的是哪一個鍵。

      請參考我寫的Arduino入門書的4.7節。
      Arduino輕鬆入門:範例分析與實作設計,
      http://yehnan.blogspot.tw/2014/02/arduino_21.html

      Delete
    2. thanks 我再試試看~

      Delete
  29. 你好
    我想讓兩個以上的溫度感應器同時偵測
    偵測到最高溫度的感應器亮燈

    有可能在Arduino上同時顯示多個溫度變化狀況嗎?

    ReplyDelete
    Replies
    1. 可以。

      每個1-Wire裝置擁有一個獨一無二的序號,所以在同一條線(匯流排)上連接多個1-Wire仍可分別彼此,在程式裡可指定。

      Delete
  30. 謝謝你的回復
    目前使用的是DS18B20

    #include
    #include
    #define ONE_WIRE_BUS A0
    #define ONE_WIRE_BUS A1
    OneWire oneWire(ONE_WIRE_BUS);
    OneWire twoWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    int a=0,b=0;
    const int led[]={8,9,10,11,12};
    int i;
    int j=0;
    void setup(void)
    {
    Serial.begin(115200);
    Serial.println("Temperature Sensor");
    pinMode(13,OUTPUT);
    sensors.begin();
    for(i=0;i<5;i++)
    {
    pinMode(led[i],OUTPUT);
    }
    }

    void loop(void)
    {
    sensors.requestTemperatures();
    a=sensors.getTempCByIndex(0);
    Serial.println(sensors.getTempCByIndex(0));
    b=sensors.getTempCByIndex(1);
    Serial.println(sensors.getTempCByIndex(1));

    if(a>b)
    {
    digitalWrite(13,HIGH);
    for(int k=0;k<5;k++)
    {
    digitalWrite(led[k],HIGH);
    delay(100);
    digitalWrite(led[k],LOW);
    }
    }
    else
    {
    digitalWrite(13,HIGH);
    for(int k=5;k>0;k--)
    {
    digitalWrite(led[k],HIGH);
    delay(100);
    digitalWrite(led[k],LOW);
    }
    }

    }

    這是目前使用的程式 如果a感應溫度比b高 燈就會順著亮 反之
    但是現在只能順著亮 而顯示的溫度兩行都一樣
    請問是哪邊打錯了

    ReplyDelete
  31. #define ONE_WIRE_BUS A0
    #define ONE_WIRE_BUS A1
    你把兩個DS18B20接在不同腳位?應該不是這樣接吧,應接在同一條線路上。

    另外,上面的兩個常數定義,名稱重複了。

    ReplyDelete
  32. 既然顯示的溫度兩行都一樣,那就代表a等於b,也就是會執行else的部份。

    ReplyDelete
  33. 成功了!非常感謝你!

    ReplyDelete
  34. This comment has been removed by the author.

    ReplyDelete
  35. 我想請問一下各前輩,我想寫一個高水停泵,低水開泵,是否一定要兩個泵來控制,兩组感應控制,可否兩個感應控制一個泵,如可以,可否教我寫,謝謝!

    ReplyDelete
    Replies
    1. > 可否兩個感應控制一個泵
      可以。

      > 可否教我寫
      不行。

      Delete
  36. 葉難老師你好,
    小弟最近把電腦重灌後,之前可以使用的程式碼現在卻無法上傳至板子上板子mega2560
    arduino版本 1.6.6
    顯示的錯誤訊息如下
    java.io.IOException: Cannot run program "{runtime.tools.avrdude.path}/bin/avrdude": CreateProcess error=2, 系統找不到指定的檔案。

    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)

    at processing.app.helpers.ProcessUtils.exec(ProcessUtils.java:26)

    at cc.arduino.packages.Uploader.executeUploadCommand(Uploader.java:113)

    at cc.arduino.packages.uploaders.SerialUploader.uploadUsingPreferences(SerialUploader.java:157)

    at cc.arduino.UploaderUtils.upload(UploaderUtils.java:78)

    at processing.app.Sketch.upload(Sketch.java:1178)

    at processing.app.Sketch.exportApplet(Sketch.java:1152)

    at processing.app.Sketch.exportApplet(Sketch.java:1124)

    at processing.app.Editor$DefaultExportHandler.run(Editor.java:2452)

    at java.lang.Thread.run(Thread.java:745)
    Caused by: java.io.IOException: CreateProcess error=2, 系統找不到指定的檔案。

    at java.lang.ProcessImpl.create(Native Method)

    at java.lang.ProcessImpl.(ProcessImpl.java:386)

    at java.lang.ProcessImpl.start(ProcessImpl.java:137)

    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)

    ... 9 more

    不知道是哪邊設定出錯了呢? 還望老師有空能幫我解答 謝謝

    ReplyDelete
    Replies
    1. Arduino IDE找不到燒錄工具avrdude。在目錄裡有avrdude.exe這支檔案嗎?
      你安裝1.6.6後,沒有改任何東西吧?

      作業系統是什麼?哪個版本?

      Delete
  37. 作業系統為 WIN7 旗艦版
    安裝1.6.6之後除了選擇板子MEGA2560之外 並沒有修改任何東西
    在目錄中
    C:\Program Files (x86)\Arduino\hardware\tools\avr\bin
    有 avrdude.exe
    感謝老師抽空幫忙

    ReplyDelete
    Replies
    1. 嗯,關閉win 7的UAC,或許有用。

      Delete
  38. 剛剛檢查了一下,發現UAC本來就是關閉的 那我再找方法試試看好了, 謝謝葉難老師

    ReplyDelete
    Replies
    1. 如果是linux或mac os x,有可能是avrdude.exe沒有執行權限,須自行手動設定,至於win7我就不曉得了。

      Delete
  39. 如何下載onewire函數庫

    ReplyDelete
    Replies
    1. 若Arduino IDE版本是1.6.2之後的,直接到選單裡的Library Manager,搜尋one wire,找到後按下Install便會自動下載安裝。
      若Arduino IDE是之前的版本,自己到https://github.com/PaulStoffregen/OneWire下載,解壓縮、放到Arduino IDE目錄下的libraries子目錄,重開IDE,如此即可。

      Delete
  40. 可以請問一下如何把ad7417這顆ic
    整合到Arduino版上嗎
    實體電路板已經LA好了
    差程式部分來驗證 不過本身算程式新手 不知道從何做起

    ReplyDelete
    Replies
    1. 我這篇使用DS18B20,然後使用兩套程式庫OneWire與DallasTemperature,然後才是上層的Arduino程式。
      你使用AD7417,溝通介面是I2C,需使用Arduino內建的Wire程式庫,接下來我上網找,並未找到AD7417的程式庫,應該要自己研讀datasheet,自己撰寫。
      然後再撰寫上層的應用程式。

      Delete
  41. 那請問另外一個函數庫也可以在ARDUINO裡面找到嗎?

    ReplyDelete
    Replies
    1. Arduino不會包含特定晶片的程式庫,除非該晶片非常有名、廣受採用。

      Arduino紅了,所以很多熱心人士都會貢獻,撰寫某晶片/功能的程式庫。
      但我上網找AD7417,沒找到,是不是這顆晶片太冷門了?沒人用?

      Delete
  42. 我的適用ds18b20,我用你的程式,可是監測時一直出現<正方形的符號

    ReplyDelete
  43. 抱歉,我剛剛忘了改鮑率

    ReplyDelete
  44. 請問一下 如果我需要輸出的溫度當作條件 我從那個地方來弄?

    ReplyDelete
    Replies
    1. 不懂你的問題。

      Delete
    2. 他說得應該是利用ds18b20的溫度控制東西啟閉吧

      Delete
    3. 或許吧,但也沒描述清楚。

      to 哈哈: 呵,也還特地來留言啊。

      Delete
  45. 請問為甚麼我監控螢幕上過一段時間就會又跳出Temprature Seneor。
    #include
    #include

    // Arduino數位腳位2接到1-Wire裝置
    #define tempsensor 6
    #define fan 7
    // 運用程式庫建立物件
    OneWire oneWire(tempsensor);
    DallasTemperature sensors(&oneWire);
    boolean fanState=LOW;
    void setup(void)
    {
    Serial.begin(115200);
    Serial.println("Temperature Sensor");
    // 初始化
    sensors.begin();
    pinMode(fan,OUTPUT);
    digitalWrite(fan,fanState);
    }

    void loop(void)
    {if(sensors.getTempCByIndex(0)>=29.00){
    digitalWrite(fan,HIGH);}
    else
    {digitalWrite(fan,LOW);}
    // 要求匯流排上的所有感測器進行溫度轉換
    sensors.requestTemperatures();

    // 取得溫度讀數(攝氏)並輸出,
    // 參數0代表匯流排上第0個1-Wire裝置
    Serial.println(sensors.getTempCByIndex(0));

    delay(1000);
    }
    這是我的程式,我是用溫度感測器的溫度當開關

    ReplyDelete
    Replies
    1. > 過一段時間就會又跳出Temprature Seneor
      多久?

      > 又跳出Temprature Seneor
      你是在setup()裡印出Temprature Seneor,
      從程式看不出來為什麼會重置。

      Delete
  46. 請問,如果要同時在一塊板子上,用2個以上的溫度感應,該如何做?

    ReplyDelete
    Replies
    1. 每個1-Wire裝置擁有一個獨一無二的序號,所以在同一條線(匯流排)上連接多個1-Wire仍可分別彼此。

      在程式裡,傳入不同索引值,取得不同DS18B20的量測值
      sensors.getTempCByIndex(0)

      或者,可先查知每個1-Wire裝置的位址,請參閱
      http://arduino-info.wikispaces.com/Brick-Temperature-DS18B20#mult

      Delete
  47. 老師好
    我買了DS18S20來練習,使用老師的程式碼
    也下載了OneWire & DallasTemperature
    Compile的時候出現以下錯誤訊息
    WARNING: Category '' in library OneWire is not valid. Setting to 'Uncategorized'
    請問老師這樣使匯入參數檔的時候有錯嗎?
    要怎麼排除這個警告

    ReplyDelete
    Replies
    1. 你下載的OneWire程式庫,裡頭有支檔案library.properties,
      修改category那一行,改成Communication。

      如沒有這支檔案,忽視該警告即可;或者下載最新版的程式庫、以及Arduino IDE。

      Delete
    2. 我有library.properties
      裡面沒有看到category
      內容如下
      name=OneWire
      version=2.3
      author=Jim Studt, Tom Pollard, Robin James, Glenn Trewitt, Jason Dangel, Guillermo Lovato, Paul Stoffregen, Scott Roberts, Bertrik Sikken, Mark Tillotson, Ken Butcher, Roger Clark, Love Nystrom
      maintainer=Paul Stoffregen
      sentence=Access 1-wire temperature sensors, memory and other chips.
      paragraph=
      url=http://www.pjrc.com/teensy/td_libs_OneWire.html
      architectures=*

      目前使用Arduino 1.6.7

      Delete
    3. 那就自己加。
      category=Communication

      Delete
    4. 感謝葉老師
      加入category=Communication
      真的就沒有WARNING的問題了

      Delete
    5. 到https://github.com/PaulStoffregen/OneWire下載OneWire最新版2.3.2,已經加上該行。

      Delete
  48. 老師您好,我想請教您如何把ds18b20溫度感測器的資料寫進webduino的網頁當中?

    ReplyDelete
    Replies
    1. 沒用過webduino。
      可以參考官方文件
      https://webduino.io/tutorials/tutorial-10-temperature-humidity-sensor.html

      Delete
  49. 葉難老師您好 , 最近以PID程式控制PWM輸出值使加熱棒升溫至指定溫度(搭配DS1821)
    當PID 控制一個加熱棒時 約10分鐘便能使加熱棒穩定輸出
    現在遇到一個問題,控制兩組加熱棒時,其PID輸出值便會互相影響 (當溫度超過指定溫度也不會停止輸出)
    以下為程式片段
    #include
    #include ...
    ...

    void setup() {

    ds.reset();
    ds1.reset();

    Input = analogRead(0);
    Setpoint = analogRead(0);
    myPID.SetMode(AUTOMATIC);
    }...
    ...

    highResTemp = ( highResTemp - 0.5);
    t1 = highResTemp;
    Serial.println(highResTemp);
    Input = t1;
    Setpoint = h1;
    myPID.Compute();
    analogWrite(heaterPin_1, Output); ...
    ...

    highResTemp = ( highResTemp - 0.5 );
    t2 = highResTemp;
    Input = t2;
    Setpoint = h2;
    myPID.Compute();
    analogWrite(heaterPin_2, Output);

    想請老師幫忙是否有方法能利用同個pid程式(library) 達成控制兩組加熱棒
    不知老師是否方便寄封E-mail給我 好傳給老師完整之程式 burning0830@gmail.com
    再次感謝老師多次的幫忙 謝謝!!

    ReplyDelete
  50. email不方便直接給你。

    程式碼可貼到pastebin.com

    ReplyDelete
    Replies
    1. 嗯,大概看了一下。

      你應該產生兩個PID物件吧,myPID與myPID2,
      分別控制兩個東西。

      Delete
  51. 那個,我用Amaba,然後直接複製貼上你的程式碼,接法是用parasite mode,可是顯示出來的數值一直是-127.0,是哪裡錯了呢?
    已經有確認過電路沒接錯了...可是就是跑不出來...

    ReplyDelete
    Replies
    1. 有人成功
      https://books.google.com.tw/books?id=xQOYCwAAQBAJ&pg=PA184&lpg=PA184&dq=ameba+ds18b20&source=bl&ots=Tm3gB60Ja4&sig=yAJKjTz0xZVp1uc-AdA6x4GmtR4&hl=zh-TW&sa=X&ved=0ahUKEwibxJPTu4nNAhUENJQKHZYlBngQ6AEIIzAA#v=onepage&q=ameba%20ds18b20&f=false

      -127的意思應該是:DS18B20沒有正常收到你發出的指令,不是電子線路有問題,就是訊號timing有問題。

      如果parasite mode不行,改成一般模式吧。

      把4.7k電阻換成2.2k試試。

      Delete
  52. 葉難老師您好 ,我想請教你DS18B20感測器所顯示的溫度是否可以微調?

    ReplyDelete
    Replies
    1. DS18B20的解析度,可調整,有9、10、11、12位元可選。
      請參考 http://www.homautomation.org/2015/11/17/ds18b20-how-to-change-resolution-9101112-bits/

      至於顯示部分,當你拿到數值後,要怎麼顯示就是你的事情了。

      Delete
  53. 請問一下,我用的是AOSONG AM2302溫溼度感測器,線路接法跟你這邊一樣,我將你的程式碼放到arduino測試,讀取的值卻都是白色框框,請問是哪裡需要修改嗎?

    ReplyDelete
    Replies
    1. > AM2302溫溼度感測器,線路接法跟你這邊一樣
      不對,不一樣。

      這篇的DS18B20走的是1-Wire介面,
      AM2302走的是一套自訂介面,可用https://github.com/adafruit/TinyDHT這套程式庫讀取。

      Delete
    2. 電路圖請參考
      http://www.electroschematics.com/11291/arduino-dht22-am2302-tutorial-library/

      Delete
  54. This comment has been removed by the author.

    ReplyDelete
  55. 我剛剛發了好幾次怎麼都消失了......
    我現在的程式是這樣:
    int potPin = 2;
    int analog = 2;
    void setup() {
    Serial.begin(9600);
    }

    void loop() {
    analog = analogRead(potPin);
    Serial.println(analog);
    delay(2000);
    }
    現在可以讀到值了,可是讀到的值我完全找不出邏輯性
    數值大約都是400左右,跟我用十進位測試時的數值一樣
    http://www.aosong.com/en/products/details.asp?id=117
    http://oao.no/wpe/2013/09/arduino-library-for-the-am2302-sensor/
    上面一個是商品的介紹,另一個是其他人的說明
    可是我還是看不太懂輸出的部分,我想要的是溫度跟濕度值
    是我程式哪裡沒寫好嗎?

    ReplyDelete
    Replies
    1. 你的程式只是讀取一般類比訊號,
      AM2302是輸出它自訂的一套數位訊號,需使用程式庫讀取。
      你給的網址
      http://oao.no/wpe/2013/09/arduino-library-for-the-am2302-sensor/
      裡頭有提供程式庫,另外網路上找找,也有很多其他人撰寫的程式庫,可讀取AM2302。

      可使用這一套https://github.com/adafruit/TinyDHT
      裡頭有範例
      https://github.com/adafruit/TinyDHT/blob/master/examples/TinyDHT_TestUno.ino
      建立DHT物件後,呼叫readHumidity與readTemperature即可讀取濕度與溫度。

      Delete
    2. 非常謝謝你!
      我已經成功讀取溫溼度值了
      我真的要好好加強英文閱讀的能力,不然很多資源都沒辦法有效利用
      謝謝你詳細的解說,萬分感激!

      Delete
  56. 葉老師,您好,請教一下,我想利用DS18B20作溫度偵測(偵測範圍:0~50度,板子為NANO,類比訊號輸出(0~5V),但是輸出給PLC類比模組的訊號,PLC無法解析(數值一直跳動),後來加上RC(220歐姆+10uF)濾波迴路後有改善,是因為D I/O第3腳位為PWM訊號輸出的關係嗎?那麼可以由A I/O輸出嗎?或者就加濾波迴路(怎麼匹配較好?),還是有其他建議?謝謝!!
    // 匯入程式庫標頭檔
    #include
    #include
    // Arduino數位腳位2接到1-Wire裝置
    #define ONE_WIRE_BUS 2
    // 運用程式庫建立物件
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    int temPin = 3;
    int temp;
    void setup(void)
    {
    Serial.begin(38400);
    sensors.begin();
    pinMode(temPin, OUTPUT);
    }
    void loop(void)
    {
    // 要求匯流排上的所有感測器進行溫度轉換
    sensors.requestTemperatures();
    // 取得溫度讀數(攝氏)並輸出,
    // 參數0代表匯流排上第0個1-Wire裝置
    Serial.println(sensors.getTempCByIndex(0));
    temp=sensors.getTempCByIndex(0)*20.46;
    // 量測範圍0~50度換算數值
    if (led<=0) {led=0;}
    analogWrite(temPin,temp);
    }

    ReplyDelete
  57. analogWrite不是類比輸出,而是PWM輸出,其電壓會在5V與0V之間跳動。

    一般Arduino板子沒有類比輸出。

    請參閱
    https://arduino-info.wikispaces.com/Analog-Output
    的Creating a True Analog Signal

    ReplyDelete
  58. 加上RC濾波迴路與LM358之後,問題已經解決了,謝謝!!

    ReplyDelete
  59. 請問arduino要怎麼連接資料庫在網頁上執行

    ReplyDelete
    Replies
    1. 您問的問題很大,不是可在留言區裡回答的問題,
      請自行使用關鍵字搜尋,找找有無分享文章,
      找找有無介紹書籍。

      Delete
  60. 想請問一下DS1821的電路和這個是一樣的嗎

    ReplyDelete
    Replies
    1. 電路應該一樣。
      但我用的程式庫DallasTemperature,不支援DS1821。

      請參考http://forum.arduino.cc/index.php?topic=104594.0

      Delete
  61. 想請問一下 我用他的程式碼 真的有顯示出溫度了
    但是它是顯示華氏 我要怎麼改成攝氏溫度呢?
    謝謝

    ReplyDelete
    Replies
    1. 我這篇文章不就是輸出攝氏溫度嗎?

      Delete
    2. 我也是用DS1821
      程式碼是上面網址的這些

      #include
      #include

      OneWire ds(10); // on pin 10

      void setup(void) {
      Serial.begin(9600);
      ds.reset();

      }

      unsigned int readBytes(int count)
      {
      unsigned int val = 0;
      for (int i = 0; i < count; i++)
      {
      val |= (unsigned int)(ds.read() << i * 8);
      }
      return val;
      }

      void loop(void) {
      byte temp_read = 0;
      unsigned int count_remain = 0;
      unsigned int count_per_c = 0;
      byte configuration_register = 0;

      ds.reset();
      ds.write(0xEE); //Start Converting the temperatures

      do {
      delay(1);
      configuration_register = 0;
      ds.reset();
      ds.write(0xAC);

      // Read the configuration Register from the DS1821
      configuration_register = readBytes(1);
      } while ((configuration_register & (1 << 7)) == 0); // If Bit #8 is 1 then we are finished converting the temp


      // Get Temp
      ds.reset();
      ds.write(0xAA);
      temp_read = readBytes(1); ;

      // Get Count Remaining
      ds.reset();
      ds.write(0xA0);
      count_remain = readBytes(2);

      // Load The Counter to populate the slope accumulator
      ds.reset();
      ds.write(0x41);

      // Read Count Per Deg
      ds.reset();
      ds.write(0xA0);
      count_per_c = readBytes(2);

      // If we are reading above the 200 mark then we are below 0 and need to compensate the calculation
      if (temp_read >= 200) temp_read -= 256;

      float highResTemp = (float)temp_read - .5 + (((float)count_per_c - (float)count_remain) / (float)count_per_c);

      highResTemp = (float)((1.80 * highResTemp) + 32.00);
      Serial.print(highResTemp);
      Serial.println(" Fahrenheit");

      delay(1000);
      }

      Delete
    3. 移除底下這行
      highResTemp = (float)((1.80 * highResTemp) + 32.00);

      那麼highResTemp就會是攝氏溫度

      然後把
      Serial.println(" Fahrenheit");
      改成
      Serial.println(" Celcius");

      Delete
  62. 我想在請問一下
    我現在DS1821有溫度了
    LCD面板上也可以跑出文字了 (參考http://coopermaa2nd.blogspot.tw/2010/12/arduino-lab9-2x16-lcd-world.html)
    那麼要怎麼樣讓溫度顯示在LCD上呢

    ReplyDelete
    Replies
    1. 請參考拙作
      Arduino輕鬆入門:範例分析與實作設計
      http://yehnan.blogspot.tw/2014/02/arduino_21.html
      第7章第1節









      lcd.print(highResTemp);

      Delete
  63. 不好意思請問我照著您的程式碼打
    可是出線的卻是亂碼耶

    ReplyDelete
    Replies
    1. 序列埠連線速率先調一調,試試看囉。

      Delete
  64. 感謝您,可是調完速率卻發現只會顯示-127度
    會不會是我感測器燒掉了?

    ReplyDelete
    Replies
    1. 溫度感測範圍-55°C到+125°C,
      只會顯示-127,有錯,找找看囉。

      Delete
    2. This comment has been removed by the author.

      Delete
  65. This comment has been removed by the author.

    ReplyDelete
  66. Anonymous18/3/17 16:57

    請問老師 如果出現找到DS18B20的地址 serial monitor一直返回-127 是什麼情況?

    ReplyDelete
    Replies
    1. 溫度感測範圍-55°C到+125°C,
      只會顯示-127,有錯,找找看囉。

      Delete
  67. 不好意思,您請教一下這個程式最後面的Delay(1000);目的是做甚麼的?為甚麼有加和沒加顯示出來的速度都一樣?

    ReplyDelete
    Replies
    1. 為了延遲1秒。
      哦,是這樣嗎,
      應該是因為DS18B20感測溫度時,需要一段轉換時間。

      Delete
  68. 請問感測器感測到特定溫度 有辦法回傳1給麵包板嗎

    ReplyDelete
  69. 我目前是打算做倒數計時器 讓程式一開始給計時器的enable 1當達到一定溫度他會把enable變成0 計時器就會開始倒數

    ReplyDelete
  70. 請問有PH值跟溫督氣合併的例子嗎?

    ReplyDelete
  71. https://forum.arduino.cc/index.php?topic=247678.0

    ReplyDelete
  72. Anonymous23/6/17 13:52

    請問 有辦法將讀取到的數值 丟進我原先在processing寫好的格子內嗎?

    ReplyDelete
  73. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. 找個懂Arduino與Processing的人進行改寫。

      Delete
  74. 葉大師 好,
    我想用你上述的程式進行溫度偵測控制,
    增加下列程式(如下列),但無法正常作用,
    請教正確語法如何寫,謝謝

    void loop(void)
    {
    sensors.requestTemperatures();
    Serial.println(sensors.getTempCByIndex(0));
    delay(1000);
    TempinStatus = digitalRead(sensors.getTempCByIndex(0));
    if ( TempinStatus >32)
    {
    digitalWrite(ledPin,HIGH);
    delay(1000);

    }
    else
    {
    digitalWrite(ledPin,LOW);
    }
    }

    ReplyDelete
    Replies
    1. 這樣?

      void loop(void)
      {
      sensors.requestTemperatures();
      TempinStatus = sensors.getTempCByIndex(0);
      Serial.println(TempinStatus);
      delay(1000);
      if ( TempinStatus >32)
      {
      digitalWrite(ledPin,HIGH);
      delay(1000);

      }
      else
      {
      digitalWrite(ledPin,LOW);
      }
      }

      Delete
    2. 補充一下,我可以在監視視窗讀到溫度數據!

      Delete
  75. 葉大師,謝謝您的回覆

    依照您上述的方式修改完,會在下列出現錯誤!
    TempinStatus = sensors.getTempCByIndex(0);
    把=改成=,就能讀到溫度,

    不過會去掉小數點,而且也不會有對應的控制!

    可以再麻煩幫忙想一下,感謝


    我試著改

    ReplyDelete
    Replies
    1. 喔,我等號打錯了,打成中文的全形,應該是
      TempinStatus = sensors.getTempCByIndex(0);

      > 去掉小數點
      因為你TempinStatus是int嗎?

      Delete
    2. 謝謝大師,我再好好試試

      Delete
  76. 報告大師,

    我把TempinStatus改float,

    現在作用正常了耶!!


    #include
    #include
    #define ONE_WIRE_BUS 2
    int IRin = 7;
    int ledPin = 11;
    int IRinStatus;
    float TempinStatus;
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);

    void setup(void)
    {
    Serial.begin(115200);
    Serial.println("Temperature Sensor");
    pinMode(ledPin, OUTPUT);
    pinMode(IRin, INPUT);
    sensors.begin();
    }

    void loop(void)
    {

    sensors.requestTemperatures();
    TempinStatus = sensors.getTempCByIndex(0);
    IRinStatus = digitalRead(IRin);
    Serial.println(TempinStatus);
    delay(1000);

    if ( TempinStatus >=31 or IRinStatus == HIGH)
    {
    digitalWrite(ledPin,HIGH);
    delay(1000);

    }
    else
    {
    digitalWrite(ledPin,LOW);
    }
    }

    ReplyDelete
    Replies
    1. 謝謝葉大師,你真神

      Delete
    2. 葉老師,再跟您請教一個問題

      我設一個按鍵開關,按下ON放開OFF

      按鍵按下時啟動溫度偵測,放開時結束偵測....
      然後擷取按鍵在按下與放開間,溫度變化過程中相對最低溫的,有無達到設定值,進行控制

      這樣的按鍵時間內,比較判斷程式該怎麼寫呢?

      可以麻煩您提示指點一下嗎?

      感謝

      Delete
    3. 大概是這樣吧
      https://pastebin.com/WWYVYFg3
      僅供參考,沒有實際試過。

      Delete
  77. 請問如果沒有加4.7k的上拉電阻,可以偵測到數據嗎?

    ReplyDelete
  78. 大師,我跟朋友都遇到這個問題,請問該怎麼解決,謝謝。
    序列阜跟開發板都確定選對。
    他上面還有一堆錯誤類似這樣
    libraries\DallasTemperature\OneWire.cpp.o (symbol from plugin): In function `OneWire::write(unsigned char, unsigned char)':

    (.text+0x0): multiple definition of `OneWire::crc8(unsigned char const*, unsigned char)'

    libraries\OneWire\OneWire.cpp.o (symbol from plugin):(.text+0x0): first defined here

    libraries\DallasTemperature\OneWire.cpp.o (symbol from plugin): In function `OneWire::write(unsigned char, unsigned char)':

    然後最後是這樣


    "OneWire.h"找到多個程式庫
    已使用: C:\Program Files (x86)\Arduino\libraries\OneWire
    未使用: C:\Users\賴柏瑋\Documents\Arduino\libraries\OneWire-master
    未使用: C:\Users\賴柏瑋\Documents\Arduino\libraries\Arduino-Temperature-Control-Library-master
    未使用: C:\Program Files (x86)\Arduino\libraries\DallasTemperature
    "DallasTemperature.h"找到多個程式庫
    已使用: C:\Program Files (x86)\Arduino\libraries\DallasTemperature
    未使用: C:\Users\賴柏瑋\Documents\Arduino\libraries\Arduino-Temperature-Control-Library-master
    exit status 1
    開發板 Arduino/Genuino Uno 編譯錯誤。


    ReplyDelete
    Replies
    1. 你有三套OneWire程式庫,有兩套DallasTemperature程式庫。清理一下吧。
      而且不知為何,Arduino-Temperature-Control-Library-master裡面也有OneWire.cpp(.h)。

      Delete
  79. WARNING: Category 'Sensor' in library DallasTemperature is not valid. Setting to 'Uncategorized'
    這個是什麼問題

    ReplyDelete
  80. 你好 請問我想讓溫度感測器收到我要的溫度後持續發出訊號的話要怎麼寫

    ReplyDelete
  81. This comment has been removed by the author.

    ReplyDelete
  82. This comment has been removed by the author.

    ReplyDelete
  83. 老師你好 我想把溫度的數據顯示在蛋腦螢幕上的話 要輸入什麼程式碼 還是要從軟體裡面哪邊設定?

    ReplyDelete