ESP12E | Arduino | Estación meteorológica Wifi solar + Thingspeak + tarjeta SD + PCB
Buenas a todos! os traigo la segunda versión de la estación meteorológica WIFI con Arduino, mucho más simple, eficiente, y con prestaciones mejoradas respecto a la versión anterior. Incluye todo lo bueno, como sincronización con ThingSpeak vía WIFI, e incluye algunas novedades muy interesantes:
- Sustituimos la placa Arduino por un ESP12E, que se programa con el mismo lenguaje e IDE de Arduino, y que incorpora todo lo necesario para conectarse a la red wifi de nuestro hogar de forma sencilla. De esta forma nos ahorramos el engorro que suponía cargar software en el ESP266-01.
- Las lecturas de temperatura, humedad y presión atmosférica se harán con un único sensor, un BME280.
- Preparado para funcionar con batería, cargador solar y placa solar. Se ha reducido el consumo de forma considerable respecto a la versión anterior, ¡y ahora puede funcionar durante 1 mes sin carga!
- Posibilidad de guardar los datos en una tarjeta SD.
- Toda la electrónica ha sido diseña con KiCad, y las placas (PCB) fabricadas de forma profesional. Esto me permite ahorrar mucho tiempo de montaje de los componentes, y también bastante dinero.
Algunas de mis gráficas
Lista materiales
Componente | Referencia esquema | Comprar |
ESP12E | U2 | Comprar en Amazon |
Lector tarjeta SD | J5 | Comprar en Amazon |
Batería LiPo 1S 2600mAh | BT1 | Comprar en RS |
Holder para la batería | BT1 | Comprar en Amazon |
Cargador TP4056 | U1 | Comprar en Amazon |
DCDC step-up 5V | J6 | Comprar en Amazon |
Sensor BME280 | J3 | Comprar en Amazon |
Diodo schottky 1A 1N5817 | D2 | Comprar en Amazon |
Conector atornillado | J1 | Comprar en Amazon |
MOSFET FDP7030BL | Q1 | Comprar en Amazon |
Kit resistencias | R1, R2, R3, R4 | Comprar en Amazon |
Jumpers | JP3 | Comprar en Amazon |
Interruptor 1A | J7 | Comprar en Amazon |
Conector JST B2B-PH-K-S (Opcional) | J2 | Comprar en Amazon |
Diseño hardware
1. Etapa de entrada
La etapa de entrada se compone de dos conectores de entrada (J1 y J2), un diodo Schottky (D2), el cargador de baterías TP4056 (U1), un interruptor para aislar la batería (J7) y desconectar el sistema, y la propia batería (BT1).
He utilizado dos conectores de entrada, uno para montar un conector atornillado y poder utilizar cualquier placa solar, y un JST B2B-PH-K-S(LF)(SN) hembra muy típico en placas solares. Este último es mas difícil de conseguir en tiendas como Amazon (hay que recurrir a tiendas especializadas como RS o Farnell), y solo sirve para placas solares que monten la versión macho del conector, por lo que recomendaría tirar por la vía del conector atornillado. Como veis, el conector atornillado tiene 3 agujeros en vez de dos. La razón principal es poder utilizar conectores de paso 2.54mm o 5mm.
La batería que he utilizado es una 18650 de 2600mA. Recomiendo utilizar el holder o soporte modelo 1043. Es el que mejor encaja, y queda como un guante. De todas formas, no es obligatorio y podéis utilizar la mayoría de las disponibles para baterías 18650 como veremos mas abajo.
Las etiquetas GND y Vbat indican el punto de conexión con los demás componentes.
La ubicación de estos componentes en el PCB es la siguiente.
Mucho ojo a la hora de montar el conector atornillado (J1). Tiene 3 agujeros para poder montar conectores de 2.54mm y 5mm. En caso de utilizar la versión de 2.54mm, conectarlo en los pines de la derecha, utilizando las entradas ‘+’ y ‘-‘.
El holder o soporte para la batería que he utilizado es el 1043. Se puede encontrar en tiendas como Ebay, aunque es un poco caro. De todas formas, la huella de la batería tiene un orificio central que permite atornillar cualquier ‘holder‘. En caso de utilizar un holder diferente al 1043, podéis utilizar los pines laterales marcados para soldar los cables de la batería:
Os dejo un par de imágenes de los soporte para que veías la diferencia:
Holder barato y fácil de encontrar. Necesario soldar los cables al PCB.
Holder 1043 recomendado.
2. ESP12E
La placa ESP12E es básicamente un Arduino Nano que incorpora un módulo WIFI, y se programa en el mismo lenguaje y con el mismo IDE que Arduino. Este nos permite programar todo el código en una sola placa, ya que tanto la lectura de temperatura, presión atmosférica y humedad, como la conexión a la red WIFI la programaremos aquí.
Las entradas/salidas de la placa ESP12E que necesitaremos se muestran en la siguiente imagen.
La lectura de la tensión de batería se hace a través de un divisor resistivo, ya que la entrada analógica solo admite tensiones de entrada de hasta 1V (aunque la propia placa ESP12E ya incluye un divisor resistivo, y podríamos subir hasta 3.3V de entrada).
Otro punto a destacar el la conexión de la D0 a RST a través de un jumper. Para salir del modo bajo consumo, el pin D0 tiene que estar conectado al pin de RST. La razón de utilizar un jumper intermedio es poder interrumpir esta conexión debido a que puede dar problemas a la hora de cargar SW. De esta forma, podremos quitar el jumper de forma sencilla en caso de haber problemas con la carga y volver a ponerlo al finalizar.
La ubicación de estos componentes en el PCB es la siguiente:
3. BME280
Podemos utilizar tanto el sensor BME280 como el BMP280. Este último no cuenta con lecturas de humedad, por lo que recomiendo utilizar el primero:
Como veis, he dejado espacio para montar un sensor u el otro. La conexión es la misma, pero fijaos en que no lo ponéis al revés:
4. Lector de tarjetas SD
Esta nueva versión incorpora lector de tarjetas SD. Por mencionar algo, he utilizado un MOSEFET FDP7030BL (Q1) para conector el módulo SD solo cuando vaya a utilizarse, manteniéndolo desconectado el resto del tiempo, ya que es energéticamente muy exigente. He añadido también el jumper JP3 por si no queremos montar el MOSFET y queremos tener el módulo siempre conectado, aunque esta opción es recomendable solo si pensamos tener el quipo permanentemente conectado a la red eléctrica vía USB.
La ubicación de estos componentes en el PCB es la siguiente:
5. Otros
He añadido una salida I2C por si queremos conectar un pequeño OLED para visualizar los datos en una pantalla. También he añadido un led y su correspondiente resistencia por si quisiéramos visualizar alguna alarma.
Consumos
En modo bajo- consumo, y sin tarjeta SD, el sistema consumos 3.2mA
Funcionamiento
Cada 30 minutos, el sistema saldrá del modo ultra-bajo consumo, ejecutando las siguientes acciones:
- Salida del modo bajo consumo y encendido del sistema.
- Hacer lecturas del sensor BME280 para obtener registros de temperatura, humedad y presión atmosférica.
- Leer tensión de batería. En caso de que esté muy baja, el tiempo entre encendidos aumentará a una hora.
- Conectarse a la red WIFI y sincronizar los datos con ThingsPeak.com.
- Cerrar el MOSFET que activa la tarjeta SD, y guardar los registros en la tarjeta.
- Volver al modo de bajo consumo.
Software
#include <ThingSpeak.h>
#include <ESP8266WiFi.h>
#include <BME280I2C.h>
#include <Wire.h>
#include <ESP8266WiFi.h>
#include <SPI.h>
#include <SD.h>
int visualizar = 1;
bool SD_ON = false;
#define SECRET_SSID "NOMBRE DE TU RED" // replace MySSID with your WiFi network name
#define SECRET_PASS "CONTRASEÑA" // replace MyPassword with your WiFi password
#define SECRET_CH_ID 1149372 // replace 0000000 with your channel number
#define SECRET_WRITE_APIKEY "8QXPSHGSI1HHNTLD" // replace XYZ with your channel write API Key
char ssid[] = SECRET_SSID; // your network SSID (name)
char pass[] = SECRET_PASS; // your network password
int keyIndex = 0; // your network key Index number (needed only for WEP)
WiFiClient client;
unsigned long myChannelNumber = SECRET_CH_ID;
const char * myWriteAPIKey = SECRET_WRITE_APIKEY;
String myStatus = "";
BME280I2C bme;
float temp, hum, pres, tempUnit, presUnit, pres_med, temp_med, hum_med;
int cont_Things, WIFI = 1;
long SLEEP_MINUTES;
float tensionVbat_suma, tension5V_suma, valorVbat, tensionVbat, tensionVbat_media;
int wifi_intento;
void setup() {
// LED PARPADEO
pinMode(LED_BUILTIN, OUTPUT); // LED
Serial.begin(115200); // Initialize serial
Wire.begin();
delay(100);
pinMode(0, OUTPUT);
Serial.println("INIT BME280");
while (!bme.begin());
Serial.println("BME280 OK");
for (int i = 0; i <= 20; i++) {
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
bme.read(pres, temp, hum, tempUnit, presUnit);
}
WiFi.mode(WIFI_STA);
ThingSpeak.begin(client); // Initialize ThingSpeak
delay(100);
}
void loop() {
LED_on();
BME280();
leer_Vbat();
WIFI_THINGSPEAK();
escribir_SD();
LED_on();
Serial.println("SLEEP");
ESP.deepSleep(1e6 * 60 * SLEEP_MINUTES, WAKE_RFCAL);
}
void leer_Vbat() {
tensionVbat_suma = 0;
tension5V_suma = 0;
for (int j = 0; j < 10; j++) {
valorVbat = analogRead(A0);
tensionVbat = 6 * 3.3 * valorVbat / 1023;
tensionVbat_suma = tensionVbat_suma + tensionVbat;
}
tensionVbat_media = tensionVbat_suma / 10;
if (tensionVbat_media > 3.6)SLEEP_MINUTES = 30;
else SLEEP_MINUTES = 60;
if (visualizar == 1) {
Serial.print("sensor = ");
Serial.print(valorVbat);
Serial.print("\t output = ");
Serial.println(tensionVbat_media);
}
}
void WIFI_THINGSPEAK() {
if (WiFi.status() != WL_CONNECTED) {
for (wifi_intento = 0; wifi_intento < 2; wifi_intento++) {
WiFi.begin(ssid, pass);
delay(5000);
if (WiFi.status() != WL_CONNECTED) {
Serial.print("Attempting to connect: ");
Serial.println(wifi_intento);
WIFI = 0;
}
else {
Serial.println("\nConnected.");
WIFI = 1;
break;
}
}
}
if (WIFI == 1) {
pres_med = 0;
temp_med = 0;
hum_med = 0;
ThingSpeak.setField(1, pres);
ThingSpeak.setField(2, temp);
ThingSpeak.setField(3, hum);
ThingSpeak.setField(4, tensionVbat_media);
ThingSpeak.setField(5, wifi_intento);
ThingSpeak.setField(6, SLEEP_MINUTES);
for (int t = 0; t < 2; t++) {
int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
if (x == 200) {
Serial.println("Channel update successful.");
break;
}
else {
Serial.println("Problem updating channel. HTTP error code " + String(x));
delay(5000);
}
}
}
}
void escribir_SD() {
if (SD_ON == true) {
digitalWrite(0, HIGH);
delay(20);
if (SD.begin(8)) {
Serial.println("SD activada con exito");
File dataFile = SD.open("datalog.txt", FILE_WRITE);
if (dataFile) {
dataFile.print(pres);
dataFile.print(",");
dataFile.print(temp);
dataFile.print(",");
dataFile.print(hum);
dataFile.print(",");
dataFile.print(tensionVbat_media);
dataFile.print(",");
dataFile.println(wifi_intento);
dataFile.close();
Serial.println("Datos guardados en SD");
}
else Serial.println("ERROR abriendo datalog.txt");
}
else Serial.println("ERROR al iniciar la SD");
digitalWrite(0, LOW);
}
}
void BME280() {
for (int j = 0; j < 20; j++) {
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
BME280::PresUnit presUnit(BME280::PresUnit_Pa);
bme.read(pres, temp, hum, tempUnit, presUnit);
pres = pres * 0.00750062;
pres_med = pres_med + pres;
temp_med = temp_med + temp;
hum_med = hum_med + hum;
delay(20);
}
pres = pres_med / 20;
temp = temp_med / 20;
hum = hum_med / 20;
Serial.print(pres);
Serial.print("\t");
Serial.print(temp);
Serial.print("\t");
Serial.println(hum);
}
void LED_on() {
digitalWrite(LED_BUILTIN, LOW);
delay(50);
digitalWrite(LED_BUILTIN, HIGH);
}
Archivos de fabricación
Podéis descarar los archivos de aquí:
Una vez descargado el .zip, solo tenéis que arrastrar el fichero completo (sin descomprimir) a la web de JLCPCB.com:
⇒ Ir a JLCPCB.com
⇒ Ir a ‘QUOTE NOW’
⇒ Ir a ‘Add you gerber file‘ y cargad el .zip que habéis descargado (sin descomprimir).
⇒ La propia web descomprimirá el archivo y generara una previsualización de la placa con las dimensiones de esta. Nada mas procesar el fichero, os saldrá también el precio de compra para 5 unidades (pedido mínimo). Las 5 placas os costarán unos 1.7€ (sin gastos de envío):
⇒ Seleccionad el color que queráis (el negro es el mas bonito), dejando los demás parámetros como vienen por defecto. Añadidlo a la cesta, y completar el pedido con vuestros datos.
NOTA IMPORTANTE: solo recibiréis el PCB ‘desnudo’, sin ningún componente montado. Estos componentes los tendréis que comprar y montar vosotros mismos.
También te puede interesar
Índice ‘Drone con Arduino’
- Conceptos generales sobre drones.
- Material necesario y montaje de los componentes hardware.
- Mando RC y receptor. Programación en Arduino (código).
- MPU6050 y su programación en Arduino (código).
- Batería LiPo (código).
- Control de estabilidad y PID.
- Motores, ESC y su programación en Arduino (código).
- Calibración de hélices y motores (código).
- Software completo y esquema detallado (código).
- Probando el Software completo antes de volar.
- Como leer variables de Arduino en Matlab (código).
Cuál es el valor de la resistencias? ( R1,R2,R3yR4)