Hier soll ein kleines Projekt umgesetzt werden, welches für die Tage um Halloween in dunklen Ecken des Hauses oder des Gartens (wasserdichtes Gehäuse!) gruselig leuchtende Augen hervorleuchten lässt. Zum Einsatz kommt hier der ATtiny13A, ein Mitglied der ATtiny-Mikrocontroller-Familie, der angeblich das höchste Stromspar-Potential aller dieser MCUs besitzt. Dies wird durch eine gewisse Einbuße in der Leistung erkauft, wie man an der folgenden Übersicht sieht.
ATtiny85 | ATtiny13A | |
---|---|---|
Flash-Speicher | 8kB | 1kB |
EEPROM | 512 | 64 |
SRAM | 512 | 64 |
8-bit Timer | 2 | 1 |
PWM-Channels | 2 | 1 |
Preis | EUR ~1,25-2,50 | EUR ~0,40-1,20 |
Der Aufbau und die Vorgehensweise wird im Beitrag zur Programmierung des ATtiny mit dem Arduino Uno grundsätzlich beschrieben. Allerdings gibt es für den ATtiny13A einige Abweichungen:
Im Menüpunkt Datei » Voreinstellungen wird im Feld Zusätzliche Boardverwalter-URLs folgende URL
hinzugefügt (kann zu evtl. anderen vorhandenen URL mit einem Komma separiert werden):
https://mcudude.github.io/MicroCore/package_MCUdude_MicroCore_index.json
Im Menüpunkt Werkzeuge » Board » Boardverwalter muss nun in der Liste nach dem "MicroCore" gesucht werden und dies wird dann installiert:
Nun werden im Menu Werkzeuge die folgenden Einstellungen getroffen:
micros()
kann zum Sparen von Flash-Speicher ein- und ausgeschaltet werden)Nun wählt man Werkzeuge » Bootloader brennen und wartet, bis der Vorgang beendet wurde. Hierbei wird kein Bootloader auf den ATtiny geschrieben, sondern lediglich die sog. Fuses für die zuvor getroffenen Einstellungen gesetzt. Dies muss nur einmal pro Chip gemacht werden, solange diese Einstellungen nicht geändert werden sollen.
Der folgende Sketch und Aufbau entspricht dem in dem Beitrag Stromsparen mit dem ATtiny, außer, dass hier der Timer des Watchdogs auf das Maximum von 8 Sekunden gesetzt wurde und natürlich der Mikrotaster nicht verwendet wird. Hier soll getestet werden, wieviel Strom der ATtiny13A im Betrieb bzw. im Sleep-Modus verbraucht, wenn er mit 3V betrieben wird.
#include <avr/sleep.h>
#include <avr/wdt.h>
#define PIN_LED PCINT0
volatile bool toggle = true;
// Watchdog imer Interrupt Service Routine
ISR(WDT_vect)
{
toggle = true;
}
void setup()
{
pinMode(PIN_LED, OUTPUT);
// setup of the WDT
cli();
wdt_reset(); // reset watchdog timer
MCUSR &= ~(1 << WDRF); // remove reset flag
WDTCR = (1 << WDCE); // set WDCE, access prescaler
WDTCR = 1 << WDP0 | 1 << WDP1 | 1 << WDP2; // set prescaler bits to to 2s
WDTCR |= (1 << WDTIE); // access WDT interrupt
sei();
}
void loop()
{
if (toggle) {
toggle = false;
digitalWrite(PIN_LED, !digitalRead(PIN_LED));
enterSleepMode();
}
}
void enterSleepMode()
{
byte adcsra;
adcsra = ADCSRA; // save ADC control and status register A
ADCSRA &= ~(1 << ADEN); // disable ADC
MCUCR |= (1 << SM1) & ~(1 << SM0); // Sleep-Modus = Power Down
MCUCR |= (1 << SE); // set sleep enable
sleep_cpu(); // sleep
MCUCR &= ~(1 << SE); // reset sleep enable
ADCSRA = adcsra; // restore ADC control and status register A
}
In dem obigen Setup wurde eine Spannungsversorgung über einen 18640-LiPo-Akku mit 3V angelegt. Die angeschlossene LED ist mit einem 1kΩ-Vorwiderstand geschaltet. Dabei verbraucht dieses Setup im Betriebsmodus -d.h. während die LED leuchtet und der ATtiny arbeitet- ~1mA. Geht der ATtiny in den Sleep-Modus, so konnte ich nur noch ~0,02mA messen.
Ziel dieses kleinen Projektes ist, zwei LEDs in verschiedenen Zeitabständen kurz aufleuchten und dann wieder erlöschen zu lassen, so dass der Eindruck entsteht ein glühendes Augenpaar blickt aus der Dunkelheit hervor. Da die glühenden Augen nur bei völliger Dunkelheit zu sehen sein sollen und die Schaltung am Tage Strom sparen soll, wird hier der Trick mit dem LDR verwendet. Das bedeutet, dass erst nach der Unterschreitung einer gewissen Helligkeitsschwelle die beiden LEDs ihre Leuchtsequenz abarbeiten.
In dem Sketch wird sowohl der Pin für die LEDs entsprechend angepasst als auch
der Code für den Sleep-Modus mit Watchdog-Timer als Wecksignal eingebaut. Um möglichst
lange Batterielaufzeiten zu erhalten, sollte die Pausenzeit zwischen dem Aufleuchten
entsprechend lang gewählt werden.
Die Pausenzeit zwischen dem Aufleuchten wird durch WAIT_CYCLES × WDT-Zeit
errechnet.
In diesem Beispiel ist WAIT_CYCLES = 10
und die WDT-Zeit 8 Sekunden.
Damit ergäben sich rechnerisch 80 Sekunden. Allerdings ist der WDT nicht sehr präzise, und somit ist dies
nur ein Richtwert.
#include <avr/sleep.h>
#include <avr/wdt.h>
#define PIN_LED PB0
#define PIN_LDR_POWER PB4
#define PIN_LDR_SENSOR PB3
#define FADE_SPEED 4 // in ms
#define GLOW_TIME 1500 // in ms
#define WAIT_CYCLES 10 // multiplier of watchdog
volatile byte cycles = 0;
ISR(WDT_vect)
{
cycles++;
}
void setup()
{
pinMode(PIN_LDR_SENSOR, INPUT);
pinMode(PIN_LDR_POWER, OUTPUT);
pinMode(PIN_LED, OUTPUT);
// intro sequence
for(byte i=0; i<5; i++) {
digitalWrite(PIN_LED, HIGH);
delay(40);
digitalWrite(PIN_LED, LOW);
delay(40);
}
// setup of the WDT
cli();
wdt_reset(); // reset watchdog timer
MCUSR &= ~(1 << WDRF); // remove reset flag
WDTCR = (1 << WDCE); // set WDCE, access prescaler
WDTCR = 1 << WDP0 | 1 << WDP3; // set prescaler bits to to 8s
WDTCR |= (1 << WDTIE); // access WDT interrupt
sei();
}
void loop()
{
digitalWrite(PIN_LDR_POWER, HIGH);
if (analogRead(PIN_LDR_SENSOR) < 200) {
if (cycles >= WAIT_CYCLES) {
glowEyes();
cycles = 0;
}
}
digitalWrite(PIN_LDR_POWER, LOW);
enterSleepMode();
}
void glowEyes()
{
pinMode(PIN_LED, OUTPUT);
for (byte i = 0; i < 255; i++) {
analogWrite(PIN_LED, i);
delay(FADE_SPEED);
}
delay(GLOW_TIME);
for (byte i = 255; i > 0; i--) {
analogWrite(PIN_LED, i);
delay(FADE_SPEED);
}
// be sure the LEDs are turned off!
digitalWrite(PIN_LED, LOW);
pinMode(PIN_LED, INPUT);
}
void enterSleepMode()
{
byte adcsra;
adcsra = ADCSRA; // save ADC control and status register A
ADCSRA &= ~(1 << ADEN); // disable ADC
MCUCR |= (1 << SM1) & ~(1 << SM0); // Sleep-Modus = Power Down
MCUCR |= (1 << SE); // set sleep enable
sleep_cpu(); // sleep
MCUCR &= ~(1 << SE); // reset sleep enable
ADCSRA = adcsra; // restore ADC control and status register A
}
Durch die geringe Anzahl an elektronische Komponenten bietet sich der Aufbau als "Freeform-Schaltung" an, wobei die Bauteile direkt verlötet werden, ohne eine Platine oder ein anderes Substrat zu verwenden.
Für besonders platzsparende Projekte kann man z.B. auf die Größe SOIC8 ("Small Outline") des Chips zurückgreifen. Der von mir erstellte ATtiny-Programmer kann diese SMD-Bauform ebenfalls beschreiben. Während das Programm hochgeladen wird, sollte der Chip z.B. mit einer Pinzette ein wenig auf die Lötstellen gedrückt werden, um bessere Leitfähigkeit zu gewährleisten.
zurück