12 day project: ESP32 - LED controller

Hey all,

I thought I would document my progress through this whole project on the forum so you all can see the progress and milestones.


Like most other makers I like bright exciting stuff, enter the WS2812B, Neopixel, GlowBit, etc.. They go by many names, I have too many and want a centralised way to control them. This project will start from the idea that I've been brainstorming for a while and pull it all the way through to a PCB (hopefully - in 5 days; amongst some other projects).

Goals for this adventure

  • Have a somewhat working project at the end of the project - have it uploaded to GitHub under an open source license so that those that are curious can jump in and understand it
  • Understand some new technologies and hopefully learn some new things along the way
  • Document the decisions and difficulties along the way
  • Share some resources that I found useful
  • Not procrastinate

Getting started

  1. Get the ESP32’s working - Arduino is great but Micropython allows for SUUUPER quick development so we need to setup my spread of MCU’s with the new firmware
  2. Verify that we can get some LED’s blinking
  3. Remove wires (Personally I’m not a huge fan of MQTT so will try to avoid it) - Investigate some wireless protocols to make the LED’s flash - ESP-NOW looks very promising
  4. Make everything work together and invesigate a circuit that lets me breakout from the breakout board
  5. Wait for the PCB’s to arrive

What exists already

  • FadeCandy -this board packs all of the punch when it comes to controlling the LED’s but doesnt have wireless
  • QuinLED - This board packs almost everything, wireless, high power handling - but I want a couple more features, a few more connections (PiicoDev/I2C, A couple digital and analog IO for sensors, maybe UART)
  • Plasma 2040 - Much like the FadeCandy but packing an RP2040 and a few more IO, still very close to what we want

Desired features

  • Already discussed: Wiresless, control some LEDs, more inputs,
  • Feedback for voltage drop over the strip and compensate (the colours deteriorate quickly if there isnt enough juice
  • A super small footprint - Ideally something that can sit off to the side rather than inline
  • Some nicities to run the strip - A smoothin capacitor, a logic level shifter to make sure the data
  • Onboard 5V regulator

Flashing the Devboards

I’ve got a few ESP32 boards

These 2 guides got me across the line flashing the MicroPython firmware:

And verifying that the interpreter is running (App used here is CoolTerm)

Getting WS2812's working

From the MicroPython docs page I copied over the code and got a GlowBit Rainbow working



Day 2: Wireless - ESP-NOW


ESP-NOW is a 2.4GHz communications stack allowing you to send packets of 250 bytes to another ESP module. ESPRESSIF boast that its lower power and real-time but that isnt critical for this project.
Here are the docs for MicroPython: espnow — Support for the ESP-NOW protocol — MicroPython 1.17 documentation

Getting started

To be able to access the ESP-NOW libraries you have to upload a different set of firmware, since we already have micropython on the ESP32 it is much easier and you can use Thonny to load it on for you(I havent tested with an unflashed board), I downloaded this repo as a zip and sniped out the GENERIC.bin file.

At the moment I’m tinkering around with the ESP-NOW code to see if I can run 2 serial connections from the same PC.
EDIT: YOU CAN! In Thonny head into Tools>General>Untick ‘Allow only single Thonny instance’, open a second window and you can connect to different boards at once!

We've got the ESP-NOW working

With a couple of modifications ot the code the 2 ESP32’s are now talking to eachother:

Time to add a few niceties and post it.


Upcoming project sneakpeak....

Inspired by Jim’s Environment Monitor project and some other weather stations, I thought I’d have a crack at it. The Stevenson screen that a lot of Makers use have a lot of supports. I dont like wasting material so here’s my take. A supportless, geometric mess - hopefully it keeps the rain out :slight_smile:
I think its optimised for almost everything except print time - 17 hours!


Day 3 updates

Last night I got the code working to send RGB values over to another ESP32, ran into an issue where if the neopixel library was imported the ‘e’ structure(function/variable - not sure what Python explicitly calls it)
Looks like its a module specific class

Gets overwritten or something funny happens behind the scenes resulting in this error:
To get around it I added the LED colour changing code into my own module - its a very dirty implementation at the moment but it shall be cleaned in the future :tm:

The Repo is now live, all of the kinda working code is there and the concept is somewhat nailed so onto the other features:

More inputs and the small footprint are easy , just breakout some pins in a friendly manner.
I’ve got a few large smoothing caps from my other LED strips, it’ll just go on the PCB
I reckon the logic level conversion can be done with the breakout board still, just some smart design to keep it small

I’ll nail down the voltage drop on a breadboard before moving to the PCB design - I think a simple voltage divider ought to get me out of trouble, step down the 5v into a workable range for the ESP32’s ADC to read.
It doesnt cover all of the failure modes but the boards should be cheapish to replace and the time spent working + new parts might end up costing more.

.I’ve got one of these ESP-32 modules on hand at the moment, the size is good - but Im not certain that its compatible with ESP-NOW (I think it is but not sure :thinking:) No harm in trying this one!
All of the necessary documenation is found in the datasheet on Core’s page:

Oh and the Stevenson Screen finished printing - the mess up the top is intended. to make a model supportless there sometimes has to be some sacrifice :frowning:

EDIT: Compatability has been tested with a couple PiicoDev modules a while ago using the LoPy4


Testing the voltage drop across a strip

My excess of LED’s helps a bit here. I theorise there are two ways you run into this issue, both being interwoven. And can be easily cimcumvented by injecting power along the length - however if the strips come in IP rated sheaths it the waterproofing is gone :frowning:

I wired up 10m (600 LED’s) of strip with a couple of headers on the end, ran the strip with each LED trying to output RGB: 45,45,45. You can clearly see the change in colour on the end of the strip

Code and further details for this experiment

I used a 5 V 6 A PSU to power the strip, above a brightness of about 30 the colour starts to change.
At this point the voltage drop is about 1.2 V.
I speculate that most people would be using a 2/4A PSU and maybe 5M/ power supply best case

Testing with a brightness of 128 (above doesnt make too much of a difference) the voltage drop was ~1.35 V. at 255 (Max brightness) the voltage drop was ~1.45 V.

Conclusion: Ideally we would be sensing with an offset and gain so that the analogue input is mapped between the power supplys voltage input(V) and V/2) to get the most out of the 12-bit ADC on the ESP32.

