First of all, thank you … The program is OK itselfe, the mistake comes up when I used “Blynk” …
The code is:
#include <ESP8266_Lib.h>
#include <Blynk.h>
#include <DHTesp.h>
#include <ThingSpeak.h>
#include <ESP8266WiFi.h>
#include <Adafruit_ST7735.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#include <SPI.h>
#include <SimpleTimer.h>
// Datos red WIFI
const char* ssid = "xxxxxxxxxx"; //Nombre de la red WiFi a la que nos vamos a conectar
const char* password = "xxxxxxxxxxx"; //Contrasena de la red WiFi a la que nos vamos a conectar
WiFiClient client;
// Token de Blynk para este proyecto
char Token[] = "xxxxx";
SimpleTimer timer; //Instancio objeto SimpleTimer
//Datos canal ThingSpeak
unsigned long myChannelNumber = xxxxx;
char* myReadAPIKey = "xxxxxxx";
char* myWriteAPIKey = "xxxxxxxx";
// Variables y constantes iniciales del TFT.
#define TFT_CS D8
#define TFT_RST D4
#define TFT_DC D3
#define TFT_SCLK D5
#define TFT_MOSI D7
//Instancia objeto Adafruit_ST7735 para pantalla TFT
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// Variables y constantes iniciales del control de calefacción
#define pinDHT22 D2 // Puerto D2 entrada de datos del sensor DHT22
#define Control_CAL D1 // Puerto D1 salida relé control calefacción
bool Mem_CAL; // Memoria del estado anterior de Control_CAL
int Prog_CAL=0; // 1: Calefacción Programada (Arrancará calefacción en función del Setpoint) / 0: Calefacción NO programada (Calefacción OFF siempre)
int Estado_CAL=0; // estado de la calefacción para su control
int Setpoint;
#define DHTTYPE DHT22 // DHT 22
DHTesp dht; // instancio un objeto DHT
// Variables y constantes iniciales del control de la alarma.
#define sensor_MOV D6 // D6 sensor movimiento HC-SR501
volatile int Estado_ALM=0; // Estado de la alarma, se activa por interrupción
int Prog_ALM=0; // 1: Alarma Programada (puede estar activo o inactiva, sensor en funcionamiento) / 0: NO Programada (No se activa nunca la alarma)
// Modo SLEEP cuando no estan programadas la calefacción o la alarma
#define SLEEP_TIME 900 // Tiempo en seg que el NODEMCU ahorra energia 900=15 min. Si no esta programada alarma ni calefacción 15 min en ahorro de energia.
// Cada 15 minutos activa el NODEMCU y corre el programa para ver si se han programada la alarma o la calefacción
bool dormido; // Variable para controlar el Modo Sleep
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
//Conexión a Red WIFI
WiFi.mode(WIFI_STA); //Establece el módulo como cliente wifi
WiFi.disconnect(); //Se desconecta de cualquier WiFi conectado
delay(100);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { // wait for WiFi
delay(500);
}
//Inicializo Blynk
Blynk.begin(Token, ssid, password);
//Inicializo ThingSpeak para almacenar los datos
ThingSpeak.begin(client);
//Inicializo DHT22
dht.setup(pinDHT22);
//Se configuran pines del NODEMCU
pinMode(Control_CAL,OUTPUT); // D1 salida digital control rele calefaccion
pinMode(sensor_MOV,INPUT); // D6 entrada digital sensor de movimiento
pinMode(pinDHT22,INPUT); // D2 entrada digital sensor de temperatura
//Inicializo TFT / Función propia
Inicio_TFT();
/* Código del programa a ejecutar tras salir del modo SLEEP y calefacción / alarma NO PROGRAMADA
Solo se almacenan los datos de temperatura / humedad y estado de la calefacción / alarma */
Mem_CAL = false; // inicializo variable Mem_CAL (calefacción estado anterior)
dormido =false; // inicializo variable de control Sleep
// Recojo la configuración de control y el estado de las variables de Blynk
// Setpoint de temperatura
BLYNK_WRITE(V4)
{
Setpoint = param.asInt();
}
// Alarma Programada-->Prog_ALM
BLYNK_WRITE(V0)
{
Prog_ALM = = param.asInt();
}
// Calefacción Programada-->Prog_CAL
BLYNK_WRITE(V1)
{
Prog_CAL = = param.asInt();
}
// Estadp Alarma-->Estado_ALM
BLYNK_WRITE(V7)
{
Prog_CAL = = param.asInt();
}
// Estadp Calefacción-->Estado_CAL
BLYNK_WRITE(V8)
{
Prog_ALM = = param.asInt();
}
//Recojo datos de temperatura y humedad del sensor
delay(dht.getMinimumSamplingPeriod());
float h = dht.getHumidity();
float t = dht.getTemperature();
if (dht.getStatusString()=="OK"){ // Estado sensor DHT22 si es OK
// Cargo datos de temperatura y humedad para almacenarlos en ThinkSpeak
ThingSpeak.setField(1,t);
ThingSpeak.setField(3,h);
//// Cargo datos de temperatura y humedad en BLYNK
Blynk.virtualWrite(V5, h);
Blynk.virtualWrite(V6, t);
}
if (Prog_CAL == 0){ // CALEFACCION NO-PROGRAMADA --> CALEFACCION OFF
digitalWrite( Control_CAL, LOW);
Estado_CAL=0;
Blynk.virtualWrite(V8, Estado_CAL);
}
//Se programan interrupciones o no dependiendo de la programacion de la alarma
if (Prog_ALM == 1){
attachInterrupt(sensor_MOV,Interrup_ALARMA,RISING);
Estado_ALM=0;
Blynk.virtualWrite(V7, Estado_ALM);
}
if (Prog_ALM == 0){
detachInterrupt(sensor_MOV);
Estado_ALM=0;
Blynk.virtualWrite(V7, Estado_ALM);
}
ThingSpeak.setField(5,Estado_CAL);
ThingSpeak.setField(7,Estado_ALM);
//Almaceno los datos de control y variables en ThingSpeak
ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
//Muestro los datos en TFT
TFT_TA(t);
TFT_HUM(h);
TFT_SP(Setpoint);
TFT_PROG_CAL(Prog_CAL);
TFT_PROG_ALM(Prog_ALM);
TFT_EST_ALM(Estado_ALM);
// definimos una función que va a ser llamada cada 2 minutos cuando solo esta programada la alarma
if ((Prog_ALM == 1)&&(Prog_CAL == 0)){
timer.setInterval(120000L,Control_ALARMA);
}
//Calefacción programada
if (Prog_CAL == 1){ //
//Se programan interrupciones o no dependiendo de la programacion de la alarma
if (Prog_ALM == 1){
attachInterrupt(sensor_MOV,Interrup_ALARMA,RISING);
timer.setInterval(120000L,Control_TEMP); // cada 2 minutos
}
if (Prog_ALM == 0){
detachInterrupt(sensor_MOV);
timer.setInterval(300000L,Control_TEMP); // cada 5 minutos
}
}// fin if (Prog_CAL == 1)
//Muestro los datos en TFT
TFT_TA(t);
TFT_HUM(h);
TFT_SP(Setpoint);
TFT_PROG_CAL(Prog_CAL);
TFT_PROG_ALM(Prog_ALM);
TFT_EST_ALM(Estado_ALM);
Blynk.virtualWrite(V7, Estado_ALM);
Blynk.virtualWrite(V8, Estado_CAL);
Blynk.virtualWrite(V0, Prog_ALM);
Blynk.virtualWrite(V1, Prog_CAL);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
//Si no está programado el arranque de la calefacción o la alarma entra en modo SLEEP
if ((millis() >= 10000) && (Prog_CAL == 0)&& (Prog_ALM == 0)) { // 10 segundos desde el reset, el dispositivo pasa a modo sleep y para que ThinkSpeak permita grabar
dormido =true;
digitalWrite( Control_CAL, LOW);
Estado_CAL=0;
Estado_ALM=0;
//Muestro los datos en el TFT
TFT_PROG_CAL(Prog_CAL);
TFT_PROG_ALM(Prog_ALM);
TFT_SLEEP();
//NODEMCU en modo ahorro de energia
ESP.deepSleep(SLEEP_TIME * 1000000, WAKE_RF_DEFAULT); // SLEEP_TIME -> tiempo en segundos que el NODEMCU estará dormido (15 minutos)
}
Blynk.run(); // iniciamos Blynk
timer.run(); // iniciamos SimpleTimer
}
//////////////////////////////////// FUNCIONES ///////////////////////////////////////////////////////////////////////////////////////////////////
//Función que se ejecuta cuando se produce una interrupción en el pin D6, sensor de alarma
void Interrup_ALARMA(){
Estado_ALM = 1;
TFT_EST_ALM(Estado_ALM);
}
//Función que se ejecuta cuando solo esta programada la alarma
void Control_ALARMA(){
// Salida y estado calefacción a 0
digitalWrite( Control_CAL, LOW);
Estado_CAL=0;
ThingSpeak.setField(5,Estado_CAL);
ThingSpeak.setField(7,Estado_ALM); // Cuando se produce una interrupción en el pin D6, sensor de alarma Estado_ALM=1
ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
Blynk.virtualWrite(V7, Estado_ALM);
Blynk.virtualWrite(V8, Estado_CAL);
//Muestro los datos en TFT
TFT_PROG_CAL(Prog_CAL);
TFT_PROG_ALM(Prog_ALM);
TFT_EST_ALM(Estado_ALM);
}
//Función que se ejecuta cuado esta programada la calefacción
void Control_TEMP(){
float h = dht.getHumidity();
float t = dht.getTemperature();
if (dht.getStatusString()=="OK"){ // Estado sensor DHT22 si es OK
float Setpoint_alto= Setpoint+1;
float Setpoint_bajo= Setpoint-0.5;
if ((t<=Setpoint_bajo)&&(!(Mem_CAL))){ // T<SETPOINT_BAJO Y CALEF. NO Mem_CAL --> CALEFACCION OFF
digitalWrite( Control_CAL, HIGH);
Estado_CAL=1;
}
if ((t<=Setpoint_alto)&&(t>Setpoint_bajo)&&(!(Mem_CAL))){ // SETPOINT_BAJO<T<=SETPOINT_ALTO Y CALEF. NO Mem_CAL --> CALEFACCION OFF
digitalWrite( Control_CAL, HIGH);
Estado_CAL=1;
}
if ((t>Setpoint_alto)){ // T>SETPOINT_ALTO --> CALEFACCION OFF
digitalWrite( Control_CAL, LOW);
Mem_CAL=true;
Estado_CAL=0;
}
if ((t<=Setpoint_alto)&&(t>=Setpoint_bajo)&&(Estado_CAL==0)&&(Mem_CAL)){ // SETPOINT_BAJO<=T<=SETPOINT_ALTO Y CALEFACCION OFF Y CALEF.Mem_CAL --> CALEFACCION ON
digitalWrite( Control_CAL, LOW);
Estado_CAL=0;
}
if ((t<Setpoint_bajo)&&(Estado_CAL==0)&&(Mem_CAL)){ // T<SETPOINT_BAJO Y CALEFACCION OFF Y CALEF.Mem_CAL --> CALEFACCION ON
digitalWrite( Control_CAL, HIGH);
Mem_CAL=false;
Estado_CAL=1;
}
ThingSpeak.setField(5,Estado_CAL);
}// fin if Estado sensor DHT22 si es OK
ThingSpeak.setField(7,Estado_ALM);
ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
Blynk.virtualWrite(V7, Estado_ALM);
Blynk.virtualWrite(V8, Estado_CAL);
//Muestro los datos en TFT
TFT_TA(t);
TFT_HUM(h);
TFT_SP(Setpoint);
TFT_PROG_CAL(Prog_CAL);
TFT_PROG_ALM(Prog_ALM);
TFT_EST_ALM(Estado_ALM);
}
// Formateo el TFT para el proyecto
void Inicio_TFT(){
tft.initR(INITR_BLACKTAB); // Inicializa
tft.setTextSize(1); //
tft.fillScreen(ST7735_BLACK);
tft.setRotation(1); // Al rotar TFT pasa a ser columna, fila
tft.setCursor(2,10); // cursor columna 2 fila 10
tft.setTextColor(ST7735_BLUE);
tft.print("CALEF_PROG =");
tft.setCursor(112,5); // cursor columna 112 fila 5
tft.setTextColor(ST7735_RED);
tft.print("HUMEDAD");
tft.setCursor(112,15); // cursor columna 112 fila 15
tft.setTextColor(ST7735_RED);
tft.print("AMBIENTE");
tft.drawFastHLine(105, 25, tft.width(), ST7735_GREEN);
tft.drawFastVLine(105, 0, 45, ST7735_GREEN);
tft.setCursor(2,30); // cursor columna 2 fila 30
tft.setTextColor(ST7735_BLUE);
tft.print("ALARM_PROG =");
tft.drawFastHLine(0, 45, tft.width(), ST7735_GREEN);
tft.setCursor(4,52); // cursor columna 4 fila 52
tft.setTextColor(ST7735_RED);
tft.print("SETPOINT");
tft.setCursor(75,52); // cursor columna 75 fila 52
tft.print("TEMP. AMBIENTE");
tft.drawFastHLine(0, 65, tft.width(), ST7735_GREEN);
tft.drawFastVLine(65, 45, 55, ST7735_GREEN);
tft.drawFastHLine(0, 100, tft.width(), ST7735_GREEN);
tft.setTextSize(1);
tft.setCursor(4,105); // cursor columna 2 fila 105
tft.setTextColor(ST7735_RED);
tft.print("ESTADO");
tft.setCursor(4,115); // cursor columna 4 fila 115
tft.print("ALARMA");
tft.drawFastVLine(148, 100,40, ST7735_GREEN);
TFT_BATERIA(); // Funcion que muestra el estado de la bateria
}
// Muestra el SP en TFT
void TFT_SP(float SP){
tft.fillRect(0, 70, 65, 25, ST7735_BLACK);
tft.setTextSize(2);
tft.setCursor(3,75); // cursor columna 3 fila 75
tft.setTextColor(ST7735_WHITE);
tft.print(SP);
}
// Muestra la temperatura ambiente en TFT
void TFT_TA(float TA){
tft.fillRect(80, 70, 110, 25, ST7735_BLACK);
tft.setTextSize(2);
tft.setCursor(85,75); // cursor columna 85 fila 75
if (Estado_CAL==1){
tft.setTextColor(ST7735_YELLOW);
}
else{
tft.setTextColor(ST7735_WHITE);
}
tft.print(TA);
}
// Muestra el estado de la alarma en TFT
void TFT_EST_ALM(float EST_ALM){
tft.fillRect(45, 105, 100, 25, ST7735_BLACK);
tft.setCursor(45,105); // cursor columna 45 fila 105
tft.setTextSize(2);
tft.setTextColor(ST7735_WHITE);
if (EST_ALM == 0){
tft.print("INACTIVA");
}
if (EST_ALM == 1){
tft.print(" ACTIVA");
}
}
// Muestra el estado SLEEP ahorro de en TFT
void TFT_SLEEP(){
tft.fillRect(45, 105, 100, 25, ST7735_BLACK);
tft.setCursor(45,105); // cursor columna 45 fila 105
tft.setTextSize(2);
tft.setTextColor(ST7735_WHITE);
if (dormido){
tft.print(".SLEEP..");
}
}
// Muestra la Programación de la calefacción en TFT
void TFT_PROG_CAL(float PROG_CAL){
tft.fillRect(80, 0, 20, 20, ST7735_BLACK);
tft.setCursor(80,10); // cursor columna 80 fila 10
tft.setTextSize(1);
tft.setTextColor(ST7735_WHITE);
if (PROG_CAL== 0){
tft.print("OFF");
}
if (PROG_CAL== 1){
tft.print("ON");
}
}
// Muestra la Programación de la alarma en TFT
void TFT_PROG_ALM(float PROG_ALM){
tft.fillRect(80, 30, 20, 15, ST7735_BLACK);
tft.setCursor(80,30); // cursor columna 80 fila 30
tft.setTextSize(1);
tft.setTextColor(ST7735_WHITE);
if (PROG_ALM== 0){
tft.print("OFF");
}
if (PROG_ALM== 1){
tft.print("ON");
}
}
// Muestra la humedad en TFT
void TFT_HUM(float HA){
tft.fillRect(115, 30, 40, 15, ST7735_BLACK);
tft.setCursor(120,32); // cursor columna 120 fila 32
tft.setTextSize(1);
tft.setTextColor(ST7735_WHITE);
tft.print(HA);
}
// Muestra el estado de la bateria en TFT
void TFT_BATERIA(){
/*
medida = analogRead(A0);
if (medida>680){
tft.fillRect(150, 102, 10, 8, ST7735_GREEN);
tft.fillRect(150, 111, 10, 8, ST7735_YELLOW);
tft.fillRect(150, 120, 10, 8, ST7735_RED);
}
if ((medida=<680)&&(medida>340)){
tft.fillRect(150, 102, 10, 8, ST7735_BLACK);
tft.fillRect(150, 111, 10, 8, ST7735_YELLOW);
tft.fillRect(150, 120, 10, 8, ST7735_RED);
}
if (medida=<340){
tft.fillRect(150, 102, 10, 8, ST7735_BLACK);
tft.fillRect(150, 111, 10, 8, ST7735_BLACK);
tft.fillRect(150, 120, 10, 8, ST7735_RED);
}
*/
tft.fillRect(150, 102, 10, 8, ST7735_GREEN);
tft.fillRect(150, 111, 10, 8, ST7735_YELLOW);
tft.fillRect(150, 120, 10, 8, ST7735_RED);
}