Difetto alquanto strano con ADS1115

Salve a tutti
Ogni tanto torno a trovarvi; questa volta ho un problema "strano" con ADS1115.
Premesso che ho due schede "Doit ESp32 devkit" con entrambi installati due ADS1115 che inviano su Arduino IOT in due progetti distinti:
Il primo montato a supporto di un acquario con due ingressi analogici per la lettura del Ph e la lettura della pressione della Co2;
Il secondo installato a supporto delle batterie del mio mini FV, con anchesso due ingressi analogici uno per la tensione e uno per la corrente;
Ecco il problema ce l'ho in quest'ultimo dove per un motivo che non riesco veramente a conprendere, durante le 24h il loop si blocca.
Che si blocca il loop me ne accorgo dal led che non blinca

...
  unsigned long t0 = millis() - t1;
  if (t0 >= 300) 
  {
    stato = !stato;
    digitalWrite(LED_BUILTIN, stato);
    t1 = millis();
  }
... 

Praticamente il problema l'ho riscontrato nell' ADS 1115, perchè se tolgo il filo dell'alimentazione e lo rimetto il loop riprende senza premere il "reset" e rifunzione random per le 24h.
La libreria usata è "Adafruit_ADS1X15.h".
Gli sketch praticamente sono identici, cambiano solo i nomi delle variabili, mentre quello a servizio dell'acquario non ha mai dato questo problema.
Ho provato a invertire le schede ADS ma il problema non cambia sull' esp del FV da sempre questo difetto.
Avreste qualche suggerimento come fare qualche tipo di debug per potere capire come risolvere questo problema?
Grazie

Letteralmente, interpreto che con la prima ADS1115 non si blocca mai, mentre si blocca con l'altra schedina ADS1115, ma da quanto hai scritto prima sembra che segua la ESP32...

Poi questa cosa complicata non serve:

  unsigned long t0 = millis() - t1;
  if (t0 >= 300) 

Più semplicemente:

  if (millis()-t1 >= 300) 

Ciao Scusa ho scritto male ora correggo anche se ho invertito le schede o ne metto una nuova (ne ho 5 schedine ADS) il difetto sull'esp delle batterie lo fa sempre

Grazie

Non c'è una "forma di risveglio" se interrompe il loop nella lettura del' ADS?

Prova con questo, ma non è detto che risolva.

Ciao, Ale.

Grazie per la risposta
Mi metto all'opera

Ho visto una lib Adafruit con un bel ciclo bloccante in caso di lettura errata da i2c (ad esempio per modulo scollegato) :roll_eyes: Magari c'entra, magari no, ma dalla descrizione...

Grazie Claudio
La cosa mi fa impazzire, ho perfino cambiato la Doit esp32 perché ne ho tre (due che lavorano e una di riserva)
Dopo aver aperto il post ho sostituito la boards sopracitata e fino a questa mattina alle 09:00 ha funzionato senza mai bloccarsi, da li in poi ho resettato e praticamente va a singhiozzo 1h, 2h, 45min, ed adesso è di nuovo in blocco
Non ho avuto ancora il tempo di modificare lo scketch come suggerito
La Doit è montata su una bords a viti quindi tutti i collegamenti sono benserrati dalla parte dell' Ads sono collegati con i fast
Quale altra libreria potrei usare? Una qualsiasi va bene?

Non saprei, non ho mai usato quel componente/libreria, ma, hai messo le resistenze di pull-up sul bus i2c? Quanto è lungo il collegamento? Si trova in vicinanza di sorgenti di disturbo elettrico? La parte che comprende logica e sensore, è attraversata da correnti impulsive che potrebbero invece essere fatte passare da un'altra parte con un diverso cablaggio?

Per risponderti;
Le resistenze di pull-up sono integrate nelle rispettive porte del esp, ma poi nell'altro progetto sono collegate identiche, il collegamento tra esp e ads e meno di 5 cm, disturbi sicuramente si perché a 20cm c'è l'inverter del fotovoltaico, no i cavi cc e ac no si interferiscono fra di loro e non sono nemmeno vicini e i componenti sono alimentati dalla 24V delle batterie ridotta a 5v da un cc/cc
Grazie
Anche io ho qualche sospetto sui disturbi dell'inverter ma mi è quasi impossibile trovargli un altra locazione ai componenti.

Hai considerato, magari anche solo per fae un test con un programmino minimalista che legge e stampa i valori sulla seriale, di non usare librerie e leggere gli ADS1115 direttamente usando comandi "wire" ? ... cosi vedresti se dipende dai componenti difettosi o dalla libreria malfunzionante.

Ho visto che spesso (almeno per roba semplice, dove si tratta solo di puntare a registri e leggere valori), usare direttamente i comandi wire mi risulta piu semplice, una volta precalcolati i valori dei vari bytes da spedire al sensore ... ad esempio, prima mi calcolo tutti i possibili MSB da spedire per i 4 canali, con la configurazione che serve a me', e me li segno:

// MEMO: 128SPS, single-shot, canali single-ended da 0 a 4.096V
// per dispositivi a 3.3V, comparatore disabilitato, tutti configurati identici
// indirizzo I2C 0x48
// valori di MSB precalcolati
// canale 0 = 0b10010010
// canale 1 = 0b10110010
// canale 2 = 0b11010010
// canale 3 = 0b11110010
// LSB = 0b10000011 uguale per tutti i canali

Poi li mando direttamente al sensore ogni volta che voglio che inizi una lettura su un determinato canale, in questo modo (esempio per il canale 0)

// per leggere un canale (ad esempio lo 0), scrivi nel registro di configurazione 0x01
// i 2 bytes MSB (diverso per ogni canale) e LSB (sempre lo stesso) in sequenza
// questo configura il canale 0 ed inizia la lettira e la conversione

Wire.beginTransmission(0x48);   // inizia la trasmissione
Wire.write(0x01);   // punta al registro di configurazione
Wire.write(0b10010010);   // spedisci MSB canale 0
Wire.write(0b10000011);   // spedisci LSB (fisso)
Wire.endTransmission();   // termina la trasmissione

delay(10); // attesa per far terminare la conversione, a 120SPS circa 8mS

Wire.beginTransmission(0x48);   // inizia la trasmissione
Wire.write(0x00);   // punta al registro di conversione, dove c'e' la lettura
Wire.endTransmission();   // termina la trasmissione
Wire.requestFrom(0x48, 2);   // richiedi i 2 bytes contenuti in 0x00 all'ADS1115
uint16_t valore = (Wire.read() << 8) | Wire.read();   // leggi i 2 bytes ed accodali

// se ti serve la tensione al posto dei bytes, converti cosi
tensioneCH0 = (valore * 4.096) / 32767.0;

Magari non sara' "elegante", ma io lo trovo piu semplice da capire (opinione assolutamente personale, ovvio) ... queste righe di esempio vengono da un programma che sto ancora tirando insieme, non e' detto che facciano quello che serve a te', e' da provare e modificare se necessario per adattarlo alle tue necessita' :wink: .

Ecco, a parte usare cavi schermati, suggerirei di mettere tutta la logica e la parte piu sensibile come l'ADS in una scatolina in metallo collegata a GND, e filtrare MOLTO bene l'alimentazione che viene dal convertitore DC-DC, non si sa mai quali "porcherie elettroniche" ci possano essere sovrapposte alle uscite di quei "cosi" :wink:

Grazie per i tuoi suggerimenti, mettero i consigli dí tutti in atto, ormai voglio riuscire a capire da dove deriva il problema
Non ho mai usato il wire direttamente quindi mi aiuterò con i tuoi esempi

... e ricordiamo sempre che I2C sta per "Inter-Integrated Circuit", ovvero un qualche cosa per collegare tra loro gli IC su un circuito e NON per portare in giro un qualche cosa.

Purtroppo viene spesso usato "per portare in giro, via cavo, segnali", ma NON essendo nato per questo, è ovvio che occorre adottare tutte le precauzioni per evitare problemi.

Consideriamo che, di base lavora nel campo delle centinaia di KHz, ma può arrivare a lavorare a velocità superiori ... quindi ...

Guglielmo

Per le mie conoscenze basilari non ho avuto sino ad adesso approcci con l'i2c, ma sono sempre più convinto che il problema venga da qualcosa di "esterno" visto che l'identica accoppiata di componenti e software funziona per l'acquario da forse un anno senza interruzioni mentre per il solare/batterie va a singhiozzo

Guglielmo, cercare di fare capire la verità su I2C a chi è profano è tempo perso
Devono sbatterci il cranio per bene e dopo averlo ben tumefatto allora "scoprono" che devono cambiare approccio con I2C, e che la documentazione va' letta e studiata

1 Like

Cercando di non fare adirare Guglielmo :wink:
In questi giorni ho fatto qualche prova; ho sostituito tutti i cavi di connessione, ho modificato lo sketch esempio di ads1115 con qualcosa non di mio ma trovato in rete che sembrava essere non bloccante, in quanto anche senza alimentare la scheda ads il loop "andava" ma con grande stupore e anche un pizzico di inc...ura dopo 22h l'ho trovato di nuovo piantato, e disalimentando e rialimentando l'ads il loop e ripartito e riscollegato nuovamente l'ads (per testare) il loop "va", tutto senza premere reset sulla board :face_with_spiral_eyes: :face_with_spiral_eyes: allego il codice trovato e attualmente provato

    unsigned long now = millis();
    switch (state) 
    {
      case WAITING_CH0:
      if (ads.conversionComplete()) 
      {
        adc0 = ads.getLastConversionResults();
        volts0 = ads.computeVolts(adc0);
        ads.startADCReading(ADS1X15_REG_CONFIG_MUX_SINGLE_1, false);
        state = WAITING_CH1;
      }
      break;
      case WAITING_CH1:
      if (ads.conversionComplete()) 
      {
        adc1 = ads.getLastConversionResults();
        volts1 = ads.computeVolts(adc1);
        state = IDLE;
        lastConversionTime = now;  // aggiorna timer per il prossimo ciclo
      }
      break;
      case IDLE:
      if (now - lastConversionTime >= samplingInterval) 
      {
        ads.startADCReading(ADS1X15_REG_CONFIG_MUX_SINGLE_0, false);
        state = WAITING_CH0;
      }
      break;
    }