Problemi con lib. Wire non bloccante

Ciao Forum,

Sto lavorando al mio primo progettino che usa la scheda Mega, uno shield a 4 relè, una scheda a 16 relè (la “classica” SainSmart e simili), la scheda ethernet ENC28J60, il comune display 4x20 con connessione I2C, e infine un RTC DS1307.

Dopo un po’ di minuti si blocca tutto e cerca che ti cerca, anche grazie alla rete, ho trovato che il blocco avviene di volta in volta sul RTC o sul display, quando vengono invocate le chiamate alla libreria per il bus I2C. Non ho dubbi su questo perché ho inserito istruzioni di stampa nei dintorni di ogni chiamata.

Ho trovato che esiste una versione non bloccante di Wire e ho tentato di installarla. Mi riferisco a questa pagina qui, a circa 2/3 si trova il link: Gammon Forum : Electronics : Microprocessors : I2C - Two-Wire Peripheral Interface - for Arduino .

Il problema è che se pure sono riuscito a usare il RTC senza le chiamate alla libreria Wire, il display ne fa uso. Le due librerie paiono poter convivere ma è inutile: basta che uno solo dei dispositivi debba utilizzare la versione bloccante e il problema si ripresenta. Cercando un po’ ho trovato che alcuni hanno modificato il codice della libreria wire per renderla non bloccante. Ora vi chiedo come potrei secondo voi procedere. Vedo solo queste due strade:

  1. Metto mano al codice della libreria wire e così posso farla direttamente utilizzare dal RTC e dal display, e dai futuri sensori e dispositivi che volessi aggiungere.

  2. Metto mano al codice della libreria a supporto del LCD in modo che non chiami più i metodi di Wire.

Entrambe le soluzioni mi paiono una cosa un po’ delicata e fuori portata da uno sciacquino della programmazione qual sono, a meno che qualcuno non mi possa dare una mano a provarci. Ovviamente mi basterebbe qualche link a portata di dilettante :confused: e in cui sia spiegato passo passo come fare.

Se ci sono alternative meno invasive ovviamente sarei lieto di poterle usare.

Altra questione: ho avuto cattive esperienze per aver messo mano (in ambiente desktop, intendo) a librerie molto utilizzate; nel caso non abbia altra scelta che mettere mano al codice delle librerie, vorrei conservare le due versioni, magari rinominando quella modificata. Pensate si possa fare o esistono soluzioni più pulite? Vorrei avere il massimo dell’ordine possibile perché purtroppo tendo a confondermi facilmente.

Infine una mia perplessità, che non deve essere letta come una critica (poco) velata. Non credo di essere il solo ad aver provato a usare più di un dispositivo su I2C con un supporto software di base che provoca un problema tanto grave, tanto che ho trovato in rete che non sono il primo e non è nemmeno una cosa recente. Cosa ha impedito agli sviluppatori di rendere la libreria non bloccante dopo un po’ che si è manifestato il problema? Potrebbe esistere qualche valida ragione e prima di muovermi a fare modifiche che non sono state fatte da persone molto più in gamba di me vorrei sentire - se verranno - le vostre opinioni. Naturalmente se il problema è stato già risolto e sono stato io a non aver trovato niente con google, come non detto tutto quanto scritto in quest’ultimo paragrafo.

grazie a chi mi darà una mano.

Apx

Ricordo un topic, piuttosto corposo che lessi per intero dove veniva affrontato l’argomento. Si cercava di sostituire la libreria wire conservando la compatibilità. Di mio ho abbandonato la strada conservando però tutte le nozioni imparate, andando a riscrivere da capo la libreria per la gestione TWI, sviluppandola direttamente in C.
Ricordo che la fase di test fu molto lunga, soprattutto per la determinazione e la gestione degli errori su AVR.
In ogni caso il problema della libreria bloccante stava nella verifica di successo del operazione. In pratica la libreria dopo l’inizio di una operazione ne attende il completamento controllando solo il registro TWCR, questo però non tiene conto di alcun timeout. La soluzione più opportuna è l’inserimento di questo timeout. Questo è il codice che usai.

bool TWIWait()
{
	uint16_t t = TWI_TIMEOUT;//Imposto un timeout
	while (!(TWCR & (1 << TWINT)) && t--);//Creo un ciclo di attesa che si ripeta fintanto che l'operazione sia conclusa o il timeout sia arrivato
	return TWCR & (1 << TWINT);//Restituisco il valore del flag interrupt per definire se l'operazione sia stata conclusa normalmente o per timeout
}

Ora però non avendo mai messo mano al codice delle librerie di Arduino non saprei dirti quanto difficile sia implementare tale timeout. Fossi in te cercherei quella famosa discussione che si trova nel forum italiano.

Edit:
L’autore del topic se non ricordo male era lesto.

Prima di dare la colpa alla Wire, verificherei se hai rispettato le specifiche hardware della connessione.

Puoi mostrare lo schema?

QUESTO post di qualche mese fa ... può essere utile ?

Non so se risolve il problema ... l'autore non ha più avuto blocchi ... ::slight_smile:

Guglielmo

Proprio ora dopo un po' di ricerca, vedo che a quanto pare la resistenza di pull up di mega non offre buone prestazioni sul tempo di salita del segnale. Dato che non le ho previste e non ho a portata di mano niente attorno ai 4.7 k, appena posso vado a comprarle e vedo se il problema mi affliggerà ancora.

Dato che non avevo disegnato lo schema, vedrò prima se il problema si risolve con le resistenze e in caso contrario lo disegnerò e lo posterò. Grazie a tutti, per ora, sicuramente ho di che provare e rifletterci su :slight_smile: