ATtiny402 Meteor Lights

ATtiny402 Meteor lights Triggered by Passive infrared - Just a light easy project for fun. I used this project to help me get familiar with 202/402 chip. Schematics and code below. (NOTE, I did include the Charlieplexed led diagram, but for more information check out: https://circuitdigest.com/microcontroller-projects/charlieplexing-arduino-to-control-12-leds-with-4-gpio-pins )

Enjoy..

/* * ATtiny402-PIR-Christmas-Tree-or-Meteor-with-sleep.c * * Currently at .16uA * With Motion sensor its 16-19uA * * * * * * Created: 4/1/2022 19:25:47 * Author : Sherman Stebbins */
#define F_CPU 10000000UL#include <avr/io.h>#include <util/delay.h>#include <avr/interrupt.h>#include <avr/eeprom.h>//#include <avr/common.h> //for random();#include <stdlib.h> //for rand();
#define PA PIN3_bm#define PB PIN6_bm#define PC PIN7_bm#define PD PIN1_bm
#define ModeMax 3//#define DEBG 
const uint8_t led_dir[12] = { ( PA | PB), //LED 0 1 ( PA | PB), //LED 0 1 ( PC | PA), //LED 2 3 ( PC | PA), //LED 2 3 ( PD | PA), //LED 4 5 ( PD | PA), //LED 4 5 ( PB | PC), //LED 6 7 ( PB | PC), //LED 6 7 ( PB | PD), //LED 8 9 ( PB | PD), //LED 8 9 ( PD | PC), //LED 10 11 ( PD | PC) }; //LED 10 11
const uint8_t led[12] = { ( PA ), //LED 0 ( PB ), //LED 1 ( PA ), //LED 2 ( PC ), //LED 3 ( PA ), //LED 4 ( PD ), //LED 5 ( PC ), //LED 6 ( PB ), //LED 7 ( PD ), //LED 8 ( PB ), //LED 9 ( PC ), //LED 10    ( PD) }; //LED 11
static volatile uint8_t sleepstate = 0;static volatile uint8_t mode = 0;uint8_t randLoops;

void gotosleep(void);void ledOn(uint8_t);void ledOff(void);void rainDrop(uint8_t, uint8_t);void randRainDrops(uint8_t);void upDown(uint8_t, uint8_t);void randLeds(uint8_t);
int main(void){// uint8_t eeprom = eeprom_read_byte(0);// long tt = random(10,20); PORTA.DIRSET = 0; for(uint8_t i=0;i<12;i++){ for (uint8_t k=0;k<10;k++){ ledOn(i); _delay_ms(1); ledOff(); _delay_ms(1); if(i>0){ ledOn(i-1); _delay_ms(1); ledOff(); _delay_ms(1); } } } //pull up pin 2 and set it to trigger int on falling edge: PORTA.PIN2CTRL = PORT_ISC_RISING_gc; //this was my fix for changing current draw sei(); //Set enable interrupt //set sleep to power down //SLPCTRL.CTRLA = 0b00000101; //sherms way SLPCTRL.CTRLA = SLPCTRL_SMODE_PDOWN_gc | SLPCTRL_SEN_bm; //Microchip studio showed this gotosleep(); //sleep //asm("sleep"); //sleep
while (1){ randLoops = (rand() % 9)+3; switch(mode){ case 0: rainDrop(50,randLoops); break; case 1: randRainDrops(randLoops); break; case 2: upDown(50,randLoops); break; case 3: randLeds(randLoops); break;
default: break; } #ifdef DEBG ledOn(mode); _delay_ms(50); ledOff(); #endif if(mode++ > ModeMax-1){ mode=0; } gotosleep(); }}

void rainDrop(uint8_t speed,  uint8_t loops){ ledOff(); for(uint8_t l=0;l<loops;l++){ for(uint8_t i=0;i<12;i++){ for (uint8_t k=0;k<speed;k++){ ledOn(i); _delay_us(50); ledOff(); _delay_us(20); if(i>0){ ledOn(i-1); _delay_us(50); ledOff(); _delay_us(20); } if(i>1){ ledOn(i-2); _delay_us(50); ledOff(); _delay_us(20); } } } for(int i=0;i<5;i++){ ledOn(11); _delay_ms(10); ledOff(); _delay_ms(10); } }}
void randRainDrops(uint8_t loops){ ledOff(); int randNum; for(uint8_t l=0;l<loops;l++){ randNum = (rand() % 205)+10; for(uint8_t i=0;i<12;i++){ for (int k=0;k<randNum;k++){ ledOn(i); _delay_us(50); ledOff(); _delay_us(50); if(i>0){ ledOn(i-1); _delay_us(50); ledOff(); _delay_us(50); } } } for(int i=0;i<5;i++){ ledOn(11); _delay_ms(10); ledOff(); _delay_ms(10); } }}
void upDown(uint8_t speed, uint8_t loops){ ledOff(); uint8_t j; for(uint8_t h=0;h<loops;h++){ for(uint8_t i=0;i<12;i++){ for (uint8_t k=0;k<speed;k++){ ledOn(i); _delay_us(50); ledOff(); _delay_us(20); } } for(uint8_t i=12;i>0;i--){ j=i-1; for (uint8_t k=0;k<speed;k++){ ledOn(j); _delay_us(50); ledOff(); _delay_us(20); } } }}
void randLeds(uint8_t loops){ uint8_t randLight; uint8_t randTime; for(uint8_t i=0;i<loops;i++){ for (uint8_t k=0;k<48;k++){ randLight = rand() % 12; ledOn(randLight); randTime = (rand() % 80) + 10; for(uint8_t l=0;l<randTime;l++){ _delay_us(200); } ledOff(); } }}
void ledOn(uint8_t light){ PORTA.DIRSET = led_dir[light]; PORTA.OUT = led[light];}
void ledOff(void){ PORTA.DIRCLR = (PA|PB|PC|PD);}
void gotosleep(void){ PORTA.DIRSET = 0b00000000;
PORTA.PIN3CTRL = PORT_PULLUPEN_bm; PORTA.PIN1CTRL = PORT_PULLUPEN_bm; PORTA.PIN7CTRL = PORT_PULLUPEN_bm; PORTA.PIN6CTRL = PORT_PULLUPEN_bm;
sei(); SLPCTRL.CTRLA = 0b00000101; //set power down and sleep enable asm("sleep"); //sleep //turn off pull ups after sleep PORTA.PIN3CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN1CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN7CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN6CTRL &= ~(PORT_PULLUPEN_bm);
}
ISR(PORTA_PORT_vect){ if(sleepstate){ sleepstate=0; } //PORTA.INTFLAGS = 0x04; //clear int flag, from Ben Heck.. PORTA.INTFLAGS = PORT_INT2_bm; //not tested, got from iotn402.h}