ESP32-C3 PWM, NeoPixel & I2C LCD: Wiring, Code and Simulator

To build this ESP32-C3 PWM, NeoPixel & I2C LCD project you need an ESP32-C3 DevKitM-1 and a potentiometer, a 220 Ω resistor, a yellow LED, a NeoPixel ring and a 16x2 LCD. One knob drives four ESP32-C3 peripherals: the ADC reads it, LEDC PWM dims an LED, RMT colours the board LED and a NeoPixel ring, and hardware I2C writes an LCD. Make the 13 connections in the wiring table, upload the MicroPython code, and turn the knob: the LED dims, the colours sweep the wheel, and the LCD shows calibrated millivolts.

Open this circuit in the free ESP32-C3 DevKitM-1 simulator

Parts list

QtyPartWhat it does
1ESP32-C3 DevKitM-1the microcontroller board
1PotentiometerVCC to 5V, GND to GND, SIG to an analog pin. Drag the knob; analogRead gives 0–1023.
1220 Ω resistorLimits current. 220 Ω in series with an LED; 10 kΩ as a pull-up or pull-down.
1yellow LEDLights when A (anode, the bent leg) is high and C (cathode) is low. Use a resistor.
1NeoPixel ringA ring of WS2812 pixels. DIN from a pin, VCC to 5V, GND to GND.
116x2 LCDCharacter LCD (HD44780). Wiring "full": RS, E and D4–D7 to pins (LiquidCrystal). Wiring "i2c": SDA to A4, SCL to A5 (LiquidCrystal_I2C, address 0x27).

Wiring

#FromTo
1ESP32-C3 DevKitM-1 3V3Potentiometer VCC
2ESP32-C3 DevKitM-1 GNDPotentiometer GND
3ESP32-C3 DevKitM-1 IO1Potentiometer SIG
4ESP32-C3 DevKitM-1 IO2220 Ω resistor leg 1
5220 Ω resistor leg 2yellow LED anode (A, long leg)
6ESP32-C3 DevKitM-1 GNDyellow LED cathode (C, short leg)
7ESP32-C3 DevKitM-1 IO4NeoPixel ring DIN
8ESP32-C3 DevKitM-1 5VNeoPixel ring VCC
9ESP32-C3 DevKitM-1 GNDNeoPixel ring GND
10ESP32-C3 DevKitM-1 IO516x2 LCD SDA
11ESP32-C3 DevKitM-1 IO616x2 LCD SCL
12ESP32-C3 DevKitM-1 5V16x2 LCD VCC
13ESP32-C3 DevKitM-1 GND16x2 LCD GND

Step by step

  1. Open the simulator. Open the BitForBytes Embedded Lab in your browser and start from the ESP32-C3 DevKitM-1. No install or account is needed.
  2. Add the parts. Add a potentiometer, a 220 Ω resistor, a yellow LED, a NeoPixel ring and a 16x2 LCD from the parts palette.
  3. Wire 1. Connect ESP32-C3 DevKitM-1 3V3 to Potentiometer VCC.
  4. Wire 2. Connect ESP32-C3 DevKitM-1 GND to Potentiometer GND.
  5. Wire 3. Connect ESP32-C3 DevKitM-1 IO1 to Potentiometer SIG.
  6. Wire 4. Connect ESP32-C3 DevKitM-1 IO2 to 220 Ω resistor leg 1.
  7. Wire 5. Connect 220 Ω resistor leg 2 to yellow LED anode (A, long leg).
  8. Wire 6. Connect ESP32-C3 DevKitM-1 GND to yellow LED cathode (C, short leg).
  9. Wire 7. Connect ESP32-C3 DevKitM-1 IO4 to NeoPixel ring DIN.
  10. Wire 8. Connect ESP32-C3 DevKitM-1 5V to NeoPixel ring VCC.
  11. Wire 9. Connect ESP32-C3 DevKitM-1 GND to NeoPixel ring GND.
  12. Wire 10. Connect ESP32-C3 DevKitM-1 IO5 to 16x2 LCD SDA.
  13. Wire 11. Connect ESP32-C3 DevKitM-1 IO6 to 16x2 LCD SCL.
  14. Wire 12. Connect ESP32-C3 DevKitM-1 5V to 16x2 LCD VCC.
  15. Wire 13. Connect ESP32-C3 DevKitM-1 GND to 16x2 LCD GND.
  16. Paste the MicroPython code. Paste the MicroPython code below into the code editor.
  17. Run it. Press Run. Turn the knob: the LED dims, the colours sweep the wheel, and the LCD shows calibrated millivolts.

MicroPython code

# ESP32-C3 (real chip emulation): one knob, four peripherals.
#   ADC   the knob on IO1, in calibrated millivolts
#   LEDC  PWM dims the LED on IO2 to match
#   RMT   the knob sets the colour of the board's RGB LED (IO8) and a NeoPixel ring
#   I2C   a 16x2 LCD on SDA=IO5 / SCL=IO6 shows the reading
from machine import Pin, ADC, PWM, I2C
import neopixel, time

knob = ADC(Pin(1), atten=ADC.ATTN_11DB)
led = PWM(Pin(2), freq=1000, duty_u16=0)
board_rgb = neopixel.NeoPixel(Pin(8), 1)
ring = neopixel.NeoPixel(Pin(4), 12)
i2c = I2C(0, scl=Pin(6), sda=Pin(5), freq=100000)

def nib(v, rs):
    d = (v << 4) | 0x08 | rs
    i2c.writeto(0x27, bytes([d | 0x04, d]))

def send(v, rs=0):
    nib(v >> 4, rs)
    nib(v & 15, rs)

def lcd_line(text, row):
    send(0x80 | (0x40 * row))
    for ch in "{:<16}".format(text)[:16]:
        send(ord(ch), 1)

time.sleep_ms(50)
for _ in range(3):
    nib(3, 0)
    time.sleep_ms(5)
nib(2, 0)
for c in (0x28, 0x0C, 0x06, 0x01):
    send(c)
time.sleep_ms(2)
print("I2C devices:", [hex(a) for a in i2c.scan()])

def wheel(pos):
    # 0..255 around the colour wheel
    if pos < 85:
        return (255 - pos * 3, pos * 3, 0)
    if pos < 170:
        pos -= 85
        return (0, 255 - pos * 3, pos * 3)
    pos -= 170
    return (pos * 3, 0, 255 - pos * 3)

while True:
    raw = knob.read_u16()
    mv = knob.read_uv() // 1000
    led.duty_u16(raw)
    colour = wheel(raw >> 8)
    board_rgb[0] = tuple(c // 4 for c in colour)
    board_rgb.write()
    for i in range(12):
        ring[i] = wheel(((raw >> 8) + i * 21) & 255)
    ring.write()
    lcd_line("Knob: %4d mV" % mv, 0)
    lcd_line("PWM duty %3d%%" % (raw * 100 // 65535), 1)
    time.sleep_ms(150)

What to try

Turn the knob: the LED dims, the colours sweep the wheel, and the LCD shows calibrated millivolts.

Frequently asked questions

How do I wire the PWM, NeoPixel & I2C LCD project on an ESP32-C3 DevKitM-1?

Make 13 connections: ESP32-C3 DevKitM-1 3V3 to Potentiometer VCC; ESP32-C3 DevKitM-1 GND to Potentiometer GND; ESP32-C3 DevKitM-1 IO1 to Potentiometer SIG; ESP32-C3 DevKitM-1 IO2 to 220 Ω resistor leg 1; 220 Ω resistor leg 2 to yellow LED anode (A, long leg); ESP32-C3 DevKitM-1 GND to yellow LED cathode (C, short leg); ESP32-C3 DevKitM-1 IO4 to NeoPixel ring DIN; ESP32-C3 DevKitM-1 5V to NeoPixel ring VCC; ESP32-C3 DevKitM-1 GND to NeoPixel ring GND; ESP32-C3 DevKitM-1 IO5 to 16x2 LCD SDA; ESP32-C3 DevKitM-1 IO6 to 16x2 LCD SCL; ESP32-C3 DevKitM-1 5V to 16x2 LCD VCC; ESP32-C3 DevKitM-1 GND to 16x2 LCD GND.

What parts do I need for this ESP32-C3 project?

An ESP32-C3 DevKitM-1 and a potentiometer, a 220 Ω resistor, a yellow LED, a NeoPixel ring and a 16x2 LCD.

Can I simulate this ESP32-C3 project online for free?

Yes. The BitForBytes Embedded Lab runs this exact circuit and MicroPython code in your browser for free, with no install and no hardware. The ESP32-C3 is emulated instruction by instruction on a RISC-V core running the official MicroPython firmware.

What does the code do?

One knob drives four ESP32-C3 peripherals: the ADC reads it, LEDC PWM dims an LED, RMT colours the board LED and a NeoPixel ring, and hardware I2C writes an LCD.

More ESP32-C3 DevKitM-1 projects