Bare Metal Bit Banging: WS2812B Driver

Поделиться
HTML-код
  • Опубликовано: 18 дек 2024

Комментарии • 50

  • @davidlarsson7555
    @davidlarsson7555 11 месяцев назад +16

    Great video! Thank you!
    One thing I noticed was that you will only have either 255 or 0 on the RGB channels, since you only check bit 7. So, if you would set the channel to 0x70 for instance, then you would get no color in that channel. You'll probably want to do if (r & (1

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад +6

      Ahhh you're right, don't know how I forgot to shift 🤦‍♂️

  • @tamas-ruszka
    @tamas-ruszka 11 месяцев назад +3

    You are back, wohoo! (while I was waiting, I started watching your oldest videos) A fun story about the WS2812 family: I have the WS2812C and I tried to place on the PCB without checking its datasheet. The problem is, that I assumed that the pin 1 is the marked corner, (just like on every other components) but in reality it's on the oposite side of the led and the marked pin is pin 3, so I had to spent many hours debugging my design. A good tip to everyone: you should always double check your datasheets!

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      One more reason to be grateful for the reverse polarity protection they built in!

  • @emasheep
    @emasheep 11 месяцев назад +5

    Was completely stumped by why it was working without the bit-shift at all... but given your "0/255-only" use-case, the code works just fine :D
    Edit: reminds me of a friend who was using "OTTO" as text to display.. and realizing quite late in the project, that his code was sending the string backwards.

  • @StreuB1
    @StreuB1 11 месяцев назад

    This is one of those videos for a channel that you have never heard of before, and you just sit and watch with your mouth open. This was absolutely unbelievable. The bit at the end where you lamented that getting an arduino or an STM32 is the easy part, but then OK, I can flash a LED. But then what?? How do I develop code? Rather how do I even start or go about developing a project?!?!? Where and how do I start?!?! If you don't know, you honestly don't know. That is where I have been for 2 years, since my initial C++ course. I have bought arduinos, STM's, ESP32, but I have no idea where to start, more so how to start a project.
    One in particular that I want to do and have had no idea how to begin. Is to literally send a simple query request to a device using MODBUS every 100ms (or 250ms really...), then receive the response, take that number and do a calculation with it, then output a pulse train from it. It seems super easy, but no idea where to start. How do I even generate an accurate pulse train with an ON time that comes from my calculation???
    This video sort of gave me a place to start.
    I believe I would use one of the MCU's hardware counters instead of trying to use software as I need the software to do the communication and the calculation based on the received communication. I think I would need to use interrupts as well. Gave me more to think about and I think some type of a pathway forward. Its amazing how watching someone explain and do something, breaks down the fear of trying it yourself. Fear of failure is so insidious. 🙂
    Thank you so much!! Subscribed and looking at your other videos shortly!

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад +1

      Thank you for this comment - I'm really happy to hear that this video gave you a direction to follow. I know how opaque this stuff can be, and how hard it is to find quality resources. Take a look at the bare metal programming playlist if you're interested in going further. I used it as a vehicle to discuss a lot of the areas that are often taken for granted in embedded, like understanding datasheets and reference manuals, memory mapped IO, how to use peripherals properly, etc.

  • @InfiniteCoder01
    @InfiniteCoder01 11 месяцев назад +2

    A year ago, I've got my hands on a WS2812B LED strip, I did a 12 by 12 matrix powered by ESP12F. It was much fun. I've programmed it through ArduinoIDE and Adafruit library. I even did some self-playing games like snake and tetris

  • @josemiguelperricone5993
    @josemiguelperricone5993 11 месяцев назад +3

    Great video. 🙂 You forgot to shift the leds values.

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      Ahhh you're right, don't know how I forgot to shift 🤦‍♂️

  • @user-qf6yt3id3w
    @user-qf6yt3id3w 10 месяцев назад

    One technique I've seen used in a lot in vXWorks board support packages is to calibrate a spinloop based timer against a slower hardware timer. The idea is you spin incrementing a counter starting at one timer tick until the next one. That then tells you "x counter increments equals one timer tick". E.g. on PC AT hardware the PIT timer runs at 18.2Hz, i.e. a 54.945 ms period. So if you know x timer increments equals 54.945ms you can scale that to smaller numbers for smaller delays. You probably need to lock the CPU clock speed and disable interrupts during the spinloop.

  • @bacphan7582
    @bacphan7582 11 месяцев назад +3

    For driving ws2812 I like using SPI more. Just define a bunch of constant for bit 1 and 0, send them to MOSI with correct clock and you are done

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      That's a pretty cool approach! Not without tradeoffs though, right - since you'd need an additional transmit buffer 8x larger than the data you're trying to send, and also need to spend CPU cycles translating the bits to bytes in that buffer.

    • @gionag
      @gionag 11 месяцев назад

      done the same, you are trading "space" for "time", sometimes it is worth, other don't...

  • @GeorgeBratley
    @GeorgeBratley 11 месяцев назад

    An absolute banger to finish the year with (pun intended)! Would be interesting to see something like a DMX decoder for this, taking an input of RGB values in one protocol like DMX, and translating it and outputing it in another like WS2812B.

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад +1

      As it happens someone was discussing a project on the discord server recently where they were translating a DMX signal to an AMX signal on the fly using two cores of an ESP32

  • @scrambledmandible
    @scrambledmandible 11 месяцев назад +1

    Hey, your vx6 series has inspired me to try creating a RISC-V processor in the graphical logic simulator Digital (ever unsearchable successor to Logisim)
    I'm following the biriscv verilog repo, but assuming I can finish it and get it working, do you want a copy to play with?
    It has a lot of the pieces you need to boot vx6, like a simple MMU and cache and those bits and bobs, though not RV64GC, it is RV32IM-Zicsr

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      Definitely!

    • @scrambledmandible
      @scrambledmandible 11 месяцев назад

      @@LowByteProductions I'll tell you what though, verilog was not meant for this kind of translation 😓

  • @merrickryman4853
    @merrickryman4853 11 месяцев назад

    I built a WS2812B driver in Rust in for a college lab, was an interesting one 😅 although it was fairly easy with PIO on the RP2040. Great video!

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      Yeah PIO is awesome. I need to play with it more!

  • @gionag
    @gionag 11 месяцев назад

    i have made an implementation on stm32 to drive this """smart""" led by leveraging DMA and SPI. the only caveat was to bound the peripheral speed to a certain, specific speed to make the bit timing correct.
    Worked like a charm

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      I had assumed that you'd need an 8x larger buffer for that, but haven't looked into it I see that you can get 3 bits per byte which isn't bad at all. Nice method indeed

    • @gionag
      @gionag 11 месяцев назад

      @@LowByteProductionsyes, you are 100% right. buffer was very big indeed. not always useful in any situation.. but, if the number of led's was small enough, could be a good method to not have mcu "wasting" time between bits...
      Oh... by the way, your contents are killer... thanks

  • @Cybnew
    @Cybnew 11 месяцев назад

    This video is great! Thank you

  • @4567guuyth
    @4567guuyth 11 месяцев назад

    Hi, nice to meet you.
    I am a student who wants to start studying the Linux kernel.
    However, I don't know what books or lectures on the Linux kernel I should take. In particular, I want to study the network side of Linux and create a server through socket programming. I'm wondering how to start.

  • @andyschneider6402
    @andyschneider6402 7 месяцев назад

    Is it possible that the fact the nop instructions don’t consume time consistently as you add them is because a NOP on ARM is not guaranteed to consume time, the processor is allowed to remove them from the pipeline?

  • @sefalibhakat143
    @sefalibhakat143 11 месяцев назад +1

    Next video suggestion:- An SD card driver..
    It would be a nice idea to read the binary colour values from the SD card and display the same on pixel leds...

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      As it happens I've actually built an SD card driver / FAT32 filesystem on the channel before: Bus Pirate Adventures: ruclips.net/p/PLP29wDx6QmW5zKp0hGR7kvwYlfl8YlxLP
      But I agree it would make a great addition to a microcontroller / neopixel project!

  • @kilwo
    @kilwo 11 месяцев назад

    Just a quick thought. Should you be turning off interrupts while you are bit-banging? And could this cause the issues of the flickering. Would only be visible when the LED is off as a single bit flip due to timing error would not be visible on a lit led. Just a thought.

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      It's possible, but not probable in my opinion, since the interrupt code here would be running very quickly - 10s of nanoseconds.

  • @thoup
    @thoup 11 месяцев назад

    This is so cool. Where do you find ideas like these? And any good resources on learning and getting more involved in low level development? I have programmed a fair bit in C/C++ but mostly from university, and I would really like to make some projects to showcase/expand my knowledge.

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      Thanks, glad you enjoyed it! I think a good way of getting into lower level code is grab a cheap arduino kit from amazon or aliexpress with an uno and a few sensors, wires, etc and get some lights blinking, read some sensors, and other little projects using the arduino libraries. From there you can learn about programming without using the arduino framework and libraries (search something like arduino register level propgramming), reimplementing the same projects from scratch. Combine that with Elicia White's book "Making Embedded Systems", and that'll put you on a fast track to learning C, low level programming, CPU internals, how to talk to other devices over different protocols, etc.

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      Oh, and look into the wokwi online simulator. You can program for virtual devices (emulated arduinos, ESP32s, etc), which can be a good way of learning about this kind of thing without paying a single penny.

  • @LordHog
    @LordHog 11 месяцев назад

    I know this topic is bit banging the control/data signal, but wouldn’t using a PWM be better to keep tighter timing?

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад +3

      Sure! I mention a possible PWM approach in the video using Timers and DMA. It's definitely the better way to do it, but bit banging is universal and the method will apply to any micro

    • @LordHog
      @LordHog 11 месяцев назад

      @@LowByteProductions sorry, was a long video and sort of skipped around to the middle and watched some while I was out. Bookmarked to watch it fully a bit later. Thanks

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      @LordHog no worries!

  • @patricklehmann24
    @patricklehmann24 11 месяцев назад +2

    The duty-cycle is 33% vs. 66%, not 25% vs. 75%. 400ns out of 1200ns is a 1/3. We also see later, the period is not 1200ns, but 1250ns.

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад +1

      True - doing the mental math while speaking to the camera is tricky!

  • @electrolyteorb
    @electrolyteorb 11 месяцев назад

    Next time, please show the top view of how everything is connected

  • @lbirkert
    @lbirkert 11 месяцев назад +2

    ruclips.net/video/KUklOA91nk0/видео.htmlfeature=shared&t=2572
    I do not think your reasoning is correct here. The thing does not work because your NOP_420NS macro does in fact not take 420ns but rather 420ns - 120ns = 300ns to run (the whole thing sums up to 420ns, as your port write takes about 120ns). Doing the calculations, this lines up with what you were getting with 2x NOP_420NS: 300ns * 2 + 120ns = 720ns.

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад

      You're right! Hard to think and speak out loud at the same time 😅

  • @兼明-p2b
    @兼明-p2b 11 месяцев назад

    I have an 8*8

  • @rty1955
    @rty1955 9 месяцев назад

    Horrible implimentation. Using assembly code for critical timming is a bad way of doing it. Because of the many, many different types of uP boards out there with so many timming variants will require too much tweaking of the assembler code. Very sloppy code
    I developed a hardware interface that you can raise a PROCESS line, then send the three data bytes and monitor a BUSY line to drop when u can send another group of 3 bytes. You so this for all the pixels you want to send. At end u drop the PROCESS line and wait for busy line to drop and you are done. Easy peasy. Works on ANY uP too and is rock solid

  • @stati5tik
    @stati5tik 11 месяцев назад

    what precisly is the reasoning behind using LED_PIN at 30:46? As far as i see gpio_port_write expects data as an argument, how exactly can a LED_PIN considered a data in the classical sense? I understand that the 8th bit denotes the very pin we want to use to communicate. Does that mean gpio_port_write turns the pin on and off? why 16 bits then?

    • @LowByteProductions
      @LowByteProductions  11 месяцев назад +1

      A "port" is made up of uo to 16 GPIOs, which you can change the state of simultaneously.

    • @stati5tik
      @stati5tik 11 месяцев назад

      @@LowByteProductions okay makes sense (-: