Hackster is hosting Hackster Holidays, Ep. 7: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 7 on Friday!
Fabrizio
Published © GPL3+

Autobots Pin Badge

Give some Energon to bring it to life... Autobots, roll out!!

IntermediateFull instructions provided2 hours2,027

Things used in this project

Hardware components

Microchip pic10LF322
×1
smd LED 1206
×2
smd capacitor 1206 1uF
×1
smd resistor 1206 47ohms
×2
smd push button
×1
cr1220/25 battery holder
×1
hardware pin
×1

Software apps and online services

Fusion
Autodesk Fusion
Autodesk EAGLE
Autodesk EAGLE
gerbv

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Schematic

Autobot PCB files

These are the main files, made on Autodesk Eagle free version.
Schematic,Board and Gerber files.

Code

main.c

C/C++
This is the main code, modify as you want.
/* 
 * File:   main.c
 * 
 * Author:  Fabrizio Barragan 
 * Twitter: @IObrizio
 * 
 * PIN LED BADGE autobot
 * 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!
 * 
 * Poner el uC en bajo consumo cuando no este activo , SLEEP
 * Despertarlo mediante interrupcion exter cambio de estado de 1-0 en RA3
 * 
 *  Wide Operating Range:
 * 1.8V to 3.6V (PIC10LF320/322)
 * 
 * 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 pwm_MAX         250

#define menu_limit       6          // 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



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

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

        switch (menu) { // 

            case 1: // MIX pattern on boot
                menu_now = menu;
                effect_wakeup(10, pwm_MAX / 2, 300);
                effect_breading();
                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; // Max brightness
                effect_flash_up();

                break;
            case 6:
                menu_now = menu; // If you came here you want to
                SetDCPWM1(10); // turn off , so Turn off
                SetDCPWM2(10);
                my_delay_ms(250);
                config_PWM(0, 124);
                IOCAF = 0;
                INTCONbits.IOCIE = 1; // Enable  Tmr0_Int ON 
                SLEEP();
                NOP();
                NOP();
                IOCAF = 0;
                INTCONbits.IOCIE = 0; // 
                config_PWM(1, 124);
                my_delay_ms(500);
                button_state = 0;
                menu = 1;

                break;


            default: // You'll never be here but
                SetDCPWM1(0); // it will turn OFF
                SetDCPWM2(0);
                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 7 Unimplemented: Read as ?0?
    //bit 6-4 IRCF<2:0>: INTOSC (FOSC) Frequency Select bits
    //111 = 16 MHz
    //110 = 8 MHz (default value)
    //101 = 4 MHz
    //100 = 2 MHz
    //011 = 1 MHz
    //010 = 500 kHz *****
    //001 = 250 kHz
    //000 = 31 kHz (LFINTOSC)
    //bit 3 HFIOFR: High-Frequency Internal Oscillator Ready bit
    //1 = 16 MHz Internal Oscillator (HFINTOSC) is ready
    //0 = 16 MHz Internal Oscillator (HFINTOSC) is not ready
    //bit 2 Unimplemented: Read as ?0?
    //bit 1 LFIOFR: Low-Frequency Internal Oscillator Ready bit
    //1 = 31 kHz Internal Oscillator (LFINTOSC) is ready
    //0 = 31 kHz Internal Oscillator (LFINTOSC) is not ready
    //bit 0 HFIOFS: High-Frequency Internal Oscillator Stable bit
    //1 = 16 MHz Internal Oscillator (HFINTOSC) is stable
    //0 = 16 MHz Internal Oscillator (HFINTOSC) is not stable
}// config osc
//-----------------------------------------

void config_PORT(void) {

    ANSELA = 0; // NO ANALOG

    IOCAP = 0;
    IOCAN = 0b1000;

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

    LATA = 0;
    TRISA = 0b001000;

    // RA3 <- MCLR Button A
    // RA2 -> --
    // 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) {
    if (INTCONbits.IOCIE == 1 && INTCONbits.IOCIF == 1) {

        INTCONbits.IOCIE = 0;
        IOCAF = 0;

    }
    //----------------- 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
            button_state = 0;
            menu++;
            while (button_Change == 0);
        }

        TMR0 = 247; // 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);
}

Configuration bits

C/C++
Dont forget use this config.
// 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 = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF       // 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>

HEX File

BatchFile
Here is the HEX file
No preview (download only).

Credits

Fabrizio
5 projects • 16 followers
Electronic engineer

Comments