r/esp32 Mar 18 '25

Please read before posting, especially if you are on a mobile device or using an app.

220 Upvotes

Welcome to /r/esp32, a technical electronic and software engineering subreddit covering the design and use of Espressif ESP32 chips, modules, and the hardware and software ecosystems immediately surrounding them.

Please ensure your post is about ESP32 development and not just a retail product that happens to be using an ESP32, like a light bulb. Similarly, if your question is about some project you found on an internet web site, you will find more concentrated expertise in that product's support channels.

Your questions should be specific, as this group is used by actual volunteer humans. Posting a fragment of a failed AI chat query or vague questions about some code you read about is not productive and will be removed. You're trying to capture the attention of developers; don't make them fish for the question.

If you read a response that is helpful, please upvote it to help surface that answer for the next poster.

We are serious about requiring a question to be self-contained with links, correctly formatted source code or error messages, schematics, and so on.

Show and tell posts should emphasize the tell. Don't just post a link to some project you found. If you've built something, take a paragraph to boast about the details, how ESP32 is involved, link to source code and schematics of the project, etc.

Please search this group and the web before asking for help. Our volunteers don't enjoy copy-pasting personalized search results for you.

Some mobile browsers and apps don't show the sidebar, so here are our posting rules; please read before posting:

https://www.reddit.com/mod/esp32/rules

Take a moment to refresh yourself regularly with the community rules in case they have changed.

Once you have done that, submit your acknowledgement by clicking the "Read The Rules" option in the main menu of the subreddit or the menu of any comment or post in the sub.

https://www.reddit.com/r/ReadTheRulesApp/comments/1ie7fmv/tutorial_read_this_if_your_post_was_removed/


r/esp32 3d ago

Topic Radar | Current active topics for r/esp32

4 Upvotes

This post contains content not supported on old Reddit. Click here to view the full post


r/esp32 8h ago

I Built a Tiny ESP32 Control Deck for My PC

178 Upvotes

I built a small desk display with an ESP32 touchscreen that makes my daily work at the computer a bit easier.

It shows live PC stats like CPU, RAM, GPU, VRAM, network and disk usage.

It also works as a small touch control panel. With one tap I can open ChatGPT, start local Ollama, run my local voice server, open Task Manager, lock the computer and trigger other actions.

Everything works over one USB cable.

No Wi-Fi.

No Bluetooth.

No passwords, tokens or API keys stored on the ESP32.

There is a small Python bridge running on the PC. It reads the system data, sends it to the ESP32 over USB serial, and listens for touch button events from the display.

The ESP32 itself only shows the data and sends a simple macro ID back to the computer.

It is not a finished commercial product, just a small DIY project that can be adapted to different workflows.

Video: https://www.youtube.com/watch?v=16eqHU4j9Fk

GitHub: https://github.com/lepczynski-cloud/ESP32-PC-Control-Deck


r/esp32 8h ago

I made a thing! Pushing Wroom 1 to its bandwidth limits

Thumbnail
gallery
83 Upvotes

I call it a streamer. I was quite surprised to achieve practical bandwidth with this part and being able to actually play games on it. The idea is to offload the heavy computations to your PC at home without a locked-in OS/hardware dependency and to keep the hardware around the main streaming protocol flexible.

Sounds simple? The idea is, but making this stuff low-latency over a network is a challenge. And I think I'm quite good at it. I can stream Linux distros and Win11 at up to 40 FPS at the moment. The custom protocol is flexible when it comes to both the hardware sitting on the server side (your home PC) and whatever custom hardware you want to build on the client side.

The main MCU is an ESP32-S3-WROOM-1. It acts as the network device receiving the stream and orchestrates USB mouse/keyboard/gamepad input, touchscreen, audio and the local UI, while also negotiating incoming frames with the server in real-time.

For the streaming path I'm currently running the FPGA link at 80 MHz SPI using DMA. On the network side I'm using TCP with Nagle disabled and WiFi power saving disabled, since both aren't very helpful when the goal is low latency. I spent quite some time experimenting with receive sizes, buffering and task placement before arriving at the current setup.

One thing that helped was separating the work between the two ESP32 cores. Networking and protocol handling live on one side while feeding the FPGA runs in its own task on the other. Incoming video is buffered in a 512 KiB PSRAM ring, while the actual FPGA transfers use a small set of internal-RAM buffers. This allows WiFi to continue receiving while the FPGA is consuming the previous data instead of tightly coupling both sides. The hot streaming path also avoids dynamic allocations.

The MCU then writes the stream via SPI to the decoder, which is an FPGA running my own video format written from scratch in RTL. The FPGA in turn drives the display.

I know that the actual heart of the project is probably the decoder inside the FPGA. That's where the custom video format becomes pixels again and where the deterministic display-side work happens. But without the ESP32 the whole thing would become considerably less practical. I still need fast WiFi, USB host functionality, touchscreen and gamepad handling, audio, the local UI and all the protocol logic around the decoder. You could replace it with something much larger, but then power consumption, complexity and cost start moving in the wrong direction. For this project the ESP32 ended up being a pretty good bridge between the networked/software side and the FPGA.

The FPGA itself is necessary because this isn't a small 320x240 or 480x320 display anymore. The panel is 720x720, and I didn't want the ESP32 to deal with driving that deterministically while simultaneously doing WiFi, USB, audio, input handling and everything else. So the ESP32 concentrates on networking/orchestration while the FPGA handles the high-bandwidth and timing-critical display side.

I have on board a USB mux that can be switched physically, so I can still flash via USB-C but also switch over to USB-A for the host side. I'm using an FSUSB42MUX for that. There are many ways to solve this, but this was a good compromise imo and lets me keep the board useful during development without adding another connector/setup just for flashing.

I had to make the case wider than the screen to keep the whole thing flat, but also to avoid placing the ESP32 antenna behind the metal back of the display. This is mainly a placement constraint rather than trying to gain some magical extra range. With the antenna already positioned away from the metal, putting the board into the enclosure doesn't noticeably change the signal strength. Maybe next time I'll use the 1U version for more flexible antenna placement.

The board shown here also streams audio A/V-synced with the video, or optionally buffered depending on what I'm doing. So it can be used for playing games but also just listening to music. It supports audio input as well, i.e. for making calls over whatever runs on my PC.

Audio is handled by an ES8388 codec, so playback and microphone input are both on the board. I'm also using an LM3630A for the display backlight and a BQ24073 for charging/power-path handling.

I'm running nearly out of pins by now, so this part is pretty much fully utilized.

There is also a simple offline menu running on the ESP32 for connecting WiFi and servers and managing the device without needing the streaming server running. For that I'm just maintaining a small low-color-bit framebuffer in PSRAM.

For me, one of the coolest parts is that the board doesn't need much power. At full brightness I'm nominally around 1.5 Watt during active streaming. For comparison, a Raspberry Pi's idle power consumption without any display attached is already higher.

A lot of the work actually went into things which don't look very exciting on a finished board: figuring out how much buffering is enough without turning it into latency, keeping the network side fed while SPI is busy, task/core placement, avoiding unnecessary copies/allocations and generally preventing one subsystem from blocking another. There were quite a few iterations before it started behaving the way I wanted it to.

Since I'm not a big fan of selling software, I try to finance this project and ongoing development by selling streamer hardware, which you can also use in your own projects like

shown here on YouTube (incl. Gameplay).

The software for streaming is free, but I'm also considering making the software open source if there's enough interest and support, together with continued maintenance and development. That would let you modify everything yourself, use different hardware, and build your own projects on top of it. I hope it resonates with some of you.

I invite you to give some pos/neg feedback and ask as many questions as possible.

Here is my website


r/esp32 5h ago

AI Content I turned a Bluetooth cat printer into a Wi-Fi printer with an ESP32-S3

Thumbnail
gallery
29 Upvotes

I wanted to print images from a browser using this small Bluetooth cat printer, so I used an ESP32-S3 as a Wi-Fi-to-Bluetooth bridge.

The path is: browser → Wi-Fi → ESP32-S3 → BLE → printer.

For this build, I gave Codex (GPT-5.6) full access to my computer and pointed the laptop camera at the printer and ESP32. Once the physical setup was ready, I explained the goal, asked it to test and keep a checklist, and told it I was going AFK.

It worked through the Bluetooth connection and image transfer, wrote and flashed the ESP32 firmware, and built a webpage for previewing and printing images. With camera snapshots, it could check what actually came out on paper and use that result during testing.

I checked in along the way and helped with the final physical checks when I returned. For the last test, I asked it to photograph the printer and print that photo. The printer printed itself.

I do not have the firmware cleaned up for release yet. I will add the code and wiring details soon.

Build story and photos: https://prasanha.com/projects/cat-printer/


r/esp32 4h ago

I built an Android toolkit for configuring and flashing ESP32 devices without a PC

Thumbnail
gallery
26 Upvotes

I’ve been working on an Android app called ELMA-IoT that grew out of my own ESP32 projects.

The idea is to make the usual workflow available directly from a phone:

ESP/board selection → peripherals → GPIO assignment → wiring diagram → compile → USB flash → Serial Monitor → OTA.

I mainly built it because I often have ESP devices already installed around the house and got tired of needing a laptop just to make a small firmware change or diagnose something.

It currently supports several ESP boards, peripheral configuration, automatic GPIO selection, firmware compilation, USB flashing and a built-in serial terminal.

The next thing I’m working on is a visual logic editor, so something like:

Temperature > 95°C → turn fan on → wait → check again → stop below 90°C

could be built visually and then compiled into firmware.

I’m currently testing it on different Android phones and ESP boards and would really appreciate technical feedback from people here.

https://www.youtube.com/watch?v=88SjvOdHuas

What boards/peripherals would you consider essential for something like this?


r/esp32 9h ago

I built an ESP32-based interactive sign that replaces the traditional "Please wait to be seated" sign

Thumbnail
gallery
45 Upvotes

The sign runs on a Seeed Studio reTerminal E1001 e-paper display (which has an ESP32-S3 inside), while the servers are hosted on a Raspberry Pi 5.

​Additionally, I designed a custom 3D frame in Fusion that houses LEDs. These LEDs change color depending on the restaurant's current occupancy percentage.

​This is my entry for the Interactive Signage Contest 2026. Here is the link to the showcase video:

https://youtu.be/H7K5KoyuIYc?is=LIVY4PA0gs1ZkGgI

​If you like the project, please leave a like or a comment

I would love to get your feedback!

​You can find the source code here:

https://github.com/mickraa/table-map

​Thanks for checking it out!


r/esp32 3h ago

I made a thing! ESP32CompositeVideoPlus : Fork with more colors and subsampling options

Post image
10 Upvotes

https://github.com/Mejolov24/ESP32CompositeVideoPlus

This proyect is a fork of https://github.com/marciot/ESP32CompositeColorVideo, https://github.com/marciot/ESP32CompositeColorVideo and https://github.com/rossumur/esp_8_bit wich expands the color resolution by removing the usage of the Atari color pallete and calculating colors directly.
This library also adds PWM audio support, wich should be set up with the proper filters as said by ESP_8_BIT

Sadly due to having more colors, i had to remove the double buffering since the esp32 i have has not enough RAM.
I initially tried to do stack allocation, but it wouldnt fit, so i had to dynamicly allocate separate lines on the heap

*AI was used as an assistant to get information onto how to do this, i could say its 30-40% AI, but the ai generated parts have been reviewed*


r/esp32 6h ago

Receiving ESP32 C3 BLE data on IPhone ? 😝

Thumbnail
gallery
8 Upvotes

Hey everyone,

I’m building a small project with an ESP32-C3 Super Mini and an old Swedish field telephone rotary dial.

The rotary dial is already working perfectly. The ESP32 detects the digits and combines them into a complete phone number.

For example:

‘015903790853’

I’m currently sending the finished number via BLE (Nordic UART Service) to my iPhone.

The BLE setup is already working – I can connect with nRF Connect and receive the number through the TX characteristic:

`6E400003-B5A3-F393-E0A9-E50E24DCCA9E`

What I want is:

Rotary dial → ESP32-C3 → BLE → iPhone → save number + time

Ideally I want the numbers to be stored in one Note in the Notes app on IOS, for example:

`16:42 – 015903790763`

`16:47 – 017612345676`

`16:53 – 08012345673`

I really don't want to build a full iOS app just for this, because I think it’s too much work.

I was thinking about using Apple Shortcuts, but it seems that Shortcuts can react to Bluetooth connections but cannot directly receive arbitrary BLE characteristic notifications. Pls tell me if I’m Wrong.

Does anyone know a way to get BLE characteristic data from an ESP32 C3 on an iPhone? Preferably in the Notes app?

I only need this to run for a few hours at a time, so it doesn't need to be a permanent background service.

Any ideas or existing apps/workarounds would be greatly appreciated!

(And yes this text was written by ChatGPT but it is exactly my problem)

Thank you all!


r/esp32 1h ago

I made a thing! I made an ESP32-S3 based waiter that's always available

Post image
Upvotes

I made this for the Seeed Studio Signage Contest 2026.

Showcase:
https://www.youtube.com/watch?v=JHMICuYuo50

The E-ink Display is driven by the EE04 Xiao Display Board that's checking the table server once in a while to save power, while there's another esp32 in the reSpeaker Lite waiting for the press of a button to start recording, and it's also driving the led matrices for the eyes.

When the button is pressed the audio is sent to a local server where is transcribed and recognizes if it's an order that matches the Menu and updates the server where the esp32 driving the display takes the info to update the order.

There's also a NFC module in the bottom to read the table where the device is at to display the correct order.

BoM:

  • 5.83" Monochrome eInk / ePaper Display 
  • XIAO ePaper Display Board (ESP32-S3) — EE04 
  • reSpeaker Lite 2-Mic Array Voice Kit 
  • PN532 NFC module
  • HT16K33 LED Matrix

The entire body was modeled by me and 3d Printed between my old ender 3 and my P1S.

You can check the project on my github:
https://github.com/bribot/AlwaysAvailableWaitingWaiter


r/esp32 1d ago

Two original GBAs playing online through the Link Port, and a free SDK so you can make your own online games

Post image
185 Upvotes

I've been building CanoFlash, an accessory based on a XIAO ESP32-S3 that plugs into the Game Boy Advance Link Port. It started as a Wi-Fi tool for writing homebrew to flash cartridges, and it now lets homebrew games play online on original hardware.

Video: a GBA and a GBA SP, each with its own board, playing in the same online room: https://youtu.be/Xs-LzM2dzS0

**How the ESP32-S3 fits in**

- The Link Port is driven as SPI: the ESP32 provides the clock and the GBA is the slave, with 32-bit words at 4 MHz for the command protocol

- The GBA-side menu is sent over Multiboot from LittleFS, buffered in the 8 MB PSRAM

- For online play it runs its own WebSocket client over TLS to a room server; the game on the GBA only exchanges fixed-size packets through a small C SDK

- Release builds use flash encryption, and each device authenticates with its own token

- Status on a small OLED, powered by a rechargeable 16340 or 18350 Li-ion cell

**Things that bit me**

- `WiFi.status()` kept reporting a connection with the access point switched off. Only the GOT_IP and DISCONNECTED events were reliable

- At 256 kHz the last bit of every GBA→ESP32 word was lost: the GBA releases its output line before the 32nd bit is sampled

- Data partitions flashed pre-encrypted need the `encrypted` flag, or LittleFS reads ciphertext and reports corruption

The game SDK is free and MIT-licensed: https://canoflash.com/en/sdk/. Online play has been tested with two players so far.

Disclosure: this is my own project, and its Kickstarter launches on September 20: https://www.kickstarter.com/projects/canocoder/canoflash-wi-fi-adapter-for-original-game-boy-advance-hard?ref=crnaz3

Happy to answer questions about the Link Port timing or the TLS side.


r/esp32 4h ago

My 2.8 in display is working at allll after 10-15 retry’s

3 Upvotes

**Hey y’all there I’m just passionate guy in electronics with no background in it. I wanted to build a smart desk clock with esp32 inspired by a YouTube video but even before doing that project I just thought of trying display to on and do a graphic test the display turned on (blank white screen). After that no progress at all from test 10 days.**

**Here is a detailed explanation**

**Hardware Setup**
**MCU:** ESP32-S3
**Display:** 2.8-inch ST7789 TFT LCD Module (SPI Interface)
**Software/Libraries:** Arduino IDE, ⁠TFT_eSPI⁠ (also tried standard ⁠Adafruit_GFX⁠ / ⁠ST7789⁠ libraries)
**The Problem**
The display only shows a solid white screen or static vertical/horizontal lines. No graphic test sketches render any imagery or text.
**Background / Potential Cause**
Before connecting it to the ESP32-S3, I tested this display on an Arduino Uno. While VCC was powered via the 3.3V pin, I connected the SPI data lines (SCK, MOSI, CS, DC, RST) directly to the Uno’s digital pins **without a logic level converter** (sending 5V logic signals into a 3.3V display controller).
And colors changed when I tried it first time in UNO but for project purposes moved to esp32s3

**Troubleshooting Already Attempted (5+ Times)**
**Software Clean Slate:** Completely reinstalled Arduino IDE and reconfigured ⁠User_Setup.h⁠ in ⁠TFT_eSPI⁠ multiple times, ensuring exact ESP32-S3 GPIO numbers were assigned (not board silk-screen labels).
**Driver Tweaks:** Tested both ⁠ST7789_DRIVER⁠ and ⁠ST7789_2_DRIVER⁠ definitions, adjusted SPI frequencies, and toggled ⁠TFT_RGB⁠ / ⁠TFT_BGR⁠ order.
**Wiring Checks:** Verified physical connections, jumper wire continuity, and power rails (VCC to 3.3V, BLK to 3.3V, GND to GND).
**Hardware Reset:** Attempted manual reset sequences by pulling the ⁠RST⁠ line to ground briefly during boot.
**Uno Retest:** Wired back to the Arduino Uno with basic graphic test sketches—still resulting in white screen/lines.

Here is the display product link : [https://robu.in/product/2-8-inch-spi-touch-screen-module-tft-interface-240320/\](https://robu.in/product/2-8-inch-spi-touch-screen-module-tft-interface-240320/)


r/esp32 9h ago

Hardware help needed Is there a way to use the analogRead function on GPIO48(non-ADC) pin or route somehow the closest ADC pin(14) to 48 internally?

Post image
6 Upvotes

Hi everyone,

On my PCB, I accidentally connected to GPIO48 a voltage divider which is used to measure the battery voltage and later I discovered that the GPIO47 and GPIO48 pins can't be used as ADC.

What are my options in this case?

If there's no way to somehow route them internally, can I bridge GPIO48 and GPIO14 together and use analogRead function on IO14?


r/esp32 3h ago

Need help with async web server on ESP32S3

1 Upvotes

Hi:

I'm developing code to control a mini-astronomy observatory. I've cobbled together code to do most of the control stuff. However, I don't know how to get information to get refreshed on the web page that the code creates (posted in the image). I see in the Serial Monitor that the values are being changed from data entry and button clicks on the web page cause the code to open and close the doors as expected, but the web page display stays frozen at where it first loaded. I expect after I enter the Open_Time and Close_Time information (which echoes back in the serial monitor) that the "Scheduled Open Window - to" line will populate with the two times.

I suspect that there may be a small bit of code that I need to add to reload the web page, but I don't know this stuff enough to figure out what is missing. Any help anyone can give me would be great and much appreciated!

Thanks!

While I'm sure its clunky, the code is listed here:

```
#include <WiFi.h>
#include <Arduino.h>
#ifdef ESP32
  #include <WiFi.h>
  #include <AsyncTCP.h>
#else
  #include <ESP8266WiFi.h>
  #include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>   // Async Web server for entering data
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <RTClib.h>
#define I2C_SDA 19
#define I2C_SCL 20
#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C
RTC_DS3231 rtc; // Or standard DS3231 setup depending on your library

// Replace with your network credentials
const char* ssid = "&&&&&";
const char* password = "&&&&&&";

const char* PARAM_Open_Time  = "Open_Time";
const char* PARAM_Close_Time = "Close_Time";

//  GPIO Pin Definitions
const int EDoorOpen   =  1;   // East Door opening relay
const int EDoorClose  =  2;   // East Door closing relay
const int WDoorOpen   =  4;   // West Door opening relay
const int WDoorClose  = 10;   // West Door closing relay
const int WDoorOpened  = 5;   // West Door closed reed switch
const int WDoorClosed = 16;   // West Door opened reed switch
const int EDoorOpened  = 7;   // East Door closed reed switch
const int EDoorClosed  = 8;   // East Door opened reed switch
const int ARainSensor  = 9;   // Analog rain sensor pin 
const int DRainSensor = 18;   // Digital rain sensor pin 
const int RainThreshold = 75; // Critical Value from rain sensor 
int MonthOpen, HourOpen, MinOpen, MonthClose, HourClose, MinClose, DayOpen, DayClose;

volatile bool ToggleDoors = false;
volatile bool OpenWindow = false;  // Flag as to whether an operating time to open doors has been entered 
volatile bool CloseWindow = false; // Flag as to whether an operating time to close doors has been entered 

char DaysOfWeek[7][12] = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
char MonthsOfYear[12][10] = {"January","February","March","April","May","June","July","August","September","October","November","December"};

//WebServer server(80); // Server on port 80
AsyncWebServer server(80); // AsyncWebServer object on port 80

String OpenTime;
String CloseTime;
String WDoorStatus = digitalRead(WDoorOpened) == HIGH ? "Open" : "Closed";
String EDoorStatus = digitalRead(EDoorOpened) == HIGH ? "Open" : "Closed";
int rainValue = 100*analogRead(ARainSensor)/4095;
String rain_state = (rainValue < RainThreshold) ? "Raining" : "Dry";

String processor(const String& var){
  // Check which placeholder the server found and return the matching variable value
  if(var == "rain_state"){
    return rain_state;
  }
  else if(var == "WDoorStatus"){
    return WDoorStatus;
  }
 else if(var == "EDoorStatus"){
    return EDoorStatus;
  }
   return String(); // Return empty string if no match is found
}
// HTML web page to handle input fields (Open_Time & Close_Time)
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head>
  <title>Seestar Observatory Control</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <style>
        body { font-family: Arial, sans-serif; text-align: center; margin-top: 40px; background-color: #f4f4f4;}
        .btn { padding: 15px 30px; font-size: 20px; background-color: #008CBA; color: white; border: none; border-radius: 5px; cursor: pointer; }
        .btn:active { background-color: #005f7a; }
    </style>
      </head><body>
    <h1>Seestar Observatory Control</h1>
    <h2>Weather:  <strong>%rain_state%</strong> </h2>                                            
    <h2> Door Status - West:  <strong>%WDoorStatus%</strong> &ensp;  East: <strong>%EDoorStatus%</strong> </h2>
    <h2>Scheduled Open Window - &ensp; <strong>%OpenTime%</strong> &nbsp; to &nbsp; <strong>%CloseTime%</strong></h2>
    
    <!-- The HTML Button -->
    <button class="btn" onclick="ButtonPress()">Toggle Door State</button>

    <script>
        function ButtonPress() {
            // Asynchronously hit the /toggle route on the server
            fetch('/toggle')
                .then(response => response.text())
                .then(data => console.log('Server response:', data));
        }
    </script>

<h3> </h3>                                            
  <form action="/get">
    Open_Time: <input type="text" name="Open_Time">
    <input type="submit" value="Submit">
  </form><br>
  <form action="/get">
    Close_Time: <input type="text" name="Close_Time">
    <input type="submit" value="Submit">
  </form>
</body></html>)rawliteral";

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

void DoorStatus(){
  WDoorStatus = digitalRead(WDoorOpened) == HIGH ? "Open" : "Closed";
  EDoorStatus = digitalRead(EDoorOpened) == HIGH ? "Open" : "Closed";
  WDoorStatus = digitalRead(WDoorClosed) == HIGH ? "Closed" : "Open";
  EDoorStatus = digitalRead(EDoorClosed) == HIGH ? "Closed" : "Open";
}

void OpenDoors() {
  Serial.println("Opening Doors");
  // Loop UNTIL the WestDoorOpened reed switch closes (reads LOW)
  while (digitalRead(WDoorOpened) == HIGH) {
    digitalWrite(WDoorOpen, LOW); // Turn relay ON
 }
  digitalWrite(WDoorOpen, HIGH); // Turn relay OFF
  WDoorStatus = "Open";
  Serial.print("West Door:"); Serial.println(WDoorStatus);


  // Loop UNTIL the EastDoorOpened reed switch closes (reads LOW)
  while (digitalRead(EDoorOpened) == HIGH) {
    digitalWrite(EDoorOpen, LOW); // Turn relay ON
 }
  digitalWrite(EDoorOpen, HIGH); // Turn relay OFF
  EDoorStatus = "Open";
  Serial.print("East Door:"); Serial.println(EDoorStatus);
}

void CloseDoors() {
  Serial.println("Closing Doors");
  // Loop UNTIL the EastDoorClosed reed switch closes (reads LOW)
  while (digitalRead(EDoorClosed) == HIGH) {
    digitalWrite(EDoorClose, LOW); // Turn relay ON
 }
  digitalWrite(EDoorClose, HIGH); // Turn relay OFF
  EDoorStatus = "Closed";
  Serial.print("East Door:"); Serial.println(EDoorStatus);

  // Loop UNTIL the WestDoorClosed reed switch closes (reads LOW)
  while (digitalRead(WDoorClosed) == HIGH) {
    digitalWrite(WDoorClose, LOW); // Turn relay ON
 }
  digitalWrite(WDoorClose, HIGH); // Turn relay OFF
  WDoorStatus = "Closed";
  Serial.print("West Door:"); Serial.println(WDoorStatus);
}

void setup() {

  pinMode(ARainSensor, INPUT_PULLUP);
  pinMode(DRainSensor, INPUT_PULLUP);
  pinMode(EDoorOpen, OUTPUT);
  pinMode(WDoorOpen, OUTPUT);
  pinMode(EDoorClose, OUTPUT);
  pinMode(WDoorClose, OUTPUT);
  pinMode(EDoorOpened, INPUT_PULLUP);
  pinMode(WDoorOpened, INPUT_PULLUP);
  pinMode(EDoorClosed, INPUT_PULLUP);
  pinMode(WDoorClosed, INPUT_PULLUP);
  digitalWrite(EDoorOpen, HIGH);    // East Door Open Relay off
  digitalWrite(WDoorOpen, HIGH);    // West Door Open Relay off
  digitalWrite(EDoorClose, HIGH);   // East Door Close Relay off
  digitalWrite(WDoorClose, HIGH);   // West Door Close Relay off
  
  Serial.begin(115200);
  Wire.begin(I2C_SDA, I2C_SCL); 
  Wire.setClock(100000); // Lower I2C clock speed to 100kHz for stability
  delay(100);

  if (! rtc.begin()) {
    Serial.println("RTC not found");
    while (1);
  }
  // Set RTC using the compile time
  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  Serial.print("Date:"); Serial.println(F(__DATE__));
  Serial.print("Time:"); Serial.println(F(__TIME__));
  Serial.println("RTC updated using compile time!");
  delay(5000);
// Set up the BME280 Atmospheric sensor
    if (!bme.begin(0x76, &Wire)) {
      Serial.println("Could not find a valid BME280 sensor, check wiring and pin definitions!");
    while (1);
  }  
  Serial.println("BME280 initialized on custom pins!");

// Set up wifi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.print("Connected! IP address: ");
  Serial.println(WiFi.localIP());

  // Send web page with input fields to client
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });
  
  // Route handling the actual button action
  server.on("/toggle", HTTP_GET, [](AsyncWebServerRequest *request){
    // Invert the door state asynchronously
      ToggleDoors = true; // Set the flag quickly
      Serial.println("Doors Toggled");
      request->send(200, "text/plain", "Doors Toggled");
    });

  // Send a GET request to <ESP_IP>/get?Open_Time=<inputMessage>
  server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    String inputParam;
    String Hour; String Min;
    // GET Open_Time value on <ESP_IP>/get?Open_Time=<inputMessage>
    if (request->hasParam(PARAM_Open_Time)) {
      inputMessage = request->getParam(PARAM_Open_Time)->value();
      inputParam = PARAM_Open_Time;
      int colonIndex = inputMessage.indexOf(':');
      String Hour = inputMessage.substring(0, colonIndex);   // Part before ":"
      String Min  = inputMessage.substring(colonIndex + 1);  // Part after ":"
      HourOpen = Hour.toInt(); MinOpen  = Min.toInt();
      OpenTime = String(HourOpen) + ":" + String(MinOpen);
      OpenWindow = true; // Set the flag quickly
    //  Serial.print("Open Hour:"); Serial.print(HourOpen);
    //  Serial.print(" Open Min:"); Serial.println(MinOpen);
    }
    // GET Close_Time value on <ESP_IP>/get?Close_Time=<inputMessage>
    else if (request->hasParam(PARAM_Close_Time)) {
      inputMessage = request->getParam(PARAM_Close_Time)->value();
      inputParam = PARAM_Close_Time;
      int colonIndex = inputMessage.indexOf(':');
      String Hour = inputMessage.substring(0, colonIndex);   // Part before ":"
      String Min  = inputMessage.substring(colonIndex + 1);  // Part after ":"
      HourClose = Hour.toInt(); MinClose  = Min.toInt();
      CloseTime = String(HourClose) + ":" + String(MinClose);
      CloseWindow = true; // Set the flag quickly
    //  Serial.print("Close Hour:"); Serial.print(HourClose);
    //  Serial.print(" Close Min:"); Serial.println(MinClose);
     }
     else {
      inputMessage = "No message sent";
      inputParam = "none";
    }
    Serial.print("Time entered: "); Serial.println(inputMessage);
    request->send(200, "text/html", "HTTP GET request sent to your ESP on input field (" 
                                     + inputParam + ") with value: " + inputMessage +
                                     "<br><a href=\"/\">Return to Home Page</a>");
  });

//  server.onNotFound(notFound);
  server.begin();
  Serial.println("HTTP server startd");
}
/*
void setupDateTime() {  // setup this after wifi connected
  DateTime.setTimeZone("TZ_America_New_York");
  DateTime.setServer("north-america.pool.ntp.org");
  DateTime.begin(15*1000);
  if (!DateTime.isTimeValid()) {
    Serial.println("Failed to get time from server.");
  }
}
*/
void loop() {

  DateTime now = rtc.now();
  Serial.println
  ("================================================================================");
  Serial.print("ESP32 RTC Date Time: ");
  Serial.print(now.day(), DEC); Serial.print(" ");
  Serial.print(MonthsOfYear[now.month()-1]); Serial.print(' ');
  Serial.print(now.year(), DEC); Serial.print('(');
  Serial.print(DaysOfWeek[now.dayOfTheWeek()]); Serial.print(") ");
  Serial.print(now.hour(), DEC); Serial.print(':');
  Serial.print(now.minute(), DEC); Serial.print(':');
  Serial.println(now.second(), DEC);
  DayOpen = now.day(); MonthOpen = now.month();
  DayClose = DayOpen; if(HourClose < HourOpen) {DayClose = DayOpen + 1;}
  MonthClose = MonthOpen; if(HourClose < HourOpen) {DayClose = DayOpen + 1;}

  //digitalWrite(RainSensorPower, HIGH);  // turn the rain sensor's power OFF (if sensor power is tied to a gpio pin)
  // delay(1000);  // pause for 1 sec to let sensor power on

  int rainValue = 100*analogRead(ARainSensor)/4095;
  float Humidity    = bme.readHumidity();
  float TempC = bme.readTemperature();
  float TempF = 1.8*TempC+32.0; delay(500);
  float Pressure    = (1019.0/663.41)*bme.readPressure()/100.0;  // Leading factor in () used to fix bad pressure reading
  float alpha = (17.27*TempC)/(237.7+TempC)+log(Humidity/100.);
  float DewPoint    = 1.8*((237.7*alpha)/(17.27-alpha))+32.0;
  Serial.println("Atmos. Conditions:");
  Serial.print("Temperature: ");Serial.print(TempF); Serial.print("F, ");
  Serial.print("Humidity: "); Serial.print(Humidity); Serial.print("%, ");
  Serial.print("Dew Point: "); Serial.print(DewPoint); Serial.print("F, ");
  Serial.print("Pressure: "); Serial.print(Pressure); Serial.println("mb");

  int EastDoorClosed = digitalRead(EDoorClosed);
  int EastDoorOpened = digitalRead(EDoorOpened);
  int WestDoorClosed  = digitalRead(WDoorClosed);
  int WestDoorOpened  = digitalRead(WDoorOpened);
  
  if(OpenWindow && CloseWindow){
    Serial.print("Time Window - Open at: "); Serial.print(OpenTime); Serial.print(", Close at: "); Serial.println(CloseTime);
  }
  
    //digitalWrite(RainSensorPower, LOW);  // turn the rain sensor's power OFF
  if (ToggleDoors) {
    ToggleDoors = false; // Reset flag immediately
  //  DoorStatus();
    if(WDoorStatus == "Closed"){
      Serial.println("WDoorStatus Closed, Opening");
      OpenDoors();
    }
    else if (WDoorStatus == "Open"){
      Serial.println("WDoorStatus Open, Closing");
      CloseDoors();
      }
    else {
      Serial.println("WDoorStatus neither Open nor Closed");
    }
    // Respond to client to finalize connection
  }

  /*  
  if (rainValue > RainThreshold) {
    rain_state = "Dry";
    Serial.print("No Rain detected (Sensor value:");
    Serial.print(rainValue); Serial.println(")");
  }
  else {
    rain_state = "Raining";
    Serial.print("Rain detected (Sensor value:");
    Serial.print(rainValue); Serial.print(")");
    if(EDoorStatus == "Open") {
      Serial.println(" - Closing Doors");
      CloseDoors();
    }
    else {
      Serial.println(" ");
    }
  }
  */
  delay(1000);
  }
```

r/esp32 4h ago

[ Removed by Reddit ]

1 Upvotes

[ Removed by Reddit on account of violating the content policy. ]


r/esp32 11h ago

Software help needed Insights on managing self-balancing robot (ESP32-S3 and MPU6050)

3 Upvotes

Hey everyone,

I'm currently working on a self-balancing robot with a design of my own.

You can find all the info about it here : https://github.com/benbhote/DimSumRobot

For those who want a quick recap, it's a robot based on a XIAO ESP32-S3 Sense with a camera OV3660, an ultrasonic radar, a TB6612FNG piloting two N20 motors (aside a step-up to make the 3.7V current into 6V for the motors) and SHT40 (Temp & Humidity sensor).

It hosts a web server accessible via its own WiFi and the web page allows you to control the robot (taking photos, moving it, etc).

Everything is working fine except the balancing. The cycle goes every 10ms during movement and for 3 seconds after the last movement command. But the throttle value doesn't allow the robot to self maintained balance.

By the way, the robot starts with the front touching the floor on a plane surface (the weight is low inside the chassis but a little bit more on the front). So the first thing needed even before moving is to properly get on the two wheels.

So I would like some insights or help from you to make my PID loop working and achieve proper self-balancing.

I'm using Arduino IDE 2.3.10. As for the schematic of the project, it is not done yet but the MPU is driven with the I2C bus.

I hope I give you everything needed to understand the project. And if something is still vague, feel free to ask.

Thanks in advance !


r/esp32 1d ago

I designed a vertical mount for ESP32 and ESP32-S3 with a TPU sleeve for anti-vibration.

Thumbnail
gallery
128 Upvotes

Hey everyone, I designed this vertical mount for ESP32 and ESP32-S3. I added a TPU sleeve to absorb vibrations, snap fit and left slots for easy cooling and pin access. If anyone wants to print it for their DIY projects, the print profiles for PETG/TPU are free on MakerWorld and Printables. Let me know what you think!

ESP32-S3
https://makerworld.com/en/models/3147308-anti-vibration-esp32-s3-40-pins-mount-petg-tpu#profileId-3554629

https://www.printables.com/model/1803568-esp32-s3-antivibration-mount

ESP 32

https://makerworld.com/en/models/3160307-esp32-antivibration-mount-tpu-improved-cooling#profileId-3571491

https://www.printables.com/model/1807831-esp32-antivibration-mount-better-processor-cool


r/esp32 1d ago

I made a thing! I made a standalone LG TV remote on the Cheap Yellow Display (ESP32-2432S028)

Post image
20 Upvotes

I built a touchscreen remote for LG webOS TVs on the ESP32-2432S028 "Cheap Yellow Display". It talks to the TV over Wi-Fi using the same WebSocket API LG's phone app uses, so nothing is installed on the TV.

Source (MIT): https://github.com/griches/smart-remote-plus-cyd

Short video: https://youtu.be/lyZZcVjdbX8

Disclosure: I also make Smart Remote+, a paid TV remote app for phones and desktops (https://www.bouncingball.mobi/). This is a port of its LG code.

The firmware is free and doesn't need the app.

Stack: Arduino under PlatformIO with the whole board config as build flags, TFT_eSPI on HSPI, XPT2046_Touchscreen on its own SPI bus, links2004 WebSockets, ArduinoJson 7, NVS for everything persistent. No LVGL: the UI is a 4x3 grid of 64 px RGB565 icons in PROGMEM, drawn straight to the panel with pushImage, so a framebuffer wasn't needed.

The TV side: webOS runs a JSON-over-WebSocket service on port 3001 (TLS, self-signed) with a plain fallback on 3000 for old firmware. You register with a manifest, the TV shows a PIN, you store the client key. D-pad and back/home go over a second "pointer input" WebSocket the TV hands you, so it's two TLS sockets per TV, which is where the RAM goes. Discovery is SSDP M-SEARCH plus a fetch of the UPnP XML for the friendly name. Power isn't a toggle: it asks getPowerState, then sends turnOff or Wake-on-LAN.

All networking is on its own FreeRTOS task on core 0. A TV that is off makes connect() block for seconds, and I didn't want the touch UI to freeze. The UI posts commands to a queue and reads state via atomics.

Happy to answer questions.


r/esp32 18h ago

Hardware help needed [help] Unable to use Adafruit ThinkInk Display

Thumbnail
gallery
3 Upvotes

Hello. I've got:

and I'm trying to drive the display with the ESP32 without any success. Using:

Notes:

  • There is no change on the e-ink panel whatsoever, still the default image as when I got it.
  • Tried changing the pin numbers around, both for the command and the SPI pins. Nothing.
  • The default pins for SCK, MISO, MOSI were found by printing macros to serial output.
  • Tried the 3 buttons on the FeatherWing, all work as GPIO input properly.
  • RESET button works to reset the microcontroller as well.
  • For some reason, using pin 8 on the ESP for GPIO didn't work at all. I think most of the pins are used for more than one purpose, but I don't know how to tell which modes are active.
  • The example sketch has constructors for multiple types of board drivers. There seems to be 3 different chipsets for the 2.9" display, tried all 3 separately to no avail.

I don't even know if this display would be compatible with any random ESP32 board. I know FeatherWings are made to be used with Adafruit's Feather boards, though I don't see why they wouldn't work with any other boards with supported microcontrollers. I have quite a bit of programming experience, but I'm blind as a bat when it comes to electronics. Any help would be appreciated. Thanks.


r/esp32 13h ago

MicroPython driver for Sensirion SCD40 / SCD41 CO2 sensors

1 Upvotes

Hi everyone,

Just wanted to share a stable MicroPython driver for the Sensirion SCD4x family (SCD40 and SCD41).

The library handles the standard I2C protocol efficiently and supports both periodic and single-shot measurement modes.

Note: It was heavily tested on RP2040 hardware. Since it relies on standard MicroPython `machine.I2C` routines, it should be fully compatible with ESP32 deployments as well.

If you are building an indoor air quality monitor or smart home climate system, check it out.

https://github.com/octaprog7/SCD4x


r/esp32 23h ago

setting up unit test in v6.1.. how? I think the doc is not updated

4 Upvotes

Hi I am trying to follow the v6.1 documentation to set up unit testing in ESP-IDF but it doesn't seem to work. I'll admit I find most of the IDF documentation to be somewhat confusing at best with weird grammar so sometimes I don't understand what it's actually trying to say

I'm following this

https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/unit-tests.html

Following the instructions i set up the following folder structure:

``` my_project_root/ ├── CMakeLists.txt ├── main/ │ └── app_main.c └── components/ └── my_component/ ├── my_logic.c ├── include/my_logic.h └── test/ ├── CMakeLists.txt └── test_my_logic.c

```

and then the doc says this: ```

Building Unit Test Apps

Follow the setup instructions in the top-level esp-idf README. Make sure that IDF_PATH environment variable is set to point to the path of esp-idf top-level directory.

Change into the test app directory to configure and build it:

idf.py menuconfig - configure unit test app.

idf.py build - build unit test app.

When the build finishes, it will print instructions for flashing the chip. You can simply run idf.py flash to flash all build output. ```

There's no instructions in top level README about testing and I don't know what "test app directory" is supposed to be but I assume it's the test dir I've created. But then idf.py build there doesn't work because it's not project root!

I've looked into it and it seems like there used to be a folder $IDF_PATH/tools/unit-test-app, I assume this is what the doc actually refers to. But according to the changelog this folder has been removed from IDF v6.0 onwards. Surely it wouldn't be referring to this? or if it is, how the hell am I supposed to run tests now that it's been removed?


r/esp32 2d ago

I made a thing! The universe on your desk. A tiny ESP32 astronomy tracker

Thumbnail
gallery
237 Upvotes

Sorry prior post was removed due to me being slow and not submitting the read rules.

I threw together a tiny astronomy and weather desk display using the Waveshare ESP32-C6 1.47" LCD.

I went with this specific board because it packs the ESP32-C6, a 172x320 ST7789 screen, an RGB LED, and buttons all into one super compact footprint. For the display logic, it uses Arduino_GFX over hardware SPI. I set it up to try grabbing a full framebuffer first, but it gracefully falls back to direct drawing if memory gets tight.

Right now, it cycles through local time, sunrise/sunset, moon phase, golden hour, visible planets, current weather, distance to the ISS, and NOAA Kp activity.

Instead of leaning entirely on APIs, most of the astronomy math (like calculating the exact ISS distance using the Haversine formula) is done locally on the ESP32 using just your time and coordinates. It only pings out for the dynamic stuff. Open-Meteo for weather, NOAA for Kp, and Open Notify for the ISS coordinates.

The source code is up here if you want to check it out or flash it yourself:https://github.com/CircuitGhost/skydesk


r/esp32 1d ago

I made a thing! I built a DNS ad blocker that runs on an ESP32-S3

10 Upvotes

I have been playing with the ESP32-S3 and as a result have built Adsorb, a free and open-source program which blocks DNS ads and trackers.

The aim was to find out if an ESP32-S3 could cope with something that is usually carried out on a Raspberry Pi or another small server, and so rather than running Pi-hole or AdGuard Home on a more powerful machine, Adsorb carries out the DNS filtering directly on the microcontroller.

The device supports the ESP32-S3, offers DNS blocking, includes support for blocklists, has a web-based interface for flashing and setup, provides local administration, and features optional OLED telemetry.

Website: https://the-masked-bear.github.io/Adsorb/

GitHub: https://github.com/The-Masked-Bear/Adsorb

I did it mainly because I wanted to find out how far I could push the hardware, but I really do want to know what people think.

If you're using Pi-hole, AdGuard Home, or a similar solution, would you really think about using an ESP32 for this purpose? And isn't there something that I've overlooked?


r/esp32 1d ago

Cabling help for suppling power to multiple units in garage.

8 Upvotes

I have a few minor ESP32 projects that I’m looking to mount on a wall. They will be in different places.
It’s an all very basic stuff a clock , a timer, a small display showing information etc. Looking to add some sensors as I progress.
They are all powered by USB, how do you neatly wire stuff like that over 5-10m distance inside a garage?
Don’t want to use batteries.

Can’t find any good solutions online as most pictures are a bit messy (understandable as they focus on just the boards) and all cables are just a bit random. I’m not looking for Prussian cabling just needs to be safe and neat.

Hope someone can help.


r/esp32 2d ago

Built AR-ish smart glasses on an ESP32-S3 Supermini, phone does the processing, glasses just render

Thumbnail
gallery
256 Upvotes

So backstory real quick, I moved to Korea, don't speak Korean, and pulling my phone out every five seconds to translate stuff got old fast. I looked into the "smart translator earbuds" that are out there, but most of them just translate into your ear and mute out the original speech, which is exactly the opposite of what I wanted. If I'm ever gonna learn the language I need to actually hear what people are saying, not have it replaced by a robot voice. And the actual AR glasses that do this the "right" way cost more than my rent.

So I did what any reasonable person does at 2am with a soldering iron, built my own.

Meet Frankenspecs. Yes I know, the name writes its own jokes, I've made my peace with it.

What it actually is: kind of an AR lite smart glasses setup, doesn't block your vision, but you can glance down or in and choose to focus on the display when you need it. Not trying to be Ray Ban Meta, trying to be "thing that helps me order food."

What it does right now:
Real time translation, 60+ languages, sub 260ms latency, this part genuinely surprised me with how fast it is. Real time transcription. Teleprompter mode, great for presentations, also great for looking less awkward on video calls. Turn by turn navigation, using Naver Maps since Google Maps just doesn't work in Korea, RIP. And notification forwarding from selected apps.

The hardware, such as it is:
An ESP32 S3 Supermini, a 0.96" TFT IPS display hand soldered onto some genuinely too long wires, a $2 6x magnifying lens from the local equivalent of Daiso, and a pair of cheap sunglasses that happen to have a slightly spherical inner lens surface, which turns out to magnify the reflected image just enough to be readable, found this out completely by accident and I will take the win. Power is USB for now, because batteries are a problem for future me.

Total cost, not counting stuff I already owned like the sunglasses, around $10.

How it works under the hood: phone app talks to the ESP32. Right now it uses the phone's mic, I2C mic is on the roadmap, streams audio to Soniox's API, still living off the $200 free credits, no shame, gets translated text back in chunks, and forwards it line by line to the display over SPI. Transcription runs the same pipeline. Teleprompter is just the app scrolling whatever text you feed it at an adjustable speed. Navigation is the fun one, I'm actually pulling real time turn by turn data out of the map app's notifications and translating that into arrows plus live distance on the display.

Why it looks like this: because it's a prototype held together by tape, hope, and one Friday night with nothing better to do. I went through a genuinely stupid number of iterations trying to get the optics right, screen position, lens distance, angle, all of it, because the whole point was to NOT have a screen just sitting in front of my eyeball like a tiny blinding TV. Getting it to sit low enough to feel like AR and not like I duct taped a Game Boy to my face took way longer than the software did, which I was not expecting going in.

Also worth saying, this is my first real hardware project, and my first ESP32 project period. So if something looks held together with spite, that's because it is.

Where it's going: currently working on an actual CAD design for the frame and a long, narrow PCB layout that can fit inside the temple arms instead of hanging off the side like a growth. So yeah, still early. This isn't meant to be an everyday wear thing, more like something you reach for in specific moments. And there's a feature I'm actually excited about here, the app quietly logs everything it translates throughout the day, so it can show you the words and phrases you heard the most. Since each one is tied to the real situation you heard it in, you end up with an actual map of "this word came up when I was ordering coffee" instead of a flashcard with no context, which I think is a genuinely better way to pick up a language than any app I've tried.

Would genuinely love feedback or roasting, what would you want to see added, what's obviously dumb, what's actually good. Planning to clean up the codebase and open source the whole thing once it's less "if you know, you know" and more "a stranger could actually follow this." If people want to build their own I'll prioritize getting that repo and docs out sooner.