ATTiny84 - 4 Pin Change Interrupts

Gast #4363441
Lesenswert?
• ▲
▼
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
#4363457
Lesenswert?
• ▲
▼
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
(Firma: matzetronics) #4363504
Lesenswert?
• ▲
▼
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.
Gast #4363537
Lesenswert?
• ▲
▼
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
(Firma: matzetronics) #4363542
Lesenswert?
• ▲
▼
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.
#4363631
Lesenswert?
• ▲
▼
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
Angehängte Dateien:
Gast #4364758
Lesenswert?
• ▲
▼
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
#4364946
Lesenswert?
• ▲
▼
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren