Pages: [1]   Go Down
Author Topic: i2c senza master?  (Read 369 times)
0 Members and 1 Guest are viewing this topic.
ITA - PV - Canneto Pavese
Offline Offline
Newbie
*
Karma: 0
Posts: 36
oggi sono stanco; non parlatemi di lavoro!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Buongiorno a tutti
abbiamo 2 arduino; i2c prevede , in configurazione canonica che 1 faccia da master e 1 da slave.
Corretto?
Attendo la vostra risposta prima di continuare con la domanda.
Grazie
Logged

Leo55

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9185
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

abbiamo 2 arduino; i2c prevede , in configurazione canonica che 1 faccia da master e 1 da slave.
Corretto?

Si e non è possibile in nessun modo non avere il master, però puoi avere più master (multi master) se il tuo problema è far comunicare i device tra di loro senza passare obbligatoriamente dal master.
« Last Edit: February 11, 2013, 04:23:59 am by astrobeed » Logged

ITA - PV - Canneto Pavese
Offline Offline
Newbie
*
Karma: 0
Posts: 36
oggi sono stanco; non parlatemi di lavoro!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao Astro e grazie per la risposta.
probabilmente dopo varie letture di documentazione devo essere arrivato alla configurazione con 2  master pero', di fatto, con il codice che tiallego (e' estrapolato da un codice molto piu' lungo, scusa per qualche inesattezza) faccio lavorare i 2 arduino sia come master che come slave all'occorrenza.
Stesso sketch su entrambi, cambia ovviamente la ID
Code:
#define THIS_ARDUINO_ID 1
#include <Wire.h>
char rets[11],ret_good[14],id[4];
String readString;

void setup()
{
Wire.begin(THIS_ARDUINO_ID);
Wire.onReceive(receiveEvent);
Wire.onRequest(requestEvent);
Serial.begin(115200);
}
void loop()
{
if (Serial.available() > 0)
{
readString="";  
while (Serial.available())
{
/* *****************************************
***  RICEVE LA STRINGA DI COMANDO
***  i primi 3 bytes sono la id di destino
***  il comando e' in readstring
***************************************** */
}
readString+="\0";

/* A chi va? */
String id_station=readString.substring(1,3);
id_station+="\0";
id_station.toCharArray(id, sizeof(id));
id_arduino_to = atoi(id);
readString=readString.substring(3);

/* se la id e' di questo arduino o null esegue il comando in locale */
if((id_arduino_to == THIS_ARDUINO_ID) || (id_arduino_to == NULL))
{
                        flag_not_local=0;
//Serial.println("LOCALE "+readString);
/*  esegue la funzione di elaborazione del comando* /
                        process_it();
                        Serial.println(ret_good);
}
else
{
                         /* E' UN COMANDO CHE VA SU UN'ALTRO ARDUINO */
Serial.println("WIRE "+readString);
/* invia la stringa comnando al target */
wire_send(id_arduino_to);
/* imposta il flag ad 1 in modo che sulla risposta non venga elaborata la wire.onreceive
ma continui su questo branch fino alla fine */
                        flag_not_local=1;
                        /* <-- importantissimo ! e' possibile che su richieste pesanti si debba aumentare il
                        delay per dare tempo all'arduino target di prepare la risposta */
                        delay(5);  
                        // richiedo alla id_targe il risultato del comando
                        Wire.requestFrom(id_arduino_to,31);
                        readString="";
           while (Wire.available())
                          {
                            char c = Wire.receive();
                            readString+= c;
                        }  
           readString+= "\0";
                        Serial.println("Ricevuto "+readString);
}
}
}

void wire_send(int id_arduino_to)
{
char w_send[31];
readString.toCharArray(w_send, sizeof(w_send));
w_send[31]= '\0';
int i;
Wire.beginTransmission(id_arduino_to);
while (w_send[i])
{
Wire.send(w_send[i++]);
}
Wire.endTransmission();
//Serial.println("Inviato "+readString);
}

void receiveEvent(int howMany)
{
  if (flag_not_local==0)
  {
/* qui riceve un stringa (comando) quando fa da pseudo slave */
readString="";
while (Wire.available()>0)
{
char c = Wire.receive();
readString+= c;
}  
readString+= "\0";
Serial.println("Ricevuto "+readString);
/* fa quello che il comando prevede */
    process_it();
  }
}

void requestEvent()
{
/* risponde ad una richiesta dati */
    Serial.println("** REQUEST TO COMMAND ");
     Wire.send(ret_good);
}

void process_it()
{
/* processa il comando */
/* il risultato va nel char ret_good */
 
}

Dimmi cosa ne pensi
Ciao e grazie
« Last Edit: February 11, 2013, 05:27:52 am by lsinfo » Logged

Leo55

Rome (Italy)
Offline Offline
Tesla Member
***
Karma: 120
Posts: 9185
"Il Vero Programmatore ha imparato il C sul K&R, qualunque altro testo è inutile e deviante."
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

faccio lavorare i 2 arduino sia come master che come slave all'occorrenza.

Così non va bene, il multi master è esplicitamente previsto dal protocollo I2C e va configurato correttamente, dovrebbero esserci delle librerie già pronto per Arduino, da qualche parte le avevo viste però non mi ricordo dove.
Logged

ITA - PV - Canneto Pavese
Offline Offline
Newbie
*
Karma: 0
Posts: 36
oggi sono stanco; non parlatemi di lavoro!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Astro
e' quello che pensavo anche io....ma invece funziona benissimo!
Ho cercato in rete da tutte le parti qualcosa del genere ma non ho trovato nulla.
Il vero gioco lo fa la if (flag_not_local==0) in testa alla receiveEvent che evita che la risposta alla wire.request sia intercetta ed esaurita nella funzione  ed invece ritorna subito nel corpo principale per fare processare i dati dal while (Wire.available()) { nel corpo del loop.
Con questo delay va alla grande, e usando la vecchia lib wire (io ho un ide 023).
Mah, che sia un bel trucco?
« Last Edit: February 11, 2013, 04:42:53 am by lsinfo » Logged

Leo55

Pages: [1]   Go Up
Jump to: