Probleme mit Impulsabstandsmessung

Hallo Arduino-Gemeinde,

Ich möchte mit Hilfe eines Adurino UNO Board ein Impulssignal analysieren. Das Signal kommt von einem Motorsteuergerät und gibt die Drehzahl des Motors aus. Es ist ein 50-50 Rechtecksignal auf 5V. Ich habe das ganze wie folgt aufgebaut (siehe Anhang).

Wenn ich das Signal mit einem Picoscope aufzeichne sehe ich auch dass das Signal aus dem Steuergerät ein schönes Rechtecksignal ist. Wenn ich dann die Drehzahl auf 6000 u/min stelle, habe ich ja einen Impulsabstand (high to high) 10ms, also High-LOW 5ms.

Ich habe es jetzt mit folgendem Code versucht zu analysieren:

int pin = 2;
unsigned long duration;

void setup()
{
  pinMode(pin, INPUT);
  Serial.begin(9600);
}

void loop()
{
  duration = pulseIn(pin, HIGH);
  Serial.println(duration);
}

Leider liefert das Board absolut nicht nachvollziehbare Werte. Hin und wieder kommt das richtige (5ms) lange Signal an, aber viel zu selten.

Kann mir jemand helfen wie man das ganze relaisieren könnte?
Es kann auch gerne über eine andere funktion gemacht werden, allerding soll der Ablauf des Programms nicht unnötig verzögert werden soll, weil mit dem Controller eine Getriebe gesteuert werden soll und das ganze natürlich so schnell wie möglich sein muss.

welche Spannung hat das Drehzahlsignal?
Hast Du die Masse des Arduino mit der Masse des Steuergerätes verbunden?
Der Motor ist ein Verbrennungsmotor?

Grüße Uwe

Signal ist auf 5V, Ich lad gleich noch ein Bild von dem Signal des Osszis hoch.

Nein habe ich nicht die Masse der ECU mit der Masse des Arduino verbunden, muss ich das?
Ja ist ein Verbrennungsmotor. Das signal kommt über eine art Zahnrad auf der Kurbelwelle mit 60-2 Zähne, ist ja aber im prinzip egal, da das Steuergerät das ja analysiert.

Ohne gemeinsame Masse geht das nicht.

Gruß
Klaus

Ah das macht jetzt schon einmal sinn und hat auch gleich bei 6000 u/min gepasst, kann daruaf schonmal aufbauen, muss jetzt aber leider noch weg. Werd mich morgen dann weiter darum kümmern.

Im Anhang noch das Signal.

zeitsignal.bmp (943 KB)

Ef_von_Iks:
Das Signal kommt von einem Motorsteuergerät und gibt die Drehzahl des Motors aus. Es ist ein 50-50 Rechtecksignal auf 5V. Ich habe das ganze wie folgt aufgebaut (siehe Anhang).

Du mußt den Minuspol des Motorsteuergeräts mit dem Minuspol des Arduino verbinden, Ground-to-Ground, nur dann gibt es einen definierten und feststellbaren Signal-Pegel.

An einer freihängenden Signalleitung kannst Du nichts messen, es wird immer ein Signal gegen Masse gemessen.

Und wenn Du zwei 5V-Geräte hast, bei dem eines das 5V-Signal liefert und das andere den 5V-Pegel messen soll, dann müssen beide Masseleitungen der Geräte miteinander verbunden sin, damit sie denselben Ground-Pegel haben.

Ef_von_Iks:
Ja ist ein Verbrennungsmotor. Das signal kommt über eine art Zahnrad auf der Kurbelwelle mit 60-2 Zähne, ist ja aber im prinzip egal, da das Steuergerät das ja analysiert.

Ein Verbrennungsmotor (Benziner) hat durch die Zündung sehr viele Störungen. Das kann Störungen auf dem Arduino geben.
Deshalb fragte ich.
Grüße Uwe

Jupp, deshalb wird die Steuerbox auch in eine Metallbox gepackt (faradayscher käfig :wink: ) und möglichst weit weg vom Motor. Ist in dem Fall zumglück nur ein 1-Zylinder, der stört nicht ganz so arg, aber dafür vibriert er ordentlich.

Also die Analyse funktioniert jetzt und stimmt auch so weit. Leider habe ich noch ein weiteres Problem.

Wenn ich die Periodendauer (Abstand zwischen 2 Impulsen) in eine Drehzahl umrechnen will muss ich die Periodendauer in Sekunden darstellen, also Teile ich die Periodendauer durch 1000000 um von µs auf s zu kommen. Als Variablentyp benutze ich daüfr extra einen float um eine Fließkommazahl zu bekommen, hier gibt es aber ein Problem: Der Chip rundet und zwar immer auf 2 Nachkommastellen. Also wird aus z.b. 10.000µs (bei 6000u/min) 0,01s. In dem Fall wäre es ja nicht schlimm, aber wenn die Drehzahl sich ändert und die Impulslänge z.B. auf 6.000µs fällt kommt eben auch 0,01s raus (ist ja auch logisch), das ist aber viel zu ungenau.

Weiß jemand wie ich den float umstellen kann damit ich 5 Nachkommastellen bekomme zum Rechnen?

Ich kann natürlich auch weiter rechnen in µs allerdings muss ich dann bei der Umrechung in eine Frequenz 1/T rechnen und stoße dann auf das Problem das eben 1/10.000 dann 0 ergibt, was ja falsch ist.

int pin = 4;
int duration;
float time;
float frequency;
int rpm;

void setup()
{
  pinMode(pin, INPUT);
  Serial.begin(9600);
}

void loop()
{
 
    
      
    duration = pulseIn(pin, HIGH);  //Messen der Impulslänge
    duration = duration*2;          //mit 2 Multiplizieren da 50-50 Impulssignal
    time = duration/1000000;        //Umrechnen von µs auf s
    frequency = 1/time;             //Umrechnen von Periodendauer in Frequenz
    rpm = frequency * 60;           //Umrechnen von 1/s in 1/min
    Serial.println(rpm);          //Ausgabe der Drehzahl in 1/min
    
   
   
    
}

Ef_von_Iks:
Jupp, deshalb wird die Steuerbox auch in eine Metallbox gepackt (faradayscher käfig :wink: ) und möglichst weit weg vom Motor.

Hilft nix!

Weil du elektrische Leitungen (= Antennen) hast, die nach aussen gehen, fängst du dir den ganzen Mist trotzdem ein.

Wenn du nur die Drehzahl wissen willst (nicht die Position des Motors), würde ich das so machen:

  1. zuerst das Signal tiefpassfiltern. Bei einer Pulslänge von minimal 10ms würde ich auf 10kOhm/100nF tiefpassfilter gehen.
  2. nicht den Abstand von Puls messen, sondern Pulse zählen. entweder alle 10pulse die Zeit nehmen, oder Pulse pro Zeitfenster.
  3. Störer über SW ausfiltern. Anhand der maximalen Drehzahl kannst du den kleinsten Pulsabstand berechnen, der überhaupt vorkommen kann. Wenn kürzere Abständen gemessen werden, dann kann man den Puls ausblenden, weil es ein Störer sein muß.

Gunther

guntherb:
Hilft nix!

Weil du elektrische Leitungen (= Antennen) hast, die nach aussen gehen, fängst du dir den ganzen Mist trotzdem ein.

Wenn du nur die Drehzahl wissen willst (nicht die Position des Motors), würde ich das so machen:

  1. zuerst das Signal tiefpassfiltern. Bei einer Pulslänge von minimal 10ms würde ich auf 10kOhm/100nF tiefpassfilter gehen.
  2. nicht den Abstand von Puls messen, sondern Pulse zählen. entweder alle 10pulse die Zeit nehmen, oder Pulse pro Zeitfenster.
  3. Störer über SW ausfiltern. Anhand der maximalen Drehzahl kannst du den kleinsten Pulsabstand berechnen, der überhaupt vorkommen kann. Wenn kürzere Abständen gemessen werden, dann kann man den Puls ausblenden, weil es ein Störer sein muß.

Gunther

Hört sich interessant an, also besonders 3. werd ich mal noch einbauen, das wenn ein Wert der kleiner als erwartet ist, einfach noch einmal gemessen wird. Es wird sich dann zeigen wie stark der Arduino beieinflusst wird, weil wir schon mehrere µC verbaut haben in dem Auto und noch keine Probleme hatten.

Wichtiger wäre aber jetzt erst einmal das float-Problem zu lösen :drooling_face:

Ef_von_Iks:
Wichtiger wäre aber jetzt erst einmal das float-Problem zu lösen :drooling_face:

Warum umgehst du die Division zu sehr kleinen Ergebnissen nicht, im dem die Kette von Berechnungen mit Konstanten zu einer einzigen zusammefasst?
du rechnest hier *2 /1000000; Kehrwert; *60

das lässt sich doch auch so zusammenfassen:

unsigned long duration, rpm;

void loop()
{
    duration = pulseIn(pin, HIGH);  //Messen der Impulslänge
    rpm = 30000000/duration;          //Umrechnen 30Mio/pulslänge
}

sollte so funktionieren.

Gunther

guntherb:
Warum umgehst du die Division zu sehr kleinen Ergebnissen nicht, im dem die Kette von Berechnungen mit Konstanten zu einer einzigen zusammefasst?
du rechnest hier *2 /1000000; Kehrwert; *60

das lässt sich doch auch so zusammenfassen:

unsigned long duration, rpm;

void loop()
{
   duration = pulseIn(pin, HIGH);  //Messen der Impulslänge
   rpm = 30000000/duration;          //Umrechnen 30Mio/pulslänge
}




sollte so funktionieren.

Gunther

Warum einfach wenn es auch Kompliziert geht :slight_smile:
Danke, geht und erfüllt seinen Dienst. Die Abweichung liegt unter 1%, damit kann ich leben.