NodeMcu Lua ESP8266

 

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 delays to achieve different effects.

 


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. Connect one pin of the potentiometer to 3V and the other pin to GND. Upload the following sketch using the Arduino IDE.

 

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 Worldon 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.

 

Connect the CLK pin of the TM1637 to digital pin D6 of the Node MCU and the DIO pin of the TM1647 to digital pin D5 of the Node MCU. Connect GND and VCC of the TM1637 to GND and VCC, respectively.

 

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() {}


 Motors

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 LED ON

 

    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

 

Connect the pin to pin D3 (GPIO0) of the Node MCU. Connect GND to GND and VCC to 3V. Upload the following sketch.

.

/*

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.

Connect an LED to to D3 (GPIO0) of the Node MCU (not forgetting to ground the other leg). This will act as a visual indicator when sound is detetected. Upload the following sketch.

 

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

Connect the DO (Digital Out) pin of the module to pin D3 (GPIO0) of the Node MCU. Connect GND to GND and VCC to 3V). Upload the following sketch.

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 flame in front of the detector .

 

 

You will see that the output changes as the flame is detected. As the detector is programmed to record and display the result every 200ms, it is difficult to see trends in results. Using the Serial Plotter makes this easier.

 

 

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

ADO:                                  GND

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 delay time after ther serial print commands  (delay(100);) from 100ms to 1000ms (one second) to make the output easier to read.

 

 

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

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("Initializing SD card...");

 

  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("Initializing SD card...");

 

  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 Crystal 32.768KHz, matching capacitance 6pF, size 2 * 6mm

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("Reading data.");

  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” textbox type in your MQTT host (broker) address or type in “broker.mqtt-dashboard.com” if using the default setting as used in this example. Leave all other settings as default. Click “Save”. A new page will open which will show “Topic to publish” on the left hand side and”outTopic” on the right hand side. Click the Subscribe button to subscribe to the topic. This enables continuous  subscription to this topic and messages that will be published by this NodeMCU. You will see data being received:

 

 

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 Adafruit IO. The data stream can be viewed at io.adafruit.com by adding a stream block to your dashboard.

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 Adafruit IO website.

 

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” textbox type in your MQTT host (broker) address or type in “broker.mqtt-dashboard.com” if using the default setting as used in this example. Leave all other settings as default. Click “Save”. A new page will open which will show “Topic to publish” on the left hand side and”outTopic” on the right hand side. Click the Subscribe button to subscribe to the topic. This enables continuous  subscription to this topic and messages that will be published by this NodeMCU. You will see data being received:

 

 

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 Adafruit IO. The data stream can be viewed at io.adafruit.com by adding a stream block to your dashboard.

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 Adafruit IO website.

 

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