Lettura sensore

Ciao a tutti
Il progetto che vi sottopongo consiste di leggere la temperatura del DHT22 su un display a 4 elementi. leggo nel modo corretto il valore della temperatura ma dopo 2 secondi (il tempo di default del sensore) il display si spegne per circa 500 ms tranne l’ultimo elemento (unità) visualizzando uno zero, poi per altri 2 secondi leggo il valore della temperatura e così via. Forse non è il modo giusto per leggere il valore del sensore con questo display?
Grazie a tutti in anticipo
Guido

// Display a 4 elementi a anodo comune

//--------------------------------------------------------------------------------------------------------
//segmenti  A  B  C  D  E  F  G  dp   tabella1  per migliaia + decine + unità
//--------------------------------------------------------------------------------------------------------
// N°0      0  0  0  0  0  0  1  1    0x03
// N°1      1  0  0  1  1  1  1  1    0x9F
// N°2      0  0  1  0  0  1  0  1    0x25
// N°3      0  0  0  0  1  1  0  1    0x0D
// N°4      1  0  0  1  1  0  0  1    0x99
// N°5      0  1  0  0  1  0  0  1    0x49
// N°6      0  1  0  0  0  0  0  1    0x41
// N°7      0  0  0  1  1  1  1  1    0x1F
// N°8      0  0  0  0  0  0  0  1    0x01
// N°9      0  0  0  0  1  0  0  1    0x09
//-------------------------------------------------------------------------------------------------------
//segmenti  A  B  C  D  E  F  G  dp    tabella2  per centinaia + punto
//-------------------------------------------------------------------------------------------------------
// N°0      0  0  0  0  0  0  1  0    0x02
// N°1      1  0  0  1  1  1  1  0    0x9E
// N°2      0  0  1  0  0  1  0  0    0x24
// N°3      0  0  0  0  1  1  0  0    0x0C
// N°4      1  0  0  1  1  0  0  0    0x98
// N°5      0  1  0  0  1  0  0  0    0x48
// N°6      0  1  0  0  0  0  0  0    0x40
// N°7      0  0  0  1  1  1  1  0    0x1E
// N°8      0  0  0  0  0  0  0  0    0x00
// N°9      0  0  0  0  1  0  0  0    0x08
//--------------------------------------------------------------------------------------------------------
#define CLOCK_PIN 2         // pin 11  shift-register 74HC595
#define LATCH_PIN 3         // pin 12  shift-register 74HC595
#define DATA_PIN  4         // pin 14  shift-register 74HC595 
#define digit1    5         // alimento tramite transistor PNP BC327 digit 1 migliaia
#define digit2    6         // alimento tramite transistor PNP BC327 digit 2 centinaia
#define digit3    7         // alimento tramite transistor PNP BC327 digit 3 decine
#define digit4    8         // alimento tramite transistor PNP BC327 digit 4 unita
#include <DHT.h>
DHT dht(9, DHT22);          // Definisco il pin al quale è collegato il sensore pin 9 arduino
//**************************************************************************************************
int intero      ;
byte  migliaia  ;
byte centinaia  ;
int totale_cent ;
byte decine     ;
byte totale_dec ;
byte unita      ;
byte tabella1[10] = {0x03, 0x9F, 0x25, 0x0D, 0x99, 0x49, 0x41, 0x1F, 0x01, 0x09};
byte tabella2[10] = {0x02, 0x9E, 0x24, 0x0C, 0x98, 0x48, 0x40, 0x1E, 0x00, 0x08};

//****************************************************************************************************
void setup() {
  pinMode (digit1, OUTPUT);
  pinMode (digit2, OUTPUT);
  pinMode (digit3, OUTPUT);
  pinMode (digit4, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);
  digitalWrite(CLOCK_PIN, LOW);
  digitalWrite (digit1, HIGH);
  digitalWrite (digit2, HIGH);
  digitalWrite (digit3, HIGH);
  digitalWrite (digit4, HIGH);
}
//***************************************************************************************************
void loop() {

  float t = dht.readTemperature();
  intero       = t * 100 ;                // Trovo l'intero del valore umidità
  migliaia     = intero / 1000 ;          // Trovo il valore delle migliaia
  totale_cent  = intero % 1000 ;          // Trovo totale delle centinaia
  centinaia    = totale_cent / 100 ;      // Trovo il valore delle centinaia
  totale_dec   = totale_cent % 100 ;      // Trovo totale delle decine
  decine       = totale_dec / 10 ;        // Trovo il valore delle decine
  unita        = totale_dec % 10 ;        // Trovo il valore delle unità
  //***************************************************************************************************
  for (int i = 0; i < 4; i++) {
    switch (i) {
      case 0 :
        digitalWrite (digit4, HIGH);
        digitalWrite (digit3, HIGH);
        digitalWrite (digit2, HIGH);
        digitalWrite(LATCH_PIN, LOW);
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, tabella1[migliaia]);
        digitalWrite(LATCH_PIN, HIGH);
        digitalWrite (digit1, LOW);
        break;
      case 1 :
        digitalWrite (digit4, HIGH);
        digitalWrite (digit3, HIGH);
        digitalWrite (digit1, HIGH);
        digitalWrite(LATCH_PIN, LOW);
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, tabella2[centinaia]);
        digitalWrite(LATCH_PIN, HIGH);
        digitalWrite (digit2, LOW);
        break;
      case 2 :
        digitalWrite (digit4, HIGH);
        digitalWrite (digit2, HIGH);
        digitalWrite (digit1, HIGH);
        digitalWrite(LATCH_PIN, LOW);
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, tabella1[decine]);
        digitalWrite(LATCH_PIN, HIGH);
        digitalWrite (digit3, LOW);
        break;
      case 3 :
        digitalWrite (digit3, HIGH);
        digitalWrite (digit2, HIGH);
        digitalWrite (digit1, HIGH);
        digitalWrite(LATCH_PIN, LOW);
        shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, tabella1[unita]);
        digitalWrite(LATCH_PIN, HIGH);
        digitalWrite (digit4, LOW);
        break;

    }
    delay (4);
  }
}

Mi sono dimenticato lo schema
Guido

Purtroppo la lettura del DHT è un'operazione bloccante, per mezzo secondo Arduino non può fare altro, e quindi neppure procedere con la scansione del display.

in effetti mezzo secondo è già molto (poco),
il datascheet riporta:

Sensing period Average: 2s

Patrick_M:
in effetti mezzo secondo è già molto (poco),
il datascheet riporta: Sensing period Average: 2s

Attento, lui NON parla dell'intervallo tra due letture, ma del tempo occorrente per fare una lettura !

>Claudio_FF: Come hai calcolato il tempo di lettura in 500 msec? A me viene al massimo qualche decina di msec ... ::slight_smile:

Guglielmo

si Guglielmo ma a parte il tempo per i calcoli in fondo c'è un delay(4) (da moltiplicare x4 :slight_smile: ) nel loop principale

Ammetto che mi sono perso nella lettura dello scatch. Ti chiederei di togliere qualche valangata di righe di commento hardware e di usare un minimo di array, che se non altro rendono più corto e chiaro (credo) il programma.
Quanto al delay 4 credo sia necessario per far leggere le scritte.
Non so quale possa essere il problema, ma concordo che potrebbe essere del datasheet/libreria lettura sensore

Prova, ad esempio, questo, che ho riscritto semplificandolo un poco. Non ho cambiato molto (spero), almeno di concettuale. L’errore dovrebbe ripresentarsi, ma almeno ora è chiaro dove si trova. Io non ho le conoscenze per leggere librerie e modificarle, mi spiace. Posso arrivare fino a qui.
Seguirò comunque con molto interesse.

#define CLOCK_PIN 2         // pin 11  shift-register 74HC595
#define LATCH_PIN 3         // pin 12  shift-register 74HC595
#define DATA_PIN  4         // pin 14  shift-register 74HC595 
#define NUMCIFRE 4
const byte pincifre [NUMCIFRE] = {5, 6, 7, 8}; //Pin display 7s in ordine di cifra (migliaia per prime)
#include <DHT.h>
#define PINSENSORE 9
DHT dht(PINSENSORE, DHT22);
int intero      ;
byte cifracifra [NUMCIFRE];
byte tabella1[10] = {0x03, 0x9F, 0x25, 0x0D, 0x99, 0x49, 0x41, 0x1F, 0x01, 0x09};
byte tabella2[10] = {0x02, 0x9E, 0x24, 0x0C, 0x98, 0x48, 0x40, 0x1E, 0x00, 0x08};

void Scomponi (int numero, byte cifracifra, byte lunghezza)
{
  for (char i = lunghezza, i > -1; i--)
  {
    cifracifra [i] = numero % 10;
    numero = numero / 10;
  }
}
void setup()
{
  for (byte i = 0; i < NUMCIFRE; i++)

  {
    pinMode (pincifre[i], OUTPUT);
    digitaWrite (pincifre[i], HIGH);
  }
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);
  digitalWrite(CLOCK_PIN, LOW);
}

void loop() {

  float t = dht.readTemperature();
  intero       = t * 100 ;                // Trovo l'intero del valore umidità
  Scomponi (intero, cifracifra, NUMCIFRE);
  for (int i = 0; i < NUMCIFRE; i++)
  {

    for (byte j = 0; j < NUMCIFRE; j++)
    {
      digitalWrite (pincifre[j], (j != i));
    }
    digitalWrite(LATCH_PIN, LOW);
    if (i != 1)
    {
      shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, tabella1[cifracifra[i]]);
    }
    else
    {
      shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, tabella2[cifracifra[i]]);
    }
    digitalWrite(LATCH_PIN, HIGH);
    delay (4);
  }
}

ok Silente tutto bene ma devono passare 2 secondi tra una lettura e l’altra del DHT22 :smiley: 4 millisecondi non bastano…

Ma d'altro canto non possiamo neanche usare un delay 500 (1/4 di due secondi), perchè si vedrebbe, di conseguenza dobbiamo pensare ad un timer millis (), sempre che serva, perchè se ho capito bene il problema si ha mezzo secondo una volta OGNI due secondi, quindi in qualche modo i due secondi necessari tra letture passando senza difficoltà. Di conseguenza va studiato qualcosa da far fare in quel mezzo secondo, o come ridurlo

Silente, t'ho detto e ripetuto mille volte ... cortesemente, intervieni solo quando SAI esattamente di cosa parli, altrimenti confondi solo le idee a chi pone le domande! :confused:

Se un sensore impiega X tempo ad inviarti lo streaming di bits, c'hai poco da inventarti; la libreria è li che sta in attesa dello streaming e non ti ritorna il controllo sino a quando non ha completato la lettura. NON c'è millis() che tenga, il tuo codice è bloccato su una funzione di libreria che è impegnata a riceve dati.

Soluzione? ... probabilmente riscrivere ex-novo la libreria ... ti ci metti tu a farlo ?

Guglielmo

gpb01:
Come hai calcolato il tempo di lettura in 500 msec? A me viene al massimo qualche decina di msec

Non l'ho calcolato, è quanto vedo in pratica perché anche a me si blocca quel mezzo secondo (in realtà 250ms per la temperatura e altri 250 per l'umidità), stasera però provo a fare una misura precisa così vediamo se si blocca anche millis ecc.

Claudio_FF:
… stasera però provo a fare una misura precisa così vediamo se si blocca anche millis ecc.

No, l’interrupt di timer0 non dovrebbe venir disabilitato …
… quello che mi meraviglia è che la funzione impieghi tanto tempo a ritornarti i valori, perchè, leggendo il datasheet (allegato), anche sommando i casi peggiori dei tempi riportati nella tabella 6, per la trasmissione di tutti e 40 i bits necessari, non vengono più di qualche decina di msec … ::slight_smile:

Guglielmo

DHT22 (Humid + Temp).pdf (596 KB)

nella dht di adafruit vengono disabilitati gli interrupt e all'inizio c'è un delay di 250 ms ...

 // Go into high impedence state to let pull-up raise data line level and
  // start the reading process.
  digitalWrite(_pin, HIGH);
  delay(250);

  // First set data line low for 20 milliseconds.
  pinMode(_pin, OUTPUT);
  digitalWrite(_pin, LOW);
  delay(20);

  uint32_t cycles[80];
  {
    // Turn off interrupts temporarily because the next sections are timing critical
    // and we don't want any interruptions.
    InterruptLock lock;

    // End the start signal by setting data line high for 40 microseconds.
    digitalWrite(_pin, HIGH);
    delayMicroseconds(40);

    // Now start reading the data line to get the value from the DHT sensor.
    pinMode(_pin, INPUT_PULLUP);
    delayMicroseconds(10);  // Delay a bit to let sensor pull data line low.

Patrick_M:
nella dht di adafruit vengono disabilitati gli interrupt e all'inizio c'è un delay di 250 ms ...

... ah ... brutta cosa ... :roll_eyes:

Quindi ... ogni volta che uno la chiama per leggere qualche cosa, blocca il chiamante per minimo 250msec, ma non solo, bloccando gli interrupt, per tutti il periodo in cui sono bloccati, ferma anche quello di timer0 e quindi SI, altera anche la "precisione" di millis() ... NON buono :grin:

Guglielmo

Micros indica che una singola lettura impiega 271ms, ma questi sono i due delay iniziali 250 + 20 della libreria, ergo il tempo di trasmissione non è misurato causa millis/micros "spenti" :slight_smile:

Ma qui il mistero si infittisce, perché la libreria poi continua ad usare micros :relaxed:

Immagino quindi che anche la porta seriale hardware non venga gestita durante la ricezione dal DHT.

Se ben ricordo, micros è indipendete dagli interrupts del timer0 (a differenza di millis) ma ne usa direttamente i registri e quindi, anche ad interrupts disabilitati, funziona ugualmente.

La seriale invece soffre della disabilitazione degli interrupts.

Guglielmo

io uso questa libreria DHTStable e qui i 250 ms di attesa non ci sono.... non è molto diversa come utilizzo si può fare una prova :smiley:
(gli interrupts li disabilita comunque)

Ciao
innanzitutto grazie a tutti per i consigli,
Patrick_M ho fatto delle prove con la libreria DHTStable purtroppo leggo sempre 00.00 sicuramente sbaglio io qualcosa , il codice è lo stesso ho cambiato solo queste righe.
Grazie per la tua disponibilità.
Guido

#include <dht.h>
dht DHT;
#define DHT22_PIN 9

void setup() {
  pinMode (digit1, OUTPUT);
  pinMode (digit2, OUTPUT);
  pinMode (digit3, OUTPUT);
  pinMode (digit4, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);
  digitalWrite(CLOCK_PIN, LOW);
  digitalWrite (digit1, HIGH);
  digitalWrite (digit2, HIGH);
  digitalWrite (digit3, HIGH);
  digitalWrite (digit4, HIGH);
}

void loop() {

 float t= DHT.temperature ;

mi pare che manchi la lettura… questa

  int chk = DHT.read22(DHT22_PIN);   //<--- devi fare questo per leggere i valori

hai provato a caricare l’esempio e verificare con quello?
intendo questo esempio

//
//    FILE: dht22_test.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.1.03
// PURPOSE: DHT library test sketch for DHT22 && Arduino
//     URL:
// HISTORY:
// 0.1.03 extended stats for all errors
// 0.1.02 added counters for error-regression testing.
// 0.1.01
// 0.1.00 initial version
//
// Released to the public domain
//

#include <dht.h>

dht DHT;

#define DHT22_PIN 5

struct
{
    uint32_t total;
    uint32_t ok;
    uint32_t crc_error;
    uint32_t time_out;
    uint32_t connect;
    uint32_t ack_l;
    uint32_t ack_h;
    uint32_t unknown;
} stat = { 0,0,0,0,0,0,0,0};

void setup()
{
    Serial.begin(115200);
    Serial.println("dht22_test.ino");
    Serial.print("LIBRARY VERSION: ");
    Serial.println(DHT_LIB_VERSION);
    Serial.println();
    Serial.println("Type,\tstatus,\tHumidity (%),\tTemperature (C)\tTime (us)");
}

void loop()
{
    // READ DATA
    Serial.print("DHT22, \t");

    uint32_t start = micros();
    int chk = DHT.read22(DHT22_PIN);   //<--- devi fare questo per leggere i valori
    uint32_t stop = micros();

    stat.total++;
    switch (chk)
    {
    case DHTLIB_OK:
        stat.ok++;
        Serial.print("OK,\t");
        break;
    case DHTLIB_ERROR_CHECKSUM:
        stat.crc_error++;
        Serial.print("Checksum error,\t");
        break;
    case DHTLIB_ERROR_TIMEOUT:
        stat.time_out++;
        Serial.print("Time out error,\t");
        break;
    default:
        stat.unknown++;
        Serial.print("Unknown error,\t");
        break;
    }
    // DISPLAY DATA
    Serial.print(DHT.humidity, 1);
    Serial.print(",\t");
    Serial.print(DHT.temperature, 1);
    Serial.print(",\t");
    Serial.print(stop - start);
    Serial.println();

    if (stat.total % 20 == 0)
    {
        Serial.println("\nTOT\tOK\tCRC\tTO\tUNK");
        Serial.print(stat.total);
        Serial.print("\t");
        Serial.print(stat.ok);
        Serial.print("\t");
        Serial.print(stat.crc_error);
        Serial.print("\t");
        Serial.print(stat.time_out);
        Serial.print("\t");
        Serial.print(stat.connect);
        Serial.print("\t");
        Serial.print(stat.ack_l);
        Serial.print("\t");
        Serial.print(stat.ack_h);
        Serial.print("\t");
        Serial.print(stat.unknown);
        Serial.println("\n");
    }
    delay(2000);
}
//
// END OF FILE
//