XIAO S3 Battery Gauge on Round Display — Xiao Esp32 S3 simulation

Battery voltage gauge using Seeed Round Display with arc indicator on XIAO ESP32-S3.

An interactive Xiao Esp32 S3 circuit simulation you can run free in your browser on Velxio, by rsetyo-widayanto.

Components

Sketch code

// XIAO ESP32S3 + Seeed Round Display — tes battery gauge
// Buka control panel Round Display saat Run:
// - Battery slider mengubah tegangan baterai
// - KE switch menghubungkan/melepas pembagi tegangan ke A0

#include <M5GFX.h>
#include <lgfx/v1/panel/Panel_GC9A01.hpp>
#include <SPI.h>

static const int PIN_BAT = 1;
static const int PIN_CS = 2;
static const int PIN_DC = 4;
static const int PIN_BL = 43;
static const int PIN_SCK = 7;
static const int PIN_MISO = 8;
static const int PIN_MOSI = 9;

class RoundDisplay : public lgfx::LGFX_Device {
  lgfx::Panel_GC9A01 gc9a01;
  lgfx::Bus_SPI spiBus;

 public:
  RoundDisplay() {
    {
      auto cfg = spiBus.config();
      cfg.spi_host = SPI2_HOST;
      cfg.spi_mode = 0;
      cfg.freq_write = 40000000;
      cfg.pin_sclk = PIN_SCK;
      cfg.pin_mosi = PIN_MOSI;
      cfg.pin_miso = PIN_MISO;
      cfg.pin_dc = PIN_DC;
      spiBus.config(cfg);
      gc9a01.setBus(&spiBus);
    }
    {
      auto cfg = gc9a01.config();
      cfg.pin_cs = PIN_CS;
      cfg.pin_rst = -1;
      cfg.panel_width = 240;
      cfg.panel_height = 240;
      cfg.invert = true;
      gc9a01.config(cfg);
    }
    setPanel(&gc9a01);
  }
};

static RoundDisplay tft;
static const int CX = 120;
static const int CY = 120;

void drawCentered(const char *text, int y, int font, uint16_t color) {
  tft.setTextDatum(textdatum_t::top_center);
  tft.setTextColor(color, TFT_BLACK);
  tft.setTextSize(font);
  tft.drawString(text, CX, y);
}

void setup() {
  Serial.begin(115200);
  pinMode(PIN_BL, OUTPUT);
  digitalWrite(PIN_BL, HIGH);

  tft.init();
  tft.setRotation(0);

  // Tes warna singkat: bukti LCD dan jalur SPI bekerja.
  tft.fillScreen(TFT_RED);   delay(500);
  tft.fillScreen(TFT_GREEN); delay(500);
  tft.fillScreen(TFT_BLUE);  delay(500);
  tft.fillScreen(TFT_BLACK);
  drawCentered("WY PRESS", 92, 2, TFT_YELLOW);
  drawCentered("DISPLAY TEST", 122, 1, TFT_WHITE);
  delay(1000);
}

void loop() {
  int mv = analogReadMilliVolts(PIN_BAT) * 2;
  int pct = (mv - 3000) / 12;
  pct = constrain(pct, 0, 100);

  tft.fillScreen(TFT_BLACK);
  tft.drawCircle(CX, CY, 116, TFT_DARKGREY);

  if (mv < 1000) {
    drawCentered("NO BATTERY", 94, 2, TFT_RED);
    drawCentered("Geser KE switch", 132, 1, TFT_WHITE);
    Serial.println("KE switch: battery terputus dari A0");
  } else {
    uint16_t color = pct > 50 ? TFT_GREEN : (pct > 20 ? TFT_YELLOW : TFT_RED);
    tft.fillArc(CX, CY, 96, 110, 135, 135 + pct * 270 / 100, color);
    tft.fillArc(CX, CY, 96, 110, 135 + pct * 270 / 100, 405, 0x2104);

    char percentText[10];
    char voltageText[16];
    snprintf(percentText, sizeof(percentText), "%d%%", pct);
    snprintf(voltageText, sizeof(voltageText), "%d.%02d V", mv / 1000, (mv % 1000) / 10);
    drawCentered(percentText, 86, 3, TFT_WHITE);
    drawCentered(voltageText, 136, 1, TFT_CYAN);
    drawCentered("BATTERY", 164, 1, TFT_YELLOW);
    Serial.printf("Battery: %d mV (%d%%)\n", mv, pct);
  }

  delay(500);
}

More projects by rsetyo-widayanto