import neopixel
import utime

print('----------RX Board----------')

np = neopixel.NeoPixel(machine.Pin(21), 600)

c = 45
c = (c,c,c)

for i in range(600):
    np[i] = c
#     np[i-1] = (0,0,0)

To keep things easy to source and assemble, a voltage divider will work a treat.
To find the upper bound of the ADC I refered to the MicroPython documentation (it is also on the ESP32 electrical specifications datasheet). 1V is the maximum unattenuated voltage (not a concern on most other devboards) - and I’ll stick to this as any software mishaps wont break anything.

With some cheeky math I arrived at a voltage divider consisting of 10k and 2k2 ohms. Check out the excel sheet for how the voltage is mapped out.

Obiously you’d want something a bit more balanced in practice but if someone wants to make one of these they have to source x more amount of parts. KISS.

At this point it is paramount that the microcontroller is powered on THEN the LED strip, voltages fed back into pins that arent powered up can destroy them. That’s due to an input having a maximum voltage of something like 0.7 x Vdd, over time powering up the system incorrectly it will destroy the ADC pin (maybe even the whole MCU).

On the final design a MOSFET will control the strip being powered on, hopefully also saving some power as WS2812’s quiescent current is 1 mA @ at large numbers it adds up!

EDIT: Just thought I broke the LED strip but a wire came loose. Tested the output with the whole system at 5V (no LED’s on) and across the power supply directly (5.1 V) and the output was still below 1V - Max of 0.94 V with the PSU directly. The IO is tolerant up until 3.3V so should be good.


Hi Liam
Regarding voltage divider.
This scenario works only if Vout is open circuit or into a high impedance load. Other times the load is in parallel with Z2 and must be considered as part of the divider.

This also applies if measuring voltage across a high impedance load even with a DMM (10MΩ input R). The meter (DMM or Analog) input resistance must be considered when measuring voltages with any voltage divider action which a large percentage of measurements are.
In your particular case here if you were just measuring the voltage at Vout Z2 is so small relative to the DMM resistance it can be ignored. But Z2 was say 22MΩ the error would be very significant
Cheers Bob


Hi Bob,

Cheers for chiming in! I havent measured the impedance on the ADC myself but have assumed its high enough to be negligible.
I landed on size of the resistors from a previous projects passive current draw and didnt want to swing into the extremes either way.

Since youre coming from industry I can see why all of these have to be reviewed. I’m still learning a ton from each reply.



Hi Liam

I attempted to do so some time ago but the highest resistor I had on hand was 22MΩ. In theory it is not that hard to get an approximation using the ADC itself as a sort of voltmeter.

  1. Apply 5V directly to an analog input.
  2. Monitor and note the ADC value (1023?)
  3. Apply the same 5V to the input via the highest resistor you can find. Up in the hundreds of MΩ if possible.
  4. Note the ADC value
  5. Consider the ADC itself as the lower leg of a voltage divider and work out the ratio using the ADC numbers. Knowing the value of your resistor you should then be able to work out the approximate Analog input impedance.
    You can expect it to be up in the GΩ area, I think from memory I found about 2GΩ but I had interference problems with the high resistances my set up and had to kill it with 10µF and then measure over 5 time constants which means my estimate was probably on the low side.

Another experiment worth demonstrating to illustrate the effects of a meter.
Measure a 5V supply with a DMM. Then measure the same supply via a 10MΩ resistor. The result will be 2.5V as the meter resistance has now become the lower leg of a voltage divider.

I guess what I am getting at here is be careful describing things like what looks like a simple voltage divider without explaining what effects different loads will have. Failing to consider this could mean some poor (inexperienced) bugger will build up a circuit using a divider to adjust voltage (even a potentiometer as that is what a pot is used for) connect it to a load and then start to panic when it does not work as expected and go off looking for faults which have been built in.

Believe me things like “built in” faults can be a real pain in you know where. Like design problems that haven’t been picked up in the test room and don’t manifest until you get in the field and the real world.
Cheers Bob


Hi Bob,

Yeah good points, with this project I think I’ll try and lock in some values and link back to your explanation with some of my own additions - a ‘good enough’/well placed passive power draw was the main consideration.

I cant even imagine the feeling when a system has been deployed and a fault occurs. It definitely backs up the idea that even with ‘accurate’ modelling some real world tests should happen.

Cheers again Bob!! :smiley:

Trying to get a measurement has been a bit of a struggle, the code in the documenation and the fact that ADC1 is used by WiFi (ESP-NOW uses the same systems) is the only written ADC’s for this version of the firmware. I’m not overly keen on learning to modify, build and test firmware so will come back and try and find a solution to this later(plus the ESP32 module that I have only features a single ADC - Technically 2 but the other is used as a reference voltage). At the rate the engineers at Core are working there will be a module for everything soon!

Due to the silicon shortage and the additional cost($3 ea from Digikey!) I wont feature a USB to serial connection on the PCB itself, Instead you’ll have to grab a CP2104 breakout (or another Serial to USB converter) to complete the breakout board equivalent.I think you could use a Pico instead of a USB-Serial chip - couldnt find anything on that though.

Onto the PCB!


Hi Liam
Sorry, I had not read through the whole thread/project and did not realise that divider is a real thing connected to an Arduino analog input. In that case the input resistance is so high it can be ignored.

I only read that post in isolation and the voltage divider bit came across as a general description. I picked up on all the bits missing which can cause headaches if not considered in the application of such a network. Sorry about that and I apologise. Will read in more detail in the future.

While on this subject though there is one thing often neglected in relation to potentiometers. Power rating. when a pot is rated as being able to dissipate say 1Watt. This means it can dissipate this power OVER THE WHOLE LENGTH of the resistive element. So if for instance you have a 1k 1W pot connected as a rheostat (variable resistor) and only are using 500Ω of it the dissipation capability becomes 0.5W. More than 1 person has come unstuck by not considering this.
Cheers Bob


Hi Bob,

No worries at all! Its quite a long topic and I definitely could have included something in that particular reply specifiying that it was going into one. Nonetheless it sparked a great discussion.

That would have completely slipped my mind, I’ve only used large pots >5k on logic level signals up to about 5 V. I’ve got a couple high power projects scoped out where this could be an issue if not taken into account. For most projects PWM has gotten me out of trouble - and a pot is just used as an input to an analog input/ a couple of OP AMP circuits at uni.


Day 4 - Designing the PCB

Using the schematic from this breakout board we can understand how it works and begin a schematic for our stripped down version.

Doing some more digging I came across this reference doc for designing boards with an ESP32 module.

Doing some research on BOM optimisation I figure that most makers would not want to buy the specific SMD components to get one together I opted for JLC’s assembly service. My original idea had me picking up a capacitor and resistor book - which would be great for prototyping. For all of the other components picking them off other boards - I was eyeing the juicy power supply from the SD card adapter.
This also means that you would only have to get major components and optional ones at that, such as the PiicoDev connection, an ADC, headers, 5V regulator and the logic level converter (the pin will have a resistor attached anyways).

This video was super helpful in giving some direction to my decisions: Episode 485: Bonus Content: How To Make A Custom PCB From Design To Assembly - Full Video - YouTube

Upon checking compatability of the .bin for the ESP32-C3 (the module I have. plus a couple devboards with the same chip on the way) it looks like it’s untested. At this stage I think I’ll continue with the PCB and might have to whip something up in Arduino if MicroPython doesnt work.


MOSFET Selection

To make the system efficient as possible the Rds of the LED should be as low as possible. Having a logic level of 3.3 V on the board will make selecting a power MOSFET slightly more difficult - Most 5 V DC barrel jack PSU’s start to max out between 6-10 A (Though the connectors max current rating is a bit how ya going at that amount).

This guide retouched the info that I’ve learnt from the forum and uni: https://www.digikey.com.au/en/blog/how-to-select-a-mosfet-for-logic-circuits-or-gate-design


Hi Liam
That is a pretty good link with some useful info re Mosfet choice.
There is a paragraph that all should read.
Input Capacitance - Ciss: The combination of the gate, oxide layer, and the body connection of a MOSFET act as a small capacitor that begins charging when voltage is present at the gate. It takes time to charge which results in an ON-state delay. Choose a MOSFET with the lowest input capacitance possible to avoid long delays and to minimize in-rush current which can be very high initially but lessens as the capacitor charges. Ideally, the ON-state delay is extremely short but may create enough surge to damage an I/O pin that has limited current sourcing capacity.

This is a subject I harp on a bit in my replies with particular reference to cumulative damage to low current I/O points. Indeed Core market a relay with driver board SKU Pololu 2480 which is quoted to be logic a level and would be attractive to anyone driving a relay with Arduino or RPi which has no gate current limiting resistor. I have been recommending a series resistor of minimum 330Ω be included to limit this current to a safe value.
Cheers Bob


Hi Bob,

Yeah it was the best one that I could find outside of reading a whole chapter from my textbook.
Everytime I’ve seen you mention it I can imagine its saved them a few questions and money down the line replacing a microcontroller.
That’s very interesting that Pololu hasnt included the resistor, usually theyre pretty good with their schematics - even a solder bridge and optional resistor would’ve been perfect. Might be worth linking to one of your replys on the product page to make others aware!


Day 5 - Schematic and EDA

To learn KiCAD I recommend taking a look at some getting started tutorials:

For general circuit design

  • Watching what the Core engineers make, and reverse engineer some boards
  • Getting involved in different faculties - Electronics relys on math, science physics, the obious ones. But there are other skills that are applicable; writting good code relies on English, Taking one out of Medicine’s book as it relies on lots of interconnected systems and levels of survival (plus the brain is an amazing computer), etc etc
  • Understanding electronics in general - and getting curcious about how stuff works helps lots here

After spending some time nutting out the schematic and plannging roughtly how everything will work together I think I’ve landed on a final design. I’ve learnt from someone that its worth getting something physical infront of you to review rather than trying to examine the digital copy.

This circuit is simiar to the ESP32-C3 Devboard, the circuit that I whipped up on the breadboard.
Mentioned breifly before I havent included the CP2102 as you can grab one for other projects and flashing multiple of the LED controllers - I plan to make a a DIY protoboard circuit so we can replicate the auto flashing circuit.(controlls the flash and reset pins)

The plan with the V1 of the board is to physically cut down the logic level converter to save a little bit of space - check out my other forum topic where I cut a Pico down

I’ve already started to consider the layout of the PCB, since there is effectively a ‘high power’ side of the board and one that is sensitive to RF considerations must be made to ensure there isnt any crosstalk (not sure if this is the correct jargon) between the sections).

ESP32_LED_Controller_v1.pdf (72.9 KB)

EDIT: Updated schematic, fixed the shorting caused by the MOSFET


Love the design-along format :ok_hand:
Setting realistic goals at the start of a project is one of the best ways to ensure it gets done at all, let alone on time.


Hi Liam
What does this do

Except short Vin to ground when activated ???
Cheers Bob


Hi Bob,

Looks like my midnight brain made a mistake there, The LED strips input should in the place of Vin.

I’ll get that fixed up and update the schematic, thanks heaps for catching that!

Cheers Michael! I’ve had plenty of projects fall due to scope creep and wanted to make this one a quick project, making changes when I have some time.

EDIT: Updated schematic, now the PSU should like the circuit a bit more :smiley: