Drehzahl mit Timer1 keine ISR(TIMER1_COMPA_vect) Reaktion

Hallo,
bin absoluter Neuling und hab mich ab Dezember erstmals mit der Materie (Elektronik und C++) befasst.
Zum Ansteuern von Injektoren und berechnen der Signalzeit benötige ich die aktuelle Drehzahl.
Hab von Timer Interrupt :: Meine Arduino-Projekte
Inspirationen geholt.
Allerdings wird der Timer Interrupt scheinbar nicht ausgelöst.
Nachfolgend der Code.
Der Code ist insgesamt noch unvollständig,
meine Frage bezieht sich lediglich auf den Timer zum Ermitteln der Drehzahl U/min.
Ich verwende einen Nano.
Ich würde mich über Tips sehr freuen.

#define hauptschalter_PIN A2 // Pin Nummer des Lenkerschalters zum EIN und Ausschalten der Einspritzung
#define injektor2_schalter A3 // Pin Nummer des Lenkerschalters zum EIN und Ausschalten des zweiten Injektors
#define injektor3_schalter A4 // Pin Nummer des Lenkerschalters zum EIN und Ausschalten des zweiten Injektors
#define injektor_pin_1 7    //PIN Nummer Injektorausgang 1
#define injektor_pin_2 8    //PIN Nummer Injektorausgang 2
#define injektor_pin_3 9    //PIN Nummer Injektorausgang 3
#define pumpe_pin 3         //PIN Nummer Pumpe Ausgang
#define pickup_signal_2 2   // PIN Nummer PickupSignal2 Eingang (2.Pickup am Ansaugbeginn)PIN 2+3 sind die PINs an welchen die "interrupt"-Funktion funktioniert
// Die Potiometer Drehzahl und TPS dienen dazu die errechnete Einspritzzeit aus (drehzahl_einspritzwert_prozent [] )und (tps_einspritzwert_prozent [] )zu beeinflussen.
// Die Potis sind während der Fahrt zu bedienen um die Grundeinstellung zu ermitteln. Die Werte der beiden Potis werden auf dem LCD Display angezeigt.
#define poti_drehzahl_parameter_pin A0    //PIN Nummer Analog, Potentiometer,Poti um die Parameter aus dem errechneten ms Einpritzwert aus (drehzahl_einspritzwert_prozent [] )zu verändern
#define poti_tps_parameter_pin A1    //PIN Nummer Potentiometer,Poti um die Parameter aus dem errechneten ms Einpritzwert aus (tps_einspritzwert_prozent [] )zu verändern
#define tps_pin A5    //PIN Nummer Potentiometer,Poti um die Parameter aus dem errechneten ms Einpritzwert aus (tps_einspritzwert_prozent [] )zu verändern
// #define injektionszeit_max 2300 // maximale Einpritzdauer in Microsekunden bei 13000U/min(Entspricht einer Überschneidung der Signale vom Pickup pro Zylinder bei 13000 U/Min)


volatile unsigned int drehzahl_pumpe_an; //Variable in welcher die Drehzahl angegeben wird, ab welcher die Pumpe angeschaltet ist
volatile unsigned int pumpe_an; // Variable 0 oder 1, welche für die Anweisung verwendet wird. Pumpe an = 1 . Berechnet aus (drehzahl_aktuell > drehzahl_pumpe_an)
volatile unsigned long systemzeit;  // Variable Speicher für Systemzeit Microsekunden.
//Formel zur Berechnung der Einspritzdauer in microsekunden ("drehzahl_einspritzwert []" multipliziert mal "tps_einpsritzfaktor []")
volatile unsigned int drehzahl_schaltpunkte [12] = {50,100,200,300,400,500,600,700,800,5000,6000,13000}; // Array mit 12 Werten zur Angabe der Drehzahlen,TEST
//volatile unsigned int drehzahl_schaltpunkte [12] = {6000,7000,7500,8000,8500,9000,9500,10000,10500,11000,11500,13000}; // Array mit 12 Werten zur Angabe der Drehzahlen, welche als Schaltpunkte verwendet werden, um die Einspritzdauer zu errechnen 
volatile unsigned int drehzahl_einspritzwert [12] = {0,350,330,310,295,280,265,250,240,230,214,214}; // Array mit 12 Werten zur Angabe der (Einspritzdauer in Microsekunden geteilt durch 10) in Abhängigkeit von der Drehzahl aus (drehzahl_schaltpunkte [])
volatile unsigned int drehzahl_einspritzwert_tmp;
volatile unsigned long drehzahl_aktuell; //aktuelle Drehzahl des Motors
volatile unsigned int pickupsignalzaehler; //summe der hochgezählten Pickupsignale während der definierten Zeitspanne zur berechnung der aktuellen Drehzahl
// Potiometer Werte TPS :::::::::: noch nicht ganz sicher, ob ich Prozentwerte oder digitalwerte nehme
volatile unsigned int tps_auslesung;
volatile unsigned int tps_stellung;
volatile unsigned int tps_wert_tmp;
volatile unsigned int tps_schaltpunkte [11] = {10,15,20,30,40,50,60,70,80,90,100}; // Array mit 11 Werten zur Angabe der TPS Prozentwerte TEST
//volatile unsigned int tps_schaltpunkte [11] = {0,10,20,30,40,50,60,70,80,90,100}; // Array mit 11 Werten zur Angabe der TPS Prozentwerte, welche als Schaltpunkte verwendet werden, um die Einspritzdauer zu errechnen 
volatile unsigned int tps_einpsritzfaktor [11] = {1,1,2,3,4,5,6,7,9,10}; // Array mit 11 Werten des Multiplikationsfaktors in Abhängigkeit von TPS Potiometerwerte aus (tps_schaltpunkte [])
//Die Einpritzzeit in Microsekunden errechnet sich aus tps_einpsritzfaktor MAL drehzahl_einspritzwert


volatile unsigned long einspritzzeit_micros; // errechnete Einspritzzeit in Microsekunden
volatile unsigned long anschaltszeit_einspritzung_micros; // Zeitstempel zu Beginn des Einspritzzeitpunktes in Microsekunden
volatile unsigned long ausschaltzeit_einspritzung_micros; // Zeitstempel zu Beginn des Einspritzzeitpunktes PLUS berechnete Einpritzzeit in Microsekunden (int einspritzzeit_micros;)GLEICH Endwert micros zum Stop des Injektorsignals
volatile unsigned int injektor_status; //Anweisung ob Injektor an sein soll oder aus , wenn Injektor AN (int injektor_pin = HIGH;)Wert=1,  wenn Injektor AUS (int injektor_pin = LOW;)Wert=0
volatile unsigned int hauptschalter_status; // Lenkerschalter AN/AUS, Hauptschalter für das Ein- und Ausschalten der Einspritzung , Ein=HIGH - aus=LOW
volatile unsigned int injektor2_schalter_status; // Lenkerschalter AN/AUS für die Verwendung des zweiten Injektors, Ein=HIGH - aus=LOW
volatile unsigned int injektor3_schalter_status; // Lenkerschalter AN/AUS für die Verwendung des zweiten Injektors, Ein=HIGH - aus=LOW
//volatile unsigned int pickupsignal; // 
volatile unsigned int index_tps; //=Ergenis, ist der Indexwert bzw. die Position des breakepoints im array-Index des tps_schaltpunkte breakpoints ermitteln um mit diesem den tps_einpsritzfaktor aus dem array zu finden
volatile unsigned int index_drehzahl; //=Ergenis, ist der Indexwert bzw. die Position des breakepoints im array Index des Drehzahlbreakpoints ermitteln um mit diesem den drehzahl_einspritzwert aus dem array zu finden
void setup() {
  Serial.begin(9600); // serielle Schnittstelle konfigurieren mit 9600 Baud
  pinMode(injektor_pin_1, OUTPUT);  // Definition, dass das injektor_pin_1 ein Ausgang ist.
  pinMode(injektor_pin_2, OUTPUT);  // Definition, dass das injektor_pin_2 ein Ausgang ist.
  pinMode(injektor_pin_3, OUTPUT);  // Definition, dass das injektor_pin_3 ein Ausgang ist.
  pinMode(pumpe_pin, OUTPUT);  // Definition, dass das pumpe_pin ein Ausgang ist.
  pinMode(tps_pin, INPUT);  // Definition, dass potiometer_drehzahl_parameter_pin ein Eingang ist.
  pinMode(poti_drehzahl_parameter_pin, INPUT);  // Definition, dass potiometer_drehzahl_parameter_pin ein Eingang ist.
  pinMode(poti_tps_parameter_pin, INPUT);  // Definition, dass poti_tps_parameter_pin ein Eingang ist.
  pinMode(injektor2_schalter, INPUT);  // Definition, dass injektor2_schalter ein Eingang ist.
  pinMode(injektor3_schalter, INPUT);  // Definition, dass injektor2_schalter ein Eingang ist.
  pinMode(pickup_signal_2,INPUT_PULLUP);  // Definition, dass pickup_signal2 ein Eingang ist.
  //attachInterrupt(digitalPinToInterrupt(pickup_signal_2), pickupsignal, RISING); // Signal vom Pickup erkennen 
  attachInterrupt(digitalPinToInterrupt(pickup_signal_2), pickupsignal, FALLING); // Signal vom Pickup erkennen  - Änderung 0.2.0 zu 0.2.1 Bleibt vorerst bei RISING und NICHT FALLING
  //injektor_status = 0;
  //pickupsignalzaehler = 0;
  drehzahl_pumpe_an = 100; // Angabe der Voreinstellung der Drehzahl, ab welcher die Pumpe an ist TEST
  //drehzahl_pumpe_an = 6000; // Angabe der Voreinstellung der Drehzahl, ab welcher die Pumpe an ist
  //START TIMER SETUP -------------------------------------------------------------------------------------------------START TIMER SETUP
//TIMER SETUP for highly preceise timed measurements TIMER SETUP für hochpräzise zeitgesteuerte Messungen
  cli();//stop all interrupts
  // turn on CTC mode
  TCCR1A = 0;// set entire TCCR1A register to 0 das gesamte TCCR1A-Register auf 0 setzen
  TCCR1B = 0;// same for TCCR1B
  TCCR1B |= (1 << WGM12); //Setze CTC-Mode (Waveform Generation Mode)
  // Set prescaler
  TCCR1B |= (1 << CS11); //Setze CS11 (Clock Select) für prescaler 8
// Verschiedene settings
  //TCCR1B |= (1 << CS12) | (1 << CS10);  //Setze CS10 und CS12 (Clock Select) für prescaler 1024
  //TCCR1B |= (1 << CS12);  //Setze CS12 (Clock Select) für prescaler 256
  TCCR1B |= (1 << CS11) | (1 << CS10);  //Setze CS11 und CS10 (Clock Select) für prescaler 64 // Prescaler 64 hier verwendet
  //TCCR1B |= (1 << CS11);  //Setze CS11 (Clock Select) für prescaler 8

  //initialize counter value to 0;
  TCNT1  = 0;
  
  // Timerzählung für 20Hz-Schritte einstellen =50Millisekunden. Der Wert des Registers OCR1A ist abhängig von der gewünschten Interruptfrequenz und dem gewählten Vorteiler. Es gilt die folgende Formel:
  // (CPU Frequenz (Hier =16000000)/(Prescaler64*gewünschte Interruptfrequenz20HZ))-1
  OCR1A = 12499; // Wert für 20Hz und prescaler 64
  
  // enable timer compare interrupt Timer-Vergleichsinterrupt aktivieren
  TIMSK1 |= (1 << OCIE1A); //Bit Output Compare A Match Interrupt Enable setzen

 
  sei();//allow interrupts //Setze globales Interrupt-Enable-Bit
  //END TIMER SETUP--------------------------------------------------------------------------------------------------END TIMER SETUP
} // setup Ende





 
  // Funktion welche ausgeführt werden soll wenn das Pickupsignal den attachInterrupt auslöst . Anfang
