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.

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

Comunicación entre dos Arduinos.

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);

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

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.

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(b);
}
}
ArduinoMaster.flush();
}

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

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="";
}
}

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="";
}
}

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);
}

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

Comuníquese con los módulos Arduino y bluetooth HC-06 y HC-05.

Fuentes

https://www.arduino.cc/reference/en/language/functions/communication/serial/