Sunday, March 4, 2018

Control Devices Using Android Phone and NodeMCU over Internet (Tutorial-8)

In this post I will show you guys, how to control devices from your Android phone and get temperature and humidity data on your Android Phone using DHT11 sensor.
If you are new to NodeMcu modules, I would recommend to read our old posts.

The answer for the above question is, Everything.
Actually the last post uses local area network to control the devices connected to the NodeMCU, which means that if you are outside your Local Area Network then you will not have any access to your home devices.
But with this post you will be able to control the devices and get temperature and humidity data from any corner of the world, just make sure you that have active internet connection.


Introduction
The NodeMcu module uses DHT11(Temperature and Humidity sensor), and after measuring the temperature and humidity it publishes this data to a server, and this server then publish this data to all the subscribers.
Similarly the Android phone, pushes the data with which NodeMCU will control the devices connected with it.For publishing and subscribing, I am going to use MQTT at all the ends (NodeMcu, Android Phone, Server).
If you are new to MQTT please have a look at the following posts, it will you some idea, plus it will also introduces you with the free CloudMQTT broker which we are going to use.
Getting Started with MQTT on Windows PC
Getting Started with MQTT Using Python  
The main challenge here, is to get the public MQTT Server or MQTT broker, which can help us to subscribe the temperature and humidity messages from any corner of the world.  
Since we don't have money and we always wanted to test everything for free, I found one popular MQTT broker, which is free to use with few limitations, and once you like it and wanted to explore more, you can purchase the paid accounts without limitations, and the name of the broker is CloudMQTT.

Hardware
The following image shows the my setup, which I am going to use for this post.

The following diagram shows the high level system block diagram.

The connection diagram is as follow:


Pin Name Pin Type Description
D1 Output Connected with Relay1
D2 Output Connected with Relay2
D3 Output Connected with Relay3
D4 Output Connected with Relay4
D5 Input DHT11 Data Pin

Components required as as follow:

The following image is of the Android Application which we are going to use to control the relays on 4-channel relay board.
Software
We need some libraries to complete this project and they are as given below.

To control Relays, digital input output pins of the NodeMCU are sufficient, and we don't need any external library for that.
The DHT Sensor Library will be used to measure the temperature and humidity data from DHT11 sensor, while the MQTT Library will be used to publish and subscribe the topics.
In this project, Android application will publish the relay states topic whenever the button's are pressed, while the NodeMcu will Publish the temperature and humidity data, while it will subscribe the led topic and relay state topics, and based on payload parameter, the on board led and relay, on NodeMcu will get turned on or off.
If you want to understand the code module wise, then use the following post, in this post, code is explained module wise and the same approach is used here.
The complete NodeMCU code in Arduino IDE is as follow and this is just the extension of the code used from the above post:

/*
 * HomeAutomation
 * This sketch will subscribe the packets for turning on and off the relays.
 * This project uses CloudMQTT Server as MQTT Broker
 */
#include <DHT.h>
#include <DHT_U.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// DHT11 Sensor Data Pin
#define DHTPIN    D5
// DHT Sensor Type
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22
//#define DHTTYPE DHT21   // DHT 21

// Relay (Loads) Pin
#define RELAY1    D1
#define RELAY2    D2
#define RELAY3    D3
#define RELAY4    D4

// Initialize DHT Sensor
DHT dht( DHTPIN, DHTTYPE);

// Update these Information
const char* ssid = "xxxxxx";                    // WiFi Name
const char* password = "xxxxxxxxxx";            // WiFi Password
const char* mqtt_server = "m14.cloudmqtt.com";  // MQTT Server Name
const int mqtt_port = 18410;                    // MQTT Server Port
const char* user_name = "setsmjwc";             // MQTT Server Instance User Name
const char* mqtt_pswd = "apDnKqHRgAjA";         // MQTT Server Instance Password

WiFiClient espClient;
PubSubClient client(espClient);
uint32_t lastMsg = 0;
#define MSG_BUFFER_LEN  10u
char msg[MSG_BUFFER_LEN];

