Logically invert the pin?

Posted on
of 3
/ 3
Last Next
  • Hi, I am trying to make a backlight using WS2812b for my nixie clock project. Here is a screenshot:

    I am controlling 5v Neopixel with 3.3v logic. As you can notice, when the microcontroller pin is high, LED's data pin is 0v, when the pin is low, LED's data pin is 5v. AFAIK Espruino's Neopixel lib is designed for non-inverted wiring only. Is there a workaround for my case? Maybe the pin itself can be inverted, so it outputs HIGH when being set to LOW and vice versa. The PCBs are already printed and I don't want to throw them away

  • I assume you need the level shift... because your driving mc pin is not 5V safe... but you do not want the inversion, do you?

    You need now to convert your inverting circuitry in a non-inverting level shifter... and with you PCB already done, you get out of this only with 'fix-wiring-in-the-air' and trace cutting... latter may be prevented...

    Give these approaches a shot:

    First is a bit a hack... The diode in the second is to make sure that the voltage on the input side is lowered, but has a negative inpact on the output, which raises the LOW... between 0.2V at lowest without Diode, and about 0.9 with Diode... To compensate for the first Diode, you may add one in the output as well in forward direction AND add a 33..68K resistor to ground... but that's a lot of stuff in the air...

    Second is a typical MOSFET level shifter.

    As a third, you may also use a 2-transistor - double inverter - after all you may just have all additional components at hand anyway ;-) - with:

    • no trace cutting
    • T1-Base on PCB (instead of T2-Base)
    • T2-Emitter and Collector on PCB (as originally)
    • R2-in-the air with one end on R3-+rail
    • R2-in-the air with non-rail, T1-Collector and T2-Base in the air
    • T1-Emitter somewhere on Ground / T2-Emitter

    3 Attachments

    • nonInvertingLevelShifter.png
    • levelShifterWithMosfet.png
    • doubleInverterWithTransistors.png
  • Thanks for that, but before hacking and messing with the wiring I want to try to fix this issue on a software level. If not, well, then hacking is the only way

  • Good luck... I was looking up whether it is possible to change the pin config to inverted logic as many devices allow... but did not find a thing (assuming you work w/ STM32F series of processors...). I hoped to find a possibility where you would poke some bit into some register and it magically happens... Since Neopixel is burned into the firmware, you may need a separate build...

    You did not answer whether you need a level shifter...

    Least messing is option 2.

  • By the way, is your fix possible with the BC817 transistors I already have?

  • Sorry, yes, a level shifter is exactly what I need here because I am controlling a 5v LED with 3.3v chip

  • Sure... because they are just plain general purpose, and the loads you put on them are way within their limits...

    For R3 you can keep your R82... and your R83 does not hurt... but it could be of higher resistance value, because you have now a double staged amplifier switch...

  • Higher like 10k? I have a bunch of different resistors to pick from (1m, 10k, 5.6k, 4.7k, 3k) which one fits most? I came to Espruino from web development because of JS, and transistors are still kind of black magic to me)

  • 10K is fine... Power seems not to be an issue, since you run anyway much more demanding things than just this transistor circuitry... R3 Suggests 33k, but 10k - if this your highest value - does work too. With this low power, DC signal, switching applications, it is not that critical.

  • What board are you running Espruino on? The Neopixel libs are all different.

    I think you might be able to make it work on STM32 using the old school SPI.send4bit method with different bit patterns, and on NRF52 you may be able to use NRF52LL to create an inverter using PPI - but all the others would require a source code change and rebuild.

    No guarantees though - SPI may change its state when idling which would break it.

    It's been on my list to try and bring all the Neopixel code into one common codebase, and then to add exactly what you're suggesting - an option to toggle the polarity. Haven't had time yet though!

  • I am running Espruino on my own nixie clock board with an STM32F100CB chip. How does SPI.send4bit method works? I mean WS2812b protocol requires 8khz rate, how can I match this with SPI?

  • Check out https://www.espruino.com/Reference#l_SPI­_send4bit

    The old way of doing neopixels on STM32 was:

    SPI1.setup({baud:3200000, mosi:B5});
    SPI1.send4bit(leds, 0b0001, 0b0011); // send to the lights

    and that's basically what still happens under the hood.

    If you tried:

    SPI1.send4bit(leds, 0b1110, 0b1100);

    instead then it might invert everything for you.

  • Thank you, I will try this tonight. By the way, if my signal is inverted, does this mean, that I should keep the pin HIGH all the time when I am not sending bits? And how can I achieve this?

  • I forget what's needed - you'd have to look at the WS2812 datasheet.

    It might be that the last bit of the data that is sent on SPI is enough to set the resting state of the line. However if it isn't then I'm afraid you're out of luck

  • I tried this:

    SPI1.setup({baud:3200000, mosi:B5});
    // like so
    SPI1.send4bit([1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1], 0b1110, 0b1100);

    This should turn the first led white, but did nothing :(
    Is this wrong?

    I also found this guide showing how to control WS2812 with PWM and DMA. This is a very efficient way, as they say. This guide is far beyond my understanding. Is something like this available with Espruino?

    When I started this project, I thought that the LED part would be easy and fun. Already wasted four days on this problem, lol)

  • Try:

    leds = new Uint8Array([255,255,255])
    SPI1.send4bit(leds, 0b1110, 0b1100);

    The bits are already split up for you.

    DMA is used on nRF52 but not STM32 - however the code that's in there works great and has been in use for years without trouble, so I'm loathe to change it.

    I'm not sure their PWM via DMA approach is better than the current SPI+DMA approach though.

    That thing I mentioned about bringing all the code together would hopefully involve using DMA, but that's another can of worms since it has to be made to work on all platforms as well.

  • Sun 2018.11.04

    Hello @George,

    'I thought that the LED part would be easy and fun'

    Yes, if this were an LED. This is in fact a Neopixel. Much more fun! ;-)

    'Already wasted four days on this problem'

    Nothing about what you are in the process of learning is wasted. Imagine Thomas Edison, 'I've just found 10,000 ways that won't work!'

    I re-read #1

    You are in fact just re-discovering methods that prove the limitation of the circuit board data input inversion!

    Note that I don't have access to a scope to verify the following . . . .

    I re-checked the device data requirement:


    The reset pulse required for the 5050 is a low state, greater than 50usec

    Although @Gordon #16 suggestion leds = new Uint8Array([255,255,255]) will turn the first Neopixel in a strip white, this will only work when on a non-inverted circuit, as you already have discovered.

    https://www.espruino.com/Reference#l_SPI­_send4bit    bit0 - The 4 bits to send for a 0 (MSB first)

    So if SPI1.send4bit(leds, 0b1110, 0b1100); sends the correct reset pulse, your data will need to be inverted. As a suggestion, try the middle road leds = new Uint8Array([127,127,127]) on the first test. Better yet, leds = new Uint8Array([90,165,15]) e.g. 0x5A 0xA5 0x0F Alternate the bits, in case the inversion is changing the reset width too much. If the reset pulse is detected, some color of some sort may be seen.

    Depending on the number of Neopixels there are, send more data. For the above circuit of three, send nine bytes or more. It's possible that some data might get detected as the reset.

    In #10 above Gordon pointed out:

    'No guarantees though - SPI may change its state when idling which would break it.'

    My guess is that this is in fact what is occurring that the data line is remaining in a high state, so a low reset pulse is never seen at
    the correct place and at the correct time interval, in the data sequence.

    As you discovered in #15 SPI1.send4bit([1,1,1,1,1,1, may work, if you are able to prove being able to send that reset pulse.

    In your circuit, remember that data is inverted, so the above code is sending a continuous stream of set the output to black.

    Although there hasn't been an indication of how many circuit boards, it seems from #1 'for my nixie clock project', only one or two perhaps?
    Four days have been spent researching a software solution when I believe @allObjects had the best suggestion in #2 Just lift the base of the input data transistor and tack solder a matching flying transistor and input resistor. Should be able to tack solder on top of the existing one without having to remove it.

    Here is yet another simple schematic showing the same - unless others disagree, two common 2n2222 should also work.


    What case package is being used? TO-92    TO-236AB perhaps?

  • Sun 2018.11.04 (after five hours of reading and thinking)

    It appears I may have to retract a bit of what I just posted.

    After doing a wee-bit of research, I had to re-learn how a data one and data zero are created.


    Under heading 'Writing Your Own Library' (Unable to paste as it is an image)

    2nd pp "There’s a math goof in the datasheet’s timing values. Use these figures instead:"

    As both a data one and a data zero start with a logic one at the leading edge, inverting the signal as in hardware #1 above, would mean that a leading edge could never be detected accurately. Data therefore could never be sync'd and decoded as sending the inverted data in software, would mean the duty cycle as seen by the 5050 would start with a leading zero, which doesn't mark the beginning of a valid data value. It might be that one could fake that using values near the middle of the range, say 0x0F by catching the declining pulse in an inverted data bit stream
    as the leading edge, but then precise data could not be sent, meaning no color control and the zero state latch/reset value could not be sent correctly.

    I now don't believe it is possible using software based on the above article and included datasheet.

    The actual neopixel module source might be of some help in understanding:


  • @Robin, thanks for the encouragement) I have tried sending data as you offered with no effect. I feel that there is nothing left to try with the software part. Another reason why I was evading hardware fixes is that all my components are SMD, and transistors have the TO-236AB package. I have a soldering station with a hot air gun, so soldering these components on a factory-quality PCB is fairly easy. But I can hardly imagine how to make this "in-the-air" fix with SMD components. Resistors are SMD too, they are 0805. So here comes the tricky part.

    By the way, I have two separate lines of Neopixels. One of them is on B5 and another one on B6 port. There is no SPI on B6. I have seen, that latest Espruino version can setup SPI on every pin, but does it have enough speed to control the Neopixels?

    Here is how my whole project looks like. Just in case.

  • I noticed this thread is posted under other boards, may I ask which board you are using, as the answer is, depends. I can provide more, knowing that based on my successes.

    Also, did you catch #18 as I made a post at the same instant your #19 came through.

  • Yep, I've seen it. I am using my own board and I made a custom build of Espruino for it. Nothing special, it is based on STM32Discovery with the package changed to LQFP48 and some more little tweaks. I also used pin_names_direct as @Gordon offered. I have posted a link to my board PCB layout and diagram in my previous post.

  • Ahhh,

    'I was evading hardware fixes is that all my components are SMD'

    Had a hunch that might have been the reason. Did my prototyping with a breadboard, so made a false assumption there. Might have been what @allObjects was thinking in #2 above also re:TO-92. Now I look at my strip and the SMD stuff there and have to agree, not easy. If fact near impossible?

    ' I am using my own board'

    So does this board then only use hardware SPI ? e.g. is it capable of software SPI ?

    ' I feel that there is nothing left to try with the software part'

    Do you agree with my #18 assessment based on the article pp and datasheet data zero and data one diagram?

  • Do you agree with my #18 assessment

    Absolutely. Thinking on how to add one more transistor on each line there. There is enough room, but I want to minimize the mess.

    So does this board then only use hardware SPI? e.g. is it capable of software SPI?

    I have no idea. The datasheet says that there is an SPI on the B5 pin. I am using Espruino's SPI.setup function. When I use it on the B5 port it is ok. When I use it on B6 port there is an error "ERROR: Pin B6 is not capable of SPI1 MOSI". I don't know what characteristics a port should have to be capable of a software SPI. As I mentioned earlier, there is this line in Espruino's 2.0 update notes:

    Software Serial Transmit and Receive on any pin

    Isn't this an SPI? This looks very promising.

  • ...take a look at this conversation about Hardware OR Software I2C/SPI/USART/... and HOWTO do it. I hope it of some help to you.

  • EDIT: Post #24 with link to post created around the same time, arrived simultaneously as I posted #25 Apparently answers what I mentioned below, I was unable to check.

    EDIT2: (3 hours later) disregard edit apparent above - either a load of doc pages have to be fine tuned (which would have been completed before 2V0 press release) or my original hunch stands based on:


    'Some boards such as those based on nRF52 chips can have SPI on any pins'

    'On STM32F1-based parts, you cannot mix AF and non-AF pins (SPI pins are usually grouped on the chip - and you can't mix pins from two groups)'

    When I saw pin B5 I immediately thought, must be running on a Pico as one of the three hardware SPI pins is B5

    Just checked: (is that the same as your project?)


    and that reference indicates 2 hdwr SPI pins, also B5 and B15 similarly to the Pico


    Now if one checks the reference of



    ex: '32 x GPIO (capable of PWM, SPI, I2C, UART)'

    Then I saw your error:

    'ERROR: Pin B6 is not capable of SPI1 MOSI'

    I thought I saw that error in the source, close but not exact,


    but I did find this on Line 92

    '* On some platforms like STM32, pins capable of hardware SPI MOSI are required.'

    So, although I would verify this with @Gordon, as the older boards (that I am familiar with) required hardware SPI, I have made the assumption, without further checking, that the new 2V0 software SPI feature was available on the newer hardware, the Pixl and MDBT42Q

    I'll agree that in the link you mentioned that this topic could be mis-understood.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

Logically invert the pin?

Posted by Avatar for George @George