When experimenting with ESP32 modules, especially the ESP32 CAMs, I wish I had a little more WIFI range reserve.
This could be achieved by adding an external antenna – but only a few modules are prepared for the connection of an external antenna. The resulting financial and mechanical outlay is also no longer negligible and may not be in good proportion to the range improvement actually required.
In the end, to keep it as simple but effective as possible, I added a half-wave antenna wire to the original onboard antenna of the ESP32 module.

The original printed antenna found at the standard ESP32 board is a meander-shaped, inverted F antenna with 1/4 wavelength. This type of antenna is a compromise between size, an almost omnidirectional antenna pattern, and a still acceptable power efficiency and WIFI range within the limits of the given RF-power and reception sensitivity of the ESP32. I found very helpful sources of information about such kind of antennas at https://www.nxp.com/docs/en/application-note/AN2731.pdf and https://www.antenna-theory.com/antennas/aperture/ifa.php
My idea was to increase the WIFI range of the module by coupling the on-board 1/4-wave antenna with an additional new external half-wave antenna with a larger shape, not shortened by the meanders, and hopefully a better free-standing placement. However, additionally no irreversible changes or soldering should become necessary. These requirements could be met by gluing the additional antenna wire directly onto the circuit board, as can be seen in photo X.
Assuming that the printed antenna is designed as a 1/4-wave monopole for 2.4 GHz, I measured its length and doubled this as a first approximation. This resulted in a half-wave antenna made of switching wire with a length of 62 mm and a diameter of 0.5 mm.
(Please note the optimisation to 58mm described at the end of this article)
Note that half of the additional antenna wire follows exactly the meandering outer shape of the printed F-antenna and is kept at a distance by the wire’s insulating material, while the other half is mounted “free”. This leads to strong inductive and capacitive coupling of the two antennas, which now form a common, larger, optimized radiating antenna element. The best point for the hot glue in terms of high frequency is the low impedance center of the new half wave antenna just at the right corner of the ESP32 module.This prevents the high-impedance part of the antenna from being affected by additional RF-attenuating material.
Now it was time to prove my promising design in practice!
To measure the effect, I mounted a modified module next to an unmodified module so that both modules should have approximately the same reception and transmission conditions to the leftmost access point and without them influencing each other by facing each other.
This setup was very easy to place anywhere and helped explore the WiFi conditions for both modules at the same time.

I wrote a few lines of ANNEX32 BASIC code that runs on both ESP32 modules and displays the WIFI field strength of the WIFI access point measured by both devices in a Life Browser window. Module 1 (with additional antenna) logs its own WIFI RSSI value and additionally requests a string with the logged RSSI from the second (unmodified) module. This browser window therefore always shows two sliding curves, each with the last 100 measurements going back about 50 seconds.
For newcomers to ANNEX32 – a stand-alone BASIC interpreter and IDE that runs completely in the ESP32, but can also be very easily supported by the scripting functions in the browser if, as here, special graphical display functions are also required – here is a link to the fabulous online manual. With just a few lines of code, this interpreter enables the creation of simple or even very complex programmes that interact with any web browser. In particular, the web-based editing of the code takes place without the need for a serial connection to the PC/laptop, simply via a WIFI connection.
I tested the effect of the additional antenna and recorded the WIFI strength of the access point under different conditions. Here I show only an excerpt from my experiments with very pleasing results overall.


It turns out that the signal is improved by at least 3 dB overall on the modified modules with an elongated non-angled antenna wire. Under very reflective environmental conditions, I had an improvement of almost 10 dB.
However, the rough measurements also clearly indicate that the now better conditions are reflected in the nulls in the antenna pattern, which are now somewhat more pronounced, as expected.
When using this antenna, one must always bear in mind that the directional effect is now much greater than before – for better or for worse!
One of the reasons for the better gain is certainly the modified antenna pattern; another could be the strong coupling to an antenna that is not downsized, partially freestanding, and thus somewhat more effective.

