Menu

WS2812 on a 64MHz device.

mkstevo
2021-01-29
2021-01-30
  • mkstevo

    mkstevo - 2021-01-29

    I have been looking at the code for my WS2812 clock. One of the things I tried was using an 18F14K22 in place of the original 16F1829.

    The 14K22 worked almost immediately when dropped into the circuit and the code downloaded to it, as long as the chip was running at 32MHz. Trying to run it at it's full speed of 64MHz resulted in no display on the WS2812 (NeoPixel) LEDs. Clearly there was a timing issue, but where? I'd noted in some earlier experimentation with these LEDs that there needed to be some minimum delays between sending packets of data of 50uS, so I initially tried adding some delays here. No effect. I tried tweaking the timer interrupt settings. No effect. Finally I added some single instruction delays in the code that sends the data out to the WS2812. Bingo! LEDs lit up correctly. With just a single "NOP" some flicker could just be seen on the WS2812s, with two they seem rock solid.

    Here is the code:

    '''A demonstration of Great Cow BASIC supporting the WS2812 LED devices.
    '''@author     EvanV
    '''@licence    GPL
    '''@version    1.00
    '''@date       2.09.2016
    '''********************************************************************************
    
    Sub WS2812_Init
        Set DIN Off
        Let TimeOutOcurred =  0
        InitTimer0(Osc, TMR0_FOSC4)
        SetTimer(0, Period_uS)  ' Preload Count
        StartTimer 0
        On Interrupt Timer0Overflow call ISR0
        Set DIN On
        NOP 'NOP needed for 18F14K22 at 64MHz
        NOP 'NOP needed for 18F14K22 at 64MHz
        Set DIN Off
        Wait 500 us
    End Sub
    
    WS2812_Bit_Banged_Send_Data:
    Sub WS2812BitBangSendData(In ColourData As Long)
        Repeat 24
            If ColourData.23 On Then
                'High to send a "1"
                Set DIN On
                NOP 'NOP needed for 18F14K22 at 64MHz
                NOP 'NOP needed for 18F14K22 at 64MHz
            Else
                'High and Low as fast as practical for a "0"
                Set DIN On
                NOP 'NOP needed for 18F14K22 at 64MHz
                NOP 'NOP needed for 18F14K22 at 64MHz
                Set DIN Off
                NOP 'NOP needed for 18F14K22 at 64MHz
                NOP 'NOP needed for 18F14K22 at 64MHz
            End If
            Rotate ColourData Left
            'Low for the 1 bit
            Set DIN Off
            NOP 'NOP needed for 18F14K22 at 64MHz
            NOP 'NOP needed for 18F14K22 at 64MHz
        End Repeat
    End Sub
    

    The original code from one of Anobium's demonstration files had none of the "NOP" instructions. Adding the "NOP"s made the code work at 64MHz. Hopefully this may help someone else from scratching their head.

    NOP is an Assembly instruction to the microprocessor to perform "No Operation". It should introduce a delay of a single instruction clock cycle. The instruction clock cycle for a PIC I think is four oscillator clock cycles long. At 64MHz this would be a 62.5 nano second delay for each "NOP". If I've got my maths right that is!

     

    Last edit: mkstevo 2021-01-29
  • Anobium

    Anobium - 2021-01-29

    Brilliant. Got a video?

     
  • mkstevo

    mkstevo - 2021-01-29

    I'll try and take one later. The new version of the clock should look rather more impressive though. Once the PCBs arrive from China I'll upload some pictures and the code into the finished projects area. The original WS2812 clock should be in the finished projects area but the rewritten code has added some real flair to it. The code was rewritten to take advantage of the new PCBs but looks as good in the earlier round version. Well, I think so!

     
  • mkstevo

    mkstevo - 2021-01-29

    A picture taken at 5:46pm. The reflection in the glass shows the colours better than the direct view. The colours are very vibrant and not as washed out as they might look.

    The minutes are shown by the green LEDs, Hours by red, seconds by a single blue LED. When the hour "hands" have a value greater than the minute "hands" the minutes are shown in full in green LEDs, with the hours following in red. When the hour "hands" have a value less than the minute "hands" the hours are shown in full in red, with the minutes following in green. Where hours and minutes overlap completely they are shown in green, with a single yellow LED to mark their final value. The hour intervals are marked with a white LED.

    The temperature is shown alongside the time by "winking" a single LED in the relevant position periodically. In the picture, it wasn't on. The temperature can be shown "fully" by pressing the OK button. This then lights the required number of LEDs fully for 30 seconds or so before time display resumes. Should the temperature be below zero, the "0" LED is blue, for temperatures above zero this is a red LED, the temperature value is then shown with green LEDs. If you look at the LCD it is showing the temperature of the DS3231 as being 23 degrees C.

    Videos here (1): https://youtu.be/HX5B5dytBzM
    And here (2): https://youtu.be/GF0aJO3Ef5k

    The second one came out much better but doesn't show the temperature "winking".
    The first is in "Part" mode where the hours and minutes are separately illuminated as I attempted to describe above. The second shows "Full" mode where the hours minutes and seconds overlap one another creating a mixture of colours. I hadn't got the "winking"temperature indication working when I took the second video.

    Once the new PCBs arrive I'll try to take a decent quality video.

     

    Last edit: mkstevo 2021-01-29
  • William Roth

    William Roth - 2021-01-30

    At 64 Mhz 1 instruction takes 62.5 nanoseconds. So the DIN ON time would only be 62.5 ns with back to back DIN ON/DIN OFF. Adding 2 "NOPS" increases the On time to about 187.5 ns.

    Does 187.5ns meet the device specification ?

     
    • mkstevo

      mkstevo - 2021-01-30

      Now that's an excellent question. I'll be honest, I didn't check that. Knowing that they had been working at 32MHz, but failed flatly at 64MHz led me to assume that there was an issue with timing. As I mentioned above, I'd found in earlier experimentation that there had to be a minimum gap between sending packets of 50uS so tried jiggling that first. When that had no effect, I assumed that the on/off times for the actual "bits" must be too fast. I wondered for a while how I could easily add some additional, but minimal length, delays to that when I realised I could use the assembler instruction "NOP" to add a tiny amount of delay (62.5nS). I added a single "NOP" to every data transition instruction (both high and low) and that brought the LEDs to life. I noticed after a while that the LEDs could be seen to flicker very slightly (which hadn't been visible with the original 16F1829 at 32MHz) so I added a further "NOP". That eliminated the flicker. I also compiled the same code with the additional delays into the 1829 and it too displays correctly. Perhaps the original running at 32MHz runs very close to the upper limit of the WS2812 timings? When I first got the WS2812 "rings" I downloaded some of the demo code and hooked it up to them, apart from finding I needed a minimal gap between refreshing them, as the code worked, I looked no further.

      I've just ordered some individual LEDs (through hole versions for soldering into my new PCBs) the information provided for the ones I ordered suggests that the overall timing for a single bit to be transmitted should be close to 1250nS. I have just got my super cheap logic analyser out and it is suggesting to me that a single bit has an overall timing of 1.125uS, the on timing is rather narrow at 208nS and 540nS when the specification shows the lower limit for these to be 220nS and 750nS. Hardly surprising it was marginal when I had only one additional "NOP".

       

      Last edit: mkstevo 2021-01-30

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.