Θερμόμετρο με το DS18B20 βασισμένο στο Arduino

Ένας από τους ευκολότερους και φθηνότερους τρόπους μέτρησης της θερμοκρασίας με το Arduino είναι χρησιμοποιώντας τον αισθητήρα DS18B20. Αυτός ο αισθητήρας επικοινωνεί ψηφιακά με τον μικροελεγκτή κάνοντας χρήση της 1-Wire διεπαφής. Ο DS18B20 κατασκευάζεται από την εταιρεία Dallas Semiconductor Corp. και χρησιμοποιεί ένα μόνο ψηφιακό ακροδέκτη για αμφίδρομη επικοινωνία  με τον μικροελεγκτή.

Ένα βασικό χαρακτηριστικό του αισθητήρα DS18B20 είναι ότι μπορούμε να συνδέσουμε πολλούς αισθητήρες παράλληλα κατανεμημένους σε μια περιοχή. Αυτό το χαρακτηριστικό το επιδεικνύουμε στο τέλος αυτού του οδηγού αφού πρώτα εξετάσουμε πως μετράμε την θερμοκρασία με ένα DS18B20.

Ο αισθητήρας κατασκευάζεται σε δυο τύπους: Ο ένας είναι σε συσκευασία ΤΟ-92 όπως ακριβώς με ένα συνηθισμένο τρανζίστορ. Ο άλλος κατασκευάζεται αδιάβροχα στην άκρη καλωδίου και είναι χρήσιμος όταν μετράμε την θερμοκρασία σε υγρά ή στο υπέδαφος.

Ο θερμοκρασιακός αισθητήρας DS18B20 είναι εξαιρετικά ακριβής και μπορεί να μετρήσει θερμοκρασίες από -55οC έως  +125οC  με ακρίβεια ±0,5οC. Η ανάλυση της ένδειξης μπορεί να οριστεί από τον χρήστη σε 9, 10, 11 ή 12-bits. Η προκαθορισμένη ανάλυση είναι 12-bits (δηλαδή 0,0625 οC). Ο αισθητήρας μπορεί να τροφοδοτηθεί με τάση από 3V έως 5,5V και καταναλώνει μόνο 1mA κατά τη διάρκεια ενεργούς λειτουργίας.

Διάταξη ακροδεκτών του θερμοκρασιακού αισθητήρα DS18B20

Η διάταξη των ακροδεκτών του αισθητήρα θερμοκρασίας DS18B20 φαίνεται στο ακόλουθο σχήμα:

Συνδέοντας τον αισθητήρα DS18B20 με το Arduino

Η σύνδεση του DS18B20 με το Arduino είναι απλή. Ξεκινώντας συνδέουμε τον ακροδέκτη VDD με το πιν 5V του Arduino και το GND με το 0V. Έπειτα συνδέουμε το πιν DQ του αισθητήρα με το ψηφιακό πιν του Arduino. Θα χρειαστεί να συνδέσετε μια αντίσταση 4,7ΚΩ pull-up μεταξύ του ακροδέκτη DQ και VDD.

Αν χρησιμοποιείται την αδιάβροχη έκδοση του DS18B20 συνδέστε τον κόκκινο ακροδέκτη στα 5V, τον μαύρο ακροδέκτη στο GND, ενώ ο κίτρινος ακροδέκτης συνδέεται σε ένα ψηφιακό πιν του Arduino. Θα χρειαστεί να συνδέσετε μια 4,7ΚΩ pull-up αντίσταση από τον ακροδέκτη DQ στο VDD.

Εγκαθιστώντας τη βιβλιοθήκη για το DS18B20

Το 1-Wire πρωτόκολλο επικοινωνίας της Dallas Semiconductor είναι κάτι το περίπλοκο και απαιτεί σύνθετο κώδικα για να επιτύχουμε επικοινωνία. Για ξεπεράσουμε αυτή τη δυσκολία χρησιμοποιούμε την βιβλιοθήκη: DallasTemperature.h Έτσι με απλές εντολές μπορούμε να διαβάσουμε την θερμοκρασία από τον αισθητήρα. Επίσης θα πρέπει να εγκαταστήσουμε τη βιβλιοθήκη OneWire που ορίζει πως μεταφέρονται τα δεδομένα πάνω στο δίαυλο 1-Wire μεταξύ του DS18B20 και του μικροελεγκτή (Arduino Nano)

Εγκατάσταση βιβλιοθηκών

Πριν φορτώσεις τον κώδικα στο Arduino θα πρέπει να έχεις εγκαταστήσει δυο βιβλιοθήκες στο περιβάλλον Arduino IDE και συγκεκριμένα τις 1) OneWire που ορίζει τον τρόπο που μεταφέρονται τα δεδομένα στο δίαυλο 1-Wire και την 2) DallasTemperature που αφορά τον τρόπο που δουλεύει ο αισθητήρας DS18B20. Ακολούθησε τα παρακάτω βήματα για να τις εγκαταστήσεις.

Δημιουργούμε ένα φάκελο στο σκληρό μας δίσκο π.χ. arduino_libraries και στην συνέχεια κατεβάζουμε τα zip αρχεία των βιβλιοθηκών, από τους ακόλουθους συνδέσμους και τα αποθηκεύουμε σ’ αυτόν τον φάκελο.

OneWire Library
Πάτησε εδώ OneWire-2.3.5.zip για να κατεβάσεις και να αποθηκεύσεις την βιβλιοθήκη του OneWire πρωτοκόλλου σε μορφή zip αρχείου.

DallasTemperature Library
Πάτησε εδώ DallasTemperature-3.9.0.zip για να κατεβάσεις και να αποθηκεύσεις την βιβλιοθήκη Dallas Temperature σε μορφή zip αρχείου.

Προτού ανεβάσεις και τρέξεις τον κώδικά στο Arduino IDE, θα πρέπει να έχεις εγκαταστήσει τις αντίστοιχες βιβλιοθήκες. Για να εγκαταστήσεις τις βιβλιοθήκες ακολούθησε τα εξής απλά βήματα:

Από το μενού επιλέγουμε διαδοχικά: Sketch > Include Library > Add .ZIP library… Από το εμφανιζόμενο παράθυρο διαλόγου πλοηγούμαστε και επιλέγουμε το επιθυμητό .ZIP αρχείο βιβλιοθήκης και κάνουμε κλικ στο κουμπί Άνοιγμα. Αν πάνε όλα καλά θα πρέπει να έχουν εγκατασταθεί οι βιβλιοθήκες.

Μέτρηση της θερμοκρασίας με ένα DS18B20

Ο ακόλουθος κώδικας ορίζει την επικοινωνία του αισθητήρα BS18B20 με το Arduino και ορίζει πως το Arduino διαβάζει τη θερμοκρασία από τον αισθητήρα. Σε αυτή την επίδειξη χρησιμοποιούμε την αναπτυξιακή πλακέτα με το Arduino Nano όπως δημοσιεύεται σε άλλη θέση αυτού του ιστότοπου.

#include <DallasTemperature.h>
#include <OneWire.h>
#include <LiquidCrystal.h>
// Data wire is plugged into digital pin 8 on the Arduino
#define ONE_WIRE_BUS 8

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

// Setup a oneWire instance to communicate with any OneWire device
OneWire oneWire(ONE_WIRE_BUS);  

// Pass oneWire reference to DallasTemperature library
DallasTemperature sensors(&oneWire);

byte Degree[] = {B00111, B00101, B00111, B00000,
                 B00000, B00000, B00000, B00000
};

void setup(void)
{
  sensors.begin();  // Start up the library
  lcd.begin(20, 4);
  lcd.clear();
  lcd.createChar(0, Degree);   // Δημιουργία συμβόλου
}

void loop(void)
{ 
  // Send the command to get temperatures
  sensors.requestTemperatures(); 
  lcd.setCursor(0, 1);
  lcd.print("Temperature: ");
  //print the temperature in Celsius
  lcd.print(sensors.getTempCByIndex(0));
  lcd.write(byte (0));
  lcd.print("C");
  
  lcd.setCursor(0, 2);
  lcd.print("Temperature: ");
  //print the temperature in Fahrenheit
  lcd.print((sensors.getTempCByIndex(0) * 9.0) / 5.0 + 32.0);
  lcd.write(byte (0)); 
  lcd.print("F");
  delay(500);
 }

Εξήγηση του κώδικα

Ο κώδικας Arduino ξεκινά με την συμπερίληψη των βιβλιοθηκών OneWire.h και DallasTemperature.h Επίσης δηλώνουμε το πιν του Arduino στο οποίο συνδέεται ο ακροδέκτης DQ του αισθητήρα.

#include  <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 8

Μετά δημιουργούμε ένα αντικείμενο oneWire περνώντας στη συνάρτηση δημιουργίας το ψηφιακό πιν του Arduino που συνδέεται ο αισθητήρας (DQ). Αυτό το oneWire αντικείμενο επιτρέπει την επικοινωνία με κάθε one-wire συσκευή και όχι μόνο με το DS18B20. Για επικοινωνία με τον αισθητήρα DS18B20 χρειάζεται να δημιουργήσουμε ένα νέο αντικείμενο της κλάσης DallasTemperature και να περάσουμε στη συνάρτηση δημιουργίας ως παράμετρο την αναφορά του αντικειμένου oneWire που δημιουργήσαμε πριν. Αυτό υλοποιείται με το ακόλουθο απόσπασμα κώδικα:

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

Μόλις το αντικείμενο DallasTemperature δημιουργηθεί μπορούμε να ζητήσουμε απλές εντολές για επικοινωνία με τον αισθητήρα, όπως περιγράφονται στις ακόλουθες συναρτήσεις:

—Η συνάρτηση begin() αναζητά για συνδεμένους αισθητήρες στο δίαυλο και θέτει την ανάλυση σε 12-bits στον καθένα.
—Η συνάρτηση requestTemperature() δίνει εντολή σε όλους τους αισθητήρες να εκτελέσουν διάβασμα της θερμοκρασίας.
—Η συνάρτηση getTempCByIndex(deviceIndex) διαβάζει και επιστρέφει την θερμοκρασία από τον αισθητήρα. Η παράμετρος deviceIndex είναι η θέση του αισθητήρα στο δίαυλο. (Εάν χρησιμοποιείται ένα μόνο DS18B20 στο δίαυλο, θέτουμε το deviceIndex ίσο με μηδέν).

Άλλες χρήσιμες συναρτήσεις της βιβλιοθήκης DallasTemperature.h

Υπάρχουν μερικές άλλες συναρτήσεις που μπορείς να χρησιμοποιήσεις με ένα αντικείμενο DallasTemperature. Μερικές από αυτές επιδεικνύονται παρακάτω.

—Η συνάρτηση setResolution θέτει την ανάλυση του εσωτερικού μετατροπέα Analog-to-Digital του αισθητήρα DS18B20 σε 9, 10, 11 ή 12-bits οι οποίες αντιστοιχούν σε μεταβολές 0,5οC, 0,25oC, 0,125oC και 0,0625οC αντίστοιχα.
—Η συνάρτηση bool  getWaitForConversion() επιστρέφει τη σημαία waitForConversion. Αυτό είναι χρήσιμο για να ελέγχουμε πότε μια θερμοκρασιακή μέτρηση έχει ολοκληρωθεί.
—Οι συναρτήσεις setHighAlarmTemp()  &   setLowAlarmTemp() θέτουν το πάνω και κάτω όριο κατάστασης συναγερμού σε βαθμούς Κελσίου. Οι έγκυρες τιμές είναι μεταξύ -55 και +125οC
—Η συνάρτηση bool hasAlarm() επιστρέφει true όταν μπαίνει σε κατάσταση συναγερμού με την θερμοκρασία να υπερβαίνει το πάνω ή κάτω όριο θερμοκρασίας.

Διαβάζοντας τις θερμοκρασίες από πολλαπλά DS18B20

Ένα από τα πλεονεκτήματα του αισθητήρα DS18B20 είναι ότι πολλαπλά DS18B20 μπορούν να συνυπάρχουν στον ίδιο 1-Wire δίαυλο, με καθένα DS18B20 να έχει το δικό του 64-bit σειριακό κωδικό από την γραμμή παραγωγής και με αυτό τον τρόπο διαχωρίζεται ο ένας από τον άλλο. Αυτό το χαρακτηριστικό προσφέρει μεγάλο πλεονέκτημα όταν θέλουμε να ελέγξουμε πολλά DS18B20 κατανεμημένα σε μια μεγάλη περιοχή.

Για να μπορέσουμε να διαβάσουμε τις θερμοκρασίες από πολλαπλά DS18B20 τα συνδέουμε παράλληλα, δηλαδή όλους τους ακροδέκτες VDD μαζί, τους ακροδέκτες GND μαζί και τους DQ μαζί. Στη συνέχεια συνδέουμε τους ακροδέκτες VDD σε τάση 5V πάνω στο Arduino, τους GNDs στα 0V στο Arduino και τους DQ σε ένα ψηφιακό πίν του Arduino. Στη συνέχεια θα πρέπει να συνδέσουμε μια αντίσταση pull-up 4,7ΚΩ μεταξύ των ακροδεκτών DQ και VDD.

Επειδή το πρωτόκολλο 1-Wire είναι κάτι το σύνθετο, θα χρειαστεί να χρησιμοποιήσουμε τις ίδιες βιβλιοθήκες. Αν δεν τις έχετε εγκαταστήσει κοιτάξτε πως τις εγκαταστήσαμε παραπάνω.

Αφού συναρμολογήσουμε το κύκλωμα ανεβάζουμε τον ακόλουθο κώδικα στο Arduino Nano

#include <LiquidCrystal.h> 
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // Δημιουργία αντικειμένου lcd

#include <OneWire.h>
#include <DallasTemperature.h>

// Ο δίαυλος δεδομένων είναι συνδεμένος με το ψηφιακό πιν 8 του Arduino
#define ONE_WIRE_BUS 8

// Δημιουργία ενός αντικειμένου oneWire για επικοινωνία με άλλες OneWire συσκευές
OneWire oneWire(ONE_WIRE_BUS);  

// Πέρασμα μιας αναφοράς oneWire πάνω στο DallasTemperature library
DallasTemperature sensors(&oneWire);

byte Degree[] = { B00111, B00101, B00111, B00000,
                  B00000, B00000, B00000, B00000
};
int deviceCount = 0;
float tempC;

void setup(void)
{
  sensors.begin();  // Αρχικοποίηση του DS18B20
  lcd.begin(20, 4); // Αρχικοποίηση του LCD
  lcd.createChar(0, Degree);   // Δημιουργία συμβόλου
  
  lcd.setCursor(0, 0);
  lcd.print("Locating devices...");
  lcd.setCursor(0, 1);
  lcd.print("Found ");
  deviceCount = sensors.getDeviceCount();
  if (deviceCount >3) deviceCount = 3;
  lcd.print(deviceCount, DEC);
  lcd.print(" devices.");
  //Serial.println("");
  delay(3000);
  lcd.clear();
}

void loop(void)
{ 
  // Εντολή προς όλους τους αισθητήρες για μέτρηση της θερμοκρασίας
  sensors.requestTemperatures(); 
  // Εμφάνιση θερμοκρασίας από κάθε αισθητήρα
  for (int i = 0;  i < deviceCount;  i++)
  {
    lcd.setCursor(0, i);
    lcd.print("Temp. ");
    lcd.print(i+1);
    lcd.print(" : ");
    tempC = sensors.getTempCByIndex(i);
    lcd.print(tempC);
    lcd.write(byte (0));
    lcd.print("C");
  }
  delay(1000);
}

Σε αυτό τον κώδικα, καθώς η βιβλιοθήκη DallasTemperature αρχικοποιείται, ανιχνεύονται όλοι οι αισθητήρες που βρίσκονται πάνω στον ίδιο δίαυλο 1-Wire. Με αυτόν τον τρόπο ορίζονται όλοι οι αισθητήρες DS18B20 πάνω στον δίαυλο σαν ένα πίνακα αισθητήρων και σε καθένα εκχωρεί και από ένα δείκτη. Έτσι μπορούμε να ξεχωρίζουμε κάθε αισθητήρα από το δείκτη του και έτσι καταφέρνουμε να διαβάζουμε την θερμοκρασία από αυτόν.

Εξήγηση του κώδικα

—Ο κώδικας αρχίζει με την συμπερίληψη των βιβλιοθηκών και δηλώνεται το πιν του Arduino πάνω στο οποίο συνδέονται οι ακροδέκτες DQ των αισθητήρων και στη συνέχεια δημιουργείται ένα αντικείμενο βιβλιοθήκης DallasTemperature.

—Στο σώμα της συνάρτησης setup() καλούμε πρώτα την συνάρτηση begin(). Αυτή αρχικοποιεί το δίαυλο και ανιχνεύει όλους τους αισθητήρες που βρίσκονται πάνω στο δίαυλο. Σε κάθε αισθητήρα αντιστοιχίζεται ένας δείκτης και η ανάλυση τίθεται σε 12-bit.

—Μετά καλούμε την συνάρτηση getDeviceCount() για να πάρουμε τον αριθμό των αισθητήρων που βρίσκονται πάνω στο δίαυλο.

—Μέσα στη συνάρτηση βρόγχου loop() καλούμε την συνάρτηση requestTemperatures() για να δώσουμε εντολή σε όλους τους αισθητήρες να μετρήσουν τη θερμοκρασία.

—Στο βρόγχο επανάληψης  for(int i=0; i<deviceCount; i++) κινούμαστε πάνω στο πίνακα των αισθητήρων για να διαβάσουμε την θερμοκρασία από τον αισθητήρα με δείκτη i, απλά καλώντας τη συνάρτηση getTempCByIndex(i);

— Μέσα σε αυτό το βρόγχο επανάληψης, αφού διαβάσουμε την ένδειξη της θερμοκρασίας του κάθε αισθητήρα, την εκτυπώνουμε στο LCD display.