NodeMcu
Lua ESP8266 WiFi Development Board
INTRO
The board used in this section includes
the following. Wifi: 802.11 b/g/n. The built-in b/g/n Wifi can operate as a
client, server, or even both at once. The Wifi Antenna is integrated on the
board. 9 digital input/output pins, all pins support interrupt/PWM/I2C/one-wire
except D0. Analog Inputs: 1 x 10-bit resolution input. 4 MByte Flash memory. The
module was pre-installed with the latest NodeMCU Lua firmware, set at 115200
baud rate.
The NodeMCU programming can be as easy as
in Arduino, the main difference is the distribution of pins in the nodemcu
board.
If you have not already done so, install
the Arduino IDE 1.6.4 or greater from https://www.arduino.cc/en/Main/Software . Select “File”,
“Prefernces”. Enter the following url into Additional Board Manager URLs field
http://arduino.esp8266.com/stable/package_esp8266com_index.json. Click “OK” to
close the window.
Next, use the Board Manager to install
the ESP8266 package. Select “Tools”, “Board”, “Board Manager”. Scroll the
Broads Manager screen down to a module
called “esp8266 by ESP8266 Community” . Select the most recent version and then
click “Install“. When installed close this window and restart the Arduino IDE.
From the Tools->Board dropdown menu
select the board and configuration that you wil be using. Selecting “Generic
ESP8266 Module” and leaving all other options as default worked for the
examples that follow.
Throughout this Section the module will
be referred to as either ESP8266 or NodeMCU
Blink On-board LED
Here
is a simple sketch to blink the on-board LED.
void
setup() {
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an
output
}
void
loop() {
digitalWrite(LED_BUILTIN, LOW); /* Turn the LED on Note that LOW is the voltage level but
actually the LED is on; this is because
it is active low on the ESP module */
delay(1000); // Wait for a second
digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH
delay(2000); // Wait for two seconds
}
Upload
the sketch using the Arduino IDE. You should see the on-board LED turn on for
one second (1000ms) and then turn off for two seconds (2000ms).
Blink External LED
Connect one end of a 220ohm
resistor to digital pin (D2, GPIO4).
Connect the long leg of the LED (the positive leg, called the anode) to
the other end of the resistor. Connect the short leg of the LED (the negative
leg, called the cathode) to the GND..
The value of the resistor
in series with the LED may be of a different value than 200 ohm; the LED will
lit up also with values up to 1K ohm.
Upload the following sketch
using the Arduino IDE.
int
LED = 4 ; // pin D2, GPIO4
void setup() {
pinMode(LED, OUTPUT); //
set the digital pin as output.
}
void loop() {
digitalWrite(LED, HIGH);//
turn the LED off.(Note that LOW is the voltage level but actually
//the LED is on; this is
because it is acive low on the ESP8266.
delay(1000); // wait for 1 second.
digitalWrite(LED, LOW); //
turn the LED on.
delay(1000); // wait for 1 second.
}
After the sketch is
uploaded, the LED will blink on and off every second (1000ms). Try using other
pins and using different
Push Button Switch
Earlier it was explained how to control an external
LED. The following example uses a push button switch for control. When the
button is pressed, the LED will turn on and will turn off when the button is
released. Set up the circuit below using a 220ohm resisitor for the LED and a
10kohm resistor for the push button switch.
Upload the following sketch using the Arduino IDE.
int ledpin = 5; // D1(GPIO5)
int button = 4; //D2(GPIO4)
int buttonState=0;
void setup() {
pinMode(ledpin,
OUTPUT);
pinMode(button,
INPUT);
}
void loop() {
buttonState=digitalRead(button); // put your
main code here, to run repeatedly:
if (buttonState
== 1)
{
digitalWrite(ledpin, HIGH);
delay(200);
}
if
(buttonState==0)
{
digitalWrite(ledpin, LOW);
delay(200);
}
}
The above example shows a method for reading the
digital state of a pin (the push button switch) and then performing some action
related to the state of that pin. This concept can be developed and used in a
whole host a applications.
To control the LED in the same way as a domestic light, i.e. click once to turn on the light, click again to turn off the light. The program needs to be modified. Modify the above program to that below and upload it to the NodeLUA using the Arduino IDE. The connections remain the same as above.
#define LED 5 // D1 (GPIO5)
#define BUTTON 4 //D2 (GPIO4)
int switchState = 0; // actual read value from
pin4
int oldSwitchState = 0; // last read value from pin4
int lightsOn = 0; // is the switch on = 1 or
off = 0
void setup() {
pinMode(BUTTON,
INPUT); // push button
pinMode(LED,
OUTPUT); // anything you
want to control using a switch e.g. a Led
}
void loop() {
switchState =
digitalRead(BUTTON); // read the
pushButton State
if
(switchState != oldSwitchState) //
catch change
{
oldSwitchState
= switchState;
if (switchState
== HIGH)
{
// toggle
lightsOn =
!lightsOn;
}
}
if(lightsOn)
{
digitalWrite(LED, HIGH); // set the LED on
} else {
digitalWrite(LED, LOW); // set the LED off
}
}
Press the button to turn on the LED, and then press the button again to turn off the LED.
Potentiometer:
Analog Read
The NodeMCU has one ADC pin that is easily accessible. This means that we can read analog signals. This example shows how to use analog read using the Arduino IDE .
Connect the data pin (centre pin) of the potentiometer
to pin A0 of the NodeMCU.
const int analogInPin = A0; // ESP8266 Analog Pin ADC0 = A0
int sensorValue = 0;
// value read from the pot
int outputValue = 0;
// value to output to a PWM pin
void setup() {
// initialize
serial communication at 115200
Serial.begin(115200);
}
void loop() {
// read the
analog in value
sensorValue =
analogRead(analogInPin);
// map it to
the range of the PWM out
outputValue =
map(sensorValue, 0, 1023, 0, 255);
// print the
readings in the Serial Monitor
Serial.print("sensor = ");
Serial.print(sensorValue);
Serial.print("\t output = ");
Serial.println(outputValue);
delay(1000);
}
Open the Arduino IDE Serial Monitor and select the
baud rate of 115200.
You will see that there are two values printed every
second (1000ms); “sensor” and “output”. Turn the potentiometer and the values
will change in the Serial Monitor.
Basic Serial
Communication
Serial communication is very useful and widely used
with microcontroller applications. Whether displaying sensor data or acting as
an interface for interactions between the user and microcontroller, serial
communication is vital in many applications.
Upload the sketch to the NodeLUA using the Arduino IDE.
void setup()
{
Serial.begin(115200); //Set the baudrate to 115200,same as the
software settings
}
void loop()
{
Serial.println("Hello World!"); //Print character string “Hello World” on the serial
delay(5000); // Delay 5 seconds
}
Open the Serial Monitor of the Arduino IDE and select
the baud rate of 115200 if not already set.
.
You will see the serial monitor output is updated
every every 5 seconds with the character string “Hello World”.
Try experimenting by altering the delay time and the
text. This method of displaying in the Serial Monitor will be developed as you
work through the examples.
Continuous Buzzer
A
continuous buzzer can have many uses and are a very convenient way of adding
sound or alarms to projects.
The
5 volt continuous buzzer has only two pins so we need to connect the shorter
one to GND and the other to a digital pin on the NodeMCU; in this example it is
connected to digital pin D2, GPIO4.
Once
you have connected the buzzer, load the following program
int
buzzer = 4; //define buzzer pin D2,
GPIO4
void
setup()
{
pinMode(buzzer,
OUTPUT); //buzzer pin as OUTPUT
}
void
loop() {
digitalWrite(buzzer,
HIGH); // make voltage HIGH, turn the LED on
delay(1000); // wait for a second
digitalWrite(buzzer,
LOW); // make voltage LOW, turn the LED
off
delay(1000); // wait for a second
}
This
very simple program turns the buzzer on for one second, then off, then waits
for a second before repeating. Experiment by altering the delay time and
putting extra delay commands into the program.
With
some imagination and dedication, I’m sure that you can design a project that
makes use of a continuous buzzer. Try adding a button or two to your circuit to
activate/deactivate the buzzer or add several buttons and write a sketch so
that each button activates the buzzer for different lengths of time.
Piezoelectric Speaker
A
piezoelectric speaker can play, as well as detect tones and can, with a little
help, enable us to play actual melodies. By using the Arduino capability of
producing pulse width modulation (PWM) signals, we are able to alter the pitch
of the sound. If you need to know more about PWM, details can be found here:
http://webzone.k3.mah.se/k3dacu/projects/ivrea/motor/pwm.html
Usually,
the two wires of the piezoelectric speaker are coloured. The black wire should
be connected to GND and the red wire connected to the output (in this case,
digital pin D2 (GPIO4 of the NodeMCU).
Below
is a very basic program that will play a single note.
const
int speakerPin =4; // speaker is on
digital pin D2
void
setup() {
pinMode(speakerPin,
OUTPUT);
}
void
loop() {
int
speakerVal = 349; //input
speakerVal to alter the note
//the
value of 349 corresponds to the note F (see bleow)
tone(speakerPin,
speakerVal); // calculate and play
the tone
}
The
required note frequencies to compose melodies using the set up can be found at
http://www.phy.mtu.edu/~suits/notefreqs.html , a summary of which is:
C
262 Hz
C#
277 Hz //middle C
D 294 Hz D# 311 Hz
E 330 Hz
F 349 Hz F# 370 Hz
G 392 Hz G# 415 Hz
A 440 Hz A# 466 Hz
B 493 Hz
C 523 Hz C# 554 Hz
D 587 Hz D# 622 Hz
Try
changing the note that is played and try adding extra lines of code to add more
notes. By adding various delay commands and different notes you should be able
to compose a simple melody. I’m sure that you will have hours of fun with this,
whilst also gaining valuable experience by working with the program. Here is a
program that will play Happy Birthday through the piezoelectric speaker:
int
speakerPin = 9;
int
length = 28; // the number of notes
char
notes[] = "GGAGcB GGAGdc GGxecBA yyecdc";
int
beats[] = { 2, 2, 8, 8, 8, 16, 1, 2, 2, 8, 8,8, 16, 1, 2,2,8,8,8,8,16,
1,2,2,8,8,8,16 };
int
tempo = 150;
void
playTone(int tone, int duration) {
for
(long i = 0; i < duration * 1000L; i += tone * 2) {
digitalWrite(speakerPin, HIGH);
delayMicroseconds(tone);
digitalWrite(speakerPin, LOW);
delayMicroseconds(tone);
}
}
void
playNote(char note, int duration) {
char
names[] = {'C', 'D', 'E', 'F', 'G', 'A', 'B',
'c', 'd', 'e', 'f', 'g', 'a', 'b',
'x', 'y' };
int
tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014,
956,
834, 765, 593,
468, 346, 224,
655 , 715 };
int SPEE = 5;
//
play the tone corresponding to the note name
for
(int i = 0; i < 17; i++) {
if (names[i] == note) {
int newduration = duration/SPEE;
playTone(tones[i], newduration);
}
}
}
void
setup() {
pinMode(speakerPin,
OUTPUT);
}
void
loop() {
for
(int i = 0; i < length; i++) {
if (notes[i] == ' ') {
delay(beats[i] * tempo); // rest
} else {
playNote(notes[i], beats[i] * tempo);
}
// pause between notes
delay(tempo);
}
}
TM1637 Seven Segment Display
Modules based on TM1637 provide two signal connections (CLK and DIO) and
two power connections (VCC and GND). Signal pins can be connected to any pair
of digital pins of the Arduino. Signal pins configuration is defined at the top
of library header file, where it can be modifed.
Upload the following sketch via the
Arduino IDE. This sketch simply counts upwards.
#include <TM1637Display.h>
const int CLK = 12; // pin D6
const int DIO = 14; // pin
D5
int numCounter = 0;
TM1637Display display(CLK, DIO); //set up
the 4-Digit Display.
void setup()
{
display.setBrightness(0x0a); //set the diplay
to maximum brightness
}
void loop()
{
for(numCounter = 0; numCounter < 1000;
numCounter++) //Iterate numCounter
{
display.showNumberDec(numCounter); //Display
the numCounter value;
delay(1000);
}
}
The following sketch demonstrates how to
display different type of values on the display such as numbers, letters and
punctuation.
The following sketch counts from -99 to
+9999.
Finally, the last sketch a clock that counts from 12:00 to 12:59
then turns the display off. To restart the clock, simply press the
reset button on the Arduino.
The
above examples show how versatile this module is and can be incorporated into
numerous larger projects.
OLED
Intro
etc
Wiring
Connect
the OLED (via a breadboard for convenience) as follows:
I2c
OLED ESP8266 Module
Vcc 3.3V
GND GND
SCL D1
SDA D2
You
will need to alter the Adafruit_SSD1306.h
library to set it for the 128x64 OLED display. Browse to the file on your
computer. It is usually installed in the ”libraries” folder which is a
sub-folder of the “Arduino” folder. Open the file in a text editor such as
Notepad and find the section which establishes the screen dimensions. Uncomment
the line
#define
SSD1306_128_64 and comment out the other two options as below:
//
ONE of the following three lines must be #defined:
#define
SSD1306_128_64 ///< DEPRECTAED: old way to specify 128x64 screen
//#define
SSD1306_128_32 ///< DEPRECATED: old
way to specify 128x32 screen
//#define
SSD1306_96_16 ///< DEPRECATED: old
way to specify 96x16 screen
Save
the file, open the Arduino IDE and upload the following sketch. The sketch was
adapted from the one at https://lastminuteengineers.com/oled-display-esp8266-tutorial/
. It is quite a comprehensive demonstration of some of the ways text can be
displayed. I have included all of the sketch so it can be used as a reference
whenever you require a specific effect in your projects.
#include
<SPI.h>
#include
<Wire.h>
#include
<Adafruit_GFX.h>
#include
<Adafruit_SSD1306.h>
Adafruit_SSD1306
display(-1);
void
setup()
{
// initialize with the I2C addr 0x3C
display.begin(SSD1306_SWITCHCAPVCC,
0x3C);
// Clear the buffer.
display.clearDisplay();
// Display Text
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,28);
display.println("Hello world!");
display.display();
delay(2000);
display.clearDisplay();
// Display Inverted Text
display.setTextColor(BLACK, WHITE); //
'inverted' text
display.setCursor(0,28);
display.println("Hello world!");
display.display();
delay(2000);
display.clearDisplay();
// Changing Font Size
display.setTextColor(WHITE);
display.setCursor(0,24);
display.setTextSize(2);
display.println("Hello!");
display.display();
delay(2000);
display.clearDisplay();
// Display Numbers
display.setTextSize(1);
display.setCursor(0,28);
display.println(123456789);
display.display();
delay(2000);
display.clearDisplay();
// Specifying Base For Numbers
display.setCursor(0,28);
display.print("0x");
display.print(0xFF, HEX);
display.print("(HEX) = ");
display.print(0xFF, DEC);
display.println("(DEC)");
display.display();
delay(2000);
display.clearDisplay();
// Display ASCII Characters
display.setCursor(0,24);
display.setTextSize(2);
display.write(3);
display.display();
delay(2000);
display.clearDisplay();
//
Scroll full screen
display.setCursor(0,0);
display.setTextSize(1);
display.println("Full");
display.println("screen");
display.println("scrolling!");
display.display();
display.startscrollright(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrollleft(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrolldiagright(0x00, 0x07);
delay(2000);
display.startscrolldiagleft(0x00, 0x07);
delay(2000);
display.stopscroll();
display.clearDisplay();
// Scroll part of the screen
display.setCursor(0,0);
display.setTextSize(1);
display.println("Scroll");
display.println("some part");
display.println("of the screen.");
display.display();
display.startscrollright(0x00, 0x00);
}
void
loop() {}
Servo Motor
Servo
motors can be found in the likes of printers and scanners. Generally they can
turn between 0 and 180 degrees and it is by selecting the degree(s) that it
turns it enables us to incorporate them in some precise applications.
The
TowerPro SG90 9G is an inexpensive servo motor which can be bought online for
only a few pounds, They generally come with an assortment of blade attachments.
Wiring
the motor to the NodeMCU is simple as there are only three wires to connect.
Black GND
Red 3V
Yellow Pin D4 (GPIO 2)
On
the following pages is a sketch that you can either copy or adapt for your
projects. It starts by setting the servo angle variable (servoAngle) to 0
degrees. There then follows a routine to turn the motor to various angles
whilst pausing between each movement. Finally, there is a section which touches
on speed.
#include
<Servo.h>
int
servoPin = 2; //GPIO 4
Servo
servo;
int
servoAngle = 0; // servo position in degrees
void
setup()
{
Serial.begin(9600);
servo.attach(servoPin);
}
void loop()
{
//control
the servo's direction and the position of the motor
servo.write(45); //
Turn servo Left to 45 degrees
delay(1000); //
Wait 1 second
servo.write(90); // Turn servo back to 90 degrees (center
position)
delay(1000); //
Wait 1 second
servo.write(135); // Turn servo Right to 135 degrees
delay(1000); //
Wait 1 second
servo.write(90); // Turn servo back to 90 degrees (center
position)
delay(1000);
//end
control the servo's direction and the position of the motor
//control
the servo's speed
//if
you change the delay value (from example change 50 to 10), the speed of the
servo changes
for(servoAngle = 0; servoAngle < 180;
servoAngle++) //move the micro servo
from 0 degrees to 180 degrees
{
servo.write(servoAngle);
delay(50);
}
for(servoAngle = 180; servoAngle > 0;
servoAngle--) //now move back the micro
servo from 0 degrees to 180 degrees
{
servo.write(servoAngle);
delay(10);
}
//end control the servo's speed
}
Try
altering the program to explore the capabilities of the servo. These small
motors could prove invaluable in your projects and it won’t break the bank
buying them.
Stepper Motor with
ULN2003 Driver
controlling
a 28BYJ-48 stepper motor with the ULN2003 driver board and Arduino
Connect
the ULN2003 driver board to four digital pins on the NodeMCU as follows:
NodeMCU ULN2003
Board
D5
GPIO14 IN1
D6
GPIO12 IN2
D7
GPIO13 IN3
D8
GPIO15 IN4
Upload
the following sketch
uint8_t
wire1 = 14;
uint8_t
wire2 = 12;
uint8_t
wire3 = 13;
uint8_t
wire4 = 15;
const
uint16_t _delay = 50; /* delay in between two steps. minimum delay more the
rotational speed */
void
sequence(bool a, bool b, bool c, bool d){
/* four step sequence to stepper motor */
digitalWrite(wire1, a);
digitalWrite(wire2, b);
digitalWrite(wire3, c);
digitalWrite(wire4, d);
delay(_delay);
}
void
setup() {
pinMode(wire1, OUTPUT); /* set four wires as
output */
pinMode(wire2, OUTPUT);
pinMode(wire3, OUTPUT);
pinMode(wire4, OUTPUT);
}
void
loop() {
/* Rotation in one direction */
for(int i = 0; i<12; i++)
{
sequence(HIGH, LOW, LOW, LOW);
sequence(HIGH, HIGH, LOW, LOW);
sequence(LOW, HIGH, LOW, LOW);
sequence(LOW, HIGH, HIGH, LOW);
sequence(LOW, LOW, HIGH, LOW);
sequence(LOW, LOW, HIGH, HIGH);
sequence(LOW, LOW, LOW, HIGH);
sequence(HIGH, LOW, LOW, HIGH);
}
sequence(HIGH, LOW, LOW, LOW);
/* Rotation in opposite direction */
for(int j = 0; j<12; j++)
{
sequence(LOW, LOW, LOW, HIGH);
sequence(LOW, LOW, HIGH, HIGH);
sequence(LOW, LOW, HIGH, LOW);
sequence(LOW, HIGH, HIGH, LOW);
sequence(LOW, HIGH, LOW, LOW);
sequence(HIGH, HIGH, LOW, LOW);
sequence(HIGH, LOW, LOW, LOW);
sequence(HIGH, LOW, LOW, HIGH);
}
sequence(LOW, LOW, LOW, HIGH);
}
Tilt Sensor
A
tilt sensor can be a useful component in numerous projects. Fixed to objects,
it switches between two states if moved or tilted. The SW-520D is a simple ball
tilt switch which has two pins. With the two pins level, a 10° tilt will close
the contacts, thus altering the “state”.
Connec
the shortest of the pins of the sensor to ground and the other pin to a 10k ohm
pull up resistor and to Node MCU pin D1 (GPIO5). Upload the following program.
const
int sensorPin = 5; // tilt sensor pin
int
sensorState = 0; // define our
variable
void
setup() {
Serial.begin(9600); // enable serial output and baud
rate
pinMode(sensorPin,
INPUT); // define sensor pin as
output
}
void
loop(){
String
s; // create a string variable called s
sensorState
= digitalRead(sensorPin); // state = value of the pin
Serial.print(sensorState);
Serial.println();
Delay(200);
}
When
the sensor is moved, its state (either 0 or 1) will be displayed in the Serial
Monitor of the IDE and the light will flash correspondingly. Open the Serial
Monitor and select 9600 baud rate if not already selected. Move the breadboard
that is housing the tilt sensor to see this happening.
This
example could be expanded to incorporate some sort of alarm when the switch
changes state. It could trigger a light to come on or even triiger a fan to
turn on. The possibilities are
numerous..
Temperature Sensor
Here,
we are going to use an LM35 precision analog temperature sensor. It has 3-pins;
5V, GND temperature.
As
you look at the flat face of the sensor with the pins hanging downwards, the
left pin is the 5V pin and should be attached to the 5V pin of the Node MCU.
The right pin of the sensor is ground and should be connected to the Node MCU GND
pin. Finally, the central pin should be connected directly to Analog input pin
A0 (ADC0) of the Node MCU. Notice that a breadboard is not being used here.
This is because if we were to use a breadboard, the temperature wouldn’t be
very stable. If you must use a breadboard, you would be well advised to add
some sort of filter.
Upload
the following and open the Serial Monitor. You should see the temperature
reading value being updated every second. If you grab hold of the sensor or
breathe on it, you should see the temperature rise. Try altering the delay so
that you see the temperature being updated at different intervals (remember
that this is milliseconds so delay(1000); pauses for one second).
#define
tempPin 0 // sensor attached
to analog pin A0 (ADC0)
int
Temp = 0; // set up a
variable
void
setup() {
Serial.begin(9600); // enable serial output and baud
rate
}
void
loop(){
analogRead(tempPin); // read the pin value
Temp
= (3.0 * analogRead(tempPin) * 100.0) / 1024;//see below
Serial.print("Temp
"); // print “Temp”
Serial.print(Temp); // print the value
Serial.println(""); // print a blank line
delay(1000); // wait 1 second
}
Before
getting the Celsius reading of the temperature the analog output voltage from
LM35 must first be read from the Vout pin of LM35. This will be the raw value
divided by 1024 times 3300. It is divided by 1024 because a span of 1024 occupies
3.3v.
Here
we get the ratio of the raw value to the full span of 1024 and then multiply it
by 3300 to get the millivolt value. Since the output pin can give out a maximum
of 3.3 volts (1024), 1024 represents the possible range it can give out..
Temp
= (3.0 * analogRead(tempPin) * 100.0) / 1024;
Open
the Serial Monitor.
Look
at the following lines of code:
Serial.print("Temp
"); // print the word “Temp” in
the Serial Monitor
Serial.print(Temp); // print the value in the Serial
Monitor
Serial.println(""); // print a blank line in the
Serial Monitor
Rather
than just have a number being displayed, you could add a couple of lines so the
word “Temp” is displayed before the value and " degrees centigrade"
after the value
This
would make the display look neater and easier to read. Try adding some
different text or more spaces. You could also try altering the time between
readings.
You
could use the temperature sensor as part of a la4rger weather station project.
Light Sensor
Light
sensors, also known as photo resistors or light dependant resistors (LDR) are
generally quite basic and un-calibrated. In this example, a GL5537 LDR is but
there are plenty of others that perform equally as well. The LDR changes its
resistance depending on the amount of light and we can measure this change
using one of the Arduino analog pins.
The
LDR has only two pins so connect one of these pins to GND (ground) and the
other pin to a 10k ohm pull up resistor and to the Node MCU analog pin A0
(ADC0). Upload the following program and
open the Serial Monitor.
#define
lightPin 0 //
data pin
int
Light = 0; //
our variable
void
setup() {
Serial.begin(9600); //
enable serial output and baud rate
}
void
loop(){
analogRead(lightPin); //
read the pin value
Light
= analogRead(lightPin); //
Light variable = value that was read
Serial.println
(Light); //
Print the value in the Serial Monitor
delay(1000); // Wait for 1 second
}
Placing
your hand (or piece of paper) over the sensor results in a change of values displayed.
The more light, the lower the reading.
As
the measured resistance varies greatly from bright light to darkness, we need
to either use a lookup table or perform calculations on the readings to convert
to lux values.
The
following program converts the measurements to lux.
#define
lightPin 0
int
Light = 0;
void
setup() {
Serial.begin(9600);
}
void
loop()
{
Light
= toLux(analogRead(lightPin)); //perform
conversion
Serial.println
(Light);
delay(1000);
}
//
Change the ADC reading to lux.
/* Vcc 5
Pullup 10000
lux ohms Voltage ADC Scaling
0 1023
1 200000 4.76 975 -0.020937188
10 30000 3.75 768 -0.043428309
80 5000 1.67 341 -0.1640625
120 4000 1.43 293 -0.8203125
150 3000 1.15 236 -0.533203125
250 2000 0.83 171 -1.5234375
300 1800 0.76 156 -3.45703125
800 700 0.33 67 -5.604580966
*/
int
toLux(int adc)
{
//return
(map(adc, 0, 1023, 900, 0)); simple linear model
if
(adc > 868)
return
300 + 5.6 * (adc - 868); else if (adc > 853)
return
250 + 3.46 * (adc - 853); else if (adc > 788)
return
150 + 1.52 * (adc - 788); else if (adc > 731)
return
120 + 0.53 * (adc - 731); else if (adc > 683)
return
80 + 0.82 * (adc - 683); else if (adc > 256)
return
10 + 0.16 * (adc - 256); else
return
0.04 * adc;
}
The
first program (without the conversion to lux) would be sufficient if you just
want to detect the difference between light and shadow, if a light is on or off
or there is just a change in brightness.
These
inexpensive sensors can be readily bought on the internet. They can be used as
part of larger projects such as monitoring light around the home and switching
lights on and off depending on levels of light detected.
DHT-11 Temperature
and Humidity Sensor
Another
sensor that you may wish to use is the humidity sensor. In this example I have
used the DHT-11. This is a digital humidity and temperature sensor and has four
pins. The measurement resolution of this module is 1°C or 1% relative humidity.
Here, it will just be used for measuring relative humidity and temperature;
measurement of temperature is better
done with the more accurate and sensitive LM35 (see previous).
Connect
the DHT data pin to the NodeMCU pin D1 (GPIO5). Also connect GND to GND and VCC
to VCC.
In
this example we will be using a library as part of the code. Libraries provide
extra functionality for use in programs and are referenced from within the
program. You will need to download the DHT 11 library and install it.
https://github.com/ghadjikyriacou/DHT11lib/blob/master/dht11.h
Instructions
for installing Arduino libraries can be on the Arduino website found at
http://arduino.cc/en/Guide/Libraries . Once the library has been installed,
upload the following code (also available from
http://robertthomasson.blogspot.co.uk/2013/09/byte-size-starter.html ) and open
the Serial Monitor:
#include
"DHT.h" // include the
library of DHT11 temperature and humidity sensor
#define
DHTTYPE DHT11 // DHT 11
#define
dht_dpin 5
DHT
dht(dht_dpin, DHTTYPE);
void
setup(void)
{
dht.begin();
Serial.begin(9600);
Serial.println("Humidity and
temperature\n\n");
delay(700);
}
void
loop() {
float h = dht.readHumidity();
float t = dht.readTemperature();
Serial.print("Current humidity =
");
Serial.print(h);
Serial.print("% ");
Serial.print("temperature = ");
Serial.print(t);
Serial.println("C ");
delay(800);
}
You
will see that the humidity measurement is updated in the Serial Monitor once
every second.
If
you breathe on the detector, you should see the humidity and temperature measurement
change. Try altering the delay interval or the way that the data is displayed
in the Serial Monitor. This sensor can be used in conjunction with other
sensors/modules as part of larger projects, for example a weather monitoring
station.
PIR Motion
Detector
PIR motion detectors are widespread as they are used in many
security systems to detect events such as trespass or other motion. The modules
themselves are quite inexpensive and can
be readily bought from numerous sources on the internet.
They have a range of detection of about 6–7m and are highly sensitive. When
the PIR motion sensor detects
motion, it outputs a signal which can be
captured by a Node MCU; this signal triggers
an interrupt.
Connect
the input pin to Node MCU pin D7
(GPIO13), GND to GND and 5V to 5V. An LED can be added for visual indication of
any detected motion; attach this to pin D6 (GPIO12).. Once the circuit is set
up, construct a sketch similar to the one below.
int
ledPin = 12; // pin D6, GPIO12
int
inputPin = 13; // pin D7, GPIO13
int
pirState = LOW; //
we start, assuming no motion detected
int
val = 0; // variable for reading the pin
status
void
setup() {
pinMode(ledPin, OUTPUT); //
declare LED as output
pinMode(inputPin, INPUT); //
declare sensor as input
Serial.begin(9600);
}
void
loop(){
val = digitalRead(inputPin); //
read input value
if (val == HIGH) { //
check if the input is HIGH
digitalWrite(ledPin, HIGH); //
turn
if (pirState == LOW) { // we have just turned on
Serial.println("Motion detected!") ;// We only want to print on the output
change, not state
pirState = HIGH;
}
} else {
digitalWrite(ledPin, LOW); // turn LED OFF
if (pirState == HIGH){ // we have just turned off
Serial.println("Motion
ended!"); // We only
want to print on the output change, not state
pirState = LOW;
}
}
}
If
motion is detected the LED turns on. If no motion is detected, the LED remains
turned off. Open the Serial Monitor at 9600 baud rate and you will see a
representation of when motion is detected.
As
shown above, these modules are quite straightforward to use and can be
incorporated into many projects, for instance in security or robotic
applications.
Ultrasound Distance Measurement
The HC-SR04 ultrasonic sensor uses sonar to determine distance to an
object. It offers excellent non-contact range detection with high accuracy and
stable readings. The range is from 2cm to 400 cm (1” to 13 feet).
There
are four pins on the sensor module and these should be connected to as follows:
HC SR04 NodeMCU
VCC VV (The module requires 5V
which is supplied to pin VV via the usb connection)
GND GND
Echo
pin
D6, GPIO12
Trig pin
D7, GPIO13
The
sketch was constructed from referencing many similar sketches that are
available in the public domain.
//
defines pins numbers
const
int trigPin = 2; //D4 GPIO2
const
int echoPin = 0; //D3 GPIO0
//
defines variables
long
duration;
int
distance;
void
setup() {
pinMode(trigPin,
OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin,
INPUT); // Sets the echoPin as an Input
Serial.begin(9600);
// Starts the serial communication
}
void
loop() {
//
Clears the trigPin
digitalWrite(trigPin,
LOW);
delayMicroseconds(2);
//
Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin,
HIGH);
delayMicroseconds(10);
digitalWrite(trigPin,
LOW);
//
Reads the echoPin, returns the sound wave travel time in microseconds
duration
= pulseIn(echoPin, HIGH);
//
Calculating the distance
distance=
duration*0.034/2;
//
Prints the distance on the Serial Monitor
Serial.print("Distance:
");
Serial.println(distance);
delay(2000);
}
Upload
the sketch and then open the Serial Monitor at 9600 baud rate. By moving an
object to various distances in front of the detector, you should see the
distance displayed change as in the screen shot below.
The
Serial Plotter can be used to graphically show trends.
The
HC SR04 Ultrasonic Sensor can be used in many projects. One that springs to
mind would be to use it in a model car or robot as part of a collision
avoidance feature.
Soil Moisture
Sensor
This sensor measures
the volumetric content of water in the soil and gives the moisture level as output. The sensor is equipped with both analog and digital output, so it
can be used in both analog and digital mode.
Connect
the data pin of the module to analog pin A0 (ADC0) of the Node MCU. Connect GND
to GND and VCC to VV on the Node MCU. The module requires 5V which is supplied
to pin VV via the usb connection,.
Once
the circuit has been set up, construct a sketch similar to the one below and
upload it to the Node MCU.
void
setup() {
Serial.begin(9600); // initialize serial communication at
9600 bits per second
}
void
loop() {
int sensorValue = analogRead(A0) /10; //
read the input on analog pin A0
(ADC0) and divide the value by 10
Serial.print("Moisture Reading
");
Serial.print(sensorValue); // print out the value
Serial.println (" ");
delay(2000); // delay between readings for
stability
}
Once
the sketch is uploaded, open the Serial Monitor. Dip the probe in and out of
water to see the readings change.
Though
the accuracy of these sensors is questionable, they can still be used in
various projects that require soil moisture level data.
An
advanced project maybe to monitor the moisture level in a plant pot and if the
level falls below a certain level, you could trigger a pump to deliver a
certain amount of water. This would be a good way of caring for you houseplants
whilst on holiday.
Capacitive Touch
Sensor
The
TTP233B capacitive touch sensor can be used as an alternative to the tactile
push button in numerous applications.
In the normal state, the
module output low, low power consumption; When a finger touches the
corresponding position, the module output high, if not touched for 12 seconds,
switch to low-power mode. Low power consumption
Power supply for 2 ~ 5.5V
DC
Can replace the traditional
touch of a button
.
/*
Author:
Danny van den Brande. Arduinosensors.nl. BlueCore Tech.
Hello
world! Today i made a code for the TTP233B capacitive touch sensor.
Its
very simple and you can toggle on and off a led/relay or whatever you wanna
add.
*/
#define
TouchSensor 0 // Pin D3 (GPIO0) for capactitive touch sensor
int
relay = 2;
boolean
currentState = LOW;
boolean
lastState = LOW;
boolean
RelayState = LOW;
void
setup() {
Serial.begin(9600);
pinMode(relay, OUTPUT);
pinMode(TouchSensor, INPUT);
}
void
loop() {
currentState = digitalRead(TouchSensor);
if (currentState == HIGH &&
lastState == LOW){
Serial.println("pressed");
delay(1);
if (RelayState == HIGH){
digitalWrite(relay, LOW);
RelayState = LOW;
} else {
digitalWrite(relay, HIGH);
RelayState = HIGH;
}
}
lastState = currentState;
}
Each
time the sensor is touched, “presssed” is displayed in the Serial Monitor. The
sensor could be used in place of a push button in a whole host of applications
and projects.
Sound Sensor
A sound sensor can, and is, a very useful
item. It can be used to trigger lights, doors, alarms etc or even used to
control a smart vehicle.
The sensor detects sound through a
microphone and this sound is passed through a LM393 op amp. The particular one
used here has an operating voltage of 3.3V-5V and has a signal output indicator
LED which comes on when a sound is detected. The output is low when there is
sound and high when there is no sound (i.e. LOW and HIGH pin states
respectively.
The three pin version of this module connects to the Arduino as follows:
VCC 5V
GND GND
OUT Digital pin D3
(GPIO0)
As the output is
digital, we can only detect when there is sound detected or not. If we wanted
to detect relative levels of sound, we would need a module that has an analog
output.
Connect the module
to your Node MCU as above and then connect the Arduino to your computer.
Compile a sketch to read the digital state of the input on pin D3. Here is
sketch that I have compiled:
int
soundDetectedPin = 0;
int
soundDetectedVal = HIGH;
void
setup()
{
Serial.begin(9600);
pinMode
(soundDetectedPin, INPUT) ;
}
void
loop()
{
soundDetectedVal = digitalRead
(soundDetectedPin) ;
digitalRead(soundDetectedPin);
if
(soundDetectedVal == HIGH)
Serial.println("Quiet");
else
if (soundDetectedVal == LOW)
Serial.println("Noise");
delay
(1000);
}
Once uploaded onto
the Node MCU, open the Serial Monitor and make some noise. You will see that
the message changes as the sensor detects the sounds. You may need to alter the
sensitivity by using the onboard potentiometer.
By
making the delay shorter, the system will become more responsive.
The
following sketch is a bit more complex and has been adapted from the one at
Henry’s Bench: http://henrysbench.capnfatz.com/henrys-bench/arduino-sensors-and-input/arduino-sound-detection-sensor-tutorial-and-user-manual/
int
soundDetectedPin = 0; //
Use D3 as input
int
soundDetectedVal = HIGH; // sound
measurement
boolean
bAlarm = false;
unsigned
long lastSoundDetectTime; // Record the time that the sound was measured
int
soundAlarmTime = 500; // Number of milliseconds to keep the sound alarm high
void
setup ()
{
Serial.begin(9600);
pinMode (soundDetectedPin, INPUT) ; // input from the Sound Detection
Module
}
void
loop ()
{
soundDetectedVal = digitalRead
(soundDetectedPin) ; // read the
sound alarm time
if (soundDetectedVal == LOW) // If
we hear a sound
{
lastSoundDetectTime = millis(); // record the time of the sound
alarm
// The following is so you don't scroll on the
output screen
if (!bAlarm){
Serial.println("SOUND
DETECTED");
bAlarm = true;
}
}
else
{
if( (millis()-lastSoundDetectTime) >
soundAlarmTime && bAlarm){
Serial.println("quiet");
bAlarm = false;
}
}
}
Load
the sketch and open the Serial Monitor. Initially, nothing will be displayed.
Make some noise and "SOUND DETECTED” will be displayed. This will remain
onscreen until sound ceases to be detected; then "quiet" will be
displayed. Here is a screenshot that I achieved by turning a radio on and off:
This module could be used
in projects for home security or traffic safety.
Sound Sensing:
Piezoelectric Element
A Piezoelectric element can be used to detect vibration, in this case, a
knock on a door, table, or other solid surface. It’s an electronic device that
generates a voltage when it's physically deformed by a vibration, sound wave,
or mechanical strain. Similarly, when you put a voltage across a piezo, it
vibrates and creates a tone. Piezoelectric elements can be used both to play
tones and to detect tones.
Piezoelectric elements are polarized, meaning that
voltage passes through them (or out of them) in a specific direction. Connect
the black wire (the lower voltage) to ground and the red wire (the higher
voltage) to analog pin 0. Additionally, connect a 1-megohm resistor in parallel
to the Piezo element to limit the voltage and current produced by the piezo and
to protect the analog input.
It
is possible to acquire piezoelectric elements without a plastic housing. These will
look like a metallic disc, and are easier to use as input sensors. PIezo
sensors work best when firmly pressed against, taped, or glued their sensing
surface.
The
sketch below reads the piezoelectric output using the analogRead() command,
encoding the voltage range from 0 to 5 volts to a numerical range from 0 to
1023 in a process referred to as analog-to-digital conversion, or ADC.
If the sensors output is stronger than a certain threshold, your board
will send the string "Knock!" to the computer over the serial port.Try
raising or lowering this value to increase your sensor's overall sensitivity.
Connect
the positive (red) wire of the piezoelectric element attached to analog pin A0
(ADC0) and the negative (black) connection of the piezo to ground. Attach a 1M
ohm resistor from analog in 0 to ground.
const
int ledPin = 0; // LED on pin D3 (GPIO0)
const
int knockSensor = A0; // piezo on
A0 (ADC0)
const
int threshold = 100; // threshold value
to decide when the detected sound is a knock or not
//
these variables will change:
int
sensorReading = 0; // variable to
store the value read from the sensor pin
int
ledState = LOW; // variable used to store the last LED status,
to toggle the light
void
setup() {
pinMode(ledPin, OUTPUT); // declare the
ledPin as as OUTPUT
Serial.begin(9600); // use the serial port
}
void
loop() {
// read the sensor and store it in the variable
sensorReading:
sensorReading = analogRead(knockSensor);
// if the sensor reading is greater than the
threshold:
if (sensorReading >= threshold) {
// toggle the status of the ledPin:
ledState = !ledState;
// update the LED pin itself:
digitalWrite(ledPin, ledState);
// send the string "Knock!" back
to the computer, followed by newline
Serial.println("Knock!");
}
delay(100);
// delay to avoid overloading the serial port buffer
}
Open the Serial Monitor.
When you knock on the
surface close to the piezoelectric element, “knock!” will be displayed in the
Serial Monitor and the LED will turn on.
Reed Sensor
The Reed sensor module is also known as a magnetron module or reed switch.
It has a working voltage 3.3V-5V, with a
digital output which is capable of switching output (0 and 1)
This module can be incorporated into
program-controlled switches, copiers, washing machines, refrigerators, cameras,
electromagnetic relays, electronic weighing scales, level meters, gas meters,
water meters and so on
int Reed = 0; //Digital
pin D3, GPIO0
int val ;
void setup ()
{
Serial.begin(9600);
pinMode (Reed, INPUT);
}
void loop ()
{
Serial.println("Reed Sensor");
val = digitalRead (Reed) ;
if (val == HIGH)
{
Serial.println("Switch closed");
}
else
{
Serial.println("Switch open");
}
delay(2000);
}
Open the Serial Monitor and
move a magnet around the sensor. You should see the switch close and open.
Hall
Effect Sensor
A Hall Effect sensor is a
transducer that varies its output voltage in response to a magnetic field. Hall
effect sensors are used for proximity switching, positioning, speed detection,
and current sensing applications.
In a Hall Effect sensor, a
thin strip of metal has a current applied along it. In the presence of a
magnetic field, the electrons in the metal strip are deflected toward one edge,
producing a voltage gradient across the short side of the strip (perpendicular
to the feed current). Hall effect sensors have an advantage over inductive
sensors in that, while inductive sensors respond to a changing magnetic field
which induces current in a coil of wire and produces voltage at its output,
Hall effect sensors can detect static (non-changing) magnetic fields.
Connect the VCC of the
sensor to the VV (5V) pin of the Node MCU. Connect GND to GND and connect the AO
to pin of the sensor to Analog pin A0 (ADC0) of the Node MCU. Upload the
following sketch.
int sensorPin = A0; // input pin for the sensor
int sensorValue = 0; // variable for the sensor value
void setup() {
Serial.begin(9600);
pinMode (sensorPin, INPUT)
;
}
void loop() {
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
Serial.println(sensorValue);
delay(100);
}
Open the Serial plotter.
You will see that every 100 milliseconds, a value will appear. This is the
analog value of pin 10 (the Hall sensor). By moving a magnet various distances
from the Hall sensor, you will see the values change.
To illustrate the changing
magnetic field, close the serial monitor and open Maker Plot and run the
Standard Interface. Select the correct port and baud rate. Alter the values of
the x and y axes to cater for your data and begin collecting.
The Hall Effect sensor
analog values are plotted in black. As the magnet gets nearer to the sensor,
the analog value decreases.
Flame Detection
Sensor
The
4 pin flame detection sensor is generally an infrared (IR) receiver which can
detect IR radiation between 760 nm and 1100 nm.
To
test the module, a flame should be set of approximately 80cm from the sensor.
If using a flame larger than that given by a lighter, this will be detected at
a greater distance.
The
module has a detection angle of 60 degrees and sensitivity is adjustable using
the on-board digital potentiometer. It has an operating voltage of 3.3V to 5V
and outputs of both digital and analog.
VCC:
VCC 3.3-5V.
GND:
GND.
DO:
TTL switch signal output.
AO:
Analog Output.
Connect the VCC pin to 3V and the GND pin
to GND of the Node MCU. Connect the DO (Digital Out) pin of the module to D0
(ADC0) of the Node MCU. Upload the following sketch.
void setup()
{
Serial.begin(9600);
}
void loop()
{
analogRead(A0);
Serial.println(analogRead(A0));
delay (200);
}
Open
the Serial Monitor and pass a
You
will see that the output changes as the
summary
Applications
Accelerometer and
Gyroscope
https://www.electronicwings.com/nodemcu/mpu6050-interfacing-with-nodemcu
Image
The
MPU 6050 module has a 3-axis accelerometer, a 3-axis gyroscope and a
temperature sensor built into a single chip called an inertial measurement unit
(IMU). This module is also called six-axis motion tracking device or 6 DoF (six
Degrees of Freedom) device, because of its 6 outputs, or the 3 accelerometer
outputs and the 3 gyroscope outputs. In summary, MPU6050 sensor module is an
integrated 6-axis Motion tracking device.
It
has a 3-axis Gyroscope, 3-axis Accelerometer, Digital Motion Processor and a
Temperature sensor, all in a single IC.
It
can accept inputs from other sensors like 3-axis magnetometer or pressure
sensor using its Auxiliary I2C bus.
If
external 3-axis magnetometer is connected, it can provide complete 9-axis
Motion Fusion output.
Gyroscope
and accelerometer reading along X, Y and Z axes are available in 2’s complement
form.
Temperature
reading is available in signed integer form (not in 2’s complement form).
Gyroscope
readings are in degrees per second (dps) unit; Accelerometer readings are in g
unit; and Temperature reading is in degrees Celsius
Connect
the MPU 6050 module to the Arduino as follows:
MPU 6050 Node MCU
VCC:
VV (5V
from tusb)
GND:
GND
SCL:
D4
SDA:
D7
XDA:
Not
connected
XCL:
Not
connected
INT:
Not
connected
Connect
a 4.7k ohm resistor between SCL and ground, and another 4.7k ohm resistor
between SDA and ground.
We will need sketch that will be capable
of getting the seven data readings and displaying them on the serial monitor.
The sketch will collect the following:
AcX: accelerometer reading in the X
direction
AcY: accelerometer reading in the Y
direction
AcZ: accelerometer reading in the Z
direction
Tmp: temperature reading
GyX: gyroscope reading about the X-axis
GyY: gyroscope reading about the Y-axis
GyZ: gyroscope reading about the Z-axis
Upload the sketch below which was adapted
from the example here https://www.electronicwings.com/nodemcu/mpu6050-interfacing-with-nodemcu
#include <Wire.h>
// MPU6050 Slave Device Address
const uint8_t MPU6050SlaveAddress = 0x68;
// Select SDA and SCL pins for I2C
communication
const uint8_t scl = 12; //pin D6
const uint8_t sda = 13; //pin D7
// sensitivity scale factor respective to
full scale setting provided in datasheet
const uint16_t AccelScaleFactor = 16384;
const uint16_t GyroScaleFactor = 131;
// MPU6050 few configuration register
addresses
const uint8_t MPU6050_REGISTER_SMPLRT_DIV =
0x19;
const uint8_t
MPU6050_REGISTER_USER_CTRL = 0x6A;
const uint8_t
MPU6050_REGISTER_PWR_MGMT_1 = 0x6B;
const uint8_t
MPU6050_REGISTER_PWR_MGMT_2 = 0x6C;
const uint8_t
MPU6050_REGISTER_CONFIG = 0x1A;
const uint8_t
MPU6050_REGISTER_GYRO_CONFIG = 0x1B;
const uint8_t
MPU6050_REGISTER_ACCEL_CONFIG = 0x1C;
const uint8_t
MPU6050_REGISTER_FIFO_EN = 0x23;
const uint8_t
MPU6050_REGISTER_INT_ENABLE = 0x38;
const uint8_t
MPU6050_REGISTER_ACCEL_XOUT_H = 0x3B;
const uint8_t
MPU6050_REGISTER_SIGNAL_PATH_RESET =
0x68;
int16_t AccelX, AccelY, AccelZ,
Temperature, GyroX, GyroY, GyroZ;
void setup() {
Serial.begin(9600);
Wire.begin(sda, scl);
MPU6050_Init();
}
void loop() {
double Ax, Ay, Az, T, Gx, Gy, Gz;
Read_RawValue(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_XOUT_H);
//divide each with their sensitivity scale factor
Ax = (double)AccelX/AccelScaleFactor;
Ay = (double)AccelY/AccelScaleFactor;
Az = (double)AccelZ/AccelScaleFactor;
T
= (double)Temperature/340+36.53; //temperature formula
Gx = (double)GyroX/GyroScaleFactor;
Gy = (double)GyroY/GyroScaleFactor;
Gz = (double)GyroZ/GyroScaleFactor;
Serial.print("Ax: "); Serial.print(Ax);
Serial.print(" Ay: "); Serial.print(Ay);
Serial.print(" Az: ");
Serial.print(Az);
Serial.print(" T: "); Serial.print(T);
Serial.print(" Gx: "); Serial.print(Gx);
Serial.print(" Gy: "); Serial.print(Gy);
Serial.print(" Gz: "); Serial.println(Gz);
delay(100);
}
void I2C_Write(uint8_t deviceAddress,
uint8_t regAddress, uint8_t data){
Wire.beginTransmission(deviceAddress);
Wire.write(regAddress);
Wire.write(data);
Wire.endTransmission();
}
// read all 14 register
void Read_RawValue(uint8_t deviceAddress,
uint8_t regAddress){
Wire.beginTransmission(deviceAddress);
Wire.write(regAddress);
Wire.endTransmission();
Wire.requestFrom(deviceAddress, (uint8_t)14);
AccelX = (((int16_t)Wire.read()<<8) | Wire.read());
AccelY = (((int16_t)Wire.read()<<8) | Wire.read());
AccelZ = (((int16_t)Wire.read()<<8) | Wire.read());
Temperature = (((int16_t)Wire.read()<<8) | Wire.read());
GyroX = (((int16_t)Wire.read()<<8) | Wire.read());
GyroY = (((int16_t)Wire.read()<<8) | Wire.read());
GyroZ = (((int16_t)Wire.read()<<8) | Wire.read());
}
//configure MPU6050
void MPU6050_Init(){
delay(150);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SMPLRT_DIV, 0x07);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_1, 0x01);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_2, 0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_CONFIG, 0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_GYRO_CONFIG, 0x00);//set
+/-250 degree/second full scale
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_CONFIG, 0x00);//
set +/- 2g full scale
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_FIFO_EN, 0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_INT_ENABLE, 0x01);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SIGNAL_PATH_RESET,
0x00);
I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_USER_CTRL, 0x00);
}
Once the sketch is uploaded, open the
Serial Monitor.
Each of the seven sensor data readings
appear on a single line. The Serial Monitor of the Arduino IDE serial window
for above sketch is shown below. Note I altered the
Ax
= Accelerometer x axis data in g unit
Ay
= Accelerometer y axis data in g unit
Az
= Accelerometer z axis data in g unit
T = temperature in degree/celcius
Gx
= Gyro x axis data in degree/seconds unit
Gy
= Gyro y axis data in degree/seconds unit
Gz
= Gyro z axis data in degree/seconds unit If you move the sensor in
various directions and planes, the values will change.
The data collection can also be viewed by
making use of the Maker Plot standard interface. Here, as above, the data sets
are reported across a single line every second.
As plotting multiple data sets in Maker
Plot requires serial data to be comma-delimited, you will need to alter the
serial print statements in the sketch to add commas. Below is a simple way to
do this:
Serial.print(Ax);
Serial.print(",");
Serial.print(Ay);
Serial.print(",");
Serial.print(Az);
Serial.print(",");
Serial.print(T);
Serial.print(",");
Serial.print(Gx);
Serial.print(",");
Serial.print(Gy);
Serial.print(",");
Serial.println(Gz);
Once the new sketch is uploaded to the Node
MCU, Maker Plot can be opened and a graphical representation of the sensor data
can be seen. If the sensor is moved to different positions and to different
orientations, each line being plotted will change (except, maybe, for the
temperature data set). You should observe a plot similar to the one below.
Data Logging To
Excel: PLX-DAQ
Parallax Data Acquisition tool (PLX-DAQ) software
is an add-in for Microsoft Excel and can acquire up to 26 channels of data from
microcontrollers and drops the numbers into columns as they arrive. PLX-DAQ
provides easy spreadsheet analysis of data collected in the field, laboratory
analysis of sensors and real-time equipment monitoring
It
can be downloaded from this link:
https://www.parallax.com/downloads/plx-daq
I
have set up a circuit with a DHT-11 humidity detector and an LM 35 temperature
sensor. If you study the sketch below, you will hopefully get an understanding
of how to use the necessary commands to populate the PLX-DAQ spreadsheet.
The
LM 35 is attached to NodeMCU pin A0 (ADC0) and the DHT-11 is attached to NodeMCU
pin D1 (GPIO5).
/*
Data is sent to an Excel spreadsheet through PLX-DAQ data acquisition software:
http://www.parallax.com/downloads/plx-daq
*/
#include
"DHT.h" // include the
library of DHT11 temperature and humidity sensor
#define
DHTTYPE DHT11 // DHT 11
#define
tempPin 0 //temperature sensor pin
#define
dht_dpin 5
DHT
dht(dht_dpin, DHTTYPE);
int
x = 0; // For PLX-DAQ
int
row = 0; // For PLX-DAQ
int
i = 0;
void
setup(void)
{
dht.begin();
Serial.begin(9600);
Serial.println("LABEL, Time, Temp (C),
Humidity");
delay(1000);
}
void
loop() {
int temp;
int humidity;
temp=(5*analogRead(tempPin)*100)/1024;
humidity = dht.readHumidity();
Serial.print("DATA,");
Serial.print ("TIME,");
Serial.print(temp);
Serial.print(",");
Serial.println(humidity);
row++;
// For PLX-DAQ
x++;
// For PLX-DAQ
delay(5000); //Set delay to 10 seconds between
readings
}
Upload
the sketch and, once loaded and connected, launch the PLX-DAQ spreadsheet.
You
will need to enable the macros and accept the warning regarding active x
controls as the spreadsheet loads. Select the baud rate (9600 for Node Lua) and
the port that your Node Lua is connected to. Click “Connect”.
Your data should begin to be logged into the spreadsheet.
By
selecting the “Sample Data With Plots” tab you will see that as well as your
temperature and humidity data being logged, there is a graph that is being
updated after each reading. You may need to alter the series settings for the
graph.
The
data in the PLX-DAQ spreadsheet is updated every 10 seconds (set in the Arduino
sketch),. You can alter this to suit your requirements.
The
PLX-DAQ spreadsheet is very good at logging data and can be used to log data
from a whole range of sensors and experiments. You can log up to 26 channels
and you can alter the spreadsheet to illustrate your data to suit your
requirements. As you develop your skills and ideas, this tool could become a
valuable constituent of you projects.
Please
see the PLX-DAQ documentation in Appendix 2.
Data Logging: MakerPlot
MakerPlot is Windows® software for plotting analog and digital
data generated by microcontrollers and other devices with ASCII serial
outputs. No proprietary hardware is required – just a serial connection
from the microcontroller or other device to the PC. More background about
this excellent package is outlined under the Arduino- Data -Data Logging:
MakerPlot section in this work.
Firstly,
set up the circuit for monitoring temperature and humidity as in NodeMCU PLX-DAQ
section earlier; i.e. the LM 35 is attached to NodeMCU pin A0 (ADC0) and the
DHT-11 is attached to NodeMCU pin D1 (GPIO5).
Upload
the following Node Lua sketch using the Arduino IDE:
#include
"DHT.h" // include the
library of DHT11 temperature and humidity sensor
#define
DHTTYPE DHT11 // DHT 11
#define
tempPin 0 //temperature sensor pin
#define
dht_dpin 5 // humidity sensor pin
DHT
dht(dht_dpin, DHTTYPE);
void
setup(void)
{
dht.begin();
Serial.begin(9600);
Serial.println("LABEL, Time, Temp (C),
Humidity");
delay(1000);
}
void loop() {
int
temp;
int humidity;
temp =
(analogRead(tempPin) * 330) / 4096;;
humidity = dht.readHumidity();
// Serial.print("DATA,");
// Serial.print ("TIME,");
Serial.print(temp);
Serial.print(",");
Serial.println(humidity);
delay(5000); //Set delay to 5 seconds between
readings
}
Connect
your NodeMCU to the computer via a USB cable and launch the MakerPlot
application. From the first screen, select “Run Standard Interface”.
You
will be greeted by a logically-displayed interface.
We
will be collecting temperature and humidity data every 10 seconds so we need to
alter the axes accordingly. I set the x-axis to 180 seconds (3 minutes) and the
y-axis to 100:Now select the port and baud rate (9600 for Arduino):
Select
“Log To File” in the bottom panel.
MakerPlot
is now ready to receive the sensor data.
Click
the Control Switch to begin data acquisition.
Above
is the resulting sensor data plot. The humidity values are in red and the
temperature values are in black. Open the std_dat.txt file to see the raw data.
Here is a screenshot of a portion of my raw data file:
You
can save this file and then import into Excel for some further
analysis/plotting.
Storage: SD Card
Module
One
of the easiest ways to store data for the sensors is the familiar SD storage
card. An SD Card Modules can be easily found and are quite reasonably priced.
The
SD Card Module has eight pins, which are all labelled. The pin out scheme that
I use is as follows:
SD Card NodeMCU
GND GND
MISO D6 (GPIO12)
SCK D5 (GPIO14)
MOSI D7 (GPIO13)
CS D4 (GPIO2)
5V
3V 3V
IRQ
Note
that the SD Card Module can be used with either 5V or 3V connected to the
Arduino. The following programs have been adapted from the examples that are
freely available in the Examples Section of the Arduino IDE. You will need to
ensure that you have the SD Card library (“SD.h”) installed.
List The Contents Of An
SD Card
Firstly, save some files to the SD card using your computer our
laptop. We will now upload the following program (based on the “CardInfo” file
from the Arduino IDE.
#include <SPI.h>
#include <SD.h>
File root;
void setup() {
pinMode(2, OUTPUT); // change this to 53 on a mega // don't follow this!!
digitalWrite(2, HIGH); // Add this line
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.print("
if (SD.begin(2)) { //this had to
be changed from 4
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
root = SD.open("/");
printDirectory(root, 0);
Serial.println("done!");
}
void loop() {
// nothing happens after setup finishes.
}
void printDirectory(File dir, int
numTabs) {
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs + 1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}}
Open the serial monitor and press the
reset button on the Node Lua. You will see the SD card contents information.
Serial
Monitor Display Of SD Card Contents
Write And Read To/From An SD Card
To
write to a file, we firstly need to create that file on the SD card. Open up a
new file using Microsoft Notepad or similar, then save it as
"test.txt" to the SD card. Upload the following program
#include
<SPI.h>
#include
<SD.h>
File
myFile;
void
setup() {
// Open serial communications and wait for
port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect.
Needed for native USB port only
}
Serial.print("
if (!SD.begin(2)) {
Serial.println("initialization
failed!");
while (1);
}
Serial.println("initialization
done.");
// open the file. note that only one file can
be open at a time,
// so you have to close this one before
opening another.
myFile = SD.open("test.txt",
FILE_WRITE);
// if the file opened okay, write to it:
if (myFile) {
Serial.print("Writing to
test.txt...");
myFile.println("testing 1, 2,
3.");
// close the file:
myFile.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.println("error opening
test.txt");
}
// re-open the file for reading:
myFile = SD.open("test.txt");
if (myFile) {
Serial.println("test.txt:");
// read from the file until there's nothing
else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening
test.txt");
}
}
void
loop() {
// nothing happens after setup
}
Open
the serial monitor and press the reset butoon on the Node Lua to initialize the
SD card. The serial output will be similar to the one below which shows the
initialization of the SD card, writing to the SD card and the result of reading
the SD card. You will see that I have written the text three times to the file
as I pressed the reset button three times.
Put
the SD card in the SD card slot of your computer and open the file
"test.txt", you will see that the Arduino has written the text
“testing 1, 2, 3." to the file. This is very useful as this program can be
used for the basis of a project. For example, you could set up a temperature
sensor and log the data to an SD card for future manipulation and analysis.
Shift Register 74HC595N
A shift register is an integrated circuit that converts serial
information to parallel. It requires 3 pins (as well as power and ground) from
a microcontroller but allows us to have a total of 8 outputs. Earlier in this
Section we have seen that we used one pin on the NodeMCU to control one LED but
by using a shift register, we can control 8 LEDs using only pins 3 pins.
For
illustration purposes, the examples below will use the 74HC595N shift register and will use digital pins
6, 7 and 8 on the NodeMCU to control it. Pin 6 is connected to the serial data
pin, pin 8 is connected to the clock pin and pin 7 is connected to the latch
pin. Note that in the programs the NodeMCU pins reference the actual GPIO pin
number ie digital pins 6, 7 and 8 correspond to GPIO pins 12, 13 and 15
respectively.
The
8 LEDs are connected with their shorter legs (cathodes) to GND, whilst their
longer legs (anodes) are connected to the shift register output pins via 220
ohm resistors.
Counting
//A
little more involved, the following sketch counts from 0 to 255 and displays
the number using the eight LEDs.
// Adapted from
https://www.arduino.cc/en/tutorial/ShiftOut
int
latchPin = 13; //Pin connected to ST_CP of 74HC595
int
clockPin = 15; //Pin connected to SH_CP
of 74HC595
int
dataPin = 12; //Pin connected to DS of 74HC595
void
setup() {
//set pins to output so you can control the
shift register
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
}
void
loop() {
// count from 0 to 255 and display the number
// on the LEDs
for (int numberToDisplay = 0; numberToDisplay
< 256; numberToDisplay++) {
// take the latchPin low so
// the LEDs don't change while you're
sending in bits:
digitalWrite(latchPin, LOW);
//
shift out the bits:
shiftOut(dataPin, clockPin, MSBFIRST,
numberToDisplay);
//take the latch pin high so the LEDs will
light up:
digitalWrite(latchPin, HIGH);
// pause before next value:
delay(500);
}
}
Using
An Array
/*
Shift Register Example
Turning on the outputs of a 74HC595 using an
array
Hardware:
* 74HC595 shift register
* LEDs attached to each of the outputs of the
shift register
*/
//Pin
connected to ST_CP of 74HC595
int
latchPin = 13;
//Pin
connected to SH_CP of 74HC595
int
clockPin = 15;
////Pin
connected to DS of 74HC595
int
dataPin = 12;
//holders
for infromation you're going to pass to shifting function
byte
data;
byte
dataArray[10];
void
setup() {
//set pins to output because they are
addressed in the main loop
pinMode(latchPin, OUTPUT);
Serial.begin(9600);
//Binary notation as comment
dataArray[0] = 0xFF; //0b11111111
dataArray[1] = 0xFE; //0b11111110
dataArray[2] = 0xFC; //0b11111100
dataArray[3] = 0xF8; //0b11111000
dataArray[4] = 0xF0; //0b11110000
dataArray[5] = 0xE0; //0b11100000
dataArray[6] = 0xC0; //0b11000000
dataArray[7] = 0x80; //0b10000000
dataArray[8] = 0x00; //0b00000000
dataArray[9] = 0xE0; //0b11100000
//function that blinks all the LEDs
//gets passed the number of blinks and the
pause time
blinkAll_2Bytes(2,500);
}
void
loop() {
for (int j = 0; j < 10; j++) {
//load the light sequence you want from
array
data = dataArray[j];
//ground latchPin and hold low for as long
as you are transmitting
digitalWrite(latchPin, 0);
//move 'em out
shiftOut(dataPin, clockPin, data);
//return the latch pin high to signal chip
that it
//no longer needs to listen for information
digitalWrite(latchPin, 1);
delay(300);
}
}
//
the heart of the program
void
shiftOut(int myDataPin, int myClockPin, byte myDataOut) {
// This shifts 8 bits out MSB first,
//on the rising edge of the clock,
//clock idles low
//internal function setup
int i=0;
int pinState;
pinMode(myClockPin, OUTPUT);
pinMode(myDataPin, OUTPUT);
//clear everything out just in case to
//prepare shift register for bit shifting
digitalWrite(myDataPin, 0);
digitalWrite(myClockPin, 0);
//for each bit in the byte myDataOut
//NOTICE THAT WE ARE COUNTING DOWN in our for
loop
//This means that %00000001 or "1"
will go through such
//that it will be pin Q0 that lights.
for (i=7; i>=0; i--) {
digitalWrite(myClockPin, 0);
//if the value passed to myDataOut and a
bitmask result
// true then... so if we are at i=6 and our
value is
// %11010100 it would the code compares it
to %01000000
// and proceeds to set pinState to 1.
if ( myDataOut & (1<<i) ) {
pinState= 1;
}
else {
pinState= 0;
}
//Sets the pin to HIGH or LOW depending on
pinState
digitalWrite(myDataPin, pinState);
//register shifts bits on upstroke of clock
pin
digitalWrite(myClockPin, 1);
//zero the data pin after shift to prevent
bleed through
digitalWrite(myDataPin, 0);
}
//stop shifting
digitalWrite(myClockPin, 0);
}
//blinks
the whole register based on the number of times you want to
//blink
"n" and the pause between them "d"
//starts
with a moment of darkness to make sure the first blink
//has
its full visual effect.
void
blinkAll_2Bytes(int n, int d) {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
delay(200);
for (int x = 0; x < n; x++) {
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 255);
shiftOut(dataPin, clockPin, 255);
digitalWrite(latchPin, 1);
delay(d);
digitalWrite(latchPin, 0);
shiftOut(dataPin, clockPin, 0);
shiftOut(dataPin, clockPin, 0);
digitalWrite(latchPin, 1);
delay(d);
}
}
Turn
On Individual LED Via Serial Monitor
/*
Shift Register Example
for 74HC595 shift register
This sketch turns reads serial input and uses
it to set the pins
of a 74HC595 shift register.
Hardware:
* 74HC595 shift register attached to pins 8,
12, and 11 of the Arduino,
as detailed below.
* LEDs attached to each of the outputs of the
shift register.
Created 22 May 2009
Created 23 Mar 2010
by Tom Igoe
*/
//Need
to use serial monitor to input pin number to switch on
//Pin
connected to latch pin (ST_CP) of 74HC595
const
int latchPin = 13;
//Pin
connected to clock pin (SH_CP) of 74HC595
const
int clockPin = 15;
////Pin
connected to Data in (DS) of 74HC595
const
int dataPin = 12;
void
setup() {
//set pins to output because they are
addressed in the main loop
pinMode(latchPin, OUTPUT);
pinMode(dataPin, OUTPUT);
pinMode(clockPin, OUTPUT);
Serial.begin(9600);
Serial.println("reset");
}
void
loop() {
if (Serial.available() > 0) {
// ASCII '0' through '9' characters are
// represented by the values 48 through 57.
// so if the user types a number from 0
through 9 in ASCII,
// you can subtract 48 to get the actual
value:
int bitToSet = Serial.read() - 48;
// write to the shift register with the
correct bit set high:
registerWrite(bitToSet, HIGH);
}
}
//
This method sends bits to the shift register:
void
registerWrite(int whichPin, int whichState) {
//
the bits you want to send
byte bitsToSend = 0;
// turn off the output so the pins don't
light up
// while you're shifting bits:
digitalWrite(latchPin, LOW);
// turn on the next highest bit in
bitsToSend:
bitWrite(bitsToSend, whichPin, whichState);
// shift the bits out:
shiftOut(dataPin, clockPin, MSBFIRST,
bitsToSend);
//
turn on the output so the LEDs can light up:
digitalWrite(latchPin, HIGH);
}
Shift Register SN74HC165
https://www.theengineeringprojects.com/2018/11/arduino-74hc165-interfacing-increase-input-pins.html
From the data sheet: The SNx4HC165 devices are 8-bit parallel-load shift
registers that, when clocked, shift the data toward a serial (QH)
output. Parallel-in access to each stage is provided by eight individual direct
data (A–H) inputs that are enabled by a low level at the shift/load (SH/LD)
input. The SNx4HC165 devices also feature a clock-inhibit (CLK INH) function
and a complementary serial (QH) output.
Ie
increase input pins
works
on the principal of Parallel In Serial Out.
Pin out
This is the one for the code
https://www.theengineeringprojects.com/2018/11/arduino-74hc165-interfacing-increase-input-pins.html
74HC165 will take 8 parallel inputs from different sensors or buttons
etc and will send them to serial OUT Pin, which will be connected to Arduino.
So, if you are working on a project where you want to get data of 15 or 20
digital sensors then you can use this shift register and just using a single
pin of Arduino you can read data of all those sensors. We can only get digital
inputs, we can’t get analog input through this shift register. So, let’s get
started with Arduino 74HC165 Interfacing:
Fore wiring diag - Can’t grab code http://wei48221.blogspot.com/2015/06/how-to-use-shift-register-74hc165_25.html
Circuit
10k ohm resistors
Fritzing
165N
Pin NodeMCU
Load 1 D0 GPIO16
Enable 15 D1 GPIO5
Data 10 D2 GPIO4
Clock 2 D3 GPIO0
#define
NUMBER_OF_SHIFT_CHIPS 1
#define DATA_WIDTH NUMBER_OF_SHIFT_CHIPS * 8
int LoadPin = 16;
int EnablePin = 5;
int DataPin = 4;
int ClockPin = 0;
unsigned long pinValues;
unsigned long oldPinValues;
void setup()
{
Serial.begin(9600);
pinMode(LoadPin, OUTPUT);
pinMode(EnablePin, OUTPUT);
pinMode(ClockPin, OUTPUT);
pinMode(DataPin, INPUT);
digitalWrite(ClockPin, LOW);
digitalWrite(LoadPin, HIGH);
pinValues = read_shift_regs();
print_byte();
oldPinValues = pinValues;
}
void loop()
{
pinValues = read_shift_regs();
if(pinValues != oldPinValues)
{
print_byte();
oldPinValues = pinValues;
}
}
unsigned long
read_shift_regs()
{
long bitVal;
unsigned long bytesVal = 0;
digitalWrite(EnablePin, HIGH);
digitalWrite(LoadPin, LOW);
delayMicroseconds(5);
digitalWrite(LoadPin, HIGH);
digitalWrite(EnablePin, LOW);
for(int i = 0; i < DATA_WIDTH; i++)
{
bitVal = digitalRead(DataPin);
bytesVal |= (bitVal <<
((DATA_WIDTH-1) - i));
digitalWrite(ClockPin, HIGH);
delayMicroseconds(5);
digitalWrite(ClockPin, LOW);
}
return(bytesVal);
}
void print_byte() {
byte i;
Serial.println("*Shift Register
Values:*\r\n");
for(byte i=0; i<=DATA_WIDTH-1; i++)
{
Serial.print("P");
Serial.print(i+1);
Serial.print(" ");
}
Serial.println();
for(byte i=0; i<=DATA_WIDTH-1; i++)
{
Serial.print(pinValues >> i & 1,
BIN);
if(i>8){Serial.print(" ");}
Serial.print(" ");
}
Serial.print("\n");
Serial.println();Serial.println();
}
Open the serial monitor of
the Arduino IDE and turn some switches on and off. You will see the values
change as you do this.
CD4051BE
Multiplexer
The CD4051BE is an 8 channel analog
multiplexer / demultiplexer device that selects one of 8 analog signals and
forwards the selected input into a single line. It can be use in both
directions, to receive signal from sensors or to send signal (power supply
usually) to a sensor.
To select a particular channel in/out pin (y
pin; pins 11, 10 and 9 in the diagram above), you have to write to S0, S1 and
S2 with values of either LOW or HIGH. The table below shows the values that
should be written to address each of the channel in/out y pins.
|
Pin |
S0 |
S1 |
S2 |
|
y0 |
LOW |
LOW |
LOW |
|
y1 |
HIGH |
LOW |
LOW |
|
y2 |
LOW |
HIGH |
LOW |
|
y3 |
HIGH |
HIGH |
LOW |
|
y4 |
LOW |
LOW |
HIGH |
|
y5 |
HIGH |
LOW |
HIGH |
|
y6 |
LOW |
HIGH |
HIGH |
|
y7 |
HIGH |
HIGH |
HIGH |
To illustrate the selection
of channel in/out pins, I have constructed a sketch that will monitor a light
sensor (LDR), two temperature sensors
(LM35), a flame detector and a gas sensor using just one of the analog data
pins on the NodeMCU LUA.
y0 (LOW, LOW, LOW) will be
the temperature sensor and
y1 (HIGH, LOW, LOW) will be
the light sensor.
Connect the Arduino to the
CD4051BE via a solderless breadboard as follows:
|
CD4051BE |
Arduino |
|
Pin
16 (Vcc) positive supply voltage |
5V |
|
Pin
6 (E) enable input (active LOW) |
GND |
|
Pin
7 (Vee) negative supply voltage |
GND |
|
Pin
8 (gnd) ground (0V) |
GND |
|
Pin
11 (S0) |
Digital
pin 2 |
|
Pin
10 (S1) |
Digital
pin 3 |
|
Pin
9 (S2) |
Digital
pin 4 |
|
Pin
3 (Z) |
Analog
pin 0 |
Wiring
CD4051BE NodeMCU
S0 D0 GPIO16
S1 D1 GPIO5
S3 D3 GPIO4
Z A0 ADC0
LM35 Transfer Function & Output
Conversion to °C for the NodeMCU LUA can be done using the converting the
analog value read by the AO pin and converting it thus::
Input
= (3.3*analogRead(InputPin)*100.0) / 1023;
#define
InputPin A0 // ADC0, Input
pin
int
Input = 0; // our
variable
void
setup() {
pinMode(16, OUTPUT); // s0
pinMode(5, OUTPUT); // s1
pinMode(4, OUTPUT); // s2
Serial.begin(9600); // enable serial output
}
void
loop(){
//Light
Y0
digitalWrite(16, LOW); //s0
digitalWrite(5, LOW); // s1
digitalWrite(4, LOW); // s2
analogRead(InputPin); // read the pin value
Input = analogRead(InputPin);
Serial.print ("Light: ");
Serial.print (Input); // Print the value
Serial.println ("");
delay(1000);
//Temperature
1 Y1
digitalWrite(16, HIGH); // s0
digitalWrite(5, LOW); // s1
digitalWrite(4, LOW); // s2
analogRead(InputPin); // read the pin value
Input = analogRead(InputPin);
Input = (3.3*analogRead(InputPin)*100.0) /
1023;
Serial.print ("Temperature 1: ");
Serial.print (Input); // Print the value
Serial.println ("");
delay(1000); // Wait for 1 second
//Temperature
2 Y2
digitalWrite(16, LOW); // s0
digitalWrite(5, HIGH); // s1
digitalWrite(4, LOW); // s2
analogRead(InputPin); // read the pin value
Input = analogRead(InputPin);
Input = (3.3*analogRead(InputPin)*100.0) /
1023;
Serial.print ("Temperature 2:
");
Serial.print (Input); // Print the value
Serial.println ("");
delay(1000); // Wait for 1
second
//Light
Y3 Flame Detector
digitalWrite(16, HIGH); //s0
digitalWrite(5, HIGH); // s1
digitalWrite(4, LOW); // s2
analogRead(InputPin); // read the pin value
Input = analogRead(InputPin);
Serial.print ("Flame Detector: ");
Serial.print (Input); // Print the value
Serial.println ("");
delay(1000);
//Light
Y4 Gas Detector
digitalWrite(16, LOW); //s0
digitalWrite(5, LOW); // s1
digitalWrite(4, HIGH); // s2
analogRead(InputPin); // read the pin value
Input = analogRead(InputPin);
Serial.print ("Gas Detector: ");
Serial.print (Input); // Print the value
Serial.println ("");
Serial.println ("");
delay(1000);
}
Open the serial monitor
Line Decoder SN74HCT138N
https://www.instructables.com/id/Simple-3-8-decoder-demultiplexer-tutorial/
http://geekswithblogs.net/osnosblog/archive/2010/11/06/142618.aspx
3-to-8 line
decoder/demultiplexer inverting. The 74HC138 / 74HCT138 decoders accept three
binary weighted address inputs (A0, A1, A2) and when enabled, provide 8
mutually exclusive active LOW outputs (Y0 to Y7).
The 74HCT138 is a 3-to-8
DEMUX, Inverting. That means that it can turn 3 digital outputs into 8 digital
outputs. Inverting means that the encoded output will actually be LOW, not HIGH
as would be expected. That means that if you encode, for instance, a 4, the 4rd
pin (Y3, as this is zero based) will be LOW while pins 0, 1, 2, 4, 5, 6 and 7
will be HIGH. For the purposes of this demo, Inverting and not Inverting are
exactly the same. I’ll show you how to wire the non-inverting version at the
end of the post. This circuit has also a fantastic characteristic: it has 3
enable inputs. The circuit will only activate if E1 and E2 are LOW and E3 is
high. This is used for chaining,
Wiring
74HC138N NodeMCU
A0 GPIO16 D0
A1 GPIO5 D1
A2 GPIO4 D2
E3 GPIO0 D3
E1 GND
E2 GND
VCC 5V
GND GND
Y0-Y4 LED1 - 5
E1 and E2 are LOW (GND),
therefore, E3 (connected to Arduino pin D5 is HIGH.
The following program will cycle through the 5
connected LEDs.
const int selA0 = 16;
const int selA1 = 5;
const int selA2 = 4;
const int E3 = 0;
void setup()
{
// initialize the control
outputs
pinMode(selA0, OUTPUT);
pinMode(selA1, OUTPUT);
pinMode(selA2, OUTPUT);
pinMode(E3, OUTPUT);
digitalWrite(selA0, LOW);
digitalWrite(selA1, LOW);
digitalWrite(selA2, LOW);
digitalWrite(E3, HIGH);
}
void loop()
{
/*turn on LED 1 */
digitalWrite(selA0, LOW);
digitalWrite(selA1, LOW);
digitalWrite(selA2, LOW);
delay(1000);
/*turn on LED 2 */
digitalWrite(selA0, HIGH);
digitalWrite(selA1, LOW);
digitalWrite(selA2, LOW);
delay(1000);
/*turn on LED 3 */
digitalWrite(selA0, LOW);
digitalWrite(selA1, HIGH);
digitalWrite(selA2, LOW);
delay(1000);
/*turn on LED 4 */
digitalWrite(selA0, HIGH);
digitalWrite(selA1, HIGH);
digitalWrite(selA2, LOW);
delay(1000);
/*turn on LED 5 */
digitalWrite(selA0, LOW);
digitalWrite(selA1, LOW);
digitalWrite(selA2, HIGH);
delay(1000);
}
Real Time Clock:
DS1302
The DS1302 Real Time Clock (RTC)
module is introduced trickle charge the clock chip, containing a real-time
clock / calendar and 31 bytes of static RAM, via a simple serial interface
to communicate with the
microcontroller. Real-time clock / calendar circuit provides seconds, minutes,
hours, days, weeks, months, years of
information, the number of days per
month and leap year automatically adjust the number of days. Clock can be done
by the AM / PM or 12
decided to use 24 hour format.
Between the DS1302 and the microcontroller can simply use the synchronous
serial communication mode, used
only three port lines: (1) RST
Reset (2) I / O data lines (3) SCLK serial clock. Clock / RAM read / write data
to a byte or up to 31 bytes of character
set way communication. DS1302
low-power work to maintain the data and clock information when power is less
than 1mW
Real time clock with the year 2100
to calculate the seconds, minutes, hours, days, weeks, months, years, the
ability, as well as the ability to leap
year adjustment
1.31 8 temporary data storage RAM
2.Serial I / O port pin makes the
least number of ways
3.Wide range of operating voltage
2.0 5.5V
4.Current 2.0V, less than 300nA
5.Read / write clock or RAM data
transmission when there are two single-byte transmit and multi-byte character
sets transfer mode
6.8-pin DIP package or optional
8-pin SOIC package assembly according to the surface
7.simple 3-wire interface
8.Vcc = 5V and TTL-compatible
9.Optional industrial temperature
range -40 to +85
10.Dual power tube for the main
power and backup power supply
Parameters:
1.PCB a single panel, size: 42mm *
24mm * 12mm(max)
Net weight:10g
Package weight:20g
Color:green (as the picture shows)
2 with 4 holes, about 3.1mm in
diameter
3 genuine spare battery for the
celestial sphere CR2032, Voltage 3V, current is 260mAh, non-rechargeable
batteries.
4
5.DS1302 made large 8-pin DIP chip,
chip, IC Block below for easy replacement and plug the chip
6 module operating voltage
compatible 3.3V/5V, 5V and 3.3V microcontrollers can be connected with
7 Operating temperature: 0℃ --- 70 ℃
NOTE:
Wiring (to provide the program, for
example, can take any IO port, the port defined in the program can be
modified):
Module NodeMCU
VCC +5 V/3.3V
GND GND
CLK D0, GPIO16
DAT
D1, GPIO5
RST D2, GPIO4
Sketch to set time and observe the
time.
//This code is to
use with DS1302 RTC module, it permits you to setup the actual time and date
//And you can
visualize them on the serial monitor
//This code is a
modified version of the code provided in virtuabotixRTC library
//Refer to
Surtrtech Youtube chhannel/Facebook page for more information
#include
<virtuabotixRTC.h> //Library used
//Wiring: CLK
-> 11 , DAT -> 12, Reset -> 13
virtuabotixRTC
myRTC(16, 5, 4); //If you change the wiring change the pins here also
void setup() {
Serial.begin(9600);
// Set the current
date, and time in the following format:
// seconds, minutes, hours, day of the week,
day of the month, month, year
// myRTC.setDS1302Time(10, 31, 12, 3, 01, 06,
2020); //Here you write your actual time/date as shown above
//but remember to "comment/remove"
this function once you're done
//The setup is done only one time and the
module will continue counting it automatically
}
void loop() {
// This allows for the update of variables for
time or accessing the individual elements.
myRTC.updateTime();
// Start printing
elements as individuals
Serial.print("Current Date / Time:
");
Serial.print(myRTC.dayofmonth); //You can
switch between day and month if you're using American system
Serial.print("/");
Serial.print(myRTC.month);
Serial.print("/");
Serial.print(myRTC.year);
Serial.print(" ");
Serial.print(myRTC.hours);
Serial.print(":");
Serial.print(myRTC.minutes);
Serial.print(":");
Serial.println(myRTC.seconds);
// Delay so the
program doesn't print non-stop
delay(1000);
}
Serial I2C EEPROM
AT24C256
From wiki: EEPROM (also
E2PROM) stands for Electrically Erasable Programmable Read-Only Memory and is a
type of non-volatile memory used in computers, integrated in microcontrollers for
smart cards and remote keyless system, and other electronic devices to store
relatively small amounts of data but allowing individual bytes to be erased and
reprogrammed
AT24C256
Serial EEPROM I2C Interface EEPROM is a data storage module.
There
are pins for power supply, …… power indicator on the board;
Because
this chip is I2C, it only uses the analog pins 4 & 5 (SDA and SCL), and of
course the power (5V) and GND.
Connect
as follows:
NodeMCU
pin D2 (GPIO4) to EEPROM pin 5 (SDA)
NodeMCU
pin D1 (GPIO5) to EEPROM pin 6 (SCL)
NodeMCU
Vcc to EEPROM pin 8 (Vcc)
It
is suggested to connect NodeMCU GND to EEPROM pin 1,2,3,4 but I left pins 1,2
and 3 open, ie not connected to anything.
Be
sure to leave pin 7 of the EEPROM open or tie it to GND otherwise the EEPROM
will be write protected.
Adapted
from http://arduinolearning.com/learning/basics/interfacing-to-a-24lc256-eeprom.php
#include
<Wire.h> // for I2C
#define
eeprom_address 0x50 // device address
byte
d=0;
void
setup()
{
Serial.begin(115200); // Initialize the
serial
Wire.begin();
//write data out
Serial.println("Writing data.");
for (int i=0; i<10; i++)
{
writeData(i,i);
}
Serial.println("Complete");
//read data back
Serial.println("
for (int i=0; i<10; i++)
{
Serial.print(i);
Serial.print(" : ");
d=readData(i);
Serial.println(d, DEC);
}
Serial.println("Complete");
}
//
writes a byte of data in memory location eaddress
void
writeData(unsigned int eaddress, byte data)
{
Wire.beginTransmission(eeprom_address);
// set the pointer position
Wire.write((int)(eaddress >> 8));
Wire.write((int)(eaddress & 0xFF));
Wire.write(data);
Wire.endTransmission();
delay(10);
}
//
reads a byte of data from memory location eaddress
byte
readData(unsigned int eaddress)
{
byte result;
Wire.beginTransmission(eeprom_address);
// set the pointer position
Wire.write((int)(eaddress >> 8));
Wire.write((int)(eaddress & 0xFF));
Wire.endTransmission();
Wire.requestFrom(eeprom_address,1); // get
the byte of data
result = Wire.read();
return result;
}
void
loop()
{
}
Upload
the sketch and open the serial monitor. Select the baud rate of 115200. Press
the reset button on the NodeMCU and you should see a display similar to that
below.
EEPROM AT24C02
Intro
Wiring
AT24C02 NodeMCU
SDA D2, GPIO4
SCL D1, GPIO5
GND GND
VCC 3,3V
#include
<Wire.h>
void
eeprom_i2c_write(byte address, byte from_addr, byte data) {
Wire.beginTransmission(address);
Wire.write(from_addr);
Wire.write(data);
Wire.endTransmission();
}
byte
eeprom_i2c_read(int address, int from_addr) {
Wire.beginTransmission(address);
Wire.write(from_addr);
Wire.endTransmission();
Wire.requestFrom(address, 1);
if(Wire.available())
return Wire.read();
else
return 0xFF;
}
void
setup() {
Wire.begin();
Serial.begin(9600);
for(int i = 0; i < 10; i++) {
eeprom_i2c_write(B01010000, i, 'a'+i);
delay(100);
}
Serial.println("Writen to
memory!");
}
void
loop() {
for(int i = 0; i < 10; i++) {
byte r = eeprom_i2c_read(B01010000, i);
Serial.print(i);
Serial.print(" - ");
Serial.print(r);
Serial.print("\n");
delay(1000);
}
}
NE555 Frequency
Adjustable Pulse Generator
Blah blah
Data pin of the NE555
module to NodeMCU pin 0 (ADC0}.
void setup()
{
Serial.begin(9600);
}
void loop()
{
analogRead(0);
Serial.println(analogRead(0));
delay(200);
}
Connect To A
Network
To
connect to a WiFi network you will need to enter your SSID and Password into
the sketch
//
Adapted from Henry's Bench website
#include <ESP8266WiFi.h>
const char* ssid =
"xxxxxxxxxx"; //Your
SSID
const char* password =
"xxxxxxxxx"; //Your
Password
int wifiStatus;
void setup() {
Serial.begin(115200);\
delay(200);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Your are connecting
to;");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
}
void
loop() {
wifiStatus = WiFi.status();
if(wifiStatus == WL_CONNECTED){
Serial.println("");
Serial.println("Your ESP is
connected!");
Serial.println("Your IP address is:
");
Serial.println(WiFi.localIP());
}
else{
Serial.println("");
Serial.println("WiFi not
connected");
}
delay(1000); // check for connection
every once a second
}
Blah
Scan WiFi Network
Here
the module is set to scan local WiFi networks. Once the sketch is uploaded,
open the serial monitor not forgetting to set the baud rate to 115200.
//Adapted
from https://circuits4you.com
#include
<ESP8266WiFi.h>
void
setup() {
Serial.begin(115200);
Serial.println("");
// Set WiFi to station mode and disconnect
from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect(); //ESP has tendency to store old SSID and
PASSword and tries to connect
delay(100);
Serial.println("WiFi 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));
Serial.println((WiFi.encryptionType(i) ==
ENC_TYPE_NONE)?" Unsecured":" Secured");
delay(10);
}
}
Serial.println("");
delay(5000); //Pause before starting a new
scan
}
For
each scan performed, you will see a list of discovered networks. For each
network the following will be displayed: SSID. Signal Strength, MAC Address and
Encryption Type. For security reasons I have not supplied a screenshot of the
output that I obtained.
Serial plot
required
Communicating
With Arduino
The
NodeMCU can communicate with the Arduino micro controllers by using NRF24L01
WiFi transceivers. In the example below, the NodeMCU will connect to the
internet and retrieve the time. A NRF24L01 transceiver connected to the NodeMCU
will transmit the time. An Arduino (Nano in this case) will receive the time
data via a connected NRF24L01 transceiver and display this on an OLED.
Firstly,
connect an NRF24L01 transceiver to the NodeMCU as follows
NRF24l01 NodeMCU
VCC 3.3V
GND GND
CE D4
CSN D2
MOSI D7
MISO D6
SCK D5
The
following sketch will enable to NodeMCU to connect to the internet, obtain the
time and then transmit that time via a NRF24L01 transceiver. You will need to
enter your own SSID and password into the sketch before uploading.
#include
<RH_NRF24.h>
#include
<ESP8266WiFi.h>
#include
<time.h>
const
char* ssid = "xxxxxx";
const
char* password = "xxxxxx";
RH_NRF24
nrf24(2,4);
void
setup()
{
Serial.begin(9600);
while (!Serial);
if (!nrf24.init())
Serial.println("initialization
failed");
if (!nrf24.setChannel(1))
Serial.println("Channel set
failed");
if (!nrf24.setRF(RH_NRF24::DataRate2Mbps,
RH_NRF24::TransmitPower0dBm))
Serial.println("RF set
failed");
Serial.setDebugOutput(true);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("\nConnecting to
WiFi");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
configTime(0, 0, "pool.ntp.org",
"time.nist.gov"); // the first zero is UTC time. If you are in a
different time zone you will need to alter this (in seconds). The second zero
relates to daylight saving.
Serial.println("\nWaiting for
time");
while (!time(nullptr)) {
Serial.print(".");
delay(1000);
}
Serial.println("");
}
void
loop()
{
Serial.println("Sending data to
receiver");
time_t now = time(nullptr);
String timestring = String(ctime(&now));
uint8_t dataArray[timestring.length()];
timestring.getBytes(dataArray,timestring.length());
nrf24.send(dataArray,sizeof(dataArray));
nrf24.waitPacketSent();
delay(1000);
}
Once
the sketch is uploaded, open the serial monitor.
Firstly
you will see that the NodeMCU attempts to connect to the internet. Once
connected, the SSID is displayed (I have erased mine in the screenshot above)
along with IP address, subnet mask and gateway. Once connected to the internet,
“Waiting for time” is printed. Once the time is obtained, this is the sent to
the receiver.
The
next step is to set up an Arduino as a receiver. Firstly connect an NRF24L01 as
follows:
NRF24L01 Arduino Nano
VCC 3.3V
GND GND
CSN 10
CE 9
SCK 13
MOSI 11
MISO 12
Connect
an i2C OLED to the Arduino as follows:
OLED Arduino (Nano)
VCC 3.3V
GND GND
SCC A5
SDA A4
Upload
the following sketch:
#include
<RH_NRF24.h>
#include
<Wire.h>
#include
<Adafruit_GFX.h>
#include
<Adafruit_SSD1306.h>
#define
SCREEN_WIDTH 128 // OLED display width, in pixels
#define
SCREEN_HEIGHT 64 // OLED display height, in pixels
//
Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306
display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
RH_NRF24
nrf24;
void
setup()
{
Serial.begin(9600);
while (!Serial) ;
if (!nrf24.init())
Serial.println("initialization
failed");
if (!nrf24.setChannel(1))
Serial.println("Channel Set
failed");
if (!nrf24.setRF(RH_NRF24::DataRate2Mbps,
RH_NRF24::TransmitPower0dBm))
Serial.println("RF set failed");
if(!display.begin(SSD1306_SWITCHCAPVCC,
0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation
failed"));
for(;;);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
}}
void
loop()
{
if (nrf24.available())
{
uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if(nrf24.recv(buf, &len))
{
Serial.print("Received: ");
Serial.println((char*)buf);
String data=String((char*)buf);
display.clearDisplay();
//display.print(data);
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(WHITE);
display.print(data.substring(0,10));
display.print (" ");
display.print(data.substring( 20,24));
display.setCursor(0,10);
display.print("Time:");
display.print (" ");
display.print(data.substring(11,19));
display.display();
}
else
{
Serial.println("recv failed");
}
}
}
The
day, month, date and year are displayed on the first line of the OLED. The time
(hour, minutes, seconds) is displayed on the second line of the OLED. This data
is updated every second.
Open
the serial monitor:
You
will see the time data updating every second.
ESP8266 Web Server
This
ESP8266 module can be used as a web server. It is capable of hosting web pages
that can be accessed by various devices as will be seen if the following sketch
is uploaded.
You
will need to enter your SSID and Password into the sketch before uploading it.
Firstly
set up a circuit that has two LEDs connected to the module. In this example, I
have connected the LEDs to pins D1 and D2 of the ESP8266 module.
// Adapted from
https://randomnerdtutorials.com
#include
<ESP8266WiFi.h> // Load Wi-Fi library
const char* ssid = "xxxxxxxxx";
const char* password =
"xxxxxxxxxx";
//
Set web server port number to 80
WiFiServer
server(80);
//
Variable to store the HTTP request
String
header;
//
Auxiliar variables to store the current output state
String
output5State = "off";
String
output4State = "off";
//
Assign output variables to GPIO pins
const
int output5 = 5;
const
int output4 = 4;
//
Current time
unsigned
long currentTime = millis();
//
Previous time
unsigned
long previousTime = 0;
//
Define timeout time in milliseconds (example: 2000ms = 2s)
const
long timeoutTime = 2000;
void
setup() {
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(output5, OUTPUT);
pinMode(output4, OUTPUT);
// Set outputs to LOW
digitalWrite(output5, LOW);
digitalWrite(output4, LOW);
// Connect to Wi-Fi network with SSID and
password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print local IP address and start web
server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
void
loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client
connects,
Serial.println("New
Client."); // print a
message out in the serial port
String currentLine = ""; // make a String to hold
incoming data from the client
currentTime = millis();
previousTime = currentTime;
while (client.connected() &&
currentTime - previousTime <= timeoutTime) { // loop while the client's
connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from
the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial
monitor
header += c;
if (c == '\n') { // if the byte is a newline
character
// if the current line is blank, you
got two newline characters in a row.
// that's the end of the client HTTP
request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a
response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client
knows what's coming, then a blank line:
client.println("HTTP/1.1 200
OK");
client.println("Content-type:text/html");
client.println("Connection:
close");
client.println();
// turns the GPIOs on and off
if (header.indexOf("GET
/5/on") >= 0) {
Serial.println("GPIO 5
on");
output5State = "on";
digitalWrite(output5, HIGH);
} else if (header.indexOf("GET
/5/off") >= 0) {
Serial.println("GPIO 5
off");
output5State = "off";
digitalWrite(output5, LOW);
} else if (header.indexOf("GET
/4/on") >= 0) {
Serial.println("GPIO 4
on");
output4State = "on";
digitalWrite(output4, HIGH);
} else if (header.indexOf("GET
/4/off") >= 0) {
Serial.println("GPIO 4
off");
output4State = "off";
digitalWrite(output4, LOW);
}
// Display the HTML web page
client.println("<!DOCTYPE
html><html>");
client.println("<head><meta name=\"viewport\"
content=\"width=device-width, initial-scale=1\">");
client.println("<link
rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the
background-color and font-size attributes to fit your preferences
client.println("<style>html
{ font-family: Helvetica; display: inline-block; margin: 0px auto; text-align:
center;}");
client.println(".button {
background-color: #195B6A; border: none; color: white; padding: 16px
40px;");
client.println("text-decoration:
none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2
{background-color: #77878A;}</style></head>");
// Web Page Heading
client.println("<body><h1>ESP8266 Web
Server</h1>");
// Display current state, and
ON/OFF buttons for GPIO 5
client.println("<p>GPIO
5 - State " + output5State + "</p>");
// If the output5State is off, it
displays the ON button
if (output5State=="off")
{
client.println("<p><a
href=\"/5/on\"><button
class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a
href=\"/5/off\"><button class=\"button
button2\">OFF</button></a></p>");
}
// Display current state, and
ON/OFF buttons for GPIO 4
client.println("<p>GPIO
4 - State " + output4State + "</p>");
// If the output4State is off, it
displays the ON button
if (output4State=="off")
{
client.println("<p><a
href=\"/4/on\"><button
class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a
href=\"/4/off\"><button class=\"button
button2\">OFF</button></a></p>");
}
client.println("</body></html>");
// The HTTP response ends with
another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline,
then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage
return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client
disconnected.");
Serial.println("");
}
}
After
turning on the first (GPIO 5) LED, I opened the serial monitor.
Getting Time From
The Internet
Intro
You
will need to enter your SSID and password into the sketch before uploading it
to the ESP8266 module.
From
https://lastminuteengineers.com/esp8266-ntp-server-date-time-tutorial/
#include
<NTPClient.h>
#include
<ESP8266WiFi.h>
#include
<WiFiUdp.h>
const
char *ssid =
"xxxxxxx"; //Insert
your SSID
const
char *password = "fxxxxxx";
//Insert your password
const
long utcOffsetInSeconds = 0;
char
daysOfTheWeek[7][12] = {"Sunday", "Monday",
"Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday"};
//
Define NTP Client to get time
WiFiUDP
ntpUDP;
NTPClient
timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
void
setup(){
Serial.begin(115200);
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED ) {
delay ( 500 );
Serial.print ( "." );
}
timeClient.begin();
}
void
loop() {
timeClient.update();
Serial.print(daysOfTheWeek[timeClient.getDay()]);
Serial.print(", ");
Serial.print(timeClient.getHours());
Serial.print(":");
Serial.print(timeClient.getMinutes());
Serial.print(":");
Serial.println(timeClient.getSeconds());
//Serial.println(timeClient.getFormattedTime());
delay(1000);
}
ESP-NOW:
Receive Data from Multiple Boards
Blah blah
https://randomnerdtutorials.com/esp-now-many-to-one-esp8266-nodemcu/
blah
Get MAC address of the Receiver
#ifdef ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif
void setup(){
Serial.begin(115200);
Serial.println();
Serial.print("ESP Board MAC Address:
");
Serial.println(WiFi.macAddress());
}
void loop(){
}
Open the Serial Monitor:
Thie MAC address will need to be
copied and put into the the Reciver program below. Once you have done this,
upload the program to the Receiver module.
Set up the Receiver module:
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp-now-many-to-one-esp8266-nodemcu/
Permission is hereby granted,
free of charge, to any person obtaining a copy
of this software and associated
documentation files.
The above copyright notice and
this permission notice shall be included in all
copies or substantial portions of
the Software.
*/
#include <ESP8266WiFi.h>
#include <espnow.h>
// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0xEC,0xFA,0xBC,0xC1,0x5D,0x92};
// Set your Board ID (ESP32 Sender #1 = BOARD_ID 1, ESP32 Sender #2 =
BOARD_ID 2, etc)
#define BOARD_ID 4
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
int id;
int x;
int y;
} struct_message;
// Create a struct_message called test to store variables to be sent
struct_message myData;
unsigned long lastTime = 0;
unsigned long timerDelay = 10000;
// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
Serial.print("\r\nLast
Packet Send Status: ");
if (sendStatus == 0){
Serial.println("Delivery
success");
}
else{
Serial.println("Delivery
fail");
}
}
void setup() {
// Init Serial Monitor
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error
initializing ESP-NOW");
return;
}
// Set ESP-NOW role
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
// Once ESPNow is successfully
init, we will register for Send CB to
// get the status of Trasnmitted
packet
esp_now_register_send_cb(OnDataSent);
// Register peer
esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
void loop() {
if ((millis() - lastTime) >
timerDelay) {
// Set values to send
myData.id = BOARD_ID;
myData.x = random(1, 50);
myData.y = random(1, 50);
// Send message via ESP-NOW
esp_now_send(0, (uint8_t *)
&myData, sizeof(myData));
lastTime = millis();
}
}
In this example I used four Sender modules. Set up the Sender modules by
uploading the following program. The Receiver MAC Address will need to be
entered and the board ID will need to be set, the latter different for each
board.
/*
Rui Santos
Complete project details at
https://RandomNerdTutorials.com/esp-now-many-to-one-esp8266-nodemcu/
Permission is hereby granted,
free of charge, to any person obtaining a copy
of this software and associated
documentation files.
The above copyright notice and
this permission notice shall be included in all
copies or substantial portions of
the Software.
*/
#include <ESP8266WiFi.h>
#include <espnow.h>
// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0xEC,0xFA,0xBC,0xC1,0x5D,0x92};
// Set your Board ID (ESP32 Sender #1 = BOARD_ID 1, ESP32 Sender #2 =
BOARD_ID 2, etc)
#define BOARD_ID 4
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
int id;
int x;
int y;
} struct_message;
// Create a struct_message called test to store variables to be sent
struct_message myData;
unsigned long lastTime = 0;
unsigned long timerDelay = 10000;
// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
Serial.print("\r\nLast
Packet Send Status: ");
if (sendStatus == 0){
Serial.println("Delivery
success");
}
else{
Serial.println("Delivery
fail");
}
}
void setup() {
// Init Serial Monitor
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error
initializing ESP-NOW");
return;
}
// Set ESP-NOW role
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
// Once ESPNow is successfully
init, we will register for Send CB to
// get the status of Trasnmitted
packet
esp_now_register_send_cb(OnDataSent);
// Register peer
esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
void loop() {
if ((millis() - lastTime) >
timerDelay) {
// Set values to send
myData.id = BOARD_ID;
myData.x = random(1, 50);
myData.y = random(1, 50);
// Send message via ESP-NOW
esp_now_send(0, (uint8_t *)
&myData, sizeof(myData));
lastTime = millis();
}
}
Upload the program to each of the Sender modules. When all Sender modules
are programmed and powered up, connect the Receiver modulw to a computer and
open the Serial Monitor. Below is a screenshot from the Receiver module. You
can see the two random numbers received from each of the four Sender modules.
Blah
ESP-NOW: Send Data to Multiple Boards
blah
Message Queuing Telemetry Transport (MQTT)
MQTT (Message Queuing Telemetry
Transport) is an OASIS standard messaging protocol for the Internet of Things
(IoT). It is designed as an extremely lightweight publish/subscribe messaging
transport that is ideal for connecting remote devices with a small code
footprint and minimal network bandwidth. MQTT today is used in a wide variety
of industries, such as automotive, manufacturing, telecommunications, oil and
gas, etc.
MQTT is lightweight publish-subscribe
based messaging protocol. Here are some of it’s main features:
a. It is quicker (faster) than other
request-response based APIs like HTTP.
b. It is developed on the base of TCP/IP
protocol.
c. It allows remote location devices to
connect, subscribe, publish etc. to a specific topic on the server with the
help of message broker.
d. MQTT Broker/Message broker is a module
in between the sender and the receiver. It is an element for message
validation, transformation and routing.
e. The broker is responsible for
distributing messages to the interested clients (subscribed clients) of their
interested topic.
If you do not want to host your own MQTT broker, you can use one of many that are available online such as Adafruit IO's MQTT broker. Using these online brokers is a great way to get started connecting your projects to the internet. You will be able to visualize incoming data from your microcontroller boards and send data to them.
Basic MQTT Example
https://osoyoo.com/2017/05/10/nodemcu-lesson-5-mqtt-pubsubclient/
mqtt_esp8266A
Here, the basic MQTT protocol usage on the NodeMCU
board will be implemented. MQTTBox client software will be used and the NodeMCU
to complete following operations:
a. Publish “hello world” to the topic “outTopic” every
two seconds.
b. Subscribe to the topic “inTopic”, print out any
received messages.
d. It assumes the received payloads are strings not
binaries.
e. If the subscribed message is “1”, light the
onboards LED.Turn off the onboard LED if the message to subscribe is “0”.
f. It will reconnect to the server if the connection is lost using a blocking reconnect function.
There are many MQTT clients available on the internet
which can be used but the example below uses the MQTTBox client which can be
downloaded from here: http://workswithweb.com/mqttbox.html
Firstly, the program needs to be set up using the
Arduino IDE.
install MQTT endpoint library(PubSubClient) to
communicate with MQTT broker, this can be downloaded from following link:
https://osoyoo.com/wp-content/uploads/samplecode/pubsubclient.zip
Unzip above file and move the unzipped folder to
Arduino IDE library folder. Restart the Arduino IDE. Open the Arduino IDE and navigate to
“File”, “Examples”, “PubSubClient” and select “mqtt_basic” to load the file.
The program needs to have your internet and on-line
broker details and credentials. Edit the following lines in the program:
onst char* ssid = "your ssid";
const char* password = "password for your
internet hub";
const char* mqtt_server = "your mqtt broker
website";
The default MQTT broker is set to
"broker.mqtt-dashboard.com" which you can leave as this is s free
service that doesn’t require any registration and is free. It is an ideal
platform for testing. You can use your own MQTT broker URL or IP address to set
the mqtt_server value. You can also use some other free MQTT server to test the
project such as
“broker.mqtt-dashboard.com”,
“iot.eclipse.org” etc.
If your MQTT broker requires clientID,username and
password authentication,you need to change the following line of code
if (client.connect(clientId.c_str()))
to
if (client.connect(clientId,userName,passWord)) //put
your clientId/userName/passWord here
If not,just keep them as the default. Upload the
program to the NodeMCU using the Artduino IDE.
Next, install MQTTBox client. After the installation,
there are only a few parameters to setup.
Fisrstly, click “Create MQTT Client”. In the “MQTT
Client Name” box type in a name for the client; this can be anything. In the
Protocol dropdown box choose “mqtt/tcp”. In the “Host”
If you now open the Arduino IDE Serial Monitor you
will see the published message “hello world” being received.
When payload “0” is published to this topic, the
NodeMCU on-board LED will be turned off.
Publish To Broker
and View Online
On the Arduino IDE there are example sketches for the
Adafruit IO online broker. Adafruit.io is a cloud service that you can connect
to over the internet. It's meant primarily for storing and then retrieving data
but it can do a lot more. It can:
Display data in real-time, online
Make projects internet-connected: Control motors and
read sensor data and much more
Connect projects to web services like Twitter, RSS
feeds, weather services, etc.
Connect projects to other internet-enabled devices
You can use triggers to control and react to data.
Configure triggers to email you when your system goes offline, react to a
temperature sensor getting too hot, and publish a message to a new feed.
After registering for an Adafruit IO account, the next
step is to load one of the example sketches in the Arduino IDE. Select “File”, “Examples”.
“Adafruit IO “ and select the “adafruitio_00_publish” sketch. Click on the
“config.h” tab at the top of the Ardiono IDE and replace the placeholders with
your Adafruit IO credentials and your WiFi connection credentials. Upload the
sketch to the NodeMCU.
Open the Arduino IDE Serial Monitor and selct a baud
rate of 115200 if it is not already selected. You will see that the NodeMCU is
sending data.to
Click on the appropriate icon on the right hand side
of the dashboard. In the this example I chose “stream”. Choose the counter feed
and click “Next”. Modify the stream block options as needed, and click the
“create block” button when you are finished. Now when you open that dashboard
you will see a stream of data being received from the NodeMCU.
Here is the data that is being sent by the NodeLUA:
https://learn.adafruit.com/adafruit-io-basics-esp8266-arduino/example-sketches
https://learn.adafruit.com/series/adafruit-io-basics
MQTT Analog
Input
https://www.electronicwings.com/nodemcu/nodemcu-mqtt-client-with-arduino-ide
https://io.adafruit.com/CyberBertie/dashboards/potentiometer
LUA_MQTT_LED_pot
This example utilises the visualisation of data
facilities of the on-line Adafruit broker Adafruit IO Basics: Dashboards by
sending analog values from a potentiometer to Adafruit IO via a NodeMCU.
Connect the NodeMCU to the PC using a usb cable and
launch the Arduino IDE. Firstly you will need to install Adafruit IO, Adafruit
MQTT, and ArduinoHttpClient libraries using the Arduino Library Manager to
communicate with MQTT broker. To do this navigate to “Sketch”, “Include Library”, “Manage Libraries”. Enter “Adafruit IO
Arduino” into the search box, and click “Install” on the Adafruit IO Arduino
library option, ensuring that the latest version is ticked in the version drop
down menu.
Enter “Adafruit MQTT” into the search box, and click
“Install”on the Adafruit MQTT library option, remembering to select the latest
version. Finally, enter “Arduino Http Client” into the search box, and click
“Install” on the ArduinoHttpClient library option, again ensuring that the
latest version was selected.
The Arduino IDE is now set up so it’s time to test it
out.
Open the example of Adafruit mqtt io dashboard. To
open it navigate to “File”, “Examples”, “Adafruit MQTT Library”, “mqtt_esp8266”
Attach the centre pin of a 10kohm potentiometer to pin
A0 (ADC0) of the Node MCU and the outer pins one to GND, the other to 3V. Connect an LED to pin
D6 (GPIO12) via a 33ohm resisitor and the short leg (GND )to GND.
You need to create an accound on the
This sketch will need to be edited so that the wifi
and Adafruit IO credentials have the correct information. .
#define WLAN_SSID
"...your SSID..."
#define WLAN_PASS
"...your password..."
#define AIO_SERVER
"io.adafruit.com"
#define AIO_SERVERPORT
1883 // use 8883 for SSL
#define AIO_USERNAME
"...your AIO username (see https://accounts.adafruit.com)..."
#define AIO_KEY
"...your AIO key..."
Here is the full code.
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#define WLAN_SSID
"xxxxxxx"
#define WLAN_PASS
"xxxxxx"
#define AIO_SERVER
"io.adafruit.com"
#define AIO_SERVERPORT
1883 // use 8883
for SSL
#define AIO_USERNAME
"xxxxxx"
#define AIO_KEY
"xxxxxx"
// Create an ESP8266 WiFiClient class to connect to
the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;
// Setup the MQTT client class by passing in the WiFi
client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER,
AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
// Setup a feed called 'potValue' for publishing.
// Notice MQTT paths for AIO follow the form:
<username>/feeds/<feedname>
Adafruit_MQTT_Publish potValue = Adafruit_MQTT_Publish(&mqtt,
AIO_USERNAME "/feeds/potValue");
// Setup a feed called 'ledBrightness' for subscribing
to changes.
Adafruit_MQTT_Subscribe ledBrightness =
Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME
"/feeds/ledBrightness");
void MQTT_connect();
uint8_t ledPin = 12; //D6, GPIO12
uint16_t potAdcValue = 0;
uint16_t ledBrightValue = 0;
void setup() {
Serial.begin(9600);
delay(10);
Serial.println(F("Adafruit MQTT demo"));
// Connect to
WiFi access point.
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while
(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Setup MQTT
subscription for ledBrightness feed.
mqtt.subscribe(&ledBrightness);
}
void loop() {
// Ensure the
connection to the MQTT server is alive (this will make the first
// connection
and automatically reconnect when disconnected).
See the MQTT_connect
MQTT_connect();
Adafruit_MQTT_Subscribe *subscription;
while
((subscription = mqtt.readSubscription(200))) {
if
(subscription == &ledBrightness) {
Serial.print(F("Got LED Brightness : "));
ledBrightValue = atoi((char *)ledBrightness.lastread);
Serial.println(ledBrightValue);
analogWrite(ledPin, ledBrightValue);
}
}
// Now we can
publish stuff!
uint16_t
AdcValue = analogRead(A0);
if((AdcValue
> (potAdcValue + 7)) || (AdcValue < (potAdcValue - 7))){
potAdcValue
= AdcValue;
Serial.print(F("Sending pot val "));
Serial.print(potAdcValue);
Serial.print("...");
if (!
potValue.publish(potAdcValue)) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
delay(5000);
}
// ping the
server to keep the mqtt connection alive
// NOT
required if you are publishing once every KEEPALIVE seconds
/*
if(!
mqtt.ping()) {
mqtt.disconnect();
}
*/
}
// Function to connect and reconnect as necessary to
the MQTT server.
// Should be called in the loop function and it will
take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if
already connected.
if
(mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t
retries = 3;
while ((ret =
mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if
(retries == 0) {
//
basically die and wait for WDT to reset me
while
(1);
}
}
Serial.println("MQTT
Connected!");
}
One the code is uploaded, log on to your Adafruit IO
account and create a dashboard for viewing your data. The example below shows a
feed of the potentiometer reading which is updated every five seconds (5000ms)
and a representative line graph of the data. There are other blocks that can be
used.
The data can be accessed from any client as long as they have internet access and the logon credentials for the dashboard.
Connect To A
Network
To
connect to a WiFi network you will need to enter your SSID and Password into
the sketch
//
Adapted from Henry's Bench website
#include <ESP8266WiFi.h>
const char* ssid =
"xxxxxxxxxx"; //Your
SSID
const char* password =
"xxxxxxxxx"; //Your
Password
int wifiStatus;
void setup() {
Serial.begin(115200);\
delay(200);
// We start by connecting to a WiFi network
Serial.println();
Serial.println();
Serial.print("Your are connecting
to;");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
}
void
loop() {
wifiStatus = WiFi.status();
if(wifiStatus == WL_CONNECTED){
Serial.println("");
Serial.println("Your ESP is
connected!");
Serial.println("Your IP address is:
");
Serial.println(WiFi.localIP());
}
else{
Serial.println("");
Serial.println("WiFi not
connected");
}
delay(1000); // check for connection
every once a second
}
Blah
Scan WiFi Network
Here
the module is set to scan local WiFi networks. Once the sketch is uploaded,
open the serial monitor not forgetting to set the baud rate to 115200.
//Adapted
from https://circuits4you.com
#include
<ESP8266WiFi.h>
void
setup() {
Serial.begin(115200);
Serial.println("");
// Set WiFi to station mode and disconnect
from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect(); //ESP has tendency to store old SSID and
PASSword and tries to connect
delay(100);
Serial.println("WiFi 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));
Serial.println((WiFi.encryptionType(i) ==
ENC_TYPE_NONE)?" Unsecured":" Secured");
delay(10);
}
}
Serial.println("");
delay(5000); //Pause before starting a new
scan
}
For
each scan performed, you will see a list of discovered networks. For each
network the following will be displayed: SSID. Signal Strength, MAC Address and
Encryption Type. For security reasons I have not supplied a screenshot of the
output that I obtained.
Serial plot
required
Communicating With Arduino
The
NodeMCU can communicate with the Arduino micro controllers by using NRF24L01
WiFi transceivers. In the example below, the NodeMCU will connect to the
internet and retrieve the time. A NRF24L01 transceiver connected to the NodeMCU
will transmit the time. An Arduino (Nano in this case) will receive the time
data via a connected NRF24L01 transceiver and display this on an OLED.
Firstly,
connect an NRF24L01 transceiver to the NodeMCU as follows
NRF24l01 NodeMCU
VCC 3.3V
GND GND
CE D4
CSN D2
MOSI D7
MISO D6
SCK D5
The
following sketch will enable to NodeMCU to connect to the internet, obtain the
time and then transmit that time via a NRF24L01 transceiver. You will need to
enter your own SSID and password into the sketch before uploading.
#include
<RH_NRF24.h>
#include
<ESP8266WiFi.h>
#include
<time.h>
const
char* ssid = "xxxxxx";
const
char* password = "xxxxxx";
RH_NRF24
nrf24(2,4);
void
setup()
{
Serial.begin(9600);
while (!Serial);
if (!nrf24.init())
Serial.println("initialization
failed");
if (!nrf24.setChannel(1))
Serial.println("Channel set
failed");
if (!nrf24.setRF(RH_NRF24::DataRate2Mbps,
RH_NRF24::TransmitPower0dBm))
Serial.println("RF set
failed");
Serial.setDebugOutput(true);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("\nConnecting to
WiFi");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
configTime(0, 0, "pool.ntp.org",
"time.nist.gov"); // the first zero is UTC time. If you are in a
different time zone you will need to alter this (in seconds). The second zero
relates to daylight saving.
Serial.println("\nWaiting for
time");
while (!time(nullptr)) {
Serial.print(".");
delay(1000);
}
Serial.println("");
}
void
loop()
{
Serial.println("Sending data to
receiver");
time_t now = time(nullptr);
String timestring = String(ctime(&now));
uint8_t dataArray[timestring.length()];
timestring.getBytes(dataArray,timestring.length());
nrf24.send(dataArray,sizeof(dataArray));
nrf24.waitPacketSent();
delay(1000);
}
Once
the sketch is uploaded, open the serial monitor.
Firstly
you will see that the NodeMCU attempts to connect to the internet. Once
connected, the SSID is displayed (I have erased mine in the screenshot above)
along with IP address, subnet mask and gateway. Once connected to the internet,
“Waiting for time” is printed. Once the time is obtained, this is the sent to
the receiver.
The
next step is to set up an Arduino as a receiver. Firstly connect an NRF24L01 as
follows:
NRF24L01 Arduino Nano
VCC 3.3V
GND GND
CSN 10
CE 9
SCK 13
MOSI 11
MISO 12
Connect
an i2C OLED to the Arduino as follows:
OLED Arduino (Nano)
VCC 3.3V
GND GND
SCC A5
SDA A4
Upload
the following sketch:
#include
<RH_NRF24.h>
#include
<Wire.h>
#include
<Adafruit_GFX.h>
#include
<Adafruit_SSD1306.h>
#define
SCREEN_WIDTH 128 // OLED display width, in pixels
#define
SCREEN_HEIGHT 64 // OLED display height, in pixels
//
Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
Adafruit_SSD1306
display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
RH_NRF24
nrf24;
void
setup()
{
Serial.begin(9600);
while (!Serial) ;
if (!nrf24.init())
Serial.println("initialization
failed");
if (!nrf24.setChannel(1))
Serial.println("Channel Set
failed");
if (!nrf24.setRF(RH_NRF24::DataRate2Mbps,
RH_NRF24::TransmitPower0dBm))
Serial.println("RF set failed");
if(!display.begin(SSD1306_SWITCHCAPVCC,
0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation
failed"));
for(;;);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
}}
void
loop()
{
if (nrf24.available())
{
uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];
uint8_t len = sizeof(buf);
if(nrf24.recv(buf, &len))
{
Serial.print("Received: ");
Serial.println((char*)buf);
String data=String((char*)buf);
display.clearDisplay();
//display.print(data);
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(WHITE);
display.print(data.substring(0,10));
display.print (" ");
display.print(data.substring( 20,24));
display.setCursor(0,10);
display.print("Time:");
display.print (" ");
display.print(data.substring(11,19));
display.display();
}
else
{
Serial.println("recv failed");
}
}
}
The
day, month, date and year are displayed on the first line of the OLED. The time
(hour, minutes, seconds) is displayed on the second line of the OLED. This data
is updated every second.
Open
the serial monitor:
You
will see the time data updating every second.
ESP8266 Web Server
This
ESP8266 module can be used as a web server. It is capable of hosting web pages
that can be accessed by various devices as will be seen if the following sketch
is uploaded.
You
will need to enter your SSID and Password into the sketch before uploading it.
Firstly
set up a circuit that has two LEDs connected to the module. In this example, I
have connected the LEDs to pins D1 and D2 of the ESP8266 module.
// Adapted from
https://randomnerdtutorials.com
#include
<ESP8266WiFi.h> // Load Wi-Fi library
const char* ssid = "xxxxxxxxx";
const char* password =
"xxxxxxxxxx";
//
Set web server port number to 80
WiFiServer
server(80);
//
Variable to store the HTTP request
String
header;
//
Auxiliar variables to store the current output state
String
output5State = "off";
String
output4State = "off";
//
Assign output variables to GPIO pins
const
int output5 = 5;
const
int output4 = 4;
//
Current time
unsigned
long currentTime = millis();
//
Previous time
unsigned
long previousTime = 0;
//
Define timeout time in milliseconds (example: 2000ms = 2s)
const
long timeoutTime = 2000;
void
setup() {
Serial.begin(115200);
// Initialize the output variables as outputs
pinMode(output5, OUTPUT);
pinMode(output4, OUTPUT);
// Set outputs to LOW
digitalWrite(output5, LOW);
digitalWrite(output4, LOW);
// Connect to Wi-Fi network with SSID and
password
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
// Print local IP address and start web
server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
server.begin();
}
void
loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client
connects,
Serial.println("New
Client."); // print a
message out in the serial port
String currentLine = ""; // make a String to hold
incoming data from the client
currentTime = millis();
previousTime = currentTime;
while (client.connected() &&
currentTime - previousTime <= timeoutTime) { // loop while the client's
connected
currentTime = millis();
if (client.available()) { // if there's bytes to read from
the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial
monitor
header += c;
if (c == '\n') { // if the byte is a newline
character
// if the current line is blank, you
got two newline characters in a row.
// that's the end of the client HTTP
request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a
response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client
knows what's coming, then a blank line:
client.println("HTTP/1.1 200
OK");
client.println("Content-type:text/html");
client.println("Connection:
close");
client.println();
// turns the GPIOs on and off
if (header.indexOf("GET
/5/on") >= 0) {
Serial.println("GPIO 5
on");
output5State = "on";
digitalWrite(output5, HIGH);
} else if (header.indexOf("GET
/5/off") >= 0) {
Serial.println("GPIO 5
off");
output5State = "off";
digitalWrite(output5, LOW);
} else if (header.indexOf("GET
/4/on") >= 0) {
Serial.println("GPIO 4
on");
output4State = "on";
digitalWrite(output4, HIGH);
} else if (header.indexOf("GET
/4/off") >= 0) {
Serial.println("GPIO 4
off");
output4State = "off";
digitalWrite(output4, LOW);
}
// Display the HTML web page
client.println("<!DOCTYPE
html><html>");
client.println("<head><meta name=\"viewport\"
content=\"width=device-width, initial-scale=1\">");
client.println("<link
rel=\"icon\" href=\"data:,\">");
// CSS to style the on/off buttons
// Feel free to change the
background-color and font-size attributes to fit your preferences
client.println("<style>html
{ font-family: Helvetica; display: inline-block; margin: 0px auto; text-align:
center;}");
client.println(".button {
background-color: #195B6A; border: none; color: white; padding: 16px
40px;");
client.println("text-decoration:
none; font-size: 30px; margin: 2px; cursor: pointer;}");
client.println(".button2
{background-color: #77878A;}</style></head>");
// Web Page Heading
client.println("<body><h1>ESP8266 Web
Server</h1>");
// Display current state, and
ON/OFF buttons for GPIO 5
client.println("<p>GPIO
5 - State " + output5State + "</p>");
// If the output5State is off, it
displays the ON button
if (output5State=="off")
{
client.println("<p><a
href=\"/5/on\"><button
class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a
href=\"/5/off\"><button class=\"button
button2\">OFF</button></a></p>");
}
// Display current state, and
ON/OFF buttons for GPIO 4
client.println("<p>GPIO
4 - State " + output4State + "</p>");
// If the output4State is off, it
displays the ON button
if (output4State=="off")
{
client.println("<p><a
href=\"/4/on\"><button
class=\"button\">ON</button></a></p>");
} else {
client.println("<p><a
href=\"/4/off\"><button class=\"button
button2\">OFF</button></a></p>");
}
client.println("</body></html>");
// The HTTP response ends with
another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline,
then clear currentLine
currentLine = "";
}
} else if (c != '\r') { // if you got anything else but a carriage
return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = "";
// Close the connection
client.stop();
Serial.println("Client
disconnected.");
Serial.println("");
}
}
After
turning on the first (GPIO 5) LED, I opened the serial monitor.
Getting Time From
The Internet
Intro
You
will need to enter your SSID and password into the sketch before uploading it
to the ESP8266 module.
From
https://lastminuteengineers.com/esp8266-ntp-server-date-time-tutorial/
#include
<NTPClient.h>
#include
<ESP8266WiFi.h>
#include
<WiFiUdp.h>
const
char *ssid =
"xxxxxxx"; //Insert
your SSID
const
char *password = "fxxxxxx";
//Insert your password
const
long utcOffsetInSeconds = 0;
char
daysOfTheWeek[7][12] = {"Sunday", "Monday",
"Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday"};
//
Define NTP Client to get time
WiFiUDP
ntpUDP;
NTPClient
timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
void
setup(){
Serial.begin(115200);
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED ) {
delay ( 500 );
Serial.print ( "." );
}
timeClient.begin();
}
void
loop() {
timeClient.update();
Serial.print(daysOfTheWeek[timeClient.getDay()]);
Serial.print(", ");
Serial.print(timeClient.getHours());
Serial.print(":");
Serial.print(timeClient.getMinutes());
Serial.print(":");
Serial.println(timeClient.getSeconds());
//Serial.println(timeClient.getFormattedTime());
delay(1000);
}
ESP-NOW:
Receive Data from Multiple Boards
Blah blah
https://randomnerdtutorials.com/esp-now-many-to-one-esp8266-nodemcu/
blah
Get MAC address of the Receiver
#ifdef ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif
void setup(){
Serial.begin(115200);
Serial.println();
Serial.print("ESP Board MAC Address:
");
Serial.println(WiFi.macAddress());
}
void loop(){
}
Open the Serial Monitor:
Thie MAC address will need to be
copied and put into the the Reciver program below. Once you have done this,
upload the program to the Receiver module.
Set up the Receiver module:
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp-now-many-to-one-esp8266-nodemcu/
Permission is hereby granted,
free of charge, to any person obtaining a copy
of this software and associated
documentation files.
The above copyright notice and
this permission notice shall be included in all
copies or substantial portions of
the Software.
*/
#include <ESP8266WiFi.h>
#include <espnow.h>
// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0xEC,0xFA,0xBC,0xC1,0x5D,0x92};
// Set your Board ID (ESP32 Sender #1 = BOARD_ID 1, ESP32 Sender #2 =
BOARD_ID 2, etc)
#define BOARD_ID 4
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
int id;
int x;
int y;
} struct_message;
// Create a struct_message called test to store variables to be sent
struct_message myData;
unsigned long lastTime = 0;
unsigned long timerDelay = 10000;
// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
Serial.print("\r\nLast
Packet Send Status: ");
if (sendStatus == 0){
Serial.println("Delivery
success");
}
else{
Serial.println("Delivery
fail");
}
}
void setup() {
// Init Serial Monitor
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error
initializing ESP-NOW");
return;
}
// Set ESP-NOW role
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
// Once ESPNow is successfully
init, we will register for Send CB to
// get the status of Trasnmitted
packet
esp_now_register_send_cb(OnDataSent);
// Register peer
esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
void loop() {
if ((millis() - lastTime) >
timerDelay) {
// Set values to send
myData.id = BOARD_ID;
myData.x = random(1, 50);
myData.y = random(1, 50);
// Send message via ESP-NOW
esp_now_send(0, (uint8_t *)
&myData, sizeof(myData));
lastTime = millis();
}
}
In this example I used four Sender modules. Set up the Sender modules by
uploading the following program. The Receiver MAC Address will need to be
entered and the board ID will need to be set, the latter different for each
board.
/*
Rui Santos
Complete project details at
https://RandomNerdTutorials.com/esp-now-many-to-one-esp8266-nodemcu/
Permission is hereby granted,
free of charge, to any person obtaining a copy
of this software and associated
documentation files.
The above copyright notice and
this permission notice shall be included in all
copies or substantial portions of
the Software.
*/
#include <ESP8266WiFi.h>
#include <espnow.h>
// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0xEC,0xFA,0xBC,0xC1,0x5D,0x92};
// Set your Board ID (ESP32 Sender #1 = BOARD_ID 1, ESP32 Sender #2 =
BOARD_ID 2, etc)
#define BOARD_ID 4
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
int id;
int x;
int y;
} struct_message;
// Create a struct_message called test to store variables to be sent
struct_message myData;
unsigned long lastTime = 0;
unsigned long timerDelay = 10000;
// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
Serial.print("\r\nLast
Packet Send Status: ");
if (sendStatus == 0){
Serial.println("Delivery
success");
}
else{
Serial.println("Delivery
fail");
}
}
void setup() {
// Init Serial Monitor
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
WiFi.disconnect();
// Init ESP-NOW
if (esp_now_init() != 0) {
Serial.println("Error
initializing ESP-NOW");
return;
}
// Set ESP-NOW role
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
// Once ESPNow is successfully
init, we will register for Send CB to
// get the status of Trasnmitted
packet
esp_now_register_send_cb(OnDataSent);
// Register peer
esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
void loop() {
if ((millis() - lastTime) >
timerDelay) {
// Set values to send
myData.id = BOARD_ID;
myData.x = random(1, 50);
myData.y = random(1, 50);
// Send message via ESP-NOW
esp_now_send(0, (uint8_t *)
&myData, sizeof(myData));
lastTime = millis();
}
}
Upload the program to each of the Sender modules. When all Sender modules
are programmed and powered up, connect the Receiver modulw to a computer and
open the Serial Monitor. Below is a screenshot from the Receiver module. You
can see the two random numbers received from each of the four Sender modules.
Blah
ESP-NOW: Send Data to Multiple Boards
blah
Message Queuing Telemetry Transport (MQTT)
MQTT (Message Queuing Telemetry
Transport) is an OASIS standard messaging protocol for the Internet of Things
(IoT). It is designed as an extremely lightweight publish/subscribe messaging
transport that is ideal for connecting remote devices with a small code
footprint and minimal network bandwidth. MQTT today is used in a wide variety
of industries, such as automotive, manufacturing, telecommunications, oil and
gas, etc.
MQTT is lightweight publish-subscribe
based messaging protocol. Here are some of it’s main features:
a. It is quicker (faster) than other
request-response based APIs like HTTP.
b. It is developed on the base of TCP/IP
protocol.
c. It allows remote location devices to
connect, subscribe, publish etc. to a specific topic on the server with the
help of message broker.
d. MQTT Broker/Message broker is a module
in between the sender and the receiver. It is an element for message
validation, transformation and routing.
e. The broker is responsible for
distributing messages to the interested clients (subscribed clients) of their
interested topic.
If you do not want to host your own MQTT broker, you can use one of many that are available online such as Adafruit IO's MQTT broker. Using these online brokers is a great way to get started connecting your projects to the internet. You will be able to visualize incoming data from your microcontroller boards and send data to them.
Basic MQTT Example
https://osoyoo.com/2017/05/10/nodemcu-lesson-5-mqtt-pubsubclient/
mqtt_esp8266A
Here, the basic MQTT protocol usage on the NodeMCU
board will be implemented. MQTTBox client software will be used and the NodeMCU
to complete following operations:
a. Publish “hello world” to the topic “outTopic” every
two seconds.
b. Subscribe to the topic “inTopic”, print out any
received messages.
d. It assumes the received payloads are strings not
binaries.
e. If the subscribed message is “1”, light the
onboards LED.Turn off the onboard LED if the message to subscribe is “0”.
f. It will reconnect to the server if the connection is lost using a blocking reconnect function.
There are many MQTT clients available on the internet
which can be used but the example below uses the MQTTBox client which can be
downloaded from here: http://workswithweb.com/mqttbox.html
Firstly, the program needs to be set up using the
Arduino IDE.
install MQTT endpoint library(PubSubClient) to
communicate with MQTT broker, this can be downloaded from following link:
https://osoyoo.com/wp-content/uploads/samplecode/pubsubclient.zip
Unzip above file and move the unzipped folder to
Arduino IDE library folder. Restart the Arduino IDE. Open the Arduino IDE and navigate to
“File”, “Examples”, “PubSubClient” and select “mqtt_basic” to load the file.
The program needs to have your internet and on-line
broker details and credentials. Edit the following lines in the program:
onst char* ssid = "your ssid";
const char* password = "password for your
internet hub";
const char* mqtt_server = "your mqtt broker
website";
The default MQTT broker is set to
"broker.mqtt-dashboard.com" which you can leave as this is s free
service that doesn’t require any registration and is free. It is an ideal
platform for testing. You can use your own MQTT broker URL or IP address to set
the mqtt_server value. You can also use some other free MQTT server to test the
project such as
“broker.mqtt-dashboard.com”,
“iot.eclipse.org” etc.
If your MQTT broker requires clientID,username and
password authentication,you need to change the following line of code
if (client.connect(clientId.c_str()))
to
if (client.connect(clientId,userName,passWord)) //put
your clientId/userName/passWord here
If not,just keep them as the default. Upload the
program to the NodeMCU using the Artduino IDE.
Next, install MQTTBox client. After the installation,
there are only a few parameters to setup.
Fisrstly, click “Create MQTT Client”. In the “MQTT
Client Name” box type in a name for the client; this can be anything. In the
Protocol dropdown box choose “mqtt/tcp”. In the “Host”
If you now open the Arduino IDE Serial Monitor you
will see the published message “hello world” being received.
When payload “0” is published to this topic, the
NodeMCU on-board LED will be turned off.
Publish To Broker
and View Online
On the Arduino IDE there are example sketches for the
Adafruit IO online broker. Adafruit.io is a cloud service that you can connect
to over the internet. It's meant primarily for storing and then retrieving data
but it can do a lot more. It can:
Display data in real-time, online
Make projects internet-connected: Control motors and
read sensor data and much more
Connect projects to web services like Twitter, RSS
feeds, weather services, etc.
Connect projects to other internet-enabled devices
You can use triggers to control and react to data.
Configure triggers to email you when your system goes offline, react to a
temperature sensor getting too hot, and publish a message to a new feed.
After registering for an Adafruit IO account, the next
step is to load one of the example sketches in the Arduino IDE. Select “File”, “Examples”.
“Adafruit IO “ and select the “adafruitio_00_publish” sketch. Click on the
“config.h” tab at the top of the Ardiono IDE and replace the placeholders with
your Adafruit IO credentials and your WiFi connection credentials. Upload the
sketch to the NodeMCU.
Open the Arduino IDE Serial Monitor and selct a baud
rate of 115200 if it is not already selected. You will see that the NodeMCU is
sending data.to
Click on the appropriate icon on the right hand side
of the dashboard. In the this example I chose “stream”. Choose the counter feed
and click “Next”. Modify the stream block options as needed, and click the
“create block” button when you are finished. Now when you open that dashboard
you will see a stream of data being received from the NodeMCU.
Here is the data that is being sent by the NodeLUA:
https://learn.adafruit.com/adafruit-io-basics-esp8266-arduino/example-sketches
https://learn.adafruit.com/series/adafruit-io-basics
MQTT Analog
Input
https://www.electronicwings.com/nodemcu/nodemcu-mqtt-client-with-arduino-ide
https://io.adafruit.com/CyberBertie/dashboards/potentiometer
LUA_MQTT_LED_pot
This example utilises the visualisation of data
facilities of the on-line Adafruit broker Adafruit IO Basics: Dashboards by
sending analog values from a potentiometer to Adafruit IO via a NodeMCU.
Connect the NodeMCU to the PC using a usb cable and
launch the Arduino IDE. Firstly you will need to install Adafruit IO, Adafruit
MQTT, and ArduinoHttpClient libraries using the Arduino Library Manager to
communicate with MQTT broker. To do this navigate to “Sketch”, “Include Library”, “Manage Libraries”. Enter “Adafruit IO
Arduino” into the search box, and click “Install” on the Adafruit IO Arduino
library option, ensuring that the latest version is ticked in the version drop
down menu.
Enter “Adafruit MQTT” into the search box, and click
“Install”on the Adafruit MQTT library option, remembering to select the latest
version. Finally, enter “Arduino Http Client” into the search box, and click
“Install” on the ArduinoHttpClient library option, again ensuring that the
latest version was selected.
The Arduino IDE is now set up so it’s time to test it
out.
Open the example of Adafruit mqtt io dashboard. To
open it navigate to “File”, “Examples”, “Adafruit MQTT Library”, “mqtt_esp8266”
Attach the centre pin of a 10kohm potentiometer to pin
A0 (ADC0) of the Node MCU and the outer pins one to GND, the other to 3V. Connect an LED to pin
D6 (GPIO12) via a 33ohm resisitor and the short leg (GND )to GND.
You need to create an accound on the
This sketch will need to be edited so that the wifi
and Adafruit IO credentials have the correct information. .
#define WLAN_SSID
"...your SSID..."
#define WLAN_PASS
"...your password..."
#define AIO_SERVER
"io.adafruit.com"
#define AIO_SERVERPORT
1883 // use 8883 for SSL
#define AIO_USERNAME
"...your AIO username (see https://accounts.adafruit.com)..."
#define AIO_KEY
"...your AIO key..."
Here is the full code.
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#define WLAN_SSID
"xxxxxxx"
#define WLAN_PASS
"xxxxxx"
#define AIO_SERVER
"io.adafruit.com"
#define AIO_SERVERPORT
1883 // use 8883
for SSL
#define AIO_USERNAME
"xxxxxx"
#define AIO_KEY
"xxxxxx"
// Create an ESP8266 WiFiClient class to connect to
the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;
// Setup the MQTT client class by passing in the WiFi
client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER,
AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
// Setup a feed called 'potValue' for publishing.
// Notice MQTT paths for AIO follow the form:
<username>/feeds/<feedname>
Adafruit_MQTT_Publish potValue = Adafruit_MQTT_Publish(&mqtt,
AIO_USERNAME "/feeds/potValue");
// Setup a feed called 'ledBrightness' for subscribing
to changes.
Adafruit_MQTT_Subscribe ledBrightness =
Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME
"/feeds/ledBrightness");
void MQTT_connect();
uint8_t ledPin = 12; //D6, GPIO12
uint16_t potAdcValue = 0;
uint16_t ledBrightValue = 0;
void setup() {
Serial.begin(9600);
delay(10);
Serial.println(F("Adafruit MQTT demo"));
// Connect to
WiFi access point.
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
WiFi.begin(WLAN_SSID, WLAN_PASS);
while
(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
// Setup MQTT
subscription for ledBrightness feed.
mqtt.subscribe(&ledBrightness);
}
void loop() {
// Ensure the
connection to the MQTT server is alive (this will make the first
// connection
and automatically reconnect when disconnected).
See the MQTT_connect
MQTT_connect();
Adafruit_MQTT_Subscribe *subscription;
while
((subscription = mqtt.readSubscription(200))) {
if
(subscription == &ledBrightness) {
Serial.print(F("Got LED Brightness : "));
ledBrightValue = atoi((char *)ledBrightness.lastread);
Serial.println(ledBrightValue);
analogWrite(ledPin, ledBrightValue);
}
}
// Now we can
publish stuff!
uint16_t
AdcValue = analogRead(A0);
if((AdcValue
> (potAdcValue + 7)) || (AdcValue < (potAdcValue - 7))){
potAdcValue
= AdcValue;
Serial.print(F("Sending pot val "));
Serial.print(potAdcValue);
Serial.print("...");
if (!
potValue.publish(potAdcValue)) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
delay(5000);
}
// ping the
server to keep the mqtt connection alive
// NOT
required if you are publishing once every KEEPALIVE seconds
/*
if(!
mqtt.ping()) {
mqtt.disconnect();
}
*/
}
// Function to connect and reconnect as necessary to
the MQTT server.
// Should be called in the loop function and it will
take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if
already connected.
if
(mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t
retries = 3;
while ((ret =
mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if
(retries == 0) {
//
basically die and wait for WDT to reset me
while
(1);
}
}
Serial.println("MQTT
Connected!");
}
One the code is uploaded, log on to your Adafruit IO
account and create a dashboard for viewing your data. The example below shows a
feed of the potentiometer reading which is updated every five seconds (5000ms)
and a representative line graph of the data. There are other blocks that can be
used.
No comments:
Post a Comment