Attiny84 - Interrupt an PIN8 PCINT10 triggert nur jedes 2. mal

Gast #5986916
Hallo,

ich finde den Fehler nicht. PIN8 ist mit Pulldown an GND und eine 
parallel an den auslösenden Taster (VCC) angeschlossene LED leuchtet bei 
jeder Betätigung -> Fehler kann nur im Code versteckt sein.

1
#include <avr/sleep.h>
2
#include <avr/interrupt.h>
3

4
const int PIN2Free = 2;
5

6
const int aRDelay = A0;
7

8
const int dRFritzLEDWLAN = 1;
9
const int dROKFritzLEDINet = 6;
10
const int dROKP7 = 7;
11
const int dRBell = 8;
12

13
const int dWWLANOn =  3;
14
const int dWNETIO =  4;
15
const int dWWLANOff =  5;
16
const int dWLiftHandset =  9;
17
const int dWRedial = 10;
18

19
volatile int ISRTrigger=0;
20

21
volatile uint8_t portbhistory;
22
volatile uint8_t portahistory;
23

24
  
25
void setup() {
26

27
  pinMode(0, INPUT);
28
  pinMode(dRFritzLEDWLAN, INPUT);
29
  pinMode(dROKFritzLEDINet, INPUT);
30
  pinMode(dROKP7, INPUT);
31
  pinMode(dRBell, INPUT);
32

33
  pinMode(PIN2Free, OUTPUT);
34
  digitalWrite(PIN2Free, LOW);
35

36
  pinMode(dWWLANOn, OUTPUT);
37
  digitalWrite(dWWLANOn, LOW);
38

39
  pinMode(dWNETIO, OUTPUT);
40
  digitalWrite(dWNETIO, LOW);
41
  
42
  pinMode(dWWLANOff, OUTPUT);
43
  digitalWrite(dWWLANOff, LOW);
44

45
  pinMode(dWRedial, OUTPUT);
46
  digitalWrite(dWRedial, LOW);
47

48
  pinMode(dWLiftHandset, OUTPUT); 
49
  digitalWrite(dWLiftHandset, LOW);
50
  
51
  SetWMA1000();
52
  
53
  portahistory = PINA;
54
  portbhistory = PINB;
55
  
56
}
57

58

59
void sleep() {
60

61
  GIMSK |= _BV(PCIE0);
62
  GIMSK |= _BV(PCIE1);
63

64
  PCMSK0 |= _BV(PCINT1);
65
  PCMSK0 |= _BV(PCINT6);
66
  PCMSK1 |= _BV(PCINT10);
67
  ADCSRA &= ~_BV(ADEN);
68
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
69

70
  sleep_enable();
71
  sei();
72
  sleep_cpu();
73

74
  cli();  
75

76
  PCMSK1 &= ~_BV(PCINT10);
77
  PCMSK0 &= ~_BV(PCINT6);
78
  PCMSK0 &= ~_BV(PCINT1);
79
  sleep_disable();
80
  ADCSRA |= _BV(ADEN);
81

82
}
83

84

85
ISR(PCINT0_vect) {
86
  
87
  uint8_t changedbits;
88

89
  changedbits = PINA ^ portahistory;
90
  portahistory = PINA;
91

92
  if(changedbits & (1 << PCINT1)){
93
    ISRTrigger=dRFritzLEDWLAN;
94
  }
95

96
  if(changedbits & (1 << PCINT6)){
97
    if (digitalRead(dROKFritzLEDINet)==HIGH){
98
      ISRTrigger=dROKFritzLEDINet;
99
    }
100
  }
101
  
102
}
103

104

105
ISR(PCINT1_vect) {
106

107
  uint8_t changedbits;
108
  
109
  changedbits = PINB ^ portbhistory;
110
  portbhistory = PINB;
111

112
  if(changedbits & (1 << PCINT10)){
113
    if (digitalRead(dRBell)==HIGH){
114
      ISRTrigger=dRBell;
115
    }
116
  }
117
  
118
}
119

120

121
void SetWMA1000(){
122
  if (digitalRead(dRFritzLEDWLAN)==HIGH) {
123
    digitalWrite(dWWLANOff, HIGH);
124
    delay(500);
125
    digitalWrite(dWWLANOff, LOW);
126
  }
127
  else {
128
    digitalWrite(dWWLANOn, HIGH);  
129
    delay(500);
130
    digitalWrite(dWWLANOn, LOW);
131
  }
132
}
133

134

135
void loop() {
136

137
  sleep();
138
  
139
  if (ISRTrigger==dRFritzLEDWLAN){
140
    unsigned long ticker=0;
141
    int state=digitalRead(dRFritzLEDWLAN);
142
    while (ticker < 50000){
143
      if (digitalRead(dRFritzLEDWLAN)!=state){
144
        state=1-state;
145
        ticker=0;
146
      }
147
      else{
148
        ticker++;
149
      }
150
    }
151
    SetWMA1000();
152
  }
153
  else if (ISRTrigger==dROKFritzLEDINet){  
154
    digitalWrite(dWNETIO, HIGH);
155
    delay(500);
156
    digitalWrite(dWNETIO, LOW);
157
  }        
158
  else if (ISRTrigger==dRBell){  
159
    digitalWrite(dWLiftHandset, HIGH);
160
    delay(250);
161
    digitalWrite(dWRedial, HIGH);
162
    delay(250); 
163
    digitalWrite(dWRedial, LOW);
164
    delay(8000+analogRead(0)/1.023*5);
165
    digitalWrite(dWLiftHandset, LOW);
166
  }
167
  
168
  ISRTrigger=0;
169
  
170
}


Vielleicht ist jemand so freundlich mir Anfänger bei der Fehlersuche zu 
helfen.

Danke

Matthias
Gast
Falls es hier um schnell aufeinander folgende Signale geht, könnte es 
sein, dass deine digitalRead() Aufrufe in den Interruptroutinen zu viel 
Zeit verplempern. Um das zu lösen, kannst du direkt aus dem PINx 
Register lesen.

Dann ist mir aufgefallen, dass du beiden ISR jeweils zweimal das PINx 
Register liest - in der Hoffnung, dass da auch zweimal der selbe Wert 
bei heraus kommt. Das ist aber nicht unbedingt der Fall, das Signal 
könnte sich zwischenzeitlich geändert haben. Lies nur einmal in eine 
zusätzliche Zwischen-Variable.

In der Loop willst du im Prinzip ständig schlafen - außer es kommt ein 
Signal rein. Richtig? Due musst hier beachten, dass das Aufwachen eine 
beträchtliche Zeit kostet. Ich hatte mich auch schonmal gewundert, warum 
mein µC zwar aufwachte, danach aber der Meinung war, dass das kein 
Signal sei. Er war einfach zu träge, bis er aufgewacht war, war das 
Signal schon wieder weg.
Gast
Danke Stefanus für die Antwort.

Die Signale sind Türklingel über Relais geschalten, Fritzbox WLAN LED 
und Fritzbox Internet LED - alles Signale im Sekundenbereich und länger 
als die Aufwachzeit.

Habe die Schaltung jetzt so umgebaut, dass die Eingänge auf INT1, INT5 
und INT6 liegen und nur ein ISR benötigt wird.

Hier zickt jetzt auch der andere Eingang, den ich im ISR mit digitalRead 
auf HIGH abfrage - um direkt aus dem PINx Register zu lesen, werde ich 
hoffentlich ein Beispiel finden.
Gast
Nein, hab nicht gewusst dass es beim Relais so was gibt - wie erwähnt 
Anfänger

Seit ich den ISR Code wie folgt
1
ISR(PCINT0_vect) {
2
  
3
  byte PinVal=PINA;
4

5
  IRQFritzLEDWLAN = PinVal & (1<<PCINT1);
6
  IRQFritzLEDWLAN = IRQFritzLEDWLAN >> PCINT1;
7

8
  IRQBell = PinVal & (1<<PCINT5);
9
  IRQBell = IRQBell >> PCINT5;
10

11
  IRQOKFritzLEDINet = PinVal & (1<<PCINT6);
12
  IRQOKFritzLEDINet = IRQOKFritzLEDINet >> PCINT6;
13
  
14
}

geändert habe, funktioniert es einwandfrei

Habe im Loop in der Zustandsabfrage trotzdem noch eine 50ms 
Prellsicherheit eingepflegt

Danke

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 7 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.