// Wenn injektor aus ist, wird der injektor_status auf 1 gesetzt und die Systemzeit in der Variable anschaltszeit_einspritzung_micros gespeichert
void pickupsignal() {  
  pickupsignalzaehler++; // Erhöht die Variable "pickupsignalzaehler" pro Pickupsignal jeweils jeweils um 1
  if (injektor_status == 0) {
       injektor_status = 1; // Injektorstatus auf 1 setzen Der Injektorstatus ist die Anweisung, dass der Injektor an oder ausgeschaltet sein soll
       anschaltszeit_einspritzung_micros = micros(); // Zeit zum Beginn der Einspritzung
       ausschaltzeit_einspritzung_micros = anschaltszeit_einspritzung_micros + einspritzzeit_micros;
  }
 }
  // Funktion welche ausgeführt werden soll wenn das Pickupsignal den attachInterrupt auslöst . Ende


void loop() {
  
// Ermitteln, ob die Pumpe angeschaltet werden soll oder nicht und setzten der Variable pumpe_an ANFANG
  if (drehzahl_aktuell >= drehzahl_pumpe_an) {
    pumpe_an = 1;
  }
  else {
    pumpe_an = 0;
  }
// Ermitteln, ob die Pumpe angeschaltet werden soll oder nicht und setzten der Variable pumpe_an ENDE

// Index des Drehzahlbreakpoints ermitteln um mit diesem den drehzahl_einspritzwert aus dem array zu finden ANFANG
//int index_drehzahl; //=Ergenis, ist der Indexwert bzw. die Position des breakepoints im array
for (int i=0; i<12; i++) {   // i<12; Auszulesender array hat 12 Einträge/Länge
   if (drehzahl_aktuell <= drehzahl_schaltpunkte[i]) {
     index_drehzahl = i-1;
     break;
   }
}
// Index des Drehzahlbreakpoints ermitteln um mit diesem den drehzahl_einspritzwert aus dem array zu finden ENDE

// Einspritzwert aus array: drehzahl_einspritzwert ermitteln um mit diesem den drehzahl_einspritzwert aus dem array zu finden ANFANG
drehzahl_einspritzwert_tmp = drehzahl_einspritzwert [index_drehzahl];
// Einspritzwert aus array: drehzahl_einspritzwert ermitteln um mit diesem den drehzahl_einspritzwert aus dem array zu finden ENDE
  
// Index des tps_schaltpunkte breakpoints ermitteln um mit diesem den tps_einpsritzfaktor aus dem array zu finden ANFANG

     //Umwandeln des TPS Signals in 0 bis 100 ANFANG
tps_auslesung = analogRead(tps_pin); //TPS Eingang Pin auslesen
tps_stellung = map(tps_auslesung, 0, 1023, 0, 100); // Auslesewert umwandeln in 0 bis 100

    //Umwandeln des TPS Signals in 0 bis 100 ENDE


//int index_tps; //=Ergenis, ist der Indexwert bzw. die Position des breakepoints im array
for (int i=0; i<11; i++) {   // i<11; Auszulesender array hat 11 Einträge/Länge
   if (tps_stellung <= tps_schaltpunkte[i]) {
     index_tps = i-1;
     break;
   }
}
// Index des tps_schaltpunkte breakpoints ermitteln um mit diesem den tps_einpsritzfaktor aus dem array zu finden ENDE

tps_wert_tmp = tps_einpsritzfaktor [index_tps]; // TPS Multiplikator ermitteln zum Errechnen der Einspritzzeit

einspritzzeit_micros = tps_wert_tmp * drehzahl_einspritzwert_tmp; //Einpritzzeit DAUER errechnen


// Funktion welche ausgeführt werden soll wenn der Lenkerschalterfür den Injektor2 auf EIN geschaltet ist und somit der 2. Injektor zusätzlich verwendet werden soll
  if (digitalRead(injektor2_schalter)== HIGH) {
    // injektor2_schalter_status auf 1 setzen
     injektor2_schalter_status = 1;
  }

// Funktion welche ausgeführt werden soll wenn der Lenkerschalterfür den Injektor3 auf EIN geschaltet ist und somit der 3. Injektor zusätzlich verwendet werden soll
  if (digitalRead(injektor3_schalter)== HIGH) {
    // injektor3_schalter_status auf 1 setzen
     injektor3_schalter_status = 1;
  }

// Funktion welche ausgeführt werden soll wenn der Lenkerschalter/Hauptschalter auf EIN geschaltet ist und somit die Einspritzung eingeschaltet ist
 // if (digitalRead(hauptschalter_PIN)== HIGH) {  // TEST IMMER AN
    // hauptschalter_status auf 1 setzen
     hauptschalter_status = 1;
 // }  // TEST IMMER AN
// Pumpe einschalten oder ausschalten ANFANG
if (hauptschalter_status == 1)
  {
  if (pumpe_an == 1)
  {
digitalWrite(pumpe_pin, HIGH); // Pumpe Ein
  } 
  else
  digitalWrite(pumpe_pin, LOW); // Pumpe Aus
  }
// Pumpe einschalten oder ausschalten ENDE  
//
 //Ausführung des Einpritzsignal 
  //injektor_pin = LOW; //Injektor Aus
  if (hauptschalter_status == 1)
Serial.print("hauptschalter_status: ");
Serial.println(hauptschalter_status);
  {
   if (injektor_status == 1)
Serial.print("injektor_status: ");
Serial.println(injektor_status);
   {
 //Ausführung des Einpritzsignal wenn Hauptschalter EIN und Injektorstatus =1 Anfang
 // anschaltszeit_einspritzung_micros = micros(); //Zeit speichern zu Beginn der Einpritzung
 //ausschaltzeit_einspritzung_micros = einspritzzeit_micros + anschaltszeit_einspritzung_micros;
Serial.print("micros zum zeitpunkt Ausführung code: ");
Serial.println(micros());
if (micros()< ausschaltzeit_einspritzung_micros )
{
digitalWrite(injektor_pin_1, HIGH); // Injektor 1 Ein
Serial.print("Injektor1 Ein: ");

if (injektor2_schalter_status == 1){
   digitalWrite(injektor_pin_2, HIGH); // Injektor 2 Ein
   }
 if (injektor3_schalter_status == 1){
   digitalWrite(injektor_pin_3, HIGH); // Injektor 3 Ein
  }
}
 }
if (micros()> ausschaltzeit_einspritzung_micros )
{
digitalWrite(injektor_pin_1, LOW); // Injektor 1 Aus
digitalWrite(injektor_pin_2, LOW); // Injektor 2 Aus
digitalWrite(injektor_pin_3, LOW); // Injektor 3 Aus
injektor_status = 0; // Injektorstatus auf 0 setzen Der Injektorstatus ist die Anweisung, dass der Injektor angeschaltet sein soll
} //Ausführung des Einpritzsignal wenn Hauptschalter EIN und Injektorstatus =1 ENDE
}
  } // Ende loop

    //Funktion welche Ausgeführt wird, wenn das Timer interrupt ausgelöst wird-----------------------------Anfang
ISR(TIMER1_COMPA_vect) {      //Interrupt at frequency of 20 Hz =50Millisekunden
//Drehzahlberechnung anhand der Variablen pickupsignalzaehler (Summe der Pickupsignale während der Zeitdauer von Timer interrupt zu Timer interrupt (HIER =50Millisekunden)
// Anzahl der Signale pro Umdrehung =2 , 50 Millisekunden pro Messung wie im Timersetup festgelegt, 60000 für Millisekuden in Minuten (pickupsignalzaehler / 50 / 2)*60000 
Serial.print("pickupsignalzaehler: "); //zum Testen
Serial.println(pickupsignalzaehler);  //zum Testen
drehzahl_aktuell= (((pickupsignalzaehler / 50)/2)*60000);
pickupsignalzaehler = 0; // PickupZähler für neue Messung zurücksetzen
}

//Funktion welche Ausgeführt wird, wenn das Timer interrupt ausgelöst wird-----------------------------Ende

Hi,

Die Serielle Schnittstelle würde ich auf alle Fälle nicht aus der ISR heraus aufrufen.

kannst du die ISR und die Ansteuerung dieser einen Routine in ein eigenes Sketch packen. Wenn diese Testroutine nicht läuft dann Poste sie und wir schaun mal

Hi,
danke für die Antwort.
Hab das mal gemacht.
kein Ergebnis.
liebe Grüße
Peter

#define hauptschalter_PIN A2 // Pin Nummer des Lenkerschalters zum EIN und Ausschalten der Einspritzung
#define pickup_signal_2 2   // PIN Nummer PickupSignal2 Eingang (2.Pickup am Ansaugbeginn)PIN 2+3 sind die PINs an welchen die "interrupt"-Funktion funktioniert

volatile unsigned long drehzahl_aktuell; //aktuelle Drehzahl des Motors
volatile unsigned int pickupsignalzaehler; //summe der hochgezählten Pickupsignale während der definierten Zeitspanne zur berechnung der aktuellen Drehzahl
volatile unsigned int injektor_status; //Anweisung ob Injektor an sein soll oder aus , wenn Injektor AN (int injektor_pin = HIGH;)Wert=1,  wenn Injektor AUS (int injektor_pin = LOW;)Wert=0
volatile unsigned long einspritzzeit_micros; // errechnete Einspritzzeit in Microsekunden
volatile unsigned long anschaltszeit_einspritzung_micros; // Zeitstempel zu Beginn des Einspritzzeitpunktes in Microsekunden
volatile unsigned long ausschaltzeit_einspritzung_micros; // Zeitstempel zu Beginn des Einspritzzeitpunktes PLUS berechnete Einpritzzeit in Microsekunden (int einspritzzeit_micros;)GLEICH Endwert micros zum Stop des Injektorsignals
volatile unsigned long systemzeit;  // Variable Speicher für Systemzeit Microsekunden.
volatile unsigned int hauptschalter_status; // Lenkerschalter AN/AUS, Hauptschalter für das Ein- und Ausschalten der Einspritzung , Ein=HIGH - aus=LOW

void setup() {
  pinMode(pickup_signal_2,INPUT_PULLUP);  // Definition, dass pickup_signal2 ein Eingang ist.
  //attachInterrupt(digitalPinToInterrupt(pickup_signal_2), pickupsignal, RISING); // Signal vom Pickup erkennen 
  attachInterrupt(digitalPinToInterrupt(pickup_signal_2), pickupsignal, FALLING); // Signal vom Pickup erkennen  - Änderung 0.2.0 zu 0.2.1 Bleibt vorerst bei RISING und NICHT FALLING
  Serial.begin(9600); // serielle Schnittstelle konfigurieren mit 9600 Baud

  //START TIMER SETUP -------------------------------------------------------------------------------------------------START TIMER SETUP
//TIMER SETUP for highly preceise timed measurements TIMER SETUP für hochpräzise zeitgesteuerte Messungen
  cli();//stop all interrupts
  // turn on CTC mode
  TCCR1A = 0;// set entire TCCR1A register to 0 das gesamte TCCR1A-Register auf 0 setzen
  TCCR1B = 0;// same for TCCR1B
  TCCR1B |= (1 << WGM12); //Setze CTC-Mode (Waveform Generation Mode)
  // Set prescaler
  TCCR1B |= (1 << CS11); //Setze CS11 (Clock Select) für prescaler 8
// Verschiedene settings
  //TCCR1B |= (1 << CS12) | (1 << CS10);  //Setze CS10 und CS12 (Clock Select) für prescaler 1024
  //TCCR1B |= (1 << CS12);  //Setze CS12 (Clock Select) für prescaler 256
  TCCR1B |= (1 << CS11) | (1 << CS10);  //Setze CS11 und CS10 (Clock Select) für prescaler 64 // Prescaler 64 hier verwendet
  //TCCR1B |= (1 << CS11);  //Setze CS11 (Clock Select) für prescaler 8

  //initialize counter value to 0;
  TCNT1  = 0;
  
  // Timerzählung für 20Hz-Schritte einstellen =50Millisekunden. Der Wert des Registers OCR1A ist abhängig von der gewünschten Interruptfrequenz und dem gewählten Vorteiler. Es gilt die folgende Formel:
  // (CPU Frequenz (Hier =16000000)/(Prescaler64*gewünschte Interruptfrequenz20HZ))-1
  OCR1A = 12499; // Wert für 20Hz und prescaler 64
  
  // enable timer compare interrupt Timer-Vergleichsinterrupt aktivieren
  TIMSK1 |= (1 << OCIE1A); //Bit Output Compare A Match Interrupt Enable setzen

 
  sei();//allow interrupts //Setze globales Interrupt-Enable-Bit
  //END TIMER SETUP--------------------------------------------------------------------------------------------------END TIMER SETUP
} // setup Ende

  // Funktion welche ausgeführt werden soll wenn das Pickupsignal den attachInterrupt auslöst . Anfang
// Wenn injektor aus ist, wird der injektor_status auf 1 gesetzt und die Systemzeit in der Variable anschaltszeit_einspritzung_micros gespeichert
void pickupsignal() {  
  pickupsignalzaehler++; // Erhöht die Variable "pickupsignalzaehler" pro Pickupsignal jeweils jeweils um 1
  if (injektor_status == 0) {
       injektor_status = 1; // Injektorstatus auf 1 setzen Der Injektorstatus ist die Anweisung, dass der Injektor an oder ausgeschaltet sein soll
       anschaltszeit_einspritzung_micros = micros(); // Zeit zum Beginn der Einspritzung
       ausschaltzeit_einspritzung_micros = anschaltszeit_einspritzung_micros + einspritzzeit_micros;
  }
 }
  // Funktion welche ausgeführt werden soll wenn das Pickupsignal den attachInterrupt auslöst . Ende

//Funktion welche Ausgeführt wird, wenn das Timer interrupt ausgelöst wird-----------------------------Anfang
ISR(TIMER1_COMPA_vect) {      //Interrupt at frequency of 20 Hz =50Millisekunden
//Drehzahlberechnung anhand der Variablen pickupsignalzaehler (Summe der Pickupsignale während der Zeitdauer von Timer interrupt zu Timer interrupt (HIER =50Millisekunden)
// Anzahl der Signale pro Umdrehung =2 , 50 Millisekunden pro Messung wie im Timersetup festgelegt, 60000 für Millisekuden in Minuten (pickupsignalzaehler / 50 / 2)*60000 
//Serial.print("pickupsignalzaehler: "); //zum Testen
//Serial.println(pickupsignalzaehler);  //zum Testen
drehzahl_aktuell= (((pickupsignalzaehler / 50)/2)*60000);
pickupsignalzaehler = 0; // PickupZähler für neue Messung zurücksetzen
}

//Funktion welche Ausgeführt wird, wenn das Timer interrupt ausgelöst wird-----------------------------Ende

void loop() {
  hauptschalter_status = 1;
einspritzzeit_micros = 1000;
// serial Print Ausgaben für Test ANFANG
Serial.print("Drehzahl: ");
Serial.println(drehzahl_aktuell);


Serial.print("pickupsignalzaehler: ");
Serial.println(pickupsignalzaehler);

Serial.print("anschaltszeit_einspritzung_micros: ");
Serial.println(anschaltszeit_einspritzung_micros);

Serial.print("einspritzzeit_micros: ");
Serial.println(einspritzzeit_micros);

Serial.print("ausschaltzeit_einspritzung_micros: ");
Serial.println(ausschaltzeit_einspritzung_micros);

Serial.print("hauptschalter_status: ");
Serial.println(hauptschalter_status);

Serial.print("injektor_status: ");
Serial.println(injektor_status);
   
  } // Ende loop

Hallo,

von welchen Frequenzen, Drehzahlen reden wir?
Das Kuddelmuddel mit Timer und Pin Interrupt und micros halte ich aktuell für nicht sinnvoll.
Zudem die loop aktuell den seriellen Monitor nur so zuballert.
Kannst mal nach Arduino Drehzahlmesser oder Arduino Frequenzmesser suchen.
Der Gedanke dahinter ist, dass man nur den Timer verwendet. Diesen konfiguriert man ensprechend, lässt ihn durchgehend zählen und bildet mit jeder gleichen Flanke die Differenz seiner Timertakte. Weil man weiß wie schnell man ihn konfiguriert hat, weiß man die Zeitbasis für einen Timertakt und kann Timertakte und t multiplizieren und hat die Periodendauer etc.

Ok, ich hab bir den Code durchgelesen.

Ich denke dass ist für einen Absoluten Neuling zu nah an der Hardware dran. Debuggen in ISR-Routinen ist nicht ganz trivial...

Versuch mal deine Routine ohne Interrupts zu machen. In der Regel kann man das Problem auch ohne Interrupts lösen.

Ich gehe, bei einer 3Zyl. Yamaha XS750, von ca 10.500 U/min aus.
Dann setzt im Original der Begrenzer ein.

Hallo,

okay, grenzen wir das mal ein in welchen Messbereich man sich bewegt. Ich rechne mal etwas großzügig.
Ca. 500 U/min (Leerlauf) bis 12000 U/min.
Das wären 8Hz bis 200Hz. Das ist langsam, hab mich von den großen Zahlen täuschen lassen.
Man würde sich im Messbereich zwischen 125ms bis 5ms bewegen. So ungefähr erstmal für die Einordnung betrachtet.
Wenn man maximale Taktgenauigkeit möchte und mit Prescaler 1 arbeitet hat man mit 16Bit Timer keine Chance.
Weil 65535 * 62,5ns nur bis 4,096ms reicht.
Gehen wir mal die Prescaler durch.
65535 * 62,5ns * 8 = 32,7ms
65535 * 62,5ns * 64 = 262,14ms
65535 * 62,5ns * 256 = 1048,56ms
65535 * 62,5ns * 1024 = 4194,24ms
Prescaler 64 müßte man verwenden.

Man kann auch mittels Overflow Interrupt den 16Bit Timer auf 32Bit aufbohren. Dann könnte man Taktgenau 4294967295 * 62,5ns = Zeiten bis 268,4s messen.

Jetzt weiß ich nicht welche Auflösung ein Einspritzsystem benötigt. ns oder µs.
Ich nehme mal an ein 16Bit Timer mit Prescaler 8 würde reichen zur Drehzahlmessung.

Mit Drehzahl messen ist das aber bestimmt alles nicht getan. Man muss ja noch den Einspritzzeitpunkt bestimmen und genau auslösen lassen wiederum mit variabler Pulslänge. So stell ich mir das vor. Spannendes Projekt würde ich sagen.

Hi,
das geht bis 12000 U/min.
Mit dem seriellen Monitor hab ich das nur zum testen gemacht, um zu sehen was für Werte ausgespuckt werden und oder überhaupt.
Verschieden Ideen zu Drehzahl- und Frequenzmessungungen hatte ich mir angeschaut, die verwendete Methode war mir schlüssiger um zu lernen, wie die Schematik grundsätzlich funktioniert.
Nur funktioniert sie halt eben so, wie ich es geschrieben habe nicht. Kein Timer Interrupt.

Ja, ich hatte schon jede Menge Ideen für Drehzahlermittlung angeschaut.
Hatte bei vielen das Problem, daß mit delay gearbeitet wurde, was mir die ganzen Berechnungen mit micros zerschossen hatte.
Die Injektoren haben eine minimale Einpritzdauer von 2100 bis 3500 Mikrosekunden.
Beim auslesen der micros von Signal- Start und Ende hatte ich schon unerklärliche Differenzen der Messung.
Die reine Drehzahlmessung muss auch nicht so fein sein, die Drehzahl dient nur zur Berechnung von Schaltpunkten in grob 500er Schritten

Hallo,

der Timer funktioniert, habs ausprobiert. Nur paar Feinheiten geändert und die Reihenfolge.

volatile byte zaehler;
byte zaehlerAlt;

void setup() {
  Serial.begin(9600);
  cli();
  TCCR1B = 0;
  TCCR1A = 0;
  TCCR1B |= _BV(WGM12);
  TCNT1 = 0;
  OCR1A = 60000;
  TIMSK1  = _BV(OCIE1A);
  TCCR1B |= _BV(CS11) | _BV(CS10);
  sei();
}

ISR(TIMER1_COMPA_vect) {
  zaehler++;
}

void loop() {
  if (zaehlerAlt != zaehler) {
    Serial.println(zaehler);
    zaehlerAlt = zaehler;
  }
}

Größere Datentypen wie byte müssen atomar ausgelesen werden, sonst kann ein Interrupt mitten im lesen den Wert ändern.

Wenn ich mir die Formel anschaue
(((pickupsignalzaehler / 50)/2)*60000)
dann hast hier leider schon verloren.
Wird der Zähler größer 50?
Angenommen ...
50/50 ist in Ganzzahlrechnung = 1
1/2 ist in Ganzzahlrechnung = 0, alles weitere damit auch.

49/50 ist in Ganzzahlrechnung auch schon 0, alles weitere damit auch.

Stelle die Formel um
49 * 60000 / 50 / 2

und schreibe

= pickupsignalzaehler * 60000UL / 50 / 2

Klammern brauchste dafür keine.

In Ganzzahlrechnung sollte man so große Werte wie möglich ausrechnen bevor man am Ende dividiert. Weil die Kommastellen abgeschnitten werden.

Dann kann man doch auch gleich pickupzähler * 600 schreiben

Danke für die Mühe,
der Motor ist ein Zweitakter mit 2 Zylindern und dreht max 12000 U/min. Ich hab 14000 U/min als Maximum genommen um Reserven zu haben.
Es kommen 2 Signale pro Umdrehung
Bei 14000 U/min kommen bei 50ms Zähldauer 23,3 Zähler beisammen.
Die niedrigste Ganzzahl kommt bei 600 U/min mit einem Zähler von 1 bei 50ms Zähldauer raus.
Für Drehzahlen unter 3600 U/min mit 6 Zählern bei 50ms Zähldauer werde ich noch eine Konstante für die Berechnung der Einspritzzeit einbauen, da die Einpritzzeit bis dahin auch Konstant ist.
Die reine Drehzahlmessung muss auch nicht so fein sein, die Drehzahl dient nur zur Berechnung von Schaltpunkten in grob 500er Schritten.
Relevant ist also ein Zählerwert zwischen 6 und grob 24 bei 50ms Zähldauer.
Das mit der Rechenmethode von mir ist wohl meinem achtel Halbwissen geschuldet.
Das hatte ich gar nicht auf dem Schirm.
Ich bin halt mit der ganzen Materie wie ein Lehrling in der ersten Ausbildungswoche.
Mit der Hardware ist das ja das selbe Problem.
War gar nicht so einfach, verarbeitbare Signale zu erschaffen ohne die Bestandteile abzurauchen.
Ohm sweet Ohm war mir bis dato nur als Liedtitel von Kraftwerk aus den Siebzigern bekannt.

Ich teste das ganze heute mal und berichte dir.
Vielen Dank und mit freundlichstem Gruß
Peter

Hallo,

kann man kürzen ja, würde die gedankliche Formel als Kommentar behalten, damit man weiß wie man zu der 600 gekommen ist - Jahre später. :wink:

= pickupsignalzaehler * 600UL; // zähler * 60000 / 50 / 2

1 Like

War relativ sicher, dass der Compiler das sowieso macht. Zumindest, wenn in einer einzigen Anweisung alle Konstanten-Literale zusammen stehen.

Fun Fact:
Vermutlich wegen der von-links-nach rechts-Regel ist bei

  • a) uint32_t wert = pickupsignalzaehler * 600UL;
  • b) uint32_t wert = pickupsignalzaehler * 60000UL / 50 / 2;
  • c) uint32_t wert = pickupsignalzaehler * (60000UL / 50 / 2);

a) und c) im Ergebnis identisch. b) braucht 8 byte mehr Code (für einen atmega328p)

Weiß man --Jahre später-- noch, woher die 60000, 50 und 2 kommen? :wink:

1 Like

Selbst c) ist bedenklich!
Das funktioniert nur, weil 60000 "zufällig" durch 50 und 2 ohne Rest teilbar ist.

1 Like

Immerhin merkt der Compiler, dass a) und c) identisch ist. (Fragt sich, welchen Wert man bei a) wählt).

Richtig: Wenn der Gesamt-Faktor keine ganze Zahl ist, kommt je nach Eingangsvariable auch ein anderes Ergebnis raus, wenn erst multipliziert und danach dividiert wird. Fast so bedenklich wie der Ausgangspunkt dieser Frage in #10.

Hallo,

habe die Sache auch nochmal näher betrachtet, Optimierung macht der Compiler mit Multiplikation, nicht mit Division, laut meinen Tests. :wink:

die beiden sind gleich, b) wird zu a)
a) zaehler * 60000UL;
b) zaehler * 600UL * 50 * 2;

Man kann mit godbolt rumspielen, habe damit Gegengeprüft.

Hi Doc,
bin happy.
Drehzahl wird ordentlich berechnet.
Hab auch schon ein Injektorsignal an einem Ausgang.
Da muß ich jetzt mal mit dem Oszi prüfen ob der Einspritzzeitpunkt und Dauer korrekt berechnet wird.
Hab da 3 Injektoren, die Pumpensteuerung, 3 Wahlschalter, TPS und 2 Potis um die Parameter bei der Motorabstimmung zu verändern. Wäre zu schön, wenn das gleich bei Anhieb alles klappen würde.
Übrigens gibt das eine Wassereinspritzung in die Airbox, mit Adblue-Injektoren für meine 250er 2Takt für die Rennstrecke.
Ich möchte schlechtes Wetter simulieren, da hat das Moped spürbar mehr Leistung und die hätte ich gerne auch bei warmen und trockenen Wetter. Hab natürlich keinen blassen Schimmer, ob das den gewünschten Effekt simulieren kann. Aber probieren muß ich das unbedingt.
Ich möchte mich ganz herzlich für die Hilfe bedanken.
Gruß
Peter

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.