Il sensore di temperatura Dallas DS18B20 è un dispositivo versatile e ampiamente utilizzato per misurare la temperatura in varie applicazioni. Quando combinato con il potente microcontrollore ESP32 o esp8266, diventa possibile collegare più sensori DS18B20 in un unico circuito e anche su lunghe distanze.
Questo articolo esplorerà come utilizzare il protocollo OneWire per comunicare con più sensori di temperatura Dallas DS18B20 e come interfacciarli con una scheda ESP32 o esp8266. Tratteremo anche come gestire i problemi che possono sorgere lavorando con linee OneWire lunghe e dispositivi multipli.
Che tu sia un hobbista, un ingegnere o un appassionato di fai-da-te, questo articolo fornirà una guida completa per iniziare con il Dallas DS18B20 e l’ESP32 o esp8266.
Caratteristiche
- Interfaccia unica 1-Wire® richiede solo un pin di porta per la comunicazione
- Riduce il numero di componenti con sensore di temperatura integrato e EEPROM
- Misura temperature da -55°C a +125°C (-67°F a +257°F)
- Precisione di ±0.5°C da -10°C a +85°C
- Risoluzione programmabile da 9 bit a 12 bit
- Non sono richiesti componenti esterni
- Modalità di alimentazione parasitica richiede solo 2 pin per il funzionamento (DQ e GND)
- Semplifica le applicazioni di rilevamento della temperatura distribuita con capacità multidrop
- Ogni dispositivo ha un codice seriale unico a 64 bit memorizzato nella ROM integrata
- Impostazioni di allarme NV (non volatili) definite dall’utente con comando di ricerca allarmi che identifica i dispositivi con temperature fuori dai limiti programmati
- Disponibile nei formati 8-Pin SO (150 mils), 8-Pin µSOP e 3-Pin TO-92
Datasheet
Pinout
Il sensore ha più varianti, ma il cablaggio rimane lo stesso.
GND: collegare a GND.
DATA: bus dati One-Wire.
VCC: alimentazione (3,3 – 5 V), ma in modalità parasitica, si può collegare a GND.
Ecco il sensore AliExpress
Introduzione alla rete OneWire
Quando crei una rete, devi prestare attenzione agli amplificatori di rilevamento della corrente (CSA), che vengono utilizzati per misurare la corrente che scorre attraverso un circuito. I CSA offrono vantaggi in varie applicazioni, tra cui la gestione dell’energia, il controllo dei motori e il monitoraggio delle batterie. Esistono diversi tipi di CSA, inclusi gli amplificatori lato alto e lato basso, e le varie architetture utilizzate nel loro design.
Non approfondiremo le specifiche chiave e i parametri di prestazione dei CSA, come la tensione di offset in ingresso, la larghezza di banda e il rapporto di reiezione del modo comune (CMRR). Ma descriveremo i diversi tipi di resistori per il rilevamento della corrente e come selezionare quello giusto per un’applicazione particolare.
Proseguiremo discutendo considerazioni pratiche per l’uso dei CSA, incluse tecniche di layout e messa a terra, riduzione del rumore e compensazione della temperatura. Mostreremo diversi circuiti applicativi per i CSA, come la semplice conversione da tensione a corrente, il rilevamento della tensione differenziale e il rilevamento della corrente basato su shunt.
Fattori di prestazione della rete OneWire
Le due misurazioni critiche nelle prestazioni di una rete 1-Wire sono: il raggio e il peso. Il raggio di una rete 1-Wire è la distanza del cavo tra il master e lo slave più distante ed è misurato in metri. Il peso di una rete 1-Wire è la lunghezza totale del cavo nella rete, anch’essa misurata in metri.
Ad esempio, una rete 1-Wire con una configurazione a stella che ha tre rami di 10m, 20m e 30m avrebbe un raggio di 30m (la distanza dal master allo slave più lontano) e un peso di 60m (la lunghezza totale del cavo nella rete, che è 10m + 20m + 30m).
In generale, il peso della rete limita il tempo di salita sul cavo, mentre il raggio determina il tempo di riflessione del segnale più lento. Queste informazioni sono essenziali per progettare e risolvere i problemi delle reti 1-Wire per garantire che operino in modo efficiente e affidabile.
Topologie della rete OneWire
Sebbene le reti OneWire siano spesso strutture ragionevolmente “libere”, di solito rientrano in alcune categorie generalizzate basate sulla distribuzione degli slave 1-Wire e sull’organizzazione dei cavi di interconnessione.
Topologia lineare
Il bus 1-Wire è un singolo cavo, che parte dal master e si estende fino al dispositivo slave più distante. Altri slave sono collegati al bus 1-Wire con rami insignificanti (< 3m) o “stub”.
Topologia a stub
Il bus 1-Wire è una linea principale singola, che parte dal master e si estende fino allo slave più distante. Altri slave sono collegati alla linea principale attraverso rami o stub di 3m o più di lunghezza.
Topologia a stella
Il bus 1-Wire è suddiviso vicino al master e si estende in più rami di lunghezze variabili. Sono presenti dispositivi slave lungo i rami o alle loro estremità.
I test hanno dimostrato che le topologie di rete a stella non commutate (ovvero quelle con diversi rami che divergono al master) sono le più difficili da rendere affidabili. Il punto di giunzione dei vari rami presenta impedenze altamente disallineate; le riflessioni dall’estremità di un ramo possono percorrere distanze pari quasi al peso della rete (piuttosto che al raggio) e causare errori nei dati. Per questo motivo, la topologia a stella non commutata non è raccomandata e non si possono fare garanzie sulle sue prestazioni.
Quando si mescolano diverse topologie, diventa molto più difficile determinare i limiti pratici della rete. Come regola generale, il progettista dovrebbe applicare i criteri più conservativi in questi casi.
Reti commutate
Per consentire alle reti di crescere in complessità senza aumentare il peso e il raggio, la rete è divisa in sezioni che vengono commutate elettronicamente una alla volta.
Utilizzando switch analogici a bassa impedenza e alimentazione singola, la rete può fisicamente somigliare a una topologia ma elettricamente a un’altra. Questo significa che una configurazione a stella con uno switch su ogni ramo potrebbe in realtà somigliare a una topologia lineare.
In questo caso, solo un ramo è attivo in qualsiasi momento. L’esempio sopra appare come una rete a stella con un raggio di 150m e un peso di 450m. Tuttavia, quando si considera ogni percorso commutato individualmente, la rete è in realtà una topologia lineare e il peso è solo 150m. In generale, la nostra discussione sulle reti non commutate può essere applicata a ciascun segmento di una rete commutata.
Limitazioni della rete OneWire
Il raggio massimo e il peso di una rete OneWire sono determinati da diversi fattori. Alcuni di questi fattori possono essere controllati, mentre altri no. L’interfaccia lato master gioca un ruolo cruciale nel determinare la dimensione consentita di una rete OneWire. Deve fornire una corrente di pilotaggio sufficiente a superare il peso del cavo e degli slave, generare forme d’onda OneWire con tempi conformi alle specifiche e ottimizzate per i tempi di carica e scarica della rete, e fornire un accoppiamento d’impedenza adatto alla rete.
Il raggio di una rete 1-Wire è limitato da diversi fattori, inclusi i tempi delle riflessioni delle forme d’onda, il ritardo temporale prodotto dal cavo, la resistenza del cavo e il degrado dei livelli di segnale. Il peso della rete è limitato dalla capacità del cavo di essere caricato e scaricato abbastanza velocemente per soddisfare il protocollo 1-Wire.
Un semplice pull-up con resistenza ha una limitazione di peso di circa 200m. In confronto, il limite di peso può essere esteso a oltre 500m utilizzando design di master 1-Wire sofisticati con pull-up attivi che forniscono correnti più elevate sotto controllo logico.
Il raggio è limitato da fattori come tempi e resistenza del cavo, mentre il peso è limitato dalla capacità del cavo di essere caricato e scaricato rapidamente. I pull-up attivi possono estendere il limite di peso di una rete 1-Wire oltre i limiti dei semplici pull-up resistivi.
Problemi con la modalità parasitica
Il protocollo di comunicazione 1-Wire non solo facilita la comunicazione, ma fornisce anche l’alimentazione operativa per gli slave. Gli slave ottengono l’alimentazione dal bus quando la tensione sul bus è maggiore della tensione sul loro condensatore interno di accumulo di energia.
Tuttavia, in reti con troppi slave, la corrente fornita dal master potrebbe non essere sufficiente a mantenere la tensione operativa negli slave, causando guasti intermittenti che dipendono dai dati.
Lo scenario peggiore per l’alimentazione parasitica è una lunga sequenza di bit zero inviati dal master, poiché il bus trascorre la maggior parte del tempo nello stato basso, con poche opportunità per ricaricare gli slave.
Man mano che la tensione in ogni slave diminuisce, la capacità dello slave di pilotare il bus diminuisce, portando infine a uno stato di reset in cui lo slave smette di rispondere.
Quando lo slave riceve nuovamente una tensione operativa sufficiente, emette un impulso di presenza, che può corrompere altre attività sul bus.
Una possibile soluzione è mostrata nell’immagine sopra. In particolare, questa configurazione viene utilizzata per i sensori di temperatura ds18b20.
Il bus 1-Wire deve essere commutato sul pull-up forte entro 10 µs (max) dopo le conversioni di temperatura, e il bus deve essere mantenuto alto dal pull-up per la durata della conversione o del trasferimento dei dati. Nessuna altra attività può avere luogo sul bus 1-Wire mentre il pull-up è attivo.
Il DS18B20 può anche essere alimentato con il metodo convenzionale collegando un’alimentazione esterna al pin VDD, come mostrato. Il vantaggio di questo metodo è che il MOSFET pull-up non è richiesto e il bus 1-Wire è libero di trasportare altri segnali durante il tempo di conversione della temperatura.
Adattamento di impedenza distribuito
Il design del bus OneWire è semplice e a basso costo, e in genere si evitano componenti aggiuntivi.
Tuttavia, quando uno stub è collegato al bus, c’è un disallineamento di impedenza nel punto di ramificazione, che può causare riflessioni che interferiscono con altri slave sulla rete.
Per mitigare questo problema, un resistore in serie con lo stub può ridurre la gravità del disallineamento e l’ampiezza dell’energia riflessa.
L’implementazione più efficace di questo concetto utilizza resistori da 150½ in ogni punto in cui uno stub è collegato al tronco principale (considerando un livello logico di 5V). Questo riduce il disallineamento al punto di connessione di circa il 20% e attenua le riflessioni risultanti di circa il 40%. Tuttavia, è necessaria cautela poiché la resistenza aggiunta può ridurre l’immunità al rumore di circa l’80%.
In alternativa, valori resistivi di 100½ hanno dimostrato buone prestazioni e non degradano l’immunità al rumore così tanto.
Scelta del resistore pull-up per risolvere i problemi
Dopo alcune ricerche in rete, ho trovato soluzioni interessanti per migliorare la distanza in una rete con logica a 3,3V.
In una rete di media distanza con DS18B20, che funzionava con un cavo corto ma falliva con un cavo CAT3 di 5 metri, qualcuno ha aggiunto un resistore da 80 ohm (scelto semi-casualmente con un valore basso) in serie con la linea dati su entrambe le estremità del cavo, riducendo la velocità di salita e risolvendo il problema.
Con un cavo CAT5 non schermato di circa 40 metri e 7 sensori DS18B20, il GND è stato collegato a 2 fili di coppie intrecciate diverse. Gli altri fili di queste coppie intrecciate sono stati utilizzati per i dati e l’alimentazione. Tra GPIO4 e 3,3V, è stato utilizzato un resistore pull-up da 2,2k. Il maker raccoglieva dati dagli ultimi 2 sensori sul cavo, mentre un sensore al centro mostrava sempre 85000. Per me, ha iniziato a funzionare quando ho cambiato il resistore pull-up da 4,7k a 2,2k.
Cablaggio
La libreria One-Wire è uno standard per tutti i microcontrollori, quindi il dispositivo può essere utilizzato con molti microcontrollori. Abbiamo già mostrato la connessione del singolo sensore, ora vedremo come connettere e gestire più sensori.
Se hai bisogno di collegare un solo sensore, fai riferimento all’articolo precedente: “Dallas DS18B20 con ESP32 e ESP8266: introduzione e modalità parasitica”.
ESP32
Ecco il pinout di una delle schede prototipo ESP32 più comuni.
Ecco la mia selezione di ESP32 ESP32 Dev Kit v1 - TTGO T-Display 1.14 ESP32 - NodeMCU V3 V2 ESP8266 Lolin32 - NodeMCU ESP-32S - WeMos Lolin32 - WeMos Lolin32 mini - ESP32-CAM programmer - ESP32-CAM bundle - ESP32-WROOM-32 - ESP32-S
Modalità normale
In modalità normale, utilizzeremo una linea di alimentazione a 3,3V, quindi la connessione sarà la seguente.
La connessione è molto semplice.
ESP32 | DS18B20 |
---|---|
GND | GND |
3.3V | VCC |
D22 con pull-up | DATA |
Modalità normale con dispositivi multipli
Ora lo schema di connessione con una topologia lineare di 5 DS18B20.
Oppure in topologia a stella.
Modalità parasitica
In modalità parasitica, devi collegare anche il GND alla linea VCC del sensore, che riceverà l’alimentazione dalla linea dati.
ESP32 | DS18B20 |
---|---|
GND | GND |
GND | VCC |
D22 con pull-up | DATA |
Modalità parasitica con dispositivi multipli
Ecco la stessa configurazione in una topologia lineare.
Ed ecco una configurazione in topologia a stella.
ESP8266
Modalità normale
ESP8266 | DS18B20 |
---|---|
GND | GND |
3.3V | VCC |
D2 con pull-up | DATA |
Modalità normale con sensori multipli
Modalità parasitica
ESP8266 | DS18B20 |
---|---|
GND | GND |
GND | VCC |
D2 con pull-up | DATA |
Modalità parasitica con sensori multipli
Libreria
Prima di tutto, devi ricordare che questo sensore utilizza il protocollo One-Wire, quindi è necessario aggiungere la libreria OneWire.
Ogni piattaforma la possiede; spiegheremo meglio questo protocollo successivamente quando introdurremo l’uso di sensori multipli.
Dopo di ciò, è necessario installare una libreria che implementi il protocollo e le funzionalità del sensore.
Ho scelto la più utilizzata, la libreria DallasTemperature (in passato conosciuta come Dallas, ora Maxim).
Dispositivi supportati
Come descritto nel repository, questa libreria supporta i seguenti dispositivi:
- DS18B20
- DS18S20 (alcuni problemi con questo dispositivo)
- DS1822
- DS1820
- MAX31820
- MAX31850
Avrai bisogno di un resistore pull-up di circa 4,7 kOhm tra la linea dati One-Wire e il VCC. Se stai utilizzando il DS18B20, puoi usare la modalità parasitica e collegare il VCC al GND come descritto.
Risoluzione dei problemi
In caso di problemi con la conversione della temperatura (il risultato è -85), potrebbe essere necessario configurare un pull-up forte. Vedi la sezione Alimentazione del DS18B20 nel datasheet del DS18B20 (pagina 7) e usa il costruttore DallasTemperature(OneWire*, uint8_t)
.
Alimentazione del DS18B20 (normale/parasitica)
Il DS18B20 può essere alimentato da una sorgente esterna sul pin VDD, oppure può operare in modalità “parasitica”, che consente al DS18B20 di funzionare senza un’alimentazione locale esterna (collega il VDD al GND). Il DS18B20 “ruba” l’alimentazione dal bus One-Wire tramite il pin DQ quando il bus è alto. La carica rubata alimenta il DS18B20 mentre il bus è alto, e una parte della carica viene immagazzinata sul condensatore di potenza parasitica (CPP) per fornire energia quando il bus è basso.
Tuttavia, quando il DS18B20 esegue conversioni di temperatura o copia i dati dalla memoria scratchpad all’EEPROM, la corrente operativa può raggiungere valori fino a 1,5mA. Questa corrente può causare un calo di tensione inaccettabile attraverso il debole resistore pull-up del bus One-Wire e supera la corrente che il condensatore di potenza parasitica (CPP) può fornire.
Pull-up forte per la modalità parasitica
Per garantire che il DS18B20 abbia una fornitura di corrente sufficiente, è necessario fornire un pull-up forte sul bus One-Wire ogni volta che avvengono conversioni di temperatura o dati vengono copiati dalla memoria scratchpad all’EEPROM. Questo può essere realizzato utilizzando un MOSFET per portare direttamente il bus alla tensione di alimentazione.
Il bus One-Wire deve essere commutato sul pull-up forte entro 10 µs (massimo) dopo le conversioni di temperatura, e il bus deve essere mantenuto alto dal pull-up per la durata della conversione o del trasferimento dei dati. Nessuna altra attività può aver luogo sul bus One-Wire mentre il pull-up è abilitato.
Il DS18B20 può anche essere alimentato con il metodo convenzionale collegando un’alimentazione esterna al pin VDD, come mostrato. Il vantaggio di questo metodo è che il MOSFET pull-up non è richiesto e il bus One-Wire è libero di trasportare altri segnali durante il tempo di conversione della temperatura.
L’uso della modalità parasitica non è raccomandato per temperature superiori a +100°C, poiché il DS18B20 potrebbe non essere in grado di mantenere la comunicazione a causa delle correnti di dispersione più elevate che possono verificarsi a queste temperature.
Ridurre le dimensioni della libreria
Abbiamo incluso le definizioni REQUIRESNEW
e REQUIRESALARMS
. Se desideri ridurre il codice, sentiti libero di usarne una includendola nella libreria DallasTemperature.h.
#define REQUIRESNEW
oppure
#define REQUIRESALARMS
Codice
Quando lavori con dispositivi multipli, è essenziale identificarli in modo univoco. Bisogna ricordare che il DS18B20 ha un indirizzo interno che può essere utilizzato come UUID.
Per ESP8266, devi solo cambiare il pin da 22 a D2 o direttamente 4.
Ricerca di tutti i sensori collegati alla rete
Ecco un esempio semplice che cerca tutti i dispositivi One-Wire collegati a un intervallo di pin e genera un elenco di indirizzi che possono essere usati per gestire i DS18B20.
/**
* OneWire Library example
* Find all device (select starting end ending pin)
*
* Renzo Mischianti <www.mischianti.org>
*/
#define STARTING_PIN 22
#define ENDING_PIN 22
uint8_t findDevices(int pin);
#include <OneWire.h>
void setup()
{
Serial.begin(115200);
Serial.println("//\n// Start oneWire search \n//");
for (uint8_t pin = STARTING_PIN; pin <= ENDING_PIN; pin++)
{
findDevices(pin);
}
Serial.println("\n//\n// End oneWire search \n//");
}
void loop()
{
}
uint8_t findDevices(int pin)
{
OneWire ow(pin);
uint8_t address[8];
uint8_t count = 0;
if (ow.search(address))
{
Serial.print("\nDeviceAddress pin");
Serial.print(pin, DEC);
Serial.println("[] = {");
do {
count++;
Serial.print(" {");
for (uint8_t i = 0; i < 8; i++)
{
Serial.print("0x");
if (address[i] < 0x10) Serial.print("0");
Serial.print(address[i], HEX);
if (i < 7) Serial.print(", ");
}
Serial.println(" },");
} while (ow.search(address));
Serial.println("};");
Serial.print("// nr devices found: ");
Serial.println(count);
}
return count;
}
Nel mio caso, l’output seriale è il seguente:
//
// Start oneWire search
//
DeviceAddress pin22[] = {
{0x28, 0xFF, 0x64, 0x0E, 0x6C, 0x63, 0xD0, 0x15 },
{0x28, 0xFF, 0x64, 0x0E, 0x6C, 0x6F, 0x7A, 0x89 },
{0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x64, 0x7F, 0x3E },
{0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x5C, 0x1A, 0x3F },
{0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x5D, 0x66, 0xA0 },
};
// nr devices found: 5
//
// End oneWire search
//
Ha trovato correttamente 5 DS18B20 e ha generato l’array degli indirizzi.
Per ESP8266, il risultato diventa:
// Start oneWire search
//
DeviceAddress pin4[] = {
{0x28, 0xFF, 0x64, 0x0E, 0x6C, 0x63, 0xD0, 0x15 },
{0x28, 0xFF, 0x64, 0x0E, 0x6C, 0x6F, 0x7A, 0x89 },
{0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x64, 0x7F, 0x3E },
{0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x5C, 0x1A, 0x3F },
{0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x5D, 0x66, 0xA0 },
};
// nr devices found: 5
//
// End oneWire search
//
Ottenere informazioni e temperatura da un array di indirizzi
Con l’array dello sketch precedente, creeremo un nuovo sketch per leggere la temperatura.
/**
* From a list of thermostat address
* generated with the previous search sketch
* we are going to get the
* temperature of every device
*
* by Renzo Mischianti <www.mischianti.org>
*
* https://mischianti.org
*
*/
// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 22
#define ONE_WIRE_BUS 22
#define TEMPERATURE_PRECISION 9
// 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);
// The array generated from the search sketch
DeviceAddress pin22[] = {
{0x28, 0xFF, 0x64, 0x0E, 0x6C, 0x63, 0xD0, 0x15 },
{0x28, 0xFF, 0x64, 0x0E, 0x6C, 0x6F, 0x7A, 0x89 },
{0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x64, 0x7F, 0x3E },
{0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x5C, 0x1A, 0x3F },
{0x28, 0xFF, 0x64, 0x0E, 0x6D, 0x5D, 0x66, 0xA0 },
};
void setup(void)
{
// start serial port
Serial.begin(115200);
Serial.println("Dallas Temperature IC Control ");
// Start up the library
sensors.begin();
// locate devices on the bus
Serial.print("Locating devices...");
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode()) Serial.println("ON");
else Serial.println("OFF");
// set the temperature accurancy
for (int i = 0; i < 5; i++) {
// set the resolution to 9 bit per device
sensors.setResolution(pin22[i], TEMPERATURE_PRECISION);
}
}
// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
// zero pad the address if necessary
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
if(tempC == DEVICE_DISCONNECTED_C)
{
Serial.println("Error: Could not read temperature data");
return;
}
Serial.print("Temp C: ");
Serial.print(tempC);
Serial.print(" Temp F: ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
}
/*
Main function, calls the temperatures in a loop.
*/
void loop(void)
{
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.print("Requesting temperatures...");
sensors.requestTemperatures();
Serial.println("DONE");
for (int i = 0; i < 5; i++) {
// print the device information
Serial.print("Device Address: ");
printAddress(pin22[i]);
Serial.print(" of ");
Serial.print(i);
Serial.print(" sensor -> ");
printTemperature(pin22[i]);
Serial.println();
}
delay(2000);
}
Il risultato nel monitor seriale sarà simile a questo:
Dallas Temperature IC Control
Locating devices...Found 5 devices.
Parasite power is: OFF
Requesting temperatures...DONE
Device Address: 28FF640E6C63D015 of 0 sensor -> Temp C: 21.12 Temp F: 70.03
Device Address: 28FF640E6C6F7A89 of 1 sensor -> Temp C: 21.37 Temp F: 70.47
Device Address: 28FF640E6D647F3E of 2 sensor -> Temp C: 21.25 Temp F: 70.25
Device Address: 28FF640E6D5C1A3F of 3 sensor -> Temp C: 21.25 Temp F: 70.25
Device Address: 28FF640E6D5D66A0 of 4 sensor -> Temp C: 21.19 Temp F: 70.14
Requesting temperatures...DONE
Device Address: 28FF640E6C63D015 of 0 sensor -> Temp C: 21.19 Temp F: 70.14
Device Address: 28FF640E6C6F7A89 of 1 sensor -> Temp C: 21.37 Temp F: 70.47
Device Address: 28FF640E6D647F3E of 2 sensor -> Temp C: 21.25 Temp F: 70.25
Device Address: 28FF640E6D5C1A3F of 3 sensor -> Temp C: 21.25 Temp F: 70.25
Device Address: 28FF640E6D5D66A0 of 4 sensor -> Temp C: 21.19 Temp F: 70.14
Indicizzazione dei sensori e lettura della temperatura
Una soluzione non particolarmente utile è indicizzare i sensori e leggere la temperatura. Questa soluzione non è molto pratica perché non puoi sapere quale sensore corrisponde a un determinato indice, poiché gli indici possono cambiare ad ogni nuova ricerca.
Per semplicità, ho ridotto il numero di sensori collegati a 4.
/**
* Indexing thermometer and read the temperature
*
* by Renzo Mischianti <www.mischianti.org>
*
* https://mischianti.org
*/
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port 22
#define ONE_WIRE_BUS 22
#define TEMPERATURE_PRECISION 9
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
DeviceAddress firstThermometer, secondThermometer, thirdThermometer, fourthThermometer;
void setup(void)
{
// start serial port
Serial.begin(115200);
Serial.println("Dallas Temperature IC Control Library Demo");
// Start up the library
sensors.begin();
// locate devices on the bus
Serial.print("Locating devices...");
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode()) Serial.println("ON");
else Serial.println("OFF");
// assigns the first address found to insideThermometer
if (!oneWire.search(firstThermometer)) Serial.println("Unable to find 1 address for insideThermometer");
// assigns the second address found to insideThermometer
if (!oneWire.search(secondThermometer)) Serial.println("Unable to find 2 address for insideThermometer");
// assigns the third address found to insideThermometer
if (!oneWire.search(thirdThermometer)) Serial.println("Unable to find 3 address for insideThermometer");
// assigns the fourth address found to insideThermometer
if (!oneWire.search(fourthThermometer)) Serial.println("Unable to find 4 address for insideThermometer");
// show the addresses we found on the bus
Serial.print("Device 0 Address: ");
printAddress(firstThermometer);
Serial.println();
Serial.print("Device 1 Address: ");
printAddress(secondThermometer);
Serial.println();
Serial.print("Device 2 Address: ");
printAddress(thirdThermometer);
Serial.println();
Serial.print("Device 3 Address: ");
printAddress(fourthThermometer);
Serial.println();
// set the resolution to 9 bit per device
sensors.setResolution(firstThermometer, TEMPERATURE_PRECISION);
sensors.setResolution(secondThermometer, TEMPERATURE_PRECISION);
sensors.setResolution(thirdThermometer, TEMPERATURE_PRECISION);
sensors.setResolution(fourthThermometer, TEMPERATURE_PRECISION);
Serial.print("Device 0 Resolution: ");
Serial.print(sensors.getResolution(firstThermometer), DEC);
Serial.println();
Serial.print("Device 1 Resolution: ");
Serial.print(sensors.getResolution(secondThermometer), DEC);
Serial.println();
Serial.print("Device 2 Resolution: ");
Serial.print(sensors.getResolution(thirdThermometer), DEC);
Serial.println();
Serial.print("Device 3 Resolution: ");
Serial.print(sensors.getResolution(fourthThermometer), DEC);
Serial.println();
}
// function to print a device address
void printAddress(DeviceAddress deviceAddress)
{
for (uint8_t i = 0; i < 8; i++)
{
// zero pad the address if necessary
if (deviceAddress[i] < 16) Serial.print("0");
Serial.print(deviceAddress[i], HEX);
}
}
// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
float tempC = sensors.getTempC(deviceAddress);
if(tempC == DEVICE_DISCONNECTED_C)
{
Serial.println("Error: Could not read temperature data");
return;
}
Serial.print("Temp C: ");
Serial.print(tempC);
Serial.print(" Temp F: ");
Serial.print(DallasTemperature::toFahrenheit(tempC));
}
// function to print a device's resolution
void printResolution(DeviceAddress deviceAddress)
{
Serial.print("Resolution: ");
Serial.print(sensors.getResolution(deviceAddress));
Serial.println();
}
// main function to print information about a device
void printData(DeviceAddress deviceAddress)
{
Serial.print("Device Address: ");
printAddress(deviceAddress);
Serial.print(" ");
printTemperature(deviceAddress);
Serial.println();
}
/*
Main function, calls the temperatures in a loop.
*/
void loop(void)
{
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.print("Requesting temperatures...");
sensors.requestTemperatures();
Serial.println("DONE");
// print the device information
printData(firstThermometer);
printData(secondThermometer);
printData(thirdThermometer);
printData(fourthThermometer);
delay(2000);
}
Ogni volta che esegui una nuova ricerca, l’indicizzazione cambia, e un indice può corrispondere a un diverso sensore rispetto alla ricerca precedente.
// assigns the first address found to insideThermometer
if (!oneWire.search(firstThermometer)) Serial.println("Unable to find 1 address for insideThermometer");
// assigns the second address found to insideThermometer
if (!oneWire.search(secondThermometer)) Serial.println("Unable to find 2 address for insideThermometer");
// assigns the third address found to insideThermometer
if (!oneWire.search(thirdThermometer)) Serial.println("Unable to find 3 address for insideThermometer");
// assigns the fourth address found to insideThermometer
if (!oneWire.search(fourthThermometer)) Serial.println("Unable to find 4 address for insideThermometer");
// assigns the fifth address found to insideThermometer
if (!oneWire.search(fifthThermometer)) Serial.println("Unable to find 5 address for insideThermometer");
// assigns the sixth address found to insideThermometer
if (!oneWire.search(sixthThermometer)) Serial.println("Unable to find 6 address for insideThermometer");
In questo modo viene evidenziata la parte più recente e rilevante dell’output seriale.
Dallas Temperature IC Control Library Demo
Locating devices...Found 4 devices.
Parasite power is: OFF
Unable to find 5 address for thermometer
Device 0 Address: 28FF640E6C6F7A89
Device 1 Address: 28FF640E6D647F3E
Device 2 Address: 28FF640E6D5C1A3F
Device 3 Address: 28FF640E6D5D66A0
Device 0 Resolution: 12
Device 1 Resolution: 12
Device 2 Resolution: 12
Device 3 Resolution: 12
Requesting temperatures...DONE
Device Address: 28FF640E6C6F7A89 Temp C: 21.31 Temp F: 70.36
Device Address: 28FF640E6D647F3E Temp C: 21.19 Temp F: 70.14
Device Address: 28FF640E6D5C1A3F Temp C: 21.31 Temp F: 70.36
Device Address: 28FF640E6D5D66A0 Temp C: 21.19 Temp F: 70.14
Requesting temperatures...DONE
Device Address: 28FF640E6C6F7A89 Temp C: 21.31 Temp F: 70.36
Device Address: 28FF640E6D647F3E Temp C: 21.19 Temp F: 70.14
Device Address: 28FF640E6D5C1A3F Temp C: 21.25 Temp F: 70.25
Device Address: 28FF640E6D5D66A0 Temp C: 21.19 Temp F: 70.14
Grazie
- ESP32: piedinatura, specifiche e configurazione dell’Arduino IDE
- ESP32: fileSystem integrato SPIFFS
- ESP32: gestire più seriali e logging per il debug
- ESP32 risparmio energetico pratico
- ESP32 risparmio energetico pratico: gestire WiFi e CPU
- ESP32 risparmio energetico pratico: modem e light sleep
- ESP32 risparmio energetico pratico: deep sleep e ibernazione
- ESP32 risparmio energetico pratico: preservare dati al riavvio, sveglia a tempo e tramite tocco
- ESP32 risparmio energetico pratico: sveglia esterna e da ULP
- ESP32 risparmio energetico pratico: sveglia da UART e GPIO
- ESP32: filesystem integrato LittleFS
- ESP32: filesystem integrato FFat (Fat/exFAT)
- ESP32-wroom-32
- ESP32-CAM
- ESP32: ethernet w5500 con chiamate standard (HTTP) e SSL (HTTPS)
- ESP32: ethernet enc28j60 con chiamate standard (HTTP) e SSL (HTTPS)
- Come usare la scheda SD con l’esp32
- esp32 e esp8266: file system FAT su memoria SPI flash esterna
- Gestione aggiornamenti firmware e OTA
- Gestione del firmware
- Aggiornamento OTA con Arduino IDE
- Aggiornamento OTA con browser web
- Aggiornamenti automatici OTA da un server HTTP
- Aggiornamento del firmware non standard
- Integrare LAN8720 con ESP32 per la connettività Ethernet con plain (HTTP) e SSL (HTTPS)
- Collegare l’EByte E70 (CC1310) ai dispositivi ESP32 c3/s3 ed un semplice sketch di esempio
- ESP32-C3: piedinatura, specifiche e configurazione dell’IDE Arduino
- Integrazione del modulo W5500 su ESP32 con Core 3: supporto nativo ai protocolli Ethernet con SSL e altre funzionalità
- Integrazione del modulo LAN8720 su ESP32 con Core 3: supporto nativo del protocollo Ethernet con SSL e altre funzionalità.
- Dallas DS18B20
- Dallas DS18B20 con ESP32 ed ESP8266: introduzione e modalità parasita
- Dallas DS18B20 con ESP32 ed ESP8266: gate P-MOSFET pull-up e allarmi
- Dallas DS18B20 con ESP32 ed ESP8266: tutte le topologie OneWire, lunghe derivazioni e più dispositivi