Go Down

Topic: come inviare pacchetti di dati via i2c tra due arduino? (Read 3271 times) previous topic - next topic

lesto

maurotec, credo che la ISR sia legata al clock, probabilmente stile change. ma nella libreria wired trovi anche twi.c e .h che saranno un ottimo punto di partenza, no?
in oltre se cerchi su iternet, come ti dicevo trovi mille implementazioni. se vuoi ci possiamo lavorare sopra, a me piacerebbe creare una libreria i2c simile alla serial, nel senso che abbia un buffer di richeste e di risposte, che lavorano "in background" tramite interrupt.

poi con calma mi leggo il datasheet, che descire lo standard twi più che parlare dell'hardware... ma se non erro twi è una implementazione opensource/openhardware, quindi non mi stupirei se tutti i micro hanno lo stesso circuito, o molto simile.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

MauroTec

La wire di arduino lo guardata e ci ho capito poco, in particolare non capisco i due puntatori a funzione con il come "*event*".

La isr twi di arduino implementa una macchina a stati con switch case e usa due buffer, come li usa non lo so perchè non ho studiato la classe, ma solo il codice C.

In pratica dopo uno start si possono scrivere e leggere un numero qualunque di byte e questo lo deve stabbilire il protocollo software, diversamente senza protocollo ogni scrittura o lettura il master deve sempre emettere la condizione di star e poi inviare il bit Read/Write e infine dopo aver ricevuto ACK invia un solo byte, per il prossimo deve fare nuovamente start.

Io penso che se la twi di arduino usa il buffer ci deve essere un metodo per inviare una array di caratteri, magari non prende string direttamente.

Quote
poi con calma mi leggo il datasheet, che descire lo standard twi più che parlare dell'hardware... ma se non erro twi è una implementazione opensource/openhardware, quindi non mi stupirei se tutti i micro hanno lo stesso circuito, o molto simile.


Twi deve per forza essere aderente allo standard i2c altrimenti non potrebbe dialogare con sensori, memorie ecc che usano i2c, quindi si tratta dello standard i2c chiamato twi per motivi di licenza.

A me serve una lib C per il twi, quindi disponibile a discutere e scrivere codice di test, ma solo C non C++ e no arduino IDE, perchè non c'è lo.

Ciao.
AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

lesto

bhe allora più tardi quando sono a casa (se funziona internet  ]:D) apro un post apposta (ahahah gioco di parole che non fa ridere nessuno) così ci possiamo sbizzarrire a farci suggerire trucchetti.

Io come limite impongo l'essere il più possibile "invisibile" all'utente (interrupt driven), asincrona (come la read della seriale) e quindi antiblocco.

Tu imponi C e nessun riferimento all'IDE (che cmq a priori credo sarebbe fuori discussione)

propongo di implementare solo il master/slave, roba più complessa la lasciamo a chi conosce bene il protocollo :)
Partiamo dal master visto che ho un sacco di sensori slave da usare come riferimento, poi lo slave speri diventi una specie di master semplificato.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

MauroTec

Quote
Tu imponi C e nessun riferimento all'IDE (che cmq a priori credo sarebbe fuori discussione)


La mia più che una imposizione è una constatazione del fatto che non posso scrivere e testare con il core,
quindi C significa codice funzionale, poi il code design ognuno lo può sviluppare come crede.

Non so se mi sono spiegato, ad esempio partiamo dalla funzione che invia dati allo slave, questa deve prendere
come parametro un'array di byte (meglio se prende un const char*). So per certo (ma faro un test in serata) sollevando
una condizione di start con:
       
Code: [Select]
// send START condition
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

avviene l'esecuzione della isr, e per qualche mistero il codice esce dalla isr e ci rientra e così via
fino a che non invii uno stop.

Ciao.
AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

lesto

guarda quà: http://arduino.cc/playground/Main/WireLibraryDetailedReference
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

secondsky

Cari ragazzi, sono felice che questo post abbia finito col porre le basi di tanti fecondi sviluppi.
Comunque, ieri sera sono riuscito con un po' di culo a fare quel che mi serviva in modo piuttosto semplice, senza comporre e scomporre stringhe.
È molto banale ma bastava spedire un byte alla volta in sequenza e leggerne uno alla volta.
Una cosa così per il master :
Code: [Select]
byte x1 = map(analogRead(A0),0,1023,0,255);
byte x2 = map(analogRead(A1),0,1023,0,255);
byte x3 = map(analogRead(A2),0,1023,0,255);
{
  Wire.beginTransmission(5); // transmit to device #4

  Wire.write(x1);              // sends one byte 
  Wire.write(x2);              // sends one byte 
  Wire.write(x3);              // sends one byte 

  Wire.endTransmission();    // stop transmitting
}


E una cosa così per lo slave :

Code: [Select]

void receiveEvent(int howMany)
{
  while(1 < Wire.available()) // loop through all but the last
  {
    byte x1 = Wire.read();
    byte x2 = Wire.read();
    byte x2 = Wire.read();
   
    Serial.print(x1);         
    Serial.print(",");         
    Serial.print(x2);         
    Serial.print(",");         
    Serial.println(x3);         


  }       // print the integer


Non pensavo fosse così semplice, non so se la cosa si complessifichi molto mandando valori differenti da quello che é un byte per volta, come qui, ma per fortuna è quello che serviva a me per ora.
Poi vedrò come implementare meglio un sistema di richieste e risposte. Se a qualcuno servisse, così dovrebbe funzionare. ;-)

PaoloP

Code: [Select]
byte x1 = map(analogRead(A0),0,1023,0,255);

credo che potresti anche scrivere

Code: [Select]
byte x1 = analogRead(A0)/4;

leo72

Arrivo solo ora, non ho letto tutto il thread, scusate se dico qualcosa già detto.
La Wire è implementata in HW nel senso che ci sono apposite circuiterie per fare il lavoro sporco di agganciarsi alla linea TWI. La ricezione avviene tramite HW/SW: la periferica riceve un carattere e contemporaneamente "suona" un interrupt di modo da avvertire la ISR preposta alla ricezione, che salva quel byte. Poi ci sono tutte le procedure per gestire i dati e su come agganciare le periferica sul bus.

lesto

meglio ancora: la twi lavora sull'hardware, la wire sono utility che lavorano sulla twi per renderela più "umana".

quindi l'idea è di rifare una wire meno umana ma più blindata.
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

secondsky


Code: [Select]
byte x1 = map(analogRead(A0),0,1023,0,255);

credo che potresti anche scrivere

Code: [Select]
byte x1 = analogRead(A0)/4;


Eh si è vero! :-)

lesto

Code: [Select]
byte x1 = analogRead(A0)>>2;

tutte le divisioni che sono potenze di 2 (quindi 2^x) possono essere sostituite da un bitshift a destra di x posizioni
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

secondsky

Più che altro il map mi era comodo perché a volte uso range diversi, ad esempio per i servi, ma grazie della dritta ;-)

Go Up