Interrupt zu Langsam?

Hallo Leute ich habe Folgenden Code:

void interrupt()
{
  noInterrupts();                     
 interruptvariab = HIGH;


if(speed_time > 200)                  
{
  if(speed_time > 210)                
  {
    drossel = 10;
  }
  
    if(speed_time > 220)
  {
    drossel = 15;
  }
  
    if(speed_time > 230)
  {
    drossel = 20;
  }
  
    if(speed_time > 240)
  {
    drossel = 25;    
  }
  
    if(speed_time > 250)
  {
    
    drossel = 30;  }
  
    if(speed_time > 260)
  {
    drossel = 35;    
  }
  
  else
  {
    drossel = 0;
  }

  entdrossel_pin = digitalRead(7);                
  
  if(entdrossel_pin = HIGH)                       
    {
      drossel = 0;
     
      entdrossel_pin = LOW;
    }  
}


delayMicroseconds(drossel);            
digitalWrite(2,HIGH);
delayMicroseconds(120);               
digitalWrite(2,LOW);


  interrupts();                     
}

Jetzt Läuft das ganz für ca. 2 Sek super gut macht das was ich will. Habe einen Funktionsgenerator dran der mir ein Rechteck mit 200Hz gibt.
Nach den 2 Sek bekomme ich ein schwingen und der µC reagiert nicht mehr auf die Trigger.... aber warum? :blush:

Viele Grüße
Delon

Hallo,

generell sollen Interruptserviceroutinen ja schnell laufen. Ich würde da kein digitalRead und digitalWrite benutzen und auf gar keinen Fall irgendwelche Delays.

Gruß,
Ralf

Allso eigentlich will ich nur das ein Trigger einen Impuls Auslöst.
Leider brauch ich ja dazu delays und digitalWrite..

Viele Grüße

Das ist ja nicht der gesamte Code, den du uns da präsentiert hast, daher kann man kaum sagen, was hier falsch läuft. Die Bezeichnungen der Variablen und der Funktionen sind für (uns) Außenstehende auch nicht nachvollziehbar.
Die angesprochenen Auffälligkeiten (delays in der ISR, Verwendung von digitalWrite statt direkte Pormanipulation) solltest du dir zu Herzen nehmen und es nicht mit einem lapidaren "geht nicht anders" abtun.
Beschreib dein Projekt doch mal ausführlicher und poste den gesamten Code, so können wir wirklich nur rumstochern. :wink:

Die Ermittlung der drossel-Variable geht sicher auch einfacher, indem man speedtime durch 2 teilt und 95 abzieht, wäre dann aber ein linearer Zusammenhang und nicht abgestuft. Ist das so tatsächlich erforderlich?

Hallo oky das Ganze soll eine Zündung werden.

Ich habe einen Zündgeber, einen Rad Sensor, einen Eingang um die Geschwindigkeitsdrossel aufzuheben und einen Ausgang zur Zündspule.
Das wichtigste ist erst mal, das das Zünden klappt. Daher sollte wenn der Interrupt ausgelöst wird, abgefragt werden wie schnell ich gerade fahre. Wenn ich nicht zu schnell fahre wird das Dorsseldelay auf null gesetzt.
Dann wird einfach nur noch der Zünd bzw Lade Impuls generiert.
Die void loop ist zweitrangig da das Zünden das wichtigste ist, sonst fährt der Bock ja leider nicht. In der loop selber frage ich nur den Radsensor ab der die Geschwindigkeit anhand von Impulsen durchs Kettenblatt erfasst. => Niedrige Zeit zwischen den Impulsen Geschwindigkeit zu hoch und es wird langsam gedrosselt.

Das ist so der Plan und die Idee:-D ich hoffe ihr könnt mir helfen. Da der Motor später 12.000 bis 18.000 rpm dreht muss das Ganze mindestens im 250hz Bereich sauber laufen.

Hier der Ganze Code:

int entdrossel_pin = 0;
int readButton = 0;
unsigned long Startzeit = 0;
unsigned long speed_time = 0;
int drossel = 0;
volatile int interruptvariab = LOW;

void setup() 
{ 
   attachInterrupt(1,interrupt, LOW);                                    // Zündgeber
   pinMode(2,OUTPUT);                                                      // Output Zünd Transistor
   pinMode(4,INPUT);                                                       // Radsensor
   pinMode(7,INPUT);                                                       // Entdrosselung
} 

void loop() 
{  
  readButton = digitalRead(4);   
  if(readButton = HIGH)                       
  {
    Startzeit = millis();    
  }
  if(readButton = LOW)                         
  {
    speed_time =  millis() - Startzeit;
  }
} 
 
void interrupt()
{
  noInterrupts();                     
 interruptvariab = HIGH;
if(speed_time > 200)                  
{
  if(speed_time > 210)                
  {
    drossel = 10;
  }  
  if(speed_time > 220)
  {
    drossel = 15;
  }  
  if(speed_time > 230)
  {
    drossel = 20;
  }  
  if(speed_time > 240)
  {
    drossel = 25;    
  }  
  if(speed_time > 250)
  {    
    drossel = 30;  }
  if(speed_time > 260)
  {
    drossel = 35;    
  }  
  else
  {
    drossel = 0;
  }
  entdrossel_pin = digitalRead(7);                
    if(entdrossel_pin = HIGH)                       
    {
      drossel = 0;     
      entdrossel_pin = LOW;
    }  
}

  interrupts();                       
}

Das ganze habe ich nur in die ISR gemacht damit das zündsignal auch sicher erfast und "bearbeitet" wird.

Viele Grüße

Aber so ganz weißt du eigentlich nicht, was du da tust, oder? Wofür soll denn interruptvariab sein? Warum int, wenn du doch nur eine HIGH- oder LOW-Zuweisung machst, die dann nicht einmal ausgewertet wird? Warum muss du bei attachinterrupt() auf LOW reagieren und nicht einmalig auf die fallende Flanke mit RISING?

Da verstehe ich den gesamten Zusammenhang noch nicht - vielleicht bin ich heute einfach nicht aufnahmefähig. :wink:

WIrd so nie und nimmer funktionieren.

Grund: keine Entprellung des Inputs. Weiterhin hast Du globale Variablen außerhalb der Interruptroutine deklariert die nur darin benutzt werden --> die solltest Du entweder "volatile" deklarieren, oder besser: nur innerhalb der ISR und dafür "static".

Die angesprochenen Delays sind in der Regel ein Problem, hier aber ausnahmsweise eher nicht schuld, denn bei 200 Hz darfst Du pro Interrupt ja 5000 Mikrosekunden brauche, das sollte also noch locker gut gehen.

Wieso braucht Dein Radsensor eigentlich keine Pullup? Das wäre der nächste Verdächtige.

Und zu guter Letzt: bloß weil das irgendwie mal zufällig funktioniert muß das nicht lange so bleiben --> im KFZ Bordnetz wirst Du mit Transienten noch viel Spaß haben. Was passiert eigentlich wenn die Konstruktion während der Fahrt nicht mehr das tut was Du erwartest?

Nachtrag:

  if(entdrossel_pin = HIGH)

ist sicher falsch, Du meinst wohl

if(entdrossel_pin == HIGH)

Noch ein Fehler: in der ISR interrupts zu sperren, diese dann aber kurz vor Schluß freizugeben ist unnötig und riskant. Erstens macht das der Controller selber und richtig und zweitens kann man genau mit der Methode sich den Stack zu pflastern. Grund: falls während der ISR neue Interrupts auflaufen werden die direkt nach "interrupts" ausgeführt, also bevor er zurückkommt.

Ich habe Deinen Code mal etwas aufgeräumt und umgestellt, ob er damit besser funktioniert wage ich trotzdem zu bezweifeln. Dazu sind zuviele "merkwürdige" Variablen drin die ich nicht verstehe. Der fehlende Pullup für den Radsensor scheint mir das größte Problem zu sein. --> Code für die Pullups habe ich auch zugefügt.

volatile int entdrossel_pin = 0;
volatile unsigned long Startzeit = 0;
volatile unsigned long speed_time = 0;
volatile int drossel = 0;
volatile int interruptvariab = LOW;

void setup() {
   attachInterrupt(1,interrupt, LOW);      // Zündgeber
   pinMode(2,OUTPUT);                      // Output Zünd Transistor
   digitalWrite(4, HIGH);                  // Pullup aktivieren
   pinMode(4,INPUT);                       // Radsensor
   pinMode(7,INPUT);                       // Entdrosselung
   digitalWrite(7, HIGH);                  // Pullup aktivieren
}

void loop() {
  if(digitalRead(4)) {
    Startzeit = millis();
  } else {
    speed_time = millis()- Startzeit;
  }
}


void interrupt() {
    interruptvariab = HIGH;

    drossel =
      speed_time > 210? 10:
      speed_time > 220? 15:
      speed_time > 230? 20:
      speed_time > 240? 25:
      speed_time > 250? 30:
      speed_time > 260? 35:
                         0;

    entdrossel_pin = digitalRead(7);
    if (entdrossel_pin == HIGH) {
        drossel = 0;
    }
}

Und noch einer. Warum nicht

drossel = speed_time > 200? (speed_time-190)/2: 0;

@Masterboy: Hast du dir schon mal überlegt welche Haupt Parameter bei einer elektronische Zündanlage für einen Otto Motor relevant sind ?

Drehzahl und Last.
Die Drehzahl kannst du über den OT Sensor (Zündgeber) ausrechnen. Die Last bekommst du über einen Druckfühler der den Saugrohrdruck misst.
Aus diesen beiden Werten musst du dir eine Tabelle (Kennfeld) in dem EEprom anlegen der den Zündwinkel vor OT angibt.

Angenommen der Zündgeber ist 40 Grad vor oberer Todpunkt (OT) des Kolbens montiert, die ISR wird ausgelöst.
Jetzt wird anhand der Drehzahl und Last aus der Tabelle der "Delay" zu den 40 Grad ausgelesen und mit diesem Zeitverzug der Funke ausgelöst.

Auch würde ich nicht eine normale Zündspule mit einem Transistor steuern, sonst must du dich unter anderem noch um solche Dinge kümmern.
http://www.kfz-tech.de/Formelsammlung/Schliesswinkel.htm

Eine Zündpule mit Endstufenelektronik (sog. Stabzündspule) hilft hier weiter, und du sparst dir viele Transistoren ein die du bei den zahlreichen Tests mit Sicherheit abschießen wirst.

Ich bin jetzt nicht auf deinem Code eingegangen, weil ich der Meinung bin das dies der falsche Ansatz ist.
Motorsteuerungstechisch gesehen.

Hallo Leute,
erst mal vielen Vielen Dank für das große und umfangreiche Feedback!!!!!

Wo fange ich an :astonished:
Das Ganze ist für ein 50ccm Moped einfach eine Bastelei. Wenn das Ganze nicht mehr tut was ich will fahre ich wohl rechts ran und rege mich auf :smiley:
Das Zündkennfeld lasse ich vorerst weck und wird in Version 2.0 dazu kommen. Das ganze werde ich dann aber nur Drehzahl abhängig machen, da ich von einem "Motorbauer" genau Anweisungen bekomme wann und wie stark die Zündung zünden soll.

@ Udo:
Udo der Code sieht ja super kompakt aus echt klasse. Ich bin noch nicht so lange dabei mit dem Arduino Programmieren und kenne noch nicht diese "Tricks" um Sachen mit zwei drei Zeichen zu beschrieben. Ich versuche es immer mit meinem Leihen wissen irgendwie zu schaffen.
Habe zwar in der Ausbildung C gehabt aber leider nur LED´s Blicken lassen. :frowning:

Das mit dem Pull-up am Radsensor ist Sinnvoll. Aber um diese Elektronik wollte ich mich später kümmern. Eine andere Frage ist, wo wird in deinem Code der Transistor angesteuert? und Wie ist Die "Zündzeitpunkt Verschiebung" sprich das Delay vor diesem Befehl?

Die Inputs müssen nicht entprellt werden da ich sie Elektronisch ansteuere also keine Mechanischen teile die wirklich prellen.
Zündgeber wird wohl ein Foto Transistor werden und Radsensor ein Induktivernäherungsschalter

und was passiert dabei?
drossel = speed_time > 200? (speed_time-190)/2: 0;

Viele Grüße und Danke

Kleiner Nachtrag noch.

@ rudirabbit:
Diese Stabzündspulen sind die einfach zu handhaben? + und - und dann einfach noch das Steuerseignal drauf?
Das wäre ja ein Traum!! Da diese ja nicht mal sehr teuer sind!
Allerding wie kann man an diesen die "Zündleistung" verstellen? Kürzer "Laden" oder einfach die Spannung verändern?

MFG

Hello again,
also ich habe gerade den Code von Udo getestet und ganz frech den Ausgang für den Transistor eingefügt :slight_smile:
so wies aussieht läuft alle super.
Jetzt habe ich nur noch ein kleines Problem. Wenn nun der Pin 3 auf LOW gezogen wird, gibt der µC die ganze Zeit Impulse aus bis er wieder auf High ist.
Gehe ich richtig in der Annahme das, ständig Interrupts generiert werden und deswegen diese Verhalten auftritt?

Aber dann müsste ich ja nur den Interrupt Modus ändern von LOW auf Falling oder?

MFG

Allso bei Falling geht es zwar das wenn er von High auf Low wechselt nur einen Impulsgibt. Wenn allerding der eingang auf High ist gibt er ganz viele Impuls raus.
Aber warum? Das ist ja eigentlich keine Flanke...

Wenn unkontrolliert Impulse kommen, hängt der Eingang meist in der Luft. Ist ein Pullup-Widerstand verbaut?
Mit Schaltplan wäre das Problem auch etwas leichter zu begreifen.

Das mit dem Pull-up am Radsensor ist Sinnvoll. Aber um diese Elektronik wollte ich mich später kümmern. Eine andere Frage ist, wo wird in deinem Code der Transistor angesteuert? und Wie ist Die "Zündzeitpunkt Verschiebung" sprich das Delay vor diesem Befehl?

Die Inputs müssen nicht entprellt werden da ich sie Elektronisch ansteuere also keine Mechanischen teile die wirklich prellen.
Zündgeber wird wohl ein Foto Transistor werden und Radsensor ein Induktivernäherungsschalter

und was passiert dabei?
drossel = speed_time > 200? (speed_time-190)/2: 0;

Ähm: Du willst die Problemverursacher erst später beseitigen? Kein Wunder, daß das nichts wird.

Was den fehlenden Code angeht: der Code ist genau da wo er bei Deinem Beispiel auch ist - nicht vorhanden. Erwartest Du, daß hier jemand hellsehen kann? Dein Code ist unverständlich und funktioniert nicht. Ich habe ihn nur etwas übersichtlicher gemacht. Die Fehler sind immer noch drin. Ohne Details wäre alles andere ein Wunder.

Was den ? Operator angeht: C-Tutorial / Kontrollstrukturen Teil 2: ?:-Operator, switch-Anweisung (Kap. 7)

Diese Stabzündspulen sind die einfach zu handhaben? + und - und dann einfach noch das Steuerseignal drauf?
Das wäre ja ein Traum!! Da diese ja nicht mal sehr teuer sind!
Allerding wie kann man an diesen die "Zündleistung" verstellen? Kürzer "Laden" oder einfach die Spannung verändern?

Im Prinzip sind diese einfach zu handhaben, ein Inpulswechsel von hi nach low oder umgekehrt je nach Typ löst einen Funken aus.
Die Zündleistung ist dank der Elektronik darin immer optimal - du must dich darum nicht kümmern.
In modernen KFZ findet man nur noch Stabzündspulen.

Das ganze werde ich dann aber nur Drehzahl abhängig machen, da ich von einem "Motorbauer" genau Anweisungen bekomme wann und wie stark die Zündung zünden soll.

Wann gezündet wird ist das Kriterium - Wie stark ?? Was soll hier eine Regelung bewirken.
Wie hoch die Spannung ansteigt bis der Funke an der Kerze überspringt wird durch den Elektrodenabstand und der Kompression des Motors bestimmt.
Generell will man eine maximale Aufladung/Sättigung der Zündspule haben, und genau das machen die Stabzündspulen.

OK - eine Kennfeldzündanlage wäre für ein 50ccm etwas übertrieben.
Also nur über die Drehzahl, je höher diese ist desto früher must du Zünden.
Aber bist zu früh, schädigt das unter Umständen den Motor (Klopfende Verbrennung), bist zu spät verschenkst du Leistung und brauchst mehr Sprit.

Da der Motor später 12.000 bis 18.000 rpm dreht

Und wenn ich das lese handelt es sich um keinen normalen 50ccm Motor, diesen kannst du mit falschen zu frühen Zündwinkel schnell in's nirvana befördern