Cheating at 5V WS2812 Control to Use 3.3V Data

If you’re looking to control WS2812 (or Neopixel) LEDs using a microcontroller running at 3.3 volts, you might run into some issues. The datasheet tells us that a logic high input will be detected at a minimum voltage of 0.7 * Vcc. If you’re running the LED at 5V, this means 5 V * 0.7 = 3.5 V will be needed for the WS2812 to detect a ‘1’ on the data line. While you might get away with using 3.3 V, after all the specification in the data sheet is meant to be a worst case, it’s possible that you’ll run into reliability issues.

So usually we’d say “add a level shifter to convert 3.3V to 5V” and this post would be over. We even have a whole post on building level shifters which would work fine for this application. However [todbot] at CrashSpace came up with a nifty hack that requires fewer components yet ensures reliability.

bigbutton-front-backFor the Big Button project at CrashSpace, [todbot] used an ESP8266 running at 3.3 volts and WS2812 LEDs running at 5 V. To perform the level shift, a signal diode is placed in series with the power supply of the first LED. This drops the first LED to 4.3 V, which means a 4.3 V * 0.7 = 3.01 V signal can be used to control it. The logic out of this LED will be at 4.3 V, which is enough to power the rest of the LEDs running at 5 V.

This little hack means a single diode is all that’s needed to control 5 V LEDs with a 3.3 V microcontroller. The first LED might be a little less bright, since it’s operating at a lower voltage, but that’s a trade off [todbot] made to simplify this design. It’s a small part of a well-executed project so be sure to click-through and enjoy all the thought [todbot] put into a great build.

51 thoughts on “Cheating at 5V WS2812 Control to Use 3.3V Data

    1. I have. Funny (really, really funny) thing is the issue went away when the logic probe was connected. Since the original issue was primarily incorrect bit values, I would guess that it was rise time related with a near limit threshold. Why the problem went away with the logic probe connected really mystified me, as I would figure that to slow down the edge, but there are mysteries….. Bumped my supply to 3.6 and no more problem.

      1. I had exactly the same problem – when I connected oscilloscope probe, everything worked. Without the probe, data got lost and random colours appeared on the LEDs. To solve this problem, I cheated a little bit – I stuck a little piece of the ESD protective black foam (ICs are sometimes sold in it) between data and ground and the problem disappeared.

    2. I just make a small experiment with two power supplies: lowering the supply of an Arduino Uno until the WS2812 start to make errors. When the WS2812 is powered by precisely 5.0V, it make error when the Arduino is powered below 4.1V. At 4.1V it work as expected and the oscilloscope show a signal with just 3.0V for the high level. Heating the WS2812 with a oven require an additional 0.1V on the Arduino power supply, but the change is very small on the oscilloscope. I would say that 3.1V high level signal seem to be safe for this particular WS2812. But is the WS2812 power supply is increased, the 3.0V high level signal is not enough anymore.

      So for simple systems where the 5.0V supply is precisely 5.0V or a bit less, 3.3V signal should be ok with about 0.2V margin. The is more complicated if the WS2812 supply is for example 5.25V, only 5% higher than 5.0V. For systems where power supplies are not precise enough, a level translator is a good idea.

  1. Nice one.
    I use a WS2812B stripe with 5V vcc and 3.3 data directly from an esp8266. The pattern updates approx. 10 times a second, and every few minutes or so there’s a visible glitch.

    1. Has anyone tested the dropout of the CCS on the WS2812? Nominally, if that circuit is working properly, the brightness should be roughly the same at 4.3V and 5V, actually, which makes this circuit even slicker than you’d normally think.

      The highest voltage LED is probably going to be 3.3-3.5V dropout worst case, so I’d imagine brightness on the WS2812, best case, will be constant for all supply voltages above 3.6V.

    1. I’ve tried a number of “simple” solutions, and other than slapping a single-gate 74HCT buffer, none of them were reliable enough. Single-transistor level converters are fine for slow I/O and even some slow serial comms, but are too slow for the 800KHz comms here.

      I have used a voltage-dropped pixel here, and it works well in this specific application. Can you provide examples of other level conversion methods you’ve used successfully with WS2812 pixels?

      1. A transistor will run at many MHz, faster than you will get data through WS2812, Just put an extra resistor between base and emitter as well as the resistor in series with the base.

        But still, for lower data rates I like the WS2812 as voltage translator idea and it saves a uC pin if used as a status indicator. I will have to buy some now.

        Nice trick, I do it differently –

        Most 3.3v chips are rated to run from 3.0v to 3.6v so I run then at 3.6v when they have to send data to 5.0v chips. This also improves the noise margin for LVTTL to TTL and makes LVTTL or CMOS (only just) work.

        I will goto ebay and get some of these. Any tips on what to buy?

      2. Unfortunately, a lot of people offering single-transistor solutions are either repeating a design they don’t understand, or don’t explain how to vary the parameters of the design. Typically you have to adjust the base resistor and collector resistor values to accommodate higher speeds – this is fairly basic analog design, but the gist of it is if your edges are not fast enough on the oscilloscope, reduce your collector resistor value. Power consumption is worse for your run-of-the-mill BJT single-transistor level shifter, but it’s not significant in lighting designs where your total LED power consumption is going to be on the order of 100s of mA.

        I was originally thinking the same as Capmo (lots of stupid solutions are often offered on the internet, and a single transistor design works in almost all cases except in the higher MHz range, or when power is important), but if you wanted to use the extra pixel anyway for indicator LED, this is actually a very elegant design – the original indicator LED would have been a resistor + LED, and now for the same component count you get a level shifter (with better edges and lower power than just a transistor driver), and a better constant current source for your LED than a resistor (I think most of these guys have a built-in moderate-quality CCS for the LED drive).

        1. What is missing here is the knowledge that a bipolar transistor has a parasitic capacitance between the base and emitter connections, so when you bias a bipolar transistor ‘ON’ you are also charging this capacitor and the end result is that then the voltage to the base is removed the energy in the capacitor takes time to dissipate so the transistor will switch ‘OFF’ very slowly as it slowly drops through it’s linear region.

          To solve this problem you need to place a resistor between base and emitter to bleed off this charge. You should also ensure that if you have series resistor from the drive or uC the the resulting divider will still allow at least 1 volt at the base.

          The collector resistor can also be reduced to about 1k Ohms.

          It seems that many are shy of bipolars and prefer FETs now and that is fine with the more specific FETs that have internal compensation for specific tasks. The reality is that generic FETs also have many parasitic qualities and because there are so many types of FETs there is consequently a lot of different combinations of parasitic qualities.

          On the other hand there are only two types of bipolar transistors NPN and PNP and both have exactly the same parasitic qualities even if the polarities are different.

          TLDR; FETs are not going to save you from picking up a calculator and doing some basic math so learn what needs to be calculated or get used to the sound of popping FETs.

          You “go to”s for bipolars are

          Vce: Voltage from collector to emitter. This should be higher than your Vcc or higher again for driving inductive loads or put a reverse diode from collector to emitter to shunt back EMF from inductive loads.

          Vbe: Voltage from base to emitter. Always around 0.6v for bipolar silicon transistors. Germanium transistors are about 0.2v

          Hfe: The AC current gain – need to drive 1Amp with a Hfe of 100 then you need 10mA of base current.

          Cbe: the capacitance between base and emitter. Even if it is not specified it still exists. Use it to calculate time delays and filtering properties or bleed resistors.

          Cob: The effective capacitance (after Hfe) at the output – collector.

    2. Fully Agree. However… the premise here is hacking, not engineering, hence “Hackaday”. The kids come up with some interesting stuff once in a while, albeit generally not for production grade work. This one is a useful hack as it solves a problem one can reasonably expect hackers to encounter with this device, but would get an engineer fired.

      1. That’s because you’re slamming it into saturation – from which it takes time to recover. Correctly biased with a gain of 5/3 you should theoretically be able to get a 180MHz 3dB BW.

        1. My gut analysis is that the limit in the design here is not the transistor. In this case it’s at least the 6.8kohm resistor, which is essentially a pull-up resistor forming an RC circuit with your WS2812 load capacitance, and cable capacitance. The WS2812 has a rated input capacitance of at least 15pF. This gives a corner frequency of 1.5MHz with 6.8kohm. It is probably lower becuase of the long cabling typically used for these LEDs. To get good square wave digital signals through, you will probably need a corner at least 10 times higher than the base square wave frequency – 800kHz in this case.

          You should also notice that the drive is asymmetric – that is, it should take substantially longer for the positive rise time than the negative rise time. That is because your BJT only actively pulls the line low, but passively lets the line float up. You might have noticed that I2C works in a similar way, with only active low and pull-ups. This is also why the standard tries to limit the maximum frequency to 400kHz – in most common setups, it becomes increasingly annoying to go higher than that.

          There’s also the effect that was described by RÖB earlier, which in this particular design may also be more substantial, depending on the exact transistor part number and how bad the line capacitance is. It should result in a similarly asymmetric output waveform. Now that I think of it, it may be more a large-signal manifestation of the Miller effect. Either way, needs to be considered.

          The real way around this is to make a totem pole output – two transistors, one PNP and one NPN (or p- and n-channel). This way, one transistor is actively driving/speeding up the positive-going edge, and the other is driving the negative-going edge. At this point, you’ve pretty much made what’s inside an older-series 7400 inverter, and you may as well buy an inverter IC…

  2. What about some simple pullup logic: Decouple the 3.3V data output with a diode (cathode pointing to signal emitter) and add a single pullup resistor to 5V? Disable the microcontrollers’ GPIO pullup, of course.
    I know an esp8266 doesn’t tolerate 5V (it would just see 4.3V), but after all it’s heat through power that destroys it, not voltage. If the current stayed low enough it should survive. The current needed to safely trigger the WS2812 should be less than the max. “low” output current of the 8266. The pullup R is dimensioned to safely fit into that gap.
    Would this work?

    Oh, just a thought on the sending microcontroller:
    The GPIO output might go low with its internal pullup enabled for some reason, thus increasing the L current (two pullup Rs in parallel). Without careful design software could fry the GPIO. Hmm, datasheets and calculations, maybe sacrificing one or two 8266s.

    Or just desolder a schmitt trigger bus buffer from some scrap pcb… ;-)

    1. I think that would work as well. It’s still one extra component compared to using a single WS2812 LED + diode. Keep in mind the pullup resistor value needs to be modified appropriately for the higher required speeds, probably to ~1k instead of the 10k you usually see. It’s a little tricky on the 3.3V end in terms of safety and tolerance; I sort of avoid this sort of situation if possible, but my understanding is some current will go through the ESD protection diode on the I/O, and if the leakage current is limited there will be no actual damage to the chip.

    2. i have done something simillar using a diode and pullup resistor but there is one big caveeat, during reset, startup, sleep, ect any current flowing INTO the input MUST be SMALLER then the total current consumed on that powersupply rail, including power LED ect, otherwise powersupply may “float up”. possibly causing a lockup or damage to something.

      my setup was using a diode to “pull down” the pullup resistor (using data). was connecting 5v CMOS logic output to 7.5v CMOS logic input and the sillicon diode-drop makes it work (at low speed) and yes i understand that the speed could have been increased with decreased pullup resistor value.

      logic went like this:
      7.45vCMOS low=4.5v
      logic LOW: 0 + 0.7 = 0.7
      logic HIGH: 5 + 0.7 = 5.7

      original problem was (other) resistive loads on data pins pulled microcontroller outputs down to less then 4.5, or at least pulled down the edges of the signals enough to corrupt.

  3. Maybe also qualify that this is if you only have 5v available. About a bazillion projects out there are running quite happily on lower voltages. A 3.3v controller and a lipo being a common choice for portability.

    1. This is exactly right. If you’re running WS2812s off a LiPo at 3.7V you don’t need this. If you have a 3.3V power source capable of driving all the pixels, you don’t need this. (Even though WS2812Bs are only spec’d down to 3.5V, many work okay if powered at 3.3V) This is for the case where: a) you only have 5V available, but b) your micro is 3.3V.

      1. You mean, those resistor values are too slow for the WS2812. The RC will set a corner frequency in the hundreds of kHz range (15pF max input on the WS2812, plus PCB parasitics, wiring, etc), and that’s not including gate capacitance, maybe some miller capacitance I’m missing, etc. If that circuit doesn’t work, try a 1kohm resistor first.

        The other thing is this looks like a bidrectional shifter. It’s a unidirectional line for the WS2812, so you can move things around and turn it into a fast open-drain driver with one R and one Q. Either way, I would say that in this particular design, if you were going to use an extra indicator LED anyway, the posted design is actually more elegant than using an additional level shifter.

  4. Actually, by accident, I found that WS2812B works from 3.3V supply and 3.3V data directly.
    A) Parallax Propeller + 5V PSU for LEDs. F**k the standards for data.
    B) Arduino Uno @5V data + 3.3V PSU for LED. Accidentally had 3.3V DC-DC step down converter instead of 5V. Can’t get full brightness.

    Without any level translation! It’s not good practice, but for standard nerds it will work.

  5. Glad the first line says “you may have an issue” since I have only used 3.3v data with WS2812s and have yet to experience any issues.

    However, to be a bit more accurate regarding the specs, you forgot to accommodate hysteresis. The WS2812 data sheet calls this out at 0.35v, so technically (by spec, your results may vary) a low-high transition will be seen at 3.85v. One could say that this hack actually proves that actual parts are “out of spec” since the hack presents a 4.3v VDD which means you have a 3.36v point for the low to high transition ((4.3v *0.7) +0.35) and that is still above the 3.3V data line.

    In any case, I would also suspect that the 3.3v data line concern is really only a problem when you are pushing the data rate near limits as well.

  6. I have long used a “sacrificial” WS2812 as a line driver when I need to have the LED string far from the controller. Without this driver, I found that I couldn’t have more than a few feet of separation (with ordinary crappy wiring, anyway), but with it I could get at least the ten feet or so that I need for some of my lighting projects. Actually, just the chip itself will work if you want to be minimalist, and you can buy those on little PCBs that don’t have an RGB LED installed.

  7. Hmm I haven’t had an issue using 3.3V logic to drive them. But this is a neat hack for sure. It’s probably working for me since my WS2812 is a couple cm away from the micro.

  8. I’ve figuerd out an easier solution that does work for me:
    When you power your wemos over the 5 volt pin (propably not recommended, yes) simply put a fordward based diode between the ground pin and the ground of your power supply. Due to the diode the low gpio state will now output 0.7 volts while the high state will output 4 volts. This is more than 3.5V (5V*0.7) for ‘high’ and still less then 1.5V (5V*0.3) for ‘low’.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s