Tak Berkategori

ESP32 DS18B20 Temperature Sensor with Arduino IDE (Single, Multiple, Web Server)

Ini adalah panduan mendalam untuk sensor suhu DS18B20 dengan ESP32 menggunakan Arduino IDE. Kami akan menunjukkan cara menghubungkan sensor, menginstal library yang diperlukan, dan menulis kode untuk mendapatkan pembacaan sensor dari satu maupun beberapa sensor. Terakhir, kita akan membuat web server sederhana untuk menampilkan hasil pembacaan sensor.

Memperkenalkan Sensor Suhu DS18B20
Sensor suhu DS18B20 adalah sensor suhu digital one-wire. Artinya, sensor ini hanya memerlukan satu jalur data (dan GND) untuk berkomunikasi dengan ESP32 kamu.Sensor ini dapat diberi daya menggunakan catu daya eksternal, atau dapat mengambil daya dari jalur data (disebut “parasite mode”), sehingga tidak memerlukan catu daya eksternal.

Setiap sensor suhu DS18B20 memiliki kode serial 64-bit yang unik. Hal ini memungkinkan kamu menghubungkan beberapa sensor ke satu jalur data yang sama. Dengan demikian, kamu dapat membaca suhu dari beberapa sensor hanya dengan satu GPIO.Sensor suhu DS18B20 juga tersedia dalam versi tahan air.

Berikut adalah ringkasan spesifikasi paling relevan dari sensor suhu DS18B20:

  • Berkomunikasi menggunakan komunikasi bus one-wire
  • Rentang catu daya: 3,0 V hingga 5,5 V
  • Rentang suhu operasi: -55 ºC hingga +125 ºC
  • Akurasi ±0,5 ºC (pada rentang -10 ºC hingga 85 ºC)

Untuk informasi lebih lanjut, silakan merujuk ke  DS18B20 datasheet.

Komponen yang Dibutuhkan Untuk mengikuti tutorial ini, kamu memerlukan komponen berikut:

  • ESP32 (baca Best ESP32 development boards)
  • Sensor suhu DS18B20 (satu atau beberapa sensor) – versi tahan air
  • Resistor 4,7 kΩ
  • Kabel jumper
  • Breadboard

Skematik – ESP32
Seperti yang telah disebutkan sebelumnya, sensor suhu DS18B20 dapat diberi daya melalui pin VDD (mode normal), atau dapat mengambil daya dari jalur data (mode parasite). Kamu dapat memilih salah satu dari kedua mode tersebut.

Jika kamu menggunakan ESP32, ikuti salah satu dari dua diagram skematik berikut.

Mode Parasite

Normal Mode

Mempersiapkan Arduino IDE

Kita akan memprogram ESP32 menggunakan Arduino IDE, jadi pastikan kamu sudah menginstal add-on ESP32 sebelum melanjutkan:

Menginstal Library
Untuk berinteraksi dengan sensor suhu DS18B20, kamu perlu menginstal library OneWire oleh Paul Stoffregen dan library Dallas Temperature. Ikuti langkah-langkah berikut untuk menginstal library tersebut.

  1. Buka Arduino IDE kamu dan masuk ke Sketch > Include Library > Manage Libraries. Library Manager akan terbuka.

2. Ketik “onewire” pada kotak pencarian dan instal library OneWire oleh Paul Stoffregen

  1. Kemudian, cari “Dallas” dan instal library DallasTemperature oleh Miles Burton.

Setelah menginstal library-library tersebut, restart Arduino IDE kamu.

Kode (DS18B20 Tunggal)

Setelah menginstal library yang diperlukan, kamu dapat mengunggah kode ke ESP32. Kode berikut membaca suhu dari sensor suhu DS18B20 dan menampilkan hasil pembacaannya pada Serial Monitor Arduino IDE.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com  
*********/

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

// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;     

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

void setup() {
  // Start the Serial Monitor
  Serial.begin(115200);
  // Start the DS18B20 sensor
  sensors.begin();
}

void loop() {
  sensors.requestTemperatures(); 
  float temperatureC = sensors.getTempCByIndex(0);
  float temperatureF = sensors.getTempFByIndex(0);
  Serial.print(temperatureC);
  Serial.println("ºC");
  Serial.print(temperatureF);
  Serial.println("ºF");
  delay(5000);
}

Ada banyak cara berbeda untuk membaca suhu dari sensor suhu DS18B20. Namun, jika kamu hanya menggunakan satu sensor saja, ini adalah salah satu cara yang paling mudah dan paling sederhana.

Bagaimana Kode Bekerja

Mulailah dengan menyertakan library OneWire dan DallasTemperature.

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

Buat instance yang dibutuhkan untuk sensor suhu. Sensor suhu terhubung ke GPIO 4.

// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

Pada setup(), inisialisasi Serial Monitor dengan baud rate 115200.

Serial.begin(115200);

Inisialisasi sensor suhu DS18B20:

sensors.begin();

Sebelum benar-benar mendapatkan nilai suhu, kamu perlu memanggil metode requestTemperatures().

sensors.requestTemperatures(); 

Kemudian, ambil suhu dalam satuan Celsius menggunakan metode getTempCByIndex() seperti ditunjukkan di bawah ini:

float temperatureC = sensors.getTempCByIndex(0);

Atau gunakan getTempFByIndex() untuk mendapatkan suhu dalam Fahrenheit.

float temperatureF = sensors.getTempFByIndex(0);

Metode getTempCByIndex() dan getTempFByIndex() menerima indeks dari sensor suhu. Karena kita hanya menggunakan satu sensor, maka indeksnya adalah 0. Jika kamu ingin membaca lebih dari satu sensor, gunakan indeks 0 untuk satu sensor, indeks 1 untuk sensor lainnya, dan seterusnya.

Terakhir, tampilkan hasilnya pada Serial Monitor.

Serial.print(temperatureC);
Serial.println("ºC");
Serial.print(temperatureF);
Serial.println("ºF");

Pembacaan suhu baru diminta setiap 5 detik.

delay(5000);

Demonstrasi

Setelah mengunggah kode, kamu akan melihat hasil pembacaan sensor ditampilkan pada Serial Monitor.

Membaca Suhu dari Beberapa Sensor Suhu DS18B20

Sensor suhu DS18B20 berkomunikasi menggunakan protokol one-wire dan setiap sensor memiliki kode serial 64-bit yang unik, sehingga kamu dapat membaca suhu dari beberapa sensor hanya dengan satu GPIO. Kamu hanya perlu menghubungkan semua jalur data menjadi satu, seperti yang ditunjukkan pada diagram skematik berikut:

Kode (Beberapa DS18B20)

Kemudian, unggah kode berikut. Kode ini akan memindai semua perangkat pada GPIO 4 dan menampilkan suhu dari masing-masing sensor. (Sketch ini didasarkan pada contoh yang disediakan oleh library DallasTemperature).

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com  
*********/

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

// Data wire is plugged TO GPIO 4
#define ONE_WIRE_BUS 4

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Number of temperature devices found
int numberOfDevices;

// We'll use this variable to store a found device address
DeviceAddress tempDeviceAddress; 

void setup(){
  // start serial port
  Serial.begin(115200);
  
  // Start up the library
  sensors.begin();
  
  // Grab a count of devices on the wire
  numberOfDevices = sensors.getDeviceCount();
  
  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  Serial.print(numberOfDevices, DEC);
  Serial.println(" devices.");

  // Loop through each device, print out address
  for(int i=0;i<numberOfDevices; i++){
    // Search the wire for address
    if(sensors.getAddress(tempDeviceAddress, i)){
      Serial.print("Found device ");
      Serial.print(i, DEC);
      Serial.print(" with address: ");
      printAddress(tempDeviceAddress);
      Serial.println();
    } else {
      Serial.print("Found ghost device at ");
      Serial.print(i, DEC);
      Serial.print(" but could not detect address. Check power and cabling");
    }
  }
}

void loop(){ 
  sensors.requestTemperatures(); // Send the command to get temperatures
  
  // Loop through each device, print out temperature data
  for(int i=0;i<numberOfDevices; i++){
    // Search the wire for address
    if(sensors.getAddress(tempDeviceAddress, i)){
      // Output the device ID
      Serial.print("Temperature for device: ");
      Serial.println(i,DEC);
      // Print the data
      float tempC = sensors.getTempC(tempDeviceAddress);
      Serial.print("Temp C: ");
      Serial.print(tempC);
      Serial.print(" Temp F: ");
      Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
    }
  }
  delay(5000);
}

// function to print a device address
void printAddress(DeviceAddress deviceAddress) {
  for (uint8_t i = 0; i < 8; i++){
    if (deviceAddress[i] < 16) Serial.print("0");
      Serial.print(deviceAddress[i], HEX);
  }
}

Demonstrasi

Dalam contoh ini, kami menggunakan tiga sensor suhu DS18B20. Berikut adalah tampilan yang muncul pada Serial Monitor Arduino IDE.

Menampilkan Pembacaan Suhu DS18B20 di Web Server

Untuk membangun web server, kita akan menggunakan library ESPAsyncWebServer yang menyediakan cara mudah untuk membuat web server asinkron. Membangun web server asinkron memiliki beberapa keuntungan. Kami menyarankan kamu untuk melihat sekilas dokumentasi library tersebut di halaman GitHub-nya.

Menginstal library ESPAsyncWebServer dan AsyncTCP
Kamu perlu menginstal library berikut di Arduino IDE untuk membangun web server pada proyek ini:

ESPAsyncWebServer oleh ESP32Async
AsyncTCP oleh ESP32Async

Kamu dapat menginstal library-library tersebut melalui Library Manager di Arduino IDE. Masuk ke Sketch > Include Library > Manage Libraries lalu cari nama library yang dimaksud.

Kode (DS18B20 Async Web Server)
Buka Arduino IDE kamu dan salin kode berikut.

/*********
  Rui Santos & Sara Santos - Random Nerd Tutorials
  Complete project details at https://RandomNerdTutorials.com  
*********/

// Import required libraries
#ifdef ESP32
  #include <WiFi.h>
  #include <ESPAsyncWebServer.h>
#else
  #include <Arduino.h>
  #include <ESP8266WiFi.h>
  #include <Hash.h>
  #include <ESPAsyncTCP.h>
  #include <ESPAsyncWebServer.h>
#endif
#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is connected to GPIO 4
#define ONE_WIRE_BUS 4

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

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

// Variables to store temperature values
String temperatureF = "";
String temperatureC = "";

// Timer variables
unsigned long lastTime = 0;  
unsigned long timerDelay = 30000;

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

String readDSTemperatureC() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempC = sensors.getTempCByIndex(0);

  if(tempC == -127.00) {
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Celsius: ");
    Serial.println(tempC); 
  }
  return String(tempC);
}

String readDSTemperatureF() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempF = sensors.getTempFByIndex(0);

  if(int(tempF) == -196){
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Fahrenheit: ");
    Serial.println(tempF);
  }
  return String(tempF);
}

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
  <style>
    html {
     font-family: Arial;
     display: inline-block;
     margin: 0px auto;
     text-align: center;
    }
    h2 { font-size: 3.0rem; }
    p { font-size: 3.0rem; }
    .units { font-size: 1.2rem; }
    .ds-labels{
      font-size: 1.5rem;
      vertical-align:middle;
      padding-bottom: 15px;
    }
  </style>
</head>
<body>
  <h2>ESP DS18B20 Server</h2>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Celsius</span> 
    <span id="temperaturec">%TEMPERATUREC%</span>
    <sup class="units">&deg;C</sup>
  </p>
  <p>
    <i class="fas fa-thermometer-half" style="color:#059e8a;"></i> 
    <span class="ds-labels">Temperature Fahrenheit</span>
    <span id="temperaturef">%TEMPERATUREF%</span>
    <sup class="units">&deg;F</sup>
  </p>
</body>
<script>
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturec").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturec", true);
  xhttp.send();
}, 10000) ;
setInterval(function ( ) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("temperaturef").innerHTML = this.responseText;
    }
  };
  xhttp.open("GET", "/temperaturef", true);
  xhttp.send();
}, 10000) ;
</script>
</html>)rawliteral";

// Replaces placeholder with DS18B20 values
String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATUREC"){
    return temperatureC;
  }
  else if(var == "TEMPERATUREF"){
    return temperatureF;
  }
  return String();
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);
  Serial.println();
  
  // Start up the DS18B20 library
  sensors.begin();

  temperatureC = readDSTemperatureC();
  temperatureF = readDSTemperatureF();

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  Serial.println("Connecting to WiFi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  
  // Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", index_html, processor);
  });
  server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", temperatureC.c_str());
  });
  server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/plain", temperatureF.c_str());
  });
  // Start server
  server.begin();
}
 
void loop(){
  if ((millis() - lastTime) > timerDelay) {
    temperatureC = readDSTemperatureC();
    temperatureF = readDSTemperatureF();
    lastTime = millis();
  }  
}

Masukkan kredensial jaringan kamu ke dalam variabel berikut dan kode akan langsung berfungsi.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Cara Kerja Kode
Pada paragraf berikut, kami akan menjelaskan bagaimana kode tersebut bekerja. Lanjutkan membaca jika kamu ingin mempelajarinya lebih lanjut, atau langsung lompat ke bagian “Demonstration” untuk melihat hasil akhirnya.

Mengimpor library
Pertama, impor library yang diperlukan untuk papan ESP32

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

Menginisialisasi Sensor DS18B20
Tentukan GPIO yang terhubung ke pin data DS18B20. Dalam hal ini, terhubung ke GPIO 4.

#define ONE_WIRE_BUS 4

Membuat instance yang dibutuhkan untuk menginisialisasi sensor:

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

// Pass our oneWire reference to Dallas Temperature sensor 
DallasTemperature sensors(&oneWire);

Mengatur kredensial jaringan Anda
Masukkan kredensial jaringan Anda ke dalam variabel berikut, agar ESP8266 dapat terhubung ke jaringan lokal Anda.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Buat objek AsyncWebServer pada port 80.

AsyncWebServer server(80);

Fungsi pembacaan suhu.

Selanjutnya, kita membuat dua fungsi untuk membaca suhu.

Fungsi readDSTemperatureC() mengembalikan nilai suhu dalam derajat Celcius.

String readDSTemperatureC() {
  // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  float tempC = sensors.getTempCByIndex(0);

  if(tempC == -127.00){
    Serial.println("Failed to read from DS18B20 sensor");
    return "--";
  } else {
    Serial.print("Temperature Celsius: ");
    Serial.println(tempC); 
  }
  return String(tempC);
}

Jika sensor tidak dapat memperoleh pembacaan yang valid, maka akan mengembalikan nilai -127. Oleh karena itu, terdapat pernyataan if yang mengembalikan dua tanda strip (–) jika sensor gagal membaca data.

if(tempC == -127.00){
  Serial.println("Failed to read from DS18B20 sensor");
  return "--";

Fungsi readDSTemperatureF() bekerja dengan cara yang sama, tetapi mengembalikan nilai suhu dalam derajat Fahrenheit.

Nilai pembacaan dikembalikan dalam tipe data string.

Untuk mengonversi nilai float menjadi string, gunakan fungsi String().

return String(tempC);

Membangun Halaman Web

Langkah selanjutnya adalah membangun halaman web. Kode HTML dan CSS yang diperlukan untuk membangun halaman web disimpan dalam variabel index_html.

Di dalam teks HTML terdapat TEMPERATUREC dan TEMPERATUREF yang diapit oleh tanda %. Ini merupakan placeholder untuk nilai suhu.

Artinya, teks %TEMPERATUREC% ini berfungsi seperti variabel yang akan digantikan oleh nilai suhu aktual dari sensor. Placeholder pada teks HTML harus diletakkan di antara tanda %.

Kami telah menjelaskan secara sangat rinci bagaimana HTML dan CSS yang digunakan pada web server ini bekerja pada tutorial sebelumnya. Jadi, jika ingin mempelajari lebih lanjut, silakan merujuk ke proyek berikut:

DHT11/DHT22 Temperature and Humidity Web Server dengan Arduino IDE

Processor

Selanjutnya, kita perlu membuat fungsi processor(), yang akan menggantikan placeholder pada teks HTML dengan nilai suhu yang sebenarnya.

String processor(const String& var){
  //Serial.println(var);
  if(var == "TEMPERATUREC"){
    return readDSTemperatureC();
  }
  else if(var == "TEMPERATUREF"){
    return readDSTemperatureF();
  }
  return String();
}

Saat halaman web diminta, kita memeriksa apakah HTML memiliki placeholder. Jika ditemukan placeholder %TEMPERATUREC%, maka kita mengembalikan nilai suhu dalam Celcius dengan memanggil fungsi readDSTemperatureC() yang telah dibuat sebelumnya.

if(var == "TEMPERATUREC"){
  return readDSTemperatureC();
}

Jika placeholder adalah %TEMPERATUREF%, maka kita mengembalikan nilai suhu dalam Fahrenheit.

else if(var == "TEMPERATUREF"){
  return readDSTemperatureF();
}

setup()

Pada fungsi setup(), lakukan inisialisasi Serial Monitor untuk keperluan debugging.

Serial.begin(115200);

Inisialisasi sensor suhu DS18B20.

sensors.begin();

Hubungkan ESP32 ke jaringan lokal dan tampilkan alamat IP ESP32.

WiFi.begin(ssid, password);
Serial.println("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}
Serial.println();

// Print ESP8266 Local IP Address
Serial.println(WiFi.localIP());

Terakhir, tambahkan baris kode berikut untuk menangani web server.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html, processor);
});
server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDSTemperatureC().c_str());
});
server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDSTemperatureF().c_str());
});

Ketika kita melakukan request ke root URL (/), server akan mengirimkan teks HTML yang disimpan dalam variabel index_html. Kita juga perlu menyertakan fungsi processor, yang bertugas menggantikan semua placeholder dengan nilai yang sesuai.

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/html", index_html, processor);
});

Kita perlu menambahkan dua handler tambahan untuk memperbarui pembacaan suhu.
Saat menerima request pada URL /temperaturec, server akan mengirimkan nilai suhu terbaru dalam bentuk plain text. Karena dikirim sebagai karakter, maka digunakan metode c_str().

server.on("/temperaturec", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDSTemperatureC().c_str());
});

Proses yang sama diterapkan untuk suhu dalam satuan Fahrenheit.

server.on("/temperaturef", HTTP_GET, [](AsyncWebServerRequest *request){
  request->send_P(200, "text/plain", readDSTemperatureF().c_str());
});

Terakhir, jalankan web server.

server.begin();

Karena ini adalah web server asynchronous, kita tidak perlu menuliskan apa pun di fungsi loop().

void loop(){

}

Kurang lebih seperti itulah cara kerja kode tersebut.

Demonstrasi

Setelah kode diunggah, buka Serial Monitor pada Arduino IDE dengan baud rate 115200. Tekan tombol RST (reset) pada board ESP32, dan setelah beberapa detik alamat IP akan muncul.

Pada jaringan lokal, buka browser lalu masukkan alamat IP ESP32 tersebut.

Sekarang kamu dapat melihat suhu dalam Celcius dan Fahrenheit pada web server. Nilai pembacaan sensor akan terbarui secara otomatis tanpa perlu me-refresh halaman web.

Selesai. Tidak ada loop kosong yang sia-sia, tidak ada refresh manual, dan web server tetap jalan seperti

Tinggalkan Balasan