Habe mir in den Kopf gesetzt (von meinen Jungs angeregt) Legospielzeug mit LEDs auszustatten. Für den Beginn habe ich den Wunsch, dass der Attiny
auf Tasterdruck aufwacht und die Led einschaltet
nach 5min automatisch abschaltet und in den Schlafmodus geht bzw dies auf Tasterdruck geschieht
1led an 3v Cr2032 mit Taster an Attiny45
Habe tagelang gebastelt, zusammenkoppelt und versucht. Kann mir jemand einen Gesankenanstoss bzgl Programmierung geben? Das wäre ungeheuerlich toll für meine Nerven
Danke für den Beispielcode und den Anstoss! (sry XenOn hatte versehentlich eine Nachricht statt Post gesendet).
Ist es nun so, dass ich Interrupt, Sleep_Mode und die Schaltung mit Timer kombinieren kann?
Aktuell gibt mir die Überprüfung noch einen Fehler aus welchen ich noch nicht ergooglen konnte...??
Ursache ---> GIMSK |= _BV(INT0); //enable INT0
MCUCR &= ~(_BV(ISC01) | _BV(ISC00)); //INT0 on low level
Darauf folgend die Frage ob ich so den Stromverbrauch minimiert habe.
#include <avr/sleep.h>
#include <avr/interrupt.h>
#define BODS 7 //BOD Sleep bit in MCUCR
#define BODSE 2 //BOD Sleep enable bit in MCUCR
uint8_t mcucr1, mcucr2;
#define taster 0 // Die Zahlen mit den genutzten Pins ersetzten
#define led 1 // Bei diesem Beispiel ist der Taster an Pin 0 und die led an Pin 1
boolean tasterold, tasternew; // Bit Variabeln für Flankenerkennung
boolean state; // Bit Variabel für den Zustand der led
unsigned int timer; // Variabel von 0 - 65535 für Zeit
void goToSleep(void)
{
GIMSK |= _BV(INT0); //enable INT0
MCUCR &= ~(_BV(ISC01) | _BV(ISC00)); //INT0 on low level
ACSR |= _BV(ACD); //disable the analog comparator
ADCSRA &= ~_BV(ADEN); //disable ADC
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
//turn off the brown-out detector.
//must have an ATtiny45 or ATtiny85 rev C or later for software to be able to disable the BOD.
//current while sleeping will be <0.5uA if BOD is disabled, <25uA if not.
cli();
mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector
mcucr2 = mcucr1 & ~_BV(BODSE);
MCUCR = mcucr1;
MCUCR = mcucr2;
sei(); //ensure interrupts enabled so we can wake up again
sleep_cpu(); //go to sleep
cli(); //wake up here, disable interrupts
GIMSK = 0x00; //disable INT0
sleep_disable();
sei(); //enable interrupts again (but INT0 is disabled from above)
}
ISR(INT0_vect) {
} //nothing to actually do here, the interrupt just wakes us up!
void setup() {
pinMode(taster, INPUT); // taster als Input festlegen
pinMode(led, OUTPUT); // led als Output festlegen
digitalWrite(led, LOW); // led ausschalten
}
void loop() {
// Flankenerkennung
tasterold = tasternew;
tasternew = digitalRead(taster);
if (!tasterold & tasternew) // Auf die positive Flanke der Taste
{
state = !state; // Zustand der Led wechseln (wenn on dann off/ wenn off dann on)
timer = 0; // Timer resetten
}
if(state == HIGH) // überprüfen ob die led ein sein soll
{
if (timer == 1000) // Die Zeit bis zum automatischen ausschalten in 10ms -> 1s = 100, 1min -> 600..
{
state = LOW; // Wenn Zeit abgelaufen led ausschalten
}
else
{
timer++; // Zeit hochzählen
}
digitalWrite(led, HIGH); // LED EINSCHALTEN
}
else // sonst:
{
digitalWrite(led, LOW); // LED AUSSCHALTEN
}
delay(10); // Verzögerung von 10ms
}
Das mit dem externen Interrupt INT0 aktivieren und deaktivieren solltest du auch über die Arduino Mittel attachInterrupt() und detachInterrupt() machen können. Dann halt eine leere Funktion anhängen.
Gelöst ist es nun über diesen Code. Mit dem eingesetzten Attiny45 läuft es problemlos mit Timer.
CR2032 -> Taster -> Attiny45 -> 1x LED
per Taster an/ausschalten, Timer 3min -> Sleep Mode Power Down
#include <avr/sleep.h>
#include <avr/interrupt.h>
#define BODS 7 //BOD Sleep bit in MCUCR
#define BODSE 2 //BOD Sleep enable bit in MCUCR
uint8_t mcucr1, mcucr2;
#define taster 0 // Die Zahlen mit den genutzten Pins ersetzten
#define led 1 // Bei diesem Beispiel ist der Taster an Pin 0 und die led an Pin 1
boolean tasterold, tasternew; // Bit Variabeln für Flankenerkennung
boolean state; // Bit Variabel für den Zustand der led
unsigned int timer; // Variabel von 0 - 65535 für Zeit
void goToSleep(void)
{
GIMSK |= _BV(INT0); //enable INT0
MCUCR &= ~(_BV(ISC01) | _BV(ISC00)); //INT0 on low level
ACSR |= _BV(ACD); //disable the analog comparator
ADCSRA &= ~_BV(ADEN); //disable ADC
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
//turn off the brown-out detector.
//must have an ATtiny45 or ATtiny85 rev C or later for software to be able to disable the BOD.
//current while sleeping will be <0.5uA if BOD is disabled, <25uA if not.
cli();
mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector
mcucr2 = mcucr1 & ~_BV(BODSE);
MCUCR = mcucr1;
MCUCR = mcucr2;
sei(); //ensure interrupts enabled so we can wake up again
sleep_cpu(); //go to sleep
cli(); //wake up here, disable interrupts
GIMSK = 0x00; //disable INT0
sleep_disable();
sei(); //enable interrupts again (but INT0 is disabled from above)
}
ISR(INT0_vect) {
} //nothing to actually do here, the interrupt just wakes us up!
void setup() {
pinMode(taster, INPUT); // taster als Input festlegen
pinMode(led, OUTPUT); // led als Output festlegen
digitalWrite(led, LOW); // led ausschalten
}
void loop() {
// Flankenerkennung
tasterold = tasternew;
tasternew = digitalRead(taster);
if (!tasterold & tasternew) // Auf die positive Flanke der Taste
{
state = !state; // Zustand der Led wechseln (wenn on dann off/ wenn off dann on)
timer = 0; // Timer resetten
}
if(state == HIGH) // überprüfen ob die led ein sein soll
{
if (timer == 18000) // Die Zeit bis zum automatischen ausschalten in 10ms -> 1s = 100, 1min -> 600..
{
state = LOW; // Wenn Zeit abgelaufen led ausschalten
}
else
{
timer++; // Zeit hochzählen
}
digitalWrite(led, HIGH); // LED EINSCHALTEN
}
else // sonst:
{
digitalWrite(led, LOW); // LED AUSSCHALTEN
goToSleep(); // In den Schlafmodus setzten
}
delay(10); // Verzögerung von 10ms
}
Ohne Hilfe würd ich noch immer hier sitzen - vielen Dank an alle und ganz besonderer Dank an XenOn!!!