Interrupt Hall Sensor negative Werte UNO

Hi liebe Community,

bislang konnt ich sehr viel lernen hier im Forum und auch auf den unzähligen Internetseiten.

Leider habe ich aktuell ein Projekt, bei welchem ich einfach nicht wirklich weiter komm.

Es geht um eine 125er Aprilia, welche ich technisch etwas upgraden will.

Ich verwende zur Zeit einen Interrupt zur Drehzahlermittlung welcher nach einer Zeitperiode den inkrementierten Counter verrechnet. Das funktioniert soweit gut nur leider ist es sehr statisch und auch nicht so aktualisierungsfreudig.

PROBLEM/FRAGE:

Ich möchte zu jeder Umdrehung die benötigte Zeit auswerten. Das funktioniert mit meiner aktuellen Konfiguration im Leerlauf und bei wenig Drehzahl, danach spinnt die Routine sehr und ich weiß nicht wieso.

Hardware:
http://www.ebay.de/itm/172166288417 als Hallsensor mit Widerstand zwischen GND VCC

So sieht die Hardware in etwa aus:

http://img5.fotos-hochladen.net/uploads/polradmoklrdjabq.jpg

Das Wäre der Code dazu:

volatile unsigned long tim = 0;
volatile unsigned long time_last = 0;
volatile unsigned long minu = 60000000;
int rpm=0; //evtl alle unsigned long
int rpm1=0;
int rpm2=0;
int rpm3=0;
int rpmres=0;
int pot;

void setup()
{

 attachInterrupt(0, rpm_interrupt, FALLING); 
 Serial.begin(115200);

}

void loop()
{
 if (tim > 1) {
      //  detachInterrupt(0); hab ich mal zum test auskommentiert - ändert aber nix
        rpm=  minu/tim;
          rpm3 = rpm2;
        rpm2 = rpm1;
       rpm1 = rpm;
        rpmres=(((rpm1*3) + (rpm2) + (rpm3)) / 5)  ; //da 2 magnete 
        Serial.println(rpmres);

      //  attachInterrupt(0, rpm_interrupt, FALLING); hab ich mal zum test auskommentiert - ändert aber nix
 }

}
 

void rpm_interrupt()
{
 tim = (micros() - time_last);
 time_last = micros();
}

Im Serial Monitor kommen super Werte raus, jedoch springen sie ab ca. 5000 umdrehungen ins negativ unermässliche.
Sehr selten sind auch bei niedrigeren Drehzahlen kurz negative werte mit drin.
Leider hab ich den Monitor geschlossen, ich mache heute abend ein Screenshot davon.

Habt ihr mir Verbesserungsvorschläge für den Code?
Ziel soll sein einen extrem genauen und schnell aktualisierenden Drehzahlmesser zu haben um Servos etc. anzusteuern.

Vielen Dank Euch im Voraus,
Lg Chris

Wenn du keine negativen Werte willst oder diese vom Prinzip her sinnlos sind, wieso verwendest du dann int als Datentyp? Das klingt nach einem ganz normalen Überlauf

Was auch fehlt ist dass du auf "tim" atomar zugreifst. Das heißt bei abgeschalteten Interrupts:

  noInterrupts();
  unsigned long t = tim;
  interrupts();

  if (t > 1) {
       //  detachInterrupt(0); hab ich mal zum test auskommentiert - ändert aber nix
         rpm=  minu / t;

Hey Serenifly,

ich hab leider nie ne Informatikausbildung genoßen und muss mir alles selber beibringen - verzeih mir deshalb bitte unsinnige Fehler :slight_smile:

ich werde das detach und attach wieder mit einbauen, bzw. mit deinen Befehlen.

Desweiteren werd ich mir nach deinem Vorschlag die Tim in ein positives long schreiben.

Ich berichte heute abend nochmal :slight_smile:

Vielen Dank dir!

ich werde das detach und attach wieder mit einbauen,

Nein, das solltest du sein lassen.
Suche mal nach "AVR ATOMIC BLOCK RESTORE STATE"

Desweiteren werd ich mir nach deinem Vorschlag die Tim in ein positives long schreiben.

Ein vorzeichenloses Long, bitte...

ich hab leider nie ne Informatikausbildung genoßen und muss mir alles selber beibringen -

Kein Problem....

Allerdings:
Interrupts sind schon die etwas höheren Weihen.
Mit Seiteneffekten, man zu kämpfen hat.
Auch mit unerwünschten.

Darum:
Bitte nur im Schritttemp denken.

Hey Combie,

auch dir vielen Dank vor allem für den Denkanstoß sich in etwas neues einlesen.
Da ich gern der Probierer bin habe ich gerade etwas getüfftelt.

Mir ist in der Interrupt Routine eigentlich zu viel Text, könnt ihr das bestätigen oder sind 2 If clauses noch in ordnung?

Mit dem upgedateten Code erhalte ich nun immerhin schon nur noch positive RPMs, jedoch ab 6000 spinnt das Signal.
Irgendwie sagt mir mein Bauchgefühl, dass die ebay Hallsensoren nicht wirklich responsive genug sind? Ich hab spaßeshalber mal gerade ein paar Honeywell Hallsensoren bestellt.

Einzige alternative wäre, dass mein Code oder Arduino zu langsam ist, nicht hinterher kommt?

Getesteter Code:

volatile unsigned long erst = 0;
volatile unsigned long letzt = 0;
volatile unsigned long minu = 60000000;
unsigned long diff=0;
unsigned long rpm=0; //evtl alle unsigned long
unsigned long rpm1=0;
unsigned long rpm2=0;
unsigned long rpm3=0;
unsigned long rpmres=0;
volatile int counter=0;

void setup()
{

 attachInterrupt(0, rpm_interrupt, RISING); //rising??
 Serial.begin(115200);

}

void loop()
{
 if (counter > 1) {
      noInterrupts();
      diff=letzt-erst;
        rpm=  minu/diff;
        Serial.println(rpm);
counter=0;
erst=0;
letzt=0;
     interrupts();
 }
 
}
 
void rpm_interrupt()
{
if (counter==0) { 
 erst = micros();}
if (counter==1) {
 letzt = micros();}
 
 counter++;
}

Das schöne Ergebnis bis 6000 upm

Und das Ergebnis ab ca 7000 8000

Die 8000 Werte dürften stimmen wieso ist immer wieder jeder 2. oder 3. falsch?
17000 sind auf alle fälle unrealistisch da würd ich vermutlich besuch von Kolben Pleuel oder beidem bekommen.

Wie schon gesagt: Interrupts sind eine wesentlich kompliziertere Sache als du denkst

Auf die serielle Schnittstelle bei abgeschalteten Interrupts zu schreiben ist eine schlechte Idee. Das solltest du erst am Ende machen wenn die Interrupts wieder aktiv sind.

Mir ist in der Interrupt Routine eigentlich zu viel Text, könnt ihr das bestätigen oder sind 2 If clauses noch in ordnung?

Du kannst ein else if draus machen. Das macht den Code etwas schneller. Counter kann außerdem byte sein, wenn die Variable nur 0 oder 1 sein kann

Einzige alternative wäre, dass mein Code oder Arduino zu langsam ist, nicht hinterher kommt?

Lässt sich schwer sagen. Es gehen aber auch noch höhere Baudraten. Selbst die Arduino IDE unterstützt das mittlerweile

Irgendwie sagt mir mein Bauchgefühl, dass die ebay Hallsensoren nicht wirklich responsive genug sind?

Würde mich wundern....

Motorrad, lange Kabel, Störungen.....usw...
Kein leichtes Umfeld.

Ich würde mir das Signal mit einem Oszi anschauen.
Ich würde den Pullup soweit verkleinern, wie es der Sensor noch gerade eben zulässt.

Auch würde ich mit pulseIn() die Zeiten gegen prüfen.
Um Interrupt Probleme auszuschließen.

Danke euch beiden, die möglichen Verbesserungen baue ich morgen gleich mal mit in den Code ein.

ein Oszi hab ich leider keins :frowning:

Was meinst du mit Pullup, combie?

Mit pulseln beschäftige ich mich mal am nächsten Wochenende sieht eh interessant aus :wink:

Was meinst du mit Pullup, combie?

Den habe ich aus deinem Text entnommen.
Und ich weiß um dessen Notwendigkeit.

Hardware:
http://www.ebay.de/itm/172166288417 als Hallsensor mit Widerstand zwischen GND VCC

Den Schaltplan könntest du mal zeigen....

ok jetzt habe ich auch verstanden um was es geht.

es ist ein 10kohm soll ich mal nen kleineren verwenden? führt ja dazu dass, das signal besser gefiltert wird?!

nach diesem "plan" habe ich das gebaut: geht dann am arduino an den interrupt 0 pin

"gefiltert" ist das falsche Wort....

Hier [Bericht] I2C Pullup habe ich 2 Oszi Bilder eingestellt.

Betrifft zwar I2C, aber hier haben wir es mit dem gleichen Prinzip zu tun.
Open Kollektor mit Pullup.

Hey Combie,

wollt mal erst kurz danke sagen dass du so nett hilfst!
Hab die Carma gegeben, hoff das bringt was :slight_smile:

geht es in deinem topic wirklich um ein RTC - real time clock? Macht in meinem kopf gerade kein sinn.

Ich habe eine neue sehr tolle aber verwirrende erkenntnis wenn ich meinen Hallsensor in komplett identlischem Hardwareaufbau mit pulseIn abfrage bekomm ich das tollste ergebnis aller zeiten....

Kann es dennoch am Pullup oder Hall liegen - nein oder?

Der pulseIn Code:

//super ergebnis

void setup()
{
 
 Serial.begin(2000000);


}

void loop()
{

unsigned long tim=pulseIn(2 , HIGH);
  unsigned long rpm;
  rpm=60000000/tim;
  Serial.println(rpm);
 }

Hier mal das wunderschöne Ergebnis:
6426
6535
6671
6765
6840
6926
6891
6862
6897
7063
7288
7464
7695
7957
8248
8538
8823
9097
9361
9606
9850
10070
10279
10480
10647
10820
11001
11158
11284
11374
11465
11562
11657
11702
11746
11818
11848
11911
11952
12002
12053
12094
12138
12180
12192
12232
12279
12315
12335
12360
12401
12424
12432
12437
12450
12476
12497
12513
12541
12573
12591
12597
12639
12631
12671
12687
12746
12757
12787
12798
12853
12883
12872
12850
12787
12719
12644
12583

wollt mal erst kurz danke sagen dass du so nett hilfst!
Hab die Carma gegeben, hoff das bringt was :slight_smile:

Ich freue mich über die Anerkennung.

geht es in deinem topic wirklich um ein RTC - real time clock?

Nein, es geht um die Wirkung der Pullups.
Und um die Notwendigkeit, diesen Beachtung zu schenken.

Kann es dennoch am Pullup oder Hall liegen - nein oder?

Ohne das Signal zu sehen, kann ich keine Aussage dazu treffen.