(HOME)
LED Ring Display
A generic 16 LED circular display.
Synopsis : This simple circular LED display can be use for many different applications, and with many different controllers. (Aug 21, 2014)
I've been working on my Hackaday Prize prize entry, a remote indicator for an existing domestic water meter. The display will use a 4 line by 20 character LCD or VFD display, but it occurred to me that I also wanted something more dramatic and eye-catching. I decided that a circle of LEDs spinning in response to the immediate flow of water at the meter would do the job nicely. It also occurred to me that this LED Ring display could be used for other things. With 16 LEDs it wouldn't do well as a clock, but it would do quite nicely as a compass rose display for a wind direction sensor or to display antenna bearing, or any other kind of direction indicating display. With that in mind I designed it as a stand alone module.

Before I get to the details, I wrote a little gratuitous flashy LED program. Here's the video ...



Obviously the first thing we need is an IC to drive all of the LEDs. There are TONS of projects all across the Internet using 74xx595 shift register chips to drive strings of LEDs. There is a big problem with that approach. The data sheet for the '595 does indeed say that you can drive 24mA of current through an output pin which is plenty for an LED. The problem is that the spec for the WHOLE CHIP says that you shouldn't exceed 50mA of current. That means that if you have LEDs on all 8 outputs, you should never have more than two of them on at any one time. Can you? Sure. Will it work? Probably. At least for a while, but it probably won't have nearly the life it should have. And besides, it's just really bad engineering practice to drive a chip to 400% of it's specified maximum current on purpose. (I've done it on accident PLENTY of times)

After a little searching, I came up with a FAR better chip; The TLC59282 from Texas Instruments ( about $1.50 US from Digikey ). This part offers several improvements over the venerable old '595.

  • The TLC59282 is a 16-bit shift register instead of the 8 bits the '595 offers. That means that we'll only need to use one of them for our LED display as opposed to two '595s.

  • Instead of TTL outputs like the '595 uses, this part has current-sink outputs designed to drive LEDs and are rated for 30mA at up to 30V. This chip is designed for use in LED video displays, message boards, and LED lighting, so it's outputs are quite strong and can drive our 16 little LEDs without breaking a sweat (even running all the LEDs at the same time).

  • It provides a BLANK input pin. Driving that pin simply turns off all of the LEDs. While that might not seem like much at first blush, you can drive that pin with a PWM signal from your controller to effect dimming of the LEDs. In my case, I wanted blue LEDs, but I did not want them to be bright and glaring. By feeding a PWM signal into the BLANK pin I was able to dial the display down to where I liked it.

  • It has a current setting pin. Placing one resistor from that pin to ground sets the current to all of the outputs. That means that you do not need a current limiting resistor for each LED, the chip takes care of that for you. Read the data sheet for information about selecting a specific resistor for your specific voltage and current.

  • And finally, it uses the same old Clock, Data, and Latch pins the '595 does. That means that any code you might be using to drive a '595 can be used to drive this part. Existing code, for example Arduino '595 libraries, should drive this chip just fine (though I've not tried it yet).




  • The schematic for the PCB is really very simple, just the driver chip, the current setting resistor, and the 16 LEDs. (click the schematic below to open a larger, printable version)



    I had the printed circuit boards made by OSH Park.



    YOU CAN BUY THESE BOARDS
    I made these PCBs public and shared on OSH Park. That means that you can go there and buy a set of your own (for about $17 US + postage). I do not make a penny off of this. Just making the boards available to anyone who might want them. Just follow this link.

    In the video demo above I was driving the display using a Microchip PIC microcontroller on a TAUTIC ELECTRONICS 20-Pic development board. The source code is listed below. Yeah, it's pretty messy, but I just hacked it together to deomnstrate the display. It's not a final application. If you're inclined to take me to task for it, do include a copy of your own demonstration code for this display along with your criticisms. :-)

    As I mentioned before, you drive this display the same as you would any shift register on an Arduino or whatever microcontroller board you use.

    
    #include <xc.h>
    #include <pic16F1509.h>
    #include <stdlib.h>
    #define _XTAL_FREQ  4000000      //tell compiler that the clock is 4 MHz
    
    // Set up pins for TLC59282 LED driver chip
    #define LATCH LATCbits.LATC0     // LATCH on display driver
    #define SERIN LATCbits.LATC1     // SERIAL IN on display driver
    #define CLOCK LATCbits.LATC2     // DATA CLOCK on display driver
    
    // Basic configuration of the PIC16F1509 microcontroller
    #pragma config MCLRE=ON          // Reset pin enabled
    #pragma config CP=OFF            // Code protection off
    #pragma config WDTE=OFF          // Watch Dog Timer disabled
    #pragma config FOSC=INTOSC       // Set to internal clock
    
    void shiftout(int);
    
    void main() {
        OSCCON  = 0b01101010;     //Set internal clock, 4MHz
    
        // I always turn all this stuff off, and selectively turn it back
        // on if needed. Been bitten too many time in the past.
        INTCON  = 0b00000000;     //Disable all interrupts
        ANSELA  = 0b00000000;     //Disable all analog input
        ANSELB  = 0b00000000;     //Disable all analog input
        ANSELC  = 0b00000000;     //Disable all analog input
        TRISA   = 0b00000000;     //Configure pins for input(1)/output(0)
        TRISB   = 0b00000000;     //Configure pins for input(1)/output(0)
        TRISC   = 0b00000000;     //Configure pins for input(1)/output(0)
    
        // Set up PWM for LED brightness on water wheel display
        // PWM2 output (RC3) connects to "BLANK" pin of display driver
        PR2     = 0b11111111;     //Set PWM period
        T2CON   = 0b00000110;     //PWM ON, Prescale clock by 16
        PWM2DCH = 0b00000011;     //Duty cycle, top 8 bits (adjust duty cycle here)
        PWM2DCL = 0b00000000;     //Duty cycle, bottom 2 bits (leave as 0)
        PWM2CON = 0b11110000;     //PWM enable, Output enable, Active high
    
    
        unsigned int DISPLAY;
        int DELAY;
        int LOOP;
        int CYCLES;
        int x;
    
        //BLANK = 0;                //Turn on LED display
    
        DISPLAY = 1;
         /* MAIN LOOP */
        while (1)
        {                         //Loop forever
    
          DELAY = 75; CYCLES = 2; LOOP = 0;
          while (CYCLES-- > 0)
            {
            while (LOOP++ < 16)
              {
                shiftout(DISPLAY);
                for(x=DELAY; x>0; x--) { __delay_ms(1);}
                DISPLAY <<= 1;
                if (DISPLAY == 0) { DISPLAY = 1; }
              }
            LOOP = 0;
            }
    
    
          DELAY = 50; CYCLES = 2; LOOP = 0;
          while (CYCLES-- > 0)
            {
            while (LOOP++ < 16)
              {
                shiftout(DISPLAY);
                for(x=DELAY; x>0; x--) { __delay_ms(1);}
                DISPLAY <<= 1;
                if (DISPLAY == 0) { DISPLAY = 1; }
              }
            LOOP = 0;
            }
    
          DELAY = 25; CYCLES = 4; LOOP = 0;
          while (CYCLES-- > 0)
            {
            while (LOOP++ < 16)
              {
                shiftout(DISPLAY);
                for(x=DELAY; x>0; x--) { __delay_ms(1);}
                DISPLAY <<= 1;
                if (DISPLAY == 0) { DISPLAY = 1; }
              }
            LOOP = 0;
            }
    
          DELAY = 10; CYCLES = 4; LOOP = 0;
          while (CYCLES-- > 0)
            {
            while (LOOP++ < 16)
              {
                shiftout(DISPLAY);
                for(x=DELAY; x>0; x--) { __delay_ms(1);}
                DISPLAY <<= 1;
                if (DISPLAY == 0) { DISPLAY = 1; }
              }
            LOOP = 0;
            }
    
          DELAY = 25; CYCLES = 4; LOOP = 0;
          while (CYCLES-- > 0)
            {
            while (LOOP++ < 16)
              {
                shiftout(DISPLAY);
                for(x=DELAY; x>0; x--) { __delay_ms(1);}
                DISPLAY <<= 1;
                if (DISPLAY == 0) { DISPLAY = 1; }
              }
            LOOP = 0;
            }
    
          DELAY = 50; CYCLES = 2; LOOP = 0;
          while (CYCLES-- > 0)
            {
            while (LOOP++ < 16)
              {
                shiftout(DISPLAY);
                for(x=DELAY; x>0; x--) { __delay_ms(1);}
                DISPLAY <<= 1;
                if (DISPLAY == 0) { DISPLAY = 1; }
              }
            LOOP = 0;
            }
    
          //__delay_ms(500);
          DISPLAY = 32768;
    
          DELAY = 50; CYCLES = 2; LOOP = 0;
          while (CYCLES-- > 0)
            {
            while (LOOP++ < 16)
              {
                shiftout(DISPLAY);
                for(x=DELAY; x>0; x--) { __delay_ms(1);}
                DISPLAY >>= 1;
                if (DISPLAY == 0) { DISPLAY = 32768; }
              }
            LOOP = 0;
            }
    
          DELAY = 25; CYCLES = 4; LOOP = 0;
          while (CYCLES-- > 0)
            {
            while (LOOP++ < 16)
              {
                shiftout(DISPLAY);
                for(x=DELAY; x>0; x--) { __delay_ms(1);}
                DISPLAY >>= 1;
                if (DISPLAY == 0) { DISPLAY = 32768; }
              }
            LOOP = 0;
            }
    
          DELAY = 10; CYCLES = 4; LOOP = 0;
          while (CYCLES-- > 0)
            {
            while (LOOP++ < 16)
              {
                shiftout(DISPLAY);
                for(x=DELAY; x>0; x--) { __delay_ms(1);}
                DISPLAY >>= 1;
                if (DISPLAY == 0) { DISPLAY = 32768; }
              }
            LOOP = 0;
            }
    
          DELAY = 25; CYCLES = 4; LOOP = 0;
          while (CYCLES-- > 0)
            {
            while (LOOP++ < 16)
              {
                shiftout(DISPLAY);
                for(x=DELAY; x>0; x--) { __delay_ms(1);}
                DISPLAY >>= 1;
                if (DISPLAY == 0) { DISPLAY = 32768; }
              }
            LOOP = 0;
            }
    
          DELAY = 50; CYCLES = 2; LOOP = 0;
          while (CYCLES-- > 0)
            {
            while (LOOP++ < 16)
              {
                shiftout(DISPLAY);
                for(x=DELAY; x>0; x--) { __delay_ms(1);}
                DISPLAY >>= 1;
                if (DISPLAY == 0) { DISPLAY = 32768; }
              }
            LOOP = 0;
            }
          CYCLES = 2;
          while (CYCLES-- > 0)
            {
            shiftout(1);     __delay_ms(50);
            shiftout(3);     __delay_ms(50);
            shiftout(7);     __delay_ms(50);
            shiftout(15);    __delay_ms(50);
            shiftout(31);    __delay_ms(50);
            shiftout(43);    __delay_ms(50);
            shiftout(127);   __delay_ms(50);
            shiftout(255);   __delay_ms(50);
            shiftout(511);   __delay_ms(50);
            shiftout(1023);  __delay_ms(50);
            shiftout(2047);  __delay_ms(50);
            shiftout(4095);  __delay_ms(50);
            shiftout(8191);  __delay_ms(50);
            shiftout(16383); __delay_ms(50);
            shiftout(32766); __delay_ms(50);
            shiftout(65535); __delay_ms(50);
            shiftout(32766); __delay_ms(50);
            shiftout(16383); __delay_ms(50);
            shiftout(8191);  __delay_ms(50);
            shiftout(4095);  __delay_ms(50);
            shiftout(2047);  __delay_ms(50);
            shiftout(1023);  __delay_ms(50);
            shiftout(511);   __delay_ms(50);
            shiftout(255);   __delay_ms(50);
            shiftout(127);   __delay_ms(50);
            shiftout(43);    __delay_ms(50);
            shiftout(31);    __delay_ms(50);
            shiftout(15);    __delay_ms(50);
            shiftout(7);     __delay_ms(50);
            shiftout(3);     __delay_ms(50);
            shiftout(1);     __delay_ms(50);
            shiftout(0);     __delay_ms(50);
          }
    
            shiftout(0b1110000011100000); __delay_ms(50);
            shiftout(0b1110000011100000); __delay_ms(50);
            shiftout(0b0111000011100000); __delay_ms(50);
            shiftout(0b0011100011100000); __delay_ms(50);
            shiftout(0b0001110011100000); __delay_ms(50);
            shiftout(0b0000111011100000); __delay_ms(50);
            shiftout(0b0000011111100000); __delay_ms(50);
            shiftout(0b0000011101110000); __delay_ms(50);
            shiftout(0b0000011100111000); __delay_ms(50);
            shiftout(0b0000011100011100); __delay_ms(50);
            shiftout(0b0000011100001110); __delay_ms(50);
            shiftout(0b0000011100000111); __delay_ms(50);
            shiftout(0b0000111000001110); __delay_ms(50);
            shiftout(0b0001110000011100); __delay_ms(50);
            shiftout(0b0011100000111000); __delay_ms(50);
            shiftout(0b0111000001110000); __delay_ms(50);
            shiftout(0b1110000011100000); __delay_ms(50);
            shiftout(0b1100000111000001); __delay_ms(50);
            shiftout(0b1000001110000011); __delay_ms(50);
            shiftout(0b0000011100000111); __delay_ms(50);
            shiftout(0b0000111000001110); __delay_ms(50);
            shiftout(0b0001110000011100); __delay_ms(50);
            shiftout(0b0011100000111000); __delay_ms(50);
            shiftout(0b0111000001110000); __delay_ms(50);
            shiftout(0b1110000011100000); __delay_ms(50);
            shiftout(0b1100000111000001); __delay_ms(50);
            shiftout(0b1000001110000011); __delay_ms(50);
            shiftout(0b0000011100000111); __delay_ms(50);
            shiftout(0b0000111000001110); __delay_ms(50);
            shiftout(0b0001110000011100); __delay_ms(50);
            shiftout(0b0011100000111000); __delay_ms(50);
            shiftout(0b0111000001110000); __delay_ms(50);
            shiftout(0b1110000011100000); __delay_ms(50);
            shiftout(0b1100000111000001); __delay_ms(50);
            shiftout(0b1000001110000011); __delay_ms(50);
            shiftout(0b0000011100000111); __delay_ms(50);
            shiftout(0b0000111000001110); __delay_ms(50);
            shiftout(0b0001110000011100); __delay_ms(50);
            shiftout(0b0011100000111000); __delay_ms(50);
            shiftout(0b0111000001110000); __delay_ms(50);
            shiftout(0b1110000011100000); __delay_ms(50);
            shiftout(0b1100000111000001); __delay_ms(50);
            shiftout(0b1000001110000010); __delay_ms(50);
            shiftout(0b0000011100000100); __delay_ms(50);
            shiftout(0b0000111000001000); __delay_ms(50);
            shiftout(0b0001110000010000); __delay_ms(50);
            shiftout(0b0011100000100000); __delay_ms(50);
            shiftout(0b0111000001000000); __delay_ms(50);
            shiftout(0b1110000010000000); __delay_ms(50);
            shiftout(0b1100000100000000); __delay_ms(50);
            shiftout(0b1000001000000000); __delay_ms(50);
            shiftout(0b0000010000000000); __delay_ms(50);
            shiftout(0b0000100000000000); __delay_ms(50);
            shiftout(0b0001000000000000); __delay_ms(50);
            shiftout(0b0010000000000000); __delay_ms(50);
            shiftout(0b0100000000000000); __delay_ms(50);
            shiftout(0b1000000000000000); __delay_ms(50);
            shiftout(0b0000000000000001); __delay_ms(50);
            shiftout(0b0000000000000010); __delay_ms(50);
            shiftout(0b0000000000000100); __delay_ms(50);
            shiftout(0b0000000000001000); __delay_ms(50);
            shiftout(0b0000000000010001); __delay_ms(50);
            shiftout(0b0000000000100010); __delay_ms(50);
            shiftout(0b0000000001000100); __delay_ms(50);
            shiftout(0b0000000010001000); __delay_ms(50);
            shiftout(0b0000000100010001); __delay_ms(50);
            shiftout(0b0000001000100010); __delay_ms(50);
            shiftout(0b0000010001000100); __delay_ms(50);
            shiftout(0b0000100010001000); __delay_ms(50);
            shiftout(0b0001000100010001); __delay_ms(50);
            shiftout(0b0010001000100010); __delay_ms(50);
            shiftout(0b0100010001000100); __delay_ms(50);
            shiftout(0b1000100010001000); __delay_ms(50);
            shiftout(0b0001000100010001); __delay_ms(50);
            shiftout(0b0010001000100010); __delay_ms(50);
            shiftout(0b0100010001000100); __delay_ms(50);
            shiftout(0b1000100010001000); __delay_ms(50);
            shiftout(0b0001000100010001); __delay_ms(50);
            shiftout(0b0010001000100010); __delay_ms(50);
            shiftout(0b0100010001000100); __delay_ms(50);
            shiftout(0b1000100010001000); __delay_ms(50);
            shiftout(0b0001000100010001); __delay_ms(50);
            shiftout(0b0010001000100010); __delay_ms(50);
            shiftout(0b0100010001000100); __delay_ms(50);
            shiftout(0b1000100010001000); __delay_ms(50);
            shiftout(0b0001000100010001); __delay_ms(50);
            shiftout(0b0010001000100010); __delay_ms(50);
            shiftout(0b0100010001000100); __delay_ms(50);
            shiftout(0b1000100010001000); __delay_ms(50);
            shiftout(0b0001000100010001); __delay_ms(50);
            shiftout(0b0010001000100010); __delay_ms(50);
            shiftout(0b0100010001000100); __delay_ms(50);
            shiftout(0b1000100010001000); __delay_ms(50);
            shiftout(0b0001000100010000); __delay_ms(50);
            shiftout(0b0010001000100000); __delay_ms(50);
            shiftout(0b0100010001000000); __delay_ms(50);
            shiftout(0b1000100010000000); __delay_ms(50);
            shiftout(0b0001000100000000); __delay_ms(50);
            shiftout(0b0010001000000000); __delay_ms(50);
            shiftout(0b0100010000000000); __delay_ms(50);
            shiftout(0b1000100000000000); __delay_ms(50);
            shiftout(0b0001000000000000); __delay_ms(50);
            shiftout(0b0010000000000000); __delay_ms(50);
            shiftout(0b0100000000000000); __delay_ms(50);
            shiftout(0b1000000000000000); __delay_ms(50);
            shiftout(0b1000000000000001); __delay_ms(50);
            shiftout(0b1100000000000011); __delay_ms(50);
            shiftout(0b1110000000000111); __delay_ms(50);
            shiftout(0b1111000000001111); __delay_ms(50);
            shiftout(0b1111100000011111); __delay_ms(50);
            shiftout(0b1111110000111111); __delay_ms(50);
            shiftout(0b1111111001111111); __delay_ms(50);
            shiftout(0b1111111111111111); __delay_ms(50);
            shiftout(0b1111111001111111); __delay_ms(50);
            shiftout(0b1111110000111111); __delay_ms(50);
            shiftout(0b1111100000011111); __delay_ms(50);
            shiftout(0b1111000000001111); __delay_ms(50);
            shiftout(0b1110000000000111); __delay_ms(50);
            shiftout(0b1100000000000011); __delay_ms(50);
            shiftout(0b1000000000000001); __delay_ms(50);
            shiftout(0b1000000000000001); __delay_ms(50);
            shiftout(0b0100000000000010); __delay_ms(50);
            shiftout(0b0010000000000100); __delay_ms(50);
            shiftout(0b0001000000001000); __delay_ms(50);
            shiftout(0b0000100000010000); __delay_ms(50);
            shiftout(0b0000010000100000); __delay_ms(50);
            shiftout(0b0000001001000000); __delay_ms(50);
            shiftout(0b0000000110000000); __delay_ms(50);
            shiftout(0b0000001001000000); __delay_ms(50);
            shiftout(0b0000010000100000); __delay_ms(50);
            shiftout(0b0000100000010000); __delay_ms(50);
            shiftout(0b0001000000001000); __delay_ms(50);
            shiftout(0b0010000000000100); __delay_ms(50);
            shiftout(0b0100000000000010); __delay_ms(50);
            shiftout(0b1000000000000001); __delay_ms(50);
            shiftout(0b0100000000000010); __delay_ms(50);
            shiftout(0b0010000000000100); __delay_ms(50);
            shiftout(0b0001000000001000); __delay_ms(50);
            shiftout(0b0000100000010000); __delay_ms(50);
            shiftout(0b0000010000100000); __delay_ms(50);
            shiftout(0b0000001001000000); __delay_ms(50);
            shiftout(0b0000000110000000); __delay_ms(50);
            shiftout(0b0000001001000000); __delay_ms(50);
            shiftout(0b0000010000100000); __delay_ms(50);
            shiftout(0b0000100000010000); __delay_ms(50);
            shiftout(0b0001000000001000); __delay_ms(50);
            shiftout(0b0010000000000100); __delay_ms(50);
            shiftout(0b0100000000000010); __delay_ms(50);
            shiftout(0b1000000000000001); __delay_ms(50);
            shiftout(0b0000000000000001); __delay_ms(50);
            shiftout(0b0000000000000011); __delay_ms(50);
            shiftout(0b0000000000000111); __delay_ms(50);
            shiftout(0b0000000000001111); __delay_ms(50);
            shiftout(0b0000000000011111); __delay_ms(50);
            shiftout(0b0000000000111111); __delay_ms(50);
            shiftout(0b0000000001111110); __delay_ms(50);
            shiftout(0b0000000011111100); __delay_ms(50);
            shiftout(0b0000000111111000); __delay_ms(50);
            shiftout(0b0000001111110000); __delay_ms(50);
            shiftout(0b0000011111100000); __delay_ms(50);
            shiftout(0b0000111111000000); __delay_ms(50);
            shiftout(0b0000011111100000); __delay_ms(50);
            shiftout(0b0000001111110000); __delay_ms(50);
            shiftout(0b0000000111111000); __delay_ms(50);
            shiftout(0b0000000011111100); __delay_ms(50);
            shiftout(0b0000000001111110); __delay_ms(50);
            shiftout(0b0000000000111111); __delay_ms(50);
            shiftout(0b1000000000011111); __delay_ms(50);
            shiftout(0b1100000000001111); __delay_ms(50);
            shiftout(0b1110000000000111); __delay_ms(50);
            shiftout(0b1111000000000011); __delay_ms(50);
            shiftout(0b1111100000000001); __delay_ms(50);
            shiftout(0b1111110000000000); __delay_ms(50);
            shiftout(0b0111111000000000); __delay_ms(50);
            shiftout(0b0011111100000000); __delay_ms(50);
            shiftout(0b0001111110000000); __delay_ms(50);
            shiftout(0b0000111111000000); __delay_ms(50);
            shiftout(0b0000011111100000); __delay_ms(50);
            shiftout(0b0000001111110000); __delay_ms(50);
            shiftout(0b0000000111111000); __delay_ms(50);
            shiftout(0b0000000011111100); __delay_ms(50);
            shiftout(0b0000000001111110); __delay_ms(50);
            shiftout(0b0000000000111111); __delay_ms(50);
            shiftout(0b0000000000011111); __delay_ms(50);
            shiftout(0b0000000000001111); __delay_ms(50);
            shiftout(0b0000000000000111); __delay_ms(50);
            shiftout(0b0000000000000011); __delay_ms(50);
            shiftout(0b0000000000000001); __delay_ms(50);
            shiftout(0b0000000000000000); __delay_ms(100);
            shiftout(0b0001000000000000); __delay_ms(100);
            shiftout(0b0001000000001000); __delay_ms(100);
            shiftout(0b0101000000001000); __delay_ms(100);
            shiftout(0b0101000010001000); __delay_ms(100);
            shiftout(0b0101000010001010); __delay_ms(100);
            shiftout(0b0101100010001010); __delay_ms(100);
            shiftout(0b0101100010011010); __delay_ms(100);
            shiftout(0b0101100110011010); __delay_ms(100);
            shiftout(0b0101100110011011); __delay_ms(100);
            shiftout(0b0101110110011011); __delay_ms(100);
            shiftout(0b0101110110111011); __delay_ms(100);
            shiftout(0b0111110110111011); __delay_ms(100);
            shiftout(0b0111110110111111); __delay_ms(100);
            shiftout(0b0111111110111111); __delay_ms(100);
            shiftout(0b1111111110111111); __delay_ms(100);
            shiftout(0b1111111111111111); __delay_ms(200);
            shiftout(0b1111111111111110); __delay_ms(50);
            shiftout(0b1111111111111100); __delay_ms(50);
            shiftout(0b1111111111111000); __delay_ms(50);
            shiftout(0b1111111111110000); __delay_ms(50);
            shiftout(0b1111111111100001); __delay_ms(50);
            shiftout(0b1111111111000011); __delay_ms(50);
            shiftout(0b1111111110000111); __delay_ms(50);
            shiftout(0b1111111100001111); __delay_ms(50);
            shiftout(0b1111111000011111); __delay_ms(50);
            shiftout(0b1111110000111111); __delay_ms(50);
            shiftout(0b1111100001111111); __delay_ms(50);
            shiftout(0b1111000011111111); __delay_ms(50);
            shiftout(0b1110000111111111); __delay_ms(50);
            shiftout(0b1100001111111111); __delay_ms(50);
            shiftout(0b1000011111111111); __delay_ms(50);
            shiftout(0b0000111111111111); __delay_ms(50);
            shiftout(0b0001111111111110); __delay_ms(50);
            shiftout(0b0011111111111100); __delay_ms(50);
            shiftout(0b0111111111111000); __delay_ms(50);
            shiftout(0b1111111111110000); __delay_ms(50);
            shiftout(0b1111111111100001); __delay_ms(50);
            shiftout(0b1111111111000011); __delay_ms(50);
            shiftout(0b1111111110000111); __delay_ms(50);
            shiftout(0b1111111100001111); __delay_ms(50);
            shiftout(0b1111111000011111); __delay_ms(50);
            shiftout(0b1111110000111111); __delay_ms(50);
            shiftout(0b1111100001111111); __delay_ms(50);
            shiftout(0b1111000011111111); __delay_ms(50);
            shiftout(0b1110000111111111); __delay_ms(50);
            shiftout(0b1100001111111111); __delay_ms(50);
            shiftout(0b1000011111111111); __delay_ms(50);
            shiftout(0b0000111111111111); __delay_ms(50);
            shiftout(0b0001111111111110); __delay_ms(50);
            shiftout(0b0011111111111100); __delay_ms(50);
            shiftout(0b0111111111111000); __delay_ms(50);
            shiftout(0b1111111111110000); __delay_ms(50);
            shiftout(0b1111111111100000); __delay_ms(50);
            shiftout(0b1111111111000000); __delay_ms(50);
            shiftout(0b1111111110000000); __delay_ms(50);
            shiftout(0b1111111100000000); __delay_ms(50);
            shiftout(0b1111111000000000); __delay_ms(50);
            shiftout(0b1111110000000000); __delay_ms(50);
            shiftout(0b1111100000000000); __delay_ms(50);
            shiftout(0b1111000000000000); __delay_ms(50);
            shiftout(0b1110000000000000); __delay_ms(50);
            shiftout(0b1100000000000000); __delay_ms(50);
            shiftout(0b1000000000000000); __delay_ms(50);
        }
    }
    
    void shiftout(int PATTERN)
      {
      unsigned char i;
      LATCH = 0;
      for(i=16; i>0; i--)
       {
       CLOCK = 0;
       if(PATTERN & 0b1000000000000000)
         { SERIN = 1; }
       else
         { SERIN = 0; }
       CLOCK = 1; CLOCK = 0;
       PATTERN <<= 1;
       }
      LATCH = 1; LATCH = 0;
      }
    
    
    [END OF CODE]


    Questions and comments? You can find me on Twitter.
    or Email me at hackersbench (at) gmail






    This page has instructions and plans for building a round circular LED ring display that can be used for many different projects and with many different microcontrollers. It includes the schematic and parts list and directions to get the printed circuit board.