- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 10 von 11

Thema: Tacho-Signal Erfassung

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    37
    Beiträge
    1.225
    Zeig Mal den Code für die Berechnung, zu Testzwecken kannst du ja auf dem Display auch Mal die µS zwischen zwei Flanken anzeigen. Ich würde fast vermuten, dass bei der Berechnung irgendwo ein Datentyp überstrapaziert wird, der Zusammenhang der Zwischenflankenzeit mit der Geschwindigkeit ist ja umgekehrt proportional.
    Allgemeiner Debugging-Tipp: Macht eine Berechnung komische Dinge, versuch Rohdaten zu bekommen und rechne einmal per Hand. Stimmt das Ergebnis, hast du entweder die Formel falsch einprogrammiert (falsche Klammerung o.ä.) oder dir läuft ein Datentyp über.

    mfG
    Markus

    Edit: Erfasst du die Rohdaten mit dem Rechner, kannst du dir auch leicht mit einer Tabellenkalkulation einen Plot ausgeben lassen, was auch oft hilfreich sein kann. (Man sieht auch oft sehr schön, wie verrauscht die Messdaten doch sind )
    Geändert von markusj (11.08.2011 um 14:11 Uhr) Grund: Nachtrag Plot

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    716
    Hallo,

    ich habe auf dem Display die µS angezeigt. Es ist leider schwer was klares abzulesen, da sich der Wert zu oft ändert, aber die Ungenauigkeit war klar zu erkennen. Hier der gewünschte Code:

    Code:
     U32 TachoTime = TachoTimeHigh;
     TachoTime = TachoTime<<16;
     TachoTime = TachoTime + TachoTimeMiddle;
     TachoTime = TachoTime<<8; 
     TachoTime = TachoTime + TachoTimeLow;
    
    LCD_Cursor (1, 1);
    LCD_Zahl (TachoTime);

    Die Funktion LCD_Zahl gibt eine 10-stellige Zahl auf dem LCD mit führenden Nullen aus.

    Ich habe die Berechnung extra in mehrere Schritte zusammengefasst, um den von dir erwähnten Überlauf zu vermeiden. Ich sitze nicht umsonst schon so lange am Problem. Ich glaube ich habe alles ausgeschlossen, was auszuschliessen ist...

  3. #3
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von Bumbum Beitrag anzeigen
    Code:
     U32 TachoTime = TachoTimeHigh;
     TachoTime = TachoTime<<16;
     TachoTime = TachoTime + TachoTimeMiddle;
     TachoTime = TachoTime<<8; 
     TachoTime = TachoTime + TachoTimeLow;
    Das sieht doch schon mal reichlich merkwürdig aus. Ist TachoTimeMiddle tatsächlich 16 Bit groß und TachoTimeLow 8 Bit?
    MfG
    Stefan

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    37
    Beiträge
    1.225
    Wie synchronisierst du deine Hauptschleife auf den Interrupt?
    Außerdem: So erfasst du ja "nur" den Abstand zwischen zwei Flanken, unter Umständen ist das Signal aber ungleichmäßig (evtl. die High-Phase kürzer als die Low-Phase oder so). Versuch Mal, die Hauptschleife und die Zeitnahme auf jede zweite Flanke zu synchronisieren, so dass du einen vollen Zyklus misst.

    Falls du das bereits getan hast: Sorry, aber das steht nicht in dem Code den du gepostet hast.

    mfG
    Markus

    EDIT: Stefan hats gefunden, ich war zu Betriebsblind :P, klar, du darfst jeweils nur um 8 Bits schieben, so machst du ein Loch rein und schiebst die oberen 8 Bits raus..

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    716
    Guten Morgen,

    Stefan hats vermutlich wirklich gefunden. Da war ich dann wohl irgendwann zu blind dafür. Ich wollte eigentlich die 16 Bits aus TachoTimeHigh "wegschieben". Aber logisch: Die müssen um 8 geschoben werden, um den 8 Bit von TachoTimeMiddle Platz zu machen.

    Ich werde diese Zusammenstellung der 3 Werte auch wieder in den Interrupt schieben, da sonst der Interrupt ja während der Berechnung die Werte verändern könnte. Sind ja immerhin 6 Befehle mit vermutlichem Zugriff auf Daten im RAM. Da ist die Wahrscheinlichkeit groß, dass mal ein IRQ "dazwischenfunkt".

    @Markus: Die Flanken sind gleich, das habe ich vorher mit dem Oszi überprüft. Trotzdem Danke für's Mitdenken. Mein Plan war dann eh das ganze noch über ein paar Werte zu glätten, aber solange es grundsätzlich nicht funktioniert nützt auch das ganze Glätten nix...

    Ich werde den Code ändern und dann ausprobieren. Ist nicht immer ganz Einfach das Fahrrad an den Basteltisch zu bekommen. Und ohne Tacho-Signal vom Fahrrad testet sich das ganze immer so schlecht...

    Ich werde berichten. Danke erst mal!

    Viele Grüße
    Andreas

  6. #6
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    02.08.2006
    Ort
    Würzburg, Germany
    Beiträge
    716
    Ich konnte es nicht abwarten und habe es gleich probiert. Leider ohne Erfolg. Es muss noch ein Fehler drin sein. Ich poste deshalb mal etwas mehr von meinem Code, vielleicht ist es ja noch eine Kleinigkeit:

    Code:
    #define AVRGCC 
    #include <avr/io.h> 
    #include <compiler.h>
    #include <util/delay.h>
    /** 
    IOs:
    PD2 (INT0)  Tacho Eingang
    **/
     
    volatile U32 TachoTime = 0;
    volatile U16 TachoTimeCounterHigh = 0;
       U32 SpeedBuffer[SpeedBufferSize];
       U8  SpeedBufferPointer;
       U32 CurrentSpeed = 0;
     
    int main(void)
    { 
     DDRB =  0b11111100; // Das LCD hängt an PB7...PB5
     PORTB = 0b00000000;
     DDRD =  0b00000000;
     PORTD = 0b01000100;
     LCD_Init ();
     
     
     // IRQ 0 für Tacho-Signal-Eingang:
     MCUCR = 0b00000001;
     GIMSK = 0b01000000;
     
     // Timer 1:  Takt für Tacho-Input-Counter:
     TCCR1B |= (1<<CS11);  // Prescaler auf 8:
     TIMSK |= (1<<TOIE1);  // IRQ für Overflow
    
    /** 
     for (SpeedBufferPointer = 1; SpeedBufferPointer < SpeedBufferSize; SpeedBufferPointer++)
      SpeedBuffer[SpeedBufferPointer] = 0;
     SpeedBufferPointer = 1;
    **/
     sei ();
     
     while (1)
     {
      // Geschwindigkeitsberechnung:
      // TachoTime:
      // 1 Sekunde entspricht  FCPU / Prescaler = 8000000 / 8 = 1000000 entspricht 1µs Auflösung
      // schnellste Geschwindigkeit: 100km/h entspricht 2,988ms Mindest-Auflösung
      // 1 km/h entspricht 298,8 ms (ganze Periode): bzw Zeit zwischen Flankenwechsel: 149,4 ms
      // --> Geschwindigkeit = 149400 µs / Flankenzeit
      // --> Geschwindigkeit in Zehntel-km/h = 1494000 µs / Flankenzeit
      
      // langsamste Geschwindigkeit: 0,1 km/h entspricht 14940000 µS
      if ((TachoTime > 0) && (TachoTime < 15000000))
       CurrentSpeed =  1494000 / TachoTime;
      else
       CurrentSpeed = 0;
      /**
      SpeedBuffer[SpeedBufferPointer] =  CurrentSpeed;
       
      if (SpeedBufferPointer < SpeedBufferSize)
       SpeedBufferPointer++;
      else
       SpeedBufferPointer = 1;
      
      CurrentSpeed = 0;
      U8 i1;
      for (i1 = 1; i1 < SpeedBufferSize; i1++)
       CurrentSpeed = CurrentSpeed + SpeedBuffer[i1];
      CurrentSpeed = CurrentSpeed / SpeedBufferSize;
      **/
      LCD_Cursor (1, 1);
      LCD_Zahl (CurrentSpeed);
     }
        return(0); 
    }
     
    // Tacho-Eingang Signalwechsel:
    SIGNAL (INT0_vect)
    {
     TachoTime = TachoTimeCounterHigh;
     TachoTime = TachoTime<<8;
     U8 tmp = TCNT1L;
     TachoTime = TachoTime + TCNT1H;
     TachoTime = TachoTime<<8;
     TachoTime = TachoTime + tmp;
     TCNT1L = 0;
     TCNT1H = 0;
     TachoTimeCounterHigh = 0;
    }
     
    // Tacho-Eingang-Zeitmessung:
    SIGNAL (SIG_TIMER1_OVF)
    {
     if (TachoTimeCounterHigh < 0xFFFF)
      TachoTimeCounterHigh++;
    }
    Das Tacho-Signal springt immer noch wild durcheinander. Selbst mit Glättung.

    Hüüüülfe! Das sollte doch eigentlich ganz easy sein!

    Viele Grüße
    Andreas

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Karlsruhe
    Alter
    37
    Beiträge
    1.225
    Hallo Andreas,

    Mal vorne angefangen. Arrays in C werden von 0 bis Größe-1 indiziert, du verwendest 1-Größe (und zerballerst damit 4 Bytes nach deinem Array, in denen andere Variablen liegen). Dann fehlt dir eine Synchronisation zwischen Hauptschleife und ISR. Volatile garantiert dir nicht, dass im Hauptprogramm TachoTime atomar ausgelesen wird!

    Vorschläge:
    1. Arrayzugriffe korrigieren
    2. Die Neuberechnung der TachoTime kannst du ruhig auch in der Hauptschleife machen, wenn du den Code in der ISR halten möchtest, solltest du die Zwischenergebnisse in einer lokalen Variable halten und erst am Ende nach TachoTime schreiben. Grund: Volatile sagt dem Compiler, dass er IMMER aus der im SRAM liegenden Variable lesen bzw. JEDE Änderung direkt dorthin zurückschreiben muss. Es würde also jede deiner Zuweisungen einmal in den SRAM geschrieben, obwohl es wesentlich effektiver wäre, die Zwischenergebnisse in den Registern zu nutzen.
    3. Locking: Lies in der Hauptschleife TachoTime (oder die Rohdaten falls du die Berechnung aus der ISR rausnimmst) in lokale Puffervariablen und schalte während des Lesevorganges Interrupts aus. Um das zu vereinfachen gibt es in util/atomic.h den ATOMIC_BLOCK, es sollte aber auch reichen, den Kopiervorgang in die lokale Variable mit cli() bzw. sei() zu umgeben.

    mfG
    Markus

    EDIT: Zu 1: Informatiker am Bahnhof - 0, 1, 2 ... wo ist mein dritter Koffer?
    Geändert von markusj (12.08.2011 um 10:27 Uhr) Grund: Informatiker am Bahnhof ...

  8. #8
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Außerdem wird das Zurücksetzen des Timers nicht richtig funktionieren, weil falsche Reihenfolge der Zugriffe. Warum überhaupt einzelne Zugriffe auf Low- und High-Byte? Warum nicht einfach:
    Code:
      TachoTime = TachoTimeCounterHigh;
      TachoTime = TachoTime<<16;
      TachoTime = TachoTime + TCNT1;
      TCNT1 = 0;
      TachoTimeCounterHigh = 0;
    Besser und genauer wäre es natürlich, das Input-Capturing des Timers zu benutzen.
    MfG
    Stefan

Ähnliche Themen

  1. IR-Sensor Erfassung mit Servo
    Von JeyBee im Forum Sensoren / Sensorik
    Antworten: 1
    Letzter Beitrag: 28.10.2008, 16:29
  2. optische Erfassung der Sonne
    Von duc750 im Forum Sensoren / Sensorik
    Antworten: 24
    Letzter Beitrag: 23.01.2007, 21:22
  3. Drehzahl erfassung
    Von ceekay im Forum AVR Hardwarethemen
    Antworten: 1
    Letzter Beitrag: 16.09.2005, 21:16
  4. Tacho Signal beim A3932 von Allegro
    Von demir im Forum Elektronik
    Antworten: 2
    Letzter Beitrag: 01.02.2005, 12:21
  5. Erfassung Pulslänge mir RN-Mega8
    Von Hellmut im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 9
    Letzter Beitrag: 31.10.2004, 19:37

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests