Shiny thing Fail, or Jim: RTFM!

I ran across running Neopixels with just 2 wires here.  Looked neat.

Unfortunately, despite many much more pressing tasks, that was too shiny to pass up, so I decided to try it.  Won’t take too long, right?  Following a pic in Tubular’s article, I soldered a 33uF cap and a BAT85 Schottky diode to the input end of a 5 LED WS2812B strip with a 2 pin 0.1″ header as input.  Fired up strandtest (with setBrightness(5) to decrease power), setting an adjacent pin as “ground”.  Nothing.

OK, we’re way out of spec anyway – maybe the ground isn’t good enough.  Tried a real ground.  Got maybe a few flashes (of more than 1 LED – so it must have been talking at some level).  Moved to pin 13, since that has a real ground next to it on the Arduino header.  Same – nothing more than flashes.

Back to original pins (A0/A1) and touched +5 to the power pin on the strip (with diode and cap still in place) – strip worked fine.

Article was originally on Parallax Propeller – do they have crazy high drive capabilities?  Checking… It’s a 3.3V part, and 40mA/pin max – same as Arduino.  OK, possibly lower output impedance, but not a huge difference.

OK, it’s a really clever idea, so what if I provide data pulses with more oomph behind them?  I happened to get some APM5943 (dual) logic level P-channel MOSFETs in the mail today, and so in my shiny-drunk took that as a sign/opportunity to try a full-power pulse train as input to the 2 wire device.  (Of course we need P-chan to provide high-side switching.)

Commence yak shaving

Unfortunately, those FETs are in an SO-8 package.  They’re not very useful for testing that way, so I really should make up some little breakout PCBs (like I did for the FDS6670 N-channel SO-8s).  Looked a little for an Eagle footprint, gave up and decided to make my own.

I’ve never really understood FET symbols, and I wanted this to be right, so I dug in a little.  “Source” and “Drain” are inverted on P-channel v N-channel.  Who knew?  And that means my one small memory crutch that “Source” sourced electrons only works for N-channel devices.  Rats.

I think I got that all sorted, and made the Eagle library part.  Of course in normal operation, unless you have a reliable rail-rail drive signal, you most always will want a gate pullup for a P-chan MOSFET, so I put some pads for 1206 resistors on the board.  Tried to make up a 6-up board of them, but you can’t copy stuff from a board with a schematic in Eagle.  Copied the whole board file (to new name) without an attached schematic, and then Eagle let me copy/paste my 6-up.  Etched the board without much trouble.

Can’t find my solder paste.  WTH?  Fine – populated 4 of the breakouts by hand instead of reflow.  Wired some flying leads.  Ready to try it out!

Back to shiny testing

Hooked the hacked WS2812B strip and MOSFET up using real +5, real ground, and my data pin.  Got very bright flashes, followed by Arduino reset.  In a loop.  Disconnected, scratched head.  Somebody’s drawing too much current.

Crap – the MOSFET inverts the signal!  I’d realized I’d need another transistor to pre-invert the signal (being too lazy to invert it in the library), but forgot about it.  Fine.  Rechecked LED strip (with real 5V) – still works.  Good.

A little breadboard, a 2N2222 with a 1K base resistor as an inverter and it was ready to try again.  Tried.  Nothing.  Looked at derived power pin with a scope.  Noisy (as expected), but only around 1.5V.  That probably won’t work.  Time to dig deeper.  (So much for a quickie project!)

On the bench with the good scope, I could see the bursts of serial data on the Arduino data pin, but not on the Din pin of the LED strip.  Huh?  OK – data at Arduino pin.  At the 2N2222 base, after the 1K – no.  Cut the 1K to 220 or something, and saw barely valid data pulses.  I can’t drive the 2222 fast enough.  We’re doomed.  Yeah, I could find a faster transistor, but no.

As long as it was right there, I looked at the MOSFET drain/Neopixel Din.  Of course I could see a pulse for each strip.show(), but not the individual data bits.  Connected gate directly to Arduino.  (This would not work for the application at hand – just a test).  No data bits!  So both transistors were bandwidth limiting me.  Time to give up.

The next day

I struggled the next day about whether to write it up – with title Shiny Thing Fail.  Projects fail sometimes – that’s fine.  But I’d put some work into this, and still failed to reproduce Tubular’s results.  (And since it was supposed to be a quickie, not justifying a writeup, I had no pictures.  All pics were after the fact.)

That low derived power supply bothered me.  Was that diode not really a Schottky?  I should at least be able to see some 0.3 or 0.4V pulses across the diode.  Back to the good scope.  Oh – to look across the diode and avoid ground problems, I’d need an isolated supply.  Blessed with a nice shop, I had my usual 2P 18650 Li-ion with female 0.1″ header, found a boost converter with 0.1″ male header in and female out, set and marked for 5V (though I did check that) and a pigtail with 0.1″ male header in and USB old type B out for the Arduino end.  I must have done something like this before. 🙂

Looking across the diode, I saw pulses – at about 1.8V PP.  Huh?  Verified diodes were BAT85.  Datasheet said 0.6-0.8V forward at 100mA.  Something’s not right.  Heat damage from soldering short leads?  Tested another one of the diodes at 85mA (DC): 0.68V.  Bridged that diode across the formally soldered in one, but still saw 1.7V data pulses.  Derived power was still ~1.5V.

Tried +5 to boost derived power.  LEDs worked, and data pulses at Din were back to ~4.7V.  Looks like we basically had the Arduino output pin beating itself up with nothing but its internal impedance to limit current thru the (Schottky!) diode directly to DC +1.3V/AC ground via that big cap. Didn’t try to measure those current pulses, but I guess they must have been big.

Last ditch effort:  With pulses potentially > 4V, that cap should at least eventually have gotten more charged than 1.3V.  Were the other LEDs drawing so much it could never charge?  Cut off top 4 LEDs, so cap only had to drive one.  Same results, whether in intended config or with real ground.  Oh well, Fail.

While writing this up, I thought I should read Tubular’s article (which I’d only skimmed before.)  And I came across this “tip”: “Have a bank of “phantom white pixels” after the physical pixels. The large number of 1’s in the data helps boost the average voltage”.  That makes a LOT of sense.  A couple of lines of code later to init the library for 100 Neopixels instead of 5 and write RGB 0xFFFFFF to the extras, and it works!  Even using another I/O pin as ground as originally designed!

The duty cycle of the data sent out by strip.show() was tiny in the strandtest example I’d chosen.  Here’s the difference between a 5 LED and 100 LED datastream at the + end of the cap.  Those nice wide bursts haul the average DC up from ~1.2V to ~2.4V – enough to make the strip work!  Tubular probably had code that refreshed his strip much more frequently than strandtest (which mostly sleeps, 20ms at a time) when he indicated it worked even without the “ghost pixels” to bump up the duty cycle and thus derived supply voltage.

Made a little video clip of one LED changing colors.  Soldered the other 4 back on and it still worked, but flicker with the camera frame rate made the video unsatisfying, so I went with the one LED version.  It’s here.

Takeaway

If I’d read the original post more completely (and understood the importance of the “ghost pixels”!), I could have saved myself a whole day of messing with this.  It then would have been the quickie I originally signed up for.

This entry was posted in RGB LED stuff and tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *