Collegare due Arduino UNO - Vettore

Ciao a tutti!

Stiamo costruendo una piccola Serra per un progetto dell'Università con Arduino UNO. Per comodità (e per aver più PIN a disposizione) abbiamo utilizzato due Arduino per fare i vari controlli.

Abbiamo però bisogno di collegarli.

Ho cercato nel forum ma ho trovato molta gente che fa cose più complesse delle mie e sto cercando di capire se esiste una soluzione più semplice ed immediata.

Semplicemente, con il mio Arduino e con il programma che ho fatto, alla fine ho quattro parametri, Ti, To, Ui, Uo (sono delle Temperature e Umidità), che misuro con dei sensori ogni secondo.

Ecco, io vorrei collegare un PIN del mio arduino in OUTPUT con un pin dell'altro arduino in INPUT in modo che possa ricevere questi 4 valori.

E' possibile farlo con un semplice cavo? Perché ho trovato cose molto più complicate ma a me basta questo piccolo scambio di una informazione.

Poi con questi dati, l'altro programma fa quello che deve fare!

Grazie mille a chiunque riesca ad aiutarmi!!

PS, so che dovrei provare da solo, ma ora come ora ho con me solo un arduino e non posso "provare" sul posto!

La soluzione più semplice è che crei su entrambi gli Arduino una nuova seriale usando la SoftwareSerial (… se li hai disponibili ti consiglio pin 10 RX e pin 11 TX), dopo di che, con due semplici cavetti incroci i segnali, ovvero :

TX SoftwareSerial Arduino 1 ----> RX SoftwareSerial Arduino 2
RX SoftwareSerial Arduino 1 <---- TX SoftwareSerial Arduino 2

ed hai un collegamento seriale con i due attraverso cui scambiarti tutte le informazioni che vuoi :wink:

Guglielmo

http://www.logicaprogrammabile.it/comunicazione-tra-arduino-tramite-i2c/

è link esterno, non sò se sia permesso e mi scuso se non lo è. Ma fa il caso tuo, 2 pin (a4 ed a5) per comunicare con x arduino.

Non ho capito ... ... perché complicarsi la vita con il bus I2C ed il suo protocollo, con tutte le limitazioni che comporta riguardo alle distanze, quando, per scambiarsi quattro informazioni in croce, le seriali vanno più che bene ? :o :o :o

Guglielmo

gpb01:
La soluzione più semplice è che crei su entrambi gli Arduino una nuova seriale usando la SoftwareSerial (… se li hai disponibili ti consiglio pin 10 RX e pin 11 TX), dopo di che, con due semplici cavetti incroci i segnali, ovvero :

TX SoftwareSerial Arduino 1 ----> RX SoftwareSerial Arduino 2
RX SoftwareSerial Arduino 1 <---- TX SoftwareSerial Arduino 2

ed hai un collegamento seriale con i due attraverso cui scambiarti tutte le informazioni che vuoi :wink:

Guglielmo

guglielmo e una volta creati tx ed rx la comunicazione come avviene a livello software?

gpb01: Non ho capito ... ... perché complicarsi la vita con il bus I2C ed il suo protocollo, con tutte le limitazioni che comporta riguardo alle distanze, quando, per scambiarsi quattro informazioni in croce, le seriali vanno più che bene ? :o :o :o

Guglielmo

Perchè io non sapevo che si potesse fare diversamente xD sono nuovo in arduino ma sto cercando di imparare :)

Con le stesse chiamate che usi per la vera seriale ;), solo che, invece di Serial.xxxx() avrai mySerial.xxxx() dove mySerial è, ad esempio, il nome della SoftwareSerial che hai creato.

Guglielmo

anto30: Perchè io non sapevo che si potesse fare diversamente xD sono nuovo in arduino ma sto cercando di imparare :)

... proprio per questo dovresti cercare di semplificarti la vita, non di complicartela :D :grin: :D :grin:

Guglielmo

Porto un banale esempio, che è quello con cui si può provare facilmente un modulo Bluetooth connesso sulla seriale software …
… l’esempio permette di prendere i dati in arrivo sulla vera seriale e trasmetterli al bluetooth sulla seriale software e viceversa :

#include <SoftwareSerial.h>

#define  SS_RX 10            // RX PIN to receive  data
#define  SS_TX 11            // TX PIN to transmit data

SoftwareSerial ssSerial(SS_RX, SS_TX);

void setup()
{
  delay (2000);
  //
  Serial.begin(9600);        // Initialize USB Serial port
  //
  Serial.println("--- Ports ready ---");
  Serial.println("");
}

void loop()
{
  if (ssSerial.available() > 0) Serial.write(ssSerial.read());
  if (Serial.available() > 0) ssSerial.write(Serial.read());
}

… estremamente semplice no ?

Guglielmo

gpb01: ... proprio per questo dovresti cercare di semplificarti la vita, non di complicartela :D :grin: :D :grin:

Guglielmo

si infatti, ma non sapendo di questo sistema usavo l'unico che conoscevo.

gpb01: Con le stesse chiamate che usi per la vera seriale ;), solo che, invece di Serial.xxxx() avrai mySerial.xxxx() dove mySerial è, ad esempio, il nome della SoftwareSerial che hai creato.

Guglielmo

Ah ok, esattamente come ho fatto con il modulo bluetooth, creo un'istanza softwareserial ed eseguo le operazioni su quella, faccio subito qualche prova anchio.

anto30: Ah ok, esattamente come ho fatto con il modulo bluetooth, creo un'istanza softwareserial ed eseguo le operazioni su quella

... hai visto che invece ... lo conoscevi ! :) :) :)

Fermatevi sempre a ragionare un po' sulle cose che avete già applicato. Spesso hanno più di un possibile uso e ... è inutile reinventare l'acqua calda ;)

Guglielmo

gpb01: ... hai visto che invece ... lo conoscevi ! :) :) :)

Fermatevi sempre a ragionare un po' sulle cose che avete già applicato. Spesso hanno più di un possibile uso e ... è inutile reinventare l'acqua calda ;)

Guglielmo

Si vero, però non avevo ben compreso il senso di quella operazione e la usavo meccanicamente senza fermarmi a ragionare sul suo reale funzionamento. Mi servirà da lezione per il futuro, infondo sbagliando si impara :D

Libreria EasyTransfert --> https://github.com/madsci1016/Arduino-EasyTransfer

Guglielmo stavo provando giusto ora la comunicazione da te descritta.
Ho scritto su arduino mega:

 #include <SoftwareSerial.h>

#define  SS_RX 50         // RX PIN to receive  data
#define  SS_TX 51            // TX PIN to transmit data

SoftwareSerial ssSerial(SS_RX, SS_TX);
void setup()
{ 
ssSerial.begin(9600);
}
 
void loop()
{

for(int i=0; i<3; i++){ ssSerial.write(i); delay(1000);}
}

e su arduino uno:

#include <IRremote.h>
#include <dht11.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>

#define  SS_RX 2          // RX PIN to receive  data
#define  SS_TX 3            // TX PIN to transmit data
#define DHT11_PIN 4
#define button1 5
#define button2 7
#define LED1 6
#define LED2 9
#define LED3 10
#define receiver 8

SoftwareSerial ssSerial(SS_RX, SS_TX);
LiquidCrystal_I2C lcd(0x3F, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results;
dht11 DHT;

int tmp = 0, hmd = 0;
long nmillis = 0, omillis = 0, n2millis = 0;
int val = 1;
int preval = 0;

byte Centigradi[8] = {
  0b00000,
  0b01110,
  0b01010,
  0b01110,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};

void setup() {
  Serial.begin(9600);
   ssSerial.begin(9600);
  pinMode(button1, INPUT_PULLUP);
  pinMode(button2, INPUT_PULLUP);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  irrecv.enableIRIn(); // Start the receiver
 

  lcd.init();                      // initialize the lcd

  // Print a message to the LCD.
  lcd.backlight();
   // create a new custom character
  lcd.createChar(0, Centigradi);
    // set up number of columns and rows
  lcd.begin(16, 2);

  // print the custom char to the lcd
  // why typecast? see: http://arduino.cc/forum/index.php?topic=74666.0
 }
void dth() {
  int chk;
  nmillis = millis();
  if (nmillis > (omillis + 1000)) {
 
    chk = DHT.read(DHT11_PIN);    // READ DATA
    switch (chk) {
      case DHTLIB_OK:
      //  Serial.print("OK,\t");
        break;
      case DHTLIB_ERROR_CHECKSUM:
      //  Serial.print("Checksum error,\t");
        break;
      case DHTLIB_ERROR_TIMEOUT:
       // Serial.print("Time out error,\t");
        break;
      default:
       // Serial.print("Unknown error,\t");
        break;
    }
    // DISPLAT DATA
    if (DHT.temperature > 18)
      tmp = DHT.temperature;
    hmd = DHT.humidity;
    lcd.setCursor(0, 0);
    lcd.print("Temperatura: ");  lcd.print(DHT.temperature);  lcd.write((uint8_t)0);
    lcd.setCursor(0, 1);
    lcd.print("Umidita': ");  lcd.print(DHT.humidity);  lcd.print("%");
    lcd.print("");
    omillis = millis();

  }
}

void infrar() {
  if (irrecv.decode(&results)) // have we received an IR signal?
  {
    lcd.clear(); lcd.setCursor(0, 0);  lcd.print("Ricevuto IR: ");
    lcd.setCursor(0, 1);
    lcd.print(results.value, HEX); // display it on serial monitor in hexadecimal
    irrecv.resume();// receive the next value
  }
}

void serial(){
  if (ssSerial.available()) 
    int i = ssSerial.read();
}

void loop() {
  if (digitalRead(button1) == LOW) {
    switch (val) {
      case 0: preval = 0; val = 1; analogWrite(LED1, 0); analogWrite(LED2, 0); analogWrite(LED3, 0); break;
      case 1:  preval = 1; val = 2; lcd.clear(); lcd.setCursor(0, 0);  lcd.print("Valore: "); analogWrite(LED1, 0); analogWrite(LED2, 0); analogWrite(LED3, 0); break;
      case 2:  preval = 2; val = 0; lcd.clear(); lcd.setCursor(0, 0);  lcd.print("Ricevuto IR: "); analogWrite(LED1, 0); analogWrite(LED2, 0); analogWrite(LED3, 0); break;
    }

    while (digitalRead(button1) == LOW) ; //{ if(millis()<nmillis+5) ; else nmillis=millis(); }  //attendi il rilascio del pulsante
  }
  if (digitalRead(button2) == LOW) {
    switch (val) {
      case 2: preval = 0; val = 1; analogWrite(LED1, 0); analogWrite(LED2, 0); analogWrite(LED3, 0); break;
      case 0:  preval = 1; val = 2; lcd.clear(); lcd.setCursor(0, 0);  lcd.print("Valore: "); analogWrite(LED1, 0); analogWrite(LED2, 0); analogWrite(LED3, 0); break;
      case 1:  preval = 2; val = 0; lcd.clear(); lcd.setCursor(0, 0);  lcd.print("Ricevuto IR: "); analogWrite(LED1, 0); analogWrite(LED2, 0); analogWrite(LED3, 0); break;
    }

    while (digitalRead(button2) == LOW) ; //{ if(millis()<nmillis+5) ; else nmillis=millis(); }  //attendi il rilascio del pulsante
  }
int x=ssSerial.read();
    if (x>-1 && x<3){
    
      val=x;
      switch (val) {
      case 2: preval = 0; val = 1; analogWrite(LED1, 0); analogWrite(LED2, 0); analogWrite(LED3, 0); break;
      case 0:  preval = 1; val = 2; lcd.clear(); lcd.setCursor(0, 0);  lcd.print("Valore: "); analogWrite(LED1, 0); analogWrite(LED2, 0); analogWrite(LED3, 0); break;
      case 1:  preval = 2; val = 0; lcd.clear(); lcd.setCursor(0, 0);  lcd.print("Ricevuto IR: "); analogWrite(LED1, 0); analogWrite(LED2, 0); analogWrite(LED3, 0); break;
    }
    }
 
  

  switch (preval) {
  case 0: analogWrite(LED2, (analogRead(A0) / 4)); dth(); break;
    case 1: {
        analogWrite(LED1, (analogRead(A0) / 4));
        int k = analogRead(A0);
        if (k < 1000) {
          lcd.setCursor(11, 0);
          lcd.print(" ");
        } if (k < 100) {
          lcd.setCursor(10, 0);
          lcd.print("  ");
        } if (k < 10) {
          lcd.setCursor(9, 0);
          lcd.print("  ");
        }  lcd.setCursor(8, 0);
        lcd.print(k);
        break;
      }
    case 2: analogWrite(LED3, (analogRead(A0) / 4)); infrar(); break;


  }

}

I 2 software funzionano, il diplay cambia funzione ogni secondo.
Il problema si presenta quando scollego i 2 arduino e li collego a 2 batterie 9v, il display funziona regolarmente con i pulsanti ma non riceve alcuna informazione dall’altro e di conseguenza non avviene il cambio di funzione “automatico”.
Il problema è lo sketch o cosa? Come posso risolvere?

Ovviamente le masse devono essere in comune ...

Ricorda che anche una trasmissione seriale si basa su dei segnali HIGH (+Vcc) e LOW (GND), ovvero su delle differenze di potenziale e ... rispetto a cosa misuri le differenze di potenziale del segnale in arrivo da Arduino_2 su Arduino_1 se le masse non sono in comune ? ? ? :D

Guglielmo

gpb01:
Ovviamente le masse devono essere in comune

Ricorda che anche una trasmissione seriale si basa su dei segnali HIGH (+Vcc) e LOW (GND), ovvero su delle differenze di potenziale e … rispetto a cosa misuri le differenze di potenziale del segnale in arrivo da Arduino_2 su Arduino_1 se le masse non sono in comune ? ? ? :smiley:

Guglielmo

XD che errore stupido che facevo :slight_smile:
Il bello è che ci avevo pensato ma poi mi è completamente volato di mente.
Collegando alle usb mettevo in comune le masse, ecco perché funzionava.
Ho appena provato e va perfettamente, grazie mille ancora una volta.