// Setup WiFi Connection
void setup_wifi()
{
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

// Callback Function
void callback(char* topic, byte* payload, uint16_t length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (uint16_t i = 0; i < length; i++)
  {
    Serial.print((char)payload[i], HEX);
  }
  Serial.println();

  // Check which topic we have received and based on that take action
  // led topic
  if( strcmp(topic,"led") == 0 )
  {
    // Switch on the LED if an 1 was received as first character
    if ((char)payload[0] == '1') 
    {
      digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on
    }
    else 
    {
      digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off
    }
  }
  // Relay1 (Load1) Topic
  if( strcmp(topic, "load1") == 0 )
  {
    // Serial.println("Load1");
    if ((char)payload[0] == '1') 
    {
      digitalWrite( RELAY1, HIGH);
    }
    else
    {
      digitalWrite( RELAY1, LOW);
    }
  }
  
  // Relay2 (Load2) Topic
  if( strcmp(topic, "load2") == 0 )
  {
    // Serial.println("Load2");
    if ((char)payload[0] == '1') 
    {
      digitalWrite( RELAY2, HIGH);
    }
    else
    {
      digitalWrite( RELAY2, LOW);
    }
  }  
  // Relay3 (Load3) Topic
  if( strcmp(topic, "load3") == 0 )
  {
    // Serial.println("Load3");
    if ((char)payload[0] == '1') 
    {
      digitalWrite( RELAY3, HIGH);
    }
    else
    {
      digitalWrite( RELAY3, LOW);
    }
  }
  // Relay4 (Load4) Topic
  if( strcmp(topic, "load4") == 0 )
  {
    // Serial.println("Load4");
    if ((char)payload[0] == '1') 
    {
      digitalWrite( RELAY4, HIGH);
    }
    else
    {
      digitalWrite( RELAY4, LOW);
    }
  }
}

// Reconnect with Server Function
void reconnect() 
{
  // Loop until we're reconnected
  while (!client.connected()) 
  {
    Serial.print("Attempting CloudMQTT connection...");
    // Create a random client ID
    // String clientId = "ESP8266Client-";
    // clientId += String(random(0xffff), HEX);
    String clientId = "EmbeddedLab";
    Serial.print("Client Id:  ");
    Serial.println(clientId);
    // Attempt to connect
    // if (client.connect(clientId.c_str())) 
    if ( client.connect(clientId.c_str(), user_name, mqtt_pswd) )  
    {
      Serial.println("connected");
      // Once connected, publish an announcement...
      // client.publish("Broadcast", "Connected with MQTT Server");
      // ... and resubscribe (Topic is "LED", to control the on board LED)
      client.subscribe("led/#");
      // subscribe to load topics also.
      client.subscribe("load1/#");
      client.subscribe("load2/#");
      client.subscribe("load3/#");
      client.subscribe("load4/#");
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() 
{
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  digitalWrite(BUILTIN_LED, HIGH);  // Turn-Off Led
  // Initialize Relay's Pins as Output
  pinMode(RELAY1, OUTPUT );
  pinMode(RELAY2, OUTPUT );
  pinMode(RELAY3, OUTPUT );
  pinMode(RELAY4, OUTPUT );
  // Turn-Off all relays
  digitalWrite( RELAY1, LOW);
  digitalWrite( RELAY2, LOW);
  digitalWrite( RELAY3, LOW);
  digitalWrite( RELAY4, LOW);
  // Intiialize Serial Communication for Debug Messages
  Serial.begin(115200);
  // Setup NodeMcu with WiFi
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
}

void loop() 
{
  if (!client.connected()) 
  {
    reconnect();
  }
  client.loop();

  uint32_t now = millis();
  // Publish Message After another 15 seconds
  if (now - lastMsg > 15000u)
  {
    lastMsg = now;
    // Read Humidity
    float h = dht.readHumidity();
    // Read temperature as Celsius (the default)
    float t = dht.readTemperature();
    // Check if any reads failed
    if( isnan(h) || isnan(t) )
    {
      // Don't do anything, if data is invalid
      Serial.println("DHT11 data in invalid");
    }
    else
    {
      uint8_t temp = (uint8_t)(t);
      uint8_t humid= (uint8_t)(h);
      snprintf(msg, MSG_BUFFER_LEN,"%02d,%02d", temp, humid);
      Serial.print("Publish message:  ");
      Serial.println(msg);
      client.publish("home", msg);
    }
  }
}

Watch the following video, to see how the system works when the software is programmed in NodeMCU.


Click Here to get the Arduino IDE Software and Android APK.

Note:
Android Application is tested on three Android Phone, and it is working fine, one limitation in Android Application is that, you have to press enter key, once you enter any information, otherwise information will not get updated.


2 comments:

  1. Hi
    I need Android APK source code(B4A).
    Help me please.
    Thank you so much for your work.

    ReplyDelete
  2. Excellent. Please share apk source code.

    ReplyDelete