Você está na página 1de 48

ÍNDICE

GLOSARIO

MARCO TEÓRICO

1.- DATALOGGER

Un Datalogger es un registrador de datos que opera en forma independiente y puede leer varios
tipos de señales eléctricas o magnitudes físicas y almacenar los datos en la memoria interna para su
posterior descarga a una computadora.

La ventaja de los registradores de datos es que pueden operar independientemente de una


computadora, a diferencia de muchos otros tipos de dispositivos de adquisición de datos. Los
registradores de datos están disponibles en varias formas y tamaños. La gama incluye registradores
de función fijos económicos simples de un solo canal a dispositivos programables más potentes
capaces de manejar cientos de entradas.

El datalogger, conocido también como sistema de adquisición de datos y control, o micrologger, es


el corazón de una estación de medida. Mide las señales eléctricas de sensores a una velocidad de
muestreo determinada, procesa y almacena los datos, y dispone de comunicación capaz de hacer la
transferencia de los datos hacia una PC
Parámetros de un DataLogger

Señal de entrada

Algunos dataloggers están dedicados a un cierto tipo de entrada mientras otros son programables
para diferentes tipos de entradas. Las magnitudes físicas mas sensadas son temperatura, humedad,
sonido, iluminación, nivel, frecuencia, velocidad del viento, dirección del viento, voltaje o corriente
de paneles solares, etc

Número de entradas

Los dataloggers están disponibles en diseños de un solo canal y multicanal. Algunos dataloggers son
capaces de manejar hasta 32 canales.

Tamaño

En muchas aplicaciones el espacio es una limitante. En esos casos el tamaño del datalogger puede
ser un parámetro de selección crucial. Se espera que un datalogger tenga un montaje
extremadamente compacto.

Velocidad/memoria

En comparación con los sistemas de adquisición de datos en tiempo real, los dataloggers en general
tienen bajas velocidades de muestreo. Esto se debe normalmente a que almacenan datos en
memoria interna, que es limitada. Los datos normalmente se recopilan en memoria no volátil para
descargar posteriormente a un computador. Cuanto más altas son las velocidades de datos más
memoria se requiere. Por lo tanto, al especificar un datalogger es importante determinar la tasa de
muestreo y la duración de la muestra que se puede usar para calcular la memoria requerida. Por
ejemplo, si una aplicación requiere tasas de muestreo de 1 por segundo y la prueba debe durar una
hora, el datalogger debe poder almacenar 3600 muestras (1 muestra/segundo x 1 hora x 3600
segundos/hora).

Operación en tiempo real

En algunas aplicaciones puede ser deseable mostrar los datos que se están recopilando en tiempo
real en un ordenador.

Tasa de muestreo

La tasa de muestreo depende del modelo específico. Algunos data loggers ofrecen tasas de hasta
una muestra cada 24 horas en sus valores máximos hasta tasas de más de 100 muestras por
segundo.

Alimentación

1
Casi todos los dataloggers funcionan con baterías aunque algunos ofrecen también una opción para
energía externa

Memoria de datos

Casi todos los dataloggers usan memoria no volátil para el almacenamiento de datos. Esto significa
que los datos no se perderán si la energía falla

Tiempo de registro

La duración del registro depende de la capacidad de memoria del datalogger y la tasa de muestreo
deseada. Para determinar la duración, divida la capacidad de la memoria (número de muestra que
el dispositivo puede registrar) entre la tasa de muestreo. Por ejemplo, supongamos que un
datalogger dado puede almacenar hasta 10,000 muestras. Si se desea registrar 2 muestras cada
minuto, el datalogger puede funcionar durante 10,000/2 o 5,000 minutos (unos 3.5 días). Si la tasa
de muestreo se recortara a la mitad (1 muestra por minuto), el periodo de registro se duplicaría a 7
días.

2.- ARDUINO

Arduino es una plataforma de prototipos electrónica de código abierto (open – source) basada en
hardware y software flexibles y fáciles de usar. Está orientado para un uso en el campo de la
computación o robótica y entornos interactivos. La placa de Arduino es multiplataforma pues su
software funciona en los sistemas operativos Windows, Macintosh OSX y Linux. El software que lo
opera es ampliable y de código abierto, esta publicado bajo una licencia libre y preparado para ser
ampliado por programadores. El lenguaje puede ampliarse a través de librerías de C++, con el
lenguaje AVR C en el que está basado. Por otro lado su hardware también es ampliable y de Código
abierto, Arduino está basado en los microcontroladores ATMEGA168, ATMEGA328 y ATMEGA1280.
Los planos de los módulos están publicados bajo licencia de Creative Commons, por lo que se puede
realizar versiones propias del módulo, ampliándo u optimizándolo.

2.1 Placa Arduino Uno

2
2.1.1 Hardware

Arduino Uno es una placa electrónica basada en el microcontrolador ATmega328. Cuenta con 13
entradas/salidas digitales, de las cuales 6 se pueden utilizar como salidas PWM (Modulación por
ancho de pulso) y otras 6 son entradas analógicas. Además, incluye un cristal o resonador cerámico
de 16 MHz, un conector USB, un conector de alimentación, una cabecera ICSP y un botón de
reseteado. Se conecta a una PC por medio de un cable USB para alimentación e intercambio de
datos o a la corriente eléctrica a través de un adaptador AC/DC.

2.1.2 Software

Arduino utiliza un lenguaje de programación que sirve para controlar los distintos sensores y
actuadores que se encuentran conectados a la placa. Este lenguaje se llama Wirirng, basado en la
plataforma Processing y primordialmente en el lenguaje de programación C/C++, de este lenguaje
derivan otros más que son muy utilizados en el ámbito de Ingeniería y desarrollo, como C#, Java,
BASIC, Php, Phytom, JavaScript, Perl, entre otros más. Para poder trabajar desde el nivel
programación del procesador, debe descargarse el software que incluye las librerías necesarias para
poder utilizar el lenguaje de manera completa. Una ventaja de este software es que puede
descargarse desde el sitio web oficial de Arduino, pues es open source.

2.1.3 Características generales de la placa Arduino

 Opera con el microprocesador ATmega328

 13 pines para entradas/salidas digitales (programables) de los cuales 6 pueden operarse


como salidas analógicas del tipo PWM

 6 pines para entradas analógicas

 Voltaje de operación 5V
3
 Voltaje de entrada (recomendado) 7-12 V

 Voltaje de entrada (limite) 6-20 V

 Corriente DC I/O Pin 40 mA

 Corriente DC 3.3V Pin 50 mA

 Memoria Flash 32 KB (2 KB para el bootloader)

 SRAM 1 KB

 EEPROM 512 byte

 Velocidad de reloj 16 MHz

 Lenguaje Wiring

3.- Conexión del Sensor de Temperatura CI LM35

El LM35 es un circuito electrónico sensor que puede medir temperatura. Su salida es analógica, es
decir, proporciona un voltaje proporcional a la temperatura. El sensor tiene un rango desde −55°C
a 150°C.
Para convertir el voltaje a la temperatura, el LM35 proporciona 10mV por cada grado centígrado. Es
decir que si se mide 20mV a la salida, se estara midiendo 2°C.

Se conecta el sensor al Arduino al puerto análogo 0 (a0)

4
El Arduino leera el puerto A0, este puerto A0 recibe una tensión Vo desde el sensor, pero el Arduino
interpreta la tensión del sensor a través de su convertidor análogo digital de 10 bits

Por lo que una tensión aplicada al puerto analogo que varia entre 0 y 5 voltios se interpreta y se lee
como un valor entre 0 y 1023 (desde que al ser el convertidor A/D de 10 bits hay 210 = 1024 posibles
valores), esto se expresa asi:

5.Vleido
𝑉𝑜 = 1023

Por otro lado el sensor proporciona en su terminal central Vout un valor de 10mV por grado celsius,
entonces Vout que es el voltaje de salida que esta en función de la temperatura se expresa asi:
5
𝑉𝑜𝑢𝑡 = 10𝑚𝑉. 𝑇 ᴼ𝐶

juntando estas 2 relaciones tenemos que el valor de la temperatura en grados Celsius será:
5.𝑉𝑙𝑒𝑖𝑑𝑜
Vout = Vo reemplazndo los terminos equivalentes: 1023
=10mV.T

Despejamos T:

5.𝑉𝑙𝑒𝑖𝑑𝑜 5(0,1𝑥103 𝑉)𝑉𝑙𝑒𝑖𝑑𝑜


𝑇 = (1023)(10𝑥10−3 𝑉) luego 𝑇= (1023)(10𝑥10−3 𝑉)

500𝑉𝑙𝑒𝑖𝑑𝑜
𝑇=
1023

En wiring al pasarlo al Arduino IDE queda así:

void setup()
{
Serial.begin(9600);
}
void loop()
{
Serial.print("LM35 T:");
Serial.print(((analogRead(0)*500)/1023));
Serial.println();
delay(100);
}
Para visualizar resultados activar monitor serial en Herramientas

6
4.- Conexión del Sensor de Temperatura y Humedad DHT11

El DHT11 es un sensor que mide humedad y temperatura. Es ideal para sistemas de medición
climatológicos o para controles de temperatura y humedad. Este sensor además incluye un
transductor interno de temperatura del tipo NTC. También el módulo tiene una gran relación señal
a ruido ante la interferencia. Por ejemplo cada circuito, se calibra estrictamente en el laboratorio.
Esto permite que sea extremadamente preciso en calibración de humedad. Los coeficientes de
calibración se almacenan como programas en la memoria OTP, que son utilizados por el proceso de
detección de la señal interna del sensor.

CARACTERÍSTICAS

 Voltaje de Alimentación: 3V-5.5V


 Corriente de Alimentación: en medición de 0.5mA-2.5mA
 Stand by: 100uA-150uA
 Alcance de medición: 20-90% humedad/ 0-50°C
 Temperatura de precisión: ±2°C

Protocolo de transmisión digital del DHT11

El DHT11 es un sensor que presenta una salida digital en forma de un tren de pulsos que se enviará
al microcontrolador. La trama de datos es de 40 bits correspondiente a la información de humedad
y temperatura del DHT11.

El primer grupo de 8-bit es la parte entera de la humedad y el segundo grupo la parte decimal. Lo
mismo ocurre con el tercer y cuarto grupo, la parte entera de la temperatura y la parte decimal. Por
último los bits de paridad para confirmar que no hay datos corruptos.

Estos bits de paridad lo único que hacen es asegurarnos de que la información es correcta, sumando
los 4 primero grupos de 8-bit. Esta suma debe ser igual a los bit de paridad. Si nos centramos en la
imagen anterior y sumamos los bits, comprobamos que todo está correcto.

0011 0101 + 0000 0000 + 0001 1000 + 0000 0000 = 0100 1101

Conexión del DHT11 a Arduino

Conexionado DHT11 sin PCB

7
Para conectar el circuito con un DHT11, necesitaremos tener una resistencia que ayude a
conformar el nivel alto (pull-up) conectada a la salida digital. La recomendación es utilizar una
resistencia de 5 kΩ. Se dispone de 4 pines el VCC (de 3,5V a 5V), la salida digital I/O, el pin no
conectado NC y la toma de tierra GND.

El esquema eléctrico del DHT11 sería el siguiente:

Conexionado DHT11 con PCB

En este caso el DHT11 esta soldado dentro de un PCB el cual ya viene con la resistencia pull-up
integrada. Este modelo de presentación del DHT11 dispone de 3 pines, la toma de tierra GND, el
terminal para los datos DATA y el pin de la alimentación VCC (de 3,5V a 5V). En la siguiente imagen se
puede ver el esquema de conexión con Arduino.

8
IMPORTANTE: Se debe de tener cuidado pues existen muchas versiones de DHT11 con PCB y
algunos modelos presentan distinto patillaje

Instalación de librerias para el DHT11 hacia el IDE de Arduino

Se debe descargar la librería de este sensor, el cual facilita su programación con el Arduino. Hay
varias librerías disponibles en Internet que se puede utilizar para obtener la información de
temperatura y humedad.

En este caso se va a utilizar la que proporciona Adafruit. El procedimiento es simple:

1.- Buscar en google con las palabras claves: Adafruit DHT11 library

2.- Se ingresa a la pagina de Adafruit y ahí seleccionar Clone or Download y luego Download ZIP

3.- Luego en esa misma pagina ir al enlace de Adafruit Unified Sensor Library

4.- Ir al enlace y y ahí seleccionar Clone or Download y luego Download ZIP

5.- Con esto se ha descargado 2 librerías que estan comprimidas en formato ZIP

9
Luego es necesario integrar estas librerías al entorno de desarrollo de Arduino IDE, para esto realizar
los siguientes pasos:

1.- Ir a la carpeta de descargas de la PC, y ahí copiar las dos librerías ZIP descargadas

2.- Ir a la carpeta de Arduino en Mis Documentos, ubicar la carpeta de Libraries, entrar a esa carpeta
y ubicar una subcarpeta tambien con el nombre de libraries y depositar los archivos copiados, en
caso no haya subcarpeta copiar los ZIP en la carpeta de libraries

3.- Ir al Arduino IDE y luego:

4.- Se elige añadir librería ZIP y se busca la ruta donde esta el DHT Sensor Library y listo, se repite
el procedimiento para el otro ZIP y eso será todo.

Programación del DHT11 en el IDE de Arduino

En este ejemplo, se va a obtener 3 valores del DHT11:

 Humedad relativa: describe la cantidad de agua que se transporta por el aire, es importante
para determinar el desarrollo de las nubes y el factor precipitación.
 Temperatura ambiente: temperatura en un determinado lugar.
 Índice de calor: indica cuánto calor hace teniendo en cuenta la humedad relativa y la
temperatura. Nos da una idea de la sensación de calor.

El programa muestrea estos valores cada 5 segundos, para esto se hace uso de la función millis.

La librería de Adafruit para el DHT11 proporciona datos en grados centígrados y Fahrenheit. Para
obtener los dos datos utilizamos la misma función, readTemperature().

10
Si no pasamos ningún parámetro nos devuelve la temperatura en grados centígrados. Si pasamos el
valor true nos devuelve la temperatura en grados Fahrenheit. La humedad se obtiene llamando a la
función readHumidity().

Se utiliza la sentencia isnan para comprobar que la información enviada por el sensor no está
corrupta y que realmente está enviando un número. Esta sentencia nos dará verdadero si no es un
número (isnan, Is Not a Number) y falso en caso contrario.

Se obtiene el índice de calor con la función computeHeatIndex. Esta función puede devolver grados
centígrados o grados Fahrenheit.

El programa tambien muestra la información del anterior sensor de temperatura LM35. Al final del
todo se muestra la información en el monitor serie.

Código completo del programa sensor de temperatura y humedad DHT11 (y LM35)

#include <DHT.h> // Incluimos librería


#define DHTPIN 2 // Definimos el pin digital donde se conecta el sensor
#define DHTTYPE DHT11 // Dependiendo del tipo de sensor
DHT dht(DHTPIN, DHTTYPE); // Inicializamos el sensor DHT11
void setup()
{
Serial.begin(9600); // Inicializamos comunicación serie
dht.begin(); // Comenzamos el sensor DHT
}
void loop()
{
if (millis() % 5000 == 0) // Esperamos 5 segundos entre medidas
{
int h = dht.readHumidity(); // Leemos la humedad relativa
int t = dht.readTemperature(); // Leemos la temperatura en grados centígrados
if (isnan(h) || isnan(t)) // Comprobamos si ha habido algún error en la lectura
{
Serial.println("Error obteniendo los datos del sensor DHT11");
return;
}
int hic = dht.computeHeatIndex(t, h, false); // Calcular el índice de calor en grados centígrados
int temp = ((analogRead(0)*500)/1023); // programa para el LM35
Serial.print("Humedad: ");
Serial.print(h);
Serial.print("% ");
Serial.print("Temperatura: ");
Serial.print(t);
Serial.print("C ");
Serial.print("Indice de calor: ");
Serial.print(hic);
Serial.print("C ");
Serial.print("LM35 T:"); // programa para el LM35
Serial.print(temp); // programa para el LM35
Serial.print("C ");
Serial.print("promedio: ");
Serial.print((t+temp)/2);
Serial.println("C");
}
}

Nota: Programa anterior es Datalogger3

11
Comparando las señales producidas por el LM35 y el DHT11 con respecto a un medidor más preciso
(DS18B20), podemos presentar la tabla a continuación

Vemos que el LM35 presenta mejor aproximación en promedio que el DHT11, por lo que el DHT11
lo usaremos para muestrear humedad y el LM35 para muestrear temperatura

5.- Almacenamiento en memoria de los datos leidos

Los datos que se pueden almacenar en una memoria pueden ser de 1 byte u 8 bits, y almacenan
valores entre 0y 255, los datos proporcionados por los sensores son datos que ocupan 2 bytes (16
bits) y se puede almacenar valores entre 0 y 216 – 1.

Capacidad de la memoria EEPROM de Arduino

Cada modelo de placa posee una EEPROM distinta. La tabla a continuación brinda información al
respecto:

12
Para programar la memoria EEPROM se debe utilizar la librería EEPROM.h (Se encuentra por defecto
en la IDE).

En la memoria del Arduino se debe trabajar por direcciones y byte a byte tanto para leer como
para escribir. Esto significa que para una memoria de 1kB se tendrá desde la dirección 0 hasta la
999 y se puede utilizar valores para almacenar desde 0 a 255. En caso de que se requiera guardar
valores mayores como los leidos por los sensores, se tendrá que dividirlos por bytes.

Se necesita un programa entonces que actue bajo la siguiente lógica:

13
En la primera parte se lee el sensor que es un valor int (16 bits), este dato se tiene que guardar en
la memoria EEPROM, pero como los datos que se graban deben ser bytes, el dato del sensor se tiene
que descomponer en 2 mitades, los 8 bits mas significativos o altos, y los 8 bits menos significativos
o bajos.

Ejemplo: Programa que descompone un dato int en 2 bytes alto y bajo y lo graba en la memoria
EEPROM del Arduino en la direccion address

byte L; //Se crean dos variables de tipo byte para almacenar la información.
byte H;
H = highByte(data); //Se almacenan los bytes más y menos significativos.
L = lowByte(data);
EEPROM.write(address, H); //Se escriben los bytes en direcciones de memoria contiguas.
EEPROM.write(address + 1, L);

El retardo que indica el diagrama de flujo sirve para espaciar las muestras en el tiempo, esto se debe
fijar en funcion del tiempo de muestreo mas adelante

En la segunda parte del diagrama de flujo se realiza la lectura de la memoria EEPROM y se


recompone el dato que habia sido particionado para poder ser almacenado en memoria

14
Ejemplo: Programa funcion que restaura un dato int a partir de 2 bytes alto y bajo grabados en
memoria EEPROM del Arduino

int ensamblardato(int direc)


{
byte H;
byte L;
H=EEPROM.read(direc); //Se leen los bytes en direcciones de memoria contiguas.
L=EEPROM.read(direc + 1);
int ensamblar;
ensamblar = H;
ensamblar = ensamblar*256;
ensamblar |= L; se realiza la operación OR lógica
return ensamblar;
}

15
Aquí se puede exponer el programa de acuerdo a sus diferentes partes:

#include <DHT.h> // Incluimos librería


#define DHTPIN 2 // Definimos el pin digital donde se conecta el sensor
#define DHTTYPE DHT11 // Dependiendo del tipo de sensor
#include <EEPROM.h> //Se incluye la librería EEPROM
int pulsador = 12;
int led= 13;
DHT dht(DHTPIN, DHTTYPE); // Inicializamos el sensor DHT11
void setup()
{
Serial.begin(9600); // Inicializamos comunicación serie
dht.begin(); // Comenzamos el sensor DHT
pinMode(pulsador, INPUT);
pinMode(led, OUTPUT);
}
void grabar(int data, int address)
{
byte L; //Se crean dos variables de tipo byte para almacenar la información.
byte H;
H = highByte(data); //Se almacenan los bytes más y menos significativos.
L = lowByte(data);
EEPROM.write(address, H); //Se escriben los bytes en direcciones de memoria contiguas.
EEPROM.write(address + 1, L);
}
void loop()
{
int direccion=0;
int dato;
for (int i = 0; i<=4; i++)
{
digitalWrite(led, HIGH);
int h = dht.readHumidity(); // Leemos la humedad relativa
int t = dht.readTemperature(); // Leemos la temperatura en grados centígrados
if (isnan(h) || isnan(t)) // Comprobamos si ha habido algún error en la lectura
{
Serial.println("Error obteniendo los datos del sensor DHT11");
return;
}
int hic = dht.computeHeatIndex(t, h, false); // Calcular el índice de calor en grados centígrados
int temp = ((analogRead(0)*500)/1023); // programa para el LM35
grabar (h,direccion);
direccion= direccion+2;
grabar (hic,direccion);
direccion= direccion+2;
grabar (temp,direccion);
direccion= direccion+2;
delay(100);
digitalWrite(led, LOW);
delay(10000);
}
direccion=0;
for (int i = 0; i<=4; i++)
{
int h=ensamblardato(direccion);
direccion=direccion+2;
int hic=ensamblardato(direccion);
direccion=direccion+2;
int temp=ensamblardato(direccion);
direccion=direccion+2;
Serial.print("Humedad: ");
Serial.print(h);
Serial.print("% ");

16
Serial.print("Indice de calor: ");
Serial.print(hic);
Serial.print("C ");
Serial.print("LM35 T:"); // programa para el LM35
Serial.print(temp); // programa para el LM35
Serial.println("C");
}
}

int ensamblardato(int direc)


{
byte H;
byte L;
H=EEPROM.read(direc); //Se leen los bytes en direcciones de memoria contiguas.
L=EEPROM.read(direc + 1);
int ensamblar;
ensamblar = H;
ensamblar = ensamblar*256;
ensamblar |= L;
return ensamblar;
}

Nota: Programa anterior es Datalogger4

Datos FLOAT

En el caso que el dato fuera float, se tienen 4 bytes utilizados, en ese caso es mejor emplear las
funciones Put, Get y Update.

Escribe una variable en la dirección address:

 EEPROM.Put(address, variable)

Lee una variable en la dirección address:

 EEPROM.Get(address, variable)

Actualiza el valor de una variable, es decir, primero la lee, y sólo la graba si su valor es distinto del
que vamos a guardar. Esto favorece a reducir el número de escrituras, y alargar la vida útil de la
memoria:

 EEPROM.Update(address, variable)

Las funciones Put, Get y Update tienen en cuenta el tamaño de la variable, y funcionan incluso con
variables y estructuras definidas por nosotros. Sin embargo, tendremos que tener en cuenta el

17
tamaño de la variable para saber cuál es la siguiente dirección a escribir, y evitar que se “solapen”
las variables.

A continuación tenemos un programa que graba datos float en la memoria eeprom

#include <EEPROM.h>

float sensorValue;
int direccion = 0;

//Funcion que simula la lectura de un sensor


float ReadSensor()
{
return 10.0f;
}
void setup()
{
}
void loop()
{
sensorValue = ReadSensor(); //Lectura simulada del sensor
EEPROM.put( direccion, sensorValue ); //Grabamos el valor
direccion += 4; //Obtener la siguiente posicion para escribir
if(direccion >= EEPROM.length()) direccion = 0; //Comprobar que no hay desbordamiento
delay(30000); //espera 30 segunos
}

Ahora se puede incluir esta forma de leer el dato float en el programa del Datalogger:

#include <DHT.h> // Incluimos librería


#define DHTPIN 2 // Definimos el pin digital donde se conecta el sensor
#define DHTTYPE DHT11 // Dependiendo del tipo de sensor
#include <EEPROM.h> //Se incluye la librería EEPROM
int pulsador = 12;
int led= 13;
DHT dht(DHTPIN, DHTTYPE); // Inicializamos el sensor DHT11
void setup()
{
Serial.begin(9600); // Inicializamos comunicación serie
dht.begin(); // Comenzamos el sensor DHT
pinMode(pulsador, INPUT);
pinMode(led, OUTPUT);
}
void loop()
{
int direccion=0;
float dato;
for (int i = 0; i<=4; i++)
{
digitalWrite(led, HIGH);
float h = dht.readHumidity(); // Leemos la humedad relativa
float t = dht.readTemperature(); // Leemos la temperatura en grados centígrados
if (isnan(h) || isnan(t)) // Comprobamos si ha habido algún error en la lectura
{
Serial.println("Error obteniendo los datos del sensor DHT11");
return;

18
}
float hic = dht.computeHeatIndex(t, h, false); // Calcular el índice de calor en grados centígrados
float temp = ((analogRead(0)*500)/1023); // programa para el LM35
EEPROM.put(direccion, h); //Se escriben los bytes en direcciones de memoria contiguas.
direccion= direccion+4;
EEPROM.put(direccion, hic); //Se escriben los bytes en direcciones de memoria contiguas.
direccion= direccion+4;
EEPROM.put(direccion, temp); //Se escriben los bytes en direcciones de memoria contiguas.
direccion= direccion+4;
delay(100);
digitalWrite(led, LOW);
delay(10000);
}
direccion=0;
for (int i = 0; i<=4; i++)
{
float h, hic,temp;
EEPROM.get(direccion, h);
direccion= direccion+4;
EEPROM.get(direccion, hic);
direccion= direccion+4;
EEPROM.get(direccion, temp);
direccion= direccion+4;
Serial.print("Humedad: ");
Serial.print(h);
Serial.print("% ");
Serial.print("Indice de calor: ");
Serial.print(hic);
Serial.print("C ");
Serial.print("LM35 T:"); // programa para el LM35
Serial.print(temp); // programa para el LM35
Serial.println("C");
}
}

Nota: Programa anterior es Datalogger5

6.- Tiempo de muestreo

Un criterio para elegir el tiempo de muestreo es determinar el tiempo (Te) de respuesta del proceso
para alcanzar el 95% de su valor final, luego el tiempo de muestreo (Tm) debe estar comprendido
entre los valores

1 1
𝑇𝑒 ≤ 𝑇𝑚 ≤ 𝑇𝑒
15 4

Si consideramos un entorno industrial en el que se tiene areas que estan bajo la influencia de
calderos, intercambiadores, hornos industriales, etc, se puede estimar que la temperatura en el
entorno industrial puede cubrir su rango de variación en un lapso de 2 horas de operación contínua,
si se toma como referencia ese tiempo tendremos que:

19
8𝑚𝑖𝑛 ≤ 𝑇𝑚 ≤ 30𝑚𝑖𝑛

Se elegirá un tiempo de muestreo de 10 minutos

7.- Ahorro de energía

El Arduino UNO tiende a consumir uso 45 mA en vacío, mientras que un Arduino Nano llega a los
15 mA, el problema consiste en que una aplicación como Datalogger implica operación
independiente y autónoma por lo que el uso de baterías para alimentar el circuito es obligatorio y
la condición de ahorro de energía es indispensable.

Para lograr este ahorro se utiliza la función sleep, para ello es necesario descargar la librería:

Low-Power-master, ir al enlace:

https://github.com/rocketscream/Low-Power

La función sleep trabaja con el Watchdog Timer del Arduino, el Watchdog Timer no es mas que un
temporizador que cuando se lo utiliza con un valor de tiempo preestablecido, empieza a realizar una
cuenta descendente respecto al tiempo prefijado, al llegar a cero, este Watchdog Timer activa una
interrupción Hardware sobre el Arduino, es decir interrumpe cualquier labor que estuviese haciendo
el Arduino y lo direcciona a realizar una tarea específica. Normalmente el watchdog se utiliza como
una condición de preeemergencia, digamos que se hacen labores repetitivas que “duran” un
periodo de tiempo, se activa el watchdog con cada labor repetitiva con un tiempo prefijado mayor
al periodo que supuestamente demora la labor repetitiva, el objetivo es que Arduino realice una
tarea de emergencia cuando la labor específica dure mas de su tiempo normal, esto es de bastante
utilidad en algunos casos.

Una vez descargada e integrada la nueva librería al Arduino IDE, se puede probar el programa
siguiente:

#include "LowPower.h"
int LED = 13 ;

void setup()
{
pinMode(13, OUTPUT);
}

void loop()
{
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
digitalWrite(LED, HIGH);
delay(1000);
digitalWrite(LED, LOW);
}

En este programa la línea que realiza el trabajo de dormir al arduino es:


20
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

El comando LowPower.powerDown utiliza la función sleep en el modo Power Down, de hecho


tenemos en el Atmega328p seis modos de Sleep:

 Idle
 ADC Noise Reduction
 Power-save
 Power-down
 Standby
 Extended Standby

