Hallo, ich möchte bei meinen ATtiny 84 einen Pin Change Interrupt durchführen. Er soll die ganze Zeit schlafen bis er an dem Pin 8 ein Wechsel von Low -> High bekommt. Danach soll er einen Ausgang/Ventil schalten und sich dann wieder schlafen legen bis zum nächsten Interrupt. Ich probiere jetzt schon seit Woche daran rum leider habe ich immer noch keine Lösung gefunden, wäre super wenn irgend jemand mir weiterhelfen könnte. Und ja... ich habe sämtliche Beträge zu Pin Change Interrupt schon durchgelesen und komme trd nicht weiter. Bin noch ein blutiger Anfänger im Arduino programmieren... Danke schon mal im Voraus Simon
Simon N. schrieb: > Und ja... ich habe sämtliche Beträge zu Pin Change Interrupt schon > durchgelesen und komme trd nicht weiter. Mein Beileid. Einzige logische Konsequenz: Such' dir ein anderes Hobby. Das hier, ist einfach nicht innerhalb deiner intellektuellen Möglichkeiten...
@ TO Poste einfach dein Programm. Es gibt hier auch normaler Menschen, die dir gern helfen, nicht nur Pöbler & Asoziale.
Simon N. schrieb: > ich habe sämtliche Beträge zu Pin Change Interrupt schon > durchgelesen (1) War auch http://ww1.microchip.com/downloads/en/devicedoc/Atmel-7701_Automotive-Microcontrollers-ATtiny24-44-84_Datasheet.pdf (Seite 31ff und Seite 47ff) dabei? (2) Was genau funktioniert denn nicht? Das Schlafenlegen, das Aufwachen, oder der Interrupt selbst? (re)
1 | #include <avr/sleep.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | #define Trig 9 //digitaler Triggerport für Start Abstandsmessung
|
5 | #define Echo 8 //digitaler Ergebnisport der Abstandsmessung
|
6 | #define Poti 0 //analoger Port für Abstandseinstellung
|
7 | #define Rel 1 // digitaler Port Ansteuerung Relais
|
8 | #define TRIGGERTIMEOUT 100000
|
9 | |
10 | |
11 | |
12 | const float VENTILSPERRE_ms = 800; // Zeitspanne in ms, in der das Relais nicht wieder aktiviert werden kann zzgl. Relaislaufzeit |
13 | |
14 | int iOeffnungsdauer = 90; // Dauer der Relaisaktivierung in ms, eingestellt via Poti |
15 | |
16 | |
17 | void setup() { |
18 | |
19 | // put your setup code here, to run once:
|
20 | |
21 | pinMode(Trig, OUTPUT); |
22 | pinMode(Echo, INPUT); |
23 | pinMode(Rel, OUTPUT); |
24 | |
25 | digitalWrite(Rel, LOW); |
26 | |
27 | }
|
28 | |
29 | float Abstand_cm() |
30 | {
|
31 | float time_us = 0, time_oneway = 0, distance = 0; |
32 | const float SCHALLSPEED = 332.35772; |
33 | |
34 | delay(10); |
35 | |
36 | //Aktivierungssequenz Ultraschallsensor starten
|
37 | digitalWrite(Trig, LOW); |
38 | delayMicroseconds(5000); |
39 | digitalWrite(Trig, HIGH); |
40 | delayMicroseconds(10); |
41 | digitalWrite(Trig, LOW); |
42 | delayMicroseconds(5); |
43 | |
44 | //Rückgabe Zeitwert Weg vom Hindernis und zurück
|
45 | time_us = pulseIn(Echo, HIGH); |
46 | |
47 | //Berechnung einfache Laufzeit und Umwandlung in s
|
48 | time_oneway = time_us/2000000; |
49 | |
50 | //Berechnung Entfernung
|
51 | distance = time_oneway*SCHALLSPEED*100; |
52 | |
53 | |
54 | return distance; |
55 | |
56 | }
|
57 | |
58 | void sleep() { |
59 | |
60 | GIMSK |= _BV(PCIE0); |
61 | GIMSK |= _BV(PCIE1); |
62 | PCMSK0 |= _BV(PCINT10); // Use PB2 as interrupt pin |
63 | ADCSRA &= ~_BV(ADEN); // ADC off |
64 | set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement |
65 | |
66 | sleep_enable(); // Sets the Sleep Enable bit in |
67 | the MCUCR Register (SE BIT) |
68 | sei(); // Enable interrupts |
69 | sleep_cpu(); // sleep |
70 | |
71 | cli(); // Disable interrupts |
72 | |
73 | PCMSK0 &= ~_BV(PCINT10); // Turn off PB2 as interrupt pin |
74 | sleep_disable(); // Clear SE bit |
75 | ADCSRA |= _BV(ADEN); // ADC on |
76 | |
77 | sei(); // Enable interrupts |
78 | }
|
79 | |
80 | |
81 | |
82 | ISR(PCINT0_vect) { |
83 | |
84 | |
85 | }
|
86 | |
87 | |
88 | |
89 | ISR(PCINT1_vect) { |
90 | |
91 | }
|
92 | |
93 | |
94 | |
95 | void loop() { |
96 | |
97 | sleep(); |
98 | |
99 | // put your main code here, to run repeatedly:
|
100 | |
101 | float fAbstand; |
102 | float fAbstandswert = 12; //Default Abstandsschwellwert in cm zum |
103 | aktivieren Relais |
104 | |
105 | |
106 | fAbstand = Abstand_cm(); |
107 | |
108 | |
109 | //Öffnen Relais, wenn Abstand ausreichend
|
110 | if(fAbstand > 4){ |
111 | if(fAbstandswert >= fAbstand ) |
112 | {
|
113 | digitalWrite(Rel, HIGH); |
114 | |
115 | delay(iOeffnungsdauer); //Aktivitätsdauer Relais; |
116 | |
117 | digitalWrite(Rel, LOW); |
118 | |
119 | delay(VENTILSPERRE_ms); |
120 | }
|
121 | |
122 | //Sperrzeit Relais
|
123 | |
124 | |
125 | }
|
126 | |
127 | fAbstandswert = 10; |
128 | |
129 | |
130 | }
|
Das ist soweit mein Programm. So wie ich das PCI verstanden haben. Das Programm tut garnichts wenn ich es in den uC lade. Es ist ein Programm das vorher schon ging ohne PCI und ich das eben jetzt auf mit PCI erweitern wollte.
:
Bearbeitet durch Moderator
> PCMSK0 |= _BV(PCINT10); > PCMSK0 &= ~_BV(PCINT10); ? PCINT10 befindet sich in PCMSK1.
Reduziere das Programm mal auf weniger, wo eine LED anzeigt, ob die CPU läuft oder schläft. Teste das erstmal ohne Interrupt-Konfiguration (also für immer schlafen) und dann nochmal mit Interrupt.
S. Landolt schrieb: >> PCMSK0 |= _BV(PCINT10); >> PCMSK0 &= ~_BV(PCINT10); > > ? > PCINT10 befindet sich in PCMSK1. Stimmt das habe ich auch grad gelesen im Datenblatt http://ww1.microchip.com/downloads/en/devicedoc/Atmel-7701_Automotive-Microcontrollers-ATtiny24-44-84_Datasheet.pdf was 're (Gast) hochgeladen hat. Hab's grad ausprobiert daran liegt es nicht. Soweit ich das am Strom messen kann schläft er dauerhaft. Stefan ⛄ F. schrieb: > Reduziere das Programm mal auf weniger, wo eine LED anzeigt, ob > die CPU > läuft oder schläft. Teste das erstmal ohne Interrupt-Konfiguration (also > für immer schlafen) und dann nochmal mit Interrupt. alles klar mach ich
Beitrag #6512265 wurde von einem Moderator gelöscht.
Stefan ⛄ F. schrieb: > Reduziere das Programm mal auf weniger, wo eine LED anzeigt, ob > die CPU > läuft oder schläft. Teste das erstmal ohne Interrupt-Konfiguration (also > für immer schlafen) und dann nochmal mit Interrupt.
1 | #include <avr/sleep.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | void setup() { |
5 | |
6 | pinMode(4, OUTPUT); //LED |
7 | pinMode(8, INPUT); //Taster |
8 | |
9 | }
|
10 | |
11 | |
12 | void sleep() { |
13 | |
14 | GIMSK |= _BV(PCIE0); |
15 | GIMSK |= _BV(PCIE1); |
16 | PCMSK1 |= _BV(PCINT10); // Use PB2 as interrupt pin |
17 | ADCSRA &= ~_BV(ADEN); // ADC off |
18 | |
19 | set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement |
20 | sleep_enable(); // Sets the Sleep Enable bit inthe MCUCR Register |
21 | sei(); // Enable interrupts |
22 | sleep_cpu(); // sleep |
23 | |
24 | cli(); // Disable interrupts |
25 | |
26 | PCMSK1 &= ~_BV(PCINT10); // Turn off PB2 as interrupt pin |
27 | sleep_disable(); // Clear SE bit |
28 | ADCSRA |= _BV(ADEN); // ADC on |
29 | |
30 | sei(); // Enable interrupts |
31 | }
|
32 | |
33 | void loop() { |
34 | |
35 | sleep(); |
36 | |
37 | |
38 | digitalWrite(4, HIGH); |
39 | |
40 | delay(1000); |
41 | |
42 | digitalWrite(4, LOW); |
43 | |
44 | delay (500); |
45 | |
46 | |
47 | }
|
Das wäre jetzt das geänderte Programm wo nur eine LED leuchten soll sobald der Taster (8) betätigt wird. Der uC schläft durchgehend und wird nicht aufgeweckt.
:
Bearbeitet durch Moderator
EGS_TI schrieb: > Funktioniert das heutzutage ohne "main"-Funktion? Achso, das ist dieser Arduino Kram.
EGS_TI schrieb: > EGS_TI schrieb: >> Funktioniert das heutzutage ohne "main"-Funktion? > > Achso, das ist dieser Arduino Kram. /offTopic genau, noch ekliger als C ...... * /offTopic off Tip: versuchs mal in ASM
Kenne die arduino IDE nicht besonders, aber sollte da nicht noch irgendwo eine ISR (zumindest in C) sein, die den Pin Change INterrupt behandelt?
Asdf schrieb: > Kenne die arduino IDE nicht besonders, aber sollte da nicht noch > irgendwo eine ISR (zumindest in C) sein, die den Pin Change INterrupt > behandelt? Bitte nicht stören. Es ist die Spitzenkraft Stefan ⛄ F. am Werk.
Simon N. schrieb: > Teste das erstmal ohne Interrupt-Konfiguration Simon N. schrieb: > Das wäre jetzt das geänderte Programm: > GIMSK |= _BV(PCIE0); > GIMSK |= _BV(PCIE1); > PCMSK1 |= _BV(PCINT10); > cli(); > sei(); Sehe ich anders. Du hast Interrupts konfiguriert, aber keine ISR. Das muss abstürzen.
Stefan ⛄ F. schrieb: > Sehe ich anders. Du hast Interrupts konfiguriert, aber keine ISR. Das > muss abstürzen. Das ist zumindest in dem Minimalprogramm der Hauptfehler. Ich habe nicht geprüft, ob die PCINT-Geschichte richtig konfiguriert ist. Simon N. schrieb: > Der uC schläft durchgehend und wird nicht aufgeweckt. Weil keine ISR vorhanden ist, schläft er tatsächlich nicht dauernd, sondern macht einen Soft-Reset. Da das sleep() ganz am Anfang von loop() steht, wird er nach dem Restart als erstes auf sleep() treffen und einschlafen. Mit dem Tastendruck weckst du ihn auf, aber er macht eben einen Reset und kommt nie weiter als bis zu diesem sleep(). Da das sehr schnell geht, kannst du das nicht z.B. am Stromverbrauch messen. Und da er schon vor den Befehlen zum ein- und ausschalten der LEDs wieder Reset macht, werden die auch nicht bedient. Mach mal in deinem Testprogramm den Sleep-Aufruf ganz an den Schluss von loop(), dann wirst du was sehen. Falsch ist es wg. fehlender PCINT-ISR trotzdem. So gesehen deckt der jetzige Code wenigstens das Problem auf ...
Wie wäre den eine minimale ISR? Oder was überhaupt ein ISR ist? Kann mir da drunter leider nichts vorstellen...
:
Bearbeitet durch User
Das waren minimale ISR:
1 | ISR(PCINT0_vect) { |
2 | |
3 | }
|
4 | |
5 | |
6 | |
7 | ISR(PCINT1_vect) { |
8 | |
9 | }
|
Aber eigentlich wollte ich dich dazu animieren, erstmal ohne ISR zu testen um zu sehen, ob das Programm ansonsten in Ordnung ist. Die ISR (un Interrupt-Konfiguration) wieder einzufügen wäre der nächste Schritt danach.
Ahh oke danke. Aber wieso brauch ich das wenn ich in die ISR garnichts reinschreibe. Die ISR sagt doch quasi was während des Interrupts getan werden sollen oder?
Auf den Interrupt PCINT10 hin erfolgt ein Sprung zum dazugehörenden Interruptvektor. Folglich muss dort etwas Vernünftiges stehen, auch wenn es nur ein reti ist.
Simon N. schrieb: > Aber wieso brauch ich das wenn ich in die ISR garnichts > reinschreibe. Wenn du einen Interrupt scharf schaltest (GIMSK |= _BV(PCIE0);) und mit sei() Interrupts global aktivierst, dann muss auch eine Interrupt Service Routine vorhanden sein. Denn wenn der Interrupt auftritt, wird der Prozessor in einer Tabelle nach der Adresse dieser Routine schauen und die anspringen. Ist sie nicht definiert, läuft er ins Leere bzw. nach Adresse 0, was sich so ähnlich auswirkt wie ein Reset. Wenn die ISR nichts tun muss, kann man sie auch so definieren: EMPTY_INTERRUPT(PCINT0_vect);
In die ISR muss dann die Abfrage des Tasters. Da die PCINT-Logik der ATMegas auf alle Pegelwechsel reagiert musst Du in der ISR prüfen welche Taste den Zustand geändert hat und ob die Änderung von high->low oder low->high war. Das bedeutet, dass ein Tastendruck einen Interrupt auslöst und ein Tastenloslassen ebenfalls.
1 | ISR(PCINT1_vect) // hier Deinen passenden Vektor rein |
2 | {
|
3 | if (digitalRead(8) == HIGH) |
4 | {
|
5 | // hier kommt Deine Logik rein
|
6 | // Zum Testen einfach eine LED toggeln
|
7 | }
|
8 | }
|
Simon N. schrieb: > Aber wieso brauch ich das wenn ich in die ISR garnichts > reinschreibe. Die ISR sagt doch quasi was während des Interrupts getan > werden sollen oder? Wenn du Interrupts per Konfiguration aktiviert, dann wird die ISR Funktion beim Interrupt ausgeführt. Wenn keine solche Funktion existiert, wird irgendwas ausgeführt, nur nichts sinnvolles. Beim avr-gcc führt das konkret zu einem Neustart des Programms ähnlich einem Reset nur dass dabei die Hardware nicht zurückgesetzt wird. Das ist so als ob die jemand sagt: Wenn ich Klatsche, springe aus Fenster A, darunter fängt dich jemand auf und sagt dir wie es weiter geht. Wenn ich Huste, springe aus Fenster B, darunter fängt dich jemand auf und sagt dir wie es weiter geht. Dann springst du und niemand fängt dich auf. Weil er vergessen hat, die ISR zu schreiben. Eine Leere ISR würde einem idealten Trampolin entsprechen. Du springst raus, und es katapultiert dich dahin zurück, wo du her gekommen bist. Ohne Trampolin fällst du auf den harten Boden.
Simon N. schrieb: > Das ist soweit mein Programm. Ich habe den Code mal in
1 | [c] |
2 | ... |
3 | [/c] |
eingebettet, damit man dies auch mit Proportionalschrift lesen kann. Bitte beim nächsten Mal beachten.
Also jetzt nochmal als Wiederholung...:
1 | .
|
2 | .
|
3 | .
|
4 | ISR(PCINT1_vect) { |
5 | }
|
6 | void loop() { |
7 | |
8 | sleep(); |
9 | |
10 | digitalWrite(4, HIGH); |
11 | |
12 | delay(1000); |
13 | |
14 | digitalWrite(4, LOW); |
15 | |
16 | delay (500); |
17 | }
|
bedeutet wenn ein Interrupt am Pin anliegt, egal welcher, würde die LED ansteuern.
1 | .
|
2 | .
|
3 | .
|
4 | if (digitalRead(8) == HIGH) |
5 | {
|
6 | digitalWrite(4, HIGH); |
7 | |
8 | delay(50); |
9 | |
10 | digitalWrite(4, LOW); |
11 | |
12 | }
|
13 | void loop() { |
14 | |
15 | sleep(); |
16 | |
17 | //Motor läuft
|
18 | |
19 | }
|
wenn jetzt ein Interrupt am Pin 8 ist der von LOW -> HIGH wechselt dann leuchtet die LED und danach läuft der Motor ODER ein Interrupt am Pin 8 mit bspw. HIGH -> LOW läuft nur der Motor. (LED leuchtet nicht auf) Hab ich das ez richtig verstanden?
Simon N. schrieb: > Hab ich das ez richtig verstanden? Nein. Du musst das, was passieren soll in die ISR schreiben. Der Code:
1 | ISR(PCINT1_vect) // hier Deinen passenden Vektor rein |
2 | {
|
3 | if (digitalRead(8) == HIGH) |
4 | {
|
5 | // hier kommt Deine Logik rein
|
6 | // Zum Testen einfach eine LED toggeln
|
7 | digitalWrite(4, !digitalRead(4)); |
8 | }
|
9 | }
|
sorgt dafür, dass jedesmal, wenn die Taste gedrückt wird (aber nie, wenn sie losgelassen wird), sich der Zustand am Pin 4 des Arduino ändert.
asdf schrieb: > Du musst das, was passieren soll in die ISR schreiben. Das ist nicht wahr! Es reicht auch, wenn "das, was passieren soll" nach sleep() ausgeführt wird. Merke: Der Interrupt soll hier nur zum wecken dienen.
Arduino Fanboy D. schrieb: >> Du musst das, was passieren soll in die ISR schreiben. > Das ist nicht wahr! > > Es reicht auch, wenn "das, was passieren soll" nach sleep() ausgeführt > wird. > > Merke: > Der Interrupt soll hier nur zum wecken dienen. Ja, stimmt für diesen Fall.
Also funktioniert alles und ich hab jetzt auch verstanden worauf es bei einem PCI ankommt danke schon mal an alle Helfer!!! Dadurch hat sich aber ein neues Problem aufgetan und zwar in meinem Ursprünglichen Programm sollte ja der PCI durch einen Ultraschallsensor erfolgen. Dieser liefert ja kontinuierlich Werte... . Geht das dann überhaupt das ich den µC durch diesen Sensor aufwachen lassen kann? Bzw. kann meine Interrupt Anweisung auch so etwas wie einen Sollwert besitzen und dann erst den µC aufwachen lassen?
Manch ein AVR (vielleicht auch deiner) bietet einen Analog Komparator. Auch dieser kann als Interruptquelle dienen.
Simon N. schrieb: > sollte ja der PCI durch einen Ultraschallsensor > erfolgen. Dieser liefert ja kontinuierlich Werte... . Kontinuierliche Werte? Den musst du aktiv triggern und dann liefert er dir nach der Schalllaufzeit ein Signal am Echo-Pin. Dazwischen muss ein Timer die Zeit feststellen. Vielleicht solltest du dein Vorhaben etwas näher erläutern. Bisher ging es ja nur um den Teil des Aufwachens via PCINT. > Geht das dann > überhaupt das ich den µC durch diesen Sensor aufwachen lassen kann? Bzw. > kann meine Interrupt Anweisung auch so etwas wie einen Sollwert besitzen > und dann erst den µC aufwachen lassen? Nein, der Interrupt weckt den µC immer. Du kannst dann aber nachschauen, ob du was tun musst und wenn nicht, ihn sofort wieder einschlafen lassen. Wenn du z.B. bei jedem 10. Aufwachen nur eine Aktion ausführen willst, dann musst du in der ISR auf 10 Zählen, ein Flag setzen wenn die 10 erreicht ist und dieses in der Mainloop abfragen. Ist es gesetzt, dann lass den µC was tun. Wenn nicht, schicke in wieder in den Schlaf.
HildeK schrieb: > Vielleicht solltest du dein Vorhaben etwas näher erläutern. Ich habe bei uns im Flur einen Desinfektionsspender selber gebaut und eben so eine kleine Platine zusammengebastelt mit einem Arduino drauf. Wenn der Ultraschall Sensor eine Hand (Abstand ca. 10cm) erkennt, soll er ein Ventil kurz öffnen um einen Tropfen des Desinfektionsmittel herausfallen lassen. Da der µC zu 95% nichts tut soll er in dieser Zeit schlafen (um Energie zu sparen) und genau dieses Problem wollte ich mit den PCI beheben. HildeK schrieb: > Wenn du z.B. bei jedem 10. Aufwachen nur eine Aktion ausführen willst, > dann musst du in der ISR auf 10 Zählen, ein Flag setzen wenn die 10 > erreicht ist und dieses in der Mainloop abfragen. Ist es gesetzt, dann > lass den µC was tun. Wenn nicht, schicke in wieder in den Schlaf. Ja das wäre grundsätzlich eine Idee aber eben auf den Fall das er 95% schlafen soll, doch iwie nur ein Tropfen auf den heißen Stein. Auser ich schreib in meine ICR Anweisung eben genau diese Bedingung mit dem Abstand, setz dann dort eine Flag (wenn der Abstand erfüllt ist), bearbeite es im Programm dann erst in der loop weiter. Dann würde ja quasi der µC erst aufwachen wenn die Flag HIGH ist oder?
:
Bearbeitet durch User
Simon N. schrieb: > Geht das dann > überhaupt das ich den µC durch diesen Sensor aufwachen lassen kann? Bzw. > kann meine Interrupt Anweisung auch so etwas wie einen Sollwert besitzen > und dann erst den µC aufwachen lassen? Nee, das geht nicht. Es sei denn du verwendest einen Sensor den du auf einen bestimmten Sollwert programmieren kannst und der den µC nur bei Überschrieten der Grenze aufweckt. Simon N. schrieb: > Da der µC zu 95% nichts tut soll er in dieser Zeit > schlafen (um Energie zu sparen) und genau dieses Problem wollte ich mit > den PCI beheben. Reden wir von so einem Sensor, der einen Impuls ausgibt, dessen Länge mit der Distanz zur Person korrespondiert? Erstens nimmt der Sensor währen der Messung einige mA auf und zweitens musst die Zeitspanne messen, was nicht geht, wenn der µC während dessen im Tiefschlaf liegt. Ich würde hier eher den Clock Prescaler nutzen, um die Taktfrequenz herab zu setzen. Ein passiver IR Sensor wäre hier besser, der bräuchte weniger Standby-Strom.
Simon N. schrieb: > Wenn der Ultraschall Sensor Mit 'näher beschreiben' war mir eigentlich wichtiger, welchen Sensor du da hast, welches Signal der abgibt. Was angesteuert wird, ist jetzt klar. Ich kenne die HC-SR04, auf die bezog ich mich. Die musst du laufend mit einem Trigger versorgen und dann messen, wie lange die Zeit des Echopulses ist. Auch da kann man den Schlafmodus sinnvoll nutzen. Es reicht doch, z.B. alle 500ms eine Messung zu starten, auszuwerten und wieder in sleep gehen. Der WD-Timer kann dann zum Aufwachen dienen. Wenn niemand in der Nähe ist (Wand in 2m Abstand z.B.), dann ist der Messvorgang in rund 10-20ms abgeschlossen. Ist irgendwas näher, dann entsprechend kürzer. Leider ist ohne erkanntes Echo die Echopulsdauer sehr lang (200ms), aber man kann ja, wenn die Zeit größer als 0.5-1ms wird, abzubrechen und wieder schlafen zu gehen und es nach einem Timer-Aufwachen in 500ms erneut zu probieren. Ich habe ähnliches vor einiger Zeit gemacht in meiner Garage, so dass ich auf den Zentimeter genau mein Auto mit bestem Abstand zum Garagentor und der Wand abstellen kann. Simon N. schrieb: > Auser ich schreib in meine ICR Anweisung eben genau diese Bedingung mit > dem Abstand, setz dann dort eine Flag (wenn der Abstand erfüllt ist), > bearbeite es im Programm dann erst in der loop weiter. Dann würde ja > quasi der µC erst aufwachen wenn die Flag HIGH ist oder? Nein, wenn du in der ISR bist, dann ist er ja aufgewacht. Das Flag sagt nur dem restlichen Programm: jetzt ist was passiert, prüfe ob du was tun musst und tue es oder gehe wieder schlafen. Ich hab jetzt viel geschrieben, wenn du einen anderen Sensor hast also ich vermute, dann war das evtl. alles Makulatur. Nenne den Sensor!
HildeK schrieb: > Mit 'näher beschreiben' war mir eigentlich wichtiger, welchen Sensor du > da hast, welches Signal der abgibt. Was angesteuert wird, ist jetzt > klar. Achso sorry. Ich habe den HC-SR04 Ultraschall Sensor. Dann ist der PCI eigentlich nicht der richtige Weg... HildeK schrieb: > Ich habe ähnliches vor einiger Zeit gemacht in meiner Garage, so dass > ich auf den Zentimeter genau mein Auto mit bestem Abstand zum Garagentor > und der Wand abstellen kann. Ja genau. Eigentlich genau wie das dein µC wird ja auch die meiste Zeit schlafen bzw. eben mit dem WDT nur ab und zu messen.
Simon N. schrieb: > Achso sorry. Ich habe den HC-SR04 Ultraschall Sensor. > Dann ist der PCI eigentlich nicht der richtige Weg... So ist es! Der PCINT hilft hier nicht. Du brauchst einen Timer mit Interrupt, ich denke der CTC-Mode ist geeignet, um die Echozeit zu vermessen. Und du brauchst den WD-Interrupt, um den Schläfer regelmäßig aufzuwecken. So mal ein grober Vorschlag zur Vorgehensweise: - im Ruhezustand selten messen, z.B. alle zwei Sekunden, dazwischen schlafen. Ruhezustand kann auch heißen: die gemessene Distanz verändert sich nicht mehr: gegenüberliegende Wand z.B.. - kommt jemand näher, das Messintervall auf 250ms oder 500ms verkürzen, um schneller reagieren zu können. - wenn die richtige Distanz mit z.B. <10cm (oder was auch immer passt) erkannt wird, dann ggf. zwei, dreimal die Distanz verifizieren und dein Ventil für kurze Zeit öffnen. Ich habe ein Medianfilter mit 5 Elementen eingebaut. - dann würde ich noch eine Schutzzeit von einigen Sekunden einfügen, um wiederholtes Öffnen des Ventils zu vermeiden. - dann wieder von vorne. Anbieten würde sich zur Stromversorgung ein USB-Netzteil, da ist es nicht ganz so wichtig, dass der Prozessor möglichst viel im Power-Down-Schlaf sich befindet. Lass das Schlafen erst mal weg und programmiere die Auswertung des Sensors. Das ist die Pflicht, den Power-Save würde ich als Kür bezeichnen ...
Stefan ⛄ F. schrieb: > Ich würde hier eher den Clock Prescaler nutzen, um die Taktfrequenz > herab zu setzen. Nein, eher nicht. Du willst ja über die Schalllaufzeit messen, wie weit der 'Gegenstand' entfernt ist. Der Sensor kann 3mm auflösen, d.h. man muss Differenzen von 17µs erkennen können, wenn man ihn ausreizen will. Ich hatte meinen Tiny mit 8MHz laufen lassen und mit einer Auflösung von 50µs, entspricht knapp 1cm gearbeitet. Das dürfte mit einer herunter gesetzten Taktfrequenz dann schwierig werden.
Der LIDL-Seifenspender funktioniert mit 4xAAA. Es muss also irgendein stromsparender Sensor drin sitzen.
HildeK schrieb: > Der Sensor kann 3mm auflösen, d.h. man > muss Differenzen von 17µs erkennen können Das ist mir klar, ich hatte allerdings das Gefühl, dass er diese Auflösung gar nicht braucht. Wenn wir zum Beispiel auf 3cm Auflösung gehen, sind es 170µs, was mit einer viel geringeren Taktfrequenz geht. Außerdem kann man solche Zeiten mit einem Timer messen.
HildeK schrieb: > So mal ein grober Vorschlag zur Vorgehensweise: Alles klar so mach ich das. Könntest du mir vlt noch einen groben Programmausschnitt von dem WDT zeigen oder ein Beispiel. Ich weis einfach nicht wie ich mir das richtig zusammenreimen kann. Oder einen Tipp wo ich mir das alles erklären lassen kann was der WDT benötigt bzw. was in der Syntax enthalten muss. Stefan ⛄ F. schrieb: > Ich würde hier eher den Clock Prescaler nutzen, um die Taktfrequenz > herab zu setzen. Ich habe den Einstellung von dem Typ des Arduinos die Taktfrequenz auf 1MHz heruntergesenkt. Meinst du das? Oder irgendeinen Code im Programm?
:
Bearbeitet durch User
Simon N. schrieb: > Könntest du mir vlt noch einen groben Programmausschnitt von dem WDT > zeigen oder ein Beispiel. Ich werde morgen mal schauen. Ich habe bestimmt ein Beispiel - allerdings in reinem C (nicht Arduino) und für den Tiny85 (oder 45/25). Verwendbar ist das aber schon ...
Simon N. schrieb: > Könntest du mir vlt noch einen groben Programmausschnitt von dem WDT > zeigen oder ein Beispiel. Lies mal hier: https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_Watchdog Ist zwar nicht für Deinen ATtiny, aber sollte schon das Prinzip verdeutlichen. Alles anderes solltest Du im Datenblatt vom ATtiny finden.
:
Bearbeitet durch Moderator
HildeK schrieb: > Lass das Schlafen erst mal weg und programmiere die Auswertung des > Sensors. Das ist die Pflicht, den Power-Save würde ich als Kür > bezeichnen ... Genau so macht man es. Man teilt die Aufgabe in einzelne Module auf und die unwichtigen kommen zum Schluß dran. Aber auch nur, wenn es was bringt. Stromsparen des MC bei Netzbetrieb ist vergeudete Arbeitszeit. Ob man modular programmiert, erkennt man daran, daß sich problemlos weitere Module hinzufügen lassen. Ist alles nur ein großes undurchdringliches Codeknäuel, geht das nämlich nicht. Auch lassen sich Module nacheinander entwickeln und testen.
Peter D. schrieb: > Stromsparen des MC bei Netzbetrieb ist vergeudete Arbeitszeit. Naja ich betriebe meine Schaltung mit ein paar Batterien und umso länger die halten desto besser. Die Schaltung läuft ja gerade schon nur halt ohne iwelche stromsparende Mittel und genau deshalb möchte ich überall Stromsparen wo es geht. (Mit niedriger Taktfrequenz und WDT)
:
Bearbeitet durch User
HildeK schrieb: > Ich werde morgen mal schauen. Ich habe bestimmt ein Beispiel - Ich hab ein vorhandenes aufs Notwendigste reduziert. Siehe Anhang.
Nachtrag: Ich verwende häufigst den Tinyx5, dafür ist das Beispiel. Kann sein, dass einzelne Register im WD-Bereich leicht anders benannt sind beim Tinyx4. Das habe ich jetzt nicht geprüft. Das sollte aber leicht matchbar sein. Übrigens: deine Aufgabe müsst sich auch mit einem Tiny25 lösen lassen. Zumindest in meinem Garagenprojekt habe ich den untergebracht: 2 Pins für den Sensor, 1 Pin für 2 LEDs aus einem WS2812-Stripe. Es sind noch zwei übrig ... 😀 Zum Batteriebetrieb: Das geht natürlich damit, aber weit mehr wird als der Prozessor wird das Ventil benötigen, auch der Sensor wird hungriger sein. Soweit ich mich erinnere, kann man dem Sensor auch nicht die Stromversorgung nehmen, denn dann braucht er einige Sekunden 'Bootzeit' bis er wieder bereit ist.
HildeK schrieb: > denn dann braucht er einige Sekunden 'Bootzeit' > bis er wieder bereit ist. Vor allen Dingen darf dabei keine Person davor stehen, sonst kalibriert er sich falsch.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.