ESP-MESH with ESP32 and ESP8266: Getting Started (painlessMesh library)

Learn how to use ESP-MESH networking protocol to build a mesh network with the ESP32 and ESP8266 NodeMCU boards. ESP-MESH allows multiple devices (nodes) to communicate with each other under a single wireless local area network. It is supported on the ESP32 and ESP8266 boards. In this guide, we’ll show you how to get started with ESP-MESH using the Arduino core.

ESP-MESH with ESP32 and ESP8266: Getting Started

This article covers the following topics:

Arduino IDE

If you want to program the ESP32 and ESP8266 boards using Arduino IDE, you should have the ESP32 or ESP8266 add-ons installed. Follow the next guides:

If you want to program the ESP32/ESP8266 using VS Code + PlatformIO, follow the next tutorial:

Introducing ESP-MESH

Accordingly to the Espressif documentation:

“ESP-MESH is a networking protocol built atop the Wi-Fi protocol. ESP-MESH allows numerous devices (referred to as nodes) spread over a large physical area (both indoors and outdoors) to be interconnected under a single WLAN (Wireless Local-Area Network).

ESP-MESH is self-organizing and self-healing meaning the network can be built and maintained autonomously.” For more information, visit the ESP-MESH official documentation.

Traditional Wi-Fi Network Architecture

In a traditional Wi-Fi network architecture, a single node (access point – usually the router) is connected to all other nodes (stations). Each node can communicate with each other using the access point. However, this is limited to the access point wi-fi coverage. Every station must be in the range to connect directly to the access point. This doesn’t happen with ESP-MESH.

Traditional Wi-Fi Network ESP32 ESP8266

ESP-MESH Network Architecture

With ESP-MESH, the nodes don’t need to connect to a central node. Nodes are responsible for relaying each others transmissions. This allows multiple devices to spread over a large physical area. The Nodes can self-organize and dynamically talk to each other to ensure that the packet reaches its final node destination. If any node is removed from the network, it is able to self-organize to make sure that the packets reach their destination.

ESP-MESH Network ESP32 ESP8266i

painlessMesh Library

The painlessMesh library allows us to create a mesh network with the ESP8266 or/and ESP32 boards in an easy way.

“painlessMesh is a true ad-hoc network, meaning that no-planning, central controller, or router is required. Any system of 1 or more nodes will self-organize into fully functional mesh. The maximum size of the mesh is limited (we think) by the amount of memory in the heap that can be allocated to the sub-connections buffer and so should be really quite high.” More information about the painlessMesh library.

Installing painlessMesh Library

You can install painlessMesh through the Arduino Library manager. Go to Tools > Manage Libraries. The Library Manager should open.

Search for “painlessmesh” and install the library. We’re using Version 1.4.5

Install painlessMesh library Arduino IDE

This library needs some other library dependencies. A new window should pop up asking you to install any missing dependencies. Select “Install all”.

Install painlessmesh library dependencies Arduino IDE

If this window doesn’t show up, you’ll need to install the following library dependencies:

If you’re using PlatformIO, add the following lines to the platformio.ini file to add the libraries and change the monitor speed.

For the ESP32:

monitor_speed = 115200
lib_deps = painlessmesh/painlessMesh @ ^1.4.5
    ArduinoJson
    arduinoUnity
    TaskScheduler
    AsyncTCP

For the ESP8266:

monitor_speed = 115200
lib_deps = painlessmesh/painlessMesh @ ^1.4.5
    ArduinoJson
    TaskScheduler
    ESPAsyncTCP

ESP-MESH Basic Example (Broadcast messages)

To get started with ESP-MESH, we’ll first experiment with the library’s basic example. This example creates a mesh network in which all boards broadcast messages to all the other boards.

We’ve experimented this example with four boards (two ESP32 and two ESP8266). You can add or remove boards. The code is compatible with both the ESP32 and ESP8266 boards.

ESP-MESH painlessMesh basic example ESP32 ESP8266

Code – painlessMesh Library Basic Example

Copy the following code to your Arduino IDE (code from the library examples). The code is compatible with both the ESP32 and ESP8266 boards.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp-mesh-esp32-esp8266-painlessmesh/
  
  This is a simple example that uses the painlessMesh library: https://github.com/gmag11/painlessMesh/blob/master/examples/basic/basic.ino
*/

#include "painlessMesh.h"

#define   MESH_PREFIX     "whateverYouLike"
#define   MESH_PASSWORD   "somethingSneaky"
#define   MESH_PORT       5555

Scheduler userScheduler; // to control your personal task
painlessMesh  mesh;

// User stub
void sendMessage() ; // Prototype so PlatformIO doesn't complain

Task taskSendMessage( TASK_SECOND * 1 , TASK_FOREVER, &sendMessage );

void sendMessage() {
  String msg = "Hi from node1";
  msg += mesh.getNodeId();
  mesh.sendBroadcast( msg );
  taskSendMessage.setInterval( random( TASK_SECOND * 1, TASK_SECOND * 5 ));
}

// Needed for painless library
void receivedCallback( uint32_t from, String &msg ) {
  Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
}

void newConnectionCallback(uint32_t nodeId) {
    Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
}

void nodeTimeAdjustedCallback(int32_t offset) {
    Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

void setup() {
  Serial.begin(115200);

//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
  mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages

  mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT );
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

  userScheduler.addTask( taskSendMessage );
  taskSendMessage.enable();
}

void loop() {
  // it will run the user scheduler as well
  mesh.update();
}

View raw code

Before uploading the code, you can set up the MESH_PREFIX (it’s like the name of the MESH network) and the MESH_PASSWORD variables (you can set it to whatever you like).

Then, we recommend that you change the following line for each board to easily identify the node that sent the message. For example, for node 1, change the message as follows:

String msg = "Hi from node 1 ";

How the Code Works

Start by including the painlessMesh library.

#include "painlessMesh.h"

MESH Details

Then, add the mesh details. The MESH_PREFIX refers to the name of the mesh. You can change it to whatever you like.

#define MESH_PREFIX "whateverYouLike"

The MESH_PASSWORD, as the name suggests is the mesh password. You can change it to whatever you like.

#define MESH_PASSWORD "somethingSneaky"

All nodes in the mesh should use the same MESH_PREFIX and MESH_PASSWORD.

The MESH_PORT refers to the the TCP port that you want the mesh server to run on. The default is 5555.

#define MESH_PORT 5555

Scheduler

It is recommended to avoid using delay() in the mesh network code. To maintain the mesh, some tasks need to be performed in the background. Using delay() will stop these tasks from happening and can cause the mesh to lose stability/fall apart.

Instead, it is recommended to use TaskScheduler to run your tasks which is used in painlessMesh itself.

The following line creates a new Scheduler called userScheduler.

Scheduler userScheduler; // to control your personal task

painlessMesh

Create a painlessMesh object called mesh to handle the mesh network.

Create tasks

Create a task called taskSendMessage responsible for calling the sendMessage() function every second as long as the program is running.

Task taskSendMessage(TASK_SECOND * 1 , TASK_FOREVER, &sendMessage);

Send a Message to the Mesh

The sendMessage() function sends a message to all nodes in the message network (broadcast).

void sendMessage() {
  String msg = "Hi from node 1";
  msg += mesh.getNodeId();
  mesh.sendBroadcast( msg );
  taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));
}

The message contains the “Hi from node 1” text followed by the board chip ID.

String msg = "Hi from node 1";
msg += mesh.getNodeId();

To broadcast a message, simply use the sendBroadcast() method on the mesh object and pass as argument the message (msg) you want to send.

mesh.sendBroadcast(msg);

Every time a new message is sent, the code changes the interval between messages (one to five seconds).

taskSendMessage.setInterval(random(TASK_SECOND * 1, TASK_SECOND * 5));

Mesh Callback Functions

Next, several callback functions are created that will be called when specific events happen on the mesh.

The receivedCallback() function prints the message sender (from) and the content of the message (msg.c_str()).

void receivedCallback( uint32_t from, String &msg ) {
  Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());
}

The newConnectionCallback() function runs whenever a new node joins the network. This function simply prints the chip ID of the new node. You can modify the function to do any other task.

void newConnectionCallback(uint32_t nodeId) {
  Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}

The changedConnectionCallback() function runs whenever a connection changes on the network (when a node joins or leaves the network).

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
}

The nodeTimeAdjustedCallback() function runs when the network adjusts the time, so that all nodes are synchronized. It prints the offset.

void nodeTimeAdjustedCallback(int32_t offset) {
  Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

setup()

In the setup(), initialize the serial monitor.

void setup() {
  Serial.begin(115200);

Choose the desired debug message types:

//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on

mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages

Initialize the mesh with the details defined earlier.

mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);

Assign all the callback functions to their corresponding events.

mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

Finally, add the taskSendMessage function to the userScheduler. The scheduler is responsible for handling and running the tasks at the right time.

userScheduler.addTask(taskSendMessage);

Finally, enable the taskSendMessage, so that the program starts sending the messages to the mesh.

taskSendMessage.enable();

To keep the mesh running, add mesh.update() to the loop().

void loop() {
  // it will run the user scheduler as well
  mesh.update();
}

Demonstration

Upload the code provided to all your boards. Don’t forget to modify the message to easily identify the sender node

With the boards connected to your computer, open a serial connection with each board. You can use the Serial Monitor, or you can use a software like PuTTY and open multiple windows for all the boards.

You should see that all boards receive each others messages. For example, these are the messages received by Node 1. It receives the messages from Node 2, 3 and 4.

ESP-MESH Basic Example 4 Boards Arduino Serial Monitor

You should also see other messages when there are changes on the mesh: when a board leaves or joins the network.

ESP MESH Basic Example Serial Monitor Changed Connections

Exchange Sensor Readings using ESP-MESH

In this next example, we’ll exchange sensor readings between 4 boards (you can use a different number of boards). Every board receives the other boards’ readings.

ESP-MESH Exchange BME280 Sensor Readings ESP32 ESP8266

As an example, we’ll exchange sensor readings from a BME280 sensor, but you can use any other sensor.

Parts Required

Here’s the parts required for this example:

Arduino_JSON library

In this example, we’ll exchange the sensor readings in JSON format. To make it easier to handle JSON variables, we’ll use the Arduino_JSON library.

You can install this library in the Arduino IDE Library Manager. Just go to Sketch Include Library > Manage Libraries and search for the library name as follows:

Install Arduino JSON library Arduino IDE

If you’re using VS Code with PlatformIO, include the libraries in the platformio.ini file as follows:

ESP32

monitor_speed = 115200
lib_deps = painlessmesh/painlessMesh @ ^1.4.5
    ArduinoJson
    arduinoUnity
    AsyncTCP
    TaskScheduler
    adafruit/Adafruit Unified Sensor @ ^1.1.4
    adafruit/Adafruit BME280 Library @ ^2.1.2
    arduino-libraries/Arduino_JSON @ ^0.1.0

ESP8266

monitor_speed = 115200
lib_deps = painlessmesh/painlessMesh @ ^1.4.5
    ArduinoJson
    TaskScheduler
    ESPAsyncTCP
    adafruit/Adafruit Unified Sensor @ ^1.1.4
    adafruit/Adafruit BME280 Library @ ^2.1.2
    arduino-libraries/Arduino_JSON @ ^0.1.0

Circuit Diagram

Wire the BME280 sensor to the ESP32 or ESP8266 default I2C pins as shown in the following schematic diagrams.

ESP32

ESP32 BME280 Sensor Temperature Humidity Pressure Wiring Diagram Circuit

Recommended reading: ESP32 with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity)

ESP8266 NodeMCU

ESP8266 NodeMCU BME280 Sensor Temperature Humidity Pressure Wiring Diagram Circuit

Recommended reading: ESP8266 with BME280 using Arduino IDE (Pressure, Temperature, Humidity)

Code – ESP-MESH Broadcast Sensor Readings

Upload the following code to each of your boards. This code reads and broadcasts the current temperature, humidity and pressure readings to all boards on the mesh network. The readings are sent as a JSON string that also contains the node number to identify the sender board.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp-mesh-esp32-esp8266-painlessmesh/
  
  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 <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include "painlessMesh.h"
#include <Arduino_JSON.h>

// MESH Details
#define   MESH_PREFIX     "RNTMESH" //name for your MESH
#define   MESH_PASSWORD   "MESHpassword" //password for your MESH
#define   MESH_PORT       5555 //default port

//BME object on the default I2C pins
Adafruit_BME280 bme;

//Number for this node
int nodeNumber = 2;

//String to send to other nodes with sensor readings
String readings;

Scheduler userScheduler; // to control your personal task
painlessMesh  mesh;

// User stub
void sendMessage() ; // Prototype so PlatformIO doesn't complain
String getReadings(); // Prototype for sending sensor readings

//Create tasks: to send messages and get readings;
Task taskSendMessage(TASK_SECOND * 5 , TASK_FOREVER, &sendMessage);

String getReadings () {
  JSONVar jsonReadings;
  jsonReadings["node"] = nodeNumber;
  jsonReadings["temp"] = bme.readTemperature();
  jsonReadings["hum"] = bme.readHumidity();
  jsonReadings["pres"] = bme.readPressure()/100.0F;
  readings = JSON.stringify(jsonReadings);
  return readings;
}

void sendMessage () {
  String msg = getReadings();
  mesh.sendBroadcast(msg);
}

//Init BME280
void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }  
}

// Needed for painless library
void receivedCallback( uint32_t from, String &msg ) {
  Serial.printf("Received from %u msg=%s\n", from, msg.c_str());
  JSONVar myObject = JSON.parse(msg.c_str());
  int node = myObject["node"];
  double temp = myObject["temp"];
  double hum = myObject["hum"];
  double pres = myObject["pres"];
  Serial.print("Node: ");
  Serial.println(node);
  Serial.print("Temperature: ");
  Serial.print(temp);
  Serial.println(" C");
  Serial.print("Humidity: ");
  Serial.print(hum);
  Serial.println(" %");
  Serial.print("Pressure: ");
  Serial.print(pres);
  Serial.println(" hpa");
}

void newConnectionCallback(uint32_t nodeId) {
  Serial.printf("New Connection, nodeId = %u\n", nodeId);
}

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
}

void nodeTimeAdjustedCallback(int32_t offset) {
  Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

void setup() {
  Serial.begin(115200);
  
  initBME();

  //mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on
  mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages

  mesh.init( MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT );
  mesh.onReceive(&receivedCallback);
  mesh.onNewConnection(&newConnectionCallback);
  mesh.onChangedConnections(&changedConnectionCallback);
  mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

  userScheduler.addTask(taskSendMessage);
  taskSendMessage.enable();
}

void loop() {
  // it will run the user scheduler as well
  mesh.update();
}

View raw code

The code is compatible with both the ESP32 and ESP8266 boards.

How the Code Works

Continue reading this section to learn how the code works.

Libraries

Start by including the required libraries: the Adafruit_Sensor and Adafruit_BME280 to interface with the BME280 sensor; the painlessMesh library to handle the mesh network and the Arduino_JSON to create and handle JSON strings easily.

#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include "painlessMesh.h"
#include <Arduino_JSON.h>

Mesh details

Insert the mesh details in the following lines.

#define MESH_PREFIX    "RNTMESH" //name for your MESH
#define MESH_PASSWORD  "MESHpassword" //password for your MESH
#define MESH_PORT      5555 //default port

The MESH_PREFIX refers to the name of the mesh. You can change it to whatever you like. The MESH_PASSWORD, as the name suggests is the mesh password. You can change it to whatever you like. All nodes in the mesh should use the same MESH_PREFIX and MESH_PASSWORD.

The MESH_PORT refers to the the TCP port that you want the mesh server to run on. The default is 5555.

BME280

Create an Adafruit_BME280 object called bme on the default ESP32 or ESP8266 pins.

Adafruit_BME280 bme;

In the nodeNumber variable insert the node number for your board. It must be a different number for each board.

int nodeNumber = 2;

The readings variable will be used to save the readings to be sent to the other boards.

String readings;

Scheduler

The following line creates a new Scheduler called userScheduler.

Scheduler userScheduler; // to control your personal task

painlessMesh

Create a painlessMesh object called mesh to handle the mesh network.

Create tasks

Create a task called taskSendMessage responsible for calling the sendMessage() function every five seconds as long as the program is running.

Task taskSendMessage(TASK_SECOND * 5 , TASK_FOREVER, &sendMessage);

getReadings()

The getReadings() function gets temperature, humidity and pressure readings from the BME280 sensor and concatenates all the information, including the node number on a JSON variable called jsonReadings.

JSONVar jsonReadings;
jsonReadings["node"] = nodeNumber;
jsonReadings["temp"] = bme.readTemperature();
jsonReadings["hum"] = bme.readHumidity();
jsonReadings["pres"] = bme.readPressure()/100.0F;

The following line shows the structure of the jsonReadings variable with arbitrary values.

{
  "node":2,
  "temperature":24.51,
  "humidity":52.01,
  "pressure":1005.21
}

The jsonReadings variable is then converted into a JSON string using the stringify() method and saved on the readings variable.

readings = JSON.stringify(jsonReadings);

This variable is then returned by the function.

return readings;

Send a Message to the Mesh

The sendMessage() function sends the JSON string with the readings and node number (getReadings()) to all nodes in the network (broadcast).

void sendMessage () {
  String msg = getReadings();
  mesh.sendBroadcast(msg);
}

Init BME280 sensor

The initBME() function initializes the BME280 sensor.

void initBME(){
  if (!bme.begin(0x76)) {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

Mesh Callback Functions

Next, several callback functions are created that will be called when some event on the mesh happens.

The receivedCallback() function prints the message sender (from) and the content of the message (msg.c_str()).

void receivedCallback( uint32_t from, String &msg ) {
  Serial.printf("startHere: Received from %u msg=%s\n", from, msg.c_str());

The message comes in JSON format, so, we can access the variables as follows:

JSONVar myObject = JSON.parse(msg.c_str());
int node = myObject["node"];
double temp = myObject["temp"];
double hum = myObject["hum"];
double pres = myObject["pres"];

Finally, print all the information on the Serial Monitor.

Serial.print("Node: ");
Serial.println(node);
Serial.print("Temperature: ");
Serial.print(temp);
Serial.println(" C");
Serial.print("Humidity: ");
Serial.print(hum);
Serial.println(" %");
Serial.print("Pressure: ");
Serial.print(pres);
Serial.println(" hpa");

The newConnectionCallback() function runs whenever a new node joins the network. This function simply prints the chip ID of the new node. You can modify the function to do any other task.

void newConnectionCallback(uint32_t nodeId) {
  Serial.printf("--> startHere: New Connection, nodeId = %u\n", nodeId);
}

The changedConnectionCallback() function runs whenever a connection changes on the network (when a node joins or leaves the network).

void changedConnectionCallback() {
  Serial.printf("Changed connections\n");
}

The nodeTimeAdjustedCallback() function runs when the network adjusts the time, so that all nodes are synchronized. It prints the offset.

void nodeTimeAdjustedCallback(int32_t offset) {
  Serial.printf("Adjusted time %u. Offset = %d\n", mesh.getNodeTime(),offset);
}

setup()

In the setup(), initialize the serial monitor.

void setup() {
  Serial.begin(115200);

Call the initBME() function to initialize the BME280 sensor.

initBME();

Choose the desired debug message types:

//mesh.setDebugMsgTypes( ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE ); // all types on

mesh.setDebugMsgTypes( ERROR | STARTUP );  // set before init() so that you can see startup messages

Initialize the mesh with the details defined earlier.

mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);

Assign all the callback functions to their corresponding events.

mesh.onReceive(&receivedCallback);
mesh.onNewConnection(&newConnectionCallback);
mesh.onChangedConnections(&changedConnectionCallback);
mesh.onNodeTimeAdjusted(&nodeTimeAdjustedCallback);

Finally, add the taskSendMessage function to the userScheduler. The scheduler is responsible for handling and running the tasks at the right time.

userScheduler.addTask(taskSendMessage);

Finally, enable the taskSendMessage, so that the program starts sending the messages to the mesh.

taskSendMessage.enable();

To keep the mesh running, add mesh.update() to the loop().

void loop() {
  // it will run the user scheduler as well
  mesh.update();
}

Demonstration

After uploading the code to all your boards (each board with a different node number), you should see that each board is receiving the other boards’ messages.

The following screenshot shows the messages received by node 1. It receives the sensor readings from node 2, 3 and 4.

ESP-MESH Exchange BME280 Sensor Readings ESP32 ESP8266 Serial Monitor f

Wrapping Up

We hope you liked this quick introduction to the ESP-MESH networking protocol. You can take a look at the painlessMesh library for more examples.

We intend to create more tutorials about this subject on a near future. So, write your suggestions on the comments’ section.

You may also like the following articles:

Learn more about the ESP32 and ESP8266 with our resources:

Thanks for reading.



Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

38 thoughts on “ESP-MESH with ESP32 and ESP8266: Getting Started (painlessMesh library)”

  1. Hi Sara, incredible stuff you can do with these “IoT” devices!

    Just wondering: if you would like to forward the temperature readings (eg with that PHP2MySQL you wrote earlier), would you advice to include that code in each of the nodes in your Mesh (because any of them may or may not be in reach of the actual “working” network with the LAMP server on it – caveat: lots of failed attempt plus if all mesh members succeed, database needs to be instrumented to avoid duplicate uploads), or would you dedicate 1 ESP for “uplink” to the real network?

    Thanks for sharing your thoughts!

    Reply
    • Hi.
      I think it would be better to have one ESP to upload to the database. But it will depend on your project requirements.
      I still need to do some more research on this topic to see how to handle different network topologies and requirements.
      Regards,
      Sara

      Reply
      • Hi Sara,

        thank you for your suggestion!

        I’m wondering if you can “hook up” other devices to this mesh (eg a raspberry pi) – found articles like this: https://github.com/Coopdis/easyMesh/issues/30 so then this pi (which is currently my php/mysql gateway) can simply listen to the mesh 🙂

        But indeed, these are other project requirements than initially drawn, but with this mesh, I can try to link to my water well sensor!

        Thank you and have a nice day!

        Reply
      • Hi Sara,

        I did some further reading on this requirement. Apparently this mesh protocol may not be compatible with the wifi modules and TCPIP stacks, so it’s either mesh or wifi, not both at the same time. So I’m not sure on how one “master” ESP32 could “listen” to the mesh and upload the JSON messages towards the wifi (through router).
        I found an android app which had a working painlessmesh, however it seems to be broken with the 2020 releases. Then I could at least copy paste the values from the mesh network into my webportal from my phone 🙂

        Reply
  2. Very interesting simple mesh. I would also like to know how to get the data out of the mesh and into MQTT running on another computer, such as a R-pi. I would guess that one of the nodes would be dedicated to that function, but I cannot visualize how to prevent duplicate messages….does the painless mesh library handle that?

    Thanks,
    Dave K.

    Reply
  3. So I am thinking about a project to attempt, I have a rather long driveway and would like to build a detector.
    I know I could easily find purchase one but what fun would that be? So my obstacles are :
    Driveway approx 700’
    WiFi distance from router around 750’
    Using WeMos in conjunction with ESP 8266
    I have 2 WeMos and 1 ESP Lolin 8266
    Would this work for me given the obstacles and boards I have ?

    Reply
  4. Great project, could be really useful for me. Would you consider expanding this project to include displaying the readings on a web page running on one of the boards accessible on my home wifi?

    Reply
  5. Can you explain the differences between this painless MESH and ESP-NOW? Are the data passed using ESP-NOW to each node rather than a master-slave scenario? Thanks and please keep up the good work.

    Reply
  6. I have tried painless mesh number of times in the past and recently.
    I don’t know if painless mesh uses any official ESP-MESH protocol feature, but it definitely has many custom features?

    Since you have quoted official ESP-MESH, I think you should confirm how painless mesh is exactly related to official espredsif ESP-MESH!

    I am fairly experienced with ESP devices and have used them successfully for long time, using both WiFi and ESP-NOW protocols. I would also love to use a reliable mesh-networking.

    Painless mesh sounds impressive, but I and some others have found it unreliable after running from few hours to few days, even with very few (less than 6) nodes, tried with both ESP8266 and ESP32 and combination. All nodes are within RF range of each other (within 10-20m).

    It generally starts OK but after some random time nodes start dropping off from the network and take very long time (minutes) or never to reconnect. This is unreliable and unacceptable.

    Please read ‘issues’ on GitLab.
    https://gitlab.com/groups/painlessMesh/-/issues

    I suggest that you set up a reasonable size (more than 6 nodes) painless mesh network for number of days or longer and then report how reliable it is.

    I enjoy your tutorials, have purchased previous courses and use lot of your tutorials as reference.

    Best Regards

    Reply
    • Hi Jack.
      Thanks for sharing your knowledge about this subject.
      We’ve only recently started experimenting with ESP-MESH.
      To get started, we experimented with 4 nodes and everything seemed to work fine. But, we’ve only did simple experiments.
      We’ll experiment different scenarios and see how it goes.
      Did you experiment with any other library that supports mesh networking?
      Thank you so much for sharing your thoughts about this.
      Regards,
      Sara

      Reply
  7. Awesome post!
    The range of the MESH network is really good. I tested here with 3 modules in an area where the router coverage doesn’t work very well and, surprisingly, the ESP-MESH bypassed the fisical problems which blocks my router signal (the router signal usually is weak because there is an elevator in the middle).

    Thank you very much for this great post!

    Reply
      • Yes Manuel,
        My tests used one ESP32 and two ESP8266. The ESP32 and one ESP8266 were reading sensors (DHT11 on the ESP32 and a BMP280 on the ESP8266) and the other ESP8266 was connected to an OLED display, printing the sensor readings sent by the other two devices. Everything working like a charm!

        Regards!

        Reply
  8. Good tutorial and also good comments 🙂
    Thank you, everyone.

    A simple question. Is it possible to automatically number each node? that is, when you insert a new node it recognizes it as “one more” and numbers it.

    Reply
    • Hi Manuel.
      The mesh recognizes the nodes by the board chip ID.
      You might add something to your code that saves the nodes’ chip IDs and numbers the nodes accordingly.
      Regards,
      Sara

      Reply
  9. I have a couple of ESP32 scattered around, all linked via my local router and my home network. Each has a fixed IP. I have them talking directly to each other, no problem.

    I cannot see how this protocol would work if these ESPs cannot directly contact each other – your comments?

    Reply
  10. Hello Sara and Rui.
    How do I only get the message text in the serial monitor?
    Without further information.
    I’m doing something wrong but don’t understand what I’m doing wrong to get this done.
    I only learn very slowly, that’s always my problem.
    Please give me a hint
    Greetings from the old man in the Netherlands.

    Reply
    • Hi Bert,

      the easiest way is to try one of the simple “Hello World” samples included in the Arduino IDE. If you can’t see these “Hello World” print-outs on your serial, you are not up to a project like this one 🙂

      Greetings from Belgium!

      Reply
      • I think I’m misinterpreting it, sorry about that.
        How do I change this rule.
        Serial.printf (“startHere: Received from% u msg =% s \ n”, from, msg.c_str ());
        I only get the text “Hi from node1” in the serial monitor.
        And not any other info.
        Thanks for your understanding.

        Reply
        • Sorry google translate is killing me and me text .
          I meant
          So that I only get the text “Hi from node1” in the serial monitor.
          And not any other info.
          Thanks for your understanding.

          Reply
          • I could also post in Dutch, but then Sara cannot read it 🙂

            Did you upload your code to another ESP device and configure it as node 2? If you only get messages from Node1, you only have 1 node in your mesh.

  11. Hello
    Thanks again, Sara and Rui.
    Do you know if there is any limitations about the number of nodes? can we assume 500 nodes or even 1000?
    Thanks

    Reply
  12. Oops, typo/copy-paste error in:

    void receivedCallback( uint32_t from, String &msg ) {

    double pres = myObject[“pres”];

    Serial.print(“Pressure: “);
    Serial.print(temp);
    Serial.println(” hpa”);

    The temp should be pres. The temp shows up twice in the printout sample above.

    Reply

Leave a Comment

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.