Hardware components | ||||||
| × | 1 | ||||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
|
NodeMCU is an open source IoT platform. It includes firmware which runs on the ESP8266 Wi-Fi SoC from Espressif Systems, and hardware which is based on the ESP-12 module. The term "NodeMCU" by default refers to the firmware rather than the development kits. The firmware uses the Lua scripting language. It is based on the eLua project, and built on the Espressif Non-OS SDK for ESP8266.
Some creative ESP8266 enthusiasts have developed an Arduino core for the ESP8266 WiFi SoC that is available at the GitHub ESP8266 Core webpage. This is what is popularly called the "ESP8266 Core for the Arduino IDE" and it has become one of the leading software development platforms for the various ESP8266 based modules and development boards, including NodeMCUs.
Let's start with setting up the ArduinoPart I: Installation and settings of Arduino IDE
- If you have not already done, follow the installation and settings of Arduino IDE through this link https://youtu.be/4Ih39hGcPzg
- Follow the settings of ESP8266 through this link https://youtu.be/G6CqvhXpBKM
- To create the temperature sensor project, go in options file New
- You can add the library files from sketch --> include library --> manage library
- Add all the libraries specified in the program
- ESP8266WiFi.h
- DNSServer.h
- ESP8266WebServer.h
- WiFiManager.h
- WiFiManager.h
Arduino side is done, let's shift to Cloud side to set up things
Setting up Cloud Account on Thingsio.AI- ThingsIO.AI is aIoT Platform for developers. As a developer we understood the pain of not having a seamless place to connect, analyze and process device data. Many pure analytics platforms does not offer device management, which is core for the iot. That is the reason of ThingsIO.AI
- Register the account in http://thingsio.ai/#/register.
- You will get the notification for sign up.
- Go in your email address and verify your account.
- After that, sign in your account with your email address and password
- Now, you will be on the project dashboard. Click on the new project option:
- Click on the add a new device option. You will get device ID.
- Enter the device name and click on the create and configure device
- You will be on your device dashboard:
1. Track your device’s special parameters here. This can be set in device configuration(default to null).
2. You can see your real time and special parameter’s graph.
3. You can see your all data points.
4. You can see here your last 5 data points.
5. You can see here all the list of created graphs.
Go in sample device code options and click on the Raspberry pi.
You will get the sample code from there copy and paste into your vi-editor or Geany programmer’s editor.
Click on the “Send trial data” to send a trial data to the server:
TO CONNECT NODEMCU WITH THINGSIO.AI:
- if(!wifiManager.autoConnect("wifiid", password)) enter your ssid and password to connect your device to your wifi.
- String PostValue = "{\"device_id\": 6112063, \"slave_id\": 1"; enter your device id and slave id.
- PostValue = PostValue +", \"data\":{\"celc\":" + t2 +", \"fahr\":" + t3 +"}"+"}"; the datas that is to be posted.
You can set the special parameters (this is tracked on the dashboard) & transform it accordingly and add new
Click on the update device option:
- You can also set your device geographical location
- To create a graph for your device click on the “create graph option”
- Click on the preview option and click save changes.
#include <SoftwareSerial.h>
SoftwareSerial mySerial(12,13); // RX, TX
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include "WiFiManager.h" //https://github.com/tzapu/WiFiManager
//////////////////////////////////////// ALL DECLARATIONS for MODBUS/////////////////////////////////////
unsigned char qry[8]={0x01,0x04,0x04,0x20,0x00,0x01};
unsigned char block[3]={0x20,0x21,0x22};
int count=0,i,m,j,k,ss=0,z;
unsigned char rx[30],c,d,lol;
char* dummy;
unsigned int check_sum,calc_checksum,transmit_CRC;
int t,t1,t2,t3;
int outputpin= A0;
///////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////// ALL DECLARATIONS for CLOUD //////////////////////////////
const char* host = "api.thingsio.ai";
const char* post_url = "/devices/deviceData";
const char* time_server = "baas.thethingscloud.com"; //this is to convert timestamp
const int httpPort = 80;
char ses_id[600];
char timestamp[10];
WiFiClient client;
//////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////CRC calculation function////////////////////////////////////////
int ModRTU_CRC(unsigned char* buf, int len)//compute the modbus rtu crc
{
int crc = 0xFFFF,temp = 0,pos,i;
for ( pos = 0; pos < len; pos++)
{
crc ^= (int)buf[pos]; // XOR byte into least sig. byte of crc
for ( i = 8; i != 0; i--) // Loop over each bit
{
if ((crc & 0x0001) != 0) // If the LSB is set
{
crc >>= 1; // Shift right and XOR 0xA001
crc ^= 0xA001;
}
else // Else LSB is not set
crc >>= 1; // Just shift right
}
}
temp = 0x00FF & crc; //Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
crc = temp<<8 |crc>>8;
return crc;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void configModeCallback (WiFiManager *myWiFiManager)
{
Serial.println("Entered config mode"); //*-*-*-*-*-*-*-*-*-*-*-*-*-*if control enters this function then net is not connected
Serial.println(WiFi.softAPIP()); // "WiFi.softAPIP() is for AP" , "WiFi.localIP() is for STA",
Serial.println(myWiFiManager->getConfigPortalSSID()); //if you used auto generated SSID, print it
}
/////////////////////////////////////// TIMESTAMP CALCULATION function///////////////////////////////////////
int GiveMeTimestamp()
{
unsigned long timeout = millis();
while (client.available() == 0)
{
if (millis() - timeout > 50000)
{
client.stop();
return 0;
}
}
while (client.available())
{
String line = client.readStringUntil('\r'); //indexOf() is a funtion to search for smthng , it returns -1 if not found
int pos = line.indexOf("\"timestamp\""); //search for "\"timestamp\"" from beginning of response got and copy all data after that , it'll be your timestamp
if (pos >= 0)
{
int j = 0;
for(j=0;j<10;j++)
{
timestamp[j] = line[pos + 12 + j];
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(115200); //(19200,SERIAL_8E1) - data size = 8 bits , parity = Even , stop bit = 1bit
mySerial.begin(115200);
//WiFiManager - Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;
//set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
wifiManager.setAPCallback(configModeCallback);
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP" and goes into a blocking loop awaiting configuration
if(!wifiManager.autoConnect("*****","*****")) //wifiManager.autoConnect("AP-NAME", "AP-PASSWORD"); (OR) wifiManager.autoConnect("AP-NAME"); only ID no password (OR) wifiManager.autoConnect(); this will generate a ID by itself
{
Serial.println("failed to connect and hit timeout"); //control comes here after long time of creating Access point "NodeMCU" by NodeMCU and still it has not connected
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(1000);
}
//if you come here you have connected to the WiFi
Serial.println("connected...yeey :");
}
void loop()
{
int analogValue = analogRead(outputpin);
for(z=0;z<7;z++)
{
qry[3]=block[z]; //bcoz for the energy meter queries for difft parameters, only 4th byte is changing
transmit_CRC = ModRTU_CRC(qry,6);
qry[6]=transmit_CRC>>8;
qry[7]=transmit_CRC & 0x00FF;
/////////////////////////////////////// SEND THE QUERY AND RECEIVE THE RESPONSE AND VALIDATE THE CHECKSUM///////////////////////
for(i=0;i<8;i++)
{
mySerial.write(qry[i]); //Serial.write(query,8); //this is only allowed for serial not software serial
Serial.write(qry[i]);
}
mySerial.flush();
Serial.flush();
delay(2);
Serial.println("");
if(mySerial.available()>0) //its like loop , it wont do any other work untill all these chars which are available are printed
{
count=mySerial.available();
m=count;
Serial.print("The response from meter in HEX is: ");
for(i=0;i<count;i++)
{
rx[i]=mySerial.read();
Serial.print(rx[i],HEX);
}
Serial.println("");
}
t=rx[3]<<8 | rx[4]; //cascade all required bytes from the response data and print it as "unsigned int"
Serial.print("The actual data in decimal is: "); //decimal bcoz mm is declared as unsigned int
Serial.println(t);
switch(qry[3])
{
case 0x20:
t1=(analogValue/1024.0) * 3300;
Serial.print("temp: ");
//Serial.println(t1);
break;
case 0x21:
t2=t1/10;;
Serial.print("celc: ");
Serial.println(t2);
break;
case 0x22:
t3=((t2 * 9)/5 + 32);
Serial.print("fhrn: ");
Serial.println(t3);
break;
}
check_sum = (rx[count-2]<<8) | rx[count-1];
calc_checksum = ModRTU_CRC(rx,(count-2));
Serial.print("received checksum: ");
Serial.println(check_sum,HEX);
Serial.print("calculated checksum: ");
Serial.println(calc_checksum,HEX);
if(check_sum == calc_checksum)
Serial.println("CRC Matched");
else
Serial.println("CRC Mismatch");
delay(1000); //between each query a delay of 1seconds
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
Serial.print("connecting to ");
Serial.println(host);
///////////////////////////////////// TIMESTAMP CODE SNIPPET /////////////////////////
Serial.println("inside get timestamp\n");
if (!client.connect(time_server, httpPort))
{
return; //*-*-*-*-*-*-*-*-*-*
}
client.println("GET /api/timestamp HTTP/1.1"); //Whats this part doing, i didnt get
client.println("Host: baas.thethingscloud.com");
client.println("Cache-Control: no-cache");
client.println("Postman-Token: ea3c18c6-09ba-d049-ccf3-369a22a284b8");
client.println();
GiveMeTimestamp(); //it'll call the function which will get the timestamp response from the server
Serial.println(timestamp);
///////////////////////////////////////////////////////////////////////////////
// Use WiFiClient class to create TCP connections
if (!client.connect(host, httpPort)) //port = 80
{
Serial.println("connection failed"); // *-*-*-*-*-*--*-*-*-*-*-*-*-*-*-*-*-*-
return;
}
//////////////////////////////////////Login to the thingscloud account ////////////////////////
client.print("POST ");
client.println(" HTTP/1.1");
client.print("host: ");
client.println(host); //host = devapi2.thethingscloud.com
client.println("Content-Type: application/json");
client.println("Cache-Control: no-cache");
client.print("Content-Length: ");
client.println();
/////////////////////////logged in and now receive the response //////////////////////////
unsigned long timeout = millis();
while (client.available() == 0)
{
if (millis() - timeout > 50000)
{
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
// Read all the lines of the reply from server and print them to Serial
Serial.println("Response From Server");
while(client.available()) //what all you get from the server print them all thru this loop
{
String line = client.readStringUntil('\r');
Serial.println(line);
int pos = line.indexOf("token");
if (pos >= 0)
{
int j = 0;
while (line[pos + 8 + j] != 34) //why 34?? , bcoz ASCII value of " is 34 . and "line[pos + 8 + j]" is considering characters not position.
{
ses_id[j] = line[pos + 8 + j];
j = j + 1;
}
ses_id[j + 1] = '\0';
}
}
Serial.println("***********************************************");
Serial.println(ses_id);
Serial.println("***********************************************");
Serial.println(timestamp);
Serial.println("***********************************************");
Serial.println();
Serial.println("closing connection");
Serial.println("inside ThingsCloudPost");
String PostValue = "{\"device_id\": 6112063, \"slave_id\": 1";
PostValue = PostValue + ",\"dts\":" +timestamp;
PostValue = PostValue +",\"data\":{\"celc\":" + t2 +",\"fahr\":" + t3 +"}"+"}";
Serial.println(PostValue);
//////////////////////////////// try to connect to server again and POST the data on the cloud //////////////////////////
if (!client.connect(host, httpPort))
{
return;
}
client.print("POST ");
client.print(post_url); /// POST api/deviceDatas HTTP/1.1 Host: api.thingsio.ai Content-Type: application/json Cache-Control: no-cache
client.print("Host: ");
client.println(host);
client.println("Content-Type: application/json");
client.println("Cache-Control: no-cache");
client.print("Authorization:Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.IjVjMDI4ODc5ODM5ZDNmMDY2MzNkZWFhYSI.2ag7FYqNN70lON3yolhnzMTtJpIq-TDFNAxPJ8unJMg ");
client.println(ses_id);
client.print("Content-Length: ");
client.println(PostValue.length());
client.println();
client.println(PostValue);
//////////////////////////////////POSTING the data on to the cloud is done and now get the response form cloud server//////////////////
Serial.println("Response From Server");
while(client.available())
{
String line2 = client.readStringUntil('\r');
Serial.print(line2);
}
Serial.println("////////////////////// THE END /////////////////////");
client.stop();
delay(3000);
}
#include <SoftwareSerial.h>
SoftwareSerial mySerial(12,13); // RX, TX
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include "WiFiManager.h" //https://github.com/tzapu/WiFiManager
//////////////////////////////////////// ALL DECLARATIONS for MODBUS/////////////////////////////////////
unsigned char qry[8]={0x01,0x04,0x04,0x20,0x00,0x01};
unsigned char block[3]={0x20,0x21,0x22};
int count=0,i,m,j,k,ss=0,z;
unsigned char rx[30],c,d,lol;
char* dummy;
unsigned int check_sum,calc_checksum,transmit_CRC;
int t,t1,t2,t3;
int outputpin= A0;
///////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////// ALL DECLARATIONS for CLOUD //////////////////////////////
const char* host = "api.thingsio.ai";
const char* post_url = "/devices/deviceData";
const char* time_server = "baas.thethingscloud.com"; //this is to convert timestamp
const int httpPort = 80;
char ses_id[600];
char timestamp[10];
WiFiClient client;
//////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////CRC calculation function////////////////////////////////////////
int ModRTU_CRC(unsigned char* buf, int len)//compute the modbus rtu crc
{
int crc = 0xFFFF,temp = 0,pos,i;
for ( pos = 0; pos < len; pos++)
{
crc ^= (int)buf[pos]; // XOR byte into least sig. byte of crc
for ( i = 8; i != 0; i--) // Loop over each bit
{
if ((crc & 0x0001) != 0) // If the LSB is set
{
crc >>= 1; // Shift right and XOR 0xA001
crc ^= 0xA001;
}
else // Else LSB is not set
crc >>= 1; // Just shift right
}
}
temp = 0x00FF & crc; //Note, this number has low and high bytes swapped, so use it accordingly (or swap bytes)
crc = temp<<8 |crc>>8;
return crc;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void configModeCallback (WiFiManager *myWiFiManager)
{
Serial.println("Entered config mode"); //*-*-*-*-*-*-*-*-*-*-*-*-*-*if control enters this function then net is not connected
Serial.println(WiFi.softAPIP()); // "WiFi.softAPIP() is for AP" , "WiFi.localIP() is for STA",
Serial.println(myWiFiManager->getConfigPortalSSID()); //if you used auto generated SSID, print it
}
/////////////////////////////////////// TIMESTAMP CALCULATION function///////////////////////////////////////
int GiveMeTimestamp()
{
unsigned long timeout = millis();
while (client.available() == 0)
{
if (millis() - timeout > 50000)
{
client.stop();
return 0;
}
}
while (client.available())
{
String line = client.readStringUntil('\r'); //indexOf() is a funtion to search for smthng , it returns -1 if not found
int pos = line.indexOf("\"timestamp\""); //search for "\"timestamp\"" from beginning of response got and copy all data after that , it'll be your timestamp
if (pos >= 0)
{
int j = 0;
for(j=0;j<10;j++)
{
timestamp[j] = line[pos + 12 + j];
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
Serial.begin(115200); //(19200,SERIAL_8E1) - data size = 8 bits , parity = Even , stop bit = 1bit
mySerial.begin(115200);
//WiFiManager - Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;
//set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
wifiManager.setAPCallback(configModeCallback);
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP" and goes into a blocking loop awaiting configuration
if(!wifiManager.autoConnect("$UG@")) //wifiManager.autoConnect("AP-NAME", "AP-PASSWORD"); (OR) wifiManager.autoConnect("AP-NAME"); only ID no password (OR) wifiManager.autoConnect(); this will generate a ID by itself
{
Serial.println("failed to connect and hit timeout"); //control comes here after long time of creating Access point "NodeMCU" by NodeMCU and still it has not connected
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(1000);
}
//if you come here you have connected to the WiFi
Serial.println("connected...yeey :");
}
void loop()
{
int analogValue = analogRead(outputpin);
for(z=0;z<7;z++)
{
qry[3]=block[z]; //bcoz for the energy meter queries for difft parameters, only 4th byte is changing
transmit_CRC = ModRTU_CRC(qry,6);
qry[6]=transmit_CRC>>8;
qry[7]=transmit_CRC & 0x00FF;
/////////////////////////////////////// SEND THE QUERY AND RECEIVE THE RESPONSE AND VALIDATE THE CHECKSUM///////////////////////
for(i=0;i<8;i++)
{
mySerial.write(qry[i]); //Serial.write(query,8); //this is only allowed for serial not software serial
Serial.write(qry[i]);
}
mySerial.flush();
Serial.flush();
delay(2);
Serial.println("");
if(mySerial.available()>0) //its like loop , it wont do any other work untill all these chars which are available are printed
{
count=mySerial.available();
m=count;
Serial.print("The response from meter in HEX is: ");
for(i=0;i<count;i++)
{
rx[i]=mySerial.read();
Serial.print(rx[i],HEX);
}
Serial.println("");
}
t=rx[3]<<8 | rx[4]; //cascade all required bytes from the response data and print it as "unsigned int"
Serial.print("The actual data in decimal is: "); //decimal bcoz mm is declared as unsigned int
Serial.println(t);
switch(qry[3])
{
case 0x20:
t1=(analogValue/1024.0) * 3300;
Serial.print("temp: ");
//Serial.println(t1);
break;
case 0x21:
t2=t1/10;;
Serial.print("celc: ");
Serial.println(t2);
break;
case 0x22:
t3=((t2 * 9)/5 + 32);
Serial.print("fhrn: ");
Serial.println(t3);
break;
}
check_sum = (rx[count-2]<<8) | rx[count-1];
calc_checksum = ModRTU_CRC(rx,(count-2));
Serial.print("received checksum: ");
Serial.println(check_sum,HEX);
Serial.print("calculated checksum: ");
Serial.println(calc_checksum,HEX);
if(check_sum == calc_checksum)
Serial.println("CRC Matched");
else
Serial.println("CRC Mismatch");
delay(1000); //between each query a delay of 1seconds
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
Serial.print("connecting to ");
Serial.println(host);
///////////////////////////////////// TIMESTAMP CODE SNIPPET /////////////////////////
Serial.println("inside get timestamp\n");
if (!client.connect(time_server, httpPort))
{
return; //*-*-*-*-*-*-*-*-*-*
}
client.println("GET /api/timestamp HTTP/1.1"); //Whats this part doing, i didnt get
client.println("Host: baas.thethingscloud.com");
client.println("Cache-Control: no-cache");
client.println("Postman-Token: ea3c18c6-09ba-d049-ccf3-369a22a284b8");
client.println();
GiveMeTimestamp(); //it'll call the function which will get the timestamp response from the server
Serial.println(timestamp);
///////////////////////////////////////////////////////////////////////////////
// Use WiFiClient class to create TCP connections
if (!client.connect(host, httpPort)) //port = 80
{
Serial.println("connection failed"); // *-*-*-*-*-*--*-*-*-*-*-*-*-*-*-*-*-*-
return;
}
//////////////////////////////////////Login to the thingscloud account ////////////////////////
client.print("POST ");
client.println(" HTTP/1.1");
client.print("host: ");
client.println(host); //host = devapi2.thethingscloud.com
client.println("Content-Type: application/json");
client.println("Cache-Control: no-cache");
client.print("Content-Length: ");
client.println();
/////////////////////////logged in and now receive the response //////////////////////////
unsigned long timeout = millis();
while (client.available() == 0)
{
if (millis() - timeout > 50000)
{
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
// Read all the lines of the reply from server and print them to Serial
Serial.println("Response From Server");
while(client.available()) //what all you get from the server print them all thru this loop
{
String line = client.readStringUntil('\r');
Serial.println(line);
int pos = line.indexOf("token");
if (pos >= 0)
{
int j = 0;
while (line[pos + 8 + j] != 34) //why 34?? , bcoz ASCII value of " is 34 . and "line[pos + 8 + j]" is considering characters not position.
{
ses_id[j] = line[pos + 8 + j];
j = j + 1;
}
ses_id[j + 1] = '\0';
}
}
Serial.println("***********************************************");
Serial.println(ses_id);
Serial.println("***********************************************");
Serial.println(timestamp);
Serial.println("***********************************************");
Serial.println();
Serial.println("closing connection");
Serial.println("inside ThingsCloudPost");
String PostValue = "{\"device_id\": 6112063, \"slave_id\": 1";
PostValue = PostValue + ",\"dts\":" +timestamp;
PostValue = PostValue +",\"data\":{\"celc\":" + t2 +",\"fahr\":" + t3 +"}"+"}";
Serial.println(PostValue);
//////////////////////////////// try to connect to server again and POST the data on the cloud //////////////////////////
if (!client.connect(host, httpPort))
{
return;
}
client.print("POST ");
client.print(post_url); /// POST api/deviceDatas HTTP/1.1 Host: api.thingsio.ai Content-Type: application/json Cache-Control: no-cache
client.print("Host: ");
client.println(host);
client.println("Content-Type: application/json");
client.println("Cache-Control: no-cache");
client.print("Authorization:Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.IjVjMDI4ODc5ODM5ZDNmMDY2MzNkZWFhYSI.2ag7FYqNN70lON3yolhnzMTtJpIq-TDFNAxPJ8unJMg ");
client.println(ses_id);
client.print("Content-Length: ");
client.println(PostValue.length());
client.println();
client.println(PostValue);
//////////////////////////////////POSTING the data on to the cloud is done and now get the response form cloud server//////////////////
Serial.println("Response From Server");
while(client.available())
{
String line2 = client.readStringUntil('\r');
Serial.print(line2);
}
Serial.println("////////////////////// THE END /////////////////////");
client.stop();
delay(3000);
}
Comments
Please log in or sign up to comment.