NodeMCU ESP8266
Programming the NodeMCU ESP8266 Board
Updated: 14 March 2024
Some notes on running code on the NodeMCU ESP8266
Basic Setup
To run the ESP8266 code you will need to use the Arduino CLI or Arduino IDE
You can compile the arduino code using the Arduino CLI
Next, you can work on this application using the Arduino IDE or the Arduino VSCode Extension. Using the VSCode extension you will need to run the Arduino: Initialize
command to configure the IDE to be aware of the relevant libraries - For the board I am using I will select NodeMCU 1.0 (ESP-12E Module)
thereafter select the Serial Port
that your device is connected on via USB as well as selecting the sketch with the Arduino: Select Sketch
command
To compile the code that will run on the device you can use the following commands:
1# Install the board2arduino-cli core install esp8266:esp8266 --config-file ./.cli-config.yml3
4# Compile the app5arduino-cli compile --fqbn esp8266:esp8266:nodemcuv2 ./sketches/blink6
7# Upload the app to the board8
9arduino-cli compile --fqbn esp8266:esp8266:nodemcuv2 --port COM3 --upload ./sketches/blink10
11# Upload the app to the board (does not compile)12arduino-cli upload --fqbn esp8266:esp8266:nodemcuv2 --port COM3 ./sketches/blink13
14# Start Serial Monitor15arduino-cli monitor -p --fqbn esp8266:esp8266:nodemcuv2 --port COM3 -c baudrate=115200
The above commands provide a basic outline for running your board and the relevant tasks associated. You will only need to run the installation once, and the compiliation is not needed if using arduino-cli upload
as it will upload the files as well
Note you can also do all of the above using the Arduino VSCode Extension
Install The Board
Before you can do anything else, you will need to install the board
First, define a config file for the Arduino CLI called .cli-config.yml
with the following in it:
1board_manager:2 additional_urls:3 - http://arduino.esp8266.com/stable/package_esp8266com_index.json
Then, install the board using this config:
1arduino-cli core install esp8266:esp8266 --config-file ./.cli-config.yml
Using the Serial Monitor
Note that you will have to set the Baud rate when connecting to a device using the serial monitor in order to view the output
You can connect the Serial Monitor to the device as follows:
1arduino-cli monitor -p --fqbn esp8266:esp8266:nodemcuv2 --port COM3 -c baudrate=115200
Note that the
baudrate
needs to be the same as what is configured during the devicesetup
function usingSerial.begin
Connecting the serial monitor like this should also cause the device to restart so you should be able to get the from the start. Note that you will have to kill this process if you want to upload any code to the device again
To use the Arduino Extension’s Serial Monitor you can simply connect to the device. In the event you want to capture output from the moment the device turns on you can press the RST
button on the device while the Serial Monitor is connected which wil allow you to connect as soon as the device starts up. This is necessary since when the device is being flashed the serial monitor must be disconnected
Examples
Note that when switching sketches you will need to use the VSCode Extension’s
Arduino: Select Sketch
and thereafter theArduino: Initialize
andArduino: Rebuild Intellisense Configuration
command to configure VSCode to register the installed libraries
For the sake of example, I will have all my sketches contained in a sketches
directory with a directory for each sketch (as is required by Arduino)
Blink
This is effectively the standard getting started hardware programming task - blinking the light on the board. For this example create the sketches/beep/beep.ino
file:
1// Based on example from: https://www.arduino.cc/en/Tutorial/BuiltInExamples/Blink2
3void setup()4{5 Serial.begin(115200);6
7 Serial.println("STARTING BLINK");8 pinMode(LED_BUILTIN, OUTPUT);9}10
11void loop()12{13 digitalWrite(LED_BUILTIN, HIGH);14 delay(1000);15 digitalWrite(LED_BUILTIN, LOW);16 delay(1000);17}
Provided you have the board connected via USB, you can then run it as follows:
1arduino-cli compile --upload --fqbn esp8266:esp8266:nodemcuv2 --port COM3 ./sketches/blink
This is also a good opportunity to connect the Serial monitor to view some output from the device using the previous command
Beep
For this example we will play a short sound on the device when the setup hook runs using the builtin tone
function. Add the following content to a file with the path esp-8266/sketches/beep/beep.ino
:
1// Note frequencies from https://learn.adafruit.com/circuit-playground-o-phonor/musical-note-basics2//3// octave = 1 2 3 4 5 6 7 84// NOTES = { "C" : (33, 65, 131, 262, 523, 1047, 2093, 4186),5// "D" : (37, 73, 147, 294, 587, 1175, 2349, 4699),6// "E" : (41, 82, 165, 330, 659, 1319, 2637, 5274),7// "F" : (44, 87, 175, 349, 698, 1397, 2794, 5588),8// "G" : (49, 98, 196, 392, 785, 1568, 3136, 6272),9// "A" : (55, 110, 220, 440, 880, 1760, 3520, 7040),10// "B" : (62, 123, 247, 494, 988, 1976, 3951, 7902)}11
12// Speaker connected to the D5 Pin and Ground13const int PIN_SPEAKER = D5;14
15void setup()16{17 Serial.begin(115200);18
19 Serial.println("STARTING BEEP");20
21 pinMode(PIN_SPEAKER, OUTPUT);22
23 playSound();24}25
26const int FREQ_HIGH = 880;27const int FREQ_LOW = 65;28
29void playSound()30{31 int duration = 500;32
33 tone(PIN_SPEAKER, FREQ_HIGH, duration);34 delay(duration);35 tone(PIN_SPEAKER, FREQ_LOW, duration);36 delay(duration * 2);37}38
39void loop() {}
This can then be uploaded and run on the device using:
1arduino-cli compile --upload --fqbn esp8266:esp8266:nodemcuv2 --port COM3 ./sketches/beep
WebServer
For this example we will create a small application that responds to HTTP requests and can be accessed from other devices on the same network:
First, define the WiFi connection details by adding a config.h
in the project directory with the following:
1#define STASSID "WIFI SSID"2#define STAPSK "WIFI_PASSWORD"
Then, the code for the Web Server will look like so:
1// Based on the ESP8266WebServer example2#include <ESP8266WiFi.h>3#include <WiFiClient.h>4#include <ESP8266WebServer.h>5#include <ESP8266mDNS.h>6#include "config.h"7
8const char *ssid = STASSID;9const char *password = STAPSK;10
11ESP8266WebServer server(80);12
13void handleRoot()14{15 digitalWrite(LED_BUILTIN, HIGH);16 server.send(200, "text/plain", "hello from esp8266!\r\n");17 digitalWrite(LED_BUILTIN, LOW);18}19
20void handleNotFound()21{22 digitalWrite(LED_BUILTIN, HIGH);23 String message = "File Not Found\n\n";24 message += "URI: ";25 message += server.uri();26 message += "\nMethod: ";27 message += (server.method() == HTTP_GET) ? "GET" : "POST";28 message += "\nArguments: ";29 message += server.args();30 message += "\n";31 for (uint8_t i = 0; i < server.args(); i++)32 {33 message += " " + server.argName(i) + ": " + server.arg(i) + "\n";34 }35 server.send(404, "text/plain", message);36 digitalWrite(LED_BUILTIN, LOW);37}38
39void setup(void)40{41 Serial.begin(115200);42
43 pinMode(LED_BUILTIN, OUTPUT);44
45 digitalWrite(LED_BUILTIN, HIGH);46 delay(1000);47 digitalWrite(LED_BUILTIN, LOW);48
49 WiFi.mode(WIFI_STA);50 WiFi.begin(ssid, password);51 Serial.println("");52
53 Serial.print("Connecting to WIFI");54 while (WiFi.status() != WL_CONNECTED)55 {56 // Wait for connection57 delay(500);58 Serial.print(".");59
60 if (WiFi.status() == WL_WRONG_PASSWORD)61 {62 Serial.print("INCORRECT WIFI PASSWORD");63 return;64 }65 }66 Serial.println("");67
68 Serial.print("Connected to ");69 Serial.println(ssid);70 Serial.print("IP address: ");71 Serial.println(WiFi.localIP());72
73 if (MDNS.begin("esp8266"))74 {75 Serial.println("MDNS responder started");76 }77
78 server.on("/", handleRoot);79
80 server.onNotFound(handleNotFound);81
82 server.begin();83 Serial.println("HTTP server started");84}85
86void loop()87{88 server.handleClient();89 MDNS.update();90}
You can then upload and run it on the device using:
And thereafter you can connect the serial monitor as normal. This is necessary since we want to view the IP adress of the
WebSocket
For this example we will create a small application that connects to a WebSocket server and prints out the received messages:
Before running the following, you will need to install the ArduinoWebSockets
library using the Arduino CLI
1arduino-cli lib install ArduinoWebsockets
Next, define the config by adding a config.h
in the project directory with the following:
1#define STASSID "WIFI SSID"2#define STAPSK "WIFI_PASSWORD"3
4// This server will send an inital message and will thereafter echo any message sent to it5#define WSSERVER "wss://echo.websocket.org"
And the code for the application can be seen below:
1// Example from the ArduinoWebsockets docs: https://github.com/gilmaimon/ArduinoWebsockets2#include <ArduinoWebsockets.h>3#include <ESP8266WiFi.h>4#include "config.h"5
6using namespace websockets;7
8const char *ssid = STASSID;9const char *password = STAPSK;10const char *websockets_server = WSSERVER;11
12void onMessageCallback(WebsocketsMessage message)13{14 Serial.println("Received Websocket Message: ");15 Serial.println(message.data());16}17
18void onEventsCallback(WebsocketsEvent event, String data)19{20
21 Serial.println("Received Event");22 Serial.println(data);23
24 switch (event)25 {26 case WebsocketsEvent::ConnectionOpened:27 Serial.println("Connnection Opened");28 break;29
30 case WebsocketsEvent::ConnectionClosed:31 Serial.println("Connnection Closed");32 break;33 }34}35
36WebsocketsClient client;37void setup()38{39 Serial.begin(115200);40 WiFi.begin(ssid, password);41
42 Serial.print("Connecting to WIFI");43 while (WiFi.status() != WL_CONNECTED)44 {45 // Wait for connection46 delay(500);47 Serial.print(".");48
49 if (WiFi.status() == WL_WRONG_PASSWORD)50 {51 Serial.print("INCORRECT WIFI PASSWORD");52 return;53 }54 }55 Serial.println("");56
57 Serial.print("Connected to ");58 Serial.println(ssid);59 Serial.print("IP address: ");60 Serial.println(WiFi.localIP());61
62 // Setup Callbacks63 client.onMessage(onMessageCallback);64 client.onEvent(onEventsCallback);65
66 client.connect(websockets_server);67}68
69void loop()70{71 client.poll();72}
Then, you can run the following command to upload and run the code on the device
1arduino-cli compile --upload --fqbn esp8266:esp8266:nodemcuv2 --port COM3 ./sketches/websocket
And thereafter you can connect the serial monitor as normal to view any logs from the websocket response
Screen
This one was a bit more complicated since it required a little more info, the following youtube videos were really handy in explaining the hardware setup process in more detail:
Connecting the Screen
For the connection Information I used the Tutorial on I2C OLED Display with Arduino/NodeMCU video. The connection information for the screen I have is as follows:
Screen Pin | NodeMCU Pin |
---|---|
VCC | 3V |
GND | GND |
SCL | D1 |
SDA | D2 |
Libraries
We also need a few libraries which we can install with:
1arduino-cli lib install "i2cdetect"2arduino-cli lib install "Adafruit GFX Library"3arduino-cli lib install "Adafruit BusIO"4arduino-cli lib install "Adafruit SSD1306"
For running the display there are two things we need to do
Get the Screen Address
Firstly, we need to figure out the screen address, this can be done by using the i2cdetect
library using their example as-is. This is just needed the first time we use the screen:
1// Example from the i2detect library2#include <Wire.h>3#include <i2cdetect.h>4
5void setup()6{7 Wire.begin();8 Serial.begin(115200);9 Serial.println("i2cdetect example\n");10 Serial.print("Scanning address range 0x03-0x77\n\n");11}12
13void loop()14{15 i2cdetect(); // default range from 0x03 to 0x7716 delay(2000);17}
You can run this with:
1arduino-cli compile --upload --fqbn esp8266:esp8266:nodemcuv2 --port COM3 ./sketches/i2c-detect
Then, we need to connect the Serial Monitor and view the output. In the output we should see a value that is active, in my case C3
:
1 0 1 2 3 4 5 6 7 8 9 a b c d e f200: -- -- -- -- -- -- -- -- -- -- -- -- --310: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --420: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --530: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --640: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --750: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --860: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --970: -- -- -- -- -- -- -- --
This is the value we will use for the Screen Address in the next setup
Write Some Stuff
To write stuff to the screen we can use the Adafruit sample from the library as a base, I’ve simplified it to just print a message on the screen to demonstrate the basic usage:
1// Based on Example for AdaFruit Monochrome OLEDs based on SSD1306 drivers2
3#include <SPI.h>4#include <Wire.h>5#include <Adafruit_GFX.h>6#include <Adafruit_SSD1306.h>7
8#define SCREEN_WIDTH 128 // OLED display width, in pixels9#define SCREEN_HEIGHT 64 // OLED display height, in pixels10
11#define OLED_RESET -112#define SCREEN_ADDRESS 0x3C // This value depends on the screen, running the i2x-detect script will give you the correct one for your screen13
14Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);15
16void displayText(void)17{18 display.clearDisplay();19
20 display.setTextSize(3);21 display.setTextColor(SSD1306_WHITE);22 display.setCursor(10, 0);23 display.println(F("Hello"));24 display.println(F("WORLD!!"));25 display.display();26}27
28void setup()29{30 Serial.begin(9600);31
32 if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS))33 {34 Serial.println(F("SSD1306 allocation failed"));35 for (;;)36 ; // Don't proceed, loop forever37 }38}39
40void loop()41{42 displayText();43}
And this can be run using:
1arduino-cli compile --upload --fqbn esp8266:esp8266:nodemcuv2 --port COM3 ./sketches/screen