domingo, 12 de junio de 2016

Arduino uno, wifi ESP8266, sensor DS18B20 y ThingSpeak

Introducción

En esta entrada utilizaremos el sensor de temperatura (DS18B20), y lo conectaremos a la página ThingSpeak, para monitorizar en todo momento los valores de temperatura. Podríamos usar cualquier tipo de sensor, como presión, humedad, etc.... Vamos al lío.


Componentes

Protoboard
Arduino Uno
Fuente alimentación 9v 1A
Fuente alimentación protoboard 5v-3.3v
Sensor de temperatura DS18B20
Wifi ESP8266
Resistencia 4.7 k
Cables jumpers
ThingSpeak.com


Esquema




pin TX esp8266-pin 1 TX arduino
pin DX esp8266-pin 0 DX arduino
pin CH_PD esp8266-VCC protoboard fuente alimentación 3.3v
pin VCC esp8266-VCC protoboard fuente alimentación 3.3v
pin GND esp8266-GND protoboard fuente alimentación
pin GND ds18b20-GND protoboard
pin DATA ds18b20-pin 2 Arduino Uno
pin VCC ds18b20-protoboard fuente alimentación 5v
GND protoboard-GND Arduino Uno
5v protoboard-Vin Arduino Uno
Resistencia 4.7 entre pin DATA ds18b20-VCC ds18b20

Código


/*Sensor de Temperatura DS18B20 Instrucciones:
*/
  
#include <OneWire.h>
#include <DallasTemperature.h>
#define SSID "tured" //Nombre de la Red Wifi a la que nos conectamos
#define PASS "tucontraseña" //Contraseña de la Red Wifi
#define IP "184.106.153.149" // thingspeak.com
  
//Sustituir [WRITE_API_KEY] por la obtenida en thingspeak.com sin []
String GET_TEMP = "GET /update?key=0000000000000000&field1="; 
//Campo de temperatura, cambiamos los ceros por la key write

int DS18S20_Pin = 2; //pin donde conectamos sensor temperatura

OneWire ds(DS18S20_Pin);
DallasTemperature sensors(&ds);
float TemperaturaA;
long previousMillis = 0;
long interval = 300000; // 5 minutos entre lecturas

 
void setup()
{
 pinMode(13,OUTPUT);
  
 sensors.begin(); //Se inicializa sensor
 Serial.begin(74880); //Se inicializa el puerto Serial para comunicarse con el Modulo Wifi ESP8266
 Serial.setTimeout(3000); //Set el Timeout en 3 segundos para Serial.find()
 Serial.println("AT\r"); //PROBAR CON \n\r
  
 delay(2000);
  
 if(Serial.find("OK")){ //Verificar si Modulo Wifi responde
    if(!connectWiFi()){ //Conectarse a la red
       Serial.println("NO SE PUDO CONECTAR A RED WIFI");
    }
 } else {
    Serial.println("MODULO WIFI NO RESPONDE");
 }
}
  
void loop(){
 sensors.requestTemperatures();
 TemperaturaA=sensors.getTempCByIndex(0);
 char bufferTemp[8]; //Crear buffer temporal para convertir float a string
 String temperatura = dtostrf(TemperaturaA, 8, 1, bufferTemp); 
//Convertir de float a String 8 = longitud de String, 1 = numero de decimales. (e.g. 1234.5)
 
 unsigned long currentMillis = millis();
 if (currentMillis - previousMillis > interval){
  previousMillis = currentMillis;

  updateTemp(temperatura);
  digitalWrite(13,HIGH);
  delay(300);
  digitalWrite(13,LOW); 
 }  
}
  
void updateTemp(String temp){
  
 String cmd = "AT+CIPSTART=\"TCP\",\""; //Crear el comando para comenzar una conexion TCP
 cmd += IP; //IP del sitio a conectarse (thingspeak.com)
 cmd += "\",80"; //Puerto (80)
 Serial.println(cmd); //Crear conexion
 delay(2000); //Darle 2 segundos para responder
 
  
 if(Serial.find("ERROR")){
    return; //No se pudo conectar
 }
  
 temp.trim(); //Remover espacios e.g. "____30.00" >> "30.00"
  
 cmd = GET_TEMP; //Crear datos a enviar
 cmd += temp; //Agregar la temperatura leida
 cmd += "\r\n"; //Agregar caracteres de newline y Carriage return
  
 Serial.print("AT+CIPSEND="); //Indicar cuantos datos se enviaran por TCP
 Serial.println(cmd.length()); //Tamaño de los datos a enviar por TCP
 
 delay(2000);
  
 if(Serial.find(">")){
    Serial.print(cmd); //Enviar datos
 }else{
    Serial.println("AT+CIPCLOSE"); //No se pudo ejecutar, cerrar conexion TCP
 }
}
  

  
//Funcion para crear conexion Wifi. Regresa true si se conecta exitosamente, si no false.
boolean connectWiFi(){
  
 Serial.println("AT+CWMODE=3"); //Configurar Modulo Wifi ESP8266 en Modo 3 = Station + Access Point (Trasmitir y Recibir)
 delay(2000); //Darle tiempo para ejecutar comando
  
 String cmd="AT+CWJAP=\""; //
 cmd+=SSID;
 cmd+="\",\"";
 cmd+=PASS;
 cmd+="\"";
 
 //cmd = AT+CWJAP="SSID","PASS"
  
 Serial.println(cmd);
 delay(10000); //Darle 10 segundos para conectarse
  
 if(Serial.find("OK")){ 
    return true; //Conexión existosa
 }else{
    return false; //No se pudo conectar
 }
}


ThingSpeak

ThingSpeak es una web dedicada a la monitorización de sensores. Básicamente es para "el internet de las cosas".
El registro y uso es gratuito, y dispone de un montón de tutoriales, además de una extensa comunidad de usuarios. Una vez que te registres tienes acceso a un canal propio, donde conectar los sensores que desees.
Este tutorial es para empezar en ThingSpeak.

Notas

Ojo, la placa ESP8266 va a 3.3 voltios!!!!
ThingSpeak recibe un dato de temperatura cada 5 minutos, podemos cambiarlo, pero no menos de 20 segundos, que es lo que necesita la web para actualizar los datos.
Cambiar "mired", "micontraseña" y los ceros de la api key por los vuestros (ver código)

Enlaces












domingo, 5 de junio de 2016

Arduino uno y wifi ESP8266

Introducción

Vamos añadir conexión inalambrica por wifi a nuestro Arduino con la placa ESP8266. La placa ESP8266 es un dispositivo wifi bastante accesible que se puede encontrar a buen precio.

Elementos

Arduino uno
Placa wifi ESP8266
Fuente alimentación
Protoboard
Cables jumpers

Esquema


pin TX esp8266-pin 2 arduino
pin DX esp8266-pin 3 arduino
pin CH_PD esp8266-VCC protoboard fuente alimentación (ojo!!!, 3.3 voltios)
pin VCC esp8266-VCC protoboard fuente alimentación (ojo!!! 3.3 voltios)
pin GND esp8266-GND protoboard fuente alimentación
GND protoboard-GND arduino (ojo!!! esto es importante)


Código

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

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

void loop()
  {  String B= "." ;
     if (BT1.available())
         { char c = BT1.read() ;
           Serial.print(c);
         }
     if (Serial.available())
         {  char c = Serial.read();
            BT1.print(c);
         }
   }



Comandos AT

Una vez que inicia el modulo wifi abrimos la consola serial y nos saldrá una serie de caracteres seguido de "ready". Eso quiere decir que está listo para recibir comandos AT. Los comandos AT son los siguientes:

AT+ [intro] , el modulo responde OK
AT+RST , el modulo resetea
AT+CWMODE? , el modulo te dice en que modo está, si en el modo 1, 2, o 3.
AT+CWMODE=3 , ponemos el módulo en modo 3, el mio estaba en el 2 y lo dejo en el 3. En modo 3 sirve para enviar como para recibir datos.
AT+CWLAP , el módulo hace un rastreo de las conexiones wifi disponibles
AT+CWJAP="mired","micontraseña" , el modulo se conecta a la red que elijas, después de un rato responde OK y te muestra la IP a la cual se conecta.
AT+CIOBAUD=? , te muestra el rango de transmisión de datos
AT+CIOBAUD? , te muestra la velocidad actual de transmisión de datos
AT+CIOBAUD=74880 , cambiamos la velocidad de transmisión de datos a 74880 baudios si tuviera otra y siempre dentro del rango.

Más en este enlace.

Problemas que he tenido

El consumo del módulo wifi cuando arranca es muy elevado, del orden de 250 miliamperios a 300. El pin de arduino como máximo puede dar 70 miliamperios. Por eso es importante lo de la fuente de alimentación que nos va ha dar energía suficiente para poder arrancar el módulo. También hay conectar las masas de la fuente de alimentación y la placa arduino, ya que al no estar las masas conectadas, no sólo no va a funcionar el módulo, sino que podemos chamuscar algo.

La velocidad de transmisión de datos debe ser la misma que la velocidad del puerto serie, en caso contrario se envían y reciben caracteres distintos de los que se desean, en consecuencia se producen errores de lecturas.
Como ejemplo tenía la velocidad de trasmisión a 115200 baudios y la del puerto serie a 74880,  no conectaba con mi red wifi. Arduino uno no va muy bien con la velocidad del puerto serie a 115200 baudios, por tanto para que la información me llegara lo mejor posible cambié la velocidad de transmisión de datos a 74880 baudios y la del puerto serie a la misma.

Si iniciamos el modulo wifi y abrimos la consola serial y no nos aparece nada, desde el interruptor de la fuente de alimentación, apagamos y encendemos de nuevo.

Notas

El módulo wifi funciona a 3.3 voltios, ¡¡¡NO OLVIDAR!!!, 
Hay que ir probando las velocidades de trasmisión hasta dar con la que mejor se ajusta.
Conectar la masa de la fuente con la del arduino

Enlaces








domingo, 6 de marzo de 2016

Programador horario

INTRODUCCIÓN

En la entrada anterior vimos como establecer la hora en el RTC y que no se pierda por un corte de electricidad. En esta entrada vamos hacer un programador horario, bien para encender una luz, dispositivo electrónico o electrodoméstico.


ELEMENTOS

Arduino uno o compatible
RTC DS3231 (previamente programado, entrada anterior)
Led


ESQUEMA

VCC RTC-5V Arduino
GND RTC-GND Arduino
SDA RTC-A4 Arduino
SCL RTC-A5 Arduino
Patilla larga Led-Pin 13 Arduino
Patilla corta Led-GND Arduino

¡Ojo, en caso de cambiar el pin 13 por otro hay que poner una resistencia de 220 ­ohmnios!





CODIGO


#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h> 

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

  setSyncProvider(RTC.get);      // Vamos a usar el RTC
  setSyncInterval(86400000);        // Sincronizo una vez cada 24 horas

  pinMode( 13, OUTPUT) ;
  digitalWrite(13 , LOW) ; // Apagamos el LED al empezar

  if (timeStatus() != timeSet){
    Serial.println("Fallo al sincronizar con el RTC");
  }else{
    Serial.println("El RTC se ha sincronizado con el sistema");
  }
}

void loop(){
  //Muestro por el puerto serie la hora
  Serial.print("Son las: ");
  Serial.println(String(hour()) + ": " + String(minute()));
  //comprobamos si es la hora
  if (esHora()) {
    //Si es la hora, mostramos un mensaje indicándolo por el puerto serie
    Serial.print("Es hora!!");
    digitalWrite(13 , HIGH) ;
    delay(1000);
  } else {
    //Muestro por el puerto serie la hora
    digitalWrite(13 , LOW);
    Serial.print("Son las: ");
    Serial.println(String(hour()) + ": " + String(minute()));
    //Si no es la hora, mostramos un mensaje indicándolo por el puerto serie tambien
    Serial.print("No es hora");
    delay(1000);          
  }
}

boolean  esHora() {
  //Defino horas Inicio a las 19:30 y termina a las 21:00
  byte horaInicio = 19;
  byte minutoInicio = 30;
  byte horaFin = 21;
  byte minutoFin = 00;

  //Para hacer las comparaciones de cuando empezar y cuando terminar, lo paso todo a minutos.

  int momentoInicio = (horaInicio * 60) + minutoInicio;
  int momentoFin = (horaFin * 60) + minutoFin;
  int momentoAhora = (hour() * 60) + minute();

  //Esto es que si hemos pasado o estamos en el momento de inicio , pero antes del momento del fin…
  if ((momentoInicio <= momentoAhora) && (momentoAhora < momentoFin)) {
    //devolver "Cierto" en esta función "esHora"
    return true;
  } else {
    //devolver "Falso" en esta función "esHora"
    return false;
  }
}


NOTAS

Usamos el RTC para sincronizar la hora con la placa Arduino a través de la librería Time.
Cada 24 horas se sincronizan la placa y el RTC
La función booleana nos permite establecer un rango horario, así evitamos que ante un pequeño corte de electricidad durante el rango horario y volver, el sistema no altera su funcionamiento.
El led es el ejemplo, podemos cambiarlo por lo que se desee.


Código:

programador horario

Librerías:


Fuente:

Foro arduino

domingo, 21 de febrero de 2016

Poner reloj rtc DS3231 en hora y mostrar en pantalla lcd 1602

Introducción

Cuando queremos usar reloj rtc para arduino tenemos la desventaja que cuando desconectamos la alimentación del reloj se nos borra la hora aunque éste lleve pilas. Si lo aplicamos a cualquier proyecto que pueda necesitar calendario y se nos corta la electricidad nos causa un problema.
Bién, con los códigos que vamos a usar eso no va a pasar. Si se nos corta la alimentación, el reloj sigue marcando internamente la hora actual, siempre que lleve pila.

Este proyecto consta de dos partes, una poner en hora el rtc, y otra visualizar la hora y fecha en una pantalla lcd de 16x02.



Elementos

Placa Arduino Uno o compatible
Reloj rtc DS3231 con pila cr2032 de 3v
Pantalla LCD 1602
Potenciómetro 50k
Protoboard
Cables jumpers
Fuente alimentación



Reloj en hora

Esquema:

SDA-A4
SCL-A5
GND-GND
VCC-5V



Ponemos el rtc en hora con el siguiente código:


#include "Wire.h" 
#define DS1307_I2C_ADDRESS 0x68
 
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}
 
void setDateDs1307(
byte second,        // 0-59
byte minute,        // 0-59
byte hour,          // 1-23
byte dayOfWeek,     // 1-7 1=Lunes, 7=Domingo
byte dayOfMonth,    // 1-28/29/30/31
byte month,         // 1-12
byte year           // 0-99
)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(dayOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}
 
void setup()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  Wire.begin();
  pinMode(13, OUTPUT);
 
  // Cambiamos los parámetros como queramos
  // Lo mejor es poner la hora del script 30 segundos antes que es lo que tarda el ordenador aproximadamente en compilar el programa
  // Sólo es necesario compilar el script una vez
  // El formato es de 24 horas
  // Días de la semana lunes es 1 a domingo que es 7
  // El formato de año son los dos últimos dígitos del año
  //
  // Una vez cargado el programa el led 13 parpadeará cada segundo, no debemos resetear.
 
  second = 0;
  minute = 06;
  hour = 10;
  dayOfWeek = 7;
  dayOfMonth = 24;
  month = 1;
  year = 16;
  setDateDs1307(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
  //*/
}
 
void loop()
{
  digitalWrite(13, HIGH);   
  delay(1000);               
  digitalWrite(13, LOW);    
  delay(1000);
}

El led 13 de la placa arduino uno parpadeará cada segundo, indicando que está el programa cargado en el rtc.

Visualización en pantalla lcd 1602

Esquema conexión:

pin 1 lcd VSS-GND
pin 2 lcd VDD-5V
pin 15 lcd A-5V
pin 16 lcd K-GND

pin 1 potenciómetro-GND
pin 2 potenciómetro-pin 3 lcd VO
pin 3 potenciómetro-5V

pin 4 lcd RS-pin 7 arduino
pin 5 lcd RW-GND
pin 6 lcd E-pin8 arduino
pin 11 lcd D4-pin 9 arduino
pin 12 lcd D5-pin 10 arduino
pin 13 lcd D6-pin 11 arduino
pin 14 lcd D7-pin 12 arduino

pin rtc VCC-5V
pin rtc GND-GND
pin rtc SDA-pin A4 arduino
pin rtc SCL-pin A5 arduino





Código:


#include "Wire.h"
#include <LiquidCrystal.h>
#define DS1307_I2C_ADDRESS 0x68
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
 
byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}
 
void getDateDs1307(byte *second,byte *minute,byte *hour,byte *dayOfWeek,byte *dayOfMonth,byte *month,byte *year)
{
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(0);
  Wire.endTransmission();
 
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
 
  *second     = bcdToDec(Wire.read() & 0x7f);
  *minute     = bcdToDec(Wire.read());
  *hour       = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek  = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month      = bcdToDec(Wire.read());
  *year       = bcdToDec(Wire.read());
}
 
 
void setup()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  Wire.begin();
  
  lcd.begin(16, 2);
}
 
void loop()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  String s, m, d, mth, h;
   
  getDateDs1307(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
 
  if (second < 10) { s = "0" + String(second); } else { s = String(second); }
  if (minute < 10) { m = "0" + String(minute); } else { m = String(minute); }
  h = String(hour);
  if (dayOfMonth < 10) { d = "0" + String(dayOfMonth); } else { d = String(dayOfMonth); }
  if (month < 10) { mth = "0" + String(month); } else { mth = String(month); }
   
  char* days[] = { "NA", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
   
  lcd.clear();
  
  lcd.setCursor(4,0);
  
  lcd.print(h + ":" + m + ":" + s);
  
  lcd.setCursor(1,1);
  
  lcd.print(String(days[dayOfWeek]) + " " + d + "/" + mth + "/20" + year);
  delay(1000); // Esperamos un segundo
}

Notas:
Antes de cargar el primer código debemos poner la hora y fecha actual en ese código.
Girar potenciómetro hasta que aparezca hora y fecha.
Podemos interrumpir la alimentación todo lo que queramos, una vez establecida dará la hora actual.

Códigos:

Poner en hora rtc
Visualizacion hora rtc lcd 1602

Librerías:
La librería wire.h viene incluida en el ide de arduino
LiquidCrystal.zip

Fuentes:
Tutorial 1
Tutorial 2

Presentación

Aficionado a la electrónica, informática y programación, uso este blog a modo de diario, para mis proyectos de Arduino. Las entradas de este blog no son tutoriales (existen muchos y muy buenos), es anotar cada uno de los pasos de mis proyectos, al mismo tiempo conservarlo, y divulgarlo para que el que lo desee los pueda modificar, mejorar y aplicar a los suyos.