Dallas ds18b20 con Raspberry Pi Pico (rp2040): introduzione e modalità parassita
Il DS18B20 è un sensore di temperatura digitale che può essere facilmente integrato con un microcontrollore Raspberry Pi Pico (rp2040). In questa risposta, fornirò un’introduzione al sensore DS18B20 e spiegherò come utilizzarlo in modalità parassita con un Raspberry Pi Pico.
Ho già mostrato alcuni sensori di temperatura e umidità in questa serie di articoli: “Sensori di temperatura e umidità: come fare e confronto“, ma ora vorrei spiegare meglio il Dallas ds28b20. Questo sensore di temperatura a un filo può essere gestito in serie senza grandi limiti.
In particolare, ha una buona precisione (±0,5°) e un notevole intervallo di temperatura (-55°C a +125°C o -67°F a +257°F), ma puoi aggiungere in un singolo filo molti dispositivi, supporta anche una modalità di alimentazione parassita che permette di utilizzare solo due fili per la connessione.
Ma ora aggiungerò la spiegazione dal datasheet per una migliore comprensione.
Il termometro digitale DS18B20 fornisce misurazioni della temperatura in gradi Celsius da 9 a 12 bit e ha una funzione di allarme con punti di attivazione superiore e inferiore programmabili dall’utente non volatili. Il DS18B20 comunica attraverso un bus a 1 filo che richiede solo una linea dati (e massa) per la comunicazione con un microprocessore centrale. Inoltre, il DS18B20 può derivare l’alimentazione direttamente dalla linea dati (“parasite power”), eliminando la necessità di un’alimentazione esterna.
Datasheet
Ogni DS18B20 ha un codice seriale unico a 64 bit, che permette a più DS18B20 di funzionare sullo stesso bus a 1 filo. Così, l’uso di un microprocessore per controllare molti DS18B20 distribuiti su un’ampia area è semplice. Le applicazioni che possono beneficiare di questa caratteristica includono controlli ambientali HVAC, sistemi di monitoraggio della temperatura all’interno di edifici, attrezzature o macchinari, e sistemi di monitoraggio e controllo dei processi.
Caratteristiche
- Interfaccia 1-Wire® unica richiede solo un pin di porta per la comunicazione
- Riduci il numero di componenti con sensore di temperatura e EEPROM integrati
- 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 a 12 bit
- Nessun componente esterno richiesto
- La modalità di alimentazione parassita richiede solo 2 pin per il funzionamento (DQ e GND)
- Semplifica le applicazioni di rilevamento della temperatura distribuite con capacità multidrop
- Ogni dispositivo ha un codice seriale unico a 64 bit memorizzato nella ROM interna
- Impostazioni di allarme non volatili (NV) definibili dall’utente flessibili con comando di ricerca di allarme identifica i dispositivi con temperature al di fuori dei limiti programmati
- Disponibile nei pacchetti SO a 8 pin (150 mils), µSOP a 8 pin e TO-92 a 3 pin
Datasheet
Schema dei pin
Il sensore ha più varianti, ma il cablaggio rimane lo stesso.
GND: collega a GND.
DATA: Bus dati One-Wire.
VCC: alimentazione (3,3 – 5 V), ma in modalità parassita, puoi collegare a GND.
Ecco il sensore AliExpress
Cablaggio
La libreria One-Wire è uno standard per tutti i microcontrollori, quindi il dispositivo può essere utilizzato con molti microcontrollori.
Raspberry Pi Pico
Ecco lo schema dei pin delle schede prototipo Raspberry Pi Pico.
O la variante WeAct:
Ecco alcune schede prototipo rp2040 Official Pi Pico - Official Pi Pico W - Waveshare rp2040-zero - WeAct Studio rp2040
Modalità normale
In modalità normale, useremo una linea di alimentazione a 3,3v, quindi la connessione diventa così.
La connessione è molto semplice.
esp32 | ds18b20 |
---|---|
GND | GND |
3.3v | VCC |
D22 pulled-up | DATA |
Schema
Ecco lo schema semplice.
Modalità parassita
Nella modalità parassita, collegherai anche la linea VCC del sensore a GND, e il sensore riceve alimentazione dalla linea dati.
esp32 | ds18b20 |
---|---|
GND | GND |
GND | VCC |
D22 pulled-up | DATA |
In seguito analizzeremo in dettaglio questa modalità, ma per ora non hai bisogno di altre informazioni.
Schema
Ecco lo schema.
Libreria
Ora, mentre scrivo questo articolo, c’è un bug nella libreria più famosa OneWire, quindi inserisco il link a questa libreria, quindi non usarla.
Usa OneWireNg e non la libreria OneWire standard
Non usarla fino a quando il bug non sarà corretto.
Prima di tutto, devi ricordare che questo sensore utilizza il protocollo One-Wire, quindi devi aggiungere la libreria OneWire.
Usa questa per ora
Dopo, devi installare una libreria che implementa il protocollo e le funzioni del sensore.
Ho scelto la più utilizzata, la DallasTemperature (in passato Dallas, ora Maxim).
Dispositivi supportati
Come descritto nel repository, questa libreria supporta i seguenti dispositivi:
- DS18B20
- DS18S20 (alcuni problemi su questo dispositivo)
- DS1822
- DS1820
- MAX31820
- MAX31850
Averai bisogno di una resistenza di pull-up di circa 4.7KOhm tra la linea dati 1-Wire e il tuo VCC. Se utilizzi il DS18B20, puoi usare la modalità parassita e puoi collegare a GND il VCC come descritto.
Risoluzione dei problemi
In caso di problemi di conversione della temperatura (il risultato è -85), potrebbe essere necessaria un’impostazione di 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/parassita)
Il DS18B20 può essere alimentato da una fonte esterna sul pin VDD, o può operare in modalità “parasite power”, che permette al DS18B20 di funzionare senza una alimentazione esterna locale (colleghi il VDD a GND). Il DS18B20 “ruba” energia dal bus 1-Wire tramite il pin DQ quando il bus è alto. L’energia rubata alimenta il DS18B20 mentre il bus è alto, e parte dell’energia viene immagazzinata nel condensatore di alimentazione parassita (CPP) per fornire energia quando il bus è basso.
Ma quando il DS18B20 esegue conversioni della temperatura o copia dati dalla memoria scratchpad all’EEPROM, la corrente operativa può essere alta fino a 1,5mA. Questa corrente può causare una caduta di tensione inaccettabile attraverso la resistenza di pull-up 1-Wire debole ed è più corrente di quanto CPP possa fornire.
Pull-up forte per la modalità parassita
Per garantire che il DS18B20 disponga di una sufficiente alimentazione, è necessario fornire un pull-up forte sul bus 1-Wire ogni volta che si verificano conversioni della temperatura o si copiano dati dalla scratchpad all’EEPROM.
Questo può essere realizzato utilizzando un MOSFET per tirare il bus direttamente al rail.
Il bus 1-Wire deve essere commutato al pull-up forte entro 10µs (max) dopo le conversioni della temperatura, e il bus deve essere mantenuto alto dal pull-up per la durata della conversione o del trasferimento dei dati. Nessun’altra attività può avere luogo sul bus 1-Wire mentre il pull-up è abilitato.
Un esempio di m
Il DS18B20 può anche essere alimentato con il metodo convenzionale collegando una fonte di alimentazione esterna al pin VDD, come mostrato. Il vantaggio di questo metodo è che il pull-up MOSFET non è richiesto e il bus 1-Wire è libero di trasportare altro traffico durante il tempo di conversione della temperatura.
L’uso dell’alimentazione parassita non è raccomandato per temperature superiori a +100°C poiché il DS18B20 potrebbe non essere in grado di mantenere le comunicazioni a causa delle maggiori correnti di dispersione che possono esistere a queste temperature.
Riduci le dimensioni della libreria
Abbiamo incluso una definizione REQUIRESNEW
e REQUIRESALARMS
. Se vuoi ridurre il codice, sentiti libero di usare uno di questi includendo
#define REQUIRESNEW
o
#define REQUIRESALARMS
all’inizio di DallasTemperature.h
Codice
E ora, possiamo iniziare con alcuni esempi.
Recupero temperatura
Prima di tutto, il modo più rapido per mettere in funzione il sensore.
// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port D22
#define ONE_WIRE_BUS D22
// 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 setup function. We only start the sensors here
*/
void setup(void)
{
// start serial port
Serial.begin(115200);
while (!Serial) { delay(100); }
Serial.println("Dallas Temperature IC Control Library Demo");
// Start up the library
sensors.begin();
}
/*
* Main function, get and show the temperature
*/
void loop(void)
{
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.print("Requesting temperatures...");
sensors.requestTemperatures(); // Send the command to get temperatures
Serial.println("DONE");
// After we got the temperatures, we can print them here.
// We use the function ByIndex, and as an example get the temperature from the first sensor only.
float tempC = sensors.getTempCByIndex(0);
// Check if reading was successful
if(tempC != DEVICE_DISCONNECTED_C)
{
Serial.print("Temperature for the device 1 (index 0) is: ");
Serial.println(tempC);
}
else
{
Serial.println("Error: Could not read temperature data");
}
delay(2000);
}
L’output seriale è molto semplice.
Dallas Temperature IC Control Library Demo
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.50
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.50
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.50
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.50
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.44
Requesting temperatures...DONE
Temperature for the device 1 (index 0) is: 20.44
Recupera informazioni sensore e temperatura (tramite indice)
Prima di tutto, andremo a recuperare l’indirizzo, le informazioni sulla connessione (parassita o meno) e la temperatura.
/**
* Retrieve information about a single sensor
* minor change by Renzo Mischianti <www.mischianti.org>
*
* www.mischianti.org
*/
// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into port D22
#define ONE_WIRE_BUS D22
// 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);
// arrays to hold device address
DeviceAddress insideThermometer;
/*
* Setup function. Here we do the basics
*/
void setup(void)
{
// start serial port
Serial.begin(112500);
Serial.println("Dallas Temperature IC Control Library Demo");
// locate devices on the bus
Serial.print("Locating devices...");
sensors.begin();
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");
// Assign address manually. The addresses below will beed to be changed
// to valid device addresses on your bus. Device address can be retrieved
// by using either oneWire.search(deviceAddress) or individually via
// sensors.getAddress(deviceAddress, index)
// Note that you will need to use your specific address here
// insideThermometer = { 0x28, 0xFF, 0x64, 0x0E, 0x79, 0x69, 0x3A, 0x1A };
// we can check if the address is correct and if It's all ok
// if (!oneWire.search(insideThermometer)) Serial.println("Unable to find address for insideThermometer");
// Search for devices on the bus and assign based on an index. Ideally,
// you would do this to initially discover addresses on the bus and then
// use those addresses and manually assign them (see above) once you know
// the devices on your bus (and assuming they don't change).
if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");
// show the addresses we found on the bus
Serial.print("Device 0 Address: ");
printAddress(insideThermometer);
Serial.println();
Serial.print("Device 0 HEX Address: ");
printHEXAddress(insideThermometer);
Serial.println();
// set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
sensors.setResolution(insideThermometer, 9);
Serial.print("Device 0 Resolution: ");
Serial.print(sensors.getResolution(insideThermometer), DEC);
Serial.println();
}
/*
* Main function. It will request the tempC from the sensors and display on Serial.
*/
void loop(void)
{
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.print("Requesting temperatures...");
sensors.requestTemperatures(); // Send the command to get temperatures
Serial.println("DONE");
// It responds almost immediately. Let's print out the data
printTemperature(insideThermometer); // Use a simple function to print out the data
delay(4000);
}
// 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);
}
}
void printHEXAddress(DeviceAddress deviceAddress)
{
Serial.print(" { ");
for (uint8_t 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(" }");
}
// function to print the temperature for a device
void printTemperature(DeviceAddress deviceAddress)
{
// method 1 - slower
//Serial.print("Temp C: ");
//Serial.print(sensors.getTempC(deviceAddress));
//Serial.print(" Temp F: ");
//Serial.print(sensors.getTempF(deviceAddress)); // Makes a second call to getTempC and then converts to Fahrenheit
// method 2 - faster
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.println(DallasTemperature::toFahrenheit(tempC)); // Converts tempC to Fahrenheit
}
Riceviamo questo quando gli output seriali.
Dallas Temperature IC Control Library Demo
Locating devices...Found 1 devices.
Parasite power is: OFF
Device 0 Address: 28FF640E79693A1A
Device 0 HEX Address: { 0x28, 0xFF, 0x64, 0x0E, 0x79, 0x69, 0x3A, 0x1A }
Device 0 Resolution: 9
Requesting temperatures...DONE
Temp C: 22.50 Temp F: 72.50
Requesting temperatures...DONE
Temp C: 22.50 Temp F: 72.50
Come puoi vedere, ho impostato il pin OneWire su 22:
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 22
// 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);
Controlla quanti sensori recuperiamo nella linea:
// locate devices on the bus
Serial.print("Locating devices...");
sensors.begin();
Serial.print("Found ");
Serial.print(sensors.getDeviceCount(), DEC);
Serial.println(" devices.");
Controlla se facciamo una connessione parassita:
// report parasite power requirements
Serial.print("Parasite power is: ");
if (sensors.isParasitePowerMode()) Serial.println("ON");
else Serial.println("OFF");
Metti in insideThermometer
l’indirizzo del sensore 0:
// Search for devices on the bus and assign based on an index. Ideally,
// you would do this to initially discover addresses on the bus and then
// use those addresses and manually assign them (see above) once you know
// the devices on your bus (and assuming they don't change).
if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");
Ora possiamo leggere la temperatura (in Celsius):
float tempC = sensors.getTempC(deviceAddress);
Poi convertire in Fahrenheit:
Serial.println(DallasTemperature::toFahrenheit(tempC)); // Converte tempC in Fahrenheit
Puoi fare una lettura diretta in Fahrenheit, ma all’interno, fai le stesse operazioni:
Serial.print(sensors.getTempF(deviceAddress)); // Makes a second call to getTempC and then converts to Fahrenheit
Grazie
- Schede Raspberry Pi Pico e rp2040: pinout, specifiche e configurazione IDE Arduino
- Schede Raspberry Pi Pico e rp2040: filesystem LittleFS integrato
- Scheda Raspberry Pi Pico e rp2040: ethernet w5500 e requests HTTP e HTTPS (SSL)
- Schede Raspberry Pi Pico e rp2040: WiFiNINA con coprocessore WiFi ESP32
- Schede Raspberry Pi Pico e rp2040: come utilizzare una scheda SD
- Dallas ds18b20
- Collegamento dell’EByte E70 ai dispositivi Raspberry Pi Pico (rp2040) ed un semplice sketch di esempio