Unofficial ESP32-based LAN remote control and browser LCD mirror for the MFJ-993B IntelliTuner.
The ESP32 passively observes the tuner's 4-bit LCD bus, reconstructs the visible 16x2 screen and dynamic 5x8 custom characters, serves a mobile-friendly web interface, and controls the nine front-panel functions through an external switch-emulation stage.
Status: experimental and hardware-specific. The pin map and LCD sampling point were tuned on one working installation. Verify signal levels, polarity and wiring on your own hardware before connecting it.
- Browser mirror of the 16x2 LCD, including DDRAM, CGRAM glyphs and tuning bars.
- Stable main meter screen: frequency,
MHz, SWR,FWD=andREF=are kept in fixed character cells. - Main-screen numeric values are accepted independently, so a damaged bus byte does not shift the entire browser display or erase the last valid value.
- The three main-screen CGRAM indicators are updated only after two identical snapshots; partial glyph rewrites are not displayed.
- CGRAM activity does not delay frequency, SWR, forward-power or reflected-power updates.
- Nine controls: ANT, C-UP, L-UP, AUTO, MODE, C-DN, L-DN, TUNE and POWER.
- True press-and-hold behavior for MODE, TUNE and C/L adjustment buttons.
- Manual-defined shortcuts and confirmation-protected power-on service operations.
- Wi-Fi configuration access point when the saved network is unavailable.
- WebSocket request/response flow with no backlog of stale LCD frames.
- Browser polling every 20 ms normally and every 100 ms while a momentary control is held.
- Firmware upload from the browser at
/updateusing the main*.ino.binfile.
![]() Main meter / Основной экран |
![]() Manual L/C / Ручная подстройка |
![]() Button combinations / Комбинации кнопок |
![]() Firmware update / Обновление прошивки |
Wi-Fi recovery setup / Настройка Wi-Fi |
|
flowchart LR
LCD["MFJ LCD bus<br>RS, E, DB4-DB7"] --> LEVEL["74LVC244A<br>5 V to 3.3 V"] --> ESP["ESP32<br>LCD decoder"]
ESP --> WEB["HTTP + WebSocket"] --> UI["Phone or PC browser"]
UI --> ESP
ESP --> DRIVER["PC817 channels<br>buttons + relay"] --> PANEL["MFJ controls<br>and power"]
On the tested tuner the PIC16F76 drives the HD44780-compatible LCD in short 4-bit bursts rather than continuously retransmitting the full screen. In the idle state E is low while RS and DB4…DB7 are high. The measured E high plateau is about 520 ns; the remaining bus lines are stable for about 1–2 µs, with brief 10–20 ns transition ringing up to approximately 0.5 V. These are measurements from the reference unit, not universal HD44780 idle requirements.
The LCD lines enter the ESP32 through a 74LVC244A powered from 3.3 V. The eight normal front-panel controls are reproduced by PC817 optocouplers wired in parallel with the physical buttons. A ninth isolated channel controls the external power-relay driver, which makes the documented service and reset combinations possible without disabling the original controls.
See Hardware implementation for measured timing, signal direction, optocoupler and relay details.
The same design approach can be adapted to the MFJ-998 family, but the present hardware map and firmware are not a drop-in MFJ-998 build. The public MFJ documentation located for this comparison names the model MFJ-998 (without the B suffix); any unit specifically labelled MFJ-998B must be checked against its own PCB revision and schematic.
The published MFJ-998 Rev. 1A schematic shows a WH1602B 16×2 display connected to a PIC18F2520 through RS, E and DB4…DB7. This makes the passive LCD capture concept and a 5 V-tolerant 74LVC244A input stage applicable in principle.
However, the following items must be measured and adapted separately:
- LCD timing, idle levels, sampling delay and CGRAM behavior;
- display layouts and parsing, especially four-digit legal-limit power values;
- ESP32 GPIO assignment and every solder point;
- eight-button MFJ-998 control layout: it has no separate AUTO button;
- button polarity, optocoupler orientation, power switching and supported combinations.
Do not use this repository's MFJ-993B wiring table or firmware unchanged on an MFJ-998-class tuner. The MFJ-998 is a legal-limit device; disconnect the amplifier, transmitter, antennas and power before any internal work.
The capture loop runs on ESP32 core 1 at 240 MHz. It samples GPIO_IN_REG 110 CPU cycles after LCD E is observed high and combines two 4-bit transfers into one command or data byte. The decoder tracks visible DDRAM addresses, CGRAM address writes, entry direction and all eight custom characters.
Networking and housekeeping run on core 0. The browser requests the next snapshot only after the previous response, so slow Wi-Fi or a VPN cannot build a queue of obsolete screens. Button commands are sent immediately.
The browser applies layout normalization only to the recognized FWD=/REF= meter screen. Tuning bars, L/C screens, Setup menus and service screens remain direct LCD copies.
firmware/MFJ993B_Remote_Control/MFJ993B_Remote_Control.ino Main firmware
tools/LCD1602_CGRAM_Terminal_110/ Serial diagnostic firmware
docs/wiring.md Wiring and electrical safety
docs/hardware.md Measured bus behavior and interface circuit
docs/controls.md Buttons and combinations
docs/protocol.md LCD capture and WebSocket protocol
docs/firmware-update.md Browser firmware-update procedure
docs/wifi-setup.md Wi-Fi fallback and recovery procedure
docs/images/ Interface screenshots and wiring diagram
CHANGELOG.md Notable firmware changes
platformio.ini Reproducible PlatformIO build
.github/workflows/build.yml Automatic build check
LICENSE MIT license
| LCD signal | ESP32 GPIO |
|---|---|
| E | 17 |
| RS | 4 |
| DB4 | 25 |
| DB5 | 18 |
| DB6 | 19 |
| DB7 | 23 |
| Bit | Control | ESP32 GPIO | UI behavior |
|---|---|---|---|
| 0 | ANT | 14 | Latched |
| 1 | C-UP | 26 | Momentary/hold |
| 2 | L-UP | 27 | Momentary/hold |
| 3 | AUTO | 33 | Latched |
| 4 | MODE | 13 | Momentary/hold |
| 5 | C-DN | 2 | Momentary/hold |
| 6 | L-DN | 5 | Momentary/hold |
| 7 | TUNE | 21 | Momentary/hold |
| 8 | POWER | 32 | Latched; physical output is inverted |
See Wiring before making any connection.
Do not connect a 5 V LCD signal directly to an ESP32 GPIO. The reference build uses a 74LVC244A powered from 3.3 V on RS, E and DB4-DB7. Both active-low output-enable inputs are held low and a 100 nF bypass capacitor is placed close to the IC.
Do not connect push-pull ESP32 outputs directly to the tuner's switch nets. The reference build uses one PC817 channel per physical button and another isolated channel feeding a proper power-relay driver. A PC817 must not drive a conventional relay coil directly.
Disconnect the transmitter, antennas and DC power before opening the tuner. Never work inside it while transmitting. Follow all warnings and service conditions in the MFJ manual.
- Install Arduino IDE.
- Install the stable Arduino core for ESP32 using Boards Manager.
- Install these libraries using Library Manager:
- Open
firmware/MFJ993B_Remote_Control/MFJ993B_Remote_Control.ino. - Select the matching classic ESP32 board and a 240 MHz CPU frequency. The tested PlatformIO target is
esp32dev. - Perform the first upload through USB. Serial Monitor speed is 460800 baud.
- If the saved Wi-Fi cannot be reached, connect to
MFJ993b-CONFIGwith password12345678. - Open
http://192.168.4.1/, enter the target Wi-Fi credentials and wait for restart. - Open the assigned LAN IP in a browser.
The current firmware does not require an Arduino IDE network port, mDNS, UDP invitation or port 3232.
- In Arduino IDE choose Sketch → Export Compiled Binary.
- Open
http://<ESP-IP>/updateor click Firmware Update (.bin) on the control page. - Select only the main file ending in
.ino.bin. - Do not select
bootloader.bin,partitions.binor a merged image. - Keep power and network connectivity until the progress reaches 100%. The ESP32 restarts automatically.
- Reload the main page with
Ctrl+F5if the browser retained an older embedded page.
The same HTTP method works through a routed VPN when the ESP32 address and TCP port 80 are reachable. Detailed instructions and file locations are in Firmware update.
Wi-Fi fallback access-point behavior is documented in Wi-Fi setup and recovery.
From the repository root:
pio runThe environment pins:
espressif32@6.12.0- board
esp32dev - CPU frequency 240 MHz
ESP32Async/AsyncTCP@3.5.0ESP32Async/ESPAsyncWebServer@3.12.0
The main image is generated as .pio/build/esp32dev/firmware.bin. GitHub Actions runs the same build on every push and pull request and publishes MFJ993B_Remote_Control.ino.bin as the MFJ993B-Remote-Control-firmware workflow artifact, ready for the browser update page.
tools/LCD1602_CGRAM_Terminal_110/LCD1602_CGRAM_Terminal_110.ino is a standalone test sketch, not the normal web firmware. It prints captured DDRAM, active CGRAM slots, 5x8 matrices and diagnostic counters to Serial Monitor at 460800 baud. Sending P performs a controlled tuner POWER OFF → ON cycle to capture LCD initialization.
The control page, Wi-Fi configuration form, WebSocket and firmware-update page do not require authentication. Use this device only on a trusted LAN or trusted VPN. Do not expose TCP port 80 directly to the public Internet. Change the configuration AP password in the source before deployment.
- MFJ-993B product page
- MFJ-993B instruction manual, version 2B (PDF)
- MFJ-991B/993B/994B/995 Rev. 2 schematic (PDF)
- MFJ-998 product page
- MFJ-998 instruction manual, version 1G (PDF)
- MFJ-998 Rev. 1A schematic (PDF)
- Hitachi HD44780U data sheet (archived PDF)
- Texas Instruments SN74LVC244A data sheet
- Sharp PC817XxNSZ1B data sheet
- Espressif ESP32 Series data sheet
- Arduino core for ESP32 documentation
- Espressif browser OTA update guide
- ESP32Async/ESPAsyncWebServer
- ESP32Async/AsyncTCP
- PlatformIO ESP32 Dev Module
Project source and original documentation are released under the MIT License.
MFJ, MFJ-993B, IntelliTuner and other MFJ product names are trademarks of their respective owner. This independent community project is not affiliated with or endorsed by MFJ Enterprises. MFJ manuals and schematics are not redistributed in this repository; the links above point to external copies.
Неофициальный сетевой пульт для антенного тюнера MFJ-993B на ESP32 с зеркалом штатного LCD 16x2 в браузере.
ESP32 пассивно считывает шину дисплея, восстанавливает DDRAM и динамические символы CGRAM, отдаёт веб-интерфейс и через внешний ключевой каскад имитирует девять кнопок передней панели.
Статус: экспериментальная прошивка для конкретной аппаратной сборки. Перед подключением обязательно проверьте уровни, полярность и распиновку своего устройства.
- LCD 16x2 в браузере, включая пользовательские символы и бегущие шкалы.
- На основном экране частота,
MHz, КСВ,FWD=иREF=закреплены за постоянными знакоместами. - Ошибочный байт не сдвигает весь основной экран и не стирает последнее корректное значение.
- Три CGRAM-значка основного экрана меняются только после двух одинаковых снимков; промежуточная построчная перерисовка не показывается.
- CGRAM больше не задерживает обновление частоты, КСВ, прямой и отражённой мощности.
- ANT, C-UP, L-UP, AUTO, MODE, C-DN, L-DN, TUNE и POWER.
- Удержание MODE/TUNE/C/L без программного автоотпускания.
- Дополнительные сочетания и сервисные операции при включении.
- Первичная настройка Wi-Fi через точку доступа.
- Один LCD-запрос в полёте — старые кадры не накапливаются даже через VPN.
- Опрос каждые 20 мс, при удержании кнопки — каждые 100 мс.
- Загрузка основной прошивки
.ino.binпрямо из браузера через/update.
PIC16F76 соединён с совместимым с HD44780 дисплеем LCD1602 по 4-битной шине RS, E, DB4…DB7. На проверенном тюнере в паузе E имеет низкий уровень, остальные наблюдаемые линии — высокий. PIC передаёт команды и изменившиеся данные короткими пакетами, а не повторяет весь экран постоянно: состояние DDRAM и CGRAM хранится самим контроллером LCD.
Измеренная длительность высокого уровня E — около 520 нс. Остальные линии устойчивы примерно 1–2 мкс; короткий переходный звон до 0,5 В длится лишь 10–20 нс. По протоколу LCD фиксирует записываемые данные по спаду E, а ESP32 делает одну одновременную выборку линий после задержки 110 тактов CPU.
Шесть сигналов LCD проходят через 74LVC244A с питанием 3,3 В. В обратном направлении восемь выходов ESP32 включают PC817, распаянные параллельно штатным кнопкам. Девятая PC817 управляет отдельным драйвером реле питания. Поэтому веб-интерфейс может нажимать обычные кнопки, удерживать их и выполнять комбинации настроек, тестов и сброса.
Полное описание измерений и электрической части: docs/hardware.md.
К MFJ-998 можно применить общий принцип этого проекта, но не готовую прошивку и не текущую распиновку целиком. В найденных открытых материалах MFJ модель обозначена как MFJ-998 без суффикса B. Если на конкретном устройстве указано MFJ-998B, сначала необходимо найти или снять схему именно его ревизии платы.
На опубликованной схеме MFJ-998 Rev. 1A дисплей WH1602B подключён к PIC18F2520 по тем же линиям RS, E, DB4…DB7. Поэтому пассивное считывание LCD через 5-вольт-совместимый входной буфер 74LVC244A технически применимо.
Но отдельно потребуется проверить и изменить:
- времена сигналов, уровни в паузе, задержку выборки и работу CGRAM;
- разметку экранов и парсер — в MFJ-998 встречаются четырёхзначные значения мощности;
- все GPIO ESP32 и физические точки пайки;
- управление восемью кнопками MFJ-998, у которого нет отдельной кнопки AUTO;
- полярность кнопочных цепей, ориентацию PC817, включение питания и сочетания кнопок.
Подключать эту сборку к MFJ-998 без измерений и доработки исходника нельзя. Поскольку это тюнер предельной мощности, перед вскрытием необходимо отключить усилитель, трансивер, антенны и питание.
- Установите Arduino IDE.
- Через Boards Manager установите стабильный Arduino core for ESP32.
- Через Library Manager установите ESPAsyncWebServer и AsyncTCP.
- Откройте
firmware/MFJ993B_Remote_Control/MFJ993B_Remote_Control.ino. - Выберите классическую ESP32 с частотой CPU 240 МГц и выполните первую прошивку по USB.
- Если домашняя сеть недоступна, подключитесь к
MFJ993b-CONFIG, пароль12345678. - Откройте
http://192.168.4.1/, сохраните SSID и пароль сети. - После перезапуска откройте новый IP ESP32 в браузере.
- В Arduino IDE выберите Скетч → Экспорт бинарного файла.
- На странице управления нажмите Firmware Update (.bin) либо откройте
http://<IP-ESP>/update. - Выберите только основной файл
*.ino.bin. - Не выбирайте
bootloader.bin,partitions.binиmerged.bin. - Дождитесь 100% и автоматической перезагрузки ESP32.
- После обновления страницы используйте
Ctrl+F5, если браузер показывает старый интерфейс.
Сетевой порт Arduino IDE, mDNS и порт 3232 этой версии не нужны. Обновление выполняется обычным HTTP-запросом и может работать через маршрутизируемый VPN. Подробности: docs/firmware-update.md.
- Аппаратная реализация, измерения и схема
- Подключение и безопасность
- Кнопки и сочетания
- Захват LCD и протокол WebSocket
- Обновление прошивки через браузер
- Настройка и восстановление Wi-Fi
Диагностический скетч tools/LCD1602_CGRAM_Terminal_110/LCD1602_CGRAM_Terminal_110.ino является отдельной тестовой прошивкой без основного веб-пульта.
Веб-пульт, настройка Wi-Fi, WebSocket и страница обновления не имеют авторизации. Используйте устройство только в доверенной локальной сети или через доверенный VPN и не публикуйте TCP-порт 80 в Интернет.
Проект распространяется по лицензии MIT и не связан с MFJ Enterprises.



