-         

Ergebnis 1 bis 8 von 8

Thema: KM/h Messung mit 2 Lichtschranken?

  1. #1
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    06.07.2006
    Alter
    87
    Beiträge
    627

    KM/h Messung mit 2 Lichtschranken?

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Hallo,
    ich möchte mit 2 Lichtschranken die Geschwindigkeit meines RC-Autos messen.
    Jede Lichtschranke ist an einem Interrupteingang des µC.

    Ich benutze einen MEGA 8. Kann ich den internen Taktgeber nutzen oder sollte ich einen richtigen Quarz nehmen?

    Hier mein (fast) fertiges Programm. Ich konnte es leider noch nicht testen, da die Hardware nocht nicht fertig ist(habe hier nur µC mit zwei Tastern):

    Code:
    '-------------------------------------------------------------------------------
    'Konfiguration µC:
    
    $regfile = "m8def.dat"                                      'MEGA8-Deklarationen
    
    $hwstack = 32
    $swstack = 8
    $framesize = 24
    
    $crystal = 8000000
    $baud = 9600                                                'Baudrate definieren
    '-------------------------------------------------------------------------------
    'Ein / Ausgänge definieren:
    Ddrd = &B00000000                                           '0=Eingang
    
    '-------------------------------------------------------------------------------
    'Variablen
    Dim Schritte As Word                                        'Wert vom Timer
    Dim Schritte_old As Word
    Dim Kmh As Single
    Dim Sperre As Byte                                          '1= gesperrt, wenn Lichtschranke 1 betätigt wurde
                                                                 '2= gesperrt, wenn Lichtschranke 2 betätigt wurde
    
    '-------------------------------------------------------------------------------
    'Timer1
    Config Timer1 = Timer , Prescale = 256                      'Teiler
    Enable Timer1
    Enable Interrupts
    On Timer1 Errorhandler
    
    Config Int0 = Rising                                        'Falling
    Enable Interrupts                                           'einschalten Der Interrupts
    Enable Int0                                                 'einschalten Von Interrupt Int0
    On Int0 Isr0
    
    Config Int1 = Rising                                        'Falling
    Enable Interrupts                                           'einschalten Der Interrupts
    Enable Int1                                                 'einschalten Von Interrupt Int0
    On Int1 Isr1
    '-------------------------------------------------------------------------------
    
    '-------------------------------------------------------------------------------
    
    
    
    Do                                                          'Hauptschleife
    
    
    If Schritte_old = Schritte Then                             'Vergleich, ob neuer Messwert vorhanden oder nicht
    'nix
    Else
    Kmh = 33750 / Schritte                                      'Timerwert in KM/h umrechnen
    Print "Geschwindigkeit: " ; Fusing(kmh , "###.#" ) ; " KM/h"
    Schritte_old = Schritte
    End If
    
    
    
    Loop
    
    
    
    '-------------------------------------------------------------------------------
    Isr0:                                                       'Aufruf bei Lichtschranke 1 per Interrupt
    If Sperre = 0 Then
     Timer1 = 0                                                 'Timer auf 0 setzen
     Sperre = 1                                                 'für Lichtschranke 1 sperren
    End If
     'Print "int0 geht"                                          'nur zum testen
    Return
    
    
    
    Isr1:                                                       'Aufruf bei Lichtschranke 2 per Interrupt
    If Sperre = 1 Then
     Schritte = Timer1                                          'Timerwert übernehmen
     Sperre = 2                                                 'für Lichtschranke 1 UND 2 sperren
    End If
     'Print "int1 geht"                                          'nur zum testen
    Return
    
    
    
    Errorhandler:                                               'wenn Timer1 überläuft
     Sperre = 0                                                 'nächste Messung freigeben
     'Print "ÜBERLAUF"                                           'nur zum testen
    Return
    kurze Beschreibung:
    Die 1te Lichtschranke setzt den Timer1 auf 0. Die zweite Lichtschranke schreibt den Wert vom Timer1 in eine Variable. Da die Lichtschranken einen festen Abstand von 30cm haben kann in der Do...Loop in KM/h umgerechnet werden. Die beiden Lichtschranken zählen eine Variable hoch, um versehentliches doppelt betätigen einer Lichtschranke zu verhindern. Wenn der Timer1 nach ca 2 Sekunden Überläuft, wird die Variable zurückgesetzt um für eine neue Messung bereit zu sein.
    Zum testen kommt das Ergebnis nur über RS232, später soll es auf eine große 7-Segmentanzeige

    Tobias

  2. #2
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Der interne Takt beim AVR hat schon ein paar % Tolleranz. Solange sich die Temperatur nicht wesentlich ändert bleibt der Takt dann aber einigermaßen Stabil. Wenn man Pech hat, macht auch die RS232 schon Probleme.

    Wenn man damit klar kommt, weil z.B. der Abstand der Lichtschranke ohnehin nicht so genau bekannt ist, geht es auch ohne Quarz. Ein Quarz wäre natürlich wesentlich genauer.

  3. #3
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    06.07.2006
    Alter
    87
    Beiträge
    627
    na dann nehme ich natürlich einen

    Der Abstand soll ja genau 30 cm sein und ich messe ja im ms Bereich.

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von Vitis
    Registriert seit
    06.01.2005
    Ort
    Südpfalz
    Alter
    43
    Beiträge
    2.240
    und worin genau besteht das Problem?

    Prinzipiell ist für genaue Messung ein Quarz oder noch besser n
    temperaturstabilisierter Oszillator zu verwenden, die
    interne RC-Taktquelle ist für timingunkritische Geschichten OK,
    aber alles was exaktes Timing braucht kannst Du das ziemlich
    knicken. Das gilt auch für USART-Kommunikation in Baudraten
    >9600 Baud.
    Vor den Erfolg haben die Götter den Schweiß gesetzt

  5. #5
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    06.07.2006
    Alter
    87
    Beiträge
    627
    Hallo Vitis,
    ich wollte nur mal fragen ob ich etwas gravierendes falsch gemacht habe. Fehler finden ist ja schwierig, da ich keine richtige Vergleichsmessung habe. (Ich wollte mal mit dem Fahrrad durch die Messung fahren und dann mit meinem Tacho vergleichen.)

    Wie du schreibst, ist es wohl besser wenn ich eine möglichst kleine Baudrate nehme. D.h. wohl auch ich muss darauf achten, dass das Messergebnis NACH der Messung nur einmal gesendet wird und dann der µC wieder frei für die Messung ist(und keine USART Kommunikation stört).

    Dann kann ich mich ja an die Hardware machen.

    Danke - Tobias

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.01.2006
    Beiträge
    4.556
    Bei den internen Ozzilator klappt es oft nicht mit der RS 232
    weil der Ozzilator die Baudrate nicht sauber halten kann. Mit
    quarz kannst Du auch weitaus schneller arbeiten. Da Du ja über IRQ
    die Zeit ermittelst kann Dir die RS "§" da eh nicht reinfummeln.

    Ich würde aber eher nur mit einem Timer arbeiten. Lichtschranke
    1 Start Timer Lichtschranke 2 Stop Timer, Timer Wert Speicher, Return
    zur Haupschleife, Auswerten und senden...Den Timer SO einstellen
    das nur über eine Flanke getriggert wird.

    Gruß Richard

  7. #7
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    So schlecht ist der interne TAkt auch nicht. Solange man keine ungewöhnlichen Temperaturen hat, klapt es noch meistens mit der RS232, aber halt nicht immer. Wenn das Programm keinen gravierenden Fehler hat, oder die Hardware extra langsam ist, hilft es auch nicht die Baudrate unter 9600 Baud zu senken. Dadrüber kann man zusätzliche Rundungsfehler bekommen so dass es dann etwas leichter Fehler gibt.

    Wenn man so wie gezeigt die Auswertung im Interrupt macht, stört es auch kaum wenn während der Wessung noch eine UART Übertragung läuft. So schnell sind die meisten Lichtschranken ja auch nicht, und auch die Position wo die Lichtschranke anspricht ist oft nicht so genau definiert.
    Wenn es sein muß hätte man mit der ICP-funktion auch noch Hardwareunterstützung für den Stop Eingang.

  8. #8
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    06.07.2006
    Alter
    87
    Beiträge
    627
    so der Testaufbau mit Laserlichtschranken ist fertig

    ich benutze 2 1mW Laserpointer und zwei Empfänger vom goßen "C" (Bausatz 117420).

    leider erkennen die Lichtschranken bei zu großer Geschwindigkeit nichts mehr... Muss ich mir mal den Schaltplan ansehen, ob man da etwas an der Geschwindigkeit machen kann...

    Hier erst mal mein fertiger Code mit 7Seg.Anzeige:

    Code:
    '7 Segmentanzeige im multiplexbetrieb mit 2 Laserlichtschranken an PIN 4 (INT0) & PIN 5 (INT1)
    ' für die Anzeige wird ein kompletter Port (0-7 = 7Seg+DP) benötigt
    ' für Anzeigen mit gemeinsamer Anode
    '
    ' Anschlüsse:
    ' -----------
    '                           7 Segmente = PB 0 - PB 7 (PB0=DP)
    '                           4 Anzeigen = PC 4 - PC 1 (4 Anzeigen / 4 Transistoren)
    'Z                          5 Anzeigen = PC 5 - PC 1 (5 Anzeigen) PC5 = Einerstelle ganz rechts!!!!
    'e
    'i
    'c
    'h
    'e
    'n     PORTB.X
    '||7|6|5|4|3|2|1|0 |Dezimal
    '| _________________
    '||G|F|E|D|C|B|A|DP| \/
    '0| |X|X|X|X|X|X|  |126
    '1| | | | |X|X| |  | 12
    '2|X| |X|X| |X|X|  |182
    '3|X| | |X|X|X|X|  |158
    '4|X|X| | |X|X| |  |204
    '5|X|X| |X|X| |X|  |218
    '6|X|X|X|X|X| |X|  |250
    '7| | | | |X|X|X|  | 14
    '8|X|X|X|X|X|X|X|  |254
    '9|X|X| |X|X|X|X|  |222
    '______________________
    '=|X| | |X| | |X|  |146 (drei waagerechte Striche)
    'F|X|X|X| | | |X|  |226
    '-|X| | | | | | |  |128
    '
    'weitere mögliche Buchstaben:
    'A-B-C-D-E-F-G-H-I-J-L-O-P-R-S-U
    '
    '
    '
    'ZEITMESSUNG FUNKTIONIERT
    'kurze Beschreibung:
    'Die 1te Lichtschranke setzt den Timer1 auf 0.
    'Die 2te Lichtschranke schreibt den Wert vom Timer1 in eine Variable.
    'Da die Lichtschranken einen festen Abstand von 30cm haben,
    'kann in der Do...Loop in KM/h umgerechnet werden. Die beiden Lichtschranken
    'zählen eine Variable(SPERRE) hoch, um versehentliches doppelt betätigen
    'einer Lichtschranke zu verhindern. Wenn der Timer1 nach ca 2,2 Sekunden Überläuft,
    'wird die Variable zurückgesetzt um für eine neue Messung bereit zu sein.
    'LED an = Messung bereit. LED aus = SPERRE aktiv
    
    
    'RECHNUNG ms:
    '8MHz / Teiler 256 = 31250 Schritte / Sec oder / 1000ms
    '1Schritt = 0,032ms
    'Also x Schritte * 0,032ms  = ms
    
    'RECHNUNG KM/h:
    '0,0003*3600000/100ms=10,8KM/h
    '3*360/100ms=10,8KM/h
    '1080/100ms=10,8KM/h
    
    'ZUSAMMEN:
    '1080/0,032/Schritte = KM/h
    '33750/Schritte = KM/h
    '
    '337500 eine NULL mehr um das Komma zu verschieben!!!
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    
    
    $regfile = "m8def.dat"                                      'AT-Mega8
    
    $hwstack = 32
    $swstack = 8
    $framesize = 24
    
    $crystal = 8000000                                          'Quarz: 8 MHz
    '$baud = 9600                                                'Baudrate der UART: 9600 Baud
    '-------------------------------------------------------------------------------
    ''Konfiguration LCD
    'Config Lcd = 20 * 4
    'Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.0 , Rs = Portd.1
    'Cursor Off Noblink
    
    '-------------------------------------------------------------------------------
    'Konfiguration Ein- / Ausgänge
    Ddrb = &B11111111                                           '1 Ausgang, 0 Eingang => Pin PB7-0 als Ausgang
    Ddrc = &B1111110                                            '1 Ausgang, 0 Eingang => Pin PC6-1 als Ausgang; 0 als Eingang
    Ddrd = &B11110011                                           '1 Ausgang, 0 Eingang => Pin PD7-4,1&0 als Ausgang; 2&3 als Eingang
    
    'Pullup´s
    Portd = &B0001100                                           'PullUp von Pin PD2&3 aktivieren
    
    
    '-------------------------------------------------------------------------------
    'Konfiguration Timer0 für 7 Segmentanzeige, Taster
    Config Timer0 = Timer , Prescale = 1024
    On Timer0 Timer0_isr
    Const Timervorgabe0 = 245                                   '781 mal / Sekunde!!!
    Enable Timer0
    Enable Interrupts
    
    
    '-------------------------------------------------------------------------------
    'TIMER1 Konfiguration für Messzeit Lichtschranke:
    Config Timer1 = Timer , Prescale = 256                      'Teiler
    Enable Timer1
    Enable Interrupts
    On Timer1 Errorhandler
    Enable Interrupts
    
    '-------------------------------------------------------------------------------
    Config Int0 = Rising                                        'Falling                                       'wechsel von High auf Low
    Config Int1 = Rising                                        'Falling                                       'wechsel von High auf Low
    Enable Int0
    Enable Int1
    On Int0 Isr0
    On Int1 Isr1
    
    '-------------------------------------------------------------------------------
    'Alias
    Led Alias Portc.6                                           'Status LED  -  1=bereit
    
    '-------------------------------------------------------------------------------
    'Variablen Anzeige:
    
    
    
    'Variablen für die 7Seg. routine
    Dim Wertstr As String * 5
    Dim Y As Byte
    Dim Tempbyte As Byte
    
    Dim Digit As Byte                                           'Variable für Digitansteuerung
    
    Dim Fivedigitdisplay As String * 5                          'Anzeige im Ganzen
    
    'führende Nullen entfernen
    Dim Digit_aus As Bit                                        'Merker =0 wenn Stelle =0
    
    
    'KM/h Messung / Rechnung:
    Dim Schritte As Word                                        'Wert vom Timer
    Dim Schritte_old As Word
    Dim Kmh As Long                                             'Single
    Dim Sperre As Byte                                          '1= gesperrt, wenn Lichtschranke 1 betätigt wurde
                                                                 '2= gesperrt, wenn Lichtschranke 2 betätigt wurde
    
    
    'Dim Lcdmerker As Word                                       'lcd anzeigen
    
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    '-------------------------------------------------------------------------------
    'Setzen:
    
    Digit_aus = 0
    
    'alle Segmente aus
    Portb = 0
    Digit = 0
    
    
    '===============================================================================
    Do
    '===============================================================================
    If Schritte_old = Schritte Then                             'Vergleich, ob neuer Messwert vorhanden oder nicht
    'nix
    Else
    Kmh = 337500 / Schritte                                     'Timerwert in KM/h umrechnen
    'Print "Geschwindigkeit: " ; Fusing(kmh , "###.#" ) ; " KM/h"
    Schritte_old = Schritte
    'Lcdmerker = 1
    End If
    
    'Anzeige Messung BEREIT
    If Sperre = 0 Then
    Led = 1                                                     'es kann gemessen werden
    Else
    Led = 0                                                     'es kann nicht gemessen werden
    End If
    
    
    ''Wert auf LCD ausgeben
    'If Lcdmerker = 1 Then
    'Cls
    'Locate 1 , 1
    'Lcd Kmh ; " KM/h:"
    'Lcdmerker = 0
    'End If
    
    Loop
    
    
    
    
    '-------------------------------------------------------------------------------
    '===============================================================================
    '-------------------------------------------------------------------------------
    'Sprungmarken
    '-------------------------------------------------------------------------------
    '===============================================================================
    '-------------------------------------------------------------------------------
    
    
    '-------------------------------------------------------------------------------
    'ISR für Lichtschranken
    '-------------------------------------------------------------------------------
    Isr0:                                                       'Aufruf bei Lichtschranke 1 per Interrupt
    If Sperre = 0 Then
     Timer1 = 0                                                 'Timer auf 0 setzen
     Sperre = 1                                                 'für Lichtschranke 1 sperren
     Portb = 0                                                  'alle Segmente aus
     Stop Timer0
     End If
     'Print "int0 geht"                                          'nur zum testen
    Return
    
    
    
    Isr1:                                                       'Aufruf bei Lichtschranke 2 per Interrupt
    If Sperre = 1 Then
     Schritte = Timer1                                          'Timerwert übernehmen
     Sperre = 2                                                 'für Lichtschranke 1 UND 2 sperren damit Auto wirklich komplett durchgefahren ist
     Start Timer0
    End If
     'Print "int1 geht"                                          'nur zum testen
    Return
    
    
    
    Errorhandler:                                               'wenn Timer1 überläuft
     Sperre = 0                                                 'nächste Messung freigeben
     'Print "ÜBERLAUF"                                           'nur zum testen
    Return
    
    '-------------------------------------------------------------------------------
    Timer0_isr:                                                 'Timer0-Interruptroutine  (312 x pro Sekunde)
    '-------------------------------------------------------------------------------
      Timer0 = Timervorgabe0
      'If Sperre = 0 Then
      Gosub 7seganzeige                                         'Routine für 7 Segmentanzeige
      'End If
      Return
    
    
    
    
    '-------------------------------------------------------------------------------
    7seganzeige:
    ' Code 7 Segmentanzeige:
    '-------------------------------------------------------------------------------
    
    
    
       'Formatiere das Display
       Wertstr = Str(kmh)
       Fivedigitdisplay = Format(wertstr , "   00")             'Nullen geben die Anzahl der Stellen an, damit die Stellen richtig gesetzt werden
    
    
       ' jeder Lauf durch die Hauptschleife zeigt ein anderes Digit
       Incr Digit
    
       Portb = 0                                                'Ghosting vermeiden
        If Digit = 5 Then                                       'mache das , bis 5 erreicht ist
       Digit = 0
    
       End If
    
       ' addiere 1 zum Digitcounter, weil MID 1-basiert ist
       Y = Digit + 1
       ' und hol das Digit, das wir brauchen
       Wertstr = Mid(fivedigitdisplay , Y , 1)
    
    
       'Anzeige auswählen
       Tempbyte = 2 ^ Digit                                     'Tempbyte = 1,2,4,8,16
    
       'Digitansteuerung auf portC: PC1-5
        Portc = Tempbyte * 2                                    'Umdreh   = 2,4,8,16,32
    
    
    
    
    'Führende Nullen entfernen:
    
    
    
    
     'Dieser Teil erledigt die Wandlung in 7 Segment Code
    
     'Für Anzeigen mit gemeinsamer Anode
      Select Case Wertstr
    
               Case "0" : Portb = 126                           'NULL
               Case "1" : Portb = 12                            'EINS
               Case "2" : Portb = 182                           'ZWEI
               Case "3" : Portb = 158                           'DREI
               Case "4" : Portb = 204                           'VIER
               Case "5" : Portb = 218                           'FÜNF
               Case "6" : Portb = 250                           'SECHS
               Case "7" : Portb = 14                            'SIEBEN
               Case "8" : Portb = 254                           'ACHT
               Case "9" : Portb = 222                           'NEUN
               Case " " : Portb = 0                             'nichts - kein Segment
              'Case Else : Portb = 128                           'mittleres Segment
               Case Else : Portb = 226                          '"F"
      End Select
    
    
    
    
    
      'Komma setzen
      'If Portc = 2 Then Portb.0 = 1                             '4 Kommastellen
      'If Portc = 4 Then Portb.0 = 1                             '3 Kommastellen
      'If Portc = 8 Then Portb.0 = 1                             '2 Kommastellen
      If Portc = 16 Then Portb.0 = 1                            '1 Kommastelle

Berechtigungen

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