Some things still to do …
I did some experiments with the free end of the antenna at a 90 degree angle up. This changed the resulting antenna pattern, which should certainly be investigated further to optimize the result. This variation can be helpful in certain mounting environments, such as when the module is sitting on a heavily populated PCB, then with a significantly more free-standing antenna.
I have not yet looked at optimizing the length of the half-wave wire, but have followed the best practice of 62 mm for 2.48GHz. Maybe it could be a little shorter, since it doesn’t just run free in the air and is not very massive. SEE UPDATE AT THE END!!
CONCLUSIONS:
Under possibly unfavorable conditions, this simple antenna modification may not work miracles, but it can
- slightly increase the range of the ESP32 module or
- improve a given less stable WIFI connection.
This improvement is inevitably accompanied by the disadvantage of a more pronounced directional effect. It works best if the module has a fixed location and if it is possible to adjust the orientation of the module’s antenna relative to the AP’s antenna.
To clarify: This means that the wide side of the antenna points towards the AP and that the antenna of the AP is polarized in the same way, i.e. the two antennas are aligned as parallel to each other as possible.
______
A practical application: The described modification resulted in a much better signal and a very stable video connection with an ESP32 CAM module in a previously quite critical location.

This is the ANNEX32-BASIC-code used in the two ESP32-modules:
'######## WIFI-GRAPH-LOGGER ####################################
' Allows to compare the two ESP-Modules which have different antennas
' (peter.neufeld@gmx.de 06/2024)
' Displays a graphical logging of two WIFI-signals in dB on module_1
' - the OWN WIFI-connection to the WIFI access point
' - the WIFI-connection of a remote ESP32 module_2 to the same AP
'
' RX = 1 => This ESP-Module regularly requests the WIFI-LOG-RESULT-STRING
' from a remote module with http://REMOTE_IP/msg?x=1
' TX = 1 => this ESP-Module returns the string with its
' WIFI-LOG-RESULT-STRING on request at http://MY_IP/msg?x=1
' uncomment this on the ESP32 module_1 as the main module
RX = 1 'This module_1 sends requests
TX = 0 'This module_1 is quiet
' uncomment this on the ESP32 module_2 as the 2nd module
'RX = 0 'This module_2 does not send requests
'TX = 1 'This module_2 responds to requests
REMOTE_IP$ = "192.168.0.141" 'Set here YOUR IP-Address of module_2
X_Num = 100 'Number of WIFI-MESSURES to display in the graph
WIFI_REMOTE$ = ""
onhtmlreload WEBPAGE
gosub WEBPAGE
IF TX = 1 onurlmessage RETURN_WIFI_STRING
IF RX = 1 onwgetasync RECEIVE_REMOTE_STRING
timer0 500, LOG_MY_WIFI_CONNECTION
IF RX = 1 timer1 1000, GET_REMOTE_WIFI_LOG_STRING
wait
'###############################################################
LOG_MY_WIFI_CONNECTION:
w=0
for i = 1 to 50
w = wifi.rssi + w
next i
w=W/(i-1) ' Thanks for the hint Fernando !
WIFI_LOCAL$= trim$(WIFI_LOCAL$ + " " +str$(wifi.rssi,"%2.1f"))
c = word.count(WIFI_LOCAL$," ")
p = instr(1, WIFI_LOCAL$, " ")
p = len(WIFI_LOCAL$) - p
If c > X_NUM then WIFI_LOCAL$ = right$(WIFI_LOCAL$, p )
'wlog WIFI_LOCAL$ , c
jscall |traceme(0,"| + WIFI_LOCAL$ + |");|
if WIFI_REMOTE$ <> "" jscall |traceme(1,"| + WIFI_REMOTE$ + |");|
return
'###############################################################
RETURN_WIFI_STRING:
URLMSGRETURN WIFI_LOCAL$
return
'###############################################################
GET_REMOTE_WIFI_LOG_STRING:
wgetasync ("http://" + REMOTE_IP$+ "/msg?x=1")
return
'###############################################################
RECEIVE_REMOTE_STRING:
WIFI_REMOTE$ = WGETRESULT$
return
'###############################################################
WEBPAGE:
cls
jsexternal "/xy.min.js"
cnt = 0
a$ = ""
a$ = a$ + |<p>WIFI Graph for two ESP32-modules .. <br> |
a$ = a$ + |GREEN = WITH additional antenna <br> RED === with original antenna |
a$ = a$ + |</p><canvas id="canvas1" width="800" height="400"></canvas>|
html a$
pause 500
A$ = ""
A$ = A$ + |var datasets = [|
A$ = A$ + | {|
A$ = A$ + | lineColor : 'rgba(20,100,100,1)',|
A$ = A$ + | pointColor : 'rgba(20,20,20,1)',|
A$ = A$ + | pointStrokeColor : '#fff',|
A$ = A$ + | data : []|
A$ = A$ + | },|
A$ = A$ + | {|
A$ = A$ + | lineColor : 'rgba(151,30,0,1)',|
A$ = A$ + | pointColor : 'rgba(151,80,0,1)',|
A$ = A$ + | pointStrokeColor : '#fff',|
A$ = A$ + | data : []|
A$ = A$ + | }|
A$ = A$ + |];|
A$ = A$ + |var ctx2 = document.getElementById('canvas1').getContext('2d');|
A$ = A$ + ||
A$ = A$ + |var xy = new Xy(ctx2, {rangeX:[0,|+ STR$(X_NUM)+ |], rangeY:[-80,-45]|
A$ = A$ + |, smooth:0.05, pointCircleRadius:2, pointStrokeWidth:1 });|
A$ = A$ + ||
A$ = A$ + |function traceme(set, data){|
A$ = A$ + | var s = data.split(" ");|
A$ = A$ + | for (var i=0; i<s.length; i++) {|
A$ = A$ + | datasets[set].data[i] = [i, s[i]];|
A$ = A$ + | }|
A$ = A$ + | xy.draw(datasets);|
A$ = A$ + |}|
jscript A$
A$ = "" ' clean memory
return
For newcomers to ANNEX32 – a standalone BASIC interpreter/IDE that runs entirely in ESP32 and is only supported by Javascript in the browser when needed – here’s a link to the fabulous online manual.

———————————–

EDIT: Optimizing the length of the halve-wave-antenna wire
I put a bit of work into optimizing the length of the antenna wire, since simply doubling the 1/4 wave length of the inverted F antenna does not take into account various physical influences on the optimal length of the only partially free-standing wire.
After removing the insulation on a length of 15 mm and then shortening the wire by 6 mm, I added a variable extension made of a 10 mm*1 mm silver wire. A piece of heat shrink tubing served as a temporary slide holder.
This allowed me to easily adjust the wire length with my test setup for the highest possible receiving field strength. The actual influence of the dielectric, inductance and capacitance on the wire length was now taken into account. Finally, I fixed the connection with very little solder.
The experimentally determined optimum length for the entire half-wave antenna wire was finally 58mm. This is 4mm less than the old value and resulted in an additional signal boost of 1.5dB!
Want to read more about ESP32, its antenna, pifa etc? Here is listed what was helpful to me:
https://www.espressif.com/sites/default/files/documentation/esp32_hardware_design_guidelines_en.pdf
https://www.esp32.com/viewtopic.php?f=2&t=3096#p14475
https://www.ti.com/lit/an/swra117d/swra117d.pdf
https://www.nxp.com/docs/en/application-note/AN2731.pdf
https://www.antenna-theory.com/antennas/aperture/ifa.php
SOME USEFUL LINKS TO THE ANNEX32 SCRIPT INTERPRETER:
Annex32 BASIC_Interpreter for ESP32: https://cicciocb.com
Annex32 online flasher : https://flasher.cicciocb.com/dist/index.html
Online manual for Annex32: https://cicciocb.com/annex32help
#
##
###
####
#####
######
#######
########
#########
##########
###########
############ END





