Introduction: Holiday Ornament PCB

Hey everyone!

Its that time of year and the season of exchanging gifts is almost upon us. I personally enjoy getting to make things and sharing them with the family. This year I decided to make holiday ornaments using the Atting85 and some WS2812C 2020 LEDs. The ornament is approximately 80mm in diameter so its a reasonably sized ornament for the tree. If you are not a tree person you know what, it makes a great desk ornament too. The WS2812C 2020 LEDs are incredibly bright little buggers so don't worry about it being too dim haha. I've tested it at 3.3 volts with a current consumption of 0.013 amps then for 5 volts the current consumption was 0.023 amps. You can either power this board with a direct 5 volts on the back or through the micro USB connector on the back. I could plug this into my laptop and power it. There is also an option on the back to power it with other power sources at a maximum of 30 volts, but thats trusting the datasheet for the 78L05 5V regulator, I wouldn't push it that far.

Please read through the entire guide before building this. Learn from my mistakes cause trust me I usually make a lot and can share my pearls of wisdom.

If you are interested in buying a premade PCB or just the PCB itself visit my tindie store.

Supplies

Let's start with all the tools you'll need to build one of these ornaments yourself. This is actually one of my few projects that don't require a significant amount of tools which is great for you!

Tools

- Heat gun (primary tool)/soldering iron (mistake fixer)

- ESD tweezers

- Isopropyl alcohol

- SMT stencil (highly recommended)

- Solder paste (I use a Low Temp Lead-Free solder paste sold on amazon)

Supplies

- x10 WS2812 2020 LEDs

- x1 Attiny85 Microcontroller

- x11 0.1uf 0603 Capacitors

- x1 0.1uf 0402 Capacitor (You could get away with a 0603 Cap)

- x1 SMD Micro USB connector

- x1 1.5K Ohm Resistor

- x1 4.7uf 0805 Capacitor

- x1 78L05 5V Regulator

- x1 SOD123 Diode (I used a wire as a replacement as this isn't necessary, but I forgot to remove it when designing the board)

- x2 SOD323 Diodes

- x2 66.5 Ohm Resistors (You could also use x2 24-Ohm resistors here too, I believe any matching pair will do actually - don't quote me)

Optional

- x1 24 Ohm Resistor

- x1 30 Ohm Resistor

(These are for a voltage divider if you wanted to measure the input voltage for a low voltage monitor - just an option)

Step 1: Assembly

The assembly process is fairly straight forward. Make sure you are orientating parts correctly and you shouldn't run into problems. You know what, if you are like me and absolutely nothing works the first time... literally nothing, I throw in some troubleshooting steps at the end.

Well first things first, you'll need that stencil now... I've attached the 1:1 scale PCB PDF file so you can raster it on your own laser cutter. If you need one cut for you, message me I'll do that too. Otherwise doing this by hand make you one skilled bada$$.

If you have experience in making PCBs this is where you'll go ahead and secure your stencil, spread your solder paste bla bla bla you get it. For those who have never done this, no worries, watch a youtube video or two. Make sure your alignment is perfect before you spread your solder paste and easy peasy lemon squeezy.

Carefully remove your stencil and let's begin placing parts!!

Observe my carefully drawn picture for you, made with love and tender care.

- Dark Purple = 0.1uf 0603

- Blue = Diodes

- Lime Green = 4.7 uf 0805 (Could use 0603, probably)

- Purple = Wire bridge

- Pink = Voltage divider resistors

- Red = WS2812C LEDs (Observe their orientation, the darker portion will be on the bottom)

- Yellow = 78L05 5V regulator 100mA

Do you want to know what the other yellow marking is for? Are you sure? Well... IT'S A MISTAKE OK! I put a freakin ground via in the signal trace, literally smack dab in the middle OK. WHY... I DON'T KNOW.

I digress. After hours of painfully pulling my hair out, I realized my mistake. In order to fix it, I had to not only drill out the ground via but drill an incredibly small hole through the board and connect the signal trace with a small wire. I used some liquid electrical tape to secure and cover my mistake. You can't see it very well once its covered thank goodness.

I will also fix this if you buy a board from me so no worries there.

Step 2: Coding

So before I designed this I thought, "Oh small WS2812 LEDs, they must use the same code as the WS2812b's, this is going to be a walk in the park!" WRONG

These do not use the same timing as the WS2812b LEDs so there is a learning curve or mountain depending on your comfort with coding.

After a minor "Oh $hit" moment, I found this blog by Josh Levin. So shout out to him for helping me figure this out. I used a significant amount of his code and modified it to work with these boards. Check his blog if you want to understand how this code works. The code I posted makes a rainbow affect. It is possible so make solid colors if that's your thing.

One minor thing is I can't figure out how to dim these LEDs as they are really bright. Maybe someone could leave a comment and help me out.

<p>#include <util/delay.h><util delay.h=""><br>#define PIXELS 3000  
#define PIXEL_PORT  PORTB  
#define PIXEL_DDR   DDRB   
#define PIXEL_BIT   0      
#define T1H  700    
#define T1L  320    
#define T0H  320
#define T0L  700    
#define RES 300000    
#define NS_PER_SEC (1000000000L)          
#define CYCLES_PER_SEC (F_CPU)
#define NS_PER_CYCLE ( NS_PER_SEC / CYCLES_PER_SEC )
#define NS_TO_CYCLES(n) ( (n) / NS_PER_CYCLE )</util></p><p>inline void sendBit( bool bitVal ) {
  
    if (  bitVal ) {        
      
    asm volatile (
      "sbi %[port], %[bit] \n\t"       
      ".rept %[onCycles] \n\t"                                
      "nop \n\t"
      ".endr \n\t"
      "cbi %[port], %[bit] \n\t"                        
      ".rept %[offCycles] \n\t"                               
      "nop \n\t"
      ".endr \n\t"
      ::
      [port]    "I" (_SFR_IO_ADDR(PIXEL_PORT)),
      [bit]   "I" (PIXEL_BIT),
      [onCycles]  "I" (NS_TO_CYCLES(T1H) - 2),   
      [offCycles]   "I" (NS_TO_CYCLES(T1L) - 2)     </p><p>    );
                                  
    } else {        </p><p>    asm volatile (
      "sbi %[port], %[bit] \n\t"       
      ".rept %[onCycles] \n\t"        
      "nop \n\t"                                              
      ".endr \n\t"
      "cbi %[port], %[bit] \n\t"                              
      ".rept %[offCycles] \n\t"                              
      "nop \n\t"
      ".endr \n\t"
      ::
      [port]    "I" (_SFR_IO_ADDR(PIXEL_PORT)),
      [bit]   "I" (PIXEL_BIT),
      [onCycles]  "I" (NS_TO_CYCLES(T0H) - 2),
      [offCycles] "I" (NS_TO_CYCLES(T0L) - 2)</p><p>    );
      
    }
}  </p><p>  
inline void sendByte( unsigned char byte ) {
    
    for( unsigned char bit = 0 ; bit < 8 ; bit++ ) { 
     sendBit( bitRead( byte , 7 ) );   
     byte <<= 1;                                   
    }           
} </p><p>void ledsetup() {
  bitSet( PIXEL_DDR , PIXEL_BIT );
}</p><p>inline void sendPixel( unsigned char r, unsigned char g , unsigned char b )  {  
  
  sendByte(g);          // Neopixel wants colors in green then red then blue order
  sendByte(r);
  sendByte(b);
}</p><p>void show() {
  _delay_us( (RES / 1000UL) + 1);       // Round up since the delay must be _at_least_ this long (too short might not work, too long not a problem)
}</p><p>void showColor( unsigned char r , unsigned char g , unsigned char b ) {
  
  cli();  
  for( int p=0; p
<pixels; p++="" )="" {=""  ="" sendpixel(="" r="" ,="" g="" b="" );="" }="" sei();="" show();=""   ="" void="" rainbowcycle(unsigned="" char="" frames="" unsigned="" int="" frameadvance,="" pixeladvance="" firstpixelhue="0; " color="" for="" the="" first="" pixel="" in="" string="" for(unsigned="" j="0;" j<frames;="" j++)="" { ="" currentpixelhue="firstPixelHue;"  cli(); ="" i="0;" i<="" pixels;="" i++)="" if="" (currentpixelhue="">=(3*256)) {                  // Normalize back down incase we incremented and overflowed
        currentPixelHue -= (3*256);
      }
            
      unsigned char phase = currentPixelHue >> 8;
      unsigned char step = currentPixelHue & 0xff;
                 
      switch (phase) {
        
        case 0: 
          sendPixel( ~step , step ,  0 );
          break;
          
        case 1: 
          sendPixel( 0 , ~step , step );
          break;</pixels;></p><p>        case 2: 
          sendPixel(  step ,0 , ~step );
          break;
          
      }
      
      currentPixelHue+=pixelAdvance;                                      
                          
    } 
    
    sei();
    show();
    firstPixelHue += frameAdvance;
           
  }
}</p><p>void setup() {
  ledsetup();  
}</p><p>void loop() {
  rainbowCycle(1000 , 10 , 10 );
  return;
}</p>

Step 3: All Done

Hopefully, everything is working at this point but if it's not, let's finish with some troubleshooting.

1. Board isn't recognized by Arduino - make sure you have the digispark library installed and you read how to use digispark boards.

2. Code won't upload - You have to press upload and then plug in the module to the computer, dumb I know, but that's how it works.

3. Board still isn't working - Make sure your micro-USB cable allows for data as well as power, not all cables do. You can imagine I figured this out the hard way.

4. Still nothing - Your diodes could be backwards - check with a multimeter for proper orientation.

5. Weird flashing LEDs - Either this is a code issue or one of your leds isn't properly sitting on the signal pad.

6. The last 3 LEDs are messed up - Ah! you have run into my design mistake. Make sure the ground via was drilled out - checking with a multimeter continuity between the signal and the ground. Then make sure your bridge wire is also isolated from the ground.

7. Still broken - I'm honestly out of solutions, message me.

Well, I hope you've enjoyed my Instructable! Please leave a comment if you did.

Best,

Nick