AutoAddress I2C. E' possibile?

Monto diversi display I2C sulle mie schede con Arduino Nano e mi trovo a cambiare spesso la riga di programma

PCF8574_HD44780_I2C lcd(0x27,20,4);

dove definisco l’indirizzo esadecimale.

Pensavo: “se fondo un programma di scanner I2C al mio programma non dovrò più preoccuparmi…”

  byte error, address;
  int nDevices;

  nDevices = 0;
  for(address = 1; address < 127; address++ ) 
  {
   
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }

In questo caso il mio indirizzo è address, ma come ce lo metto in una riga “fuori” dal programma?

il problema è proprio quello...

non credo sia possibile, comunque

:) seguo

Se ci sono 2 dispositivi i2c (tra cui il display) non saprai mai quale dei due indirizzi corrisponde al display...

In questo caso il mio indirizzo è address, ma come ce lo metto in una riga "fuori" dal programma?

Intendi questo?

PCF8574_HD44780_I2C lcd(address,20,4);

miky_police: Se ci sono 2 dispositivi i2c (tra cui il display) non saprai mai quale dei due indirizzi corrisponde al display...

Intendi questo?

PCF8574_HD44780_I2C lcd(address,20,4);

Se avessi due periferiche I2C non avrei fatto questo tipo di domanda, magari ne avrei fatta un'altra... Quindi non ho questo problema.

Poi, si, il succo è quello. Address dovrei andare a metterlo prima del setup (), ma se lo calcolo "dopo" come faccio a metterlo "prima" ? (magari funziona lo stesso, non ci ho provato, ma dubito fortemente).

Una idea chè mi è venuta è quello di trovare Address, memorizzarlo su Eprom e far ripartire Arduino...

Secondo me potresti vedere se la classe ha un metodo per re-inizializzare l'oggetto (oppure te lo crei). Così istanzi l'oggetto prima del setup con un indirizzo a caso, poi nel setup trovi l'indirizzo correttoe re-inizializzi l'oggetto col nuovo indirizzo... Cazzata?

ho dato una letta veloce alla libreria e NON c'è un metodo setID() ...o simili...una volta passato l'ID al costruttore basta...quello è.

dovresti aggiungerlo tu il metodo.

soluzione alternativa...crei il tuo oggetto nel loop()...quindi nel setup() fai la ricerca dell'indirizzo e lo passi dopo ...con tutto ciò che ne consegue a livello di memoria.

Premesso che non sono proprio esperto di C / C++ / classi / metodi / ecc...

Guardando la libreria, il costruttore si limita ad assegnare il valore passato (lcd_Addr) alla variabile _Addr, che presumo sia privata. Poi il valore di _Addr viene usato solo dalla Wire.beginTrasmission(). Credo non sia problematico aggiungere un metodo pubblico tipo setAddr per assegnare il valore passato a _Addr. Anzi, potresti creare il metodo setAutoAddr che fa proprio quello che vuoi tu... si cerca l'indirizzo da solo.

Alla peggio potresti chiedere a testato (mi sembra che la libreria sia sua) se fa lui queste modifiche...

Si, l'aiuto di TESTATO (la libreria è sua e va benissimo) sarebbe il massimo...

ho provato a modificare la libreria per la ricerca automatica… e con uno dei miei display funziona…
è una modifica molto grezza… non gestisce errori in caso di address non trovato… probabilmente andrebbe controllata da qualcuno di quelli bravi…

comunque se vuoi provare basta che la inizializzi così:

PCF8574_HD44780_I2C lcd(0,20,4);

in pratica se passi 0 (zero) come indirizzo la libreria se lo cerca da sola. se passi un valore invece usa quello.

ti allego il cpp modificato, sostituisci quello che hai adesso.

EDIT: non gestisce nemmeno la presenza di più periferiche I2C… il primo indirizzo che trova lo assegna al display e morta lì…

PCF8574_HD44780_I2C.cpp (9.04 KB)

