Routing Packets Directly Between ESP8266 Modules
2018-12-30 - By Mike Jarabek, Gagandeep Kaur Gill, Kenosha Filomena Vaz, Shaheena Shaik, Robert Elder
Introduction
This article is a review of a capstone project completed by Gagandeep Gill, Kenosha Vaz, and Shaheena Shaik. The goal of the project was to attempt to bridge a wireless network connection directly between ESP8266 modules without any independent intermediary router hardware. In the end, a minimum viable product was obtained that demonstrates this objective of direct ESP8266 to ESP8266 module communication. This article includes the source code for a minimum viable product that will forward packets between ESP modules, along with detailed information on the supporting install environment and dependencies to reproduce results. The final product did not include the ability to route packets back to a standard desktop PC or laptop (simply due to lack of time), however this should be achievable in a future project using a simple serial connection at the endpoints of the bridge.
High-Level Project Insights and Results
The results from this project include a demo of 6 ESP8266 modules performing bi-directional communication using a setup with pre-assigned 'neighbours'. Complete source code for this demo is provided below. This setup does not involve any traditional routers or IP level routing, but instead demonstrates multi-hop wireless communication using only ESP8266 modules based on MAC addresses.
The positive result obtained in this project stems from substantial technical insights from the project's faculty supervisor, Mike Jarabek. If you decide to try and replicate these results for yourself, you may be interested in several observations made by Mike that would otherwise have made this project more difficult and time consuming:
- The ESP8266 is very sensitive to voltage fluctuations and the original jumper wires that were supplied for the project were too thin which caused the voltage to sag when the current draw increased during CPU intensive operations. Mike estimated that the inadequate wires were probably around AWG 26 or AWG 28. The observable symptom was that everything would work fine until a certain point in the process of flashing the module's firmware where the current draw became high enough to sag the voltage in the thin wires and cause the module to crash, manifesting in an error message to the user. The solution was to user thicker wires of around AWG 22 or thicker.
- One of Mike's most important contributions to this project was figuring out that the 'ESP Now' API is exactly what is needed to achieve the primary objective of this project. Espressif's poor choice of naming for the 'ESP Now' API and the lack of ubiquitous knowledge and documentation of this API makes it very difficult to find through Google even if you have an idea what you want to achieve for this module. There are surprisingly few blogs posts about this topic given how useful this feature is.
- The specific version of the ESP8266 used in this project used a 26MHz oscillator crystal which results in the communication baud rate for early parts of the bootloader being set to 74880 baud instead of the more common 115200 baud. This non-standard baud rate is rejected by some applications such as minicom or cu running on a Linux system (but not FreeBSD) which can make it difficult to debug bootloader issues.
- Another key observation was that many of the third-party community documentation, GitHub repos and blog posts related to the ESP8266 include instructions that neglect the different addresses that are required to correctly flash the firmware on each module. It is therefore imperative to figure out which version of the ESP8266 chip you have, and correctly identify the flash memory size and respective addresses of key firmware files. Furthermore, if you try flashing once with the incorrect addresses first, you may need to later re-flash certain other sections that you've accidentally overwritten that you would otherwise not need to actually flash yourself.
- One final observation was that it is necessary to use the '-nostdlib' flag with the cross compiler to avoid pulling in the entire c standard library and avoid immediate stack overflows due to the limited memory of the ESP8266 device.
Overview of Solution
This section will describe the minimum viable product required for sending data directly between ESP8266 Modules in a way that can accomplish wireless bridging. The technique described here has been tested to work with sending packets in both directions through six ESP8266 modules. Simply illustrating the ability to send information between two ESP8266 modules is insufficient for demonstrating a practical implementation that could be extended to include an arbitrarily large number of ESP8266 modules that extend the chain further and further. The reason is that the modules are usually programmed to work either in the 'access point' mode (which functions like a router) or 'station' mode (which functions like a client connecting to the router), however it isn't possible (at least as far as I know) to gain the features of both modes at the same time with IP-based routing in order to 'chain' the access point connections to form a bridge of arbitrary length.
The technique described here use the ESP-now API to send packets to neighbouring modules using fixed hard-coded pre-determined MAC addresses. Each module is programmed with the same static list of MAC addresses. Then, on initialization, each module determines its MAC address looks this up in the list of all MAC addresses to determine which neighbours it has. This allows it to identify the upstream and downstream nodes.
Source Code
Here, you will find the makefile and source code used to produce this demo. Before you run this, be sure to complete the 'Toolchain Installation' section below.
# Make a test folder for our project
mkdir /tmp/example
# Move there
cd /tmp/example
# This empty file needs to exist as it is referenced in the library dependencies:
touch user_config.h
# Set up our Makefile:
cat > Makefile <<EOL
CC = xtensa-lx106-elf-gcc
CFLAGS = -I. -mlongcalls -I/opt/Espressif/ESP8266_NONOS_SDK/include -I/opt/Espressif/ESP8266_NONOS_SDK/driver_lib/include -I/opt/Espressif/ESP8266_SDK/include -Wall
LDLIBS = -L /opt/Espressif/ESP8266_NONOS_SDK/lib -L /opt/Espressif/ESP8266_SDK/lib -nostdlib -Wl,--start-group -lmain -lespnow -lnet80211 -lwpa -llwip -lpp -lphy -lcrypto -ldriver -lc -Wl,--end-group -lgcc
LDFLAGS = -T/opt/Espressif/ESP8266_NONOS_SDK/ld/eagle.app.v6.ld
esp_packet_router-0x00000.bin: esp_packet_router
esptool.py elf2image $^
esp_packet_router: esp_packet_router.o
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@
esp_packet_router.o: esp_packet_router.c
$(CC) $(CFLAGS) -c -o $@ $^
flash: esp_packet_router-0x00000.bin
esptool.py --port /dev/ttyUSB0 --baud 115200 write_flash 0 esp_packet_router-0x00000.bin 0x10000 esp_packet_router-0x10000.bin
clean:
rm -f esp_packet_router esp_packet_router.o esp_packet_router-0x00000.bin esp_packet_router-0x10000.bin
EOL
And put the following into a file called 'esp_packet_router.c' in the same directory:
#include <ets_sys.h>
#include <osapi.h>
#include <gpio.h>
#include <os_type.h>
#include <user_interface.h>
#include <espnow.h>
#include <driver/uart.h>
const u8 mac_addr[][6] = {
/* You'll have to replace the lines below with the specific MAC addresses of your modules: */
{0xa2, 0x20, 0xa6, 0x08, 0x6f, 0x3d}, //module #1 /* Most Upstream MAC... */
{0xa2, 0x20, 0xa6, 0x08, 0x6f, 0x70}, //module #2
{0xa2, 0x20, 0xa6, 0x14, 0xbf, 0x87}, //module #3
{0xa2, 0x20, 0xa6, 0x08, 0x6e, 0xd0}, //module #4
{0xA2, 0x20, 0xA6, 0x08, 0x7A, 0x12}, //module #5
{0xA2, 0x20, 0xA6, 0x08, 0x6D, 0x68} //module #6 /* Most Downstream MAC... */
};
#define NUM_MACS (sizeof(mac_addr)/sizeof(mac_addr[0]))
#define MAX_MESSAGE_CHARS 30
struct some_message{
uint32_t num_hops;
uint32_t text_len;
u8 msg[MAX_MESSAGE_CHARS];
};
int32_t upstream_mac_index = -1, downstream_mac_index = -1;
int32_t my_index;
/* Return true if both mac addresses match */
uint32_t compare_mac(const u8 *mac1, const u8 *mac2){
uint32_t i;
uint32_t match;
/* If either MAC is null, return no match */
if((mac1 == NULL) || (mac2 == NULL))
return 0;
/* Loop over bytes in MAC address */
match = 1;
for(i=0; i<6; i++) {
if(mac1[i] != mac2[i]) {
match = 0;
break;
}
}
if(match) {
return 1;
}
return 0;
}
void print_mac(const u8* mac){
int i;
for (i = 0; i < 6; i++) {
os_printf("%02X", mac[i]);
if(i < 5) {os_printf(":");}
}
}
int32_t get_mac_index(u8 *mac) {
int32_t i;
/* Search through mac list until we find ours */
/* loop over mac addresses */
for(i=0; i<NUM_MACS; i++) {
if(compare_mac(mac, mac_addr[i])) {
return i;
}
}
return -1;
}
void user_pre_init(void) { }
static const int pin = 2;
static os_timer_t some_timer;
void print_message(struct some_message *m) {
int i;
os_printf("{num_hops: %u, ", m->num_hops);
os_printf("text_len: %u, ", m->text_len);
for(i = 0; i < m->text_len; i++){
os_printf("%c", m->msg[i]);
}
os_printf("}");
}
void some_timerfunc(void *arg) {
int32_t send_to_mac_index = -1;
struct some_message m;
m.num_hops = 0;
//Do blinky stuff
if (GPIO_REG_READ(GPIO_OUT_ADDRESS) & (1 << pin)) {
// set gpio low
gpio_output_set(0, (1 << pin), 0, 0);
} else {
// set gpio high
gpio_output_set((1 << pin), 0, 0, 0);
}
if(downstream_mac_index == -1 && upstream_mac_index >= 0) {/* Is this the last node? */
const char * text = "Sending upstream";
m.text_len = os_strlen(text);
send_to_mac_index = upstream_mac_index;
os_memcpy((char *)&m.msg[0], text, m.text_len);
}
if(upstream_mac_index == -1 && downstream_mac_index >= 0) {/* Is this the first node? */
const char * text = "Sending downstream";
m.text_len = os_strlen(text);
send_to_mac_index = downstream_mac_index;
os_memcpy((char *)&m.msg[0], text, m.text_len);
}
if(send_to_mac_index >= 0){
esp_now_send((u8*)&mac_addr[send_to_mac_index][0], (u8*)&m, sizeof(m));
os_printf("Created message: '");
print_message(&m);
os_printf("' and sent it to MAC: ");
print_mac(&mac_addr[send_to_mac_index][0]);
os_printf("\n");
}else{
os_printf("I'm a Middle node, I just forward packets.\n");
}
}
void ICACHE_FLASH_ATTR simple_cb(u8 * from_mac, u8 *data, u8 len) {
int32_t send_to_mac_index;
struct some_message m;
os_memcpy(&m, data, len);
os_printf("Just got an ESPNow packet from MAC: ");
print_mac(&from_mac[0]);
os_printf(" ");
print_message(&m);
os_printf("'\n");
/* Keep track of how many times this packet was forwarded for fun. */
m.num_hops++;
/* see if data is from upstream or downstream, and if so, forward it */
send_to_mac_index = -1;
if(upstream_mac_index >= 0){
if(compare_mac(from_mac, &mac_addr[upstream_mac_index][0])) {
/* From our upstream neighbour, send downstream */
send_to_mac_index = downstream_mac_index;
os_printf("Send to Downstream neighbour: ");
print_mac(&mac_addr[send_to_mac_index][0]);
}
}
if(downstream_mac_index >= 0){
if(compare_mac(from_mac, &mac_addr[downstream_mac_index][0])) {
/* From our downstream neighbour, send upstream */
send_to_mac_index = upstream_mac_index;
os_printf("Send to Upstream neighbour:");
print_mac(&mac_addr[send_to_mac_index][0]);
}
}
os_printf("\n");
/* If we don't know who it came from, it dies here */
if(send_to_mac_index >= 0) {
esp_now_send((u8*)&mac_addr[send_to_mac_index][0], (u8*)&m, sizeof(m));
}
}
void ICACHE_FLASH_ATTR user_init() {
uint8_t mac[6];
// init gpio subsytem
gpio_init();
// configure UART TXD to be GPIO1, set as output
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1);
gpio_output_set(0, 0, (1 << pin), 0);
uart_init(115200, 115200);
if (esp_now_init() == 0) {
os_printf("XXXXXXXXXXX\n"); /* The first few characters printed out ends up as garbage... */
wifi_get_macaddr(SOFTAP_IF, mac);
my_index = get_mac_index(mac);
if(my_index == -1){
os_printf("\n\nI couldn't find my MAC address (");
print_mac(&mac[0]);
os_printf(") in the hard-coded list. Please add it.\n");
}else{
os_printf("\n\nI'm at index %u\n", my_index);
os_printf("My mac is ");
print_mac(&mac_addr[my_index][0]);
os_printf("\n");
/* If we are the last in the list, we are an end node, nobody to
send downstream to. */
if(my_index == (NUM_MACS-1)) {
downstream_mac_index = -1;
os_printf("I am the most downstream.\n");
} else {
/* Otherwise, send data upstream and */
downstream_mac_index = my_index + 1;
os_printf("The next node downstream is index %d at MAC: ", downstream_mac_index);
print_mac(&mac_addr[downstream_mac_index][0]);
os_printf("\n");
}
/* If we are the first on the list, we are an end node and we
should send upstream */
if(my_index == 0) {
upstream_mac_index = -1;
os_printf("I am the most upstream.\n");
} else {
upstream_mac_index = my_index - 1;
os_printf("The next node upstream is index %d at MAC: ", upstream_mac_index);
print_mac(&mac_addr[upstream_mac_index][0]);
os_printf("\n");
}
if(my_index == NUM_MACS) {
os_printf("I can't find my MAC address in the list!\n");
}
os_printf("esp_now init ok\n");
esp_now_register_recv_cb(simple_cb);
esp_now_set_self_role(1);
// setup timer (500ms, repeating)
os_timer_setfn(&some_timer, (os_timer_func_t *)some_timerfunc, NULL);
os_timer_arm(&some_timer, 500, 1);
}
} else {
os_printf("esp_now init failed\n");
}
}
uint32 ICACHE_FLASH_ATTR user_rf_cal_sector_set(void) {
enum flash_size_map size_map = system_get_flash_size_map();
uint32 rf_cal_sec = 0;
switch (size_map) {
case FLASH_SIZE_4M_MAP_256_256:
rf_cal_sec = 128 - 5;
break;
case FLASH_SIZE_8M_MAP_512_512:
rf_cal_sec = 256 - 5;
break;
case FLASH_SIZE_16M_MAP_512_512:
case FLASH_SIZE_16M_MAP_1024_1024:
rf_cal_sec = 512 - 5;
break;
case FLASH_SIZE_32M_MAP_512_512:
case FLASH_SIZE_32M_MAP_1024_1024:
rf_cal_sec = 1024 - 5;
break;
case FLASH_SIZE_64M_MAP_1024_1024:
rf_cal_sec = 2048 - 5;
break;
case FLASH_SIZE_128M_MAP_1024_1024:
rf_cal_sec = 4096 - 5;
break;
default:
rf_cal_sec = 0;
break;
}
return rf_cal_sec;
}
Setup and Sample Outputs
This section will show sample output obtained from installing and running the sample code above on all of the 6 modules. The setup used 6 ESP8266 modules, most of which were wired up on a breadboard without any soldering using a TO-220 LD1117V33 linear voltage regulator and 4 AA batteries in series. To power the ESP8266, power is sent to the VCC and CH_PD Pins. Only the ground pin was connected to the ground:
Here is a sample of the output obtained from each ESP8266 module with all others operating at the same time:
ESP Module #0 Output
I'm at index 0
My mac is A2:20:A6:08:6F:3D
The next node downstream is index 1 at MAC: A2:20:A6:08:6F:70
I am the most upstream.
esp_now init ok
mode : softAP(a2:20:a6:08:6f:3d)
add if1
dhcp server start:(ip:192.168.4.1,mask:255.255.255.0,gw:192.168.4.1)
bcn 100
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 4, text_len: 16, Sending upstream}'
Send to Upstream neighbour:64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 18, Sending downstream}' and sent it to MAC: A2:20:A6:08:6F:70
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 4, text_len: 16, Sending upstream}'
Send to Upstream neighbour:64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 18, Sending downstream}' and sent it to MAC: A2:20:A6:08:6F:70
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 4, text_len: 16, Sending upstream}'
Send to Upstream neighbour:64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 18, Sending downstream}' and sent it to MAC: A2:20:A6:08:6F:70
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 4, text_len: 16, Sending upstream}'
Send to Upstream neighbour:64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 18, Sending downstream}' and sent it to MAC: A2:20:A6:08:6F:70
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 4, text_len: 16, Sending upstream}'
Send to Upstream neighbour:64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 18, Sending downstream}' and sent it to MAC: A2:20:A6:08:6F:70
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 4, text_len: 16, Sending upstream}'
Send to Upstream neighbour:64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 18, Sending downstream}' and sent it to MAC: A2:20:A6:08:6F:70
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 4, text_len: 16, Sending upstream}'
Send to Upstream neighbour:64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 18, Sending downstream}' and sent it to MAC: A2:20:A6:08:6F:70
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 4, text_len: 16, Sending upstream}'
Send to Upstream neighbour:64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 18, Sending downstream}' and sent it to MAC: A2:20:A6:08:6F:70
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 4, text_len: 16, Sending upstream}'
Send to Upstream neighbour:64:39:35:29:00:00
ESP Module #1 Output
I'm at index 1
My mac is A2:20:A6:08:6F:70
The next node downstream is index 2 at MAC: A2:20:A6:14:BF:87
The next node upstream is index 0 at MAC: A2:20:A6:08:6F:3D
esp_now init ok
mode : softAP(a2:20:a6:08:6f:70)
add if1
dhcp server start:(ip:192.168.4.1,mask:255.255.255.0,gw:192.168.4.1)
bcn 100
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:3D {num_hops: 0, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:14:BF:87
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 3, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:3D
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:3D {num_hops: 0, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:14:BF:87
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 3, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:3D
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:3D {num_hops: 0, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:14:BF:87
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 3, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:3D
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:3D {num_hops: 0, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:14:BF:87
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 3, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:3D
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:3D {num_hops: 0, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:14:BF:87
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 3, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:3D
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:3D {num_hops: 0, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:14:BF:87
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 3, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:3D
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:3D {num_hops: 0, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:14:BF:87
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 3, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:3D
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:3D {num_hops: 0, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:14:BF:87
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 3, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:3D
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:3D {num_hops: 0, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:14:BF:87
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 3, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:3D
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:3D {num_hops: 0, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:14:BF:87
Just got an ESPNow packet from MAC: A2:20:A6:
ESP Module #2 Output
I'm at index 2
My mac is A2:20:A6:14:BF:87
The next node downstream is index 3 at MAC: A2:20:A6:08:6E:D0
The next node upstream is index 1 at MAC: A2:20:A6:08:6F:70
esp_now init ok
mode : softAP(a2:20:a6:14:bf:87)
add if1
dhcp server start:(ip:192.168.4.1,mask:255.255.255.0,gw:192.168.4.1)
bcn 100
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 1, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6E:D0
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 2, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:70
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 1, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6E:D0
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 2, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:70
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 1, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6E:D0
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 2, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:70
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 1, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6E:D0
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 2, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:70
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 1, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6E:D0
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 2, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:70
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 1, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6E:D0
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 2, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:70
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 1, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6E:D0
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 2, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:70
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 1, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6E:D0
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 2, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:70
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6F:70 {num_hops: 1, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6E:D0
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 2, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6F:70
I'm a Middle node, I just forward packets.
ESP Module #3 Output
I'm at index 3
My mac is A2:20:A6:08:6E:D0
The next node downstream is index 4 at MAC: A2:20:A6:08:7A:12
The next node upstream is index 2 at MAC: A2:20:A6:14:BF:87
esp_now init ok
mode : softAP(a2:20:a6:08:6e:d0)
add if1
dhcp server start:(ip:192.168.4.1,mask:255.255.255.0,gw:192.168.4.1)
bcn 100
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 2, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 1, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:14:BF:87
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 2, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:7A:12
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 2, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 1, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:14:BF:87
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 2, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 1, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:14:BF:87
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 2, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 1, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:14:BF:87
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 2, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 1, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:14:BF:87
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 2, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 1, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:14:BF:87
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:14:BF:87 {num_hops: 2, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 1, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:14:BF:87
I'm a Middle node, I just forward packets.
ESP Module #4 Output
I'm at index 4
My mac is A2:20:A6:08:7A:12
The next node downstream is index 5 at MAC: A2:20:A6:08:6D:68
The next node upstream is index 3 at MAC: A2:20:A6:08:6E:D0
esp_now init ok
mode : softAP(a2:20:a6:08:7a:12)
add if1
dhcp server start:(ip:192.168.4.1,mask:255.255.255.0,gw:192.168.4.1)
bcn 100
Just got an ESPNow packet from MAC: A2:20:A6:08:6D:68 {num_hops: 0, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6E:D0
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 3, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6D:68
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 3, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6D:68
Just got an ESPNow packet from MAC: A2:20:A6:08:6D:68 {num_hops: 0, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6E:D0
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 3, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6D:68
Just got an ESPNow packet from MAC: A2:20:A6:08:6D:68 {num_hops: 0, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6E:D0
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 3, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6D:68
Just got an ESPNow packet from MAC: A2:20:A6:08:6D:68 {num_hops: 0, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6E:D0
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 3, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6D:68
Just got an ESPNow packet from MAC: A2:20:A6:08:6D:68 {num_hops: 0, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6E:D0
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 3, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6D:68
Just got an ESPNow packet from MAC: A2:20:A6:08:6D:68 {num_hops: 0, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6E:D0
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 3, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6D:68
Just got an ESPNow packet from MAC: A2:20:A6:08:6D:68 {num_hops: 0, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6E:D0
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 3, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6D:68
Just got an ESPNow packet from MAC: A2:20:A6:08:6D:68 {num_hops: 0, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6E:D0
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 3, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6D:68
Just got an ESPNow packet from MAC: A2:20:A6:08:6D:68 {num_hops: 0, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6E:D0
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 3, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6D:68
Just got an ESPNow packet from MAC: A2:20:A6:08:6D:68 {num_hops: 0, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6E:D0
I'm a Middle node, I just forward packets.
Just got an ESPNow packet from MAC: A2:20:A6:08:6E:D0 {num_hops: 3, text_len: 18, Sending downstream}'
Send to Downstream neighbour: A2:20:A6:08:6D:68
Just got an ESPNow packet from MAC: A2:20:A6:08:6D:68 {num_hops: 0, text_len: 16, Sending upstream}'
Send to Upstream neighbour:A2:20:A6:08:6E:D0
ESP Module #5 Output
I'm at index 5
My mac is A2:20:A6:08:6D:68
I am the most downstream.
The next node upstream is index 4 at MAC: A2:20:A6:08:7A:12
esp_now init ok
mode : softAP(a2:20:a6:08:6d:68)
add if1
dhcp server start:(ip:192.168.4.1,mask:255.255.255.0,gw:192.168.4.1)
bcn 100
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 4, text_len: 18, Sending downstream}'
Send to Downstream neighbour: 64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 16, Sending upstream}' and sent it to MAC: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 4, text_len: 18, Sending downstream}'
Send to Downstream neighbour: 64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 16, Sending upstream}' and sent it to MAC: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 4, text_len: 18, Sending downstream}'
Send to Downstream neighbour: 64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 16, Sending upstream}' and sent it to MAC: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 4, text_len: 18, Sending downstream}'
Send to Downstream neighbour: 64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 16, Sending upstream}' and sent it to MAC: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 4, text_len: 18, Sending downstream}'
Send to Downstream neighbour: 64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 16, Sending upstream}' and sent it to MAC: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 4, text_len: 18, Sending downstream}'
Send to Downstream neighbour: 64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 16, Sending upstream}' and sent it to MAC: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 4, text_len: 18, Sending downstream}'
Send to Downstream neighbour: 64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 16, Sending upstream}' and sent it to MAC: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 4, text_len: 18, Sending downstream}'
Send to Downstream neighbour: 64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 16, Sending upstream}' and sent it to MAC: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 4, text_len: 18, Sending downstream}'
Send to Downstream neighbour: 64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 16, Sending upstream}' and sent it to MAC: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 4, text_len: 18, Sending downstream}'
Send to Downstream neighbour: 64:39:35:29:00:00
Created message: '{num_hops: 0, text_len: 16, Sending upstream}' and sent it to MAC: A2:20:A6:08:7A:12
Just got an ESPNow packet from MAC: A2:20:A6:08:7A:12 {num_hops: 4, text_len: 18, Sending downstream}'
Send to Downstream neighbour: 64:39:35:29:00:00
Determining ESP8266 Firmware Flashing Addresses
Here is an example of what you need to look for to identify the flash memory size and address requirements for your module:
Now, go to Google and search for 'ESP8266EX Datasheet'. You'll find this document. Check section '3.1.3. External Flash' and note that it says in relation to flash memory 'OTA enabled: 1 MB at least'. Now, check section '4.1.2. Download Addresses' of the document ESP8266 SDK Getting Started Guide Version 3.1. This table lists various values for the download addresses based on flash memory size:
Table 4-2. Download Address for Non-OTA Firmware (unit: KB) | ||||||
Binaries | Download addresses in flash with different capacities | |||||
512 | 1024 | 2048 | 4096 | 8192 | 16*1024 | |
blank.bin | 0x7B000 | 0xFB000 | 0x1FB000 | 0x3FB000 | 0x7FB000 | 0xFFB000 |
esp_init_data_default.bin | 0x7C000 | 0xFC000 | 0x1FC000 | 0x3FC000 | 0x7FC000 | 0xFFC000 |
blank.bin | 0x7E000 | 0xFE000 | 0x1FE000 | 0x3FE000 | 0x7FE000 | 0xFFE000 |
eagle.flash.bin | 0x00000 | |||||
eagle.irom0text.bin | 0x10000 |
Reading From The ESP8266
During normal operation, the command used to view the serial output from the ESP8266 module was:
cu -s 115200 -l /dev/ttyUSB0
However, if an error was encountered during an early phase of the bootloading sequence, the 'cu' tool was not able to support the slightly different baud rate of '74880' on Linux. Instead, it was found that the following command worked in this situation:
sudo python /usr/lib/python2.7/dist-packages/serial/tools/miniterm.py /dev/ttyUSB0 74880
Toolchain Installation
Installation steps for installing the cross compiler were found and adapted from here. The steps at the original source didn't work out of the box, so the adapted sequence is documented here which worked:
sudo apt-get install git autoconf build-essential gperf bison flex texinfo libtool libncurses5-dev wget gawk libc6-dev-amd64 python-serial libexpat-dev libtool-bin
sudo mkdir /opt/Espressif
sudo chown `whoami`:`whoami` /opt/Espressif
cd /opt/Espressif
git clone -b lx106 git://github.com/jcmvbkbc/crosstool-NG.git
# This document was tested with commit f4a3946c3e120d1826bf458a8c1c4c50bc19d9e9
cd crosstool-NG
At this point, attempting to run 'make' would produce the following error:
In file included from zconf.tab.c:213:0:
zconf.hash.c:163:1: error: conflicting types for ‘kconf_id_lookup’
kconf_id_lookup (register const char *str, register size_t len)
^~~~~~~~~~~~~~~
zconf.hash.c:34:25: note: previous declaration of ‘kconf_id_lookup’ was here
static struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len);
If you run this sed command, this should fix the compile error:
# Fix a compile error:
sed -i 's/register unsigned int len/register size_t len/' kconfig/zconf.gperf
./bootstrap && ./configure --prefix=`pwd` && make && make install
./ct-ng xtensa-lx106-elf
# Fix a broken URL
sed -i 's/http:\/\/www.multiprecision.org\/mpc\/download/https:\/\/ftp.gnu.org\/gnu\/mpc/' lib/ct-ng.1.20.0/scripts/build/companion_libs/140-mpc.sh
sed -i 's/http:\/\/www.multiprecision.org\/mpc\/download/https:\/\/ftp.gnu.org\/gnu\/mpc/' scripts/build/companion_libs/140-mpc.sh
./ct-ng build
# Use this command if you want to add the cross compiler to your PATH variable:
echo 'PATH='`pwd`'/builds/xtensa-lx106-elf/bin:$PATH' >> ~/.profile
source ~/.profile
cd /opt/Espressif
# md5sum b95e004840d3cea5951ee5e350884c13 esp_iot_sdk_v0.9.3_14_11_21.zip
wget -O esp_iot_sdk_v0.9.3_14_11_21.zip https://github.com/esp8266/esp8266-wiki/raw/master/sdk/esp_iot_sdk_v0.9.3_14_11_21.zip
# md5sum d8d3f8c96c5c67c499c8ca4c9593dbaf esp_iot_sdk_v0.9.3_14_11_21_patch1.zip
wget -O esp_iot_sdk_v0.9.3_14_11_21_patch1.zip https://github.com/esp8266/esp8266-wiki/raw/master/sdk/esp_iot_sdk_v0.9.3_14_11_21_patch1.zip
unzip esp_iot_sdk_v0.9.3_14_11_21.zip
unzip -o esp_iot_sdk_v0.9.3_14_11_21_patch1.zip
mv esp_iot_sdk_v0.9.3 ESP8266_SDK
mv License ESP8266_SDK/
cd /opt/Espressif/ESP8266_SDK
sed -i -e 's/xt-ar/xtensa-lx106-elf-ar/' -e 's/xt-xcc/xtensa-lx106-elf-gcc/' -e 's/xt-objcopy/xtensa-lx106-elf-objcopy/' Makefile
mv examples/IoT_Demo .
cd /opt/Espressif/ESP8266_SDK
# md5sum 0b6ee9bde48e292e70882db6bd03f07a /opt/Espressif/ESP8266_SDK/lib/libc.a
wget -O lib/libc.a https://github.com/esp8266/esp8266-wiki/raw/master/libs/libc.a
# md5sum b36e7762295cfd9ef7c95fa4ed3e56e4 /opt/Espressif/ESP8266_SDK/lib/libhal.a
wget -O lib/libhal.a https://github.com/esp8266/esp8266-wiki/raw/master/libs/libhal.a
# md5sum 25c41b16a2092bbbeddcf104ff9b8063 /opt/Espressif/ESP8266_SDK/include.tgz
wget -O include.tgz https://github.com/esp8266/esp8266-wiki/raw/master/include.tgz
tar -xvzf include.tgz
cd /opt/Espressif
# md5sum d58f2da804fd49e26ad37bdf5b80f5e8 esptool_0.0.2-1_i386.deb
wget -O esptool_0.0.2-1_i386.deb https://github.com/esp8266/esp8266-wiki/raw/master/deb/esptool_0.0.2-1_i386.deb
sudo dpkg -i esptool_0.0.2-1_i386.deb
cd /opt/Espressif
# Tested with commit f262eacbc01afbb1661a5f0d7de2487e004ee952
git clone https://github.com/themadinventor/esptool esptool-py
chmod u+w crosstool-NG/builds/xtensa-lx106-elf/bin/
ln -s `pwd`/esptool-py/esptool.py crosstool-NG/builds/xtensa-lx106-elf/bin/
And then finally, espnow dependencies were found in:
cd /opt/Espressif
git clone https://github.com/espressif/ESP8266_NONOS_SDK.git
cd ESP8266_NONOS_SDK
# I found it to be absolutely necessary to checkout out the
# stable release at this commit hash:
git checkout f32da973de57555a634f72b4dc0a0f0ac4df1770
Conclusion
In this article, a functional demo of direct ESP8266 to ESP8266 wireless communication has been presented. In the future, may be possible to extend this project to allow for the ability to seamless PC to PC wireless bridges or other novel uses.
How To Make A CPU - A Simple Picture Based Explanation
Published 2021-11-09 |
$1.00 CAD |
Example Uses Of Semiconductors - More Than Just CPUs
Published 2022-03-03 |
What Causes Bit Flips In Computer Memory?
Published 2023-02-08 |
Jeri Ellsworth & the Robot Uprising of 2038
Published 2018-10-11 |
CPUs Are Smaller Than You Think
Published 2021-11-09 |
Can You Create A Wireless Bridge With ESP8266 Modules?
Published 2018-09-02 |
Using The GY-511 LSM303DLHC Accelerometer To Detect Waving Motion
Published 2018-04-25 |
Join My Mailing List Privacy Policy |
Why Bother Subscribing?
|