[risolto] arduino e AM2321 si blocca in un looping infinito

salve a tutti.
Ho collegato un AM2321 al mio arduino micro e funziona benino.
l'unico problema che ho riscontrato e, che non riesco a risolvere, è che quando
effettuo la lettura su di esso alcune volte si blocca tutto.
ecco il codice:

void loop() 
{
  static bool ct1=false,ct2=false,ct3=false;

    if(millis()-relztime > 500 && !ct1)
          {leggisensori();ct1=true;}                            //questo  ci impiega circa 20 millisecondi ma alcune volte anche 8000 secondi
    if(millis()-relztime > 700 && !ct3)
          { VisualizzaMainScreen(); ct3=true;}  //questo ci impiega circa 120 millisecondi
    if(millis()-relztime > 900 && !ct2) 
         { controllotasti(); ct2=true;}                  //questo ci impiega circa 20 millisecondi
  
  if(millis()-relztime >= (100-p0)*10) 
           digitalWrite(4,true); //accende  in base alla percentuale p0
  if(millis()-relztime >= 999)  
  {
    ct1=false;ct2=false;ct3=false; //resetta le variabili statiche
    relztime=millis();   //ogni secondo ricomincia il conteggio
    digitalWrite(4,false); // e spegne
  }

}

void leggisensori()
{
   am2321.read();
   if(am2321.available())
   {
     u0= am2321.humidity/10.0L;
     t1= am2321.temperature/10.0L; 
   
   }     
}

Non capisco come mai succede: di norma la funzione leggisensori() impiega solo pochi millisecondi, altre volte impiega fino a otto secondi per effettuare le letture.
Questa cosa non va bene inquanto tutto il programma così va in malfunzionamento.
qualcuno mi può aiutare?
grazie e saluti.

La prima cosa che risulta evidente è lo scheduler delle varie operazioni che mi sembra un po' contorto.

Ma, a parte questo, nel calcolo della temperatura ed umidità dividi per 10.0L che non mi sembra corretto visto che la prima variabile è unsigned int e la seconda int.
u0= am2321.humidity / 10;
t1= am2321.temperature / 10;

ottaviane:
salve a tutti.

Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni
e a leggere il regolamento: Regolamento

Dovresti vedere il codice del metodo .read della classe am2321 all'interno della libreria.
Potrebbero esserci dei while o dei delay di attesa finché il dato non è disponibile.

Grazie PaoloP. Hai centrato il problema:
ho già fatto un po' di debugging delle librerie utilizzate per la lettura del sensore.
Mi sono accorto che il blocco avviene proprio nel metodo read() della classe wire.
Infatti la classe AM2321 utilizza wire.h per leggere i dati in modo seriale.
di seguito il codice detto cioè il metodo usato da AM2321 per leggere tramite wire.h:

bool readRaw() {
        //
        // Wakeup
        //
        Wire.beginTransmission(I2CADDR);
        Wire.endTransmission();

        //
        // Read Command
        //
        Wire.beginTransmission(I2CADDR);
        Wire.write(COMMAND);
        Wire.write(REGADDR);
        Wire.write(REGCOUNT);
        Wire.endTransmission();

        //
        // Waiting
        //
        delayMicroseconds(1600); //>1.5ms

        //
        // Read
        //
        Wire.requestFrom(I2CADDR, 2 + REGCOUNT + 2); // COMMAND + REGCOUNT + DATA + CRCLSB + CRCMSB
        int i = 0;
        for (; i < 2 + REGCOUNT; ++i)
            buf[i] = Wire.read();

        unsigned short crc = 0;
        crc  = Wire.read();     //CRC LSB
        crc |= Wire.read() << 8;//CRC MSB

        if (crc == crc16(buf, i))
            return true;
        return false;
    }

Il blocco avviene proprio in questa funzione.
Ho notato inoltre che il blocco aumenta la propria frequenza con l'aumentare del valore dell'umidità.
credo dunque che il problema sia proprio nel chip del sensore che s'imballa.
Però il fatto che la libreria wire.h non preveda il blocco dei looping di lettura mi sembra un po'
grave...forse il codice è giovane?
ciao e grazie.

per nid69ita: Ho fatto la presentazione...scusami :stuck_out_tongue:

risolto!!!!
nella twi.h dei cicli while non controllati entravano in looping infinito :astonished:
ho modificato un po' così:

#define TIMEOUT 250
uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop)
{
  uint8_t i;
  unsigned long tempo;

  // ensure data will fit into buffer
  if(TWI_BUFFER_LENGTH < length){
    return 1;
  }

  // wait until twi is ready, become master transmitter
  tempo=millis();
  while(TWI_READY != twi_state)
  {
    if(millis()-tempo>TIMEOUT) return 4;  //se il loop impiega più del tempo prestabilito esce e torna un errore
    continue;
  }
  twi_state = TWI_MTX;
  twi_sendStop = sendStop;
  // reset error state (0xFF.. no error occured)
  twi_error = 0xFF;

  // initialize buffer iteration vars
  twi_masterBufferIndex = 0;
  twi_masterBufferLength = length;
  
  // copy data to twi buffer
  for(i = 0; i < length; ++i){
    twi_masterBuffer[i] = data[i];
  }
  
  // build sla+w, slave device address + w bit
  twi_slarw = TW_WRITE;
  twi_slarw |= address << 1;
  
  // if we're in a repeated start, then we've already sent the START
  // in the ISR. Don't do it again.
  //
  if (true == twi_inRepStart) {
    // if we're in the repeated start state, then we've already sent the start,
    // (@@@ we hope), and the TWI statemachine is just waiting for the address byte.
    // We need to remove ourselves from the repeated start state before we enable interrupts,
    // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning
    // up. Also, don't enable the START interrupt. There may be one pending from the 
    // repeated start that we sent outselves, and that would really confuse things.
    twi_inRepStart = false;			// remember, we're dealing with an ASYNC ISR
    TWDR = twi_slarw;				
    TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE);	// enable INTs, but not START
  }
  else
    // send start condition
    TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA);	// enable INTs

  // wait for write operation to complete
  tempo=millis();
  while(wait && (TWI_MTX == twi_state))
  {
    if(millis()-tempo>TIMEOUT) return 4;  //se il loop impiega più del tempo prestabilito esce e torna un errore
    continue;
  }
  
  if (twi_error == 0xFF)
    return 0;	// success
  else if (twi_error == TW_MT_SLA_NACK)
    return 2;	// error: address send, nack received
  else if (twi_error == TW_MT_DATA_NACK)
    return 3;	// error: data send, nack received
  else
    return 4;	// other twi error
}

ciao e grazie.