WS2812s with PIC24FJ128GA010 - Having Issues with controlling an LED

Thread Starter

nhuttinger

Joined Feb 24, 2024
1
Hey there,

I have been trying for 3 weeks now and have had no success with controlling the WS2812s with a PIC24FJ128GA010. Here is my current code
Code:
#include "mcc_generated_files/system.h"

#define DATA _RA15

void one()
{
    LATAbits.LATA15 = 1;
    Nop(); Nop(); Nop(); Nop(); Nop(); Nop();
    LATAbits.LATA15 = 0;
    Nop(); Nop(); Nop();
    
}

void zero()
{
    LATAbits.LATA15 = 1;
    Nop(); Nop();
    LATAbits.LATA15 = 0;
    Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop();
}

void shift_out(unsigned char B)
{
    if ((B & 0x80) == 1)
        one();
    else
        zero();
    if ((B & 0x40) == 1)
        one();
    else
        zero();
    if ((B & 0x20) == 1)
        one();
    else
        zero();
    if ((B & 0x10) == 1)
        one();
    else
        zero();
    if ((B & 0x08) == 1)
        one();
    else
        zero();
    if ((B & 0x04) == 1)
        one();
    else
        zero();
    if ((B & 0x02) == 1)
        one();
    else
        zero();
    if ((B & 0x01) == 1)
        one();
    else
        zero();
}

void rgb(unsigned char R, unsigned char G, unsigned char B)
{
    shift_out(G);
    shift_out(R);
    shift_out(B);
}
int main(void)
{
    // initialize the device
    SYSTEM_Initialize();
    PORTAbits.RA15 = 0;
    DATA = 0;
    for(int i = 0; i < 20; i++);
    while (1)
    {
        rgb(0,64,0);
        for(int i = 0; i < 20; i++);
    }

    return 1;
}
/**
 End of File
*/
And here is how I have the MCC Clock set up within MPLAB
1708787421312.png
Based on the WS2812 datasheet, I have to be having an issue with timing. I am just not understanding how to implement the correct timing for this specific IC. Has anyone done a similar application, and how have you implemented the correct timing?
 

nsaspook

Joined Aug 27, 2009
13,297
Aside from almost everything else, this is the worst part of coding in C.
When you have cache and instruction/branch prediction, you can't bit-bang totally DETERMINISTICALLY even with machine code.

That's why you should only bit-bang hardware in 2024 as a last resort. You don't need it for this application.
 
Last edited:

ApacheKid

Joined Jan 12, 2015
1,615
Hey there,

I have been trying for 3 weeks now and have had no success with controlling the WS2812s with a PIC24FJ128GA010. Here is my current code
Code:
#include "mcc_generated_files/system.h"

#define DATA _RA15

void one()
{
    LATAbits.LATA15 = 1;
    Nop(); Nop(); Nop(); Nop(); Nop(); Nop();
    LATAbits.LATA15 = 0;
    Nop(); Nop(); Nop();
  
}

void zero()
{
    LATAbits.LATA15 = 1;
    Nop(); Nop();
    LATAbits.LATA15 = 0;
    Nop(); Nop(); Nop(); Nop(); Nop(); Nop(); Nop();
}

void shift_out(unsigned char B)
{
    if ((B & 0x80) == 1)
        one();
    else
        zero();
    if ((B & 0x40) == 1)
        one();
    else
        zero();
    if ((B & 0x20) == 1)
        one();
    else
        zero();
    if ((B & 0x10) == 1)
        one();
    else
        zero();
    if ((B & 0x08) == 1)
        one();
    else
        zero();
    if ((B & 0x04) == 1)
        one();
    else
        zero();
    if ((B & 0x02) == 1)
        one();
    else
        zero();
    if ((B & 0x01) == 1)
        one();
    else
        zero();
}

void rgb(unsigned char R, unsigned char G, unsigned char B)
{
    shift_out(G);
    shift_out(R);
    shift_out(B);
}
int main(void)
{
    // initialize the device
    SYSTEM_Initialize();
    PORTAbits.RA15 = 0;
    DATA = 0;
    for(int i = 0; i < 20; i++);
    while (1)
    {
        rgb(0,64,0);
        for(int i = 0; i < 20; i++);
    }

    return 1;
}
/**
End of File
*/
And here is how I have the MCC Clock set up within MPLAB
View attachment 316063
Based on the WS2812 datasheet, I have to be having an issue with timing. I am just not understanding how to implement the correct timing for this specific IC. Has anyone done a similar application, and how have you implemented the correct timing?
Reduce this to the simplest possible form, get rid of everything except a minimal on/off. Focus on getting that working before analyzing this code. There's a good chance you'll find something silly going on.
 

John P

Joined Oct 14, 2008
2,026
I've done this with a lowly PIC16F part, where the processor can catch and buffer characters from the UART while driving a string of WS2812's. It uses a block of carefully written assembly code, and I did check it with a scope, but I mostly planned the timing just by counting the number of instructions.
 

Sensacell

Joined Jun 19, 2012
3,449
I have used the SPI engine for this with great success.

You can create a lookup table that creates a pattern of bits that emulates the signal you are trying to create.
If you use a PIC with DMA, the whole process can be automated to require minimal software overhead. (and rock steady timing)
 

