Andiamo a vedere come collegare ed utilizzare con Arduino il sensore di temperatura DS18B20 del kit Elegoo (il produttore di questi sensori è unico, così come le librerie di comunicazione).
Il sensore digitale DS18B20 è un sensore di temperatura molto più sensibile del modulo composito visto precedentemente qui. È infatti possibile raggiungere una risoluzione da 9 a 12 bit.
Ciò che però distingue davvero questo modulo dal precedente è la possibilità di aggiungere più sensori sullo stesso bus.
Ognuno di questi sensori ha infatti un numero seriale univoco, che ci permette di rivolgerci allo specifico sensore senza fare confusione tra quelli connessi sul bus.
Il protocollo utilizzato è standard, e lo troveremo in altri sensori: OneWire. Questo protocollo utilizza un pin digitale da cui inizia un bus, e permette di comunicare con uno specifico dispositivo sul bus sapendo il suo indirizzo univoco.
Questo sensore si trova in vari formati, tra cui in alcune configurazioni adatte all’immersione in acqua e all’utilizzo all’esterno, ad esempio il seguente:
Struttura Modulo

Specifiche Tecniche
Riportiamo qui di seguito le specifiche tecniche del sensore del kit Elegoo. Per altri sensori, è semplice procurarsi il file delle specifiche in rete.
Sensore Temperatura
Intervallo misurazione | -55, +125 °C |
Risoluzione | 9-12 Bit |
Accuratezza | ± 0.5°C (da -10°C a +85°C) |

Caratteristiche Modulo
Tensione Alimentazione | DC 3.3V – 5.5V |
Corrente Alimentazione | Misurazione: 1.5mA (max) Standby: 3µA (max) |
Tempo lettura | Risoluzione – 9bit: 93.75ms – 10bit: 187.5ms – 11bit: 375ms – 12bit: 750ms |
Schema Collegamento
Normalmente, per il sensore DS18B20 avremmo bisogno di una resistenza di pullup. Inoltre possiamo trovarlo in due configurazioni:
- Modalità parassita: il sensore non è alimentato esternamente, ma si utilizza unicamente il filo del bus sia per l’alimentazione che per la comunicazione (da qui il nome del protocollo, OneWire)
- Modalità normale: il sensore è alimentato da un’alimentazione esterna, e usa il bus solo per comunicare



Nel nostro modulo, che opera in modalità normale, la resistenza di pullup è già integrata sulla scheda.
Ci limitiamo quindi a collegare l’alimentazione ai pin di alimentazione di Arduino, mentre il pin dei dati va collegato ad uno qualsiasi dei pin digitali di Arduino.

La lunghezza massima teorica per il bus di trasmissione dipende fortemente dalla modalità di connessione dei sensori e dal cavo utilizzato.
Mentre per distanze fino ad un metro, se il cavo del sensore non passa vicino a fonti di disturbo elettromagnetico (quali fili della rete elettrica), non ci sono particolari accorgimenti da avere, nel caso contrario è bene tenere a mente le seguenti indicazioni:
- Usare un cavo schermato. È possibile acquistare un cavo schermato soltanto a 3 fili, oppure utilizzare un cavo Ethernet standard.
- Tenere il cavo del sensore non schermato più corto possibile.
- Collegare sempre lo schermo del cavo a terra (non a GND!), almeno da uno dei due lati.
- Nel caso di cavo Ethernet, maggiore la certificazione del cavo (Cat5E, Cat6, …), maggiore sarà la distanza che sarà possibile raggiungere. Si consiglia di collegare i fili del cavo come segue, per minimizzare le interferenze:
Descrizione Filo | Colore | Collegato a |
Transmit Data+ | Bianco con una striscia verde![]() | GND |
Transmit Data- | Verde con una striscia bianca o completamente verde![]() | GND |
Receive Data+ | Bianco con una striscia arancione![]() | GND |
Bi-directional+ | Blu con una striscia bianca o completamente blu![]() | DATA |
Bi-directional- | Bianco con una striscia blu![]() | GND |
Receive Data- | Arancione con una striscia bianca o completamente arancione![]() | GND |
Bi-directional+ | Bianco con una striscia marrone![]() | VCC |
Bi-directional- | Marrone con una striscia bianca o completamente marrone![]() | GND |
In questo modo è possibile connettere sullo stesso bus fino a 20 sensori di temperatura DS18B20, oppure dislocare un singolo sensore di temperatura molto lontano e poi comunicarci con Arduino.
Codice
Per il sensore di temperatura DS18B20 su Arduino esiste un set di librerie ufficiali molto semplici da usare.
Per prima cosa, andiamo ad installare le librerie “OneWire” e “DallasTemperature” per la comunicazione. In caso di dubbi, consultare questa guida.
Si tratta di librerie ufficiali presenti nella sezione di gestione librerie di Arduino IDE.


Con un solo sensore
#include <OneWire.h>
#include <DallasTemperature.h>
#define SENSOR_BUS_PIN 2
OneWire oneWire(SENSOR_BUS_PIN); //Creiamo istanza OneWire per utilizzare il canale di comunicazione
DallasTemperature sensors(&oneWire); //Passiamo il canale di comunicazione alla libreria della Dallas
void setup() {
Serial.begin(9600);
Serial.println("DS18B20 test");
sensors.begin(); //Inizializzo comunicazione
}
void loop() {
Serial.print("Richiesta temperatura... ");
//L'esecuzione si blocca sul comando per il tempo richiesto (dipende dalla risoluzione impostata)
sensors.requestTemperatures(); //Invio comando per leggere temperatura
//Stampo temperatura del (primo) sensore del bus
Serial.print(sensors.getTempCByIndex(0));
Serial.println("°C");
}
Con più sensori
#include <OneWire.h>
#include <DallasTemperature.h>
#define SENSOR_BUS_PIN 2
OneWire oneWire(SENSOR_BUS_PIN); //Creiamo istanza OneWire per utilizzare il canale di comunicazione
DallasTemperature sensors(&oneWire); //Passiamo il canale di comunicazione alla libreria della Dallas
void setup() {
Serial.begin(9600);
Serial.println("DS18B20 test");
sensors.begin(); //Inizializzo comunicazione
//Scansione sensori sul bus
Serial.print("Scansione dispositivi... ");
Serial.print("Trovati ");
int numSensori = sensors.getDeviceCount();
Serial.print(numSensori, DEC);
Serial.println(" sensori.");
Serial.println("");
//Mi stampo i loro indirizzi univoci
Serial.println("Stampo indirizzi...");
DeviceAddress Termometro;
for (int i = 0; i < numSensori; i++)
{
Serial.print("Sensore ");
Serial.print(i+1);
Serial.print(" : ");
sensors.getAddress(Termometro, i);
printAddress(Termometro);
}
Serial.println("");
}
void printAddress(DeviceAddress deviceAddress){
for (unsigned int i = 0; i < 8; i++){
Serial.print("0x");
if (deviceAddress[i] < 0x10)
Serial.print("0");
Serial.print(deviceAddress[i], HEX);
if (i < 7)
Serial.print(", ");
}
Serial.println("");
}
void loop(){
}
#include <OneWire.h>
#include <DallasTemperature.h>
#define SENSOR_BUS_PIN 2
OneWire oneWire(SENSOR_BUS_PIN); //Creiamo istanza OneWire per utilizzare il canale di comunicazione
DallasTemperature sensors(&oneWire); //Passiamo il canale di comunicazione alla libreria della Dallas
int numSensori = 0;
void setup() {
Serial.begin(9600);
Serial.println("DS18B20 test");
sensors.begin(); //Inizializzo comunicazione
//Scansione sensori sul bus
Serial.print("Scansione dispositivi... ");
Serial.print("Trovati ");
numSensori = sensors.getDeviceCount();
Serial.print(numSensori, DEC);
Serial.println(" sensori.");
Serial.println("");
}
void loop() {
Serial.print("Richiesta temperatura... ");
//L'esecuzione si blocca sul comando per il tempo richiesto (dipende dalla risoluzione impostata)
sensors.requestTemperatures(); //Invio comando per leggere temperatura
Serial.println("OK");
//Stampo temperatura del sensore i-esimo
for(int i=0;i<numSensori;i++){
printSensor(i);
}
}
void printSensor(int i){
Serial.print("Sensore ");
Serial.print(i+1);
Serial.print(": ");
float tempC = sensors.getTempCByIndex(i);
Serial.print(tempC);
Serial.print("°C | ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
Serial.println("°F");
}
#include <OneWire.h>
#include <DallasTemperature.h>
#define SENSOR_BUS_PIN 2
OneWire oneWire(SENSOR_BUS_PIN); //Creiamo istanza OneWire per utilizzare il canale di comunicazione
DallasTemperature sensors(&oneWire); //Passiamo il canale di comunicazione alla libreria della Dallas
//Ottenuti con il codice mostrato prima
DeviceAddress sensore1 = { 0x28, 0xAA, 0x4F, 0x44, 0x50, 0x14, 0x01, 0x17 };
DeviceAddress sensore2 = { 0x28, 0x6F, 0x0F, 0x29, 0x00, 0x00, 0x80, 0xF9 };
void setup() {
Serial.begin(9600);
Serial.println("DS18B20 test");
sensors.begin(); //Inizializzo comunicazione
}
void loop() {
Serial.print("Richiesta temperatura... ");
//L'esecuzione si blocca sul comando per il tempo richiesto (dipende dalla risoluzione impostata)
sensors.requestTemperatures(); //Invio comando per leggere temperatura di tutti i sensori connessi
/*
* È anche possibile leggere la temperatura singolarmente
* con il comando sensors.requestTemperaturesByAddress(sensore1).
* Il comando è però più lento nel caso di letture da più sensori
*/
Serial.println("OK");
//Stampo temperatura del sensore 1
Serial.print("Sensore 1: ");
printSensor(sensore1);
//Stampo temperatura del sensore 2
Serial.print("Sensore 2: ");
printSensor(sensore2);
}
void printSensor(DeviceAddress addr){
float tempC = sensors.getTempC(addr);
Serial.print(tempC);
Serial.print("°C | ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
Serial.print("°F (Risoluzione ");
Serial.print(sensors.getResolution(addr), DEC);
Serial.println("bit)");
}
Impostare la risoluzione dei sensori
La risoluzione del sensore è scritta in una sua memoria retentiva interna (EEPROM). Questo significa che non va persa quando togliamo l’alimentazione al sensore.
Tuttavia le memorie EEPROM possono essere scritte solo un numero finito di volte. Per il nostro sensore DS18B20 abbiamo 55000 scritture, ciascuna rimane inalterata per 10 anni.
È quindi buona cosa utilizzare uno script apposito per impostare la risoluzione, e non farlo nel codice che andremo ad utilizzare per la lettura. Così facendo evitiamo nel tempo di danneggiare la EEPROM e dover buttare il sensore.
Inoltre per impostare la risoluzione è necessario conoscere l’indirizzo univoco del sensore. Questo può essere fatto con il codice mostrato prima.
#include <OneWire.h>
#include <DallasTemperature.h>
#define SENSOR_BUS_PIN 2
OneWire oneWire(SENSOR_BUS_PIN); //Creiamo istanza OneWire per utilizzare il canale di comunicazione
DallasTemperature sensors(&oneWire); //Passiamo il canale di comunicazione alla libreria della Dallas
//Ottenuti con il codice mostrato prima
DeviceAddress sensore1 = { 0x28, 0xAA, 0x4F, 0x44, 0x50, 0x14, 0x01, 0x17 };
void setup() {
Serial.begin(9600);
Serial.println("DS18B20 set risoluzione");
sensors.begin(); //Inizializzo comunicazione
//Come valori di risoluzione sono consentiti: 9, 10, 11, 12
sensors.setResolution(sensore1, 9);
Serial.print("Risoluzione Sensore: ");
Serial.println(sensors.getResolution(sensore1), DEC);
Serial.println();
}
void loop() {
}
Cambiare la risoluzione influirà notevolmente sul tempo di lettura, e ci permetterà di evitare cicli lenti nel codice qualora non servisse una precisione elevata.
Vittorio
Spiegazione Super Esauriente e fatta mooolto bene, complimenti.
Ho una domanda però, dici di utilizzare un cavo con sezione 0,6 (equivalente a 19 AWG), ma cavi LAN twistati nemmeno quelli in categoria 8 arrivano a quelle sezioni.
Per caso ti riferisci a due casi distinti? Sezione 0,6 o cavo LAN?
Ovviamente mi riferisco al caso di avere diverse sonde…
Inoltre ho notato che se l’alimentazione viene fornita a 3,3 V è opportuno abbassare la resistenza di pullup.
Complimenti ancora…
Vittorio
Andrea Aspesi
Grazie Vittorio. L’info sulla sezione era in realtà un refuso, ho provveduto a toglierla. Un normale cavo LAN twistato (ad esempio un CAT 5/5E) dovrebbe andare più che bene.
Come giustamente osservi tu, minore la tensione, maggiore è in genere la sensibilità del circuito integrato alla caduta di tensione dovuta al cavo. Lo stesso vale anche per un cavo lungo: se non funziona con 4.7k, è possibile provare ad abbassare la resistenza di pull-up per “forzare” maggiormente verso Vdd la linea. Ovviamente la resistenza deve essere abbastanza alta da permettere al sensore di poter tirare verso GND la linea senza superare i suoi limiti interni, quindi per il valore minimo di resistenza è sempre opportuno leggere la documentazione dell’integrato del sensore.
Se hai trovato un valore che funziona bene con 3.3V, ti invito a mettere la tua configurazione qui sotto per i prossimi lettori!
Giulio
Spiegazione super esauriente, con esempi molto chiari.
Vorrei sapere, però, se esiste un wiki della libreria con la classica elencazione dei tipi, metodi e costruttori inclusi per poter apprezzare tutti i dettagli degli esempi proposti ed eventualmente modificarli secondo esigenza con cognizione di causa.
Sono andato sul sito
https://github.com/milesburton/Arduino-Temperature-Control-Library
ma il link per ulteriore documentazione https://www.milesburton.com/Dallas_Temperature_Control_Library
pare non funzionare.
Puoi aiutarmi a trovare il documento ?
Giulio
Andrea Aspesi
Ciao Giulio, spesso capita che in una libreria non sia inclusa una wiki con metodi e costruttori.
Puoi però facilmente estrarla guardando il file .h della libreria, che spesso contiene i commenti (o almeno dovrebbe se è scritta bene 😉 )
I metodi e i costruttori che puoi usare sono riportati nella classe sotto “public”. Te ne riporto alcuni qui per te, a titolo di esempio:
Quando sei in dubbio sul significato di un parametro, ti può aiutare andare a controllare anche il file .cpp
Ad esempio, per il metodo getAddress, troverai: