Saturday, 26 March 2016

UDP-Ranger - a simple ESP8266 range tester

The problem

I tried to find reliable information on the range of the ESP-12 series modules, but was not quite happy with what I found. Neither the use of highly directional antennas (or is it "antennae"?) nor the selection of client devices seemed right to draw conclusions about the actual range.

EDIT: see the 1st part of my video about the tester here.
EDIT: and here is the 2nd part if the video with the results

The idea

ESP-8266 modules at both ends of the connection seemed like a good idea to me. Normally you would use a simple ping-test to see if packets are lost on the way between the modules.


Despite the fact that the LWIP stack in NodeMCU does handle ICMP properly, I have yet to see a "Ping" program to send/revceive ICMP echo-requests/replies.


TCP connections between two NodeMCU endpoints are super easy. But the TCP  protocol will do it's best to compensate the loss of packets, so we wouldn't detect missing packets until the connection breaks up completely.


UDP does not provide such a recovery mechanism for lost packets, so the application has to handle that. We can use that easily to find out when packets go missing.

The solution

Ok, so UDP it is. We'll simply connect an ESP-12e module in station-mode to an ESP-12f module in soft-ap mode and send UDP packets from the ESP-12e to the ESP-12f module.
The payload of each packet is a numer that is incremented by one for each packet. So if a packet is missing, it is easy to detect.
The ESP-modules

What you need

The server.lua script

 local LED_PIN1 = 4  
 gpio.mode(LED_PIN1, gpio.OUTPUT)  
 local sw1 = true  
 function init_OLED(sda,scl)  
    sla = 0x3c  
    i2c.setup(0, sda, scl, i2c.SLOW)  
    disp = u8g.ssd1306_128x64_i2c(sla)  
    disp:drawStr(0, 10, "AReResearch UDP-Ranger")  
    disp:drawStr(5, 35, "Waiting for client...")  
   until disp:nextPage() == false  
   print("Sequence="..c.." Previous:"..cold)  
 if ((cold+1)~=tonumber(c)) then  
    disp:drawStr(0, 10, "AReResearch UDP-Ranger")  
    disp:drawStr(5, 35, "Packet Nr:" .. c)  
    disp:drawStr(5, 45, "Errors:" .. err)  
     until disp:nextPage() == false  
     if (sw1) then  
       gpio.write(LED_PIN1, gpio.LOW)  
       gpio.write(LED_PIN1, gpio.HIGH)  
   sw1 = not sw1  

The client-lua script
 LED_PIN1 = 4  
 gpio.mode(LED_PIN1, gpio.OUTPUT)  
 print (wifi.sta.getip())  
 tmr.alarm(2, 1000, 1, function()  
   conn = net.createConnection(net.UDP, 0)  
   conn = nil  
   print (x)  
   if x>1000 then x=1 end  
   print (p)  
   if p == 5  
     gpio.write(LED_PIN1, gpio.LOW)  
     print ("LED OFF")  
     gpio.write(LED_PIN1, gpio.HIGH)  
     print ("LED ON")  

Ok, the programming is admittedly a bit sloppy. The counter will simply roll over at 1000 packets and will thus increment the "lost packets" counter by one. It is good enough for me at the moment.

Start the "server"module first

The "client" has sent packets

How to use this

Once the client module has connected to the "server", the server module's  LED will be toggled every time a packet is received. More info in how many packets have been missed is shown on the OLED.
So it is easy to tell when the connection starts breaking up.

The results

My first test run gave me a pretty stable connection up to 300 meters. Beyond 400m I couldn't get anything at all.

Sunday, 13 March 2016

Espressif ESP-12e module radiation pattern

The ESP-12e module has an onboard PCB antenna. When an IoT device is located near the edge of my WIFI network, pointing the antenna the right way may add a few meters to the useable range.
Having had a little time over the weekend, I decided to build a contraption that allows me to rotate the module and record both signal strength and orientation.
There ist a nice protractor.svg file on wikipedia. I use Inkscape to scale and print that.

You may also want to watch my video on this topic here.

Some woodworking

And the protractor
Pointer and tripod adapter
Next I need to put the ESP-12e module in AP-Mode, so it sends beacon packets. Then I wire it in a very basic configuration to run from a 3,7V lithium cell. To drop 0.6V, I put a 1N4148 in series with the module. (Actually, a 1N4148 a bit weak for the job. Go for a 1N4001 if you can. I couldn't find one in my parts bin.)
The TXD/RXD wires are still connected for programming
Can it get any simpler than that? GND and GPIO15 are connected to the negative terminal, VCC and CH_PD to the cathode of the 1N diode. The anode is connected to the positive terminal.
I use a 18650 cell and this holder.
No more unnecessary stuff
Test run
Now mount it all on a tripod and wait for a sunny day to take it all outside where we have little or no reflections.

Ok, let's go outside...


I used LibreOffice to turn the handwritten values into a polar diagram. Here is the resulting  chart:

Although I didn't expect the field to be completely uniform, the result is pretty obvious:
The module (looked at from the component side, antenna pointing away from us) has a clear west-north-westernly preference and a clearly visible minimum at the opposite end. So you'll want that (upper left) corner of the module to point at your access point if you get near the edge of your wifi range.


While working on this project, I found out about the ESP-12F, which supposedly has an improved antenna design over the ESP-12E. I do not have one here at the moment, but will compare the two if I can get hold of one.
To get a smoother chart, I should do two full rounds to smooth out the errors and do finer steps (5 instead of 10 degrees).


If you want to try the same, you don't need a Wifi tester. A PC with InSSIDer (the free version), or even use another ESP-Module as WiFi scanner as shown here.

PPS: Shopping list:

Thin plywood, the size if an A4 paper
The protractor.svg file from wikipedia
A 18650 rechargeable battery. (Well, and a charger if you don't have one)
Suitable 18560 battery holder
One 1N4001 diode
and of course the ESP-12e module