Etiquetas: , , ,

La forma más fácil de comunicarse con Arduino es usar el puerto serie. También es la herramienta más poderosa para probar y depurar su código.

Material

  • Ordenador
  • Arduino UNO x2
  • Jumper cable M/M x3

Comunicación con el monitor serie

Las funciones de la biblioteca en serie para saber:

  • Serial.begin() para inicializar la velocidad de comunicación. La comunicación no funcionará si esto no es correcto
  • Serial.print() and Serial.println() para enviar cadenas. El último con un final de línea ‘\ n’
  • Serial.write() para enviar un byte a la vez
  • Serial.available() para verificar si hay datos en el búfer
  • Serial.read() para recibir los datos del puerto

Cargue el siguiente código para probar la comunicación entre la computadora y el Arduino.

char cmd="";
char old_cmd;
boolean enable=false;


void setup(){
  // Initialize serial port
  Serial.begin(9600);
  Serial.println("ENTER Commands:");        
}

void loop(){
  old_cmd=cmd;
  if (Serial.available()){ // Verify that data are available
    cmd=Serial.read();  // Read data on serial port
  } 
  
  if(cmd!=old_cmd){
    if(cmd=='O'){
      Serial.println("Set to ON"); // Send data to serial port
      enable=true;
    }else if(cmd=='F'){
      Serial.println("Set to OFF"); // Send data to serial port
      enable=false;
    }
  }

   if(enable){
      Serial.println("System is running");
      delay(200);
    }
}

Si escribe O, en la barra de comandos del monitor, debería ver la siguiente pantalla:

arduino-serial-com Comunicarse con Arduino

Comunicación entre dos Arduinos

Es posible utilizar el puerto serie (Rx0,Tx1) utilizado por el puerto USB para comunicarse entre dos placas Arduino. Para ello, basta con conectar las clavijas de la siguiente manera

  • Arduino 1 Rx -> Arduino 2 Tx
  • Arduino 1 Tx -> Arduino 2 Rx
  • Arduino 1 GND -> Arduino 2 GND
connection-2xarduino-serial_bb Comunicarse con Arduino

PRECAUCIÓN: Si se utilizan placas diferentes, los niveles de tensión pueden no ser compatibles. En este caso, debes utilizar un convertidor de tensión. Consulta la documentación de cada placa.

Como hemos dicho, los pines 0 y 1 son utilizados por el puerto USB. Para evitar conflictos con el monitor de serie, veremos la biblioteca SoftwareSerial que utiliza otros pines del microcontrolador. Los siguientes ejemplos también son posibles con el puerto serie de hardware. Sólo tienes que sustituir «ArduinoSlave» y «ArduinoMaster» por «Serial» en los siguientes códigos.

En general, las técnicas de intercambio de datos que se comentan a continuación son aplicables a todas las comunicaciones en serie.

Comunicación entre dos Arduinos con SoftwareSerial

Es posible comunicarse entre diferentes dispositivos utilizando un puerto serie como dos Arduinos. Uno será programado como «Maestro» (dar órdenes) y el otro como «Esclavo» (recibir orden y reaccionar).

Un puerto serie está definido por dos cables y una velocidad de comunicación. La biblioteca SoftwareSerial.h se utiliza para definir puertos serie. En este ejemplo, elegimos los pines 2 y 3 como pin de recepción (RX) y transmisión (TX) respectivamente (SoftwareSerial ArduinoSlave (2,3);). La velocidad de comunicación es de 9600bps (ArduinoSlave.begin (9600);

ATENCIÓN : Aquí utilizamos los pines 2 y 3 del Arduino UNO. Dependiendo del microcontrolador utilizado, los pines utilizados para la comunicación en serie pueden ser diferentes. Especialmente para las placas Arduino Mega, Micro, Leonardo. Comprueba la documentación.

Para establecer una comunicación correcta, los paneles deben identificarse adecuadamente y mostrarse en los siguientes esquemas.

connection-2xarduino_bb-640x311 Comunicarse con Arduino

En nuestro ejemplo, la placa maestra envía datos y la placa esclava los recibe y los devuelve.

Código «maestro»

#include <SoftwareSerial.h>

SoftwareSerial ArduinoSlave(2,3);
char cmd="";
char old_cmd;
char answer="";
char old_answer;

void setup(){
  Serial.begin(9600);
  Serial.println("ENTER Commands:");
  ArduinoSlave.begin(9600);            
}

void loop(){
  old_cmd=cmd;
  old_answer=answer;
  //Read command from monitor
  if (Serial.available()){
    cmd=Serial.read();
  } 
  //Read answer from slave
  if (ArduinoSlave.available()){
    answer=ArduinoSlave.read();
  } 
  //Send data to slave
  if(cmd!=old_cmd){
    Serial.print("Master sent : ");
    Serial.println(cmd);
    ArduinoSlave.write(cmd);
  }
  //Send answer to monitor
  if(answer!=old_answer){
    Serial.print("Slave received : ");
    Serial.println(answer);
  }
}

Código «esclavo»

#include <SoftwareSerial.h>

SoftwareSerial ArduinoMaster(2,3);
char cmd="";
char old_cmd;

void setup(){
  ArduinoMaster.begin(9600);    
}

void loop(){
  old_cmd=cmd;
  // Read data from master
  if (ArduinoMaster.available()){
    cmd=ArduinoMaster.read();
  } 
  // Send answer to master
  if(cmd!=old_cmd){
    ArduinoMaster.write(cmd);
  }
}

En el monitor en serie de la placa maestra, debería ver la respuesta de la placa esclava.

arduinox2-serial-byte Comunicarse con Arduino

Con este código puede enviar y recibir un byte a la vez. Los caracteres se codifican siguiendo la tabla ASCII. Consulte la tabla ASCII para ver cómo están codificados. Algunos caracteres no se pueden enviar, como «°» o acentos «é».

Juega con datos

ara algunos proyectos, necesitará obtener más información sobre los diferentes tipos de valor. Una solución rápida es convertir el valor en una cadena y enviarlo con la función print ().

Código maestro

#include <SoftwareSerial.h>

SoftwareSerial ArduinoSlave(2,3);
String msg;

void setup(){

  Serial.begin(9600);
  Serial.println("ENTER Commands:");
  ArduinoSlave.begin(9600);
                
}

void loop(){
  //Read command from monitor
  readSerialPort();
  
  //Send data to slave
  if(msg!=""){
    Serial.print("Master sent : ");
    Serial.println(msg);
    ArduinoSlave.print(msg);
    msg="";
  }

}

void readSerialPort(){
 while (Serial.available()) {
   delay(10);  
   if (Serial.available() >0) {
     char c = Serial.read();  //gets one byte from serial buffer
     msg += c; //add to String
   }
 }
 Serial.flush(); //clean buffer
}

Código esclavo

#include <SoftwareSerial.h>

SoftwareSerial ArduinoMaster(2,3);
String msg;

void setup(){
  Serial.begin(9600);
  ArduinoMaster.begin(9600);    
}

void loop(){
  readMasterPort();
  
  // Send answer to master
  if(msg!=""){
    ArduinoMaster.print(msg);
    Serial.print("Master sent : " );
    Serial.println(msg);
    msg=""; 
  }
}

void readMasterPort(){
 while (ArduinoMaster.available()) {
   delay(10); 
   if (ArduinoMaster.available() >0) {
     char c = ArduinoMaster.read();  //gets one byte from serial buffer
     msg += c; //makes the string readString
     Serial.println(msg);
   }
 }
 ArduinoMaster.flush();
}

Con este código puede enviar cualquier tipo de datos.

arduinox2-serial-com Comunicarse con Arduino

Una vez que la comunicación está configurada correctamente y las placas pueden intercambiar datos, puede pensar en cómo usarlo.

Enviar y recibir valor del sensor

Un buen ejemplo de una aplicación es cambiar el brillo de un LED conectado a la placa Slave usando un sensor conectado a la placa Master. A medida que obtenemos los datos en forma de una cadena, tenemos que convertirlos en un entero. La función para realizar la conversión es atoi (). El valor PWM del LED está entre 0 y 255, el valor del sensor entre 0 y 1023 debe convertirse a la función map ().

Código maestro para leer y enviar el valor del sensor

#include <SoftwareSerial.h>

SoftwareSerial ArduinoSlave(2,3);
String answer;
String msg;
int intVal=0,oldIntVal=0;

void setup(){

  Serial.begin(9600);
  Serial.println("ENTER Commands:");
  ArduinoSlave.begin(9600);
                
}

void loop(){
  //Read sensor
  intVal=analogRead(A0);
  //Read answer from slave
  readSlavePort();
  
  //Send data to slave
  if(oldIntVal!=intVal){
    Serial.print("Master sent : ");
    Serial.println(intVal);
    ArduinoSlave.print(intVal);
    oldIntVal=intVal; 
  }
  //Send answer to monitor
  if(answer!=""){
    Serial.print("Slave LED PWM value : ");
    Serial.println(answer);
    answer="";
  }
  delay(1000);
}

void readSlavePort(){
  while (ArduinoSlave.available()) {
   delay(10);  
   if (ArduinoSlave.available() >0) {
     char c = ArduinoSlave.read();  //gets one byte from serial buffer
     answer += c; //makes the string readString
   }
 }
}

Código esclavo para recibir y usar el valor del sensor

#include <SoftwareSerial.h>

SoftwareSerial ArduinoMaster(2,3);

#define ledPin 11

String msg="";
int ledVal=0;
int intVal=0,oldIntVal=0;

void setup(){
  Serial.begin(9600);
  ArduinoMaster.begin(9600);
  pinMode(ledPin,OUTPUT);    
}

void loop(){
  readMasterPort();
  convertMsgToCmd();
  // Send answer to master
  if(intVal!=oldIntVal){
    Serial.print("Master sent : " );
    Serial.println(intVal);

    ledVal=map(intVal,0,1023,0,255);
    Serial.print("led value : ");
    Serial.println(ledVal);
    ArduinoMaster.print(ledVal);
    analogWrite(ledPin,ledVal);
    oldIntVal=intVal; 
  }
}

void readMasterPort(){
 while (ArduinoMaster.available()) {
   delay(10); 
   if (ArduinoMaster.available() >0) {
     char c = ArduinoMaster.read();  //gets one byte from serial buffer
     
     msg += c; //makes the string readString
   }
 }
 ArduinoMaster.flush();
}

void convertMsgToCmd(){
   if (msg.length() >0) {
    Serial.print("message length : ");
    Serial.println(msg.length());
    
     char carray1[6]; //magic needed to convert string to a number
     msg.toCharArray(carray1, sizeof(carray1));
     intVal = atoi(carray1);
     
     msg="";
 }
}

arduinox2-serial-int Comunicarse con Arduino

Enviar y recibir dos valores de sensor

Para recibir diferentes valores, la idea es definir un separador. En este caso, usamos el carácter «x». Luego, simplemente ubique el carácter en la cadena usando la función indexOf ().

Código maestro para leer y enviar dos valores de sensor

#include <SoftwareSerial.h>

SoftwareSerial ArduinoSlave(2,3);
String answer;
String msg;
int intVal1=0,oldIntVal1=0;
int intVal2=0,oldIntVal2=0;


void setup(){
  Serial.begin(9600);
  Serial.println("ENTER Commands:");
  ArduinoSlave.begin(9600);
                
}

void loop(){
  //Read sensors
  intVal1=analogRead(A0);
  intVal2=analogRead(A1);
  
  //Send data to slave
  if(oldIntVal1!=intVal1 || oldIntVal2!=intVal2 ){
    Serial.print("Master sent : ");
    Serial.print(intVal1);
    Serial.print("x");
    Serial.println(intVal2);
    
    ArduinoSlave.print(intVal1);
    ArduinoSlave.print("x");
    ArduinoSlave.print(intVal2);
    oldIntVal1=intVal1;
    oldIntVal2=intVal2;
  }
  delay(1000);
  //Read answer from slave
  readSlavePort();
  
  //Send answer to monitor
  if(answer!=""){
    Serial.println("Slave received : ");
    Serial.println(answer);
    answer="";
  }
  
}

void readSerialPort(){
 while (Serial.available()) {
   delay(10);  
   if (Serial.available() >0) {
     char c = Serial.read();  //gets one byte from serial buffer
     msg += c; //makes the string readString
   }
 }
 Serial.flush();
}

void readSlavePort(){
  while (ArduinoSlave.available()) {
   delay(10);  
   if (ArduinoSlave.available() >0) {
     char c = ArduinoSlave.read();  //gets one byte from serial buffer
     answer += c; //makes the string readString
   }
 }
}

Código esclavo para recibir dos valores de sensor

#include <SoftwareSerial.h>

SoftwareSerial ArduinoMaster(2,3);

String msg="",m1="",m2="";
int num1=-1,num2=-1;
int sep;

void setup(){
  Serial.begin(9600);
  ArduinoMaster.begin(9600);
}

void loop(){
  readMasterPort();
  convertMsgToMultiCmd();
  // Send answer to master
  if(num1!=-1 && num2!=-1){
    Serial.print("Sensor 1 : " );
    Serial.println(num1);

    Serial.print("Sensor 2 : " );
    Serial.println(num2);

    ArduinoMaster.print("Sensor 1 : " );
    ArduinoMaster.println(num1);

    ArduinoMaster.print("Sensor 2 : " );
    ArduinoMaster.println(num2);
    num1=-1;
    num2=-1;
  }
}

void readMasterPort(){
 while (ArduinoMaster.available()) {
   delay(10); 
   if (ArduinoMaster.available() >0) {
     char c = ArduinoMaster.read();  //gets one byte from serial buffer
     
     msg += c; //makes the string readString
   }
 }
 ArduinoMaster.flush();
}


void convertMsgToMultiCmd(){
   if (msg.length() >0) {
    Serial.print("message length : ");
    Serial.println(msg.length());
     sep = msg.indexOf('x');
     //Serial.println(sep);    
     m1 = msg.substring(0, sep); //get servo id
     m2 = msg.substring(sep+1, msg.length()); //get servo pos 
    
     char carray1[6]; //magic needed to convert string to a number
     m1.toCharArray(carray1, sizeof(carray1));
     num1 = atoi(carray1);
     
     char carray2[6];
     m2.toCharArray(carray2, sizeof(carray2));
     num2 = atoi(carray2);
      
     msg="";
 }
}

arduinox2-serial-intx2 Comunicarse con Arduino

Enviar y recibir múltiples datos

Es posible que en su aplicación necesite intercambiar una gran cantidad de datos entre dos tarjetas. En este caso, debe cambiar ligeramente la función de conversión. En nuestro ejemplo, suponemos que queremos controlar el estado de un led, la velocidad y la dirección de un motor.

Código maestro para enviar múltiples datos

#include <SoftwareSerial.h>

SoftwareSerial ArduinoSlave(2,3);
String answer;
String msg;
int intVal1=0,oldIntVal1=0;
int intVal2=0,oldIntVal2=0;


void setup(){

  Serial.begin(9600);
  Serial.println("ENTER Commands:");
  ArduinoSlave.begin(9600);
                
}

void loop(){
  //Read command from monitor
  readSerialPort();
 
  //Read answer from slave
  readSlavePort();
  
  //Send data to slave
  if(msg!=""){
    Serial.print("Master sent : ");
    Serial.println(msg);
    ArduinoSlave.print(msg);
    msg="";
  }
  
  //Send answer to monitor
  if(answer!=""){
    Serial.print("Slave received : ");
    Serial.println(answer);
    answer="";
  }
  delay(1000);
}

void readSerialPort(){
 while (Serial.available()) {
   delay(10);  
   if (Serial.available() >0) {
     char c = Serial.read();  //gets one byte from serial buffer
     msg += c; //makes the string readString
   }
 }
 Serial.flush();
}

void readSlavePort(){
  while (ArduinoSlave.available()) {
   delay(10);  
   if (ArduinoSlave.available() >0) {
     char c = ArduinoSlave.read();  //gets one byte from serial buffer
     answer += c; //makes the string readString
   }
 }
}

Código esclavo para recibir y usar múltiples datos

#include <SoftwareSerial.h>

SoftwareSerial ArduinoMaster(2,3);

String msg="";
int ledVal=0;
int sep;
String data[3];
unsigned int data_count=0;

void setup(){
  Serial.begin(9600);
  ArduinoMaster.begin(9600);
}

void loop(){
  readMasterPort();
  convertMsgToMultiCmd();

  //Use data
  if(data_count==3){
    for(int i=0;i<(data_count+1);i++){
      switch(i){
        case 0: //led status
          if(data[0]=="ON"){
            Serial.println("Switch led ON");
          }else if(data[0]=="OFF"){
            Serial.println("Switch led OFF");
          }else{
            Serial.println("Led wrong command");
          }
        break;
        case 1: //motor PWM
           Serial.print("Set motor power to : ");
           Serial.println(stringToInt(data[1]));
        break;
        case 2: //motor direction
           if(data[2]=="forward"){
            Serial.println("Motor direction forward");
          }else if(data[2]=="backward"){
            Serial.println("Motor direction backward");
          }else{
            Serial.println("Motor wrong command");
          }
        break;
        
      }
    }
    data_count=0;
  }
  
}

void readMasterPort(){
 while (ArduinoMaster.available()) {
   delay(10); 
   if (ArduinoMaster.available() >0) {
     char c = ArduinoMaster.read();  //gets one byte from serial buffer
     
     msg += c; //makes the string readString
   }
 }
 ArduinoMaster.flush();
}


void convertMsgToMultiCmd(){
  
   if (msg.length() >0) {
    data_count=0;
    Serial.print("Master sent : ");
    Serial.println(msg);//Serial.println(msg.length());
    do{
      sep = msg.indexOf('x');
       // expect a string like 0x0021 containing the two servo positions      
       String m1 = msg.substring(0, sep); //get servo id
       msg = msg.substring(sep+1, msg.length()); //get servo pos 
      data[data_count]=m1;
      data_count++;
    } while(sep!=-1);
    
    Serial.println("data received : "); 
    for(int i=0;i<(data_count+1);i++) Serial.println(data[i]); 
     msg="";
 }
}

int stringToInt(String s){
     char carray1[6]; //magic needed to convert string to a number
     s.toCharArray(carray1, sizeof(carray1));
     return atoi(carray1);
}

arduinox2-serial-multidata Comunicarse con Arduino

Una vez que pueda recibir y separar los datos, puede usarlos como desee. Convierta a valor de sensor entero o use una cadena específica para activar acciones.

Con este conocimiento básico, debería poder comunicarse entre sí como un serial servo controller, Bluetooth module u otro microcontrolador como Raspberry Pi .

Si tiene dificultades para establecer una comunicación entre dos dispositivos o si desea decir algo más, deje un comentario o envíenos un mensaje.

Aplicaciones

Fuentes

Encuentre otros tutoriales y ejemplos en el generador de código automático
Arquitecto de Código