Documentation

KY-018 Photoresistor Light Sensor Module for Arduino & ESP32 | ShillehTek Product Manual
Documentation / KY-018 Photoresistor Light Sensor Module for Arduino & ESP32 | ShillehTek Product Manual

KY-018 Photoresistor Light Sensor Module for Arduino & ESP32 | ShillehTek Product Manual

shillehtek

Overview

The KY-018 is the classic first light sensor: a photoresistor (LDR) whose resistance falls as light hits it, paired with a fixed resistor to form a voltage divider. The S pin outputs the divider's midpoint voltage, so as the room gets brighter or darker, the analog value your board reads slides smoothly up and down. No protocol, no library, no configuration — one analogRead() and you are measuring light.

The LDR responds like a human-friendly light meter: from over a megaohm in darkness down to a few kilohms in bright light, with most of the change happening in the everyday indoor range. That makes the KY-018 ideal for threshold decisions — is it day or night, did someone switch on the lamp, is the enclosure lid open, did a shadow pass over the desk — rather than laboratory lux measurements (for calibrated lux, the BH1750 digital sensor is the right tool).

It runs on 3.3V or 5V, and because the output can never exceed the supply, it wires directly to the ESP32 and Pico when powered at 3.3V. Arduino reads it directly at 5V, and the Raspberry Pi — which has no analog inputs — reads it through an ADS1115 ADC. Typical projects: automatic night lights, dusk-triggered blinds, light-following robots, laser tripwires, and plant-light monitors.

At a Glance

Sensor
Photoresistor (LDR)
Output
Analog voltage on S
Operating Voltage
3.3V - 5V DC
Bright Resistance
A few kΩ
Dark Resistance
> 1 MΩ
Pins
S, VCC (middle), GND (-)

Specifications

Parameter Value
Sensing Element CdS photoresistor (GL5528 class)
Circuit LDR + fixed resistor voltage divider
Output Analog voltage on S (0 to VCC)
Operating Voltage 3.3V - 5V DC
Light Resistance ~8 - 20 kΩ at 10 lux
Dark Resistance > 1 MΩ
Response Behavior Brighter light → higher S voltage on this board layout
Response Time Tens of milliseconds (CdS cells are not instant)
Spectral Peak ~540 nm (green — close to human eye response)
Board Format KY-018 3-pin module, ~36 x 18 mm

Pinout Diagram

Three pins, marked on the silkscreen: S is the analog signal, the middle pin is VCC, and the pin marked with a minus sign is GND. On this board the LDR sits between VCC and S with the fixed resistor from S to ground, so more light pulls S toward VCC — brighter room, bigger number. If you ever meet a KY-018 revision wired the other way (readings fall with light), nothing is wrong; just flip your comparison in code.

KY-018 photoresistor light sensor module pinout diagram showing SIGNAL, VCC, and GND pins

Wiring Guide

Arduino Wiring

KY-018 Pin Arduino Pin
S A0
VCC (middle) 5V
- (GND) GND
Tip: Watch the raw values in the Serial Monitor while covering the LDR with your hand and shining a phone flashlight on it — those two numbers are your project's real-world range, and the best threshold sits comfortably between them.

ESP32 Wiring

Power from 3V3 so the S output tops out at 3.3V — inherently safe for the ESP32's ADC.

KY-018 Pin ESP32 Pin Details
S GPIO 34 ADC1 channel, input-only pin
VCC (middle) 3V3 Do NOT use VIN/5V
- (GND) GND
Warning: Powered at 5V the S pin can reach 5V — too high for ESP32 inputs. Powering the module from 3V3 removes the risk entirely, with no loss of usefulness.
Tip: Keep S on an ADC1 pin (GPIO 32-39) if your project uses Wi-Fi — ADC2 pins stop converting while the radio is active.

Raspberry Pi Wiring

The Pi has no analog inputs, so an ADS1115 I2C ADC reads the S pin. Power everything from the 3.3V rail.

Wire / Pin Connects To Details
KY-018 S ADS1115 A0 Analog channel 0
KY-018 VCC Pin 1 (3.3V) Shared rail
KY-018 GND Pin 6 (GND)
ADS1115 VDD / GND Pin 1 / Pin 6
ADS1115 SDA Pin 3 (GPIO 2) I2C data
ADS1115 SCL Pin 5 (GPIO 3) I2C clock
Tip: Enable I2C with sudo raspi-config, then i2cdetect -y 1 should show the ADS1115 at 0x48.

Raspberry Pi Pico Wiring

KY-018 Pin Pico Pin Details
S GP26 (pin 31) ADC0 input
VCC (middle) 3V3(OUT) (pin 36) Do NOT use VBUS (5V)
- (GND) GND (pin 38)

Code Examples

Each example prints the raw reading plus a simple day/dim/dark classification. The thresholds are starting points — tune them to the numbers you see in your own room.

Arduino

ky018_arduino.ino
// KY-018 Photoresistor - Arduino Example
// S -> A0, VCC (middle) -> 5V, - -> GND

const int sensorPin = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int raw = analogRead(sensorPin);   // 0-1023, higher = brighter

  Serial.print("Light level: ");
  Serial.print(raw);

  if (raw > 700) {
    Serial.println("  (bright)");
  } else if (raw > 300) {
    Serial.println("  (dim)");
  } else {
    Serial.println("  (dark)");
    // Example action: digitalWrite(LED_BUILTIN, HIGH);  // night light on
  }

  delay(500);
}

ESP32 (MicroPython)

ky018_esp32.py
# KY-018 Photoresistor - ESP32 MicroPython Example
# S -> GPIO 34, VCC (middle) -> 3V3, - -> GND

from machine import ADC, Pin
import time

adc = ADC(Pin(34))
adc.atten(ADC.ATTN_11DB)   # full 0-3.3V range

while True:
    raw = adc.read()        # 0-4095, higher = brighter

    if raw > 2800:
        state = "bright"
    elif raw > 1200:
        state = "dim"
    else:
        state = "dark"

    print("Light level: {} ({})".format(raw, state))
    time.sleep(0.5)

Raspberry Pi (Python + ADS1115)

ky018_rpi.py
#!/usr/bin/env python3
# KY-018 Photoresistor - Raspberry Pi + ADS1115 Example
# S -> ADS1115 A0, SDA/SCL -> GPIO 2/3, VCC -> 3.3V
# Install: pip3 install adafruit-circuitpython-ads1x15

import time
import board
import busio
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn

i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c)
ads.gain = 1                       # +/-4.096V range
channel = AnalogIn(ads, ADS.P0)

try:
    while True:
        volts = channel.voltage    # 0-3.3V, higher = brighter

        if volts > 2.3:
            state = "bright"
        elif volts > 1.0:
            state = "dim"
        else:
            state = "dark"

        print("Light level: {:.2f} V ({})".format(volts, state))
        time.sleep(0.5)
except KeyboardInterrupt:
    print("Stopped by user")

Raspberry Pi Pico (MicroPython)

ky018_pico.py
# KY-018 Photoresistor - Pico MicroPython Example
# S -> GP26 (ADC0), VCC (middle) -> 3V3(OUT), - -> GND

from machine import ADC
import time

adc = ADC(26)

while True:
    raw = adc.read_u16()    # 0-65535, higher = brighter

    if raw > 45000:
        state = "bright"
    elif raw > 20000:
        state = "dim"
    else:
        state = "dark"

    print("Light level: {} ({})".format(raw, state))
    time.sleep(0.5)

Frequently Asked Questions

Do higher readings mean more light or less?
On this board layout, more light means a higher reading — the LDR sits on the VCC side of the divider and pulls S up as its resistance drops. A few KY-018 revisions swap the divider and read the opposite way. Thirty seconds with a flashlight tells you which one you have, and flipping a comparison operator adapts any code.
Can it measure lux?
Not meaningfully. CdS photoresistors are non-linear, vary unit to unit, and drift with temperature, so the KY-018 is a relative sensor — perfect for "brighter or darker than my threshold" decisions. When you need real lux values (for lighting design, plant PAR estimates, or datasheet-grade numbers), use a calibrated digital sensor like the BH1750, which outputs lux directly over I2C.
Can I plug S into a digital pin instead of an analog one?
It works but wastes the sensor: a digital input just reports whether S happens to be above its fixed logic threshold, which you cannot tune. Read it with an ADC and compare in code instead — you get an adjustable threshold plus hysteresis for free. (The KY-018 has no comparator or potentiometer; that is what distinguishes it from LDR modules with a D0 pin.)
Why do my readings flicker rhythmically under room lights?
Mains-powered lamps — especially cheap LED bulbs — pulse at 100/120 Hz, and the LDR partially follows it. Average a handful of readings per decision, or add small hysteresis between your on and off thresholds, and the flicker disappears from your logic. The same trick prevents a night light from strobing at dusk when the level hovers right at the threshold.
How fast does it respond?
CdS cells brighten-up in tens of milliseconds but take noticeably longer — sometimes over a second — to recover full dark resistance after bright exposure. That is fine for daylight logic and tripwires with generous timing, but for fast beam-break counting a photodiode or phototransistor responds orders of magnitude quicker.
Should I power it with 3.3V or 5V?
Match your board: 5V on classic Arduinos, 3.3V on ESP32, Pi, and Pico. The output scales with the supply and never exceeds it, so powering from 3.3V is the built-in way to keep the signal safe for 3.3V ADCs — no divider needed anywhere.

Related Tutorials