Hallo ich habe einen ATTiny85 mit einem LED Program bespielt die Modi
werden mit einem Taster weiter geschaltet, alles läuft soweit auch,nur
in der letzten Zeile vom blinken zum Shutdownmodus geht es nur
sporatisch immer genau dann wenn das Programm die zeile (Blizen) neu
startet was hab ich falsch gemacht?
1
2
3
#include <avr/sleep.h>
4
#include <avr/interrupt.h>
5
#define BODS 7 //BOD Sleep bit in MCUCR
6
#define BODSE 2 //BOD Sleep enable bit in MCUCR
7
uint8_t mcucr1, mcucr2;
8
const int tasterPin = 2; // Taster an Pin 4 angeschlossen
9
int LED = 0;
10
int brightness = 0; // how bright the LED is
11
int fadeAmount = 5; // how many points to fade the LED by
12
// Variablen
13
boolean gedrueckt = false;
14
int lichtModusAlt = 0;
15
int lichtModus = 0; // Variable für die verschiedenen festgelegten modi
16
int tasterStatus = LOW;
17
void goToSleep(void) {
18
ACSR |= _BV(ACD); //disable the analog comparator
19
ADCSRA &= ~_BV(ADEN); //disable ADC
20
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
21
sleep_enable();
22
cli();
23
mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector
24
mcucr2 = mcucr1 & ~_BV(BODSE);
25
MCUCR = mcucr1;
26
MCUCR = mcucr2;
27
sei(); //ensure interrupts enabled so we can wake up again
28
sleep_cpu(); //go to sleep
29
cli(); //wake up here, disable interrupts
30
sleep_disable();
31
sei(); //enable interrupts again (but INT0 is disabled from above)
32
}
33
void setup()
34
{
35
pinMode(tasterPin, INPUT); // Setzt den TasterPin als Eingang
Bei einem DELAY macht der Controller nix. Auch keine Tasten abfragen.
Läuft also alles wie erwartet.
Am besten die DELAYs ausschmeissen und das ganze mit einem Timer
steuern.
Also müsste ich noch einen 6. Modus hinzufügen?? Wenn ich den Blitzmodus
weg lasse läuft alles so wie es sein soll. Ps. neu gestartet wird mit
reset Pin.
Deine Kette von if ... else sorgt dafür, dass für lichtModus 0 bis 5
immer einer der Fälle zutrifft; das Programm kommt dann nicht in die
letzte Klammer.
Das passiert erst, wenn keiner der Fälle mehr zutrifft, weil nämlich
durch Tastendruck im lichtModus 5 der lichtModus auf 6 geht.
In dem Fall wird dann LichtModus wieder auf 0 gesetzt und goToSleep()
aufgerufen.
Wenn Du einen anderen Ablauf willst, könntest Du einen zweiten Taster
einbauen, der das Gerät schlafen schickt, oder auch die Dauer des
Tastendrucks auswerten (kurz = lichtModus hochzählen, lang = schlafen
gehen).
BS schrieb:
Das passiert erst, wenn keiner der Fälle mehr zutrifft, weil nämlich
> durch Tastendruck im lichtModus 5 der lichtModus auf 6 geht.> In dem Fall wird dann LichtModus wieder auf 0 gesetzt und goToSleep()> aufgerufen.
Ok aber wenn ich 5 weg lasse funktioniert es ?
Wie kann ich den Sprung in 5 von Blitz auf sleep also am besten lösen
bzw. Warum funktioniert es von 4 auf sleep? Mfg
Wie bereits oben erwähnt wird das Programm durch delay(x) angehalten.
Funktionieren könnte es wenn der Taster so lange gedrückt wird bis die
drei Sekunden Wartezeit herum sind. Nur den richtigen Zeitpunkt
abzupassen bevor der Sleepmodus wider deaktiviert wird ist wohl eher
Glücksache.
In diesem Fall wirst du wohl um einen Timer nicht herum kommen.
Evt. wäre es möglich den INT0 zu verwenden und das Flag als Tastendruck
Indikator auszuwerten, in wie fern es mit der delay Funktion läuft kann
ich leider nicht sagen.
Das if...else ist, zumindest für mich, eher schwer zu lesen. Es würde
sich eine switch case Syntax anbieten:
https://www.programiz.com/c-programming/c-switch-case-statement
Wenn die Möglichkeit wie bei Arduino besteht Daten an den PC
zurückzusenden ist es immer hilfreich sich Werte wie den lichtModus bei
Änderung anzeigen zu lassen.
Ok danke! Aber ich benötige ja die 3Sek delay da es ja die Wartezeit für
die LED ist. Giebts es da keine Anweisung die nebenbei wartet bis die
tasterabfrage kommt? Und ja wenn ich 3 Sek. Tastern drücke geht er in
den sleep Modus.
Markus R. schrieb:> Giebts es da keine Anweisung die nebenbei wartet bis die> tasterabfrage kommt?
Es gibt sogenannte "Timer". Mit denen macht man das.
Den kannst du brav im Hintergrund zählen lassen und dein Delay durch
eine "Wenn Taste nicht gedrückt UND Wartezeit noch nicht abgelaufen ist,
dann warte"-Schleife ersetzen. Das wäre der einfachste Fall.
Informationen dazu gibt es genug hier im Forum.
Uwe K. schrieb:> Bei einem DELAY macht der Controller nix. Auch keine Tasten abfragen.> Läuft also alles wie erwartet.>> Am besten die DELAYs ausschmeissen und das ganze mit einem Timer> steuern.
Irgendwie hat er ja recht.
Du kannst aber auch das mal probieren:
1
intblitzCounter=0;
2
.
3
.
4
.
5
elseif(lichtModus==5)// Blizer
6
{
7
8
ifblitzCounter==0{
9
digitalWrite(LED,HIGH);
10
delay(10);
11
digitalWrite(LED,LOW);
12
}
13
blitzCounter+=1;
14
ifblitzCounter>=150blitzCounter=0;// nutzt die 20 ms von der Tastenentprellung
15
}
Nicht schön, weil hier ein DELAY genutzt wird, der eigendlich nicht für
das Blinken gedacht ist. Aber es sollte klappen.
leider funktioniert es so nicht folgendes wird als fehler angezeigt:
C:\Users\Notebook\Desktop\test\test.ino: In function 'void loop()':
test:96: error: expected '(' before 'blitzCounter'
if blitzCounter == 0 {
^
test:103: error: expected '(' before 'blitzCounter'
if blitzCounter >= 150 blitzCounter = 0; // nutzt die 20 ms von der
Tastenentprellung
^
exit status 1
expected '(' before 'blitzCounter'
<
<
<
1
// Konstanten // Helligkeits über Taster weiterschalten Attiny über reset aufwecken im
2
//schlafmodus ca. 0,4µA bei 5Volt
3
int blitzCounter = 0;
4
#include <avr/sleep.h>
5
#include <avr/interrupt.h>
6
#define BODS 7 //BOD Sleep bit in MCUCR
7
#define BODSE 2 //BOD Sleep enable bit in MCUCR
8
uint8_t mcucr1, mcucr2;
9
const int tasterPin = 2; // Taster an Pin 4 angeschlossen
10
int LED = 0;
11
int brightness = 0; // how bright the LED is
12
int fadeAmount = 5; // how many points to fade the LED by
13
// Variablen
14
boolean gedrueckt = false;
15
int lichtModusAlt = 0;
16
int lichtModus = 0; // Variable für die verschiedenen festgelegten modi
17
int tasterStatus = LOW;
18
void goToSleep(void) {
19
ACSR |= _BV(ACD); //disable the analog comparator
20
ADCSRA &= ~_BV(ADEN); //disable ADC
21
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
22
sleep_enable();
23
cli();
24
mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector
25
mcucr2 = mcucr1 & ~_BV(BODSE);
26
MCUCR = mcucr1;
27
MCUCR = mcucr2;
28
sei(); //ensure interrupts enabled so we can wake up again
29
sleep_cpu(); //go to sleep
30
cli(); //wake up here, disable interrupts
31
sleep_disable();
32
sei(); //enable interrupts again (but INT0 is disabled from above)
33
}
34
void setup()
35
{
36
pinMode(tasterPin, INPUT); // Setzt den TasterPin als Eingang
Markus R. schrieb:> C:\Users\Notebook\Desktop\test\test.ino: In function 'void loop()':>> test:96: error: expected '(' before 'blitzCounter'>> if blitzCounter == 0 {>> ^>> test:103: error: expected '(' before 'blitzCounter'>> if blitzCounter >= 150 blitzCounter = 0; // nutzt die 20 ms von der> Tastenentprellung>> ^>> exit status 1> expected '(' before 'blitzCounter'
Das sind elementare Grundlagen der Programmiersprache, die Du da
verwenden willst.
Der Ausdruck nach dem Schlüsselwort "if" muss in runden Klammern
untergebracht werden.
Das steht in wirklich jedem Buch über C bzw. C++ drin, auch in jedem
Arduino-Lehrgang.
Markus R. schrieb:> leider funktioniert es so nicht folgendes wird als...
So langsam wird dein Code zum Spaghetticode und sehr unleserlich.
Mein Rat: Mache es GANZ ANDERS.
Als erstes solltest du dir eine Art Systemuhr einrichten. Ob die nun
alle 1 ms oder alle 10 ms weiterzählt, ist hier wohl schnurz für deine
Led-Lichtorgel.
Als nächstes solltest du dich bekannt machen mit dem Verfahren, mit
Events zu arbeiten und dein Programm ereignisgesteuert schreiben, also
nichtblockierend schreiben.
Dann besteht dein Programm nämlich nicht mehr aus lauter blockierenden
Schleifen, sondern wird ganz einfach:
- Es kreiselt immerzu in der Hauptschleife von main und guckt dort nach,
ob in der Event-Warteschlange ein Event drin ist. Ebenso guckt es, ob
irgend eine Taste gedrückt ist oder ein Zeichen am UART angekommen ist
oder sonstwas noch eingetrudelt ist.
- Wenn ja, dann holt es diesen Event dort heraus und reagiert auf ihn.
Als Events würde ich beispielsweise sowas vorschlagen:
1
#define LED1_ein 1
2
#define LED1_aus 2
3
#define LED2_ein 3
4
#define LED2_aus 4
5
..naundsoweiterjenachGusto
6
7
undalsReaktion:
8
switch(event)
9
{caseLED1_ein:
10
SchalteLED1ein();
11
Add_Delayed_Event(3000,LED1_aus);
12
break;
13
caseLED1_aus:
14
SchalteLED1aus();
15
Add_Delayed_Event(1000,LED1_aus);
16
break;
17
...
18
usw.
Damit blinkt deine LED 3 Sekunden ein, 1 Sekunde aus. Ist nur ein
Beispiel.
- Die Systemuhr verwaltet eine kleine Liste von 3..5 "delayed" Events.
Das ist wie eine Signalverzögerung. Man kann per Funktion
so einen Event dort einsteuern und wenn die Verzögerungszeit um ist,
dann nimmt der Timer-Interrupt-Handler diesen Event aus der Liste der
Systemuhr heraus und stopft ihn in die gewöhnliche Event-Warteschlange.
Ob du nun deine Events als bytes oder int oder long deklarierst, ist
deine Sache, ebenso ob du die Verzögerungszeit als int oder long
deklarierst.
W.S.
Tastenabfrage macht man am besten per Timerinterrupt.
In der Mainloop gibt es regelmäßig Ärger oder sie ist wirklich extrem
verdammt kurz (Ausführungszeit).
Danke für eure Hilfe der Sketch läuft jetzt ohne Probleme und Hänger.
Ergänzend wollte ich noch sagen das es ein Selbstgebauter LED Schwimmer
ist wo ich einem kleinen Akku und Tiny untergebracht und mit Giesharz
ausgefüllt habe. Geladen wird mittels kleiner Induktionsspule Adafruit
micro li-ion Laderegler mit 5V1 Zenerdiode vorgeschaltet damit bei
ereichen der Ladeschlussspannung die Spannung nicht schlagartig ansteigt
und die Elektronik bzw Akku beschädigt. Die Modi werden mit integrirtem
Reedkontakt von außen mittels Magnet durchgeschalten.
Hört sich interessant an.
Gibt es dafür einen speziellen Grund oder ist das "nur" ein Blickfang
wie ein schwimmendes Teelicht?
Wenn du magst und die Möglichkeit hast wäre ein Foto ganz nett.
So etwas ist immer sehr interessant, nicht nur um es nachzubauen sondern
auch um ein paar kreative Ideen für eigene Projekte zu sammeln.
Der WAF Faktor bei einem entspannenden Bad liegt garantiert bei 10+ ;)
Bild kommt sobald ich alles zusammen habe ich hab den fürs Angeln
gemacht da es mich gestört hat jede Stunde ein neues knicklicht dran zu
machen und die Batterieschwimmer teuer Spezial Chinabatterien verwenden
und manchmal auch undicht sind.dann ist es ärgerlich wenn man 12 Euro
jedes mal für Schwimmer ausgiebt. Aber als schwimmlicht mit induktiver
wiederaufladung auch gut müsste nur in ein anderes Gehäuse rein.