Share NodeMCU ESP8266 Communication Methods and Protocols - Programming With Arduino IDE PDF
Share NodeMCU ESP8266 Communication Methods and Protocols - Programming With Arduino IDE PDF
ESP8266 Communication
Methods and Protocols
Programming with Arduino IDE
Manoj R. Thakur
Table of Contents 1. Introduction 6
1.1 ESP8266 6
1.1.1 The ESP8266 specification 6
1.1.2 Node MCU Pin Connections 7
1.2 Software Deveopment Using Arduino IDE 7
1.2.1 Installing ESP8266 board in Arduino IDE 7
1.2.2 Checking Installation is Working 12
2. Serial Communication 16
2.1 Serial Communication 16
2.2 Other Useful Serial Commands 20
2.2.1 begin() 20
2.2.2 print() 21
2.2.3 println() 21
2.2.4 available() 22
2.2.5 availableForWrite() 22
2.2.6 End() 23
2.2.7 Serial.setTimeout() 23
2.2.8 find() 23
2.2.9 flush() 24
2.2.10 parseFloat() 24
2.2.11 parseInt() 25
2.2.12 peek() 25
2.2.13 read() 25
2.2.14 readBytes() 25
2.2.15 readBytesUntil() 26
2.2.16 write() 26
2.3 Software Serial 26
3. I2C Inter IC Communication 28
3.1 Introduction 28
3.2 I2C Signalling 28
3.3 Interfacing AT24C256 with ESP8266 29
3.3.1 Points to concider 29
3.3.2 Pin discription of AT24C256 30
3.3.3 24C256 Connections with NodeMCU 30
3.3.3 I2C communication header file 31
3.3.4 Program for EEPROM 24C256 interface 34
3.3.5 Results 36
4. Soft Access Point 37
4.1 Introduction 37
4.2 NodeMCU as Access Point 37
4.2.1 WiFi Modes 37
4.3 Creating Access Point using NodeMCU 38
4.4 Results 39
5. WiFi Station Mode 40
5.1 Introduction 40
5.2 Connecting NodeMCU to Access Point 40
5.3 Results 42
5.4 WiFi Network Scan 44
5.5 Results 46
6. Static IP 47
6.1 Introduction 47
6.2 Connecting NodeMCU to Access Point with Static IP 47
6.3 Results 50
7. mDNS 51
7.1 Introduction 51
What is mDNS? 51
7.2 Configuring NodeMCU to use mDNS 51
7.3 Results 54
8. MAC Address 56
8.1 Introduction 56
8.2 Get MAC Address of NodeMCU 56
8.3 Results 57
9. HTTP 58
9.1 Introduction 58
9.2 Sending plain text to Client 58
9.2.1 Program for sending Plain text 59
9.2.2 Results 60
9.3 HTML web page 61
9.3.1 Program for HTTP HTML web page 62
9.3.2 Results 63
9.4 Redirect and Handle Not found web requests 64
9.4.1 Program for handling not found links and redirect 64
9.4.2 Results 67
10. GET 72
10.1 Introduction 72
10.1.1 HTTP Methods: GET and POST 72
GET 72
The GET Method 72
10.2 NodeMCU GET Request Example 73
10.2.1 Results 74
10.3 Handling GET request sent to NodeMCU 75
10.3.1 Program to handle GET requests 75
10.3.2 Results 77
11. POST 80
11.1 Introduction 80
11.1.1 HTTP Request Methods: GET and POST 81
POST 81
The POST Method 81
11.2 NodeMCU POST Request Example 82
11.2.1 Results 83
11.3 Handling POST request sent to NodeMCU 84
11.3.1 Program to handle POST requests 84
11.3.2 Results 86
12. JSON 88
12.1 Introduction 88
12.2 NodeMCU JSON Decode Example 90
12.2.1 Results 93
12.3 NodeMCU JSON Encode Example 93
12.3.1 Results 95
13. Java Scripts 96
13.1 Introduction 96
13.2 NodeMCU JavaScript Example 96
13.2.1 htmlPage.h 97
13.2.2 NodeMCU main file code 100
13.2.3 Results 103
14. AJAX (Asynchronous JavaScript and XML) 106
14.1 Introduction 106
14.2 NodeMCU AJAX Example 108
14.2.1 htmlPage.h 108
14.2.2 NodeMCU AJAX Example code 109
14.2.3 Results 111
15. JQuery 112
15.1 Introduction 112
15.2 NodeMCU JQuery using CDN example 112
15.2.1 htmlPage.h 112
15.2.2 NodeMCU JQuery example code 118
15.2.3 Results 119
16. UDP 123
16.1 Introduction 123
Features 123
16.2 NodeMCU UDP example code 123
16.3 Results 125
17. NTP 126
17.1 Introduction 126
17.1.1 What is NTP? 126
17.1.2 What is NTP Server? 126
17.1.3 What is NTP Port? 126
17.1.4 How NTP UDP Protocol Works? 126
17.2 NodeMCU NTP example code 132
17.3 Results 136
18. SPIFFS 137
18.1 Introduction 137
18.2 File system object (SPIFFS) 137
begin 137
format 137
open 137
exists 138
openDir 138
remove 138
rename 138
seek 138
position 139
size 139
name 139
close 139
18.3 NodeMCU SPIFFS example code 139
18.4 Results 141
18.5 Directly uploading files to NodeMCU 141
18.5 Reading uploaded file 144
18.6 Results 145
19. Smart Config 146
19.1 Introduction 146
19.2 Smart Config Example 146
19.3 Results 148
20. WebSocket 155
20.1 Introduction 155
20.1.1 What is WebSocket? 155
20.1.2 WebSocket Attributes 155
20.1.3 WebSocket Events 156
20.1.4 WebSocket Methods 156
20.2 NodeMCU WebSocket example code 157
20.2.1 index.h file 157
20.2.2 webSocket.ino NodeMCU code file 161
20.4 Results 164
21. MQTT 167
21.1 Introduction 167
21.2 Configuring MQTT Server 168
21.3 NodeMCU MQTT example code 170
21.4 Results 172
22.4 Controlling LED over internet using MQTT 174
22.5 Results of above HTML code 175
22. OTA 177
22.1 Introduction 177
22.2 NodeMCU OTA example code 177
22.3 Results 179
23. Sending Email 181
23.1 Introduction 181
23.2 SMTP Commands 181
23.3 NodeMCU Email example code 182
23.4 Results 183
24. MODBUS TCP and RS485 186
24.1 Introduction 186
24.2 NodeMCU MODBUS TCP example code 186
mainPage.h 207
24.3 Results 213
1. Introduction
1.1 ESP8266
The ESP8266 is Low-power, highly-integrated Wi-Fi microcontroller
designed by Espressif Systems. It requires minimum of 7 external
components to get it in action. It operates at wide temperature range:
-40°C to +125°C.
Espressif is a Chinese company based out of Shanghai. Volume
production of the ESP8266 started in the beginning of 2014
ESP8266 IC is very tiny and virtually impossible for hobbyists to
attach wires to allow them to be plugged into breadboards. For
simplicity we can buy pre-made development boards such as
NodeMCU board from e-bay, amazon for a few dollars on.
There are a variety of board styles available. In this book we mainly
focus on commonly used and easily available board NodeMCU.
Recently Espressif released ESP32 more powerful low-cost
microcontroller with dual core and large number of IOs and TLS 1.2,
Capacitive touch pad, ADC, DAC, Bluetooth capability.
1.1.1 The ESP8266 specification
To start with this board first we must know about its specification.
Here are some of the salient points:
Operating Voltage: 3.3V
Current consumption: 10uA – 170mA
Flash memory attachable 16MB max (512K normal)
Processor Tensilica: L106 32-bit
Processor speed: 80-160MHz
RAM: 32K + 80K
GPIOs: 17 (multiplexed with other functions)
Analog to Digital 1 input with 1024 step (10 bit) resolution
Wi-Fi: 802.11 support b/g/n
Maximum concurrent TCP connections 5
1.1.2 Node MCU Pin Connections
NodeMCU has different labels on it when programming with arduino
refer this diagram.
Figure 1.1:
NodeMCU Pin Diagram
1.2 Software Development Using
Arduino IDE
Thanks to Arduino community we can program ESP8266 Directly
using Arduino IDE with Arduino style coding. There are two ways to
program it, using AT commands (requires external controller) and
directly flashing. I don’t know why few people prefer AT commands
when we have such a powerful 32-bit controller with huge RAM and
FLASH. In this book we focus on direct flashing of ESP8266.
1.2.1 Installing ESP8266 board in Arduino
IDE
Installation procedure for adding ESP8266 board in arduino IDE is
very simple with latest versions of Arduino IDE. Follow these steps
Step 1: Open Arduino IDE
Go to File >> Preferences
Add additional board manager URLs:
http://arduino.esp8266.com/stable/package_esp8266com_index.json
Figure 1.2:
Preferences
Step 2: Open Board Manager
Go to Tools >> Board >> Board Manager
Figure 1.3:
Board Manager
Step 3: Install ESP8266 Board
Search for ESP8266 and then click install button. Note: If Step 1 URL
is not added then it will not find ESP8266 board.
Figure 1.4:
Install ESP8266
Step 4: After clicking install. Installation progress is shown in
bottom.
Once it is installed open Tools>>Boards and look for ESP8266.
1.2.2 Checking Installation is working
To check installation is working or not. Test LED blink program.
Step 1: Select ESP8266 Generic Board or NodeMCU 1.0
Generic ESP8266 Module, Works for all boards so I prefer this board.
Figure 1.6:
Open Blink Example Step 3: Modify or Write New Program to
make GPIO2 LED blinking.
NodeMCU is having two on board LEDs as shown in Figure 1.1. We
use LED connected to GPIO2 for this example
#define LED 2
void setup() {
pinMode(LED,OUTPUT); //Define pin as output }
void loop() {
//LED off. LED is connected in reverse digitalWrite(LED,HIGH);
delay(500); digitalWrite(LED,LOW); //LED on delay(500); }
Step 4: Uploading Program to NodeMCU
Select your board’s com port. Make sure that you have installed
drivers for your board. NodeMCU uses CP2102 as USB to Serial
converter. Install drivers for CP2102 if not installed.
Figure 1.7:
Communication Port Selection When you click on upload button
press and hold FLASH button of NodeMCU which is present near
USB connection, Once upload is started (blue led blinks at faster
rate) you can release it. Pressing of FLASH button is not required if
selected board is NodeMCU 1.0.
Step 5: Once uploading is successful, check LED is blinking.
Now your setup is ready to go for further.
2. Serial Communication
The first and basic most communication that is required for most of
the devices and program debugging is serial communication. It’s
simple but important to know. Serial communication is used to make
ESP communicate with PC and serial communication devices.
ESP8266 RX TX line uses 3.3V logic. All IO lines and supply voltage
for ESP8266 is 3.3V. Do not connect any IO line with 5V logic
2.1 Serial Communication
ESP8266 Serial works the same way as on a regular Arduino. Apart
from hardware FIFO (128 bytes for TX and RX) Serial has additional
256-byte TX and RX buffers. Both transmit and receive is interrupt-
driven. Write and read functions only block the sketch execution
when the respective FIFO/buffers are full.
Serial uses UART0, which is mapped to pins GPIO1 (TX) and GPIO3
(RX).
Example 1: Serial Data Transmission Program to send “Hello
World” message to serial
void setup() {
Serial.begin(115200); }
void loop() {
Serial.println("Hello World"); delay(500); }
Upload above program and open serial monitor to see transmitted
data.
void loop() {
Serial.println("Hello World"); delay(500); }
After uploading program you will see blue led flashes due to data is
getting sent on GPIO2(TX). Data will not come on serial monitor as
we changed the pins.
By default the diagnostic output from Wi-Fi libraries is disabled when
you call Serial.begin. To enable debug output again, call
Serial.setDebugOutput(true). To redirect debug output to Serial1
instead, call Serial1.setDebugOutput(true).
Example 5: Turning ON Serial Debug You also need to use
Serial.setDebugOutput(true) to enable output from printf() function.
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
void loop() {
Serial.println("Hello World"); delay(500); }
Output on Serial Terminal
Figure 2.2:
Serial output with debug on Debug is very useful to see what’s
going inside the ESP8266. ESP8266 Libraries and its internal OS
keep track of Wi-Fi and many other functions. Here we have not used
Wi-Fi connections but it is showing reconnect to circuits4you.com
(it’s my Wi-Fi SSID). ESP8266 stores the Wi-Fi configuration in its
memory after reflashing it. These configuration settings remain there
and unnecessarily use CPU. See Figure 2.1 where we have disabled
the debug.
Note: Turning debug on helps to understand wdt_reset and Fatal
error messages The method Serial.setRxBufferSize(size_t size)
allows defining the receiving buffer depth. The default value is 256.
Both Serial and Serial1 objects support 5, 6, 7, 8 data bits, odd (O),
even (E), and no (N) parity, and 1 or 2 stop bits. To set the desired
mode, call Serial.begin(baudrate, SERIAL_8N1),
Serial.begin(baudrate, SERIAL_6E2), etc.
A new method has been implemented on both Serial and Serial1 to get
current baud rate setting. To get the current baud rate, call
Serial.baudRate(), Serial1.baudRate(). Return a int of current speed.
Example 6: Get current serial baudrate
void setup() {
Serial.begin(115200);
void loop() {
int baud = Serial.baudRate(); Serial.print("Current Baud:");
Serial.println(baud); delay(500); }
Upload above program and open serial monitor to see results.
Figure 2.3:
Current baudrate function output
2.2 Other Useful Serial Commands
2.2.1 begin()
Sets the data rate in bits per second (baud) for serial data transmission.
For communicating with the computer, use one of these rates: 300,
600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, or
115200.
An optional second argument configures the data, parity, and stop
bits. The default is 8 data bits, no parity, and one stop bit.
2.2.2 print()
Prints data to the serial port as human-readable ASCII text. This
command can take many forms. Numbers are printed using an ASCII
character for each digit. Floats are similarly printed as ASCII digits,
defaulting to two decimal places. Bytes are sent as a single character.
Characters and strings are sent as is.
Examples:
Serial.print(78); //gives "78"
Serial.print(1.23456); //gives "1.23"
Serial.print('N'); //gives "N"
Serial.print("Hello world."); //gives "Hello world."
An optional second parameter specifies the base (format) to use;
permitted values are BIN(binary, or base 2), OCT(octal, or base 8),
DEC(decimal, or base 10), HEX(hexadecimal, or base 16). For
floating point numbers, this parameter specifies the number of
decimal places to use.
Examples:
Serial.print(78, OCT); //gives "116"
Serial.print(78, BIN); //gives "1001110"
Serial.print(78, DEC); //gives "78"
Serial.print(78, HEX); //gives "4E"
Serial.println(1.23456, 0); //gives "1"
Serial.println(1.23456, 2); //gives "1.23"
Serial.println(1.23456, 4); //gives "1.2346"
You can pass flash-memory based strings to Serial.print() by
wrapping them with F(). For example: Serial.print(F(“Hello World”));
2.2.3 println()
Prints data to the serial port as human-readable ASCII text followed
by a carriage return character (ASCII 13, or '\r') and a newline
character (ASCII 10, or '\n'). This command takes the same forms as
Serial.print().
2.2.4 available()
Get the number of bytes (characters) available for reading from the
serial port. This is data that’s already arrived and stored in the serial
receive buffer (which holds 128 bytes).
Example: Program to display number of bytes in serial buffer
void setup() {
Serial.begin(115200);
void loop() {
int dataSize = Serial.available();
Serial.print("Current Data count in buffer:"); Serial.println(dataSize);
delay(500); }
Upload above program and open serial monitor and enter some data
and press send button. Output will show number of bytes data present
in serial receive FIFO. Maximum of 128 bytes can be stored in FIFO.
The count will go max 128.
2.2.5 availableForWrite()
ESP8266 works at 80MHz. While sending large data having length
more than 128 bytes then you have to take care that previous data is
sent out and buffer (send FIFO) is free for more data. If this check is
not done then data gets lost or FIFO overwritten before data sending.
Example: To get free space of Write FIFO buffer
void setup() {
Serial.begin(115200);
void loop() {
//Comment this line it will show FIFO 128
Serial.println("Some data to write before next line"); int dataSize =
Serial.availableForWrite();
Serial.print("Current Data in write FIFO:"); Serial.println(dataSize);
delay(500); }
Upload program and open serial monitor it will show 92 bytes free
FIFO. Comment first line that sends data and again upload program, it
will show 128 bytes free. Or add delay after first line to give some
time for data to get sent.
2.2.6 End()
Disables serial communication, allowing the RX and TX pins to be
used for general input and output. To re-enable serial communication,
call Serial.begin().
Example: Serial.end();
2.2.7 Serial.setTimeout()
Sets the maximum milliseconds to wait for serial data when using
Serial.readBytesUntil(), Serial.readBytes(), Serial.parseInt() or
Serial.parseFloat() . It defaults to 1000 milliseconds.
2.2.8 find()
Serial.find() reads data from the serial buffer until the target string of
given length is found. The function returns true if target string is
found, false if it times out.
Example: Turns on LED when it receives “on” and turns off when
receives “off”
void setup() {
Serial.begin(115200);
Serial.println(""); Serial.println("Type few words"); pinMode(LED,OUTPUT);
pinMode(LED,HIGH); //LED in off }
void loop() {
if(Serial.available()) {
Serial.println(Serial.available()); if(Serial.find("on")) {
digitalWrite(LED,LOW); //LED on Serial.println("ON"); }
if(Serial.find("off")) {
digitalWrite(LED,HIGH); //LED off Serial.println("OFF"); }
}
Open serial monitor and send ‘on’ to turn on led and ‘off’ to make it
off. Find will search for those words no matter how you write ex.
“aksjhajkonasdjh”. Find reads data from buffer and clears it. You
need additional logic when you look for two words, it clears buffer on
first find command.
2.2.9 flush()
Waits for the transmission of outgoing serial data to complete.
2.2.10 parseFloat()
Serial.parseFloat() returns the first valid floating point number from
the Serial buffer. Characters that are not digits (or the minus sign) are
skipped. parseFloat() is terminated by the first character that is not a
floating point number. This is useful in GCODE decoder used in 3D
printers.
void setup() {
Serial.begin(115200);
Serial.println(""); Serial.println("Type floating number Ex. abc12.34xyz"); }
void loop() {
if(Serial.available()>5) {
Serial.println(Serial.available()); Serial.println(Serial.parseFloat()); }
}
2.2.11 parseInt()
Looks for the next valid integer in the incoming serial
stream.parseInt() similar to parseFloat but only gets integer.
In particular:
Initial characters that are not digits or a minus sign, are
skipped;
Parsing stops when no characters have been read for a
configurable time-out value, or a non-digit is read;
If no valid digits were read when the time-out occurs, 0 is
returned;
2.2.12 peek()
Returns the next byte (character) of incoming serial data without
removing it from the internal serial buffer. That is, successive calls to
peek() will return the same character, as will the next call to read() .
2.2.13 read()
Reads incoming serial data. Read().
Example:
void setup()
{
Serial.begin(115200);
Serial.println("");
Serial.println("Waiting For Data:");
}
void loop()
{
if(Serial.available())
{
Serial.println(char(Serial.read()));
}
}
Open serial monitor and send some data. Try code by removing char.
2.2.14 readBytes()
Serial.readBytes() reads characters from the serial port into a buffer.
The function terminates if the determined length has been read, or it
times out (see Serial.setTimeout()).
Syntax: Serial.readBytes(buffer, length)
2 .2.15 readBytesUntil()
Serial.readBytesUntil() reads characters from the serial buffer into an
array. The function terminates if the terminator character is detected,
the determined length has been read, or it times out. The function
returns the characters up to the last character before the supplied
terminator. The terminator itself is not returned in the buffer.
Syntax: Serial.readBytesUntil(character, buffer, length)
2.2.16 write()
Writes binary data to the serial port. This data is sent as a byte or
series of bytes.
Syntax
Serial.write(val)
Serial.write(str)
Serial.write(buf, len)
2.3 Software Serial
Software serial uses timer, be careful when you are using software
serial. Timer is also used for Wi-Fi communication section if you
don’t give enough time to Wi-Fi routines it will create problem of
stack error or misbehaviour. It is better to use software serial only
when you need two serial ports and also avoid use of software serial
for data reception.
For this you need SoftwareSerial Library Link:
https://circuits4you.com/wp-
content/uploads/2016/11/SoftwareSerial.zip
Example:
#include <SoftwareSerial.h> //Define hardware connections and buffer size
SoftwareSerial swSerial(14, 12, false, 128); void setup() {
swSerial.begin(115200); //Initialize software serial
swSerial.println("Software serial test started"); swSerial.println("Hello World");
}
void loop() {
3. I2C Inter IC Communication
3.1 Introduction
In this lesson we interface commonly used two I2C devices,
EEPROM AT24C256 and 12-bit 2-channel ADC MCP3202. I2C is
invented by Philips semiconductor, This protocol is mainly used for
on board IC to IC communication. It supports more than 100kbps
speed. In this tutorial we are not using dedicated SCL, SDA pins and
no library. We right code from scratch to make clear understanding
and make easy to interface with any I2C device.
3.2 I2C Signalling
CLOCK and DATA TRANSITIONS: The SDA pin is normally
pulled high with an external device or resistor. Data on the SDA pin
may change only during SCL low time periods. Data changes during
SCL high periods will indicate a start or stop condition as shown
below.
//----------------------------------------------------
//----------------------------------------------------
#define I2C_DELAY 5 //5 micro seconds = 200KHz #define
I2C_TIMEOUT 1000
#define I2C_READ 1
#define I2C_WRITE 0
#define I2C_QUIT 0
#define I2C_CONTINUE 1
#define I2C_NO_ERROR 0
#define I2C_ERROR_DEVICE_BUSY 1
#define I2C_ERROR_DEVICE_NOT_RESPONDING 2
/* Macro definitions */
#define I2C_START(ADDRESS) { i2c_start(); i2c_transmit(ADDRESS); }
#define I2C_START_TX(ADDRESS) I2C_START(ADDRESS) #define
I2C_START_RX(ADDRESS) I2C_START(ADDRESS | I2C_READ) //--------
----------------------------
#define SCL_1() { pinMode(SCL_PIN,0); }
#define SCL_0() { pinMode(SCL_PIN,1); }
#define SDA_1() { pinMode(SDA_PIN,0); }
#define SDA_0() { pinMode(SDA_PIN,1); }
#define RELEASE_I2C_BUS() { SCL_1(); SDA_1(); }
void i2c_start(void); void i2c_init(void); void i2c_stop(void); unsigned char
i2c_transmit(unsigned char data); unsigned char i2c_receive(unsigned char
ack); /*###########################################*/
void i2c_init(void) {
digitalWrite(SDA_PIN,0); digitalWrite(SCL_PIN,0); RELEASE_I2C_BUS();
delayMicroseconds(I2C_TIMEOUT); i2c_start();
delayMicroseconds(I2C_TIMEOUT); i2c_stop();
delayMicroseconds(I2C_TIMEOUT); return; }
/*###########################################*/
void i2c_start(void) {
RELEASE_I2C_BUS(); delayMicroseconds(I2C_DELAY); SDA_0();
delayMicroseconds(I2C_DELAY); SCL_0();
delayMicroseconds(I2C_DELAY); return; }
/*###########################################*/
void i2c_stop(void) {
SDA_0(); SCL_1(); delayMicroseconds(I2C_DELAY); SDA_1();
delayMicroseconds(I2C_DELAY); SCL_0();
delayMicroseconds(I2C_DELAY); return; }
/*###########################################*/
unsigned char i2c_transmit(unsigned char data) {
register unsigned char bit=0; for(bit=0; bit<=7; bit++) {
if( data & 0x80 ) { SDA_1(); } else { SDA_0(); }
SCL_1(); delayMicroseconds(I2C_DELAY); SCL_0();
delayMicroseconds(I2C_DELAY); data = (data<<1); }
/* Look for AKNOWLEDGE */
RELEASE_I2C_BUS(); delayMicroseconds(I2C_DELAY);
if(digitalRead(SDA_PIN)==0) {
SCL_0(); delayMicroseconds(I2C_DELAY); }
else{
delayMicroseconds(I2C_TIMEOUT); if(digitalRead(SDA_PIN)==0) {
SCL_0(); delayMicroseconds(I2C_DELAY); }
else { return(I2C_ERROR_DEVICE_NOT_RESPONDING); }
}
if(digitalRead(SDA_PIN)==0) {
delayMicroseconds(I2C_TIMEOUT); if(digitalRead(SDA_PIN)==0) {
return(I2C_ERROR_DEVICE_BUSY); }
}
return(I2C_NO_ERROR);
/*###########################################*/
unsigned char i2c_receive(unsigned char ack) {
register unsigned char bit=0, data=0; SDA_1(); for(bit=0; bit<=7; bit++) {
SCL_1(); delayMicroseconds(I2C_DELAY); data = (data<<1);
if(digitalRead(SDA_PIN)==1) { data++; }
SCL_0(); delayMicroseconds(I2C_DELAY); }
/* if CONTINUE then send AKNOWLEDGE else if QUIT do not send
AKNOWLEDGE (send Nack) */
if(ack==I2C_CONTINUE) { SDA_0(); } else { SDA_1(); }
SCL_1(); delayMicroseconds(I2C_DELAY); SCL_0();
delayMicroseconds(I2C_DELAY); return data; }
/*###########################################*/
3.3.4 Program for EEPROM 24C256
interface
This program simply writes one byte at the beginning (setup) and in
loop it reads it from same memory address.
#include "i2c.h"
void setup() {
delay(1); Serial.begin(115200); Serial.println(""); //Pin SCL and SDA
Connections are defined in header file i2c_init(); //Initialize I2C
Serial.println("I2C Initialized"); Serial.println("Writing Data: 123");
Write_EEPROM(0,123); //Data to write }
void loop() {
Serial.print("Reading Data: "); Serial.println(Read_EEPROM(0));
delay(1000);
void Write_EEPROM(int add, char data) {
int temp1,addH,addL; addH = (add & 0xFF00); addH = addH >> 8; addL =
(add & 0x00FF); I2C_START_TX(0b10100000); //Device address with read
command i2c_transmit(addH); //Send Word Address i2c_transmit(addL);
i2c_transmit(data); //Send data to write i2c_stop(); delay(20); //Wait for
EEPROM to write data }
int Read_EEPROM(int add) {
int data,addH,addL; //Dummy Write for addressing addH = (add & 0xFF00);
addH = addH >> 8; addL = (add & 0x00FF); I2C_START_TX(0b10100000);
//Device address with read command i2c_transmit(addH); //Send Word
Address i2c_transmit(addL); //Read Data byte I2C_START_TX(0b10100001);
//Device address with read command data = i2c_receive(0); i2c_stop();
return data; }
Figure 3.5:
Memory Read Write Results
4. Soft Access Point
4.1 Introduction
An access point is a device that creates a wireless local area network,
or WLAN, usually in an office or large building. An access point
connects to a wired router, switch, or hub via an Ethernet cable, and
projects a Wi-Fi signal to a designated area. ESP8266 Wi-Fi Access
point is mainly used for configuration purpose such as SSID and
Password. It does not have any Ethernet connection so we cannot use
it for internet access.
4.2 NodeMCU as Access Point
Example below presents how to configure ESP8266 to run in soft
access point mode so Wi-Fi stations (devices) can connect to it. The
Wi-Fi network established by the soft-AP will be identified with the
SSID (Service Set IDentifier) set during configuration. The network
may be protected with a password. The network may be also open, if
no password is set during configuration.
4.2.1 Wi-Fi Modes
Devices that connect to Wi-Fi network are called stations (STA).
Connection to Wi-Fi is provided by an access point (AP), which acts
as a hub for one or more stations. The access point on the other end is
connected to a wired network. An access point is usually integrated
with a router to provide access from Wi-Fi network to the internet.
Each access point is recognized by a SSID (Service Set IDentifier),
which essentially is the name of network you select when connecting
a device (station) to the Wi-Fi.
ESP8266 module can operate as a station, so we can connect it to the
Wi-Fi network. It can also operate as a soft access point (soft-AP), to
establish its own Wi-Fi network. Therefore we can connect other
stations to such ESP module. ESP8266 is also able to operate both in
station and soft access point mode. This provides possibility of
building e.g. mesh networks.
Wi-Fi Mode can be set in access point, station or both modes.
WiFi.mode(WIFI_AP); //Access Point Only WiFi.mode(WIFI_STA); //Station
Mode Only WiFi.mode(WIFI_AP_STA); //Both Modes AP and STA
Password Protected Network WiFi.softAP(ssid, password); //With
Password Open Network WiFi.softAP(ssid); //No password
4.3 Creating Access Point using
NodeMCU
Enter some meaningful ssid, password and upload sketch.
#include <ESP8266WiFi.h> //Enter SSID and Password for ESP8266
const char* ssid = "ssid_for_AP"; const char* password =
"password_for_AP"; void setup() {
Serial.begin(115200); Serial.println(); Serial.print("Setting soft-AP ... ");
WiFi.softAP(ssid, password); Serial.print("Access Point: "); Serial.print(ssid);
Serial.println(" Started"); }
void loop() {
int dev = WiFi.softAPgetStationNum(); Serial.printf("Devices connected =
%d\n", dev); delay(3000); }
After uploading sketch, open serial monitor. Then take your mobile
phone or a PC, open the list of available access points, find SSID of
ESP and connect to it. This should be reflected on serial monitor as a
new station connected: Stations connected = 0
Stations connected = 1
Stations connected = 1
...
If you have another Wi-Fi station available then connects it as well.
Check serial monitor again where you should now see two stations
reported.
Stations connected = 2
4.4 Results
Figure
4.1: Serial monitor showing connected devices
You can enable debug mode using Serial.setDebugOutput(true);
5. Wi-Fi Station Mode
5.1 Introduction
In this lesson we connect NodeMCU ESP8266 to Wi-Fi Access point
(Wi-Fi router).
5.2 Connecting NodeMCU to Access
Point
Below example shows how to configure ESP8266 to connect with Wi-
Fi access point. The Wi-Fi network is identified with the SSID and
Password. Network may be protected with a password or hidden
network. NodeMCU can connect to hidden network also.
Connect to Password Protected Network WiFi.begin(ssid,
password); //With Password Connect to Open Network
WiFi.begin(ssid); //No password At line const char* ssid = “Wi-Fi-
name” replace Wi-Fi-name and Wi-Fi-password with name and
password of Wi-Fi network you like to connect. Then upload this
sketch to NodeMCU module and open serial monitor.
#include <ESP8266WiFi.h> //Enter SSID and Password of your Wi-Fi Router
const char* ssid = "Wi-Fi-name"; const char* password = "Wi-Fi-password";
void setup() {
Serial.begin(115200); Serial.println(); Serial.println("Setting Wi-Fi Mode..");
WiFi.mode(WIFI_STA); //Set Wi-Fi mode as station
WiFi.begin(ssid, password); //Begin Connection Serial.println("Connecting to
"); Serial.print(ssid); while(WiFi.status() != WL_CONNECTED) {
delay(500); Serial.print("."); }
Serial.print("Connected, IP address: "); Serial.println(WiFi.localIP());
//Display IP assigned by Wi-Fi Router }
void loop() {
Serial.printf("Signal Strength in dB = %d\n", WiFi.RSSI()); delay(3000); }
Figure
5.1: Wi-Fi Hotspot Connect and Signal Strength Now let’s check
the use of serial debug. It is Wi-Fi library function of ESP8266.
Upload below code and open serial monitor, you will find that esp is
connecting to your Wi-Fi router. Without coding.
ESP stores the Wi-Fi configuration and library enables it. It is useful
for WDT_reset and other esp reset errors due to invalid commands,
these errors are not visible while compilation.
#include <ESP8266WiFi.h> void setup() {
Serial.begin(115200); Serial.setDebugOutput(true); //Enable Serial Debug of
ESP
Serial.println(); Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP()); //Display IP assigned by Wi-Fi Router }
void loop() {
Serial.printf("Signal Strength in dB = %d\n", WiFi.RSSI()); delay(3000); }
5.4 Wi-Fi Network Scan
ESP8266 NodeMCU Wi-Fi Scanner allows you to easily locate
visible wireless networks and its corresponding information. This
program obtains the network name (SSID), signal strength (RSSI) and
MAC Address, security. Wi-Fi scanner can only start when
NodeMCU is not connected to any network. As we have seen in
previous program, after removing all connection related code esp still
connects to Wi-Fi router. To disconnect ESP from Wi-Fi router use
WiFi.disconnect(); Example Code for Wi-Fi Network Scan
#include <ESP8266WiFi.h> void setup() {
Serial.begin(115200); Serial.println(""); //Remove garbage // Set Wi-Fi to
station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA); //ESP has tendency to store old SSID and PASSword
and tries to connect WiFi.disconnect();
delay(100); Serial.println("Wi-Fi Network Scan Started"); }
void loop() {
// WiFi.scanNetworks will return the number of networks found int n =
WiFi.scanNetworks(); Serial.println("Scan done"); if (n == 0) Serial.println("No
Networks Found"); else {
Serial.print(n); Serial.println(" Networks found"); for (int i = 0; i < n; ++i) {
// Print SSID and RSSI for each network found Serial.print(i + 1); //Sr. No
Serial.print(": "); Serial.print(WiFi.SSID(i)); //SSID
Serial.print(" ("); Serial.print(WiFi.RSSI(i)); //Signal Strength Serial.print(")
MAC:"); Serial.print(WiFi.BSSIDstr(i)); //Display MAC address of Wi-Fi
Router Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?"
Unsecured":" Secured"); //Display Security delay(10); }
}
Serial.println(""); // Wait a bit before starting New scanning again delay(5000);
}
5.5 Results
Upload sketch and open serial monitor.
Figure 5.2:
Network Scan Results
6. Static IP
6.1 Introduction
An IP address, or simply an "IP," is a unique address that identifies
a device on the Internet or a local network. It allows a system to be
recognized by other systems connected via the Internet protocol. In
previous lessons we have seen IP address of NodeMCU.
To get dynamically assigned IP of NodeMCU simply use
Serial.println(WiFi.localIP()); //Display IP assigned by Wi-Fi Router
When NodeMCU works in AP (Access point mode) default IP address
of ESP is 192.168.4.1
6.2 Connecting NodeMCU to Access
Point with Static IP
Below example shows how to configure ESP8266 to connect with Wi-
Fi access point with static IP configuration. Static IP is required in IoT
based network because we identify devices based on their IP
addresses. Another way to identify device is using name system like
we use for websites called “Domain Names” that we discuss in next
chapter.
Configuring ESP to use Static IP address using below command
NodeMCU can be configured to use static IP address.
WiFi.config(staticIP, subnet, gateway, dns);
At line const char* ssid = “Wi-Fi-name” replace Wi-Fi-name and
Wi-Fi-password with name and password to the Wi-Fi network you
like to connect.
Change IP configuration as per your Wi-Fi router IP series. Then
upload this sketch to NodeMCU module and open serial monitor.
#include <ESP8266WiFi.h> //Static IP address configuration IPAddress
staticIP(192, 168, 43, 123); //ESP static ip IPAddress gateway(192, 168, 43,
1); //IP Address of your Wi-Fi Router (Gateway) IPAddress subnet(255, 255,
255, 0); //Subnet mask IPAddress dns(8, 8, 8, 8); //DNS defaut const char*
deviceName = "circuits4you.com"; //used to identify in router //On board LED
Connected to GPIO2
#define LED 2
//SSID and Password of your Wi-Fi router const char* ssid = "Wi-Fi-name";
const char* password = "Wi-Fi-password"; void setup(void){
Serial.begin(115200); Serial.println(""); //Prevent connecting to Wi-Fi based
on previous configuration WiFi.disconnect();
// DHCP Hostname (useful for finding device for static lease)
WiFi.hostname(deviceName);
WiFi.config(staticIP, subnet, gateway, dns); WiFi.begin(ssid, password);
WiFi.mode(WIFI_STA); //Wi-Fi mode station (connect to Wi-Fi router only //
Wait for connection while (WiFi.status() != WL_CONNECTED) {
delay(500); Serial.print("."); }
//If connection successful show IP address in serial monitor Serial.println("");
Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: ");
Serial.println(WiFi.localIP()); //IP address assigned to your ESP
//============================================================
// LOOP
//============================================================
void loop(void){
//Nothing to do here delay(1000); }
Figure 6.1: IP
Assigned to NodeMCU
7. mDNS
7.1 Introduction
In networking world it is difficult to remember ip address of each
website and computer, to solve this problem Domain Name System
(DNS) is used to make human understandable names such as Google,
yahoo, Facebook. In ESP8266 when using ESP as web server, It is
difficult to remember ip address of ESP8266 and also it is difficult to
identify ip address of each ESP in DHCP mode. i.e. Wi-Fi router
assigns IP address to ESP8266. Most ESP8266 application doesn’t
have display interface and they are not easy to access to know its IP
address. To overcome this problem mDNS is used.
What is mDNS?
As networked devices become smaller, more portable, and more
ubiquitous, the ability to operate with less configured infrastructure is
increasingly important. In particular, the ability to look up DNS
resource record data types (including, but not limited to, host names)
in the absence of a conventional managed DNS server is useful.
Multicast DNS (mDNS) provides the ability to perform DNS-like
operations on the local link in the absence of any conventional
Unicast DNS server. In addition, Multicast DNS designates a portion
of the DNS namespace to be free for local use, without the need to
pay any annual fee, and without the need to set up delegations or
otherwise configure a conventional DNS server to answer for those
names.
The primary benefits of Multicast DNS names are that
1. They require little or no administration or configuration to
set them up,
2. They work when no infrastructure is present, and
3. They work during infrastructure failures.
7.2 Configuring NodeMCU to use mDNS
Below example shows how to configure ESP8266 to use mDNS.
Configuring ESP to use mDNS
Library required #include <ESP8266mDNS.h> using below command
NodeMCU can be configured to use static IP address.
MDNS.begin("esp8266")
At line const char* wifiName = “Wi-Fi-name” replace Wi-Fi-name
and Wi-Fi-password with name and password to the Wi-Fi network
you like to connect.
Program for mDNS demo
/*
/*
Figure 8.1:
NodeMCU MAC Address
9. HTTP
9.1 Introduction
HTTP is the underlying protocol used by the World Wide Web and
this protocol defines how messages are formatted and transmitted, and
what actions Web servers and browsers should take in response to
various commands. With help of HTTP we look for more web related
functions such as serving HTML web pages, redirect and handling not
found. In next chapter HTTP methods are explain GET and POST.
9.2 Sending plain text to Client
Web server requires <ESP8266WebServer.h> library. Its object is
defined using ESP8266WebServer server(80); After defining object in
setup define functions to handle web requests present on root.
server.on("/", handleRoot); The “/” represents root location i.e. IP
address, after that start the web server using server.begin(); In loop we
have to handle client request using server.handleClient(); In function
to handle client requests i.e. handleRoot we send plain text to the web
browser . 200 is OK response
//Handles http request void handleRoot() {
digitalWrite(2, 0); //Blinks on board led on page request server.send(200,
"text/plain", "hello from esp8266!"); digitalWrite(2, 1); }
9.2.1 Program for sending Plain text
Change Wi-Fi-name and Wi-Fi-password as per your Wi-Fi router
configuration.
/*
/*
Figure 9.2:
HTML Web Page Web Sever demo
9.4 Redirect and Handle Not found web
requests
Redirects are useful when using web forms. A server side redirect is
a method of URL redirection using an HTTP status code (e.g., 301
Moved Permanently, 303 See Other and 307 Temporary Redirect)
issued by a web server in response to a request for a particular URL.
The result is to redirect user's web browser to another web page with
a different URL
Similar to previous example, here the server is on two locations i.e.
root and handleNotFound.
//Initialize Webserver server.on("/",handleRoot);
server.onNotFound(handleNotFound); //Handles Not found links server.begin();
9.4.1 Program for handling not found links
and redirect
This program contains both redirect and custom not found example.
Modify handleNotFound subroutine.
1. For Redirect broken links
void handleNotFound() {
server.sendHeader("Location", "/",true); //Redirect to our html web page
server.send(302, "text/plane",""); //302 is redirect }
2. For custom 404 error message
//Handles http request void handleNotFound() {
//Use this for custom messages for Error 404
digitalWrite(2, 0); //Blinks on board led on page request server.send(200,
"text/html", htmlNotFoundPage); digitalWrite(2, 1); }
Handing Not Found Pages Complete Code Complete code for
handling not found and redirect. Change Wi-Fi-name and Wi-Fi-
password as per your Wi-Fi router configuration.
/*
// the setup function runs once when you press reset or power the board void
setup() {
Serial.begin(115200); delay(10); pinMode(2,OUTPUT); Serial.println();
Serial.print("Connecting"); WiFi.begin(wifiName, wifiPass); //Connect to Wi-
Fi while (WiFi.status() != WL_CONNECTED) {
delay(500); Serial.print("."); }
Serial.println(""); Serial.println("Wi-Fi connected"); Serial.println("IP address:
"); Serial.println(WiFi.localIP()); //You can get IP address assigned to ESP
server.on("/", handleRoot); //Associate handler function to web requests
server.onNotFound(handleNotFound); //Handle not found links server.begin();
//Start web server Serial.println("HTTP server started"); }
void loop() {
//Handle Clinet requests server.handleClient(); }
9.4.2 Results
Get IP address from serial monitor and open it in web browser.
Program 1: Redirect
In redirect program when broken link is clicked page comes back to
root location again.
/*
void loop() {
HTTPClient http; //Declare object of class HTTPClient String ADCData =
String(analogRead(A0)); String getData, Link; //GET Data //Note "?" added at
front and "&" is used after each new parameter as per GET format getData = "?
data=" + ADCData + "&sensor=temperature";
Link = host + getData; Serial.print("Request Link:"); Serial.println(Link);
http.begin(Link); //Specify request destination int httpCode =
http.GET(); //Send the request String payload = http.getString(); //Get
the response payload from server Serial.print("Response Code:"); //200 is OK
Serial.println(httpCode); //Print HTTP return code Serial.print("Returned data
from Server:"); Serial.println(payload); //Print request response payload
http.end(); //Close connection delay(5000); //GET Data at every 5 seconds }
10.2.1 Results
Open serial monitor and observe the response. Try same link in web
browser it should return same response same as we are getting in ESP
serial monitor.
Figure
10.1: Serial Monitor with GET request results
10.3 Handling GET request sent to
NodeMCU
In previous chapter we made NodeMCU as Server. Now we handle
GET request sent to NodeMCU from a client. To demonstrate this we
turn on/off on board LED using GET request “?LED=on”.
10.3.1 Program to handle GET requests
In program change Wi-Fi-name and Wi-Fi-password as per your Wi-
Fi router configuration.
/*
Figure 10.2:
/*
void loop() {
HTTPClient http; //Declare object of class HTTPClient String ADCData =
String(analogRead(A0)); String postData; //POST Data postData = "data=" +
ADCData + "&sensor=temperature";
Serial.print("Post Data:"); Serial.println(postData); http.begin(host); //Specify
request destination http.addHeader("Content-Type", "application/x-www-form-
urlencoded"); //Specify content-type header int httpCode =
http.POST(postData); //Send the request String payload = http.getString();
//Get the response payload Serial.print("Response Code:"); //200 is OK
Serial.println(httpCode); //Print HTTP return code Serial.print("Returned data
from Server:"); Serial.println(payload); //Print request response payload
http.end(); //Close connection delay(5000); //POST Data at every 5 seconds }
Figure 11.1:
POST Request Response from server
11.3 Handling POST request sent to
NodeMCU
In previous chapter we made NodeMCU as Server. Now we handle
POST request sent to NodeMCU from a client.
11.3.1 Program to handle POST requests
In program change Wi-Fi-name and Wi-Fi-password as per your Wi-
Fi router configuration. The program is same as GET request handler
except we are sending POST request using web forms. HTML web
page code is only changed. Button Name is kept same and its value is
changed while using server.arg(“LED”); use name of the html form
component to read value from it. It is possible to have multiple
arguments with different value. Just add multiple lines of
server.arg(“name of component”).
<BUTTON name="LED" value="1">ON</BUTTON>
<BUTTON name="LED" value="0">OFF</BUTTON>
/*
Figure 11.2:
LED Control using POST Request
12. JSON
12.1 Introduction
JSON (JavaScript Object Notation) is a lightweight data-interchange
format. It is easy for humans to read and write. It is easy for machines
to parse and generate. It is based on a subset of the JavaScript
Programming Language, Standard ECMA-262 3rd Edition -
December 1999. JSON is a text format that is completely language
independent but uses conventions that are familiar to programmers of
the C-family of languages, including C, C++, C#, Java, JavaScript,
Perl, Python, and many others. These properties make JSON an ideal
data-interchange language.
[ref https://www.json.org/]
JSON is built on two structures:
A collection of name/value pairs. In various languages, this
is realized as an object, record, struct, dictionary, hash table,
keyed list, or associative array.
An ordered list of values. In most languages, this is realized
as an array, vector, list, or sequence.
These are universal data structures. Virtually all modern programming
languages support them in one form or another. It makes sense that a
data format that is interchangeable with programming languages also
be based on these structures.
Example : { "name":"John", "age":31, "city":"New York" }
In JSON, they take on these forms: An object is an unordered set of
name/value pairs. An object begins with { (left brace) and ends with }
(right brace). Each name is followed by : (colon) and the name/value
pairs are separated by , (comma).
An array is an ordered collection of values. An array begins with [
(left bracket) and ends with ] (right bracket). Values are separated by ,
(comma).
Whitespace can be
inserted between any pair of tokens.
12.2 NodeMCU JSON Decode Example
For this program ArduinoJSON library is required. Go to
Sketch>>Include Library>>Manage Libraries..
Figure
12.2: Adding JSON Library to ArduinoIDE
This program makes NodeMCU as a client to send http request to web
server (similar to your web browser) and gets JSON response from it
and decodes it. In program change Wi-Fi-name and Wi-Fi-password
as per your Wi-Fi router configuration.
/*
void loop() {
HTTPClient http; //Declare object of class HTTPClient Serial.print("Request
Link:"); Serial.println(host); http.begin(host); //Specify request destination int
httpCode = http.GET(); //Send the request String payload =
http.getString(); //Get the response payload from server Serial.print("Response
Code:"); //200 is OK
Serial.println(httpCode); //Print HTTP return code Serial.print("Returned data
from Server:"); Serial.println(payload); //Print request response payload
if(httpCode == 200) {
// Allocate JsonBuffer // Use arduinojson.org/assistant to compute the
capacity.
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2)
+ 60; DynamicJsonBuffer jsonBuffer(capacity); // Parse JSON object
JsonObject& root = jsonBuffer.parseObject(payload); if (!root.success()) {
Serial.println(F("Parsing failed!")); return; }
// Decode JSON/Extract values Serial.println(F("Response:"));
Serial.println(root["sensor"].as<char*>());
Serial.println(root["time"].as<char*>()); Serial.println(root["data"]
[0].as<char*>()); Serial.println(root["data"][1].as<char*>()); }
else {
Serial.println("Error in response"); }
http.end(); //Close connection delay(5000); //GET Data at every 5 seconds }
12.2.1 Results
Open serial monitor and observe the response. Try same link
(http://arduinojson.org/example.json) in web browser it should return
JSON response same as we are getting in ESP serial monitor.
Figure
12.3: JSON Decode result
12.3 NodeMCU JSON Encode Example
In program change Wi-Fi-name and Wi-Fi-password as per your Wi-
Fi router configuration. This example shows how to encode Analog
and digital value with example of ADC and Flash button.
Example Encoded JSON: {"ADC":0,"KEY":0}
/*
Figure 12.4:
JSON Encode Results
13. Java Scripts
13.1 Introduction
JavaScript is a programming language that adds interactivity to your
website (for example: games, responses when buttons are pressed or
data entered in forms, dynamic styling, and animation). This article
helps you get started with this exciting language and gives you an idea
of what is possible.
JavaScript ("JS" for short) is a full-fledged dynamic programming
language that, when applied to an HTML document, can provide
dynamic interactivity on websites. It was invented by Brendan Eich,
co-founder of the Mozilla project, the Mozilla Foundation, and the
Mozilla Corporation.
JavaScript is incredibly versatile. You can start small, with carousels,
image galleries, fluctuating layouts, and responses to button clicks.
With more experience, you'll be able to create games, animated 2D
and 3D graphics, comprehensive database-driven apps, and much
more!
JavaScript itself is fairly compact yet very flexible. Developers have
written a large variety of tools on top of the core JavaScript language,
unlocking a vast amount of extra functionality with minimum effort.
These include:
Browser Application Programming Interfaces (APIs) —
APIs built into web browsers, providing functionality like
dynamically creating HTML and setting CSS styles,
collecting and manipulating a video stream from the user's
webcam, or generating 3D graphics and audio samples.
Third-party APIs to allow developers to incorporate
functionality in their sites from other content providers,
such as Twitter or Facebook.
Third-party frameworks and libraries you can apply to your
HTML to allow you to rapidly build up sites and
applications.
13.2 NodeMCU JavaScript Example
In this Example we build complete paddle ball game using Java
Scripts. The complete JavaScript game building tutorial is available
on Git hub
https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-
pages/lesson10.html
Fist create htmlPage.h header file. Use above link to avoid typing of
large code and modify first and last line as given in below code. We
include this as header in program memory. Program is build using
two parts first is htmlPage.h contains all web pages and JavaScript’s
and NodeMCU code handles web server and Wi-Fi. JavaScript are
executed on client side so NodeMCU only sends Java Script code to
Web browser.
13.2.1 htmlPage.h
const char webPage[] PROGMEM = R"=====(
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Gamedev
Canvas Workshop - lesson 10: finishing up</title> <style>* { padding: 0;
margin: 0; } canvas { background: #eee; display: block; margin: 0 auto; }
</style> </head> <body> <canvas id="myCanvas" width="480"
height="320"></canvas> <script> var canvas =
document.getElementById("myCanvas"); var ctx = canvas.getContext("2d");
var ballRadius = 10; var x = canvas.width/2; var y = canvas.height-30; var dx
= 2; var dy = -2; var paddleHeight = 10; var paddleWidth = 75; var paddleX =
(canvas.width-paddleWidth)/2; var rightPressed = false; var leftPressed = false;
var brickRowCount = 5; var brickColumnCount = 3; var brickWidth = 75; var
brickHeight = 20; var brickPadding = 10; var brickOffsetTop = 30; var
brickOffsetLeft = 30; var score = 0; var lives = 3; var bricks = []; for(var c=0;
c<brickColumnCount; c++) {
bricks[c] = []; for(var r=0; r<brickRowCount; r++) {
bricks[c][r] = { x: 0, y: 0, status: 1 }; }
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, false);
function keyDownHandler(e) {
if(e.keyCode == 39) {
rightPressed = true; }
else if(e.keyCode == 37) {
leftPressed = true; }
}
function keyUpHandler(e) {
if(e.keyCode == 39) {
rightPressed = false; }
else if(e.keyCode == 37) {
leftPressed = false; }
}
function mouseMoveHandler(e) {
var relativeX = e.clientX - canvas.offsetLeft; if(relativeX > 0 &&
relativeX < canvas.width) {
paddleX = relativeX - paddleWidth/2; }
}
function collisionDetection() {
for(var c=0; c<brickColumnCount; c++) {
for(var r=0; r<brickRowCount; r++) {
var b = bricks[c][r]; if(b.status == 1) {
if(x > b.x && x < b.x+brickWidth && y > b.y && y <
b.y+brickHeight) {
dy = -dy; b.status = 0; score++; if(score ==
brickRowCount*brickColumnCount) {
alert("YOU WIN, CONGRATS!");
document.location.reload(); }
}
}
}
}
}
function drawBall() {
ctx.beginPath(); ctx.arc(x, y, ballRadius, 0, Math.PI*2); ctx.fillStyle =
"#0095DD"; ctx.fill(); ctx.closePath(); }
function drawPaddle() {
ctx.beginPath(); ctx.rect(paddleX, canvas.height-paddleHeight,
paddleWidth, paddleHeight); ctx.fillStyle = "#0095DD"; ctx.fill();
ctx.closePath(); }
function drawBricks() {
for(var c=0; c<brickColumnCount; c++) {
for(var r=0; r<brickRowCount; r++) {
if(bricks[c][r].status == 1) {
var brickX = (r*(brickWidth+brickPadding))+brickOffsetLeft; var
brickY = (c*(brickHeight+brickPadding))+brickOffsetTop; bricks[c][r].x =
brickX; bricks[c][r].y = brickY; ctx.beginPath(); ctx.rect(brickX, brickY,
brickWidth, brickHeight); ctx.fillStyle = "#0095DD"; ctx.fill(); ctx.closePath();
}
}
}
}
function drawScore() {
ctx.font = "16px Arial"; ctx.fillStyle = "#0095DD"; ctx.fillText("Score:
"+score, 8, 20); }
function drawLives() {
ctx.font = "16px Arial"; ctx.fillStyle = "#0095DD"; ctx.fillText("Lives:
"+lives, canvas.width-65, 20); }
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height); drawBricks(); drawBall();
drawPaddle(); drawScore(); drawLives(); collisionDetection(); if(x + dx >
canvas.width-ballRadius || x + dx < ballRadius) {
dx = -dx; }
if(y + dy < ballRadius) {
dy = -dy; }
else if(y + dy > canvas.height-ballRadius) {
if(x > paddleX && x < paddleX + paddleWidth) {
dy = -dy; }
else {
lives--; if(!lives) {
alert("GAME OVER"); document.location.reload(); }
else {
x = canvas.width/2; y = canvas.height-30; dx = 3; dy = -3; paddleX
= (canvas.width-paddleWidth)/2; }
}
}
if(rightPressed && paddleX < canvas.width-paddleWidth) {
paddleX += 7; }
else if(leftPressed && paddleX > 0) {
paddleX -= 7; }
x += dx; y += dy; requestAnimationFrame(draw); }
draw(); </script> </body> </html> )=====";
13.2.2 NodeMCU main file code
Keep header file at same location where .ino file is. Change Wi-Fi-
name and Wi-Fi-password as per your Wi-Fi router configuration.
/*
Figure 13.1:
JavaScript Web Server Results
14. AJAX (Asynchronous JavaScript
and XML)
14.1 Introduction
AJAX stands for Asynchronous JavaScript and XML. AJAX is a new
technique for creating better, faster, and more interactive web
applications with the help of XML, HTML, CSS, and Java Script.
AJAX is a technique for creating fast and dynamic web pages.
AJAX allows web pages to be updated asynchronously by exchanging
small amounts of data with the server behind the scenes. This means
that it is possible to update parts of a web page, without reloading the
whole page.
Classic web pages, (which do not use AJAX) must reload the entire
page if the content should change.
Examples of applications using AJAX: Google Maps, Gmail,
YouTube, and Facebook tabs.
How NodeMCU AJAX Works ?
Figure 14.1:
AJAX Flow Data Flow In ESP8266 NodeMCU we create two pages
on server. First that loads as normal visible webpage and second
webpage is behind the scene i.e. AJAX. With AJAX, JavaScript will
make a request to the server at every two second for ADC data as per
our java script program, interpret the results, and update the current
screen. In the purest sense, the user would never know that anything
was even transmitted to the server.
LED On Off Control Sends GET request with arguments
LEDstate=1 or 0, when button is pressed.
<button type="button" onclick="sendData(1)">LED ON</button> <button
type="button" onclick="sendData(0)">LED OFF</button> function
sendData(led) {
var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("LEDState").innerHTML =
this.responseText; }
}; xhttp.open("GET", "setLED?LEDstate="+led, true); xhttp.send(); }
ADC Value Refresher Sends readADC GET request to NodeMCU at
every two seconds and updates HTML element inner “ADCValue”
data.
setInterval(function() {
// Call a function repetitively with 2 Second interval getData(); }, 2000);
//2000mSeconds update rate function getData() {
var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("ADCValue").innerHTML =
this.responseText; }
}; xhttp.open("GET", "readADC", true); xhttp.send(); }
AJAX is based on internet standards, and uses a combination of:
XMLHttpRequest object (to exchange data asynchronously
with a server)
JavaScript/DOM (to display/interact with the information)
CSS (to style the data)
XML (often used as the format for transferring data)
14.2 NodeMCU AJAX Example
In this Example we build simple LED on/off and ADC value display
in real time. This way both getting data from ESP and Sending data to
ESP can be demonstrated. Program is in two parts HTML web page
and NodeMCU code.
14.2.1 htmlPage.h
const char webPage[] PROGMEM = R"=====(
<!DOCTYPE html> <html> <body> <div id="demo"> <h1>The ESP8266
NodeMCU Update web page without refresh</h1> <button type="button"
onclick="sendData(1)">LED ON</button> <button type="button"
onclick="sendData(0)">LED OFF</button><BR> </div> <div> ADC Value is
: <span id="ADCValue">0</span><br> LED State is : <span
id="LEDState">NA</span> </div> <script> function sendData(led) {
var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("LEDState").innerHTML =
this.responseText; }
}; xhttp.open("GET", "setLED?LEDstate="+led, true); xhttp.send(); }
setInterval(function() {
// Call a function repetitively with 2 Second interval getData(); }, 2000);
//2000mSeconds update rate function getData() {
var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("ADCValue").innerHTML =
this.responseText; }
}; xhttp.open("GET", "readADC", true); xhttp.send(); }
</script> <br><br><a href="https://circuits4you.com">Circuits4you.com</a>
</body> </html> )=====";
14.2.2 NodeMCU AJAX Example code
Keep header file at same location where .ino file is. Change Wi-Fi-
name and Wi-Fi-password as per your Wi-Fi router configuration.
/*
Figure 14.2:
AJAX Web Page
15. JQuery
15.1 Introduction
jQuery is not a language, but it is a well written JavaScript code. As
quoted on official jQuery website, "it is a fast and concise JavaScript
Library that simplifies HTML document traversing, event handling,
animating, and Ajax interactions for rapid web development"
15.2 NodeMCU JQuery using CDN
example
In this example we are making simple calculator using jQuery. jQuery
is imported in HTML page using CDN (Content Delivery Network),
for this demo active internet connection is required, to use jQuery
without internet is shown on my web site using SPIFFS.
15.2.1 htmlPage.h
Use source link https://codepen.io/mattboldt/pen/aoKkH and copy
paste code parts as shown in below
//Source Link: https://codepen.io/mattboldt/pen/aoKkH
const char webPage[] PROGMEM = R"=====(
<html> <head> <script
src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<style> body{
background-image: -moz-linear-gradient(top, #137cbc 0%, #30a3d3 25%,
#4ba4be 35%, #4094a1 40%, #c2c7aa 50%, #beaa79 100%); background-
image: -webkit-linear-gradient(top, #137cbc 0%, #30a3d3 25%, #4ba4be 35%,
#4094a1 40%, #c2c7aa 50%, #beaa79 100%); background-image: linear-
gradient(top, #137cbc 0%, #30a3d3 25%, #4ba4be 35%, #4094a1 40%, #c2c7aa
50%, #beaa79 100%); background-attachment: fixed; background-repeat:
no-repeat; color:#c0c0c0; font-family: "Helvetica Neue", Arial, sans-serif;
font-weight: 300; font-size:100%; letter-spacing: 1.2px; }
.wrap{
width:480px; margin:50px auto 0; }
.cal{
width:480px; height:auto; padding:10px 0; margin: auto;
background:#232323; border:#000 1px solid; border-radius:7px; -webkit-
border-radius:7px; -moz-border-radius:7px; box-shadow:rgba(0,0,0,0.4) 0px
2px 5px, inset rgba(255,255,255,0.9) 0px 1px 1px -1px; -webkit-box-
shadow:rgba(0,0,0,0.4) 0px 2px 5px, inset rgba(255,255,255,0.9) 0px 1px 1px
-1px; -moz-box-shadow:rgba(0,0,0,0.4) 0px 2px 5px, inset
rgba(255,255,255,0.9) 0px 1px 1px -1px; background-image:-moz-linear-
gradient(top, #333333, #1f1f1f); background-image:-webkit-linear-
gradient(top, #333333, #1f1f1f); background-image:linear-gradient(top,
#333333, #1f1f1f); overflow: hidden; text-align: center; }
.screen{
width:424px; height:93px; margin: 12px auto 30px; padding:15px 20px;
color:#c0c0c0; text-align: right; font-size: 3em; letter-spacing: 3px;
overflow:hidden; border:#000 1px solid; border-radius:7px; -webkit-border-
radius:7px; -moz-border-radius:7px; box-shadow:inset rgba(0,0,0,1) 0px 1px
4px, inset rgba(225,225,225,0.3) 0px -2px 4px -2px; -webkit-box-shadow:inset
rgba(0,0,0,1) 0px 1px 4px, inset rgba(225,225,225,0.3) 0px -2px 4px -2px; -
moz-box-shadow:inset rgba(0,0,0,1) 0px 1px 4px, inset rgba(225,225,225,0.3)
0px -2px 4px -2px; background-image: -moz-linear-gradient(top, #3e3e3e 0%,
#303030 100%); background-image: -webkit-linear-gradient(top, #3e3e3e 0%,
#303030 100%); background-image: linear-gradient(top, #3e3e3e 0%,
#303030 100%); -moz-box-sizing:border-box; -webkit-box-sizing:border-box;
box-sizing:border-box; }
.title{
font-size: 1.2em; }
.buttons{
padding:0; width:423px; margin:auto; overflow: hidden; list-style: none; }
.buttons li{
display:inline; float:left; padding:0px; margin-right:13px; margin-
bottom:10px; }
/* remove margin-right on every fourth button */
.buttons li:nth-child(4n){
margin-right:0; }
.buttons a{
display:block; width:95px; height:68px; padding:18px 0 12px;
color:#c0c0c0; font-family: "Myriad Pro", Arial, sans-serif; font-size:1.6em;
font-weight: 500; letter-spacing: -2px; background-color:#2f2f2f; border:
#000 1px solid; border-radius:5px; -webkit-border-radius:5px; -moz-border-
radius:5px; text-align: center; text-decoration: none; text-shadow:#000 0px
-1px 0px; box-shadow: inset rgba(255,255,255,0.1) 0px 1px 0px, inset
rgba(0,0,0,0.2) 0px -2px 2px; -webkit-box-shadow: inset rgba(255,255,255,0.1)
0px 1px 0px, inset rgba(0,0,0,0.2) 0px -2px 2px; -moz-box-shadow: inset
rgba(255,255,255,0.1) 0px 1px 0px, inset rgba(0,0,0,0.2) 0px -2px 2px;
background-image:-moz-linear-gradient(top, #363636 0%, #313234 40%,
#2f2f2f 100%); background-image:-webkit-linear-gradient(top, #363636 0%,
#313234 40%, #2f2f2f 100%); background-image:linear-gradient(top, #363636
0%, #313234 40%, #2f2f2f 100%); -moz-box-sizing:border-box; -webkit-box-
sizing:border-box; box-sizing:border-box; cursor: pointer; }
.buttons a:active{
box-shadow: inset rgba(0,0,0,0.5) 0px 2px 8px; background-image:-moz-
linear-gradient(top, #2f2f2f 0%, #363636 100%); background-image:-webkit-
linear-gradient(top, #2f2f2f 0%, #363636 100%); background-image:linear-
gradient(top, #2f2f2f 0%, #363636 100%); }
/* tall = button */
.tall{height:151px !important;}
/* Wide 0 */
.wide{width:205px !important;}
/* shift last row up, because the tall button pushes it down */
.shift{margin-top:-78px;}
/* close, min, max buttons */
.ctrls{
list-style: none; margin:5px 0 0 20px; padding:0; position: absolute; }
.ctrls li{
float:left; display:inline; }
.ctrls li a{
display: block; width:18px; height:18px; margin-right:10px; border-
radius:100%; box-shadow:rgba(255,255,255,0.3) 0px 0px 1px, inset
rgba(0,0,0,1) 0px 1px 2px 1px; background-image: -moz-radial-gradient( 9px
-4px, #FFF 0px, #fff 2px, rgba(255,255,255,0) 4px), -moz-linear-
gradient(bottom, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%);
background-image: -webkit-radial-gradient( 9px -4px, #FFF 0px, #fff 2px,
rgba(255,255,255,0) 4px), -webkit-linear-gradient(bottom,
rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); background-image:
radial-gradient( 9px -4px, #FFF 0px, #fff 2px, rgba(255,255,255,0) 4px), linear-
gradient(bottom, rgba(255,255,255,0.5) 0%, rgba(255,255,255,0) 100%); }
.close a{
background-color:#f32c31; }
.min a{background-color:#f7bf67;}
.max a{background-color:#89cb5a;}
.h1{
text-align: center; color:#fff; font-weight: 400; font-size: 4em; line-height:
0; margin-top:80px; margin-bottom:-60px; text-shadow:#000 0px -1px 0px; }
p{
color:#fff; text-shadow: #999 0px -1px 0px; font-size:1.2em; line-height:
2em; }
a{
color:#953b3b; }
</style> </head> <body> <div class="wrap"> <div class="cal"> <ul
class="ctrls"> <li class="close"><a href="#"></a></li> <li class="min"><a
href="#"></a></li> <li class="max"><a href="#"></a></li> </ul> <span
class="title">Calculator</span> <div class="screen">2+2</div> <input
type="hidden" class="outcome" value="2+2" /> <ul class="buttons"> <li><a
class="clear">C</a></li> <li><a class="val" href="-">±</a></li> <li>
<a class="val" href="/">÷</a></li> <li><a class="val"
href="*">×</a></li> <li><a class="val" href="7">7</a></li> <li><a
class="val" href="8">8</a></li> <li><a class="val" href="9">9</a></li> <li>
<a class="val" href="-">-</a></li> <li><a class="val" href="4">4</a></li>
<li><a class="val" href="5">5</a></li> <li><a class="val" href="6">6</a>
</li> <li><a class="val" href="+">+</a></li> <li><a class="val"
href="1">1</a></li> <li><a class="val" href="2">2</a></li> <li><a
class="val" href="3">3</a></li> <li><a class="equal tall">=</a></li> <li><a
class="val wide shift" href="0">0</a></li> <li><a class="val shift" href=".">.
</a></li> </ul> </div> <script> $(function(){
// when a value is clicked $(".val").click(function(e){
// prevent the link from acting like a link e.preventDefault(); //grab this link's
href value var a = $(this).attr("href"); // append said value to the screen
$(".screen").append(a); // append same value to a hidden input
$(".outcome").val($(".outcome").val() + a); }); // when equals is clicked
$(".equal").click(function(){
// solve equation and put in hidden field
$(".outcome").val(eval($(".outcome").val())); // take hidden field's value & put
it on screen $(".screen").html(eval($(".outcome").val())); }); // clear field
$(".clear").click(function(){
$(".outcome").val(""); $(".screen").html(""); }); // minimize (looks kinda
cool?) $(".min").click(function(){
$(".cal").stop().animate({
width: "0px", height: "0px", marginLeft: "700px", marginTop: "1000px"
}, 500); setTimeout(function(){$(".cal").css("display", "none")}, 600); });
//close window. refresh to get back $(".close").click(function(){
$(".cal").css("display", "none"); }) }) </script> </body> </html> )=====";
15.2.2 NodeMCU JQuery example code
Change Wi-Fi-name and Wi-Fi-password as per your Wi-Fi router
configuration.
/*
UDP is stateless.
/*
}
16.3 Results
After uploading open serial monitor and test program with packet
sender program or using Linux commands, Use port no. 2000.
To send UDP packet use
$echo "Test" > devudp/192.168.43.19/2000
To see data recived use
$sudo tcpdump -i wlp3s0 -n udp port 2000 -X
Data recived by NodeMCU is shown in serial monitor and data sent
from serial monitor will be visible in UDP packet receiver.
17. NTP
17.1 Introduction
This lesson we learn how to get Network Time using NTP (Network
Time Protocol) ? Getting network time is much simpler than adding
external RTC Chip to NodeMCU. Use of NTP with ESP8266 makes
getting time simpler and accurate. Before we start we must know what
is NTP and How to get NTP Time in NodeMCU.
17.1.1 What is NTP?
The Network Time Protocol (NTP) is widely used to synchronize
computer clocks in the Internet. NTP is intended to synchronize all
participating computers to within a few milliseconds of Coordinated
Universal Time (UTC).
17.1.2 What is NTP Server?
NTP uses the concepts of server and client. A server is a source of
time information, and a client is a system that is attempting to
synchronize its clock to a server.
17.1.3 What is NTP Port?
OpenNTPD also uses high-numbered source ports so if it is able to
synchronize but ntpd is not, it is very probable that the incoming UDP
port 123 is blocked. If you’re going to run ntpd , you need to fix your
network/firewall/NAT so that ntpd can have full unrestricted access to
UDP port 123 in both directions.
17.1.4 How NTP UDP Protocol Works?
for more details read RFC958
The NTP packets sent by the client to the server and the responses
from the server to the client use a common format, as shown in
Figure.
/*
//============================================================
void setup() {
Serial.begin(115200); Serial.println(); Serial.println(); // We start by
connecting to a Wi-Fi network Serial.print("Connecting to ");
Serial.println(ssid); WiFi.mode(WIFI_STA); WiFi.begin(ssid, pass); while
(WiFi.status() != WL_CONNECTED) {
delay(500); Serial.print("."); }
Serial.println(""); Serial.println("Wi-Fi connected"); Serial.println("IP address:
"); Serial.println(WiFi.localIP()); Serial.println("Starting UDP");
udp.begin(localPort); Serial.print("Local port: "); Serial.println(udp.localPort());
}
//=============================================================
//============================================================
// LOOP
//============================================================
void loop() {
char hours, minutes, seconds; //get a random server from the pool
WiFi.hostByName(ntpServerName, timeServerIP);
sendNTPpacket(timeServerIP); // send an NTP packet to a time server // wait to
see if a reply is available delay(1000); int cb = udp.parsePacket(); if (!cb) {
Serial.println("no packet yet"); }
else {
Serial.print("packet received, length="); Serial.println(cb); // We've received
a packet, read the data from it udp.read(packetBuffer, NTP_PACKET_SIZE); //
read the packet into the buffer //the timestamp starts at byte 40 of the received
packet and is four bytes, // or two words, long. First, extract the two words:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); //
combine the four bytes (two words) into a long integer // this is NTP time
(seconds since Jan 1 1900): unsigned long secsSince1900 = highWord << 16 |
lowWord; Serial.print("Seconds since Jan 1 1900 = " );
Serial.println(secsSince1900); // now convert NTP time into everyday time:
Serial.print("Unix time = "); // Unix time starts on Jan 1 1970. In seconds, that's
2208988800: const unsigned long seventyYears = 2208988800UL; // subtract
seventy years: unsigned long epoch = secsSince1900 - seventyYears; // print
Unix time: Serial.println(epoch); // print the hour, minute and second: minutes =
((epoch % 3600) / 60); minutes = minutes + MM; //Add UTC Time Zone hours
= (epoch % 86400L) / 3600;
if(minutes > 59) {
hours = hours + HH + 1; //Add UTC Time Zone minutes = minutes - 60; }
else {
hours = hours + HH; }
Serial.print("The UTC time is "); // UTC is the time at Greenwich
Meridian (GMT) Serial.print(hours,DEC); // print the hour (86400 equals secs
per day) Serial.print(':'); if ( minutes < 10 ) {
// In the first 10 minutes of each hour, we'll want a leading '0'
Serial.print('0'); }
Serial.print(minutes,DEC); // print the minute (3600 equals secs per minute)
Serial.print(':'); seconds = (epoch % 60); if ( seconds < 10 ) {
// In the first 10 seconds of each minute, we'll want a leading '0'
Serial.print('0'); }
Serial.println(seconds,DEC); // print the second }
// wait ten seconds before asking for the time again delay(10000); }
//==============================================================
17.3 Results
Upload program and open serial monitor, It will get time from internet
(NTP Server) and displays.
exists
SPIFFS.exists(path) Returns true if a file with given path exists, false
otherwise.
openDir
SPIFFS.openDir(path) Opens a directory given its absolute path.
Returns a Dir object.
remove
SPIFFS.remove(path) Deletes the file given its absolute path. Returns
true if file was deleted successfully.
rename
SPIFFS.rename(pathFrom, pathTo) Renames file from pathFrom to
pathTo. Paths must be absolute. Returns true if file was renamed
successfully.
seek
file.seek(offset, mode) This function behaves like fseek C function.
Depending on the value of mode, it moves current position in a file as
follows:
if mode is SeekSet, position is set to offset bytes from the
beginning.
if mode is SeekCur, current position is moved by offset
bytes.
if mode is SeekEnd, position is set to offset bytes from the
end of the file.
Returns true if position was set successfully.
position
file.position() Returns the current position inside the file, in bytes.
size
file.size() Returns file size, in bytes.
name
String name = file.name(); Returns file name, as const char*. Convert
it to String for storage.
close
file.close() Close the file. No other operations should be performed on
File object after close function was called.
18.3 NodeMCU SPIFFS example code
/*
}
void loop() {
int i; //Read File data File f = SPIFFS.open(filename, "r"); if (!f) {
Serial.println("file open failed"); }
else {
Serial.println("Reading Data from File:");
//Data from file for(i=0;i<f.size();i++) //Read upto complete file size {
Serial.print((char)f.read()); }
f.close(); //Close file Serial.println("File Closed"); }
delay(5000); }
18.4 Results
Figure 18.2:
jar File Location in Arduino Sketch folder
Restart Arduino IDE
Open a sketch (or create a new one and save it)
Go to sketch directory (choose Sketch > Show Sketch
Folder)
Create a directory named data and put your files (ex.
notes.txt) you want in the file system there
Figure 18.3: sketch data folder location
Make sure you have selected a board, port, and closed
Serial Monitor
Select Tools > ESP8266 Sketch Data Upload. This should
start uploading the files into ESP8266 flash file system.
When done, IDE status bar will display SPIFFS Image
Uploaded message. Note during upload it takes longer time.
Figure 18.4:
Sketch Data Upload Option
18.5 Reading uploaded file
Upload sketch in NodeMCU. Uploading of sketch process will not
delete/affect Sketch Data i.e. our uploaded file.
/*
}
18.6 Results
Open serial monitor and press reset button on ESP. Serial monitor will
show contents of the File.
Figure 18.5:
Reading contents of directly uploaded file
19. Smart Config
19.1 Introduction
Espressif Systems developed the ESP-TOUCH protocol to seamlessly
configure Wi-Fi devices to connect to the router. This is particularly
important for headless systems, because of the lack of a user interface.
Espressif’s ESP-TOUCH protocol implements Smart Config
technology to help users connect ESP8266 devices to a Wi-Fi network
through simple configuration on a smartphone. Since the ESP8266 is
not connected to the network at the beginning, the user application
cannot send the information to the device directly.
With ESP-TOUCH communication protocol, a Wi-Fi enabled device
such as a smartphone sends UDP packets to the Wi-Fi Access Point
(AP), and encodes the SSID and password into the Length field of a
sequence of UDP packets where the ESP8266 device can reach and
decode the information.
Figure
19.1: UDP Packet format
19.2 Smart Config Example
This example shows how NodeMCU gets SSID and Password of Wi-
Fi router from the mobile app.
/*
/*
* ESP8266 Communication and Protocols * WebSocket Example * -Manoj
R. Thakur */
#include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include
<ESP8266mDNS.h> #include <WebSocketsServer.h> #include "index.h"
//Web page with client side socket handling scripts ESP8266WebServer
server(80); // create a web server on port 80
WebSocketsServer webSocket = WebSocketsServer(81); // create a websocket
server on port 81
const char *ssid = "wifi_ssid"; // The name of the Wi-Fi network that will be
created const char *password = "Wi-Fi-password"; // The password required
to connect to it, leave blank for an open network const char* mdnsName =
"esp8266"; // Domain name for the mDNS responder void setup() {
Serial.begin(115200); // Start the Serial communication to send messages
to the computer delay(10); Serial.println("\r\n"); startWiFi(); // Start a
Wi-Fi access point, and try to connect to some given access points. Then wait
for either an AP or STA connection startWebSocket(); // Start a
WebSocket server startMDNS(); // Start the mDNS responder
startServer(); // Start a HTTP server with a file read handler and an
upload handler }
void startWiFi() { // Start a Wi-Fi access point, and try to connect to some given
access points. Then wait for either an AP or STA connection WiFi.begin(ssid,
password); Serial.println("Connecting"); while (WiFi.status() !=
WL_CONNECTED) {
delay(500); Serial.print("."); }
Serial.println("\r\n"); Serial.print("IP:"); Serial.println(WiFi.localIP()); }
void startWebSocket() { // Start a WebSocket server
webSocket.begin(); // start the websocket server
webSocket.onEvent(webSocketEvent); // if there's an incoming websocket
message, go to function 'webSocketEvent'
Serial.println("WebSocket server started."); }
void startMDNS() { // Start the mDNS responder
MDNS.begin(mdnsName); // start the multicast domain name
server Serial.print("mDNS responder started: http://"); Serial.print(mdnsName);
Serial.println(".local"); }
void handleRoot() {
String s = MAIN_page; server.send(200, "text/html", s); }
void startServer() { // Start a HTTP server with a file read handler and an upload
handler server.onNotFound(handleNotFound); // if someone requests any
other file or page, go to function 'handleNotFound'
server.on("/",handleRoot); server.begin(); // start the HTTP
server Serial.println("HTTP server started."); }
unsigned long prevMillis = millis(); void loop() {
webSocket.loop(); // constantly check for websocket events
server.handleClient(); // run the server }
void handleNotFound(){ // if the requested file or page doesn't exist, return a
404 not found error server.send(404, "text/plain", "404: File Not Found"); }
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t
lenght) { // When a WebSocket message is received switch (type) {
case WStype_DISCONNECTED: // if the websocket is disconnected
Serial.printf("[%u] Disconnected!\n", num); break; case
WStype_CONNECTED: { // if a new websocket connection is
established IPAddress ip = webSocket.remoteIP(num); Serial.printf("[%u]
Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3],
payload); }
break; case WStype_TEXT: // if new text data is received
Serial.printf("[%u] get Text: %s\n", num, payload);
webSocket.sendTXT(num, payload); //Send back recived message to
client break; }
20.4 Results
Upload sketch in NodeMCU, Open Serial monitor and get IP or enter
esp8266.local in web browser.
Figure
20.2: WebSocket Communication server page Type some message
and click send, also observe serial monitor.
21. MQTT
21.1 Introduction
MQTT is a machine-to-machine (M2M)/"Internet of Things"
connectivity protocol. It was designed as an extremely lightweight
publish/subscribe messaging transport. It is useful for connections
with remote locations where a small code footprint is required and/or
network bandwidth is at a premium. For example, it has been used in
sensors communicating to a broker via satellite link, over occasional
dial-up connections with healthcare providers, and in a range of home
automation and small device scenarios. It is also ideal for mobile
applications because of its small size, low power usage, minimised
data packets, and efficient distribution of information to one or many
receivers.
Application Messages are transported by MQTT they have an
associated Quality of Service and a Topic Name.
Client:
A program or device that uses MQTT. A Client always establishes the
Network Connection to the Server. It can
Publish Application Messages that other Clients might be
interested in.
Subscribe to request Application Messages that it is
interested in receiving.
Unsubscribe to remove a request for Application Messages.
Disconnect from the Server.
Server:
A program or device that acts as an intermediary between Clients
which publish Application Messages and Clients which have made
Subscriptions. A Server
Accepts Network Connections from Clients.
Accepts Application Messages published by Clients.
Processes Subscribe and Unsubscribe requests from Clients.
Forwards Application Messages that match Client
Subscriptions.
Subscription:
A Subscription comprises a Topic Filter and a maximum QoS. A
Subscription is associated with a single Session. A Session can
contain more than one Subscription. Each Subscription within a
session has a different Topic Filter.
Topic Name:
The label attached to an Application Message which is matched
against the Subscriptions known to the Server. The Server sends a
copy of the Application Message to each Client that has a matching
Subscription.
Topic Filter:
An expression contained in a Subscription, to indicate an interest in
one or more topics. A Topic Filter can include wildcard characters.
Session:
A stateful interaction between a Client and a Server. Some Sessions
last only as long as the Network Connection, others can span multiple
consecutive Network Connections between a Client and a Server.
MQTT Control Packet: A packet of information that is sent across
the Network Connection. The MQTT specification defines fourteen
different types of Control Packet, one of which (the PUBLISH packet)
is used to convey Application Messages.
21.2 Configuring MQTT Server
For this mqtt demonstration we are using free plan
https://www.cloudmqtt.com/plans.html
Step 1: Choose free plan Step 2: Enter your email id and register
Step 3: Click email verification link and enter password Step 4:
Create New Instance
Figure 21.1:
Create New Instance Step 5: Get Your MQTT Configurations
Click on Instance name “esp8266mqtt”
Figure 21.2:
Configure instance Copy this information and enter it in your
NodeMCU program.
Figure 21.3:
Instance Information
21.3 NodeMCU MQTT example code
Enter your Wi-Fi and MQTT settings in program. For this program
PubSubClient library is required download it from here:
https://circuits4you.com/wp-content/uploads/2018/06/pubsubclient-
master.zip
/*
void loop() {
client.loop(); }
21.4 Results
In case you get connection failed error refer this and rectify problem
Error State
MQTT_CONNECTION_TIMEOUT -4
MQTT_CONNECTION_LOST -3
MQTT_CONNECT_FAILED -2
MQTT_DISCONNECTED -1
MQTT_CONNECTED 0
MQTT_CONNECT_BAD_PROTOCOL 1
MQTT_CONNECT_BAD_CLIENT_ID 2
MQTT_CONNECT_UNAVAILABLE 3
MQTT_CONNECT_BAD_CREDENTIALS 4
MQTT_CONNECT_UNAUTHORIZED 5
At first time you may get connection failed error: 5, Check your
mqtt configurations are same as your account settings.
On successful connection you can view your ESP in Connections
page Figure
21.4: MQTT Connected device IP
To send message to NodeMCU goto Websocket UI and enter topic
name and message then click send. Observe Serial monitor.
Figure 21.5:
Sending MQTT message to device
22.4 Controlling LED over internet using
MQTT
Keep same previous program in NodeMCU. Open notepad and create
web page (html page) having on off button to control LED using
below HTML code. In this we use JavaScript based MQTT library
“paho-mqtt”. This is included from CDN link.
Enter your MQTT configuration in below program and save this file
as samplePage.html.
Open it in web browser and click on buttons. In case LED is not
controlling then right click and click on inspect. Then click on
console. Look for any error logs.
<!DOCTYPE html> <html> <head> <script
src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js"
type="text/JavaScript"></script> </head> <body> <p>Click the button to turn
on/off on Board Blue LED</p> <button onclick="ledState(1)">LED
ON</button> <button onclick="ledState(0)">LED OFF</button><br> <a
href="https://circuits4you.com">Circuits4you.com</a> <script
type="text/JavaScript"> // Create a client instance // #############
ATTENTION: Enter Your MQTT TLS Port and host######## Supports only
TLS Port client = new Paho.MQTT.Client("m13.cloudmqtt.com",
36354,"web_" + parseInt(Math.random() * 100, 10)); // set callback handlers
client.onConnectionLost = onConnectionLost; client.onMessageArrived =
onMessageArrived; //############# ATTENTION: Enter Your MQTT user
and password details ########
var options = {
useSSL: true, userName: "username_here", password: "password_here",
onSuccess:onConnect, onFailure:doFail }
// connect the client client.connect(options); // called when the client connects
function onConnect() {
// Once a connection has been made, make a subscription and send a message.
console.log("onConnect"); client.subscribe("esp/test"); message = new
Paho.MQTT.Message("Hello CloudMQTT"); message.destinationName =
"esp/test"; client.send(message); }
function ledState(state) {
if(state == 1) { message = new Paho.MQTT.Message("#on"); }
if(state == 0) { message = new Paho.MQTT.Message("#off"); }
message.destinationName = "esp/test"; client.send(message); }
function doFail(e){
console.log(e); }
// called when the client loses its connection function
onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log("onConnectionLost:"+responseObject.errorMessage); }
}
// called when a message arrives function onMessageArrived(message) {
console.log("onMessageArrived:"+message.payloadString); }
</script> </body> </html>
22.5 Results of above HTML code
Open this html file in web browser. And click on LED on/off buttons
and observe On board LED of NodeMCU. This HTML code sends
MQTT commands to MQTT server on same topic, as ESP is
subscribed to same topic also receives LED on off commands. This
way on board LED control takes place over internet.
22. OTA
22.1 Introduction
OTA (Over the Air) update is the process of loading the firmware to
NodeMCU (ESP) module using Wi-Fi connection rather than a serial
port. Such functionality became extremely useful in case of limited or
no physical access to the module.
OTA may be done using:
Arduino IDE
Web Browser
HTTP Server
Arduino IDE option is intended primarily for software development
phase. The two other options would be more useful after deployment,
to provide module with application updates manually with a web
browser, or automatically using an http server.
In any case, the first firmware upload has to be done over a serial port.
If the OTA routines are correctly implemented in a sketch, then all
subsequent uploads may be done over the air.
There is no imposed security on OTA process from being hacked. It is
up to developer to ensure that updates are allowed only from
legitimate / trusted sources. Once the update is complete, the module
restarts, and the new code is executed. The developer should ensure
that the application running on the module is shut down and restarted
in a safe manner.
22.2 NodeMCU OTA example code
Enter Your Wi-Fi SSID and Password.
/*
Figure 22.1:
OTA Upload Option in Arduino IDE
In case OTA port is not visible, check these things
1. Restart ArduinoIDE
2. NodeMCU is connected to Wi-Fi, check Wi-Fi configuration.
3. Make sure NodeMCU and Your arduino IDE laptop is in same
network.
4. Disable Firewall.
Once OTA is visible select OTA port and now you can upload other
sketches using OTA port.
Open example LED blink and upload with Port : esp8266 (Network
port) OTA If during upload process python error is occurred then
install python.
23. Sending Email
23.1 Introduction
Simple Mail Transfer Protocol (SMTP) is a standard communication
protocol for sending email messages on business networks and the
Internet. SMTP was originally developed in the early 1980s and
remains one of the most popular protocols in use worldwide.
How SMTP Works ?
All modern email client programs support SMTP. The SMTP settings
maintained in an email client include the IP address of an SMTP
server.
A physical SMTP server may be dedicated to servicing email traffic
only but is often combined with at least POP3 and sometimes other
proxy server functions.
SMTP runs on top of TCP/IP and uses TCP port number 25 for
standard communication. To improve SMTP and help combat spam
on the Internet, standards groups have also designed TCP port 587 to
support certain aspects of the protocol. A few Web email services,
such as Gmail, use the unofficial TCP port 465 for SMTP.
Smtp2go.com uses port 2525.
23.2 SMTP Commands
The SMTP standard defines a set of commands - names of specific
types of messages that mail clients to the mail server when requesting
information. The most commonly used commands are: HELO and
EHLO - commands that initiate a new protocol session between client
and server. The EHLO command requests them to respond with any
optional SMTP extensions it supports MAIL - command to initiate
sending an email message RCPT - command to provide one email
address for a recipient of the current message being prepared DATA -
command indicating the start of transmission of the email message.
This command initiates a series of one or more follow-on messages
each containing a piece of the message. The last message in the
sequence is empty (containing only a period (.) as a termination
character) to signify the end of the email.
RSET - while in the process of sending an email (after issuing the
MAIL command), either end of the SMTP connection can reset the
connection if it encounters an error NOOP - an empty ("no
operation") message designed as a kind of ping to check for
responsiveness of the other end of the session QUIT - terminates the
protocol session The recipient of these commands replies with either
success or failure code numbers.
23.3 NodeMCU Email example code
Change Wi-Fi SSID, Password as per your Wi-Fi network and SMTP
mail settings. For this example three libraries required, download
from here: 1. https://circuits4you.com/wp-
content/uploads/2018/06/ESPMailer.zip
2. https://circuits4you.com/wp-content/uploads/2018/06/Time-
master.zip
3. https://circuits4you.com/wp-content/uploads/2018/06/NTP-
master.zip
/*
}
23.4 Results
Open serial monitor and see it works, or check for any errors in SMTP
configuration.
Below image show how to get your login user and password for smtp.
Click on Settings >> Users >> Username (email)
Figure 23.1:
Getting your username and password of smtp2go
Open serial monitor for successfully sent email you will get this.
Figure 23.2:
Sent Email Results in serial monitor
After this check your email inbox.
/*
//===========================================================
void handleRoot() {
String Name,_ssid,_password,locssid,locpassword,baudrate; String WebLink,
Host, SlaveID, FunctionCode, Offset, Length, dataType, ScanRate; String s =
MAIN_page;
char d; int opmode; for(int i=0;i<21;i++) {
d = char(EEPROM.read(0x0F+i)); if(d != 0x00) { Name = Name + d; }
//Read one by one with starting address of 0x0F
else { i=25; }
}
for(int i=0;i<21;i++) {
d = char(EEPROM.read(0x2F+i)); if(d != 0x00) { _ssid = _ssid + d; } //Read
one by one with starting address of 0x0F
else { i=25; }
}
for(int i=0;i<21;i++) {
d = char(EEPROM.read(0x4F+i)); if(d != 0x00) { _password = _password +
d; } //Read one by one with starting address of 0x0F
else { i=25; }
}
//Get HotSpot Local ssid password ----------------------------------
for(int i=0;i<21;i++) {
d = char(EEPROM.read(0x6F+i)); if(d != 0x00) { locssid = locssid + d; }
//Read one by one with starting address of 0x0F
else { i=25; }
}
for(int i=0;i<21;i++) {
d = char(EEPROM.read(0x8F+i)); if(d != 0x00) { locpassword =
locpassword + d; } //Read one by one with starting address of 0x0F
else { i=25; }
}
//Baud rate and Operating Modes ------------------------------------------
for(int i=0;i<8;i++) {
d = char(EEPROM.read(0xAF+i)); //Read one by one with starting
address of 0x0F
if(d != 0x00) { baudrate = baudrate + d; } //Read one by one with starting
address of 0x0F
else { i=25; }
}
opmode = EEPROM.read(0xBF); if(WiFi.status() == WL_CONNECTED) {
s.replace("@@STATUS@@","Connected");}
else {s.replace("@@STATUS@@","Disconnected");}
localip = String(WiFi.localIP() & 0x000000FF) + "." + String((WiFi.localIP()
& 0x0000FF00) >> 8) + "." +
String((WiFi.localIP() & 0x00FF0000)>>16) + "." +
String((WiFi.localIP() & 0xFF000000) >> 24); //IoT Configuration ---------------
-----------------------------
for(int i=0;i<210;i++) {
d = char(EEPROM.read(0xFF+i+100)); if(d != 0x00) { Host = Host + d;
} //Read one by one with starting address of 0x0F
else { i=250; }
}
s.replace("@@host@@", Host); for(int i=0;i<210;i++) {
d = char(EEPROM.read(0xFF+i)); if(d != 0x00) { WebLink = WebLink
+ d; } //Read one by one with starting address of 0x0F
else { i=250; }
}
s.replace("@@weblink@@", WebLink); SlaveID =
String(EEPROM.read(0xE0)); s.replace("@@slaveid@@", SlaveID);
FunctionCode = String(EEPROM.read(0xE1)); s.replace("@@function" +
FunctionCode + "@@", "selected"); int j = EEPROM.read(0xE4); j = j << 8; j =
j & 0xFF00; j = j | EEPROM.read(0xE5); Offset = String(j);
s.replace("@@offset@@", Offset); j = EEPROM.read(0xE8); j = j << 8;
j = j & 0xFF00; j = j | EEPROM.read(0xE9); ScanRate = String(j);
s.replace("@@scanrate@@", ScanRate); dataType =
String(EEPROM.read(0xE7)); s.replace("@@datatype" + dataType + "@@",
"selected"); //-----------------------------------------------------------------
s.replace("@@IP@@",localip); s.replace("@@name@@",Name);
s.replace("@@ssid@@",_ssid);
s.replace("@@pass@@",_password); s.replace("##ssid##",locssid);
s.replace("##pass##",locpassword); s.replace("@@baud" + baudrate + "@@",
"selected"); s.replace("@@mode" + String(opmode & 0x0F) +
"@@","selected"); webserver.send(200, "text/html", s);
//===========================================================
//===========================================================
//===========================================================
//============================================================
}
for(int i=0;i<21;i++) {
d = char(EEPROM.read(0x8F+i)); if(d != 0x00) { Lpassword[i] = d; } //Read
one by one with starting address of 0x0F
else { Lpassword[i] = d; i=25; }
*/
//===========================================================
//===========================================================
void SetBaudRate() {
long baud; String baudrate; char d; // put your setup code here, to run once:
for(int i=0;i<8;i++) {
d = char(EEPROM.read(0xAF+i)); if(d != 0x00) { baudrate = baudrate +
d; }
else { i=25; }
}
baud = ((baudrate[0] & 0x0F) * 100000) + ((baudrate[1] & 0x0F) * 10000) +
((baudrate[2] & 0x0F) * 1000) + ((baudrate[3] & 0x0F) * 100) + ((baudrate[4]
& 0x0F) * 10) + (baudrate[5] & 0x0F); if(!(baud > 115300)) {
Serial.begin(baud); }
else {
Serial.begin(115200); }
}
}
//==========================================================
// SETUP
//==========================================================
void setup() {
EEPROM.begin(512);
char d; SetBaudRate(); Serial.println("Device Started"); digitalWrite(0,HIGH);
//Make pullup on forget pass word button //WiFi.mode(WIFI_STA); //This line
hides the viewing of ESP as Wi-Fi network WiFi.mode(WIFI_AP_STA);
//Both hotspot and client are enabled //WiFi.mode(AP); //Only Access
point SoftAPWiFiConnect(); //Start Hot Spot WiFiConnect();
webserver.on("/", handleRoot); webserver.on("/form", handleForm); localip =
String(WiFi.localIP() & 0x000000FF) + "." + String((WiFi.localIP() &
0x0000FF00) >> 8) + "." +
String((WiFi.localIP() & 0x00FF0000)>>16) + "." +
String((WiFi.localIP() & 0xFF000000) >> 24); if((EEPROM.read(0xBF)=='1') ||
EEPROM.read(0xBF)=='3') {
server.begin(); //TCP Modbus server }
if((EEPROM.read(0xBF)=='2') || EEPROM.read(0xBF)=='4') {
udp.begin(localPort); //UDP Modbus }
webserver.begin(); }
//============================================================
// LOOP
//============================================================
void loop() {
// Web Server handling ---------
webserver.handleClient(); //------------------- MODBUS UDP/IP ----------------
---------
if((WiFi.status() == WL_CONNECTED) && ((EEPROM.read(0xBF)=='2') ||
(EEPROM.read(0xBF)=='4'))) {
int cb = udp.parsePacket(); if (cb) //if UDP Packet is recived then process {
udp.read(packetBuffer, cb); // read the packet into the buffer char
modbuspacket[1000]; //RTU Packet Decoder ----------
int j=0;
//Decode UDP RTU Packet for(int i=0;i<cb;i++) {
Serial.print(char(packetBuffer[i])); }
//Wait for data response if not in 1 Second Error int TimeOut=0;
while((Serial.available() == 0) && (TimeOut<100))
{
TimeOut++; delay(10); }
delay(20);
BufferCounter=0; while (Serial.available() > 0) //Greater than 2
remaing 2-bytes are CRC
{
inByte = Serial.read(); MODBuffer[BufferCounter] = inByte;
BufferCounter++; delayMicroseconds(10); }
size_t send_len = (unsigned int)BufferCounter; uint8_t
sbuf[send_len]; for (int i=0; i<BufferCounter; i++) sbuf[i] = MODBuffer[i];
if(BufferCounter > 2) //Make sure replay is recived from device {
udp.beginPacket(udp.remoteIP(), 4800); //Send UDP requests
are to port 4800
//udp.write(MODBuffer,BufferCounter); //Packet Start String
udp.write(sbuf, send_len); udp.endPacket(); }
}
}
//------------------------------------------------------------
//---------------------------------------------------
//-------------- Handles MODBUS RTU/ASCII TCP/IP Requests --
if((WiFi.status() == WL_CONNECTED) && (EEPROM.read(0xBF)=='3')) {
WiFiClient client = server.available(); if (client) {
if (client.connected()) {
for (int x = 0; x < 300; x++) { // Time to have data available if
(client.available()) {
while (client.available() > raw_len) { //Computes data length raw_len
= client.available(); delay(1); }
break; }
delay(10); }
}
char j;
if (raw_len > 7) {
for (int i=0; i<raw_len; i++) {
j = client.read(); //Get Raw Data Serial.print(char(j)); //Send data to
Modbus device }
//Wait for data response if not in 1 Second Error int TimeOut=0;
while((Serial.available() == 0) && (TimeOut<100))
{
TimeOut++; delay(10); }
delay(20); BufferCounter=0; while (Serial.available() > 0) //Greater
than 2 remaing 2-bytes are CRC
{
inByte = Serial.read(); MODBuffer[BufferCounter] = inByte;
BufferCounter++; delayMicroseconds(10); }
client.flush(); if(BufferCounter > 0) {
size_t send_len = (unsigned int)BufferCounter; uint8_t
sbuf[send_len]; for (int i=0; i<BufferCounter; i++) sbuf[i] = MODBuffer[i];
client.write(sbuf, send_len);
client.stop(); }
}
}
}
//-----------------------------------------------------------
//-----------------------------------------------------------
//===========================================================
//--------------------------------------------------------
Figure
23.2: MODBUS TCP Results in web browser
Don’t forget to read Good Stuff from other
books
1. Zero to Hero: ESP8266
Become super hero of Internet of Things world with knowledge of
programming IoT Module ESP8266 using Arduino IDE. This book
coves from basics to advance best guide for beginners.
2 Arduino Display Interfacing Focuses on depth only on display
interface with arduino.
4. Arduino Projects Vol-I: Don’t Just read it, Try it A read
practical book, comes with proteus simulation files, Don’t just read it,
try it on your PC with simulation code and designs.
This page intentionally left blank