dopo mesi chiedo aiuto i2c UnoR3 non va

ho perso mesi pensando fosse il codice

breadboard con i2c rtc e pullups.
Col mega tutto fila
con unor3 (a4,a5) non risponde.

leggo in rete che i2c sull'uno potrebbe essere difettoso.
chiedo una conferma.. prima di abbandonare il progetto.

naturalmente volevo anche utilizzare una comunicazione soft serial.. in alternativa. ma anche li vuoto tombale.

va tutto storto.

ho tentato di fare cerca sul forum ma dopo pagine di cose non pertinenti.. mi sono davvero arreso

asluti

Mah ... io ho alcune UNO R3 funzionanti e collegate a sensori e display I2C e non ho problemi ... cosa non va sulla UNO del I2C ??? :astonished:

Guglielmo

Non mi risulta che la I2C della UNO sia difettosa. :roll_eyes:

provato con l'i2c scanner? è presente nel playground anche se al momento non mi è accessibile.

Andrea

Fornire codice, schema ed esatti problemi.
Non si può tirare ad indovinare cos'è che non va a casa tua... :stuck_out_tongue:

rispondo a tutti.
scusate il ritardo nel rispondervi.

da tempo vorrei avere (e credo dovrò farmela visto che non ne trovo) una funzione che mi dia una risposta di presenza di un device i2c.
nel mio caso è un io expander mcp23017.
anche perchè ho notato che se la comunicazione i2c fallisce (uno o mega) non solo non ho risposte, ma l'esecuzione del progetto si interrompe.
Cioè se nel setup nelle prime righe ho un comando di begin transmission su un device i2c.. se stacco un filo il codice si interrompe. anche se quella richiesta non è vitale nel sw. cioè non fa nulla delle righe successive!
ho implementato l'if comunicazione == 0 .. in modo da avere almeno un bypass del blocco 'comunicazione i2c' ed andare avanti.
ma è banale.
cercherò i2c scanner.

ciò premesso..

ho una breadbord da tempo, con un rtc e l'expander.
se li attacco al mega col mio sw di base (sono pezzi di codice già fatto più personalizzazioni)
dove ho una read del device rtc, ed una inizializzazione dei banchi a e b dell'expander..

