Fabrizio
Published © LGPL

Catch 'Em All, At Least This Little Pikachu Pin Badge!

This is a Pikachu pin badge. You'll see the thundershock LEDs, it has a button to select shocking effects from slow to psycho mode.

IntermediateFull instructions provided2 hours1,854

Things used in this project

Hardware components

BAT-HLD-001
×1
1 uF capacitor smd 1206
×1
Microchip pic10LF322
×1
LED smd 0805
×2
Tie tack pin
×1
N mosfet RUC002N05HZGT116
×1
P mosfet DMG2301L
×1
100 ohm smd resistor 1206
×2
1M ohm smd resistor 1206
×2
MD Push button
×1
Custom PCB
Custom PCB
×1
Coin Cell Battery CR2032
Coin Cell Battery CR2032
×1

Software apps and online services

Fusion 360
Autodesk Fusion 360
Autodesk EAGLE
Autodesk EAGLE
Microchip XC8 compiler
Gerbv

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Hot air soldering Station

Story

Read more

Schematics

Schematic

Made on Autodesk Eagle 9.2.2 free version

This contain all files.

Eagle Board ,gerbers & Code Files including the HEx files to just flash it!

Code

configuration bits

C Header File
dont forget this file
// PIC10LF322 Configuration Bit Settings

// 'C' source line config statements

// CONFIG
#pragma config FOSC = INTOSC    // Oscillator Selection bits (INTOSC oscillator: CLKIN function disabled)
#pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD)
#pragma config CP = OFF         // Code Protection bit (Program memory code protection is disabled)
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
#pragma config LPBOR = OFF      // Brown-out Reset Selection bits (BOR disabled)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>

LED pin badge code

C/C++
This is the main program, you can modify the flashings patterns.
/* 
 * File:   main.c
 * 
 * Author:  Fabrizio Barragan 
 * Twitter: @IObrizio
 * 
 * PIN LED BADGE
 * 3v battery powered (cr2032)
 * Low power device
 * One button turn ON/OFF.
 * Same button to change fancy light patterns.
 * Two LEDs controlled by PWM module at 1KHz frequency.
 * 
 * PCB made on Autodesk Eagle free version
 * Code on MPLABX & XC8
 * This is a little mcu " pic10LF322 " love it!
 * 
 * Any question send DM
 */

// 'C' source line config statements
#define _XTAL_FREQ 500000           // Fosc 500KHz  frequency for _delay()

#include <xc.h>
#include "config_bits.h"

#include <stdint.h>

#define LED_1           LATA0       // LED 1
#define LED_2           LATA1       // LED 2

#define button_Change   PORTAbits.RA3       //  Sense the input switch state
#define switch_ON_OFF   LATAbits.LATA2       // Latch ON/OFF

#define ON  1
#define OFF 0

#define pwm_MAX         255

#define menu_limit       11          // LED pattern
//--------------------------------------------------------------
void config_OSC(void);              //Oscillator Config
void config_PORT(void);             // Port pin configuration
void config_TMR0(void);             // Timer0 configuration

void config_PWM(uint8_t stat_pwm, uint8_t pr2_value);   //Enable PWM & set Freq
void SetDCPWM1(uint8_t);                                //Set PWM duty cycle
void SetDCPWM2(uint8_t);                                //Set PWM duty cycle
void my_delay_ms(uint16_t delay_ms);    // ms delay, break out if Menu changes

void effect_wakeup(uint8_t times, uint8_t pwm, uint16_t delays);    // pattern
void effect_blinking(void);    // pattern
void effect_flash_up(void);    // pattern
void effect_breading(void);    // pattern
//------------------------------------------------------------
uint8_t button_state = 0;
uint8_t pwm1_dc = 0;
uint8_t pwm2_dc = 0;
volatile uint8_t menu = 1;
volatile uint8_t menu_now = 1;
uint8_t t_on = 0;

