Por que conectar dous arduínos?
Imos conectar dous arduinos entre si para que funcionen de maneira sincronizada. Hai diversas ocasións nas que podemos necesitalo, pero vou resaltar dúas delas:
Programas en paralelo
Se usásemos un microprocesador (como no caso dun LEGO ou unha Raspberry Pi) isto non tería problema, pois permite a execución de varios programas de maneira simultánea.
Unha solución é utilizar dúas placas: unha encárgase do control do motor de apertura e peche da porta e outra das luces, son, alarma, etc., e sincronizamos os dous programas mediante o envío de mensaxes desde unha placa a outra.
Necesitamos moitos pins
Sin embargo pode ser tamén interesante traballar na clase a conexión entre arduínos. Por exemplo, nun proxecto dun cruce de semáforos, un compoñente do equipo pódese encargar do control dos LEDs dos semáforos e do son dos pasos de peóns, e outro de programar nunha matriz de LEDs o boneco que se move cando o semáforo está verde. No canto de unificar todo iso nunha única placa (non nos chegarían os pins), facer de novo as conexións e unificar os programas nun programa global podemos facer que o programa de control dos semáforos envíe unha orde a outra placa para que active a matriz de LEDs cando se precise.
Conexión serial:
Para poder establecer a comunicación serie entre dous arduínos requírense unha conexión serie Rx-Tx cruzada e unir as masas:
- Para envío de datos do mestre ao escravo: Pin Tx do mestre co pin Rx do escravo.
- Para envío de datos do escravo ao mestre: Pin Tx do escravo co pin Rx do mestre.
- Unión das masas dos dispositivos.
A distancia máxima que soporta o bus serie depende da velocidade de transmisión de datos pero aproximadamente a 9600 baudios podemos poñer unha distancia máxima de 15 metros.
Montaxe
Hai dúas maneiras de facer isto:
- Mediante os pins Rx (pin 0) e Tx (pin 1) das placas. Neste caso antes de subir el código a cada Arduíno cómpre desconectar os pins Rx e Tx, pois estes pins tamén son usados para comunicarse por USB e non poderiamos instalar o programa.
- Habilitando outros pins dixitais da placa para que fagan a función Rx e Tx. Desta maneira non é necesario desconectar a comunicación para poder instalar os programas mediante USB.
Antes de instalar os programas fíxate ben a que porto tes conectada cada placa, pois cada unha levará un programa diferente. No caso de dúbidas deixa conectado o cable USB só da placa na que queiras instalar o programa e desconecta o da outra.
Prácticas:
Imos facer dúas prácticas, unha sinxela na que un pulsador conectado á placa 1controla un LED conectado á placa 2, e outra na que se move un servo conectado á placa 1 e uns LEDs conectados á placa 2 escintilan segundo sexa o movemento do servo.
- Se utilizamos a conexión Rx=0 e Tx=1, nos programas, para enviar e recibir datos, utilízanse os mesmos comandos que utilizamos para comunicarnos coa consola serie:
Serial.print('A'); Serial.available(); Serial.parseInt(); Serial.read(); etc.
- Se habilitamos outros pins Rx e Tx (no noso caso Rx=7 e Tx=8), hai que instalar a librería SoftwareSerial.h e indicar os pins Rx e Tx que queremos habilitar mediante a instrución
SoftwareSerial nomedaplaca(7, 8);
Os comandos utilizamos son moi similares aos que utilizamos para comunicarnos coa consola serie, só hai que substituír “Serial” polo nome da placa.
nomedaplaca.begin(9600); // Inicia a comunicación serie nomedaplaca.print('A'); nomedaplaca.available(); nomedaplaca.read(); etc
Segundo sexa a conexión que vaias utilizar elixe as prácticas correspondentes.
1. Proba (pins 0-1)
1. Probamos: Imos facer unha práctica sinxela para entender como hai que facer para enviar datos dunha placa a outra: Nun Arduíno conectamos un pulsador e noutro conectamos un LED. O LED debe cambiar de estado cada vez que prememos no pulsador.
// Declaración de variables: int pulsador=2; // Configuración: void setup(){ Serial.begin(9600); // Inicia a comunicación serie } // Programa: void loop() { if (digitalRead(pulsador)==1){ while(digitalRead(pulsador)==1); // Agarda mentres o pulsador esta premido delay(20); // tempo para evitar o efecto rebote do pulsador Serial.print('A'); // Envía o dato A } }
Programa da placa 2:
// Declaración de variables: int led=13; char sinal; int estado=0; // variable na que almacenamos o estado do LED // Configuración: void setup(){ Serial.begin(9600); // Inicia a comunicación serie pinMode (led, OUTPUT); digitalWrite(led, LOW); } // Programa: void loop(){ if (Serial.available()) { // Se recibe un dato sinal = Serial.read(); // Lemos o dato if (sinal == 'A') { // Se o dato é A cambiamos o estado do led if (estado==0) { digitalWrite(led, HIGH); estado=1; } else{ digitalWrite(led, LOW); estado=0; } } } }
Lembra que se envías un número e non un carácter, para recibilo no canto de usar Serial.read() debes usar Serial.parseInt()
2. Servo e luz (pins0-1)
2. Movemento e luz (pins 0-1): Imos facer que un servo se mova lentamente de o a 180º e despois en sentido contrario de forma cíclica. Cada vez que xira nun sentido escintila un LED verde, e cando xira en sentido contrario escintila un LED vermello.
#include <Servo.h> // Declaración de variables: Servo meuservo; // poñémoslle nome ao servo: "meuservo" // Configuración: void setup(){ Serial.begin(9600); // Inicia a comunicación serie meuservo.attach(6); // servo conectado no pin 6 } // Programa: void loop() { meuservo.write(0); // Parte da posición de 0º Serial.print('A'); // Envía o dato A for(int i=0;i<=180;i++){ meuservo.write(i); delay (20); } Serial.print('B'); // Envía o dato B for(int i=180;i>=0;i--){ meuservo.write(i); delay (20); } }
Programa da placa 2:
// Declaración de variables: int ledverde=12; int ledvermello=13; int sinal; // Configuración: void setup(){ Serial.begin(9600); // Inicia a comunicación serie pinMode (ledverde, OUTPUT); pinMode (ledvermello, OUTPUT); } // Programa: void verde(){ digitalWrite(ledverde, HIGH); delay(100); digitalWrite(ledverde, LOW); delay(100); } void vermello(){ digitalWrite(ledvermello, HIGH); delay(100); digitalWrite(ledvermello, LOW); delay(100); } void loop(){ if(Serial.available()){ // Se hai un dato sinal = Serial.read(); // Lemos o dato Serial.print(sinal); if (sinal == 'A') { // Se o dato é 'A' while(!Serial.available()){ // executamos verde mentres non haxa un novo dato verde(); } } if (sinal == 'B'){ while(!Serial.available()){ vermello(); } } } }
3. Proba (pins 7-8)
3. Probamos (pins 7-8): Imos facer unha práctica sinxela para entender como hai que facer para enviar datos dunha placa a outra: Nun Arduíno conectamos un pulsador e noutro conectamos un LED. O LED debe cambiar de estado cada vez que prememos no pulsador.
#include <SoftwareSerial.h> SoftwareSerial placa1(7, 8); // RX, TX // Declaración de variables: int pulsador=2; // Configuración: void setup(){ placa1.begin(9600); // Inicia a comunicación serie } // Programa: void loop() { if (digitalRead(pulsador)==1){ while(digitalRead(pulsador)==1); // Agarda mentres o pulsador esta premido delay(20); // tempo para evitar o efecto rebote do pulsador placa1.print('A'); // Envía o dato A } }
Programa da placa 2
#include <SoftwareSerial.h> SoftwareSerial placa2(7, 8); // RX, TX // Declaración de variables: int led=13; int sinal; int estado=0; // variable na que almacenamos o estado do LED // Configuración: void setup(){ placa2.begin(9600); // Inicia a comunicación serie pinMode (led, OUTPUT); digitalWrite(led, LOW); } // Programa: void loop(){ if (placa2.available()) { // Se recibe un dato sinal = placa2.read(); // Lemos o dato if (sinal == 'A') { // Se o dato é A cambiamos o estado do led if (estado==0) { digitalWrite(led, HIGH); estado=1; } else{ digitalWrite(led, LOW); estado=0; } } } }
4. Servo e luz (pins 7-8)
4. Movemento e luz (pins 7-8): Imos facer que un servo se mova lentamente de o a 180º e despois en sentido contrario de forma cíclica. Cada vez que xira nun sentido escintila un LED verde, e cando xira en sentido contrario escintila un LED vermello.
#include <Servo.h> #include <SoftwareSerial.h> SoftwareSerial placa1(7, 8); // RX, TX // Declaración de variables: Servo meuservo; // poñémoslle nome ao servo: "meuservo" // Configuración: void setup(){ placa1.begin(9600); // Inicia a comunicación serie meuservo.attach(6); // servo conectado no pin 6 } // Programa: void loop() { meuservo.write(0); // Parte da posición de 0º placa1.print('A'); // Envía o dato A for(int i=0;i<=180;i++){ meuservo.write(i); delay (20); } placa1.print('B'); // Envía o dato B for(int i=180;i>=0;i--){ meuservo.write(i); delay (20); } }
Programa da placa 2
#include <SoftwareSerial.h> SoftwareSerial placa2(7, 8); // RX, TX // Declaración de variables: int ledverde=12; int ledvermello=13; int sinal; // Configuración: void setup(){ placa2.begin(9600); // Inicia a comunicación serie pinMode (ledverde, OUTPUT); pinMode (ledvermello, OUTPUT); } // Programa: void verde(){ digitalWrite(ledverde, HIGH); delay(100); digitalWrite(ledverde, LOW); delay(100); } void vermello(){ digitalWrite(ledvermello, HIGH); delay(100); digitalWrite(ledvermello, LOW); delay(100); } void loop(){ if(placa2.available()){ // Se hai un dato sinal = placa2.read(); // Lemos o dato placa2.print(sinal); if (sinal == 'A') { // Se o dato é 'A' while(!placa2.available()){ // executamos verde mentres non haxa un novo dato verde(); } } if (sinal == 'B'){ while(!placa2.available()){ vermello(); } } } }
Prácticas:
- Outras accións: Engade á práctica “Probamos” outro botón, de xeito que cando o premamos envíe outro dato diferente, e que a placa escrava execute outra acción diferente (que o LED escintile, que soe unha melodía, etc.)
- Datos de volta: Nas anteriores prácticas o mestre funcionou como transmisor (Tx) e o escravo coma receptor (Rx). Fai agora que a segunda placa devolva un dato á primeira despois de executar un proceso, e que ao recibilo realice algunha acción.