Hallo, versuche seit Tagen mit dem ATTiny84 und der Arduino IDE/Arduino ISP 3 Pin Change Interupts auf PCIE0 und 1 Pin Change Interupt auf PCIE1 inkl. 4 LED Kontrollen hinzubekommen. Zusätzlich müsste ich bei den 3en noch ermitteln können, welcher Pin getriggert hat, um die richtige LED ansteuern zu können. Bin Anfänger und erbitte Hilfe. Codebeispiel (Arduino) ist herzlich willkommen. Danke Matthias
Hallo, Deinen Satz, was Du wo und wie machen willst, habe ich nichteinmal verstanden... Zeige Dein Programm, was Du gemacht hast, erkläre, was es machen soll und sage, was stattdessen passiert. Dann kann man sich damit auch auseinandersetzen und vielleicht helfen. Hast Du eine der existierenden Libs benutzt oder den PCI selbst geschrieben? Gruß aus Berlin Michael
:
Bearbeitet durch User
Matthias schrieb: > Zusätzlich müsste ich bei den 3en noch > ermitteln können, welcher Pin getriggert hat, um die richtige LED > ansteuern zu können. Das geht nur, wenn du weisst, was für ein Pegel den IRQ ausgelöst haben müsste, denn der PinChange Interrupt tut genau das - bei Pegelwechsel reagieren. Wenn du z.B. weisst, das ein Lowpegel den IRQ ausgelöst haben muss, fragst du das PIN Register des Portes direkt am Anfang der ISR ab und entscheidest, welcher der drei Pins ausgelöst hast.
Danke für die Antwort Habe 3 Bewegungsmelder und einen Taster und möchte, dass der uC per Interrupt aufwacht, sobald einer davon auslöst. Erforderlich ist, dass der auslösende Bewegungsmelder im Programm ermittelt werden kann. Als Kontrolle soll jeweils noch die entsprechende LED angesteuert werden.
1 | #include <avr/sleep.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | const int dRButton = ??; //pin?? Taster |
5 | const int dRPC1 = ??; //pin?? Eingang1 |
6 | const int dRPC2 = ??; //pin?? Eingang2 |
7 | const int dRPC3 = ??; //pin?? Eingang3 |
8 | |
9 | const int dwButton = ??; //pin?? LED |
10 | const int dWPC1 = ??; //pin?? LED |
11 | const int dWPC2 = ??; //pin?? LED |
12 | const int dWPC3 = ??; //pin?? LED |
13 | |
14 | |
15 | void setup() { |
16 | |
17 | pinMode(dRButton, INPUT); |
18 | digitalWrite(dRButton, HIGH); |
19 | |
20 | pinMode(dRPC1, INPUT); |
21 | digitalWrite(dRPC1, HIGH); |
22 | |
23 | pinMode(dRPC2, INPUT); |
24 | digitalWrite(dRPC2, HIGH); |
25 | |
26 | pinMode(dRPC3, INPUT); |
27 | digitalWrite(dRPC3, HIGH); |
28 | |
29 | |
30 | pinMode(dWButton, OUTPUT); |
31 | digitalWrite(dWButton, LOW); |
32 | |
33 | pinMode(dWPC1, OUTPUT); |
34 | digitalWrite(dWPC1, LOW); |
35 | |
36 | pinMode(dWPC2, OUTPUT); |
37 | digitalWrite(dWPC2, LOW); |
38 | |
39 | pinMode(dWPC3, OUTPUT); |
40 | digitalWrite(dWPC3, LOW); |
41 | |
42 | } |
43 | |
44 | |
45 | void sleep() { |
46 | |
47 | GIMSK |= _BV(PCIE0); |
48 | GIMSK |= _BV(PCIE1); |
49 | PCMSK0 |= _BV(PCINT0); // Use PA0 as interrupt pin |
50 | PCMSK0 |= _BV(PCINT1); // Use PA1 as interrupt pin |
51 | PCMSK0 |= _BV(PCINT2); // Use PA2 as interrupt pin |
52 | PCMSK1 |= _BV(PCINT8); // Use PB0 as interrupt pin |
53 | ADCSRA &= ~_BV(ADEN); // ADC off |
54 | |
55 | set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement |
56 | sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT) |
57 | sei(); // Enable interrupts |
58 | sleep_cpu(); // sleep |
59 | |
60 | sleep_disable(); // Clear SE bit |
61 | |
62 | cli(); // Disable interrupts |
63 | |
64 | PCMSK1 &= ~_BV(PCINT8); // Turn off PB0 as interrupt pin |
65 | PCMSK0 &= ~_BV(PCINT2); // Turn off PA2 as interrupt pin |
66 | PCMSK0 &= ~_BV(PCINT1); // Turn off PA1 as interrupt pin |
67 | PCMSK0 &= ~_BV(PCINT0); // Turn off PA1 as interrupt pin |
68 | ADCSRA |= _BV(ADEN); // ADC on |
69 | |
70 | } |
71 | |
72 | |
73 | ISR(PCINT0_vect) { |
74 | |
75 | // Check which Pin triggered |
76 | |
77 | // ToDO if dRPC1 triggered |
78 | // ToDO if dRPC2 triggered |
79 | // ToDO if dRPC3 triggered |
80 | |
81 | } |
82 | |
83 | |
84 | ISR(PCINT1_vect) { |
85 | |
86 | // ToDO if dRButton triggered |
87 | |
88 | } |
89 | |
90 | |
91 | void loop() { |
92 | |
93 | sleep(); |
94 | |
95 | // ToDo |
96 | |
97 | } |
Bin noch am Probieren, ob ich bei den Konstanten-Deklarationen die Phys. Pin Nr. oder die Tinycore Ref Nr. angeben muss, deshalb die ?? Wie erwähnt bin ich Anfänger und habe mir o.g. Code fragmentweise aus dem Internet zusammengereimt
Matthias S. schrieb: > fragst du das PIN Register des Portes direkt am Anfang der ISR ab und Wenn ich wüsste wie, hätte ich es vielleicht schon gemacht ;-)
Matthias schrieb: > und habe mir o.g. Code fragmentweise aus > dem Internet zusammengereimt Da steht ja auch gar nichts drin, ausser ein bisschen Arduino Zeugs. Bei deinem jetzigen Stand empfehle ich dir, lieber einfach in der Hauptschleife die Eingänge der Bewegungsmelder abzufragen und damit weiter zu arbeiten. Die Sache mit den Interrupts verschieben wir mal.
Hallo, bei der Arduino-Geschichte gibt es gerade am Anfang mehrere Wege: man legt sich vorerst auf die Möglichkeiten der Ardunino-Libs fest und schaut, was man da findet und wie man damit klarkommt. Alternativ kann man auch in der Arduino-IDE einfach alles in C von Hand machen und orientiert sich an den Beispielen die es dort gibt. Beides mischen ohne große Programmiererfahrung auf dem AVR ist zumindest problematisch. Die Arduino-Erweiterungen erwarten die Pinnummern der Arduino-Boards, die GCC-Makros (_BV z.B.) erwarten die Bezeichnungen der AVR-CPU. Ich habe hier gerade ein Beipiel gefunden, das scheint auch Deine Basis zu sein und sollte zum ersten Test unverändert ganz brauchbar zu sein. Daran dann eben schrittweise anbauen. https://bigdanzblog.wordpress.com/2014/08/10/attiny85-wake-from-sleep-on-pin-state-change-code-example/ Im Anhang ein Bild mit den Pin-Zuordnungen der Tinys, ich finde das leider im Netz nicht mehr wieder... Gruß aus Berlin Michael
:
Bearbeitet durch User
Hallo Michael, Michael U. schrieb: > Die Arduino-Erweiterungen erwarten die Pinnummern der Arduino-Boards, Diese Info und der Anhang helfen mir sicher weiter, werde heute Abend mal testen Danke
Habs hinbekommen inkl. Abfrage Pin Register Evtl. kann der Code jemand anders weiterhelfen
1 | #include <avr/sleep.h> |
2 | #include <avr/interrupt.h> |
3 | |
4 | const int dRPC1 = 1; |
5 | const int dRPC2 = 2; |
6 | const int dRPC3 = 3; |
7 | const int dRBell = 9; |
8 | |
9 | const int dWAlarm = 0; |
10 | const int dWPC1 = 4; |
11 | const int dWPC2 = 5; |
12 | const int dWPC3 = 6; |
13 | const int dWBell = 10; |
14 | |
15 | volatile int IRQNr = 0; |
16 | volatile int IRQRegister = 2; |
17 | |
18 | |
19 | void setup() { |
20 | |
21 | pinMode(dWAlarm, OUTPUT); |
22 | digitalWrite(dWAlarm, LOW); |
23 | |
24 | pinMode(dWPC1, OUTPUT); |
25 | digitalWrite(dWPC1, LOW); |
26 | |
27 | pinMode(dWPC2, OUTPUT); |
28 | digitalWrite(dWPC2, LOW); |
29 | |
30 | pinMode(dWPC3, OUTPUT); |
31 | digitalWrite(dWPC3, LOW); |
32 | |
33 | pinMode(dWBell, OUTPUT); |
34 | digitalWrite(dWBell, LOW); |
35 | |
36 | |
37 | pinMode(dRPC1, INPUT); |
38 | digitalWrite(dRPC1, HIGH); |
39 | |
40 | pinMode(dRPC2, INPUT); |
41 | digitalWrite(dRPC2, HIGH); |
42 | |
43 | pinMode(dRPC3, INPUT); |
44 | digitalWrite(dRPC3, HIGH); |
45 | |
46 | pinMode(dRBell, INPUT); |
47 | digitalWrite(dRBell, HIGH); |
48 | |
49 | } |
50 | |
51 | |
52 | void sleep() { |
53 | |
54 | GIMSK |= _BV(PCIE0); |
55 | GIMSK |= _BV(PCIE1); |
56 | PCMSK0 |= _BV(PCINT1); // Use PA1 as interrupt pin |
57 | PCMSK0 |= _BV(PCINT2); // Use PA1 as interrupt pin |
58 | PCMSK0 |= _BV(PCINT3); // Use PA1 as interrupt pin |
59 | PCMSK1 |= _BV(PCINT9); // Use PA0 as interrupt pin |
60 | ADCSRA &= ~_BV(ADEN); // ADC off |
61 | |
62 | set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement |
63 | sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT) |
64 | sei(); // Enable interrupts |
65 | sleep_cpu(); // sleep |
66 | |
67 | sleep_disable(); // Clear SE bit |
68 | |
69 | // cli(); // Disable interrupts |
70 | |
71 | PCMSK1 &= ~_BV(PCINT9); // Turn off PA1 as interrupt pin |
72 | PCMSK0 &= ~_BV(PCINT3); // Turn off PA1 as interrupt pin |
73 | PCMSK0 &= ~_BV(PCINT2); // Turn off PA1 as interrupt pin |
74 | PCMSK0 &= ~_BV(PCINT1); // Turn off PA0 as interrupt pin |
75 | ADCSRA |= _BV(ADEN); // ADC on |
76 | |
77 | } |
78 | |
79 | |
80 | ISR(PCINT0_vect) { |
81 | |
82 | cli(); // Disable interrupts |
83 | |
84 | byte PVal; // Port value (8 Bits) |
85 | byte IRQ1ActVal; // Actual IRQ1 value |
86 | byte IRQ2ActVal; // Actual IRQ2 value |
87 | byte IRQ3ActVal; // Actual IRQ2 value |
88 | |
89 | IRQRegister = 0; |
90 | |
91 | PVal = PINA; // Read port A (8 bit) |
92 | IRQ1ActVal = PVal & (1<<PCINT1); // Mask out all except IRQ1 |
93 | IRQ1ActVal = IRQ1ActVal >> PCINT1; // shift to right for bit0 position |
94 | IRQ2ActVal = PVal & (1<<PCINT2); // Mask out all except IRQ2 |
95 | IRQ2ActVal = IRQ2ActVal >> PCINT2; // shift to right for bit0 position |
96 | IRQ3ActVal = PVal & (1<<PCINT3); // Mask out all except IRQ2 |
97 | IRQ3ActVal = IRQ3ActVal >> PCINT3; // shift to right for bit0 position |
98 | |
99 | if(IRQ1ActVal==0) |
100 | { |
101 | IRQNr = 1; |
102 | } |
103 | |
104 | if(IRQ2ActVal==0) |
105 | { |
106 | IRQNr = 2; |
107 | } |
108 | |
109 | if(IRQ3ActVal==0) |
110 | { |
111 | IRQNr = 3; |
112 | } |
113 | |
114 | } |
115 | |
116 | |
117 | ISR(PCINT1_vect) { |
118 | cli(); // Disable interrupts |
119 | IRQRegister = 1; |
120 | } |
121 | |
122 | |
123 | void loop() { |
124 | |
125 | sleep(); |
126 | |
127 | if (IRQRegister == 0) |
128 | { |
129 | digitalWrite(IRQNr + 3, HIGH); |
130 | digitalWrite(dWAlarm, HIGH); |
131 | delay(2000); |
132 | digitalWrite(dWAlarm, LOW); |
133 | digitalWrite(IRQNr + 3, LOW); |
134 | } |
135 | else if (IRQRegister == 1) |
136 | { |
137 | digitalWrite(dWBell, HIGH); |
138 | delay(2000); |
139 | digitalWrite(dWBell, LOW); |
140 | } |
141 | |
142 | IRQRegister = 2; |
143 | IRQNr = 0; |
144 | |
145 | } |
Danke an alle Helfer
Hallo, die Interrupts brauchst Du in der ISR nicht zu sperren, das erledigt die Hardware des AVR alleine. Um den restlichen Ablauf (nötige Register retten usw.) kümmert sich der Compiler. Die nötige Nutzung von volatile hast Du ja offenbar schon selbst entdeckt. Viel Spaß weiterhin. Gruß aus Berlin Michael
:
Bearbeitet durch User
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.