Hi,
I am struggeling with the accuracy of interrupt in Duemilanove 328. What I try to do is to get a quick and even response to an interrupt getting a HIGH to pin13.
Here is my issue: I am pushing a 5V signal into a interrupt 0 and want to get a immediate response. The acuracy shall be below +/-4 microseconds.
Below is the code I used.
I used the command "attachInterrupt(0, ignite, RISING);" command to put the LEDpin to high. I attached an oscilloscope screenshot of showing the outcome. The interrupt trigger is very much left. The next rising signal (response1) is the response to it I normally get- which would be fine. But for whatever reason there is sometimes a response (response2) which is 20 micros delayed- and only 20 micros..not more and not less. This photo contains both response signals because I used a long exposure time with my camera to get some kind of overlaying signals.
Here is my question. How can I avoid this irregular response?
#include <EEPROM.h>
#include <avr/pgmspace.h>
int maps[4][23] = {
{110, 100, 90, 80, 70, 60, 50, 40, 30, 20, 10, 100, 90, 80, 70, 60, 50, 40, 30, 20, 10, 0, 7500 }
, {310, 300, 290, 280, 270, 260, 250, 240, 230, 220, 210, 200, 190, 180, 170, 160, 150, 140, 130, 120, 110, 100, 7500}
, {410, 400, 390, 380, 370, 360, 350, 340, 330, 320, 310, 300, 290, 280, 270, 260, 250, 240, 230, 220, 210, 200, 7500}
, {510, 500, 490, 480, 470, 460, 450, 440, 430, 420, 410, 400, 390, 380, 370, 360, 350, 340, 330, 320, 310, 300, 7500}
};
int lowgreenrpm=500;
int lowyellowrpm=3000;
int lowredrpm=4000;
int dwell=2500;
//Shift register
#include <Shifter.h>
#define SER_Pin 5 //SER_IN
#define RCLK_Pin 4 //L_CLOCK
#define SRCLK_Pin 3 //CLOCK
#define NUM_REGISTERS 1 //how many registers are in the chain
Shifter shifter(SER_Pin, RCLK_Pin, SRCLK_Pin, NUM_REGISTERS);
//Shift register
//LCD
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
unsigned long refresh=0;
unsigned long refreshold=0;
unsigned long refreshtarget=500;
//LCD
#define FASTADC 1
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
//Analoge Eingänge
int MAPPin=A0; //Map Selektor
int baseZZPPotiPin=A1;
int EGTPin=A2;
int IATPin=A3;
int baseZZPPin = 6;
int LEDpin=13; //Input trigger auf Board LED zeigen
//Verschiedene Variablen
int baseZZPPinstat;
int baseZZPPinstatold;
int EEPROMval;
int EGTval=0;
int IATval=0;
int MAPval;
int z=1;
unsigned long delaycalc;
unsigned long mi;
unsigned long microshigh1;
unsigned long microshigh2;
float deltamicros;
int delayignitionmicros=0;
int LEDbaseign = 13;
int LEDtrigger=11;
int RPMsteps[] = { 500,1000,1500,2000,2500,3000,3500,4000,4500,5000,5500,6000,6500,7000,7500,8000,8500,9000,10000,10500,11000};
int RPM; //gemittelter Wert
int RPM1; //Erster Wert der Mittelung
int RPM2; //Zweiter Wert der Mittelung
float RPM3; //Dritter Wert der Mittelung
int ignlow;
int ignhigh;
int retardlow;
int retardhigh;
float zzp;
float delayzzp;
float baseZZP;
float baseZZPadjust;
void setup()
{
Serial.begin(115200);
#if FASTADC
sbi(ADCSRA,ADPS2) ;
cbi(ADCSRA,ADPS1) ;
cbi(ADCSRA,ADPS0) ;
#endif
pinMode(baseZZPPin, INPUT);
pinMode(LEDpin, OUTPUT);
attachInterrupt(0, ignite, RISING);
baseZZP=250;
baseZZPadjust=EEPROM.read(1); //Korrektur ZZP aus EEPROM
//LCD Displaygrösse definieren
lcd.begin(16, 2);
shifter.clear(); //set all pins on the shift register chain to LOW
shifter.write(); //send changes to the chain and display them
}
void loop(){
external(); //lcd1(); //LCD Display Funktion Aktivierung
}
void ignite()
{
mi=micros();
digitalWrite(LEDpin, HIGH);//für LED
microshigh2 = micros();
deltamicros= microshigh2-microshigh1;
digitalWrite(LEDpin, LOW);//für LED
zzpcalc(); //Starte Berechnung des ZZP sofort nach Zündung
}
void lcd1()
{
}
void zzpcalc(){
//MAPval=1;
//Errechnung der Drehzahl aus deltamicros und Mittelung der Drehzahl über die letzten 3 Werte
RPM1=RPM2;
RPM2=RPM3;
RPM3=((1/ deltamicros)*60000000.0); //Errechnung aktuellen der Drehzahl
RPM= (RPM1+RPM2+RPM3)/3; //Gemittelte Drehzahl zur weiteren Benutzung
if (RPM3<100) (RPM=500); //Falls bei der ersten Umdrehung noch keine Drehzahl errechnet werden kann oder 0 ist werden 500RPM angenommen
microshigh1= microshigh2; //Alten Wert in Buffer legen
// Feststellen welche Spalte der ZZP und DrehzahlMap ausgelesen wird
ignlow= (RPM/500)-1;
ignhigh=ignlow+1;
retardlow = maps[MAPval][ignlow]; //unterer ZZP Datenpunkt der Map zur interpolation
retardhigh = maps[MAPval][ignhigh]; //oberer ZZP Datenpunkt der Map zur interpolation
if (RPM<500) {
retardlow=100;
retardhigh=100;
}
zzp=((((float)retardlow +((float)RPM-RPMsteps[ignlow])*(((float)retardhigh-(float)retardlow)/((float)RPMsteps[ignhigh]-(float)RPMsteps[ignlow])))));//Lineare Interpolation//
delayzzp= (deltamicros/360.00)*((baseZZP-(float)baseZZPadjust-(float)zzp)/10.0); // Erechnung des zeitlichen Verzögerung der Zündauslösung inklusive des Basiszündzeitpunkts
if (RPM>(maps[MAPval][22])) (delayzzp=100000); //Drehzahlbegrenzer: Zündung wird in einen Bereich verschoben, der später als der nächste Trigger liegt
if (baseZZPPinstat==HIGH){
delayzzp= (deltamicros/360.00)*((baseZZP-(float)baseZZPadjust)/10); // Erechnung des zeitlichen Verzögerung der Zündauslösung inklusive des Basiszündzeitpunkts
}
}
void external(){
if (z==1) //einlesen EGT
{
EGTval= analogRead(EGTPin);
EGTval= EGTval/20;
}
if (z==2) //Analogread Map (mit Zuweisung der Map)
{
MAPval= analogRead(MAPPin);
if ((MAPval>0) && (MAPval<256)) MAPval=0;
if ((MAPval>257) && (MAPval<512)) MAPval=1;
if ((MAPval>513) && (MAPval<767)) MAPval=2;
if ((MAPval>768) && (MAPval<1024)) MAPval=3;
}
if (z==3) //lese IAT und errechne Temperatur
{
IATval= analogRead(IATPin); //WERT= 850
IATval= 731;
if (IATval>=466)(IATval=-0.1124*IATval+102.3);
if (IATval<466)(IATval=0.006*(IATval*IATval)-0.5229*IATval+169.35);
}
//***************************************************************
//Schaltanzeige
//***************************************************************
if (z==4) //DigitalRead für Displayumschaltung
{
if (RPM > lowgreenrpm){
if (RPM < lowyellowrpm)
{
shifter.setPin(0, LOW); //set pin 1 in the chain(second pin) HIGH
shifter.setPin(1, HIGH); //set pin 1 in the chain(second pin) HIGH
shifter.setPin(2, HIGH); //set pin 1 in the chain(second pin) HIGH
shifter.write(); //send changes to the chain and display them
}
if (RPM > lowyellowrpm)
{
shifter.setPin(0, LOW); //set pin 1 in the chain(second pin) HIGH
shifter.setPin(1, LOW); //set pin 1 in the chain(second pin) HIGH
shifter.setPin(2, HIGH); //set pin 1 in the chain(second pin) HIGH
shifter.write(); //send changes to the chain and display them
}
if (RPM > lowredrpm)
{
shifter.setPin(0, LOW); //set pin 1 in the chain(second pin) HIGH
shifter.setPin(1, LOW); //set pin 1 in the chain(second pin) HIGH
shifter.setPin(2, LOW); //set pin 1 in the chain(second pin) HIGH
shifter.write(); //send changes to the chain and display them
}
}
else
{
shifter.setPin(0, HIGH); //set pin 1 in the chain(second pin) HIGH
shifter.setPin(1, HIGH); //set pin 1 in the chain(second pin) HIGH
shifter.setPin(2, HIGH); //set pin 1 in the chain(second pin) HIGH
shifter.write(); //send changes to the chain and display them
}
}
if (z==5) //Basiszündzeitpunkt Funktion
{
baseZZPPinstat= digitalRead(baseZZPPin); //Auslesen des Schalters zum einstellen des BasisZZP
if (baseZZPPinstat==HIGH) basezzp(); //basezzp einstellen
if (baseZZPPinstat != baseZZPPinstatold)
{
EEPROM.write(1, (baseZZPadjust)); //Schreibt Wert in den nichtflüchtigen Speicher wenn Schalter wieder umgelegt wird
baseZZPPinstatold=LOW;
baseZZPadjust=EEPROM.read(1);
}
baseZZPPinstatold= baseZZPPinstat;
}
// Zähler um die obigen Funktionen abwechselnd auszuführen
if (z<7) z=z+1;
if (z>6) z=1;
microshigh2 = microshigh1; //wichtig um die ZZP zu berechnen
}
// Einstellung der Zündung ohne Schwungscheibe abzunehmen (Basezzp)
void basezzp(){
baseZZPadjust= analogRead(baseZZPPotiPin); //angenommen wird ein Verstellbereich von 0 bis 10° KW
baseZZPadjust= map(baseZZPadjust, 0, 1024, 0, 100);
}