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
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!
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.
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!
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.
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
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.
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.
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.
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
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
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
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
@@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
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.
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?
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...
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!
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.
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.
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.
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.
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
@@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
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.
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
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?
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
Ahhh you're right, don't know how I forgot to shift 🤦♂️
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!
One more reason to be grateful for the reverse polarity protection they built in!
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.
🤦♂️
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!
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.
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
Great video. 🙂 You forgot to shift the leds values.
Ahhh you're right, don't know how I forgot to shift 🤦♂️
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.
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
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.
done the same, you are trading "space" for "time", sometimes it is worth, other don't...
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.
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
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
Definitely!
@@LowByteProductions I'll tell you what though, verilog was not meant for this kind of translation 😓
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!
Yeah PIO is awesome. I need to play with it more!
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
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
@@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
This video is great! Thank you
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.
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?
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...
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!
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.
It's possible, but not probable in my opinion, since the interrupt code here would be running very quickly - 10s of nanoseconds.
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.
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.
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.
I know this topic is bit banging the control/data signal, but wouldn’t using a PWM be better to keep tighter timing?
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
@@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
@LordHog no worries!
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.
True - doing the mental math while speaking to the camera is tricky!
Next time, please show the top view of how everything is connected
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.
You're right! Hard to think and speak out loud at the same time 😅
I have an 8*8
Nice, that'll do fine!
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
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?
A "port" is made up of uo to 16 GPIOs, which you can change the state of simultaneously.
@@LowByteProductions okay makes sense (-: