ESP32 Dual-Fuel HVAC Controller With Android Monitoring — V5.3.0 FINAL
by spartiduck in Circuits > Microcontrollers
22 Views, 0 Favorites, 0 Comments
ESP32 Dual-Fuel HVAC Controller With Android Monitoring — V5.3.0 FINAL
This project adds an ESP32 supervisory controller to an existing gas furnace and a Senville/Midea-compatible mini-split, while keeping the wall thermostat in charge of heating, cooling, and fan demand.
The current release pairs ESP32 firmware v5.3.0 FINAL with Android UI16-FINAL. GAS PRIMARY is the default heating strategy, with supervised emergency heat-pump backup if a sustained gas call fails to warm the house. HP PREFERRED remains available as an optional strategy.
The controller senses thermostat W, Y, and G through optocouplers, controls the mini-split through local UART, and uses two furnace-side relay functions: a normally-closed W bypass and a blower G relay. A local web interface and Android app provide operating status, settings, room temperatures, alarms, and event history.
Loss of controller or relay power releases the bypass contact and restores the ordinary thermostat-W-to-furnace-W path. This is a DIY retrofit for a specific installation; all factory furnace safety circuits must remain intact.
DRAFT STATUS: Public-safe source downloads and selected project images are included. Source behavior was checked against v5.3.0 FINAL / UI16-FINAL. Physical wiring and relay/reset behavior, current final-build screenshots and reproducible build versions remain UNVERIFIED.
IMAGE: The cover is a generated project illustration, not a photograph of the installed controller. Older dashboard screenshots are labeled as development images.
Supplies
Main controller
• ESP32 development board suitable for the configured GPIO pins.
• Independent regulated USB 5 V supply and cable.
• Three H11AA1 optocoupler input circuits for thermostat W, Y, and G.
• Two usable relay channels: W bypass with COM/NC contacts, and furnace blower G with COM/NO contacts.
• Suitable UART level conversion for the mini-split interface.
• Local DHT22 sensor on GPIO26.
• Prototyping board, removable headers, terminals, enclosure, labels, and strain relief.
Optional room nodes
• ESP8266 or ESP32-based room sensor nodes with DHT22 sensors.
• Up to five remote room slots in addition to the local sensor.
Software and tools
• Arduino IDE with ESP32 board support, the compatible MideaUART library, and DHT sensor dependencies.
• Existing Android Studio HVAC Control project for the UI16 file update.
• Multimeter, soldering equipment, and equipment service documentation.
VERIFY HARDWARE: The final firmware is configured for active-LOW relay inputs. The earlier article's active-HIGH instructions must not be reused without checking the actual relay board. Optocoupler resistor sizing, connector pinouts, level conversion, and protection components must be documented from the installed hardware.
VERIFY BUILD: Exact board-core/library and Android SDK/Gradle versions are not established in this draft. The UI16 download is an update bundle, not a standalone Android Studio project or installable APK.
Understand the Fail-Safe and Heating Strategies
The thermostat remains in charge of room-temperature demand. R and C are the normal furnace control supply; W requests heat, Y requests cooling, and G requests the blower.
The thermostat W conductor passes through COM and NC on the bypass relay before reaching furnace W. When the bypass relay is de-energized, the NC contact closes and the furnace receives the thermostat's W call directly. The furnace retains responsibility for inducer, ignition, gas valve, limits, and its normal blower timing.
The separate blower relay connects furnace R through COM and NO to furnace G when the heat pump needs central air circulation. Thermostat Y and G remain directly connected to the furnace during ordinary cooling/fan operation.
GAS PRIMARY is the default software strategy. A normal heat call uses gas. HP PREFERRED allows eligible heat calls to use the mini-split instead. The first v5.3.0 deployment performs a one-time selection of GAS PRIMARY; later user mode changes persist normally.
GAS PRIMARY still permits supervised emergency HP backup following a gas-performance fault. It must not be described as a mode that permanently disables the heat pump.
VERIFY HARDWARE: The Step 2 reference shows source configuration and contact routing. A current photograph and checked as-built schematic of the installed relay module are still needed. Preserve all factory equipment safeties.
Build and Verify the ESP32 Inputs and Relay Outputs
The configured GPIO map in v5.3.0 FINAL is:
Senville UART RX: GPIO16
Senville UART TX: GPIO17
Thermostat W sense: GPIO27
Thermostat Y sense: GPIO32
Thermostat G sense: GPIO14
Furnace blower relay: GPIO23
W bypass relay: GPIO25
Local Furnace Room DHT22: GPIO26
GPIO18 and GPIO19 are retired in this two-relay arrangement. The existing four-channel board uses IN3 for the blower and IN4 for the W bypass.
Three H11AA1 optocoupler circuits isolate the thermostat's AC signals from the ESP32 inputs. The firmware validates AC pulse width and repetition, then uses a five-second majority vote to form the logical W/Y/G states. Brief input changes are not instantaneous demand changes.
Relay polarity matters. The final source sets both G_RELAY_ACTIVE_LOW and BYPASS_RELAY_ACTIVE_LOW to true. With matching active-LOW relay hardware, GPIO23 LOW energizes the blower relay and HIGH releases it. GPIO25 LOW energizes the bypass relay, opening the NC W path; HIGH releases the relay and closes the NC W path.
IMAGE: Revised low-voltage connection reference for v5.3.0 FINAL. Both relay channels are labeled active LOW to match the final source. This is not a verified as-built schematic.
VERIFY HARDWARE: Confirm the installed board’s trigger polarity and boot/reset behavior before connecting furnace controls. Optocoupler package pinout, resistor values and ratings, pull-ups, sensor supply and level conversion need physical confirmation. Do not reuse the earlier active-HIGH tests or pull-down recommendation.
Connect UART and Understand Link Supervision
The mini-split is controlled over a local Midea-style UART. The project uses ESP32 GPIO16 for RX and GPIO17 for TX. The interface connector and voltage levels must be checked for the exact indoor unit before connection.
Normal Midea C0 state reports are the authoritative control-status source. The final firmware accepts status up to 10 seconds old. Between 10 and 20 seconds old, the link remains usable only while UART traffic has arrived within the previous 5 seconds. C0 status older than 20 seconds is unusable regardless of other UART bytes.
Engineering polling reads Groups 1, 2, 5, and 7 for model-dependent temperatures, compressor data, fan information, and other diagnostics. Group-1 data also supports stable idle T3 learning and heat-pump performance supervision, so these readings are not all diagnostic-only. Engineering polling yields when normal status ages.
When a heat-pump call needs to hand over to gas, the controller requests HP OFF and uses OFF confirmation plus settling before normal restoration of the gas path. Do not equate a UART timeout with an immediate, confirmed mechanical changeover.
IMAGES: Supplied UART level-converter photo, followed by a development screenshot from earlier firmware illustrating engineering diagnostics. The screenshot is not evidence of v5.3.0 FINAL behavior.
VERIFY HARDWARE/BUILD: Confirm connector pin order, electrical levels, baud settings and compatible MideaUART release. The public-safe controller copy corrects the stale copied-sensor version label to 5.3.0 FINAL.
Configure and Flash V5.3.0 FINAL
Download HVAC_ESP32_FINAL_v5_3_0_PUBLIC_SAFE.ino from Step 8. Put it in a folder named HVAC_ESP32_FINAL_v5_3_0_PUBLIC_SAFE and open it in Arduino IDE. This public source edition was prepared from HVAC_ESP32_FINAL_v5_3_0.ino. Its runtime firmware version is 5.3.0 FINAL.
In Arduino IDE, select Huge APP (3MB No OTA / 1MB SPIFFS) for this release. The data partition is used by LittleFS for stored events despite the SPIFFS wording in the partition menu. Keep the controller on its independent normal USB supply rather than powering it from the mini-split supply.
Replace WIFI_SSID and WIFI_PASSWORD with your own values locally. Weather is disabled in the public edition until you configure WEATHER_LOCATION_NAME, WEATHER_LAT, WEATHER_LON and URL-encoded WEATHER_TIMEZONE_URL, then set WEATHER_CONFIGURED=true. Weather alerts additionally require the correct WEATHER_ALERT_BBOX and WEATHER_ALERTS_ENABLED=true; the original alert feed is Canada-specific.
Remote app access is disabled by REMOTE_APP_ENABLED=false. Leave it disabled for LAN use. If you enable it, use your own unique credentials and separately secured transport. Never distribute your configured source. See README_PUBLIC_SAFE.md.txt for all public-source changes and setup notes.
First-flash defaults are an HP lockout of −5 °C and a maximum HP heat-call duration of 25 minutes. Valid saved settings can differ and normally survive an upgrade. Lockout accepts −20 to +15 °C; maximum duration accepts 5–120 minutes. Personal settings such as −14 °C or 30 minutes must be labeled as examples rather than firmware defaults.
On the first v5.3.0 deployment, GAS PRIMARY is selected once. Later strategy changes are remembered normally. Stored event history is intended to survive ordinary sketch uploads; a full-flash erase removes it.
VERIFY BUILD: Record the board model, ESP32 board-core version, library versions, and successful compile/upload procedure before publication. This draft does not claim a new hardware flash or compile test.
Weather, Heat-Pump Lockout, and Performance Backup
For a NEW HP PREFERRED W call, fresh Internet weather is the preferred outdoor reference. If weather is unavailable or stale, the controller may use a stabilized idle T3 outdoor-coil reference. Running coil temperature is not treated as ambient air temperature. If neither reference is valid, the new call uses gas.
The outdoor-lockout decision stays fixed for the current W call. Losing Wi-Fi or weather, or seeing a changed outdoor reading, does not itself switch an already-running heat-pump call to gas. UART health, performance supervision, and the maximum runtime still remain active. Once a call has fallen back to gas, normal logic keeps it on gas for the remainder of that heat call.
The heat-pump target is 30 °C in heating and 17 °C in cooling; the wall thermostat still owns room demand. HP PREFERRED requires an armed controller and usable UART status. Selecting the strategy during an active W call does not guarantee an immediate HP takeover.
The gas watchdog evaluates valid whole-house average readings during a sustained gas call. In this build, a rise of less than 0.2 °C after 15 minutes triggers the gas-performance fault and emergency HP sequence. Furnace W is isolated and a 90-second settling interval precedes emergency HP operation. Emergency backup can bypass the normal outdoor lockout but still needs usable UART control.
This is a temperature-response heuristic, not a burner or flame sensor. Missing house readings do not prove a gas failure, and an emergency request does not guarantee successful heating at every outdoor temperature.
VERIFY RUNTIME: Add dated final-build logs showing ordinary gas heat, optional HP heating, weather loss, and controlled handoff.
IMAGES: Weather/house dashboard and cooling-call screenshots from earlier development firmware. They illustrate the interface only; their labels, defaults and readings must not be treated as final-build verification.
Room Sensors, Alarms, and Event History
The controller supports a local DHT22 named Furnace Room plus up to five remote room slots. Remote readings are identified and assigned by node identity. Seen remote sensors become stale after five minutes without an update and are excluded from the active average.
The controller provides mDNS and UDP discovery support. That does not establish that every node firmware reconnects reliably after Wi-Fi loss. Node firmware and its reconnect/reboot hardening are separate from the v5.3.0/UI16 package.
First-flash house alarm defaults are 16 °C low and 28 °C high. Ordinary room defaults are 15 °C low and 30 °C high; the critical room-low default is 10 °C. Ordinary high/low alarms use a ten-minute confirmation and 0.5 °C hysteresis. Critical-low logic is separate. Saved user thresholds can differ.
Current event history is held in RAM, with 160 entries. Separate LittleFS stored history trims from more than 400 records to the newest 300. Stored records include event ID, boot ID, uptime, severity, message, and wall-clock time when NTP has synchronized. Early boot records may have only boot number and uptime. Filesystem mount failure can leave RAM logging only.
GET /api/events returns current events. GET /api/events/stored?limit=200 returns stored events. POST /api/events/clear and POST /api/events/stored/clear clear the corresponding histories separately. The stored API accepts a limit of 1–300.
Temperature history is a different feature: the rolling graph remains in RAM and clears on reboot. The Android app has CURRENT and STORED event views; the reviewed web log uses current events.
NODE DOWNLOADS: Step 8 includes the earlier public ESP8266 v3.1 and ESP32-CAM v1.1 sensor-node sources separately. They are legacy node versions, not new v5.3.0 builds. Edit their Wi-Fi placeholders locally; optional fallback is disabled by default.
VERIFY NODES: Board-specific wiring, reporting intervals, build compatibility and reconnect/reboot behavior still need checking. No reconnect hardening is claimed.
Install Android UI16-FINAL and Background Monitoring
UI16-FINAL is paired with controller firmware v5.3.0 FINAL. The public-safe download in Step 8 supplies MainActivity.kt.txt, HvacMonitorService.kt.txt, HvacBootReceiver.kt.txt, PublicConfig.kt.txt and AndroidManifest_Install_Guide.txt. It is an update to an existing Android Studio project, not a complete project or an APK.
Remove the final .txt suffix from the four Kotlin downloads. Replace MainActivity.kt, HvacMonitorService.kt and HvacBootReceiver.kt in package com.hvaccontrol.app, and add PublicConfig.kt in that same package. Copy only the XML block from AndroidManifest_Install_Guide.txt into the app’s AndroidManifest.xml; omit the surrounding text and code fences. Use all five files together, then clean, rebuild and run in your existing compatible HVAC Control project. The expected Settings version text is “App UI16-FINAL · Controller v5.3.0 FINAL.” Configure your own LAN endpoint in PublicConfig.kt. Its example LAN address is not your installation address. The shared configuration is used by both the activity and monitoring service; remote fallback is disabled by remoteEnabled=false.
Allow notifications and set app battery use to Unrestricted. Use SEND TEST NOTIFICATION to check delivery. The foreground monitor checks about every 30 seconds and issues a controller-offline alert after about two minutes of failed monitoring. Actual timing depends on Android scheduling, connectivity, and notification permission.
The monitor reports LOCAL, REMOTE, or OFFLINE. It tries its last working route, then the configured local address and UDP discovery. Authenticated remote fallback is attempted only when PublicConfig.remoteEnabled is enabled. It monitors faults and recoveries while the app is in the background. The boot/update receiver starts monitoring when notifications are enabled.
The app provides normal strategy/settings controls, room alarm editing, and separate CURRENT/STORED event views. Normal remote app operations require authentication; service/manual relay controls remain LAN-only in the firmware.
Remote access currently uses HTTP Basic over plain HTTP. Authentication does not encrypt the traffic; using port 18443 does not make it HTTPS. VPN/HTTPS transport is not implemented by this release. Do not publish private endpoint settings or credentials.
VERIFY APP: Add current version, mode-control, alarm-editor, event, and monitor screenshots. Exact SDK/Gradle requirements, install/signing instructions, and notification/reboot tests remain to be recorded.
Commission the Installation and Prepare Downloads
Commission one function at a time with furnace control wiring isolated until the individual circuits have been verified.
1. Check the actual relay polarity and confirm the de-energized COM/NC bypass closes the thermostat W path.
2. Verify optocoupler diagnostics and completed W/Y/G input votes against real thermostat calls.
3. Verify the matching active-LOW blower relay energizes on GPIO23 LOW and releases on HIGH.
4. Establish UART status and controlled OFF/FAN/COOL/HEAT operation using the exact unit's documentation.
5. Test normal GAS PRIMARY heating and thermostat-controlled cooling/blower operation.
6. Select HP PREFERRED with W idle and usable UART status; verify eligible HP heat uses the open bypass and blower relay.
7. Verify active HP heat continues through Wi-Fi/weather loss, and a new HP-preferred call uses gas when neither outdoor reference is valid.
8. Verify UART/runtime/performance faults and controlled changeover without bypassing factory safety devices.
9. Verify CURRENT and STORED histories across a normal controller reset and their separate clear actions.
10. Verify foreground/background notifications, LOCAL/REMOTE/OFFLINE indication, and room-node recovery separately.
DOWNLOADS — PUBLIC SOURCE EDITION
The attached controller sketch and UI16 source update were prepared from the current final baseline. Private credentials and endpoints were replaced, stale version labels corrected, and configuration guards added. Weather and WAN access are disabled until configured. No HVAC control algorithm change is intended; key control-function bodies were compared against the original baseline.
Start with README_PUBLIC_SAFE.md.txt. The controller download is HVAC_ESP32_FINAL_v5_3_0_PUBLIC_SAFE.ino. The four Kotlin files have a final .txt suffix for site compatibility; remove that suffix before use. AndroidManifest_Install_Guide.txt contains the manifest XML to copy. Two legacy remote-node sketches, image captions and validation notes are also attached. This is source, not an APK or a complete Android Studio project.
IMAGES
The generated cover, revised editable wiring reference, supplied UART photo and older dashboard screenshots are included. Development screenshots are labeled in their steps. The download package includes the editable SVG and PNG reference. A current installed-controller photograph, component close-ups, partition-setting capture and actual v5.3.0/UI16 screenshots remain to be added.
VERIFY BEFORE PUBLICATION: Full Arduino and Android builds, precise dependencies, hardware/reset tests, room-node recovery and notification tests remain unverified. This draft documents checked source behavior and publication preparation; it does not claim a newly tested binary or universal equipment compatibility.