Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.
Sunshine Hours Logger: the finished build
ESP32-C3 SuperMiniWeather

Sunshine hours logger before you install solar (ESP32-C3 + BH1750)

Hours of bright sun and a rough daily solar energy figure for any spot.

Difficulty
Easy
Build time
1 h
Parts cost
₹1,320 · $16
Verified — core esp32 3.3.12, BH1750 1.3.0, 3 Nov 2026Compile-only

Community draft — report a mistake

Parts list

PartQtyApprox.Buy
ESP32-C3 SuperMini1₹230Buy ESP32-C3 SuperMini
BH1750 light sensor module (GY-302)1₹120Buy BH1750 light sensor module (GY-302)
0.96" SSD1306 I2C OLED (4-pin)1₹220Buy 0.96" SSD1306 I2C OLED (4-pin)
Clear food container with lid (weather cover)1₹60Buy Clear food container with lid (weather cover)
4-core cable, 1 m (sensor on the roof edge)1₹40Buy 4-core cable, 1 m (sensor on the roof edge)
USB power bank (10,000 mAh) or 5 V adapter1₹650Buy USB power bank (10,000 mAh) or 5 V adapter
Total₹1,320

Affiliate disclosure: “Buy” links may earn FlashReady a small commission at no extra cost to you. Prices are indicative.

Wiring

ESP32-C3 SuperMiniOnly the pins used are shown · 3.3 V logicBH1750 lux sensor (GY-302)SSD1306 OLED 0.96″ (128×64, I2C)GND3V36 · 67 · 7VCCGNDSCLSDAADDRGNDVCCSCLSDA
Every connection
ESP32-C3 SuperMiniPart · pinWireNotes
7BH1750 lux sensor (GY-302) · SCLyellowGPIO7
6BH1750 lux sensor (GY-302) · SDAblueGPIO6 — keeps I2C off strapping pins 8 and 9
3V3BH1750 lux sensor (GY-302) · VCCred
GNDBH1750 lux sensor (GY-302) · GNDblack
GNDBH1750 lux sensor (GY-302) · ADDRblackADDR low = address 0x23
7SSD1306 OLED 0.96″ (128×64, I2C) · SCLyellowSame I2C bus
6SSD1306 OLED 0.96″ (128×64, I2C) · SDAblue
3V3SSD1306 OLED 0.96″ (128×64, I2C) · VCCred
GNDSSD1306 OLED 0.96″ (128×64, I2C) · GNDblack

Board quirks: The sensor must face straight up, level, with nothing above it but the clear lid. Tilted, it measures a different thing. The BH1750 normally tops out at about 65,000 lux, and Indian noon sun is around 100,000. The sketch shortens the measuring time (MTreg 32) to stretch the range to about 117,000 lux. The kWh/m² figure uses a rough 120 lux per W/m² for sunlight. It is good for comparing spots and days, not for sizing a system to the watt — use the solar calculator and real irradiance data for that. “Bright sun” here means more than 30,000 lux on a level sensor — about when shadows are sharp. Weather services define sunshine more strictly; treat the hours as comparative.

Code

sunshine-hours-logger.inoArduino C++Open in PlaygroundOpen in PlaygroundFlash
// Sunshine hours logger — ESP32-C3 SuperMini + BH1750 (GY-302) + SSD1306 OLED
// BH1750 and OLED share I2C: SDA GPIO6, SCL GPIO7, both at 3V3; BH1750 ADDR to GND (0x23).
// Logs how many hours of bright sun a spot gets and a rough daily solar energy figure — handy
// before you put up a solar panel, a polyhouse or a kitchen garden. No Wi-Fi or clock needed:
// three hours of darkness close the day, and the next sunrise starts a new one.
#include <Wire.h>
#include <BH1750.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

constexpr uint8_t SDA_PIN = 6, SCL_PIN = 7;
constexpr float SUN_LUX = 30000;        // "bright sun" threshold (approximate; see the project page)
constexpr float DARK_LUX = 10;
constexpr float LUX_PER_WM2 = 120;      // rough sunlight conversion: ~120 lux per W/m²
constexpr float CALIBRATION = 1.0;      // raise if a diffuser cap makes it read low
constexpr unsigned long SAMPLE_MS = 10000;
constexpr unsigned long NIGHT_AFTER_S = 3UL * 3600UL;

BH1750 meter(0x23);
Adafruit_SSD1306 oled(128, 64, &Wire, -1);
unsigned long lastSample = 0;
unsigned long sunSeconds = 0, darkSeconds = 0, daySeconds = 0;
float energyWh = 0, peakLux = 0;
bool dayOpen = false;
uint16_t dayNumber = 0;

void closeDay() {
  Serial.printf("DAY %u done: sun %.2f h, %.2f kWh/m2 (rough), peak %.0f lux, daylight %.1f h\n", dayNumber, sunSeconds / 3600.0, energyWh / 1000.0,
                peakLux, daySeconds / 3600.0);
  sunSeconds = daySeconds = 0;
  energyWh = peakLux = 0;
  dayOpen = false;
}

void draw(float lux) {
  oled.clearDisplay();
  oled.setTextColor(SSD1306_WHITE);
  oled.setTextSize(1);
  oled.setCursor(0, 0);
  oled.printf("Now %.0f lux", lux);
  oled.setTextSize(2);
  oled.setCursor(0, 14);
  oled.printf("%luh %02lum", sunSeconds / 3600, (sunSeconds / 60) % 60);
  oled.setTextSize(1);
  oled.setCursor(0, 34);
  oled.print("of bright sun today");
  oled.setCursor(0, 46);
  oled.printf("~%.1f kWh/m2", energyWh / 1000.0);
  oled.setCursor(0, 56);
  oled.printf("peak %.0fk lux", peakLux / 1000.0);
  oled.display();
}

void setup() {
  Serial.begin(115200);
  Wire.begin(SDA_PIN, SCL_PIN);
  if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) Serial.println("OLED not found at 0x3C");
  if (!meter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23, &Wire)) Serial.println("BH1750 not found at 0x23 — check SDA GPIO6, SCL GPIO7, ADDR to GND.");
  meter.setMTreg(32);  // shorter integration: the range reaches ~117,000 lux, enough for Indian noon sun
  Serial.println("minutes,lux,sun_minutes,wh_per_m2");
}

void loop() {
  if (millis() - lastSample < SAMPLE_MS) return;
  lastSample = millis();
  float lux = meter.readLightLevel();
  if (lux < 0) {
    Serial.println("BH1750 read error");
    return;
  }
  lux *= CALIBRATION;
  const unsigned long dt = SAMPLE_MS / 1000;

  if (lux < DARK_LUX) {
    darkSeconds += dt;
    if (dayOpen && darkSeconds >= NIGHT_AFTER_S) closeDay();
  } else {
    darkSeconds = 0;
    if (!dayOpen) {
      dayOpen = true;
      dayNumber++;
      Serial.printf("DAY %u started\n", dayNumber);
    }
    daySeconds += dt;
    if (lux >= SUN_LUX) sunSeconds += dt;
    energyWh += lux / LUX_PER_WM2 * dt / 3600.0f;
    peakLux = max(peakLux, lux);
  }
  static uint8_t samples = 0;
  if (samples == 0)  // a CSV line every 10 minutes (60 samples)
    Serial.printf("%lu,%.0f,%lu,%.0f\n", millis() / 60000UL, lux, sunSeconds / 60, energyWh);
  samples = (samples + 1) % 60;
  draw(lux);
}

Compiled for c3supermini on esp32 3.3.12 with BH1750 1.3.0 · 3 Nov 2026

How it works

Before you spend on rooftop solar, a polyhouse, or even move the tulsi and tomato pots, it helps to know how much sun a spot actually gets. A water tank, a neighbour’s new floor or a coconut tree can shade a corner for hours that you never notice while at work. This logger sits at the spot and counts.

What it measures

Every 10 seconds the BH1750 gives the light level in lux. The ESP32-C3 adds up:

  • Hours of bright sun — time above 30,000 lux.
  • A rough solar energy figure in kWh/m² — the lux reading divided by about 120 lux per W/m², added up over the day. For comparison, most of India gets roughly 4–6 kWh/m² a day on open ground, less in the monsoon.
  • Peak lux of the day.

The OLED shows them all, and a CSV line goes to Serial every 10 minutes.

No clock needed

The board doesn’t need Wi-Fi or a real-time clock to know when a day starts. When light drops below 10 lux for three hours in a row, it’s night: the day’s totals are printed and reset, and the first light of the next morning starts a new day. That also handles a power bank running out and being replaced at noon — you lose only that morning.

Why these parts

The BH1750 is a digital lux meter with a response close to the human eye and a range far beyond cheap LDRs, which saturate in daylight and drift with temperature. The ESP32-C3 SuperMini is small enough to tape inside a lunch box with the OLED and a power bank; both I2C devices share GPIO6/GPIO7, keeping the strapping pins 8 and 9 free.

Set-up

Put the sensor in a clear, level container on the exact spot — the roof edge where panels would go, the balcony rail, the garden bed. Leave it for several days and compare the totals, ideally on clear days. A spot with 6 sun hours beats one with 4 by half as much energy again.

Troubleshooting

Lux is stuck near 54,000 or 65,000 at noon

The sensor saturates: check the MTreg line ran (Serial shows no BH1750 error), or add a piece of white diffuser plastic and raise CALIBRATION to compensate.

A new day starts in the middle of the afternoon

Three hours of darkness close the day. A thick monsoon storm doesn’t get that dark (still hundreds of lux), but a sensor under a tarpaulin will — keep it clear.

The lid fogs up in the morning

Drill two small holes at the bottom of the container and add a silica gel sachet.

Upgrades

  • Log each day’s totals to Google Sheets over Wi-Fi to build a month of data.
  • Put two loggers on two candidate roof spots and compare them side by side.
  • Add a real pyranometer-style calibration against a known solar panel’s output.

↑↓ to move · Enter to open