comunicazione I2C

uwefed:
Gli indirizzi possono essere fissi, oppure avere una parte (normalmente i 3 bit inferiori) che possono essere selezionati con 3 piedini. cosí si possono mettere 8 dispositivi uguali sullo stesso bus.

Un esempio sono i chip EEPROM I2C tipo la serie 24LCxx. Mettendo a massa o a Vcc questi 3 piedini gli possiamo far assumere il valore logico 0 o 1 rispettivamente. Siccome i piedini sono 3, la logica binaria dice che 2^3 sono 8 combinazioni, ecco quindi gli 8 dispositivi uguali che possono essere messi insieme.
I restanti bit dell'indirizzo sono fissi e programmati in HW dal costruttore. L'indirizzo si può leggere dal datasheet del dispositivo.

ok mi è un po' più chiaro adesso :slight_smile:
ma mi sorge un'altra domanda... questo sistema di comunicazione mi sembra "lento" o sbaglio? a che frequenza va sull'arduino?
per svolgere il programma che ho postato sopra quanti millisecondi ci mettera più o meno? (tolto il delay finale ovviamente)
comunque il codice è giusto no? non ci sono errori vero?
grazie ancora :wink:

Le possibili velocitá sono:
Standard Mode 100 kHz
Fast Mode 400 kHz
Fast Mode Plus 1 MHz
High Speed Mode 3,4 MHz
Il ATmega sopporta:
Up to 400 kHz Data Transfer Speed
vedi pagina 214 di http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf
Ciao Uwe

La velocità dell'I2C (100 o 400 kHz) sugli Atmega la stabilisce la corrente di pull-up.
Per avere la max velocità mi pare servano sui 2/3 mA: per ottenerli usa 2 resistenze di pull-up da 1K5-2K2 (una per linea del bus): con 1K5 hai 3 mA, con 2K2 hai 2 mA. Sotto ai 2K2 non scendere, se vuoi la max velocità.

ok grazie :slight_smile:

Calamaro ha scritto una guida davvero completa qui:

scusate, sto disegnando un pcb e ho il problema che il sensore che comunica in I2C con l'arduino è un po' distante e mi chiedevo quale fosse la posizione migliore per piazzare le resistenze di pull-up? vicino all'arduino o vicino al sensore? non penso che cambi molto perchè non ho una grande distanza, 20/30 cm, è più che altro una curiosità :grin:
grazie in anticipo :wink:

Mettile dove capita, magari centralmente alle linee, così dai nel mezzo. Un fattore importante è il loro valore. Usa R comprese fra 1K5 e 2K2, per avere come minimo 2mA di corrente di pull-up con tensione a 5V.

@Leo
Nel caso di Arduino, le resistenze di pullup per il bus I2C sono interne al micro-controllore oppure vanno messe esterne?
E se non si mettono?

Giorni fa ne abbiamo discusso con Uwe. Il core di Arduino quando si comunica con l'I2C attiva in automatico le pull-up interne sui pin A4 e A5. Ma le pull-up di Arduino sono da 20/30K, quindi danno una corrente molto bassa. L'I2C può lavorare a 2 frequenze, 100 kHz e 400 kHz: per lavorare a 400 kHz necessita di una corrente di pull-up sulle linee di 2/3 mA.

Io uso quelle esterne. Volendo si può modificare il core per togliere l'attivazione delle pull-up interne.

se non si mettono non funziona.
Se si usano quelle interne, puo' funzionare, tenendo le connessioni molto corte ci sono casi in cui si puo' fare. ad esempio se usi un RTC che e' fisicamente vicino al micro perche' hai fatto uno standalone, puoi provare ad usare quelle interne.

Il valore delle resistenze non altera solo l'assorbimento, ma anche la forma d'onda dei segnali i2c, ed e' quello il motivo del mancato aggancio alla alta velocita'

Ho visto che nel file twi.c c'è la funzione che inizializza il bus per il master.

void twi_init(void)
{
  // initialize state
  twi_state = TWI_READY;
  twi_sendStop = true;		// default value
  twi_inRepStart = false;
  
  // activate internal pullups for twi.
  digitalWrite(SDA, 1);
  digitalWrite(SCL, 1);

  // initialize twi prescaler and bit rate
  cbi(TWSR, TWPS0);
  cbi(TWSR, TWPS1);
  TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;

  /* twi bit rate formula from atmega128 manual pg 204
  SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
  note: TWBR should be 10 or higher for master mode
  It is 72 for a 16mhz Wiring board with 100kHz TWI */

  // enable twi module, acks, and twi interrupt
  TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA);
}

Qui vengono attivate le resistenze di pullup interne.
Io collegato un RTC e un LCD con modulo specifico se breadboard e funzionano. (in effetti i cavetti sono abbastanza corti)
Cosa succede se oltre a quelle interne, che vengono attivate automaticamente dalla libreria, metto anche quelle esterne?

Usualmente è meglio non attivarle.
Come ha detto Testato, il valore influisce anche il fronte d'onda.
Guarda qui:

con le pull-up interne i fronti di salita sono molto lenti. Meglio disattivarle (commentando quelle 2 righe di codice) e mettere quelle esterne.

PaoloP:
Cosa succede se oltre a quelle interne metto anche quelle esterne?

E' come se stessi facendo un parallelo, quindi facendo i calcoli puoi capire di quanto stai caricando

Ciao a tutti, volevo chiedere: ho visto diversi schemi per collegare due modelli di Arduino con i2c ed alcuni hanno la 5V in comune e altri no, da cosa dipende?
Io ho provato con una mega ed un arduino uno alimentati separatamente sia con la 5V in comune che senza ed in tutte e due i casi funziona perfettamente, ho anche letto che se le due schede hanno alimentazione separata bisogna collegare la5V del master con il vin dello slave ma non mi sono fidato a provare.
Qualcuno di voi mi sa dire qual'é la configurazione corretta?

I due Arduino, se alimentati tramite due alimentatori diversi, devono avere in comune il segnale di "riferimento" ovvero ... il GND, e null'altro (salvo ovviamente il bus I2C) !

Guglielmo

gpb01:
I due Arduino, se alimentati tramite due alimentatori diversi, devono avere in comune il segnale di "riferimento" ovvero ... il GND, e null'altro (salvo ovviamente il bus I2C) !

Guglielmo

Grazie Guglielmo, e quale sarebbe la soluzione migliore, tenendo presente che sfrutterei praticamente quasi tutti i pin digitali sia del master che dello slive?
Due alimentatori o un unico (attualmente utilizzo uno da 9V da 850mA per il mega, basterebbe questo per tutti e due?), considerando che le varie schede relè le alimento separatamente.

Grazie

Quello che conta è cosa colleghi ai due Arduino ...
... in pratica devi vedere quanto assorbi su ciascuno, fare la somma, aggiungici un 30% per prudenza e ... hai che potenza ti serve per l'alimentatore.

Ovviamente, se hai servo o motori, ricordati di alimentarli con alimentatore separato per non sovraccaricare quello con cui alimenti Arduino e per ... non portare dentro disturbi :wink:

Guglielmo

Grazie