Termometr na Arduino i DS18B20

Wpis w kategorii [ Arduino ]
Termometr

Temperatura to jedna z najważniejszych i najczęściej mierzonych wielkości fizycznych. Do jej mierzenia można zastosować nawet najprostszą, tanią diodę półprzewodnikową. Na rynku dostępne są także specjalne, kalibrowane układy przetwarzające temperaturę na napięcie (np. LM35).

My jedak pójdziemy o krok dalej i wykorzystamy do tego celu układ DS18B20, który zmierzoną wartość temperatury zamienia na postać cyfrową. Poza tym, zawiera w swej strukturze interfejs pozwalający na komunikacje z wykorzystaniem tylko jednego przewodu (tzw. 1-Wire).

Co będzie potrzebne?

  • Arduino (oprogramowanie oraz dowolny klon płytki),
  • układ DS18B20,
  • wyświetlacz alfanumeryczny LCD ze sterownikiem zgodnym z HD44780,
  • płytka stykowa, przewody

Połączenie Arduino, LCD oraz DS18B20

We wcześniejszym wpisie przedstawiony został sposób podłączenia wyświetlacza LCD do płytki Arduino.

W omawainym przypadku, do podłączenia wyświetlacza, wykorzystane zostały piny od 5 do 11. Pin 12 posłużył do podłączenia układu DS18B20 (środkowy pin układu).

DS18B20 - opis wyprowadzeń

DS18B20 - opis wyprowadzeń

Musimy także dodać rezystor o wartości 4,7k podłączając go do pinu 2 układu DS18B20 oraz do zasilania 5V.

Układ DS18B20 może pracować w dwóch trybach: pierwszy tzw. Normal

  • GND (pin1) podłączony do GND,
  • DQ (pin2) podłączony do pinu 12,
  • VDD (pin3) podłączony do 5V,
  • rezystor 4.7k pomiędzy DQ (pin2) oraz VDD (pin3)

Drugi tzw. Parasitic – nie wymaga doprowadzania zasilania (jest ono „podkradane” z pinu DQ)

  • GND (pin1) oraz VDD (pin3) podłączone do GND,
  • DQ (pin2) podłączony do pinu 10,
  • rezystor 1k pomiędzy DQ (pin2) oraz 5V

Program

Na początek należy zaopatrzyć się w bibliotekę obsługującą układ DS18B20. Jest to najszybszy sposób, aby rozpocząć pracę z układem. Biblioteka dostępna jest poniżej:

DallasTemperature.rar

Archiwum należy rozpakować do folderu hardware\libraries w miejscu, gdzie zainstalowane jest środowisko Arduino.

Aby sprawdzić, czy biblioteka jest prawidłowo zainstalowana należy uruchomić Arduino. Następnie należy sprawdzić, czy w przykładach pojawiła się pozycja widoczna na poniższym obrazku.

Biblioteka DallasTemperature

Biblioteka DallasTemperature

Gdy biblioteka jest już zainstalowana, możemy przejśc do napisania programu:

#include <LiquidCrystal.h>
#include <DallasTemperature.h>
 
DallasTemperature tempSensor;
LiquidCrystal lcd(5, 6, 7, 8, 9, 10, 11);
 
float temp, min = 150, max = -150;
int p = 0;
 
void setup(void) {
  lcd.clear();
  tempSensor.begin(12);
}
 
void loop(void) {
 
  switch(tempSensor.isValid())
  {
    case 1:
      lcd.clear();
      lcd.print("Invalid CRC");
      tempSensor.reset();
      return;
    case 2:
      lcd.clear();
      lcd.print("Not a valid device");
      tempSensor.reset();
      return;
  }
 
  temp = tempSensor.getTemperature();
 
  if(temp < min)
    min = temp;
 
  if(temp > max)
    max = temp;
 
  lcd.setCursor(0,0);
  lcd.print("T = ");
  lcd.print(temp);
  lcd.write(0xDF);
  lcd.write('C');  
 
  if(p < 3)
  {
    lcd.setCursor(0,1);
    lcd.print("Min = ");
    lcd.print(min);
    lcd.write(0xDF);
    lcd.write('C');
    p++;
  }
  else
  {
    lcd.setCursor(0,1);
    lcd.print("Max = ");
    lcd.print(max);
    lcd.write(0xDF);
    lcd.write('C');
    p++;
    if(p == 6)
      p = 0;
  }
}

Sprawdzamy działanie

Wgrywamy program do mikrokontrolera (Upload to I/O Board). Teraz możemy sprawdzić, czy wszystko działa jak należy.

Jeśli układ działa, na wyświetlaczu pojawi się aktualna temperatura, temperatura maksymalan oraz minimalna (dwie ostatnie wyświetlane na przemian).

Działający termometr

Działający termometr

Biblioteka DallasTemperature

W skład biblioteki wchodzą funkcje:

DallasTemperature

Opis:

Tworzy obiekt typu DallasTemperature.

Składnia:

DallasTemperature temp

Parametry:

temp: nazwa tworzonego obiektu

begin()

Opis:

Inicjuje obsługę układu DS1820 na wybranym wyprowadzeniu.

Składnia:

temp.begin(pin)

Parametry:

pin: numer wyprowadzenia Arduino do którego podłączony jest czujnik

temp: obiekt typu DallasTemperature

isValid()

Opis:

Funkcja służy do sprawdzenia poprawności komunikacji z czujnikiem.

Składnia:

temp.isValid()

Parametry:

temp: obiekt typu DallasTemperature

getTemperature()

Opis:

Funkcja inicjuje pomiar temperatury przez czujnik oraz zwraca wynik tej operacji w stopniach Celsjusza.

Składnia:

temp.getTemperature()

Parametry:

temp: obiekt typu DallasTemperature

reset()

Opis:

Resetuje komunikację z czujnikiem.

Składnia:

temp.reset()

Parametry:

temp: obiekt typu DallasTemperature

toFahrenheit()

Opis:

Funkcja zamienia wynik pomiaru temperatury w stopniach Celsjusza na stopnie Fahrenheita.

Składnia:

temp.toFahrenheit()

Parametry:

temp: obiekt typu DallasTemperature

Oceń ten wpis:
1 gwiazdka2 gwiazdki3 gwiazdki4 gwiazdki5 gwiazdek (Nikt jeszcze nie ocenił tego wpisu)
Loading ... Loading ...
Wyświetleń: 2 850

Podobne artykuły

Możesz śledzić komentarze do tego wpisu poprzez kanał RSS 2.0. Możesz także dodać własny komentarz, lub trackback z własnej strony WWW.

29 komentarzy do “Termometr na Arduino i DS18B20”

  • Grejzen (1 października, 2009, 15:23)

    Nijak nie mogę uruchomić tego. Wysypuje się przy kompilowaniu, Twój przykład jak i oryginalny z transmisją szeregową zwracają ten sam błąd.
    Załączam zrzut może ktoś będzie wiedział o co chodzi:
    http://i33.tinypic.com/2a4zcp2.jpg

  • michal (1 października, 2009, 15:38)

    @Grejzen: Jaką wersję oprogramowania Arduino posiadasz? Biblioteka została prawidłowo zainstalowana?

  • Grejzen (1 października, 2009, 16:10)

    Wersje mam najnowsza tj. 0017. Instalowałem biblioteki z tego artykułu, jak i biblioteki z oryginalnego wątku o DallasTemperature na forum Arduino. Zawsze ten sam błąd.

  • michal (1 października, 2009, 16:32)

    @Grejzen: A inne przykłady kompilują się poprawnie? Np. Blink

  • Grejzen (1 października, 2009, 16:43)

    Pozostałe przykłady kompilują się bez problemu. Przykład z OneWire też się kompiluje ale jakieś krzaczki wysyla :(

  • Maciek [vobo] (2 października, 2009, 11:51)

    U mnie wszystko działa, ale nie wyświetlają się minimalna i maksymalna wartość – może jest to spowodowane tym, że nie świeci w ogóle dolna połówka wyświetlacza. (wyświetlacz 2×16 z podświetleniem)?

  • michal (2 października, 2009, 14:27)

    @Maciek [vobo]: Spróbuj wcisnąć reset, gdy program jest już załadowany do mikrokontrolera – czasami wyświetlacz źle się inicjuje.

    @Grejzen: działasz pod Linuxem? Jeśli tak, to zajrzyj na stronę arduino, gdzie znajdziesz dodatkowe kroki wymagane przy instalacji oprogramowania.

  • Grejzen (2 października, 2009, 17:28)

    Działam tylko i wyłącznie pod Windowsem.

  • Grejzen (9 listopada, 2009, 21:41)

    Michał, a możesz przesłać mi Twoją wersje ze wszystkimi bibliotekami? Na grejzen [ małpa ] gmail [ kropka] com.

  • Maciek [vobo] (12 grudnia, 2009, 14:48)

    już działa dolna połówka wyświetlacza
    wystarczyło dopisać w sekcji „void setup” następującą linijkę:
    lcd.begin(2, 16);
    teraz działa cały wyświetlacz

    pozdrawiam,

    Maciek

  • savve (12 maja, 2010, 16:59)

    Witam!

    Robię podobny projekt tylko rozbudowany o większą ilość czujników i kontroler obrotów. Wszystko mi na razie działa ok, nie licząc wyświetlacza. Mianowicie na wyświetlaczu 2×16 lini przez większość czasu mam „krzaczki”, natomiast po podłączeniu wyświetlacza 4×16 wszystko jest ok. Większy mi się nie zmieści w moim projekcie, a szkoda mi niepotrzebnie kupować wyświetlacz. Sytuacja jest tym dziwiniejsza, że wyświetlacz działa dobrze na prostych porgramach, nie chce dla mojego:

    #include
    #include

    LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

    static const int ONE_WIRE_PIN = 12;

    NewOneWire oneWire(ONE_WIRE_PIN);
    DallasTemperature tempSensor0(oneWire, 0);
    DallasTemperature tempSensor1(oneWire, 1);
    DallasTemperature tempSensor2(oneWire, 2);

    void setup(void) {
    lcd.begin(16, 2);

    TCCR1B = TCCR1B & 0b11111000 | 0×01;

    Serial.begin(9600);

    tempSensor0.begin();
    tempSensor1.begin();
    tempSensor2.begin();

    tempSensor0.setResolution(9);
    tempSensor1.setResolution(9);
    tempSensor2.setResolution(9);

    // sends convert temperature to all devices on the NewOneWire connection.
    // only one device on each bus needs to do this. ideally, it should be
    // on your highest resolution device so if a longer delay is necessary,
    // it will be the long enough.
    tempSensor0.globalTempRequest();
    tempSensor0.conversionDelay();
    //Serial.println(„Dallas Temperature IC Control Library”);
    }

    void printId(DallasTemperature &sensor) {
    for (uint8_t i = 0; i < 8; i++) {
    Serial.print(sensor.getSlaveAddr()[i], HEX);
    //lcd.print(sensor.getSlaveAddr()[i], HEX); //jeżeli na LCD puszcze tylko ta linijke to wyswietla ja dobrze
    }
    }

    void display(DallasTemperature &sensor) {
    // Ask the library whether the device is valid
    Serial.print("sensor ");
    Serial.print(sensor.getIndex(), DEC);
    Serial.print(" ");
    printId(sensor);
    Serial.print(": ");
    switch(sensor.isValid())
    {
    case 1:
    Serial.println("Invalid CRC");
    sensor.reset(); // Attempts to redetect IC
    return;
    case 2:
    Serial.println("Not a valid device");
    sensor.reset(); // Attempts to redetect IC
    return;
    }

    // getTemperature returns a float.
    float temperature = sensor.getTemperature();
    lcd.print(temperature);
    Serial.print(temperature);
    Serial.println("C");

    }

    void loop(void) {
    lcd.clear();
    lcd.setCursor(0,0);
    display(tempSensor0);
    lcd.setCursor(8,0);
    display(tempSensor1);
    lcd.setCursor(0,1);
    display(tempSensor2);
    Serial.println();
    delay(1000);
    }

    Ma ktoś jakiś pomysł?

  • michal (14 maja, 2010, 14:00)

    Po pierwsze: gdzie podłączasz sygnał RW wyświetlacza? Sprawdź, czy połączenie jest pewne.

    Po drugie: nie bardzo rozumiem co chcesz osiągnąć poprzez ten fragment kodu:
    TCCR1B = TCCR1B & 0b11111000 | 0×01;
    Mało tego, ten zapis jest nieco bez sensu :)

  • savve (14 maja, 2010, 14:28)

    RW jest na stale do masy. A ten zapis powoduje zwiększenie częstotliwości PWM dla wentylatorów, żeby cewki nie piszczały. 0×01 daje 32MHz

  • michal (14 maja, 2010, 18:35)

    Chyba raczej 16MHz, chyba że o czymś nie wiem. Czy wywalenie tej linii nie poprawia sytuacji?

  • savve (15 maja, 2010, 12:24)

    Pins 9 and 10: controlled by timer 1
    Setting Divisor Frequency
    0×01 1 31250
    0×02 8 3906.25
    0×03 64 488.28125
    0×04 256 122.0703125
    0×05 1024 30.517578125

    Nie pomaga wyrzucenie tej linii.
    Wcześniej działał dobrze, wydaje mi się że jak sprawdzałem bibliotekę LiquidCrystal_I2C to od tego czasu nie działa dobrze. Możliwe że uszkodziłem go jakoś? I czemu na prostych programach działa?

  • michal (15 maja, 2010, 12:35)

    No właśnie 31,25kHZ a nie 32MHz.

    Spróbuj na czystej instalacji Arduinio tzn. utwórz nowy katalog, wrzuć tam Aduino, LiquidCrystal i DallasTemperature.

  • savve (16 maja, 2010, 12:59)

    W sumie to podałem w przybliżeniu częstotliwość :) A ważne dla mnie było żeby cewki nie piszczały. Tylko faktycznie w tej części kodu nie jest to potrzebne- okroiłem program, żeby tylko wyświetlacz sprawdzić. W sumie zamówiłem nowy wyświetlacz 2×20 linii. I zobaczymy jak pójdzie.

  • Bartek (9 czerwca, 2010, 16:32)

    Czy do zrobienia tego układu należy zakupić potencjometr liniowy czy logarytmiczny?

  • michal (9 czerwca, 2010, 17:50)

    Ja zastosowałem potencjometr montażowy o charakterystyce liniowej, ale nie jest to bardzo istotne, gdyż służy on jedynie do regulacji kontrastu wyświetlacza.

  • Bartek (9 czerwca, 2010, 21:27)

    Jaka jest maxymalna długość przewodów od czujnika do procesora? Chciałbym mierzyć temperaturę na zewnątrz lecz odległość, gdzie znajdował by się układ od okna to ok. 4m.

  • michal (9 czerwca, 2010, 21:51)

    Dla 1wire przewód o długości 4 metrów, to praktycznie żaden problem.
    Osobiście przeprowadzałem próby na 10 metrowym przewodzie, które zakończyły się sukcesem.

  • Bartek (9 czerwca, 2010, 22:13)

    A gdy będę dosztukowywał przewody, to straty będą dość duże na pomiarze temperatury?

  • michal (10 czerwca, 2010, 16:54)

    Dane w standardzie 1wire wysyłane są w sposób cyfrowy, więc albo je odbierzesz, albo nie. Nie wystąpi sytuacja „straty” – jeśli odbierzesz dane i sprawdzisz sumę kontrolną, to na pewno temperatura będzie prawidłowa.

  • Bartek (10 czerwca, 2010, 23:34)

    Z serii nudnych pytań następna seria. Czy do zrobienia tego układu można zastosować wyświetlacz ledowy bez sterownika HD44780. Chodzi mi o ten:
    http://www.sklep.avt.pl/p/pl/47220/wyswietlacz+czerwony+2+cyfry+14-2mm+wa.html

  • michal (13 czerwca, 2010, 17:52)

    Możesz użyć ten wyświetlacz tylko jeśli dokonasz zmian w projekcie.
    Powyższy kod jest napisany dla wyświetlacza LCD ze sterownikiem HD44780.

  • pasta20 (18 sierpnia, 2010, 10:51)

    Jak poprawnie odczytać temperaturę na NTC w arduino.
    Proszę o jakiś przykład.

  • Bartek (28 sierpnia, 2010, 22:09)

    Witam, czy jest możliwość napisania aplikacji, która sczytywała informacje o temperaturze z czujnika w programie na komputerze?

  • michal (5 września, 2010, 20:14)

    Nie wiem, czy dobrze rozumiem pytanie… powiem tak – jest możliwość napisania aplikacji, która odczyta temperaturę z czujnika – wystarczy dane z przedstawionego projektu wysłać poprzez port szeregowy do komputera i odebrać w napisanym programie.

Dodaj komentarz