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.

ICMP

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

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

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  
 wifi.setmode(wifi.SOFTAP)  
 cfg={}  
    cfg.ssid="AReResearch"  
    wifi.ap.config(cfg)  
 function init_OLED(sda,scl)  
    sla = 0x3c  
    i2c.setup(0, sda, scl, i2c.SLOW)  
    disp = u8g.ssd1306_128x64_i2c(sla)  
    disp:setFont(u8g.font_6x10)  
    disp:setFontRefHeightExtendedText()  
    disp:setDefaultForegroundColor()  
    disp:setFontPosTop()  
 end  
 init_OLED(5,6)  
 err=0  
 cold=1  
 disp:firstPage()  
   repeat  
    disp:drawStr(0, 10, "AReResearch UDP-Ranger")  
    disp:drawStr(5, 35, "Waiting for client...")  
   until disp:nextPage() == false  
 s=net.createServer(net.UDP)   
 s:on("receive",function(s,c)  
   print("Sequence="..c.." Previous:"..cold)  
 if ((cold+1)~=tonumber(c)) then  
   err=err+1  
   end  
 disp:firstPage()  
   repeat  
    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)  
     else  
       gpio.write(LED_PIN1, gpio.HIGH)  
     end  
   sw1 = not sw1  
 cold=c  
 end)   
 s:listen(8888)  

The client-lua script
 wifi.setmode(wifi.STATION)  
 wifi.sta.config("AReResearch","")  
 wifi.sta.connect()  
 LED_PIN1 = 4  
 gpio.mode(LED_PIN1, gpio.OUTPUT)  
 print (wifi.sta.getip())  
 x=1  
 tmr.alarm(2, 1000, 1, function()  
   conn = net.createConnection(net.UDP, 0)  
   conn:connect(8888,"192.168.4.1")  
   conn:send(x)  
   conn:close()  
   conn = nil  
   x=x+1  
   print (x)  
   if x>1000 then x=1 end  
   p=tonumber(wifi.sta.status())  
   print (p)  
   if p == 5  
     then  
     gpio.write(LED_PIN1, gpio.LOW)  
     print ("LED OFF")  
     else  
     gpio.write(LED_PIN1, gpio.HIGH)  
     print ("LED ON")  
     end  
 end)  

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.

6 comments:

  1. 300m! that's not bad for a $3 module, not bad at all! I've found that the signal strength is pretty good myself. I recently bought a wifi camera, and I found that it works through 2 concrete walls plus 2 interior walls, which I found to be beyond what my cell phone can do. When I opened it up to take a look inside, I found an ESP-07 to my surprise...

    On an unrelated topic: considering your solution for using the ESP as a range extender, and your DNS forwarder, I was wondering if you would happen to know how to forward DHCP requests through the ESP? I'm thinking something like this:
    A client connects to the ESP softap, then makes a DHCP request to get an IP address. Instead of the ESP handling it, the ESP forwards it through its station interface, and waits for the reply. When the reply is received at the station interface, it gets passed back to the client through the softap connection.

    ReplyDelete
  2. Hello dear friend, I'm new in these topics, actually I triying to connect two ESP8266 whit UDP protocol, and I think your idea is great, but I can't understand well.
    Why you use the IP "192.168.4.1", the Access Point IP is?
    In that case how do you know the IP, what can I do to check the ESP8266 AP IP adress?
    Finally, how many devices can be connected to ESP as AP?
    ...thanks in advance...

    ReplyDelete
    Replies
    1. The 192.168.4.1 is the default address when you activate the AP. I simply left it at the default.

      Delete
  3. Which software is used here to program esp ??

    ReplyDelete
  4. Hello, can you give me the Arduino IDE file? please...

    ReplyDelete
  5. Thanks but something has to have changed since this code was written because every time I try to execute any code with x:send() it fails to send anything at all with the latest version of firmware.

    ReplyDelete