En este momento estás viendo Comunicando dos placas Arduino usando WiFi UDP

Comunicando dos placas Arduino usando WiFi UDP

En este post mostraremos como podemos comunicar dos placas Arduino usando UDP.

Para ello usaremos la placa MKR1000, que como vimos en el post Conociendo la placa Arduino MKR1000,  tiene capacidad de conexión a WiFi. Aunque también podríamos usar el shield WiFi101 que usa la misma librería, en conjunto con otra placa Arduino.

Usaremos la clase UDP de la librería wifi101, aunque la misma clase esta disponible también en la librería wifi y ethernet que podríamos usar dependiendo de nuestro hardware.

Para el ejemplo usaremos dos placas MKR1000, en la placa 1 tendremos conectado un potenciometro y en la otra un servomotor, enviaremos el valor del potenciometro via UDP de la placa 1 a la placa 2, y el servomotor se movera de acuerdo al valor recibido.

Ejemplo 1 – Programa de la placa 1 (potenciometro)

#include <SPI.h>
#include <WiFi101.h>
#include <WiFiUdp.h>

int status = WL_IDLE_STATUS;
char ssid[] = "MiFibra-2F43"; //  El nombre de tu red wifi
char pass[] = "qz4x3a7p";    // la clave de tu red wifi

unsigned int localPort = 2390; // numero del puerto de la placa para recibir mensajes

IPAddress ipremoto(192, 168, 1, 131);    //direccion IP de placa remota
unsigned int puertoRemoto = 1500; //numero de puerto de la placa remota

char  msg[20];  //Matriz de caracteres 

WiFiUDP Udp;  //nombre de la instancia

void setup() {
  //Inicia el puerto serial y espera hasta que se complete:
  Serial.begin(9600);
  while (!Serial) {
    ; // espera la conexion del puerto serie. Solo es necesario para placas con puerto USB nativo
      // Remover este while si la placa no estara conectada al ordenador
  }

  // revision de la presencia del shield de comunicación:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("El shield WiFi no esta presente");
    // no continua:
    while (true);
  }

  // intenta conectar a la red wifi:
  while ( status != WL_CONNECTED) {
    Serial.print("Conectando a SSID: ");
    Serial.println(ssid);
    // Conecta a una red WPA/WPA2:
    status = WiFi.begin(ssid, pass);
    // espera 10 segundos por la coneccion:
    delay(10000);
  }
  Serial.println("Conectado a wifi");
  printWiFiStatus();
  
  Udp.begin(localPort); // Inicia el socket WiFiUDP, y escucha el puerto local
}

void loop() {

    int valorPot = analogRead(A1); //leo el valor del potenciometro
    sprintf(msg, "ValPot:%i", valorPot); // Crea una cadena de texto con el valor del potenciometro
    Serial.println(msg); //Imprimo la cadena de texto al monitor serie
    
    Udp.beginPacket(ipremoto, puertoRemoto); //configura el envio del paquete de datos
    Udp.write(msg); //coloca en el buffer los datos de salida
    Udp.endPacket(); //envia el paquete de datos

   delay(500);
}

  void printWiFiStatus() {
  // imprime el nombre de la red a la cual estas conectado:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // imprime la direcion IP del shield o placa con la cual estas conectado:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // imprime la intensidad de señal recibida:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

La función sprintf es la que nos permite convertir un numero entero en una cadena de caracteres (matriz) para poder enviarla via udp.

Ejemplo 2 – Programa de la placa 2 (servomotor)

#include <SPI.h>
#include <WiFi101.h>
#include <WiFiUdp.h>
#include <stdio.h>
#include <Servo.h>

int status = WL_IDLE_STATUS;
char ssid[] = "MiRedWifi"; //  El nombre de tu red wifi
char pass[] = "MiClave";    // la clave de tu red wifi

char convBuffer[4];
int valServo =0;
char packetBuffer[20]; // buffer para guardar los datos entrantes
unsigned int localPort = 1500;  // numero del puerto de la placa para recibir mensajes
 
Servo myservo; //nombre de la instancia servo
WiFiUDP Udp; //nombre de la instancia UDP

void setup() {
   myservo.attach(5);  //el servo esta conectado en el pin 5
  //Inicia el puerto serial y espera hasta que se complete:
  Serial.begin(9600);
  while (!Serial) {
    ; // espera la conexión del puerto serie. Solo es necesario para placas con puerto USB nativo
  }

  // revision de la presencia del shield de comunicación:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("El shield WiFi no esta presente");
    // no continua:
    while (true);
  }

   // intenta conectar a la red wifi:
  while ( status != WL_CONNECTED) {
    Serial.print("Conectando a SSID: ");
    Serial.println(ssid);
     // Conecta a una red WPA/WPA2:
    status = WiFi.begin(ssid, pass);

    // espera 10 segundos por la coneccion:
    delay(10000);
  }
  Serial.println("Conectado a wifi");
  printWiFiStatus();
  
  Udp.begin(localPort); // Inicia el socket WiFiUDP, y escucha el puerto local
}

void loop() {

    // Si hay datos disponibles, lee el paquete
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    Serial.print("Tamaño del paquete recibido ");
    Serial.println(packetSize);
    Serial.print("De ");
    IPAddress remoteIp = Udp.remoteIP();
    Serial.print(remoteIp);
    Serial.print(", puerto ");
    Serial.println(Udp.remotePort());

    // lee el paquete y lo guarda en el buffer
    int len = Udp.read(packetBuffer, 20);  //lee el paquete y lo guarda en el buffer
    if (len > 0) packetBuffer[len] = 0;  // coloca el caracter null al final de la cadena
    Serial.println("Contents:");
    Serial.println(packetBuffer);
    
    convBuffer[0]=packetBuffer[7];
    convBuffer[1]=packetBuffer[8];
    convBuffer[2]=packetBuffer[9];
    convBuffer[3]=packetBuffer[10];
    convBuffer[4]=0;
    valServo=atoi(convBuffer); //convierte la cadena de caracteres a entero

    Serial.print("El valor extraido es:");
    Serial.println(valServo);

    myservo.write(valServo);    
  }
}

void printWiFiStatus() {
  // imprime el nombre de la red a la cual estas conectado:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // imprime la direcion IP del shield o placa con la cual estas conectado:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // imprime la intensidad de señal recibida:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

En este sketch la función atoi es la que nos permite convertir la cadena de caracteres a entero. ya que previamente conocemos su posición en el paquete de datos.

Como verificar que los datos se envían por UDP

Cuando solo tenemos una sola placa y necesitamos verificar si los datos se envían y como se reciben una buena alternativa es usar la aplicación packetsender la cual es muy fácil de configurar, es software libre y nos servirá para verificar nuestros sketch. solo debemos indicarle la dirección IP y el puerto.

Espero te sea de utilidad, si tienes alguna duda o quieres conocer un poco mas, nos encantaría recibir tus comentarios.

Esta entrada tiene un comentario

  1. laia

    Tengo dos dudas.

    La primera; en UDP no podemos enviar directament el valor numerico sin pasarlo a caracteres?

    La segunda; porque quieres una matriz de 20 i al volver a convertirlo a numero, cojes los caracteres de las posiciones de la 7 a la 10?

    Gracias

Deja una respuesta