Provato ma a me non funziona. Uso solo una periferica I2C (display) su 0x27 ma se metto 0 oppure 0x0 il display non funziona. Ho visto come hai modificato la libreria e dovrebbe essere così, ma evidentemente qualcosa non va...

Ciao.
Ho provato con 3 diversi display (2 cinesate 20x4 comprate con I2C già saldato + il display 20x2 del kit arduino con un adattatore cinesata che ho comprato a parte) e funziona su tutti…
Non saprei che altro provare, forse il tuo display funziona in modo diverso dai miei…

PS: so che è banale e non voglio dubitare delle tue capacità… sicuro di aver sostituito il cpp originale nella cartella corretta?

PPS: questo il codice che sto usando per le prove:

#include <Wire.h> 
#include <PCF8574_HD44780_I2C.h>


// Address 0x27, 16 chars, 2 line display
PCF8574_HD44780_I2C lcd(0,16,2);


void setup()
{
  lcd.init();           // LCD Initialization              
  lcd.backlight();      // Backlight ON
  lcd.clear();          // Clear the display
  
  lcd.setCursor(0,0);   // Set the cursor to col 0, row 0
  lcd.print("Hello");   // Print the first word
  lcd.setCursor(0,1);   // Set the cursor to col 0, row 1
  lcd.print("World!   333");  // Print the second word
}

void loop()
{
}

Provato anche con il tuo programma, ma niente. Se metto l'indirizzo funziona, ma se metto ZERO non funziona.

Non è che devi mandarmi anche il file .h?

Il file lo ho sostituito nella cartella giusta spostando quello vecchio in un'altra cartella

eccolo, anche se non l’ho modificato…

nessun altro che abbia voglia di fare una prova? giusto per capire se ho beccato io gli unici 3 display che funzionano oppure se c’è un altro inghippo…

PCF8574_HD44780_I2C.h (3.8 KB)

Ciao...ho un paio di LCD a casa 20X4 e 16X2...con indirizzi diversi...sta sera, se riesco, faccio un test e faccio sapere.

Non essendo il C++ il mio forte (... solo ANSI C * *:grin:) magari dico una grossa stupidaggine, ma ... ... non puoi creare la variabile del tipo necessario globalmente ed inizializzarla succesivamente nel setup() dopo che avrai scoperto quale indirizzo I2C usare?

Una cosa del tipo ...

...
PCF8574_HD44780_I2C lcd;
...
void setup(void) {
...
... scopri l'indirizzo I2C
...
lcd = PCF8574_HD44780_I2C(_indirizzo_scoperto_ , 20, 4);
...
...
}

void loop(void) {

}

Guglielmo

No, perché la classe non ha un costruttore senza argomenti :).

SukkoPera:
No, perché la classe non ha un costruttore senza argomenti :).

Quindi basterebbe aggiungerlo nella libreria ? E’ possibile ?

Guglielmo

fratt:
eccolo, anche se non l’ho modificato…

nessun altro che abbia voglia di fare una prova? giusto per capire se ho beccato io gli unici 3 display che funzionano oppure se c’è un altro inghippo…

Niente da fare.
Ho provato anche a togliere tensione e rimetterla (nel LCD rimangono memorizzati dei parametri anche se resetti il NANO) ma se metto l’indirizzo funziona altrimenti se metto ZERO non lo trova

Beh, modificando la libreria si può sicuramente fare. Oppure con l’allocazione dinamica:

PCF8574_HD44780_I2C* lcd = NULL;

void setup() {
  for(byte address = 1; address < 127 && !lcd; address++ ) {
    Wire.beginTransmission(address);
    if (Wire.endTransmission() == 0) {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.println(address,HEX);

      lcd = new PCF8574_HD44780_I2C(address, 20, 4);
    }
  }

  if (!lcd) {
    Serial.println("No display found");
    while (true)
      ;
  }
}

Facendo così bisognerà anche cambiare tutte le righe tipo

lcd.print(...);

in:

lcd -> print(...);

SukkoPera: Oppure con l'allocazione dinamica ...

Questa mi sembra la soluzione più pulita :D

Guglielmo