El consumo para cada modo es:

 Sleep modo IDLE: 15 mA


 Sleep modo ADC: 6.5 mA
 Sleep modo POWER SAVE: 1.62 mA
 Sleep modo EXT STANDBY: 1.62 mA
 Sleep modo STANDBY : 0.84 mA
 Sleep modo POWER DOWN : 0.36 mA

Entonces estamos consumiendo con el modo utilizado sólo 0,36 mA.

Ahora respecto al dato SLEEP_8S, éste va directo al Watchdog Timer y sera el tiempo que dormira
el arduino hasta que lo despierte la interrupción activada por el watchdog cuando la cuenta
regresiva del tiempo programado (8 segundos) llegue a cero.

Este tiempo puede variar de acuerdo a la tabla siguiente:

 SLEEP_15MS
 SLEEP_30MS
 SLEEP_60MS
 SLEEP_120MS
 SLEEP_250MS
 SLEEP_500MS
 SLEEP_1S
 SLEEP_2S
 SLEEP_4S
 SLEEP_8S
 SLEEP_FOREVER

Se debe tener cuidado con SLEEP FOREVER pues el Arduino “dormira” por siempre si es que no se
ha establecido el procedimiento de hardware o software para “despertarlo”

Respecto al tiempo, vemos que el mayor disponible es el de 8 segundos, pero esto puede extenderse
realizando bucles anidados que prolongan la cantidad de estos periodos de “sueño”
21
El programa siguiente:

for (int i = 0 ; i < 76 ; i++)


LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

Genera un lapso de 8 segundos x 75 = 600 segundos o 10 minutos, en los que el WDT despierta el
micro lo justo para hacer una tarea especifica , incrementar la variable i, y volver a dormirse. (no
hay ninguna razón para no hacer lo mismo 8 x 75 x 6 = 1 hora (si es lo que se requiere).

Anteriormente se habia previsto un tiempo de muestreo de cada 10 minutos por lo que el programa
del Datalogger incorporara esta linea.

Con respecto a los otros datos:

ADC_OFF: Apaga los convertidores Analógico a digital

BOD_OFF: Apaga el circuito de Brown Out Detection, que es un circuito para detectar niveles bajos
de tensión. Si no fuera por este detector BOD, cuando las pilas se fueran agotando la tensión podría
descender de un cierto nivel y dañar los circuitos. Apagarlo ayuda a reducir consumo, pero
ciertamente se corre otros peligros.

8.- Inicio y fin de operación de muestreo e inicio y fin de transmisión de datos

El Datalogger se debe poner en operación de muestreo de algún modo, sea este manual o
automático. Una forma eficiente y automática sería que inicie sus operaciones de toma de muestras
a una hora en particular esto se puede realizar si utilizamos la librería de manejo de tiempo Time.h

Que se puede encontrar en el enlace:

https://github.com/PaulStoffregen/Time

La librería descargada renombrarla como Time.ZIP se añade al Arduino IDE de la forma ya


especificada dentro de directorio Mis Documentos/Arduino/libraries/libraries, una vez alli se añade
desde Arduino IDE:

Programa -> Incluir Librería -> Añadir Librería ZIP -> especificar la ruta donde se ha depositado el ZIP

Siempre es aconsejable verificar que la librería ha sido añadida en Arduino IDE:

22
Programamos lo siguiente:

#include <Time.h>
#include <TimeLib.h>
#include <Time.h>//Incluimos la librería Time

void setup()
{
Serial.begin(115200);//Inicializamos el puerto serie.
//Anotamos la hora y la fecha desde la que nuestro programa empezará a contar.
//Formato: hora, minutos, segundos, días, mes, año
setTime(14,25,06,04,05,2018);
}
void loop()
{
time_t t = now();//Declaramos la variable time_t t

//Imprimimos la fecha y la hora


Serial.print(day(t));
Serial.print(+ "/") ;
Serial.print(month(t));
Serial.print(+ "/") ;
Serial.print(year(t));
Serial.print( " ") ;
Serial.print(hour(t));
Serial.print(+ ":") ;
Serial.print(minute(t));
Serial.print(":") ;
Serial.println(second(t));
delay(3000);//Esperamos 3 segundos

Los resultados se observan en monitor serial

23
9.- Interrupciones

Las interrupciones son útiles para hacer que las cosas sucedan automáticamente en un programa
de un microcontrolador y pueden ayudar a resolver problemas de tiempo. Una tarea adecuada para
usar una interrupción pueden incluir leer un sensor eventualmente o monitorear algún puerto de
entrada.

Si se desea asegurar de que un programa siempre capte los impulsos proporcionados por el rotor
de una turbina giratoria, para que nunca falle la recepción del pulso se tendría que realizar un
complicado programa para hacer que el microcontrolador haga algo adicional a eso, puesto que el
programa necesitaría sondear constantemente al sensor, procesar la señal obtenida, etc. Otras
situaciones en las que se utilicen sensores también tienen una dinámica de interfaz similar, como
tratar de leer un sensor de sonido que está tratando de captar un clic, o un sensor de ranura
infrarroja (fotointerruptor) que intenta capturar una caída de moneda. En todas estas situaciones,
usar una interrupción puede liberar el microcontrolador para realizar otro trabajo sin perder la
entrada.

Una interrupción se puede llamar de varias formas:

 Un Timer ( Un Watch Dog, es un caso particular de Timer)


 Una interrupción hardware.
 Una señal UART

Un ejemplo de interrupción por hardware lo implementamos a continuación:

24
Primero se tiene que elegir la placa arduino que se utiliza, en el caso que fuese Arduino UNO el pin
digital 2 será por donde se habilite la interrupción 0, y el pin digital 3 será por donde se habilite la
interrupción 1. Para otras placas se puede revisar la tabla siguiente:

Placa Arduino INT.0 INT.1 INT.2 INT.3 INT.4 INT.5

Uno, nano, mini, Ethernet 2 3


Número
del pin
Mega, mega2560, megaADK 2 3 21 20 19 18
de la
placa
Basados en el 32u4 (ej.Leonardo, Micro) 3 2 0 1 7

Como tenemos en nuestro desarrollo el puerto digital 2 ocupado por el DHT11, utilizamos el pin 3 o
interrupción 1 para la prueba respectiva:

25
Para poder utilizar interrupciones con Arduino no necesitamos incorporar ningún tipo de librería al
programa, únicamente se necesita hacer referencia a las funciones que trabajan con ello:

attachInterrupt(pin, ISR, modo)

Esta función nos va a permitir definir o configurar uno de los pines como un puerto de interrupción.
Los tres parámetros que admite son:

pin: debemos llevar especial cuidado con este parámetro, no se refiere al pin utilizado para la
interrupción sino al numero de interrupcion asociado al pin utilizado, (ver la tabla previa).por
ejemplo si trabajamos con Arduino UNO tenemos dos pines para interrupciones el 2 y el 3. Si
queremos utilizar el 2 debemos poner un 0 y si queremos utilizar el 3 debemos poner un 1. Esto se
resuelve muy fácilmente utilizando otra función, digitalPinToInterrupt(pin), que devuelve el ordinal
del pin que queremos utilizar. Por ejemplo, en el caso anterior, si queremos utilizar el pin 2
llamaríamos a la función digitalPinToInterrupt(2). Esto nos devolverá un 0 y es el método
recomendado por Arduino para pasar este parámetro.

ISR: es una abreviatura de Interrupt Service Routine y no es más que la función o método
que se llama cuando se produce la interrupción. Es de un tipo particular ya que no admite
parámetros y tampoco devuelve ningún valor. En general, se debe hacer métodos o
funciones ISR lo más cortas y rápidas posibles. Se puede producir un bloqueo entre los
diferentes ISR. Lo que sucede en estos casos es que solo se ejecuta una a la vez quedando
en cola el resto de interrupciones.

Dentro de las interrupciones no funciona el delay() (retardo) por lo tanto no se debe utilizar.
Si se requiere un retardo dentro de un ISR se puede utilizar la función delayMicrosends(),
que funciona con normalidad. Tambien ocurre que los datos recibidos por el puerto serie
se pueden perder mientras se está en la función llamada por la interrupción.

Las variables que se vayan a utilizar tanto dentro de los métodos ISR como fuera, ya sea en
el loop() o en cualquier otra función, deben ser declararlas como volatile. Esta palabra
reservada le dice al compilador que estas variables pueden cambiar de valor en cualquier
momento y, por lo tanto, el compilador debe volver a cargar la variable cada vez que se
hace referencia en algún sitio a ella. Al contrario que ocurre con otras variables donde el
compilador confía en alguna copia que pueda tener en algún registro del procesador.

modo: define cuando debe ser disparada la interrupción. Puede tomar cuatro valores constantes
dependiendo de lo que se quiera hacer:

 LOW: se lanzará la interrupción cuando el pin esté en estado bajo.


 CHANGE: se lanzará la interrupción cuando el pin cambie de valor de alto a bajo, o de bajo
a alto.

26
 RISING: se lanzará la interrupción cuando el pin cambie de estado de bajo a alto.
 FALLING: se lanzará la interrupción cuando el pin cambie de estado de alto a bajo.
 Existe un quinto estado que solo los Arduino Due, Zero y MKR1000 permiten:
 HIGH: se lanzará la interrupción cuando el pin esté en estado alto.

detachInterrupt(pin)

Si attachInterrupt() nos permite configurar un pin como interrupción, el método detachInterrupt()


anula esa configuración. Como parámetro le pasamos el pin y lo podemos hacer con la
función digitalPinToInterrupt(número de pin) que nos devolverá el ordinal del pin del que queremos
anular la configuración.

A continuación se muestra un programa que maneja interrupcion por hardware para salir de el
modo Sleep forever

#include "LowPower.h"
const int pindisparador = 2; // se utiliza el pin 2 para activar la interrupcion
int contador = 0;
volatile int n = contador ;
void setup()
{
Serial.begin(9600);
pinMode( pindisparador, INPUT);
}
void loop()
{
attachInterrupt(1, subrutina, FALLING); // engancha la int por pulso en pin 3, saldra del sleep y eje subrutina
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); // dormira, sale cuando se produce la interrupcion
detachInterrupt(0); // se inhabilita la interrupcion pues pasara a imprimir
if (n != contador) // si n no es igual a contador
{
Serial.println(contador); // envia a la PC el valor del contador
n = contador ; // hace n igual al contador
Serial.flush(); // vaciamos la cola serie
}
}
void subrutina() // subrutina de servicio de la interrupción
{ contador++ ; // incrementa el valor del contador de pulsos
}

27
10.- Incorporamos la funcion sleep y las interrupciones en el programa del datalogger

Para realizar el programa primero trazamos el diagrama de flujo, este se basa en la forma como
operaría el Datalogger, las condiciones serán las siguientes:

a) En el programa ya se fija 2 datos importantes que necesita el Datalogger:


 Sample Rate: que es el periodo de tiempo entre las muestras, este será
preconfigurado a un valor de 8 segundos
 Sample points: que es la cantidad de muestras que seràn tomadas por el
Datalogger, este será preconfigurado a 10 muestras
b) Al colocar el interruptor de encendido a ON el Datalogger entra inmediatamente en modo
sleep
c) Cuando el usuario lo determine, para iniciar el proceso de muestreo debe de presionar el
pulsador de habilitación Enable
d) El Datalogger realizara la toma de muestras de acuerdo a la cantidad especificada por
Sample Points y de acuerdo al periodo fijado por Sample Rate
e) Durante el proceso de muestreo se activará un led Rojo indicando este modo
f) Luego de terminar el proceso de muestreo el Datalogger pasa inmediatamente al modo
sleep
g) Cuando el usuario lo determine, para iniciar el proceso de transferencia de datos a la PC,
debe de presionar el pulsador de habilitación Enable
h) El Datalogger realizará la transferencia de la data a la PC, en este modo será indicado por
un LED Verde
i) Al término de este proceso el Datalogger pasa a repetir su operación especificada desde el
item b

El diagrama de flujo correspondiente será:

28
El circuito completo tiene 2 sensores, LM35, DHT11, un pulsador y un led bicolor.

29
Luego pasamos a implementar el programa:

#include <DHT.h> // Incluimos librería


#define DHTPIN 2 // Definimos el pin digital donde se conecta el sensor
#define DHTTYPE DHT11 // Dependiendo del tipo de sensor
#include <EEPROM.h> //Se incluye la librería EEPROM
int pulsador = 12;
int ledm= 10; // led que indica muestreo
int ledt= 11; // led que indica transmisión a la PC
DHT dht(DHTPIN, DHTTYPE); // Inicializamos el sensor DHT11
#include "LowPower.h"
const int pindisparador = 3; // se utiliza el pin 3 para activar la interrupcion
int contador = 0;
volatile int n = contador ;

void setup()
{
Serial.begin(9600); // Inicializamos comunicación serie
dht.begin(); // Comenzamos el sensor DHT
pinMode(pulsador, INPUT);
pinMode(ledm, OUTPUT);
pinMode(ledt, OUTPUT);
pinMode(pindisparador, INPUT);
}

void loop()
{
attachInterrupt( 1, subrutina, FALLING); // engancha interrupción por pin 3, saldra de de sleep y hace la subrutina
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); // pasa a dormir, saldra con la interrupcion
detachInterrupt(1); // se inhabilita la interrupcion
int direccion=0;
float dato;
int samplepoints=10;
int samplerate=1;
30
for (int i = 0; i<samplepoints; i++)
{
digitalWrite(ledm, HIGH);
float h = dht.readHumidity(); // Leemos la humedad relativa
float t = dht.readTemperature(); // Leemos la temperatura en grados centígrados
if (isnan(h) || isnan(t)) // Comprobamos si ha habido algún error en la lectura
{
Serial.println("Error obteniendo los datos del sensor DHT11");
return;
}
float hic = dht.computeHeatIndex(t, h, false); // Calcular el índice de calor en grados centígrados
float temp = (((analogRead(0)*500)/1023)+t)/2; // temperatura promedio del LM35 y DHT11
EEPROM.put(direccion, h); //Se escriben los bytes en direcciones de memoria contiguas.
direccion= direccion+4;
EEPROM.put(direccion, hic); //Se escriben los bytes en direcciones de memoria contiguas.
direccion= direccion+4;
EEPROM.put(direccion, temp); //Se escriben los bytes en direcciones de memoria contiguas.
direccion= direccion+4;
delay(100);
digitalWrite(ledm, LOW);
for (int j = 0 ; j < samplerate ; j++)
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}
attachInterrupt( 1, subrutina, FALLING); // engancha interrupción por pin 3, saldra de de sleep y hace la subrutina
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); // pasa a dormir, saldra con la interrupcion
detachInterrupt(1); // se inhabilita la interrupcion
direccion=0;
digitalWrite(ledt, HIGH);
for (int i = 0; i<samplepoints; i++)
{
float h, hic,temp;
EEPROM.get(direccion, h);
direccion= direccion+4;
EEPROM.get(direccion, hic);
direccion= direccion+4;
EEPROM.get(direccion, temp);
direccion= direccion+4;
Serial.print("Humedad: ");
Serial.print(h);
Serial.print("% ");
Serial.print("Indice de calor: ");
Serial.print(hic);
Serial.print("C ");
Serial.print("LM35 T:"); // programa para el LM35
Serial.print(temp); // programa para el LM35
Serial.print("C");
Serial.println();
}
delay(1000);
digitalWrite(ledt, LOW);
}
void subrutina() // subrutina de servicio de la interrupción
{ contador++ ; // incrementa el valor del contador de pulsos
}

Nota: Programa anterior es Datalogger6


31
11.- Transmisión de datos por Bluetooth

Bluetooth es una especificación industrial para Redes Inalámbricas de Área Personal (WPAN) que
posibilita la transmisión de voz y datos entre diferentes dispositivos mediante un enlace por
radiofrecuencia en la banda ISM (Industrial, Scientific and Medical, reservadas internacionalmente
para uso no comercial de radiofrecuencia electromagnética en dichas área) de los 2.4 GHz.

Utilizamos el módulo Bluetooth HC-05

 Vcc: Alimentación del módulo entre 3,6V y 6V.


 GND: La masa del módulo.
 TXD: Transmisión de datos.
 RXD: Recepción de datos a un voltaje de 3,3V.
 KEY: Poner a nivel alto para entrar en modo configuración del módulo (solo el modelo HC-
05)
 STATE: Para conectar un led de salida para visualizar cuando se comuniquen datos.

Este módulo realiza la comunicación por via BT y sus terminales Rx y Tx, estos terminales pueden
conectarse en forma cruzada a los correspondientes del Arduino Rx y Tx que son los pines digitales
0 y 1 respectivamente, pero el problema es que Arduino se enlaza por dicha vía con el puerto serial
USB de la PC, por tanto es conveniente utilizar otros pines digitales del Arduino para que intercambie
datos con este módulo BT, para realizar esto necesitamos una librería denominada softwareserial

Que se puede descargar de este enlace:

32
https://www.robot-r-us.com/e/995-softwareserial.html

Primero instalamos el módulo bluetooth en el circuito del Datalogger, vamos a utilizar para la
comunicación entre Arduino y el BT, los pines del arduino: 6 como Rx y 7 como Tx, se deben conectar
pero en forma cruzada a los pines Rx y Tx del módulo BT

Programa para que el módulo Bluetooth envíe datos a la PC

#include <SoftwareSerial.h>
SoftwareSerial BT1(6, 7); // RX | TX

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

void loop()
{
if (millis() % 2000 == 0)
{
BT1.println("Analog 0 = " + String(analogRead(A0))) ;
BT1.println("Analog 1 = " + String(analogRead(A1))) ;
BT1.println("Analog 2 = " + String(analogRead(A2))) ;
BT1.println(".................");
}
}

33
Para comprobar su operación primero se debe de emparejar el módulo BT con la PC

a) Emparejar el módulo bluetooth con la PC

Para esto conectar el circuito al puerto USB, esto también conectará el módulo bluetooth. Hacer clic
en el icono de Bluetooth en la bandeja del sistema que normalmente se encuentra en la esquina
inferior derecha de la pantalla de la PC.
Se debe hacer clic y desplegar el menú contextual:

Al hacer clic en el icono debe obtener un menú con "Agregar un dispositivo" en la parte superior del
menú así que seguir adelante y haga clic en él.

 puede hacer clic en "Mostrar dispositivos Bluetooth", donde también encontrará un enlace
"Añadir un dispositivo" en la esquina superior izquierda de la ventana que se abre.
 Al hacer clic en el vínculo "Añadir un dispositivo", lo llevará a la pantalla "Agregar un
dispositivo" donde su computadora comenzará a buscar dispositivos Bluetooth.
 Asegúrese de que su proyecto está encendido en este momento para que su computadora
pueda encontrar el HC-06.
 Cuando vea el HC-06 ha sido encontrado y el icono se muestra haga clic en él y verá la
pantalla de vinculación de dispositivos Bluetooth.
 Usted debe elegir "Introduzca el código de emparejamiento del dispositivo" y luego haga
clic en "Siguiente" donde puede ingresar el código de emparejamiento, que es "1234" o
"0000".
 A continuación, haga clic en "Siguiente" y verá que su dispositivo se ha agregado
correctamente.

34
No olvidarse que el Bluetooth debe ser emparejado con la PC en un momento distinto al de la
programación del arduino, y cuando se programa el arduino, no debe de estar energizado el modulo
bluetooth.

 Una vez que esta programado, entrar al icono de bluetooth y ver en que puerto esta
conectado el módulo bluetooth emparejado con la PC
 Vuelva a la ventana "Mostrar dispositivos Bluetooth" Haga clic con el botón derecho del
ratón en el nuevo icono HC-05
 Luego haga clic en "Propiedades" Cuando aparezca la ventana "Propiedades" aparecerá
cuatro tablas.
 Hacer click en la sección "Servicios" y aparece el numero de puerto COM.

Es el puerto COM27 en este caso particular.

35
b) Recepción desde la PC de los datos enviados por el módulo BT

Para que la PC pueda recibir los datos se pueden probar 2 herramientas de software muy utiles,
ambas se descargan gratuitamente de Internet y son:
 Hyperterminal
 Putty

c) Control desde la PC con Hyperterminal


Hyperterminal es una herramienta para hacer conexiones de la PC a través de sus puertos COM, con
dispositivos externos, normalmente viene instalado en el sistema operativo de Windows, pero a
partir de windows 7 ya no lo incorpora por defecto, si que si ese es el caso puede utilizar el archivo
descargado de internet y simplemente instalarlo.

Correr Hyperterminal, aparece la ventana para una nueva conexión, colocar cualquier nombre

Luego especificar el puerto COM27 para el enlace

36
Y listo,

d) Control desde la PC con PUTTY


activar Putty elegir el campo Serial y colocar el puerto COM 27 en este caso y la velocidad de
transmisión que será igual a la que ha sido configurado el módulo BT, esto es 9600

37
Luego debajo de Session hacer click en Logging (Registro), aquí se configura que todo lo que
reciba el software Putty se guarde en un archivo (all session output) que será llamado
putty.log, también se selecciona la opción de sobreescribir lo anterior (always overwrite it)
si existe.

38
Si hacemos click ahora en Terminal, se selecciona que fuerce el hecho en lo que se recibe y
también en lo que se envia

Luego se vuelve a session para guardar esta configuración como BtQueen para que sea más facil
entrar las siguientes veces.

39
Luego de ello se procede a hacer click en Open para enlazar el BT que ya esta operando con el
Arduino

e) Control desde la PC via bluetooth

#include <SoftwareSerial.h>
SoftwareSerial BT1(6, 7); // RX | TX
void setup()
{
BT1.begin(9600);
}

void loop()
{
pinMode(13, OUTPUT);
String B= "." ;
if (BT1.available())
{ B= GetLineBT();
Serial.write(BT1.read());
}
if (B =="13")
digitalWrite(13, !digitalRead(13));
}

String GetLineBT()
{
String S = "" ;
if (BT1.available())
40
{ char c = BT1.read(); ;
while ( c != '\r' ) //Hasta que el caracter sea intro
{ S=S+c;
delay(25) ;
c = BT1.read();
}
return( S ) ;
}
}

Con este programa se envía data por bluetooth que realiza una acción concreta en la tarjeta
Arduino:

Desde la consola de Putty que ya esta configurada, al pulsar el número 13 el LED embebido en la
placa el pin 13 encenderá, si se vuelve a pulsar 13 este se apagará y asi sucesivamente

Respecto al módulo BT, este tiene leds incorporados que avisan su estado:

 El módulo BT en estado de conexión flashea 2 pulsos rápidos de corta duración por cada 2
segundos
 Cuando Putty no enlaza aún con el dispositivo BT, este flashea a un periodo de 0,25 s
 Antes de emparejarse el módulo BT flashea a un periodo de 0,5 s

41
El software completo que maneja el módulo BT es el siguiente:

#include <SoftwareSerial.h>
SoftwareSerial BT1(6, 8); // RX | TX

void setup()
{
Serial.begin(9600);
BT1.begin(38400); // depende de la velocidad por defecto del módulo BT
pinMode(13, OUTPUT);
}

void loop()
{
String B= "." ;
if (BT1.available()) // lee lo que viene desde la PC por putty via bluetooth
{ B= GetLineBT();
Serial.println(B);
}

if (Serial.available()) // lee lo que viene desde la PC por Monitor serie ("Ambos NL&CR") via USB
{ String S = GetLine();
BT1.println(S);
Serial.println(S);
}
if (B =="3") // en función de lo recibido acciona led pin 13
digitalWrite(13, !digitalRead(13));

if (millis() % 2000 == 0) // envia desde el módulo BT hacia la PC via bluetooth datos de puertos
{
BT1.println("Analog 0 = " + String(analogRead(A0))) ;
BT1.println("Analog 1 = " + String(analogRead(A1))) ;
BT1.println("Analog 2 = " + String(analogRead(A2))) ;
BT1.println(".................");
}
}

String GetLine() // Devuelve lo tecleado en la PC y enviado por Monitor serie via USB
{ String S = "" ;
if (Serial.available())
{ char c = Serial.read(); ;
while ( c != '\n') //Hasta que el caracter sea intro
{ S=S+c;
delay(25) ;
c = Serial.read();
}
return( S ) ;
}
}

String GetLineBT() // Devuelve lo tecleado en la PC y enviado por Putty via bluetooth


{ String S = "" ;
if (BT1.available())
{ char c = BT1.read(); ;
while ( c != '\r' ) //Hasta que el caracter sea intro
{ S=S+c;

42
delay(25) ;
c = BT1.read();
}
return( S ) ;
}
}

NOTA: El módulo BT ya viene con una velocidad por defecto que es de 9600 bps pero esto no es una
constante en todos los casos por lo que si no se obtienen los resultados deseados y se imprime ruido
o barras horizontales, se puede probar con otras velocidades para el módulo BT en el programa (la
parte de color verde en el programa principal)

Lo siguiente es incorporar el enlace bluetooth para enviar los datos del Datalogger a la PC

43
#include <SoftwareSerial.h>
#include <DHT.h> // Incluimos librería
#define DHTPIN 2 // Definimos el pin digital donde se conecta el sensor
#define DHTTYPE DHT11 // Dependiendo del tipo de sensor
#include <EEPROM.h> //Se incluye la librería EEPROM
SoftwareSerial BT1(6, 8); // RX | TX
int pulsador = 12;
int ledm= 10; // led que indica muestreo
int ledt= 11; // led que indica transmisión a la PC
DHT dht(DHTPIN, DHTTYPE); // Inicializamos el sensor DHT11
#include "LowPower.h"
const int pindisparador = 3; // se utiliza el pin 3 para activar la interrupcion
int contador = 0;
volatile int n = contador ;

void setup()
{
Serial.begin(9600); // Inicializamos comunicación serie
BT1.begin(38400); // depende de la velocidad por defecto del módulo BT
dht.begin(); // Comenzamos el sensor DHT
pinMode(pulsador, INPUT);
pinMode(ledm, OUTPUT);
pinMode(ledt, OUTPUT);
pinMode(pindisparador, INPUT);
pinMode(13, OUTPUT);

void loop()
{
attachInterrupt( 1, subrutina, FALLING); // engancha interrupción por pin 3, saldra de de sleep y hace la subrutina
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); // pasa a dormir, saldra con la interrupcion
detachInterrupt(1); // se inhabilita la interrupcion
int direccion=0;
float dato;
int samplepoints=10;
int samplerate=1;
for (int i = 0; i<samplepoints; i++)
{
digitalWrite(ledm, HIGH);
float h = dht.readHumidity(); // Leemos la humedad relativa
float t = dht.readTemperature(); // Leemos la temperatura en grados centígrados
if (isnan(h) || isnan(t)) // Comprobamos si ha habido algún error en la lectura
{
Serial.println("Error obteniendo los datos del sensor DHT11");
return;
}
float hic = dht.computeHeatIndex(t, h, false); // Calcular el índice de calor en grados centígrados
float temp = (((analogRead(0)*500)/1023)+t)/2; // temperatura promedio del LM35 y DHT11
EEPROM.put(direccion, h); //Se escriben los bytes en direcciones de memoria contiguas.
direccion= direccion+4;
EEPROM.put(direccion, hic); //Se escriben los bytes en direcciones de memoria contiguas.
direccion= direccion+4;
44
EEPROM.put(direccion, temp); //Se escriben los bytes en direcciones de memoria contiguas.
direccion= direccion+4;
delay(100);
digitalWrite(ledm, LOW);
for (int j = 0 ; j < samplerate ; j++)
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
}
attachInterrupt( 1, subrutina, FALLING); // engancha interrupción por pin 3, saldra de de sleep y hace la subrutina
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); // pasa a dormir, saldra con la interrupcion
detachInterrupt(1); // se inhabilita la interrupcion
direccion=0;
BT1.begin(38400); // depende de la velocidad por defecto del módulo BT
digitalWrite(ledt, HIGH);
for (int i = 0; i<=samplepoints; i++)
{
float h, hic,temp;
EEPROM.get(direccion, h);
direccion= direccion+4;
EEPROM.get(direccion, hic);
direccion= direccion+4;
EEPROM.get(direccion, temp);
direccion= direccion+4;
// BT1.println("Humedad = " + String(h)) ;
// BT1.println("Indice Calor = " + String(hic)) ;
// BT1.println("Temperatura= " + String(temp)) ;
// BT1.println(".................");
BT1.println(String(h)) ;
BT1.println(String(hic)) ;
BT1.println(String(temp)) ;
Serial.flush(); // para asegurar que se vacia la cola
}
delay(1000);
digitalWrite(ledt, LOW);
}
void subrutina() // subrutina de servicio de la interrupción
{ contador++ ; // incrementa el valor del contador de pulsos
}

45
46
47