se ho il mega attaccato tutto fila liscio
cambio il tipo di device sull'IDE, riscrivo il codice nell'arduino 1r3.. lancio e non da segni di vita (l'i2c)

ovviamente non ho impegnato le porte a4 ed a5 in nessuna parte del codice.

cioè non mi resta che fisicamente collegare un oscilloscopio per capire se esiste un segnale i2c sui pins??

è questa la mia domanda: esiste un modo per fare una query sia dal lato di chi trasmette che da chi riceve? alcuni bus lo prevedono come specifiche.. ma io non sono esperto di bus.. e in generale non trovo in nessuna guida di arduino una bella lista di errorlevel che potrei eventualmente gestire a fronte di routines di trasmissione.

vi ringrazio!!

EDIT:
trovato
http://playground.arduino.cc/Main/I2cScanner

effettivamente ho una sorpresa: vedo solo l'rtc
e siccome l'output dell'ora è subordinato alla routine di inizializzazione dell'expander.. il programma si blocca perchè l'expander non risponde (o almeno lo deduco visto che lo scanner non lo sente!)

vi ringrazio

ugokind:
...
da tempo vorrei avere (e credo dovrò farmela visto che non ne trovo) una funzione che mi dia una risposta di presenza di un device i2c.
...

Io, per testare all'inizio la presenza di tutti i devices I2C, eseguo questa sequenza :

Wire.beginTransmission(0xnn);
delay(50);
if (Wire.endTransmission() != 0) {
   Serial.println("ERROR: No device available");
}

... dove ovviamente al posto di xx metti l'indirizzo del device. La Wire.endTransmission() ha il "buon giusto" di ritornare un codice d'errore :slight_smile:

Certo che se poi durante il funzionamento uno si scollega o si guasta ... ti frega :frowning:

Guglielmo

concordo. anche se è una prova per assurdo

cioè : io parlo.. se non rispondi deduco che non sei disponibile.

grazie g.

aggiungo (lo leggo nel codice scanner)

else if (error==4)
    {
      Serial.print("Unknow error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }

da qui scopro un errorlevel4..

ma la curiosità mi porta ad un altra domanda?
come mai tutti gli i2c sotto l'ID 16 vengono gestiti separatamente? (rc=68, expander va da 20 in su..)

arduino è uno di quelli?

In che senso scusa ? Parli di quel pezzo di codice che hai postato ?

Perché in quel caso l'IF serve solo a mettere lo zero di fronte alla cifra decimale se questa è una sola (in fase di print è brutto scrivere 0x4 e allora aggiunge lo 0 e stampa 0x04) :wink:

Guglielmo

non in quel senso.
è un copia incolla del codice di i2cscanner

dicevo che vedendolo noto che parla di un errorlevel 4
dunque sarebbe bello avere una lista di tuttigli errorlevel

tuttoqui

ugokind:
dunque sarebbe bello avere una lista di tuttigli errorlevel

nel i2c scanner c'è

error = Wire.endTransmission();

quindi l'errore è restituito dal metodo endTrasmission.

Se vai a vedere nella libreria Wire trovi

uint8_t TwoWire::endTransmission(uint8_t sendStop)
{
  // transmit buffer (blocking)
  int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop);
  // reset tx buffer iterator vars
  txBufferIndex = 0;
  txBufferLength = 0;
  // indicate that we are done transmitting
  transmitting = 0;
  return ret;
}

quindi in sostanza l'errore è il risultato della scrittura di twi_writeTo, ovvero

/* 
 * Function twi_writeTo
 * Desc     attempts to become twi bus master and write a
 *          series of bytes to a device on the bus
 * Input    address: 7bit i2c device address
 *          data: pointer to byte array
 *          length: number of bytes in array
 *          wait: boolean indicating to wait for write or not
 *          sendStop: boolean indicating whether or not to send a stop at the end
 * Output   0 .. success
 *          1 .. length to long for buffer
 *          2 .. address send, NACK received
 *          3 .. data send, NACK received
 *          4 .. other twi error (lost bus arbitration, bus error, ..)
 */
uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop)
{
  uint8_t i;

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

  // wait until twi is ready, become master transmitter
  while(TWI_READY != twi_state){
    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
  while(wait && (TWI_MTX == twi_state)){
    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
}

ecco l'elenco degli errori. :wink:

... emmm ... perché quelli riportati nel reference ufficiale non andavano bene ??? qui : Wire - Arduino Reference ]:smiley:

Guglielmo

No: il Reference viene aggiornato molto più lentamente del codice.
Se devo controllare cosa restituisce una funzione o come si inizializza, di solito, mi leggo il codice non il Reference. :wink:

@PaoloP : Si, ovvio, anche io, ma solo in seconda battuta :wink:

Ritengo comunque fondamentale una prima lettura del "reference" per capire "cosa fa cosa" (... non sempre così evidente nel codice) ed in seguito, occorrendo, l'esame del codice. Se prendi questo caso specifico vedrai che gli errori sono già tutti presenti nel reference, quindi, salvo che la funzione gli restituisse un valore non compreso tra quelli riportati nel reference, la lettura di quella parte di codice non aggiunge nulla di costruttivo :slight_smile:

Guglielmo

ultrachiaro

grazie

desidero non andare OT, ma ho da poco appreso una nuova disarmante situazione.
se cancello delle funzioni giusto per stare sotto i 23K di compilato.. funziona
se sto sopra, e ripeto codice funzionante sul mega, ho dei buchi
x es ho la funzione gettime che è il timestamp del ds1307. se compilo as is.. sopra i 23k di codice.. non vedo l'ora (ecco perchè credevo di non comunicare col bus)

invece se cancello a caso giusto per ridurre il codice (ho un loop molto corto e non cambia o da errori se piallo del codice) e mando su.. lo vedo.

in genereale sto sbattendo un po la testa.. perchè ho dei comportamenti anomali.
un altra situazione è che ho dei costanti reboot (ho un serial.println alla terza riga come "welcome") e mi trovo che se sto sopra i 23k.. con molto codice i2c di diagnostica (es i2c scanner come funzione) ho una ripetizione infinita del welcome!

ora devo mollare
stasera testerò un baud rate più basso, eventualmente cercherò di ridurre il codice

volendo mettere il programma su un chip montato su una millefori.. devo stare sull'1 e non sul mega!

saluti

L'unico dubbio che mi viene che il problema NON sia legato alla memoria Flash (con 256K non può dare problemi con un codice di 23K), ma piuttosto a qualche cosa che fai nel codice e che riempie la SRAM (8K sembrano tanti, ma ci vuole poco a riempirli) e ti incasina tutto ...

Magari sei al limite e togliendo un pezzo di codice, elimini delle variabili che così non occupano più la SRAM ...

... ripeto, non so, sto veramente tirando ad indovinare, ma se fossi in te inizierei con l'inserire la funzione che ti da la quantità SRAM disponibile (... non ho il link sottomano, ma con Google la trovi rapidamente) :wink:

Guglielmo

ugokind:
volendo mettere il programma su un chip montato su una millefori.. devo stare sull'1 e non sul mega!

Già.
Dovrai rivedere il codice perché la quantità di memoria della UNO è appena 2KB.
Per approfondire --> http://www.leonardomiliani.com/2013/la-memoria-sram-dei-microcontrollori/

farò così

utilissimi
spero di ricambiare!


EDIT

vi devo baciare in bocca!
scusate la confidenza ma erano mesi..

confermo!
dopo una 60ina di (F

prima di ogni uscita seriale

ho probabilmente abbattuto la soglia.
ora ho imparato una cosa nuova..

ugokind:
...
vi devo baciare in bocca!
...

Emmm ... facciamo una stretta di mano va ... XD XD XD

Battute a parte, ora però la vedo dura ... se già andavi fuori SRAM con gli 8K del mega ... sarà dura farlo stare nei 2K del uno ... :roll_eyes:

Guglielmo