BobTPH

Joined Jun 5, 2013
8,989
p
When you have cache and instruction/branch prediction, you can't bit-bang totally DETERMINISTICALLY even with machine code.
Which does not apply to the PIC24. Instruction timing is completely deterministic as long as interrupts are disabled.

Code very similar to this works for me in PIC24.

To the OP: What speed are you running at? I needed to run at 32MHz to get my code to work. Can you post the machine code it translates to?
 

nsaspook

Joined Aug 27, 2009
13,297
p

Which does not apply to the PIC24. Instruction timing is completely deterministic as long as interrupts are disabled.

Code very similar to this works for me in PIC24.

To the OP: What speed are you running at? I needed to run at 32MHz to get my code to work. Can you post the machine code it translates to?
Sure, but you don't need to bit bang this on a PIC24.
Like the pic24, a nice clean programming architure: https://forum.allaboutcircuits.com/threads/pic24-bluetooth-low-energy-dk.128497/
https://github.com/nsaspook/fac_relay_clone/tree/master

A hardware solution is so much better than old, dumb software emulators of digital logic. SPI. DMA, CLC modules, etc... are in modern controllers as deterministic coprocessors to offload instruction bound tasks from the CPU. New PIC16 chips now have a small FPGA for even more of a hardware boost for these sorts of tasks.

https://www.eejournal.com/article/t...real-time-speed-sells-for-less-than-50-cents/
 
Last edited:

nsaspook

Joined Aug 27, 2009
13,297
I have used the SPI engine for this with great success.

You can create a lookup table that creates a pattern of bits that emulates the signal you are trying to create.
If you use a PIC with DMA, the whole process can be automated to require minimal software overhead. (and rock steady timing)
Exactly, I don't understand the reluctance to use simple hardware solutions for this task on capable hardware other than Inertia because most have the technical capabilities to handle the hardware task easily IMO.
 
Last edited:

BobTPH

Joined Jun 5, 2013
8,989
Exactly, I don't understand the reluctance to use simple hardware solutions for this task on capable hardware other than Inertia because most have the technical capabilities to handle the hardware task easily IMO.
For me, sure, I could use SPI and DMA. But if I don’t need the performance, it is not worth the increase in complexity of the software. Also, to make use of the overlap, double buffering is required, and the RAM might not be available. If fact, that is a problem in one of my WS2812 projects.
 

joeyd999

Joined Jun 6, 2011
5,283
For me, sure, I could use SPI and DMA. But if I don’t need the performance, it is not worth the increase in complexity of the software. Also, to make use of the overlap, double buffering is required, and the RAM might not be available. If fact, that is a problem in one of my WS2812 projects.
@nsaspook thinks I've got all this extra hardware sitting around idle on the die, just yearning to be put to useful work by lighting a few LEDs.

It never occurred to him I might need that hardware for something just a bit more intricate.
 

nsaspook

Joined Aug 27, 2009
13,297
@nsaspook thinks I've got all this extra hardware sitting around idle on the die, just yearning to be put to useful work by lighting a few LEDs.

It never occurred to him I might need that hardware for something just a bit more intricate.
Don't make nonsense comments about self-imposed engineering restraints. You know exactly what your doing, and you love it like walking on a tightrope. I respect that, even if I don't agree at times.

Yes, I know all about resource constraints and being in a maze of twisty little passages, all alike. That's why I add a lot extra at times to the resources needed specification.
 
Last edited:

nsaspook

Joined Aug 27, 2009
13,297
For me, sure, I could use SPI and DMA. But if I don’t need the performance, it is not worth the increase in complexity of the software. Also, to make use of the overlap, double buffering is required, and the RAM might not be available. If fact, that is a problem in one of my WS2812 projects.
IMO the software complexity (it's not on a simple controller, it's only complicated, the first time you do it) should be a non-issue with something like this, as you abstract the actual bit-shuffle code section in any case of good software design. The other constraints are very valid.
 
Last edited:

nsaspook

Joined Aug 27, 2009
13,297
Ordered a string of WS2812s for a CLC to SPI with DMA demo on the Q84.
No mainline code for timing or sequencing. The TMR0 ISR sequences the datastream and DMA to drive the SPI outputs to the CLC modulator.
C:
void __interrupt(irq(TMR0),base(8)) TMR0_ISR()
{
    // clear the TMR0 interrupt flag
    PIR3bits.TMR0IF = 0;
  
    uint24_t ws2812_seed_addr = &ws2812_seed;

    // start DMA transfer (transfer GRB data to SPI for WS2812)
    DMASELECT = 0x02;
    DMAnCON0bits.SIRQEN = 1;
    DMAnSSA += DMAnSSZ;     // move source start addr ahead
    if(DMAnSSA >= (ws2812_seed_addr + WS2812_SEED_SIZE))    // rollover
        DMAnSSA = ws2812_seed_addr;
}
1709526374446.png
1709526433832.png
clc3.png
Trace 1 is the LED modulated data from the CLC logic with 2 sck ,3 sdo, 4 pwm (SPI clock source) as the CLC inputs.
Uses a extra (testing) PIC18F47Q84 board from the FM80 solar monitor project.
 
Last edited:
Top