Comunicazione tra arduino uno ed arduino due (pin digitali)

Salve! Ho a disposizione Arduino Uno e Arduino Due, e vorrei metterli in comunicazione tra loro (un semplice passaggio di dati di tipo Stringa).Per problemi dovuti al progetto che sto realizzando, ho a disposizione solo i pin digitali e non le porte seriali hardware! Qualcuno ha qualche idea? Inoltre ci sarebbe il problema dei differenti livelli di tensione, e anche su questo ho qualche dubbio. Grazie dell'aiuto!

Usa la I2C con pullup collegate al 3.3V.

Mmm. Non ho mai usato la comunicazione con protocollo I2C, esiste qualche esempio o tutorial chiaro a riguardo? Inoltre la rete di pull up credi che vada realizzata in modo resistivo o esiste un modo migliore che non appesantisca ulteriormente lo schema circuitale complessivo sulla breadboard?

La pagina della libreria Wire (I2C/TwoWire):

Qualche tutorial venuto fuori googlando su internet:
http://playground.arduino.cc/Main/WireLibraryDetailedReference

Grazie mille! Questi tutorial sono davvero utili!

DemonDust:
Grazie mille! Questi tutorial sono davvero utili!

mi fa piacere :wink:

Ciao Leo72, mi dispiace se rompo ancora ma volevo un tuo consiglio riguardo un piccolo progetto che sto realizzando, e che coinvolge a questo punto anche la comunicazione I2C. Per farla breve ho realizzato una piccola applicazione android che mi consente attraverso uno shield bluetooth (quello della seeedstudio) di comunicare con arduino uno. Questo qui (master) a sua volta comunica con un altro arduino uno (slave). Per provare la comunicazione tra i due, invio delle stringhe in maiuscolo dal cellulare al master, questo le invia allo slave che ne trasforma i caratteri in minuscolo, per poi rimandarle al master e di seguito al cellulare. Ecco il codice:

//MASTER: Arduino uno smd r3

#include <Wire.h>
#include <SoftwareSerial.h>   //Software Serial Port

/*Pin per la serial tra modulo BT e shield
Non uso 0 ed 1 dato che questi vengono usati di default per la serial tra shield e arduino*/
#define RxD 6 
#define TxD 7

#define DEBUG_ENABLED  1

//Baud rate
const unsigned int BAUD_RATE = 38400;
const unsigned int BTBAUD_RATE = 38400;

//Software Serial
SoftwareSerial blueToothSerial(RxD,TxD);

//Variabili
char master1;
char master2;
char master3;

void setup()
{
  //Set di Arduino come Master nella I2C
  Wire.begin();
  
  //Set altre comunicazioni
  Serial.begin(BAUD_RATE);
  pinMode(RxD, INPUT);
  pinMode(TxD, OUTPUT);
  setupBlueToothConnection();

  //Avviso d'inizio programma
  Serial.println("START E FINE SETUP");
  Serial.println("Programma per la conversione di stringhe");
  Serial.println("dal maiuscolo al minuscolo");
}
 
void loop()
{
    
  while(blueToothSerial.available()>0)//controlla l'arrivo di dati DALLO shield bluetooth
  {
    master1 = blueToothSerial.read();
    //Serial.print(rec_command);
    /*Invio sul bus I2C una stringa allo slave
    device che ha come indirizzo il valore 0x04*/
    Wire.beginTransmission(0x04);
    delay(10);
    //invio un carattere
    Wire.write(master1);
    //fine trasmissione
    Wire.endTransmission();
    delay(10);
    //richiedo un byte allo slave che ha indirizzo 0x04
    Wire.requestFrom(0x04, 1);
    //attendo la disponibilità di dati sul bus I2C
    while(Wire.available())
    {
      /*quando è presente un dato avvia
      la lettura*/
      master2 = Wire.read();
      //verifico che il byte letto dallo slave sia stato
      //incrementato
      if(master2 != master1)
      {
        Serial.println(master2);
        blueToothSerial.print(master2);
      }
    }
    
    delay(5);
 
    }
    
    if(Serial.available()>0)
    {
      blueToothSerial.print("\r\n");
      while (Serial.available()>0)
      {
        master3  = Serial.read();
        blueToothSerial.print(master3);
        delay(10);
      }
    blueToothSerial.print("\r\n");
  }
  
 
  
  delayMicroseconds(500);
 
  
}

//Funzione di setup per lo shield bluetooth
void setupBlueToothConnection()
{
  blueToothSerial.begin(BTBAUD_RATE); //Set BaudRate 38400 (valore di default)
  blueToothSerial.print("\r\n+STWMOD=0\r\n"); //set bluetooth slaver
  blueToothSerial.print("\r\n+STNA=SeeedBTGianni\r\n"); //set il nome come "SeeedBTGianni"
  blueToothSerial.print("\r\n+STOAUT=1\r\n"); // permette ai dispositivi accoppiati di connettersi
  blueToothSerial.print("\r\n+STAUTO=0\r\n");// auto connessione proibita
  delay(2000); //delay obbligatorio.
  blueToothSerial.print("\r\n+INQ=1\r\n"); //rende lo slave bluetooth individuabile
  delay(100); 
  blueToothSerial.print("\r\n+STECHO=1\r\n");
  delay(2000); //delay obbligatorio.
  Serial.println("Lo slave bluetooth e' adesso individuabile!");

  blueToothSerial.flush();
}
//SLAVE: Arduino uno
#include <Wire.h>

//variabili
char slave1;
char slave2;

void setup()
{
  //Impostazione dell'arduino slave
  Wire.begin(0x04);
 
  /*Eventi per la ricezione del dato
  e per la richiesta del dato*/
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);
}
 
void loop()
{
  //esegui qualcosa
  delay(1000);
}
 
void receiveEvent(int data)
{
  /*questo evento viene generato quando sul bus
  è presente un dato da leggere*/
 
  //eseguo la lettura
  slave1 = Wire.read();
 
  //elaboro il dato letto
  slave2 = slave1 - 32;
}
 
void requestEvent()
{
  /*questo evento viene generato quando il master
    richiede ad uno specifico slave
    una richiesta di dati*/
 
  //spedisco il dato al Master
  Wire.write(slave2);
}

Ora la comunicazione avviene con successo, solo che ho tre problemi che per poca esperienza non so come risolvere

  1. I caratteri convertiti mi appaiono uno alla volta sullo schermo del cellulare: come posso correggere il codice in modo da far arrivare le stringhe intere?
    2)Purtroppo quando lo shield cerca dispositivi con cui connettersi l’arduino converte e stampa sullo schermo del cellulare le stringhe che informano sullo stato attuale dello shield. Come posso impedirlo?
    3)Quando invio delle stringhe dal monitor seriale del pc arrivano a pezzi sul cellulare, o mi stampa caratteri nulli? Hai qualche idea a riguardo?
    Grazie mille dell’aiuto a te e a chiunque voglia darmi il suo parere! :smiley:

DemonDust:

  1. I caratteri convertiti mi appaiono uno alla volta sullo schermo del cellulare: come posso correggere il codice in modo da far arrivare le stringhe intere?

Vedendo il codice, viene eseguito ciò che ha descritto, ossia l'invio e la ricezione di un solo carattere per volta.
Metti un controllo basato su .available() affinché continui a ricevere i dati finché ce ne sono di disponibili.
Oppure prevedi che la trasmissione inizi trasmettendo il numero di caratteri che verranno immessi e che in ricezione vengano letti tutti questi.
Oppure ancora prevedi un carattere di fine, ricevuto il quale termini la ricezione.

2)Purtroppo quando lo shield cerca dispositivi con cui connettersi l'arduino converte e stampa sullo schermo del cellulare le stringhe che informano sullo stato attuale dello shield. Come posso impedirlo?

Inizia le trasmissioni con un carattere particolare oppure con una sequenza specifica. Solo nel caso riceva/no questo/i carattere/i lo/li stampi.

3)Quando invio delle stringhe dal monitor seriale del pc arrivano a pezzi sul cellulare, o mi stampa caratteri nulli? Hai qualche idea a riguardo?

La velocità impostata sul monitor seriale è identica a quella dello sketch?
Hai provato usando un terminale vero e proprio invece del monitor dell'IDE?
Forse vengono interpretati anche i caratteri di fine riga?

Applicando un po' di controlli il codice sembra funzionare correttamente! Però c'è una cosa che non capisco della I2C: dato che la funzione Wire.read legge solo un byte alla volta, solo char posso leggere? Ad esempio se volessi inviare dallo slave al master un dato di tipo float userei "Wire.write(float)", ma se volessi leggere lo stesso float col master che funzione dovrei usare?

Si entra in un campo minato. La scomposizione di tipi di dato che occupano più di 1 byte è stato trattato diverse volte.
Devi spedire il dato scomposto nei singoli byte e poi lato ricevente devi ricostruire il dato riassemblandolo.

Se cerchi argomenti tipo "spedire numeri su seriale" o cose del genere troverai quel che cerchi, la logica è la stessa cambia solo il canale (I2C al posto della seriale).

Immaginavo si dovesse fare una cosa del genere, ora devo solo provare con vari tipi di dato e vedere come funziona la comunicazione. Tra l'altro ho il dubbio che il pin SDA e il pin SCL delle due schede (Arduino Uno e Arduino Due) lavorino a tensioni diverse, o mi sbaglio? Lasciando il collegamento diretto tra questi pin (ad eccezione della rete di pullup prevista dall'I2C) non dovrebbero esserci problemi, vero?

DemonDust:
Immaginavo si dovesse fare una cosa del genere, ora devo solo provare con vari tipi di dato e vedere come funziona la comunicazione. Tra l'altro ho il dubbio che il pin SDA e il pin SCL delle due schede (Arduino Uno e Arduino Due) lavorino a tensioni diverse, o mi sbaglio?

Non ti sbagli. La DUE lavora a 3V3 mentre la UNO a 5V.

Lasciando il collegamento diretto tra questi pin (ad eccezione della rete di pullup prevista dall'I2C) non dovrebbero esserci problemi, vero?

No, non va bene. Devi usare un traslatore di livelli

Pensavo che la rete di pullup alimentata a 3.3V mantenesse i valori di tensione abbastanza bassi da essere accettabili da entrambe le board! Comunque grazie mille, i tuoi consigli mi sono stati molto utili! :smiley:

come si realizza un traslatore di livelli tra Arduino due e arduino uno , per poterli collegare attraverso la I2C ?

c'è qualche link o spiegazione dove guardare ?

Pensare ad un arduino due che fa da master è tre arduino uno come slave, i quali a loro volta sono dei master rispetto ad altri arduino uno (ramificazione), è possibile ?

A 4 canali, quindi 2 I2C--> http://www.robot-italy.com/it/4-channel-i2c-safe-bi-directional-logic-level-converter-bss138.html
Oppure a 8, 4 I2C --> 501395 - Convertitore di livello logico - 8 canali - bidirezionale , da Adafruit a € 8,70 su Robot Italy

Io userei quello a 4.
Visto che la 2 ha 2 I2C, basta collegare da un lato VCC (3V3), SDA, SCL, SDA1, SCL1, GND e dall'altro VCC (5V), due linee SDA, SCL e il GND.

Naturalmente te lo puoi ricreare su una basetta millefori.
Di questo (712009 - Logic Level Converter Bi-Directional , da Sparkfun a € 2,70 su Robot Italy), simile al primo, trovi anche lo schema: http://dlnmh9ip6v2uc.cloudfront.net/datasheets/BreakoutBoards/Logic_Level_Bidirectional.pdf