Ho raggruppato nella seguente tabella i due sensori con le principali caratteristiche, si noti che l’involucro plastico bianco o blu rendono molto facile la differenziazione fra i due.
Una cosa a cui prestare estrema attenzione è, come spesso accade in molti sensori, la differenza con cui devono essere connessi visto che i pin non si trovano sempre nella stessa sequenza. Per questo motivo dovete sempre fare riferimento alla documentazione del modello in vostro possesso e, se possibile, verificare anche se la serigrafia stampata sul modulo corrisponde alla documentazione. Diciamo subito che questi moduli utilizzano tre pin, uno per l’alimentazione, una massa ed un pin per il transito dei dati. Se ci sono 4 pin, uno risulterà non collegato. Una volta identificati i 3 pin il cablaggio rasenta la banalità, il 5V andrà collegato all’alimentazione, GND a massa e il pin rimanente ad uno dei pin digitali di Arduino. Viene consigliato l’utilizzo di un resistore da 5K fra il pin dei dati ed i 5V come resistore di pull-up. Questo diventa particolarmente utile con l’incremento della lunghezza del cavo che collega Arduino al sensore stesso, nel caso di cablaggi che vanno oltre i 20 metri potrà essere necessario ridurre il valore di resistenza. Per cablaggi molto corti potete anche omettere il resistore, io ad esempio non l’ho usato e non ho avuto nessun problema. Come per tutti gli integrati, viene consigliato l’uso di un condensatore da 100nF fra 5V e GND per smussare le variazioni di tensione durante il funzionamento del sensore.
Questi sensori comunicano in maniera seriale attraverso il pin dati, con metodologie simili ma non identiche e quindi non compatibili con l’1-wire che abbiamo ampiamente trattato in questo blog. Per una volta mi limiterò ad usare una libreria già pronta senza andare a sviscerare il protocollo di comunicazione; ho seguito il playground ufficiale e sono approdato qui perciò vi consiglio di scaricare la libreria da quel link. Partendo da uno dei semplici esempi ci vuole davvero poco a creare uno sketch in grado di leggere temperatura ed umidità. Lo sketch di base legge i sensori DHT11, ma se seguite le modifiche poste nei commenti in linea potete leggere i sensori DHT22 con la modifica di una sola riga di codice. Nell’esempio ho lasciato il pin numero 5 per la ricezione dei dati dal sensore.
#include <dht.h> dht DHT; #define DHT_PIN 5 void setup() { Serial.begin(9600); Serial.println("DHT TEST PROGRAM "); Serial.print("LIBRARY VERSION: "); Serial.println(DHT_LIB_VERSION); Serial.println(); Serial.println("Type,\tstatus,\tHumidity (%),\tTemperature (C)"); } void loop() { // READ DATA Serial.print("dhtXX, \t"); int chk = DHT.read11(DHT_PIN); // chk = DHT.read22(DHT_PIN); cambia questa riga se vuoi usare i DHT22 switch (chk) { case DHTLIB_OK: Serial.print("OK,\t"); break; case DHTLIB_ERROR_CHECKSUM: Serial.print("Checksum error,\t"); break; case DHTLIB_ERROR_TIMEOUT: Serial.print("Time out error,\t"); break; case DHTLIB_ERROR_CONNECT: Serial.print("Connect error,\t"); break; case DHTLIB_ERROR_ACK_L: Serial.print("Ack Low error,\t"); break; case DHTLIB_ERROR_ACK_H: Serial.print("Ack High error,\t"); break; default: Serial.print("Unknown error,\t"); break; } // DISPLAY DATA Serial.print(DHT.humidity, 1); Serial.print(",\t"); Serial.println(DHT.temperature, 1); delay(2000); }
Con questo sketch siete già operativi e potete vedere su seriale sia le letture di temperatura ed umidità che eventuali messaggi di errore.
Invio remoto tramite nrf24
Arduino Board | MOSI | MISO | SCK | SS (slave) | SS (master) |
Uno / Duemilanove / Pro / Nano / Fio | 11 or ICSP-4 | 12 or ICSP-1 | 13 or ICSP-3 | 10 | – |
Mega1280 or Mega2560 | 51 or ICSP-4 | 50 or ICSP-1 | 52 or ICSP-3 | 53 | – |
Leonardo / Micro / YUN | ICSP-4 | ICSP-1 | ICSP-3 | – | – |
Due | ICSP-4 | ICSP-1 | ICSP-3 | – | 4, 10, 52 |
Mini | 11 | 12 | 13 | – | – |
E’ prevista una sezione del codice che riceve messaggi dalla controparte remota, nell’esempio sotto riceve ogni 30 secondi il valore di millis() della scheda remota. Questo dato non viene usato in nessun modo nell’esempio ma permette di avere un pezzo di codice già pronto per la gestione degli eventi remoti.
Vediamo il codice da installare sulla scheda con i sensori:
// facciamo le necessarie inclusioni #include <dht.h> #include <SPI.h> #include <Mirf.h> #include <MirfHardwareSpiDriver.h> #include <Time.h> dht DHT; #define DHT_PIN 5 unsigned long tempo; // usata per contare il tempo trascorso.... // struct ed union usate per lo scambio di dati su nrf24 union DataMix { char datachar[4]; int dataint[2]; float datafloat; unsigned long datalong; } ; struct McMajanData { char Command; union DataMix Data; } ; union dataRF24 { char databuffer[5]; struct McMajanData IO; }; dataRF24 IORF24; void setup(void) { Serial.begin(9600);// inizializza la porta seriale a 9600 Mirf.cePin = 9; //SS Mirf.csnPin = 10; // CSN Mirf.spi = &MirfHardwareSpi; Mirf.init(); Mirf.setRADDR((byte *)"c0001"); //nome del client Mirf.payload = 5; // usiamo comandi composti da 5 bytes Mirf.channel =90; // canale numero 90 Mirf.config(); Mirf.configRegister(RF_SETUP,0x26); //250k //Mirf.configRegister(RF_SETUP,0x00); //1mb //Mirf.configRegister(RF_SETUP,0x0E); //2mb tempo=0; } void loop(void) { char * data; // riceve comunicazioni via nrf24 if(!Mirf.isSending() && Mirf.dataReady()) { // queste righe servono ad espandere il software per leggere messaggi di ritorno dall'altra scheda Serial.println("Ricezione dati...."); Mirf.getData((uint8_t *)IORF24.databuffer); if(IORF24.IO.Command=='X') // ho ricevuto comando T (che su Arduino remoto è la ricezione termica { Serial.println("Ricevuto ping remoto "); float temporemoto=(float)(IORF24.IO.Data.datafloat); // ... elaborazione dati a proprio piacimento } } if(tempo+30000<millis()) // ripete il ciclo ogni 30 secondi { tempo=millis(); int chk = DHT.read11(DHT_PIN); // oppure int chk = DHT.read22(DHT_PIN); if (chk==DHTLIB_OK) // lettura avvenuta correttamente { // invio temperatura IORF24.IO.Data.datalong=DHT.temperature; IORF24.IO.Command='T'; Mirf.setTADDR((byte *)"s0001"); Mirf.send((byte *)IORF24.databuffer); while(Mirf.isSending()){} // .. e umidità IORF24.IO.Data.datalong=DHT.humidity; IORF24.IO.Command='H'; Mirf.setTADDR((byte *)"s0001"); Mirf.send((byte *)IORF24.databuffer); while(Mirf.isSending()){} delay(100); } } // millis }
Ed ora vediamo la controparte remota che riceve i dati di temperatura ed umidità:
// facciamo le necessarie inclusioni #include <dht.h> #include <SPI.h> #include <Mirf.h> #include <MirfHardwareSpiDriver.h> #include <Time.h> dht DHT; #define DHT_PIN 5 unsigned long tempo; // usata per contare il tempo trascorso.... // struct ed union usate per lo scambio di dati su nrf24 union DataMix { char datachar[4]; int dataint[2]; float datafloat; unsigned long datalong; } ; struct McMajanData { char Command; union DataMix Data; } ; union dataRF24 { char databuffer[5]; struct McMajanData IO; }; dataRF24 IORF24; void setup(void) { Serial.begin(9600);// inizializza la porta seriale a 9600 Mirf.cePin = 9; //SS Mirf.csnPin = 10; // CSN Mirf.spi = &MirfHardwareSpi; Mirf.init(); Mirf.setRADDR((byte *)"s0001"); //nome del client Mirf.payload = 5; // usiamo comandi composti da 5 bytes Mirf.channel =90; // canale numero 90 Mirf.config(); Mirf.configRegister(RF_SETUP,0x26); //250k //Mirf.configRegister(RF_SETUP,0x00); //1mb //Mirf.configRegister(RF_SETUP,0x0E); //2mb tempo=0; } void loop(void) { char * data; // riceve comunicazioni via nrf24 if(!Mirf.isSending() && Mirf.dataReady()) { Serial.println("Ricezione dati...."); Mirf.getData((uint8_t *)IORF24.databuffer); if(IORF24.IO.Command=='T') // ho ricevuto comando T (che su Arduino remoto è la ricezione termica { Serial.print("Ricevuta temperatura remota: "); float temperatura=(float)(IORF24.IO.Data.datafloat); // ricavo temperatura Serial.println(temperatura, 1); } if(IORF24.IO.Command=='H') // ho ricevuto comando T (che su Arduino remoto è la ricezione termica { Serial.print("Ricevuta temperatura remota: "); float humidity=(float)(IORF24.IO.Data.datafloat); // ricavo umidità Serial.println(humidity, 1); } } if(tempo+30000<millis()) // ripete il ciclo ogni 30 secondi { tempo=millis(); IORF24.IO.Data.datalong=tempo; // invio i millis() IORF24.IO.Command='X'; Mirf.setTADDR((byte *)"c0001"); Mirf.send((byte *)IORF24.databuffer); while(Mirf.isSending()){} delay(100); } // millis }
Ad essere onesto non ho un modulo nrf24 libero per fare i test per cui ho scritto il codice senza testarlo, ma non dovrebbero esserci problemi visto che è lo stesso degli scorsi articoli, adattato per l’occasione. Ho verificato che la compilazione avvenga correttamente e, caso più unico che raro, non ho riscontrato nemmeno un piccolo errore di digitazione. Detto ciò nell’articolo di oggi abbiamo visto come sia abbastanza semplice modificare il software visto in precedenza ed adattarlo a nuove situazioni. Questo era l’intento dell’articolo originale e devo ammettere che passare dall’uso dei ds18b20 ai DHT è stato molto facile. Anche se abbiamo usato temperature ed umidità potete tranquillamente, con poche modifiche, trasmettere qualunque grandezza fisica, che sia essa una velocità, pressione, accelerazione, profondità, distanza, frequenza, etc, etc, etc….
Ciao Stefano lo sketch ricevente puo’ funzionare sul raspberry?
Hai un email?
Se con ricevente intendi la scheda che riceve dati attraverso il modulino nrf allora non ho delle certezze. Per prima cosa dovresti installare Wiring sul RB, ma poi non ho idea di come si comporterebbe la mia libreria, non ho mai provato a compilarla sul RB e dubito che funzionerebbe al primo colpo senza modifiche. Se invece intendevi la parte che “riceve” i dati via web, allora si, basta che sia installato il web server con relativo php e dovrebbe funzionare tutto senza alcuna modifica. Ho da poco cominciato a scrivere un software web decisamente molto complesso che permette la gestione multiutente / multiboaard per raccogliere / gestire dati remoti e che funzionerà anche su RB….ma ci vorrà un bel po’ di tempo prima che possa iniziare ad usarlo, sono ancora allo “scheletro”, per ora è pronta tutta la parte che gestisce utenti / permessi / registrazioni, etc e stò creando il “motore” che genera le pagine web dinamicamente…..ma la strada è lunga e piena di insidie….la mia mail smania2000@gmail.com, è attiva anche info@mcmajan.com ma la leggo solo saltuariamente…. per ora….