Interrupt Probleme

Hallo zusammen,
ich habe meine Probleme mit den Interrupts noch immer nicht gelöst. Irgendwie mache ich was grundsätzliches falsch. Ich habe mir ein Beispiel Sketch aus dem Netz genommen und auf meinen 8Mhz 328 on breadboard geladen. daran sind 4 Taster die einfach auf Masse schalten. Lasse ich den Sketch laufen, dann zählt er nicht zuverlässig die Tastimpulse. Manchmal reagiert er nicht, dann zweimal, manchmal auf rising statt auf falling, manchmal auch mehrfach hintereinander, dann wieder nicht. Auch Pull Up Widerstände haben daran nichts geändert. Ich bin ratlos… Könnte einer von euch mal den Sketch testen? Vielleicht liegts ja an meiner hardware… somehow…

Hier der Sketch:
// Define values for the interrupt counter:
volatile int counter1 = 0; // Counter incremented by pin change interrupt
volatile int counter2 = 0; // Counter incremented by pin change interrupt
volatile int counter3 = 0; // Counter incremented by pin change interrupt
volatile int counter4 = 0; // Counter incremented by pin change interrupt

volatile int bounceTime = 20; // Switch bouncing time in milliseconds

volatile unsigned long IRQ1PrevTime; // Last time in milliseconds IRQ1 arrived
volatile unsigned long IRQ2PrevTime; // Last time in milliseconds IRQ2 arrived
volatile unsigned long IRQ3PrevTime; // Last time in milliseconds IRQ3 arrived
volatile unsigned long IRQ4PrevTime; // Last time in milliseconds IRQ4 arrived

volatile int IRQ1PrevVal = 0; // Contact level last IRQ1
volatile int IRQ2PrevVal = 0; // Contact level last IRQ2
volatile int IRQ3PrevVal = 0; // Contact level last IRQ3
volatile int IRQ4PrevVal = 0; // Contact level last IRQ4

volatile int irqFlag = 0; // 1=display counters after IRQ; 0=do nothing

// Setup and Main:
void setup(){
Serial.begin(9600); // Initialize serial interface with 9600 Baud
Serial.write(“Waiting for an interrupt…\n”);

// INT1 → Make Arduino Pin 11 (PCINT3/Port B.3) an input and set pull up resistor:
pinMode(11, INPUT_PULLUP);

// INT2 → Make Arduino Pin 12 (PCINT4/Port B.4) an input and set pull up resistor:
pinMode(12, INPUT_PULLUP);

// INT3 → Make Arduino Analog input 1 (PCINT9/Port C.1) an input and set pull up resistor:
pinMode(15, INPUT_PULLUP);

// INT4 → Make Arduino Analog input 2 (PCINT10/Port C.2) an input and set pull up resistor:
pinMode(16, INPUT_PULLUP);

// This is ATMEGA368 specific, see page 75 of long datasheet
// PCICR: Pin Change Interrupt Control Register - enables interrupt vectors
// Bit 2 = enable PC vector 2 (PCINT23…16)
// Bit 1 = enable PC vector 1 (PCINT14…8)
// Bit 0 = enable PC vector 0 (PCINT7…0)
PCICR |= (1 << PCIE0); // Set port bit in CICR for INT1 and INT2
PCICR |= (1 << PCIE1); // Set port bit in CICR for INT3 and INT4

// Pin change mask registers decide which pins are enabled as triggers:
PCMSK0 |= (1<<PCINT3); // Set pin interrupt for INT1
PCMSK0 |= (1<<PCINT4); // Set pin interrupt for INT2
PCMSK1 |= (1<<PCINT9); // Set pin interrupt for INT3
PCMSK1 |= (1<<PCINT10); // Set pin interrupt for INT4

IRQ1PrevTime=millis(); // Hold actual time
IRQ2PrevTime=millis(); // Hold actual time
IRQ3PrevTime=millis(); // Hold actual time
IRQ4PrevTime=millis(); // Hold actual time
interrupts(); // Enable interrupts
}

void loop()
{
// Place your main loop commands here (e.g. output to LCD)
if (irqFlag==1) // Flag was set by IRQ routine
{
noInterrupts();

Serial.write("IRQ rising edge, Counter1 = “);
Serial.print(counter1);
Serial.write(”, Counter2 = “);
Serial.print(counter2);
Serial.write(”, Counter3 = “);
Serial.print(counter3);
Serial.write(”, Counter4 = ");
Serial.println(counter4);
irqFlag=0; // Reset IRQ flag
interrupts();
}
}

//-----------------------------------------------------------------------------
// Subs and Functions:

ISR(PCINT0_vect)
{

// You have to write your own interrupt handler. Don’t change the name!
// This code will be called anytime when PCINT23 switches high to low,
// or low to high. This is for INT1 and INT2 (both Port B)
byte PVal; // Port value (8 Bits)
byte IRQ1ActVal; // Actual IRQ1 value
byte IRQ2ActVal; // Actual IRQ2 value
long unsigned IRQ1ActTime;
long unsigned IRQ2ActTime;

PVal = PINB; // Read port D (8 bit)
IRQ1ActVal = PVal & (1<<PCINT3); // Mask out all except IRQ1
IRQ1ActVal = IRQ1ActVal >> PCINT3; // shift to right for bit0 position
IRQ2ActVal = PVal & (1<<PCINT4); // Mask out all except IRQ2
IRQ2ActVal = IRQ2ActVal >> PCINT4; // shift to right for bit0 position

IRQ1ActTime=millis(); // Read actual millis time
if(IRQ1ActTime - IRQ1PrevTime > bounceTime) // No bouncing anymore:
{
// No contact bouncing anymore:
if(IRQ1PrevVal==0 && IRQ1ActVal==1) // Transition 0–>1
{
// Place your command for rising signal here…

IRQ1PrevVal=IRQ1ActVal;

}
if(IRQ1PrevVal==1 && IRQ1ActVal==0) // Transition 1–>0
{
// Place your command for falling signal here…
counter1++;
if(counter1>255) counter1 = 0;
IRQ1PrevTime=IRQ1ActTime;
IRQ1PrevVal=IRQ1ActVal;
irqFlag=1;
}
}

IRQ2ActTime=millis(); // Read actual millis time
if(IRQ2ActTime - IRQ2PrevTime > bounceTime) // No bouncing anymore:
{
// No contact bouncing anymore:
if(IRQ2PrevVal==0 && IRQ2ActVal==1) // Transition 0–>1
{
// Place your command for rising signal here…
IRQ2PrevVal=IRQ2ActVal;

}
if(IRQ2PrevVal==1 && IRQ2ActVal==0) // Transition 1–>0
{
// Place your command for falling signal here…
counter2++;
if(counter2>255) counter2 = 0;
IRQ2PrevTime=IRQ2ActTime;
IRQ2PrevVal=IRQ2ActVal;
irqFlag=1;
}
}
}

ISR(PCINT1_vect)
{
// You have to write your own interrupt handler. Don’t change the name!
// This code will be called anytime when PCINT23 switches high to low,
// or low to high. This is for INT3 and INT4 (both Port C)
byte PVal; // Port value (8 Bits)
byte IRQ3ActVal; // Actual IRQ3 value
byte IRQ4ActVal; // Actual IRQ4 value
long unsigned IRQ3ActTime;
long unsigned IRQ4ActTime;

PVal = PINC; // Read port C (8 bit)
IRQ3ActVal = PVal & (1<<PCINT9); // Mask out all except IRQ3
IRQ3ActVal = IRQ3ActVal >> PCINT9; // shift to right for bit0 position
IRQ4ActVal = PVal & (1<<PCINT10); // Mask out all except IRQ4
IRQ4ActVal = IRQ4ActVal >> PCINT10; // shift to right for bit0 position

IRQ3ActTime=millis(); // Read actual millis time
if(IRQ3ActTime - IRQ3PrevTime > bounceTime) // No bouncing anymore:
{
// No contact bouncing anymore:
if(IRQ3PrevVal==0 && IRQ3ActVal==1) // Transition 0–>1
{
// Place your command for rising signal here…

IRQ3PrevVal=IRQ3ActVal;

}
if(IRQ3PrevVal==1 && IRQ3ActVal==0) // Transition 1–>0
{
counter3++;
if(counter3>255) counter3 = 0;
IRQ3PrevTime=IRQ3ActTime;
IRQ3PrevVal=IRQ3ActVal;
irqFlag=1;

// Place your command for falling signal here…
}
}

IRQ4ActTime=millis(); // Read actual millis time
if(IRQ4ActTime - IRQ4PrevTime > bounceTime) // No bouncing anymore:
{
// No contact bouncing anymore:
if(IRQ4PrevVal==0 && IRQ4ActVal==1) // Transition 0–>1
{
// Place your command for rising signal here…
IRQ4PrevVal=IRQ4ActVal;
}
if(IRQ4PrevVal==1 && IRQ4ActVal==0) // Transition 1–>0
{
counter4++;
if(counter4>255) counter4 = 0;
IRQ4PrevTime=IRQ4ActTime;
IRQ4PrevVal=IRQ4ActVal;
irqFlag=1;
// Place your command for falling signal here…

}
}
}

Ich würde mal einen Minimalcode nehmen als grundsätzlichen Test und nicht diesen Monstercode.

Ich würde erstmal auf der Hardware Seite entprellen. Verträgt sich die Entprellung per Software überhaupt mit den Interrupts?

Gruß

Ein Interrupt tritt eben mehrfach auf, wenn der Schalter prellt. Wenn man per Software entprellt, geht das einfacher ohne Interrupt.

Dein Code kommt mir irgendwie unsinnig vor. Wenn der Schalter kürzer prellt als die vorgegbene Zeit (bounceTime), tritt kein weiterer Interrupt mehr auf - es passiert also garichts bis irgendwas wieder einen Interrupt auslöst.

Und bitte Code in Code Tags </> posten.

DrDiettrich: Dein Code kommt mir irgendwie unsinnig vor. Wenn der Schalter kürzer prellt als die vorgegbene Zeit (bounceTime), tritt kein weiterer Interrupt mehr auf - es passiert also garichts bis irgendwas wieder einen Interrupt auslöst.

Genau das meinte ich...