/*
Projekt: 3 Totenkopf-LEDs für Geburtstagsgeschenk an Enrico Gruber.
Hardware: ATtiny85 (liegt gerade herum und hat 3 PWM-fähige Ausgänge)
und 3 LEDs, hier H-aktiv, an den Augen (rot) und auf der Mütze (orange).
Mikrocontroller-Portpins (in Klammern nur für ISP-Funktion):
5 PB0 OC0A (MOSI) LED linke Augenhöhle
6 PB1 OC0B (MISO) LED rechte Augenhöhle
7 PB2 INT0 (SCK) Ein-Taster
2 PB3 - -
3 PB4 OC1B LED Mütze
1 PB5 !RESET -
Stromverbrauch:
* In Gebrauch ca. 5 mA für Mikrocontroller und LEDs
* 0,14 µA nach Timeout @ 3 V
Regime:
Diverse Muster werden auf die LEDs gegeben.
Der Watchdog-Timer wird für die Spiellänge herangezogen
und greift dadurch „zufällig“ in die feste Sequenz ein.
*/
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
typedef unsigned char byte;
ISR(INT0_vect) {
wdt_reset();
GPIOR1 = 30; // ≈ 30 s Action
}
ISR(WDT_vect) {
if (!--GPIOR1) {
WDTCR = 0x06; // Watchdog anhalten
DDRB = 0; // Keine Ausgänge
MCUCR = 0x30; // PowerDown, INT0 asynchron
sei();
sleep_cpu(); // Einzige Interruptquelle: Taster
MCUCR = 0x22; // Idle, INT0 bei fallender Flanke
GIFR = 0x40;
DDRB = 0x13;
WDTCR = 0x46;
}
}
ISR(TIMER0_OVF_vect) {
++GPIOR2;
}
// Timerüberläufe (2 ms) warten, 0 = 256 ≈ 0,5 s
static void delay(byte t) {
do sleep_cpu(); while(--t);
}
int main() {
PORTB = 0x04;
DDRB = 0x13;
DIDR0 = 0x3B; // Digital-Lesefunktion nur an PB2
MCUCR = 0x22; // Idle und INT0 bei fallender Flanke
GIFR = 0x40;
GIMSK = 0x40; // INT0 aktiv
ACSR = 0x80;
TCCR0A= 0xA3; // OC0A, OC0B: PWM nichtinvertierend
TCCR0B= 0x02; // PWM mit ≈ 500 Hz bei Vorteiler 8
TIMSK = 0x02; // Timer0-Überlauf = Interrupt = Zeitschritt für Programm
TCCR1 = 0x84; // Vorteiler 8, PWM-Modus
GTCCR = 0x60; // OC1B = nichtinvertierende PWM, !OC1B frei
GPIOR1= 15; // 15 s nach PowerOn (nach Taster länger)
WDTCR = 0xDE; // 1 s
WDTCR = 0x46; // Interrupt-Mode
sei();
for(;;){
// Programm 1: Wechselblinken, Kopf halbe Frequenz, 10 Zyklen
byte z=10,t=0;
OCR1B = 0;
do{
OCR1B =~OCR1B; // oben an
OCR0A = 0xFF; // links an
OCR0B = 0x00; // rechts aus
delay(0); // 0,5 s
OCR0A = 0x00;
OCR0B = 0xFF;
delay(0); // 0,5 s
}while (--z);
// Programm 2: Auf- und Abschwellen der Augen, wechselseitig
z=10;
do{
OCR1B = 0x60;
do{
OCR0A = --t; // links dunkler werdend
OCR0B = ~t; // rechts heller werdend
sleep_cpu(); // 2 ms
}while(t);
OCR1B = 0x20;
do{
OCR0B = --t; // rechts dunkler werdend
OCR0A = ~t; // links heller werdend
sleep_cpu(); // 2 ms
}while(t);
}while (--z);
// Programm 3: Zwinkern (beide Augen)
z=10;
do{
OCR1B = 0xE8;
for (byte zz=0; zz<2; zz++) {
OCR0A = OCR0B = 0xFF;
delay(10);
OCR0A = OCR0B = 0x00;
delay(30);
}
do sleep_cpu(); while(--t);
OCR1B-= 0x18;
}while (--z);
}
}
Detected encoding: UTF-8 | 0
|