Está en la página 1de 11

UNIVERSIDAD POLITÉCNICA SALESIANA

MAESTRÍA EN ELECTRÓNICA Y AUTOMATIZACIÓN

ASIGNATURA: COMUNICACIONES ELECTRÓNICAS

TEMA: DISEÑO E IMPLEMENTACIÓN DE UNA RED


DE SENSORES INALÁMBRICOS WSN

REALIZADO POR: ANDRADE PAÚL


CONTRERAS MARCO
ENCALADA FABIÁN
MARTÍNEZ PAÚL
RODRÍGUEZ DAVID

FECHA: 2019-06-21
CUENCA-ECUADOR
DISEÑO E IMPLEMENTACIÓN DE UNA RED DE SENSORES
INALÁMBRICOS WSN

1. OBJETIVOS

• Diseñar e implementar una red de sensores inalámbricos óptima


• Identificar los aspectos técnicos de las tecnologías para WSN que pueden ser implementadas
con IoT
• Diseñar la topología de una Red de sensores inalámbricos para ser implementada en un
ambiente que demande el uso de IoT
• Implementar una red WSN usando equipos de laboratorio usando XBEE
• Implementar un pequeño Sistema para recibir los datos por sockets

2. IMPLEMENTACIÓN

Luego de realizar la respectiva investigación acerca de la tarjeta STM32F4 Discovery, en conjunto


con sus módulos propietarios XBEE y ETHERNET; nos hemos encontrado con los siguientes
inconvenientes.

• No se encuentra información suficientemente comprensible acerca del funcionamiento de la


tarjeta STM32F4 Discovery en conjunto con sus módulos propietarios XBEE y ETHERNET
• La tensión de funcionamiento de las tarjetas antes mencionadas (3.3V) es una limitante en
cuanto a la variedad de sensores que se pueden seleccionar.
• Tanto los módulos XBee propietarios de mikroelectrónica (provistos por la Universidad) como
los de Digi trabajan en la banda abierta de 2.4Ghz.
Por tanto, se toma la decisión de implementar la red inalámbrica de sensores mediante tarjetas
Arduino en conjunto con módulos XBEE de Digi y ETHERNET genéricos, de los cuales se puede
encontrar una vasta cantidad de información y ejemplos de aplicación; cuya tensión de trabajo es
5V. Además de la ventaja que existen una gran variedad de sensores compatibles con dicho
hardware.
Además, se manejará los XBEE en su modo de comunicación API 2, el mismo que tiene las
siguientes ventajas sobre el modo transparente (AT) designado por defecto:

• Identificación del origen de cada paquete (nos permite tener mejor control sobre la red al
conocer el punto del que proviene determinada información).
• Información del estado de recepción de los paquetes (éxito/fracaso)
• Transmisión inalámbrica de datos a un único destino o varios destinos (sin necesidad de
reconfigurar los módulos y cambiar su dirección de destino).
• Configuración de dispositivos XBee locales o remotas (via inalámbrica).
• Información acerca de la potencia de la señal de cada paquete recibido.
• Información de desconexión de los nodos.

2.1. Topología de la Red de Sensores

La red de sensores implementada se compone de tres nodos, uno funcionando como


coordinador y dos nodos funcionando como routers, todos manejados por tarjetas Arduino tal
como se indica en la siguiente figura:

En este caso se seleccionó como elementos de medida un sensor de temperatura (LM35) y un


potenciómetro para los distintos nodos. De este modo, la composición del proyecto es la siguiente:
2.1.1. Nodo Maestro.
Compuesto por:
• 1 Arduino Uno
• 1 XBee Serie 2
• 1 módulo XBEE Explorer
• 1 módulo Ethernet
2.1.2. Nodo Router 1.
Compuesto por:
• 1 Arduino Uno
• 1 XBee Serie 2
• 1 módulo XBEE Explorer
• 1 Sensor de Temperatura LM35
2.1.3. Nodo Router 2.
Compuesto por:
• 1 Arduino Uno
• 1 XBee Serie 2
• 1 módulo XBEE Explorer
• 1 Potenciómetro de 100kΩ

2.2. Configuración de los Nodos


La configuración de nuestras tarjetas XBEE se realiza dentro del software XCTU propio de Digi
mediante una tarjeta XBEE Xxplorer, la cual sirve como interfaz USB-Serial para este propósito.
Debido a que la comunicación que realizan los módulos XBEE con nuestros microcontroladores es
por vía serial, como primer paso debemos configurar los parámetros de dicha comunicación en
nuestras tarjetas XBEE. Como parámetros generales de configuración se establecen los siguientes:

• Velocidad de comunicación serial: 9600 baudios por segundo.


• Número de bits de datos: 8 bits.
• Paridad: Ninguna
• Bits de parada: 1
• Control de flujo: Ninguno

2.2.1. Nodo Maestro.

Para que los nodos se puedan comunicar entre sí, se debe configurar inicialmente el maestro,
que tendrá la tarea principal de establecer la red; entre los parámetros más importantes se
configuran:
Function: Tarea del nodo en la red, en este caso Zigbee Coordinator API
PAN ID: nombre de la red, en este caso 1234 (todos los dispositivos que se vayan a conectar
a esta red deben tener el mismo nombre).
Node Identifier: identificador de nodo, en este caso 0
Destination Address High: Parte alta de la dirección de escritura : 0
Destination Address Low: Parte baja de la dirección de escritura : FFFF

2.2.2. Nodos Router 1 y 2

Function: Tarea del nodo en la red, en este caso Zigbee Router API
PAN ID: nombre de la red, en este caso 1234
Node Identifier: identificador de nodo, en este caso 1 y 2
Destination Address High: Parte alta de la dirección de escritura : 0
Destination Address Low: Parte baja de la dirección de escritura : FFFF

El truco de escribir la misma dirección en la Destination Address es el que permite la


comunicación en modo malla o Mesh.

2.3. Programación dentro de Arduino


A continuación se presentan los códigos implementados dentro del programa Arduino
2.3.1. Nodo Router 1 y Router 2
En este caso, al ser transductores que entregan como salida voltaje, el mismo que se lee en el
ADC, se implementa el mismo programa en ambos nodos y se realiza el procesamiento de los
datos en el nodo Maestro (linealización y escalamiento de valores).
//Añadimos Libreria XBee
#include <XBee.h>
#include <SoftwareSerial.h>

//Definimos DH_Coordinador
#define DH_COORDINADOR 0x0013A200
//Definimod DL_Coordinador
#define DL_COORDINADOR 0x40F2A594
//Definimmos pin para potenciometro
#define pin_pot A0
//Declaración de constantes generales
const unsigned int LED_SENALIZADOR = 13;
const unsigned int LED_ERROR = 12;
const unsigned int BAUD_RATE = 9600;
const float ALIMENTACION = 5.0;
//Declaracion de estructuras de datos
//Dato a enviar en 4 bytes
union u_tag1
{
byte v[4];
float fvolt;
} datos1;
//Declaracion de constantes para ejecucion de programa
int i = 0;
//Byte para detectar id de nodo actual
byte id = 0xFF;
//Estructura de payload (datos a enviar)
// Payload conformado por:
// Byte id nodo, Byte padre nodo, bytes voltaje potenciometro
// En total 6 bytes.
byte datos[] = { 0, 0, 0, 0, 0, 0};
//Inicialización parámetros XBee
XBee xbee = XBee(); //Creación objeto Xbee
XBeeAddress64 direccion64 = XBeeAddress64( DH_COORDINADOR, DL_COORDINADOR); // Dirección XBee
64bits
ZBTxRequest zbTx = ZBTxRequest(direccion64, datos, sizeof(datos)); //Requerimiento de transmisión
XBee
ZBTxStatusResponse txStatus = ZBTxStatusResponse(); //Dato de estado de solicitud de transmisión
XBee
//Puerto serie para XBee si no tenemos serial fisico libre usamos uno virtual
SoftwareSerial XBeeSerial(2, 3); // RX, TX
//RX ARDUINO --- DOUT XBEE (PIN 2)
//TX ARDUINO --- DIN XBEE (PIN 3)
void setup()
{
pinMode(LED_SENALIZADOR, OUTPUT);
pinMode(LED_ERROR, OUTPUT);
Serial.begin(9600);
//Serial 1 para XBee
Serial1.begin(BAUD_RATE);
//XBeeSerial.begin(BAUD_RATE);
//Establecemos XBee
xbee.setSerial(Serial1);
//xbee.setSerial(XBeeSerial);
//Obtenemos ID del Nodo
obtener_ID();
}

void loop()
{ //Obtenemos voltaje del adcy lo adjuntamos a la estructura
datos1.fvolt = get_volt();
//Comenzamos a rellenar la trama de datos
datos[0] = id;
//Asignamos valor de nodo padre (en este caso nodo principal)
datos[1] = 0;
//Asignamos valor de voltaje en potenciometro a trama de datos
for (i = 0; i < 4; i++)
{ datos[i + 2] = datos1.v[i]; }
//Enviamos trama de datos
xbee.send(zbTx);
//Encendemos led de envio de datos
parpadeo_led(LED_SENALIZADOR, 1, 100);
// Luego de enviar solicitud Tx, esperamos una respuesta de estado de transmisión
// esperamos hasta medio segundo por la respuesta de estado
if (xbee.readPacket(500))
{ // Se obtuvo una respuesta!
Serial.println("Enviado");
// Debe haber un valor de znet tx status
if (xbee.getResponse().getApiId() == ZB_TX_STATUS_RESPONSE)
{
xbee.getResponse().getZBTxStatusResponse(txStatus);
// Buscamos el estado de la entrega, el quinto byte
if (txStatus.getDeliveryStatus() == SUCCESS)
{ // Envio correcto.
parpadeo_led(LED_SENALIZADOR, 5, 50);
Serial.println("Recibido");
} else
{ // La XBee de destino no recibió el dato. ¿Se encuentra encendida?
parpadeo_led(LED_ERROR, 3, 500);
}
}
}
else
{Serial.println("No se envio correctamente");
}
delay(1000);
}
//Función que lee el sensor
const float get_volt()
{
int vpot = analogRead(pin_pot);
float vpot_temp =(5.0 * vpot)/1024.0;
return (vpot);
}
//Función que controla el parpadeo de led
void parpadeo_led(int pin, int times, int wait)
{
for (int i = 0; i < times; i++)
{digitalWrite(pin, HIGH);
delay(wait); digitalWrite(pin, LOW);
if (i + 1 < times) {delay(wait);}
}
}
//Función para obtener id de nodo
void obtener_ID()
{
byte comando_NI[] = {'N', 'I'};
AtCommandRequest atRequest = AtCommandRequest(comando_NI);
AtCommandResponse atResponse = AtCommandResponse();
//Se obtiene el ID del nodo mediante el comando AT NI
xbee.send(atRequest);
//Esperamos hasta 5 segundos para la respuesta del estado
if (xbee.readPacket(5000))
{ //Hay una respuesta
//Deberia ser una respuesta al comando AT
if (xbee.getResponse().getApiId() == AT_COMMAND_RESPONSE)
{
xbee.getResponse().getAtCommandResponse(atResponse);
//Si el valor de la respuesta at es Ok
if (atResponse.isOk())
{
if (atResponse.getValueLength() > 0)
{ //Calculamos el valor de id del nodo
id = atResponse.getValue()[0] - '0';
}
}
}
}
}

2.3.2. Nodo Maestro


//Añadimos Libreria XBee
#include <XBee.h>
#include <SoftwareSerial.h>
#include <SPI.h> //Importamos librería comunicación SPI
#include <Ethernet.h> //Importamos librería Ethernet
//Definiciones RED
#define NUM_NODOS 3
#define NUM_ROUTERS 2
//Declaración de constantes generales
const unsigned int LED_SENALIZADOR = 13;
const unsigned int LED_ERROR = 12;
const unsigned int BAUD_RATE = 9600;
const float ALIMENTACION = 5.0;
//Creamos definiciones para XBee
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };//Ponemos la dirección MAC de la Ethernet
Shield que está con una etiqueta debajo la placa
SoftwareSerial XBeeSerial(2, 3); // RX, TX
//Creamos definiciones para Ethernet
IPAddress ip(192,168,1,100); //Asingamos la IP al Arduino
EthernetServer server(80); //Creamos un servidor Web con el puerto 80 que es el puerto HTTP por
defecto
XBee xbee = XBee(); //Creación objeto Xbee
XBeeResponse response = XBeeResponse(); //Respuesta de XBee
ZBRxResponse rx = ZBRxResponse(); //Respuesta de XBee en ZNet
ModemStatusResponse msr = ModemStatusResponse(); //Estado de Respuesta de Módem
//Constantes pricipales
int i = 0;
byte origen = 0 ;
byte padre = 0 ;
//Estructura de payload (datos a enviar)
// Payload conformado por:
// Byte id nodo, Byte padre nodo, Bytes temperatura, Bytes humedad.
// En total 10 bytes.
byte buffer[] = { 0, 0, 0, 0, 0, 0 };
//Creación de estructura de datos
union u_tag1
{
byte v[4];
float fvolt;
}
datos1;
typedef struct
{
byte padre;
byte timeout;
float grupo1;
} Nodo;
int data1=0;
int data2=0;
Nodo nodo[NUM_NODOS];
void setup()
{
pinMode(LED_SENALIZADOR, OUTPUT);
pinMode(LED_ERROR, OUTPUT);
//Serial1.begin(9600);
XBeeSerial.begin(BAUD_RATE);
xbee.setSerial(XBeeSerial);
parpadeo_led(LED_SENALIZADOR, 3, 50);
Serial.begin(9600);
// Inicializamos la comunicación Ethernet y el servidor
Ethernet.begin(mac, ip);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
pinMode(led,OUTPUT);pinMode(led1,OUTPUT);
}
void loop()
{
//Esperamos hasta 100 milisegundos para determinar si se ha recibido
//un mensaje en el XBee Coordinador
xbee.readPacket(100);
if (xbee.getResponse().isAvailable())
{
//Se obtuvo una respuesta
//Serial.println("Recibido");
//Debe haber un valor de znet en rx status
if (xbee.getResponse().getApiId() == ZB_RX_RESPONSE)
{
xbee.getResponse().getZBRxResponse(rx);
if (rx.getOption() == ZB_PACKET_ACKNOWLEDGED)
{//El nodo que envía datos recibió un ACK (fue reconocido)
parpadeo_led(LED_SENALIZADOR, 10, 10);
}
else
{ //El nodo que envía datos no recibió un ACK (no fue reconocido)
parpadeo_led(LED_ERROR, 2, 20);
}
//Llenamos array buffer con datos provenientes en puerto serial XBee
for (i = 0; i <6; i++)
{
buffer[i] = rx.getData(i);
}
//Determinamos ID Nodo Origen de Informacion
origen = buffer[0];
if (origen >= 'A') origen = origen - 'A' + NUM_ROUTERS + 1;
//Asignamos timeout a nodo actual
nodo[origen].timeout = NUM_NODOS;
//Asignamos valor de nodo padre a nodo actual
nodo[origen].padre = buffer[1];
//Llenamos estrcutura de datos con demás datos provenientes de Router
for ( i = 0; i < 4; i++)
{
datos1.v[i] = buffer[i + 2];
}
nodo[origen].grupo1 = datos1.fvolt;
}
//Si se encuentra otro tipo de mensaje
//(Control, Error, Desconocido, etc)
//El LED_ERROR parpadea para indicarlo
else if (xbee.getResponse().getApiId() == MODEM_STATUS_RESPONSE)
{
xbee.getResponse().getModemStatusResponse(msr); if (msr.getStatus() == ASSOCIATED) {
parpadeo_led(LED_ERROR, 10, 10);
}
else if (msr.getStatus() == DISASSOCIATED)
{
parpadeo_led(LED_ERROR, 10, 10);
}
else
{
parpadeo_led(LED_ERROR, 5, 10);
}
}
else
{
parpadeo_led(LED_ERROR, 1, 25);
}
}
data1= nodo[1].grupo1;
data2= nodo[178].grupo1;
//Actualizamos timeout en los nodos
actualizar_nodos();
//Seccion Ethernet
EthernetClient client = server.available(); //Creamos un cliente Web
//Cuando detecte un cliente a través de una petición HTTP
if (client) {
boolean currentLineIsBlank = true; //Una petición HTTP acaba con una línea en blanco
String cadena=""; //Creamos una cadena de caracteres vacía
while (client.connected()) {
if (client.available()) {
char c = client.read();//Leemos la petición HTTP carácter por carácter
//Cuando reciba una línea en blanco, quiere decir que la petición HTTP ha acabado y el
servidor Web está listo para enviar una respuesta
if (c == '\n' && currentLineIsBlank) {
// Enviamos al cliente una respuesta HTTP
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
//Página web en formato HTML
client.println("<html>");
client.println("<head>");
client.println("</head>");
client.println("<body>");
client.println("<h1 align='center'>PROYECTO FINAL COMUNICACIONES ELECTRONICAS</h1><h3
align='center'>LECTURA DE SENSORES</h3>");
//Linealizacion, escalamiento y presentacion de valores
client.println("<div style='text-align:center;'>");
client.println("</button>");
client.println("<br /><br />");
client.println("<b>DATOS DEL SENSOR 1 = ");
client.print(int(data1));
client.println("<br /><br />");
client.println("<b>DATOS DEL SENSOR 2 = ");
client.print(float((data2*5.0/1024)));
client.println("</b><br />");
client.println("</b></body>");
client.println("</html>");
break;
}
if (c == '\n') {
currentLineIsBlank = true;
}
else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
//Dar tiempo al navegador para recibir los datos
delay(1);
client.stop();// Cierra la conexión
}
}
//Función para decrementar el tiempo de espera en los nodos
void actualizar_nodos()
{
for (i = 0; i < NUM_NODOS; i++)
{
if (nodo[i].timeout > 0)
{
nodo[i].timeout -= 1;
}
}
}

//Función que controla el parpadeo de led


void parpadeo_led(int pin, int times, int wait)
{
for (int i = 0; i < times; i++)
{
digitalWrite(pin, HIGH);
delay(wait); digitalWrite(pin, LOW);
if (i + 1 < times) {
delay(wait);
}
}
}

3. CONCLUSIONES

• Con el desarrollo de esta práctica se han logrado evidenciar el amplio campo de


investigación y desarrollo relacionado a las redes inalámbricas de sensores, asi como
una pequeña parte de las tecnologías que confluyen para su implementación.
• Al realizar nuestro proyecto, podemos concluir que la combinación entre tecnología
Xbee de Digi y los módulos open source de Arduino se pueden implementar redes
inalámbricas de sensores con propósitos de IOT.
• La amplia cantidad de información disponible en la nube acerca de las tarjetas Arduino
en conjunto con su política open source brinda la capacidad de desarrollo de proyectos a
nivel académico con prestaciones muy similares a aquellas alcanzadas con módulos y
tarjetas propietarios de empresas dedicadas al mismo propósito. En este caso
mikroelectronika.
• En el desarrollo del presente proyecto, la implementación de los sockets de comunicación
no fue posible debido a la capacidad del hardware encargado de controlar el módulo de
ethernet, ya que; en conjunto con el manejo del nodo coordinador se producían conflictos
y retrasos en el funcionamiento de la red implementada. Razón por la cual se decidió
implementar un servidor local alojado en la tarjeta de Ethernet de Arduino.

4. RECOMENDACIONES

• Se debe tener mucho cuidado en la manipulación de todas las tarjetas y módulos, con
especial atención en las XBee, ya que debido a su tensión de funcionamiento (3.3V) son
más delicadas en casos de polarización inversa y/o polarización en pines de propósito
general (GPIO).
• Debido a que el funcionamiento de las tarjetas XBee se realiza en la banda libre de
2.4Ghz debemos tomar en cuenta que las redes de tipo WiFi podrían generar algún
conflicto en la comunicación, e incluso si su potencia llega a ser demasiado grande podría
estropearla por completo.
• Para lograr una mejor integración con los aspectos de IOT se puede recurrir a la
implementación de un servidor local en un microcomputador con sistema operativo Linuz
tal como Raspberry Pi usando la aplicación XAMPP, o si lo deseamos en una portátil con
Windows usando WAMPSERVER (alternativa de XAMPP para Windows).
• El desarrollo de aplicaciones de este tipo orientadas a IOT está en auge en este momento,
sin embargo aún no se ha estandarizado sistemas de gestión ya que aún existe un
sinnúmero de proveedores de tecnología tanto para los sensores como para los
dispositivos de comunicación.

ANEXOS

Captura de Pantalla de Sistema Implementado

También podría gustarte