int main(void) {

    config_OSC();       // Oscillator config
    config_PORT();      // Port Pin config  
    config_TMR0();      // TMR0 config

    INTCONbits.TMR0IF = 0;      // Clear Tmr0 flag
    INTCONbits.TMR0IE = 1;   // Enable  Tmr0_Int ON  

    INTCONbits.GIE = 1;     // Global Int ON

    config_PWM(1, 124);     // PWM ON and set Frequency at 1KHz , no flickering

    switch_ON_OFF = ON;     // Keep ON when push button is pressed

    // loop
    while (1) {             // Main Program

        if (menu > menu_limit)menu = 1;     //Return if last pattern shown

        switch (menu) {             // 

            case 0:
                menu_now = menu;
                while (menu == menu_now);   // Keep OFF until discharge
                break;
                
            case 1:                         // MIX pattern on boot
                menu_now = menu;
                effect_wakeup(10, pwm_MAX/2 ,300);
                
                effect_blinking();
                effect_blinking();
                
                effect_breading();
                effect_breading();
                effect_breading();
                
                effect_flash_up();
                
                effect_wakeup(10, pwm_MAX , 200);

                effect_breading();
                effect_breading();
                effect_breading();
                
                effect_blinking();
                effect_blinking();
                effect_blinking();

                effect_wakeup(20, pwm_MAX / 2, 200);         
                break;
                
            case 2:                     // Blinking pattern
                menu_now = menu;
                effect_blinking();
                break;

            case 3:
                menu_now = menu;
                SetDCPWM1(pwm_MAX / 16);    // 1/16 brightness
                SetDCPWM2(pwm_MAX / 16);
                while (menu == menu_now);
                break;

            case 4:
                menu_now = menu;            // Max brightness
                SetDCPWM1(pwm_MAX);
                SetDCPWM2(pwm_MAX);
                while (menu == menu_now);

                break;

            case 5:
                menu_now = menu;            // Flash both LEDs slow to fast
                effect_flash_up();
                break;

            case 6:                         // Set previus flashing speed
                menu_now = menu;
                pwm1_dc = 0;
                do {
                    pwm1_dc ^= 200;
                    SetDCPWM1(pwm1_dc);
                    SetDCPWM2(pwm1_dc);
                    my_delay_ms(t_on);

                } while (menu == menu_now);
                
            case 7:
                menu_now = menu;         // Dimming low to hi then MAX and Low
                effect_breading();
                break;

            case 8:                     // Flashing alternating
                menu_now = menu;
                pwm1_dc = 0;

                for (t_on = 20; t_on < 100; t_on++) {

                    SetDCPWM1(pwm1_dc);
                    my_delay_ms(t_on);
                    pwm1_dc ^= 200;
                    SetDCPWM2(pwm1_dc);
                    my_delay_ms(t_on);
                    if (menu != menu_now)break;
                }//for

                break;

            case 9:                     //Set las speed and pattern
                menu_now = menu;

                SetDCPWM1(pwm1_dc);
                my_delay_ms(t_on);
                pwm1_dc ^= 200;
                SetDCPWM2(pwm1_dc);
                my_delay_ms(t_on);

                break;

               
            case 10:
                menu_now = menu;
                effect_wakeup(9, pwm_MAX, 2500); // 9 flashes,max brightness,delay
                break;


            case 11:
                menu_now = menu;                // If you came here you want to
                SetDCPWM1(0);                   // turn off , so Turn off
                SetDCPWM2(0);
                switch_ON_OFF = OFF;
                my_delay_ms(100);
                while (menu == menu_now);
                break;


            default:                            // You'll never be here but
                SetDCPWM1(0);                   // it will turn OFF
                SetDCPWM2(0);
                switch_ON_OFF = OFF;
                break;
        }//switch
    } //loop Main program

} //main loop 

//Functions//-------------------- below

void my_delay_ms(uint16_t delay_ms) { // retardo en ms

    for (uint16_t aux_ms = 0; aux_ms < delay_ms; aux_ms++) {
        __delay_ms(1); // delay 1 ms FOSC dependant
        if (menu != menu_now)break;
    }

}

//------------------------------------------

void SetDCPWM1(uint8_t pwm_1_dc) {

    PWM1DCH = pwm_1_dc; //MSB PWM duty

}// set pwm 1
//------------------------------------------

void SetDCPWM2(uint8_t pwm_2_dc) {

    PWM2DCH = pwm_2_dc; //MSB PWM duty

}// set pwm 2
//------------------------------------------

void config_OSC(void) {     // 500KHz oscillator

    OSCCON = 0b00100000;
    //bit 6-4 IRCF<2:0>: INTOSC (FOSC) Frequency Select bits
    //011 = 1 MHz
    //010 = 500 kHz

}// config osc
//-----------------------------------------

void config_PORT(void) {

    ANSELA = 0; // NO ANALOG

    OPTION_REGbits.nWPUEN = 0;
    WPUAbits.WPUA3 = 1; // Pull UP RA3

    LATA = 0;
    TRISA = 0b001000;

    // RA3 <- MCLR Button A
    // RA2 -> ON/OFF circuit
    // RA1 -> LED   1
    // RA0 -> LED   2   
}// Config port
//++++++++++++++++++++++++++++++

void config_TMR0(void) { // Timer0 config

    OPTION_REGbits.T0CS = 0; //0 = Internal instruction cycle clock (FOSC/4)
    OPTION_REGbits.PSA = 0; //0 = Prescaler is assigned to the Timer0 module
    OPTION_REGbits.PS = 0b111; // Prescaler Rate 1:256

}// Timer 0 config
//++++++++++++++++++++++++++++++

void config_PWM(uint8_t stat_pwm, uint8_t pr2_value) {// Config PWM module

    if (stat_pwm) {

        TRISAbits.TRISA0 = 1;   
        TRISAbits.TRISA1 = 1;

        PWM1CON = 0;
        PWM2CON = 0;

        PR2 = pr2_value; //1KHz output

        PWM1DCH = 0; // Duty Cycle 0
        PWM1DCL = 0; // Duty Cycle 0

        PWM2DCH = 0; // Duty Cycle 0
        PWM2DCL = 0; // Duty Cycle 0

        PIR1bits.TMR2IF = 0; // TMR2 flag 0

        T2CONbits.T2CKPS = 0;
        T2CONbits.TMR2ON = 1; // Timer 2 ON

        TRISAbits.TRISA0 = 0; // PWM output pin enable
        TRISAbits.TRISA1 = 0; // PWM output pin enable

        PWM1CON = 0b11000000; // PWM enable
        PWM2CON = 0b11000000;
    } else {
        T2CON = 0;
        PWM1CON = 0;
        PWM2CON = 0;
    }

}

//------------------------------------------

/***       INTERRUPT SERVICE ROUTINE           ***/
void interrupt isr(void) {
    //----------------- TIMER0 --------------------------------
    if (INTCONbits.TMR0IE == 1 && INTCONbits.TMR0IF == 1) {

        button_state <<= 1; //rotate                

        if (button_Change == 0) {
            button_state |= 1; //bit set

        } else {
            button_state &= ~(1 << 0); //bit clear

        }

        if (button_state == 0x1F) { //Debounce filter doing polling, 5x overflow
            menu++;
        }

        TMR0 = 250; // Reload Tmr0/ overflow  4ms aprox

        INTCONbits.TMR0IF = 0; // Clear flag Tmr0

    }// TRM0 interrupt
    //------------------------------------------------------------
}// ISR

void effect_wakeup(uint8_t times, uint8_t pwm, uint16_t delays) {
    pwm1_dc = 0;
    for (uint8_t x = 0; x < times; x++) {
        pwm1_dc ^= pwm;
        SetDCPWM1(pwm1_dc);
        SetDCPWM2(pwm1_dc);
        my_delay_ms(50);
    }
    my_delay_ms(delays);
}

///+++++++++++++++

void effect_blinking(void) {
    pwm1_dc = 0;
    for (uint8_t x = 0; x < 6; x++) {
        pwm1_dc ^= pwm_MAX;
        SetDCPWM1(pwm1_dc);
        my_delay_ms(50);
    }
    my_delay_ms(100);
    for (uint8_t x = 0; x < 6; x++) {
        pwm1_dc ^= pwm_MAX;
        SetDCPWM2(pwm1_dc);
        my_delay_ms(50);
    }
    my_delay_ms(100);
}

//+++++++++++

void effect_flash_up(void) {
    pwm1_dc = 0;
    for (t_on = 80; t_on > 5; t_on--) {
        pwm1_dc ^= pwm_MAX;
        SetDCPWM1(pwm1_dc);
        SetDCPWM2(pwm1_dc);
        my_delay_ms(t_on);

        if (menu != menu_now)break;
    }//for
}

void effect_breading(void) {
    for (pwm1_dc = 0; pwm1_dc < 60; pwm1_dc++) {

        SetDCPWM1(pwm1_dc);
        SetDCPWM2(pwm1_dc);
        if (menu != menu_now)break;
        my_delay_ms(20);
    }
    for (pwm1_dc = 220; pwm1_dc > 0; pwm1_dc--) {

        SetDCPWM1(pwm1_dc);
        SetDCPWM2(pwm1_dc);
        if (menu != menu_now)break;
        my_delay_ms(3);
    }
    SetDCPWM1(0);
    SetDCPWM2(0);
    
    my_delay_ms(500);
}

Credits

Fabrizio

Fabrizio

5 projects • 16 followers
Electronic engineer

Comments