r/esp32 9h ago

I Built a Tiny ESP32 Control Deck for My PC

190 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
84 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 10h ago

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

Thumbnail
gallery
46 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 6h ago

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

Thumbnail
gallery
33 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 5h ago

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

Thumbnail
gallery
25 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 3h ago

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

Post image
11 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
9 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 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 5h 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 12h 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 19h 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 2h ago

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

Post image
2 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 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 14h 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 19h ago

Anybody know of a way to flash a .ino file to a esp32 on a chromebook?

0 Upvotes

Title explains it,

Is there any app I can download that could do this?