/* Ansteuerung eine 2-phasigen Lichterkette per Timer0 und Erzeugung von Stromimpulsen zum Wachhalten einer Powerbank per WDT. Um 2-phasige Blinkeffekte bei Lichterketten über zwei Adern zu erzeugen, sind die angeschlossenen LEDs zur Hälfte invertiert an die Zuleitung angeschlossen. Je nach Polung leuchtet die eine Phase oder die andere. Um Dauerlicht von beiden Phasen zu erhalten, muß die Polung der Ausgänge permanent gewechselt werden. Dazu erzeugt Timer0 an den Ausgängen LED1_PIN und LED2_PIN ein gegenphasiges Signal mit rund 1,95 kHz. Laut Datenblatt darf der Ausgangsstrom/Ausgang max. 40 mA betragen, was unter Umständen einen strombegrenzen Widerstand in der Zuleitung erfordert. Da viele Powerbanks bei nur 40 mA Laststrom nach einer Minute abgeschalten, wird zusätzlich ein Ausgangsimpuls an den Ausgängen OUT1_PIN und OUT2_PIN erzeugt. Zusammen mit einem Widerstand 47 Ohm wird alle 4 s einen Stromimpuls von 80 mA für 0,3 s erzeugt. Das reicht aus, um viele Powerbanks wach zu halten und erzeugt nur eine zusätzliche Stromaufnahme von rund 6 mA. Die Stromaufnahme inkl. LED-Kette bleibt unter 50 mA. Bei Bedarf anpassen: Das Programm erzeugt einen negativen Impuls, sodaß der 47 Ohm Widerstand an +5 V einerseits und andererseits an die OUT_PINS angeschlossen wird. Michael Nowak www.mino-elektronik.de 2021-12-24 */ #include <avr/io.h> #include <avr/interrupt.h> #define BIT(x) (1<<x) #define LED1_PIN BIT(0) // PB0 #define LED2_PIN BIT(2) // PB2 #define OUT1_PIN BIT(3) // PB3 #define OUT2_PIN BIT(4) // PB4 #define LED_PINS (LED1_PIN | LED2_PIN) #define OUT_PINS (OUT1_PIN | OUT2_PIN) #define WDT_PAUSE (60*4) // 4 Sekunden Pause bei 60 Hz WDT #define WDT_IMPULS (19) // 0,3 s aktiv uint16_t wdt_cnt; // Abwärtszähler für die WDT-Zeiten ISR(WDT_vect) { // Aufruffrequenz 60 Hz if(!wdt_cnt--) { // für +Impuls nachfolgende Zeitvorgaben vertauschen if(PORTB & OUT1_PIN) // bei aktuellem +Pegel wdt_cnt = WDT_IMPULS; // Zeit für -Impuls vorgeben else wdt_cnt = WDT_PAUSE; // ansonsten Pausenzeit einstellen PORTB ^= OUT_PINS; // neuen Pegel einstellen } } ISR(TIMER0_OVF_vect) { PORTB ^= LED_PINS;; } int main(void) { DDRB = LED_PINS | OUT_PINS; PORTB = LED1_PIN; // gegenphasiges Signal für LEDs einstellen WDTCR = BIT(WDIE); // schnellstes Watchdog-Intervall 16 ms wdt_cnt = WDT_IMPULS; // mit Ausgangsimpuls = aktiv beginnen PORTB |= OUT_PINS; // und beide Ausgänge einschalten TCCR0B = BIT(CS00); // T0 einschalten 1 MHz Takt TIMSK |= BIT(TOIE0); // OVF freigeben sei(); // ISR zulassen while (1) { } }