- LiTime Speicher und Akkus         
Ergebnis 1 bis 6 von 6

Thema: Probleme mit Timer1

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    21.04.2011
    Beiträge
    24

    Probleme mit Timer1

    Anzeige

    Praxistest und DIY Projekte
    Hi,

    Unser FTS-Projekt nähert sich langsam dem Ende.

    Die induktive Spurführung klappt fast immer, also der Lenkmotor lenkt wenn er soll und auch wieder zurück. Manchmal gibt es aber ein paar Probleme. Mein betreuender Prof meinte ich soll da nen digitalen Tiefpassfilter programmieren... Ähm genau... Mal gucken ob wir das auch anders lösen können.

    Aber irgendwie haut das mit dem Timer nicht so hin. Der Timer1 sollte eigentlich 10 Mal pro Sekunde den Interrupt aufrufen und zum einen überprüfen, ob die beiden induktiven Sensoren sich noch auf der Spur befinden und dann ggf. den Antriebsmotor stoppen wenn sich das FTS außerhalb der Spur befindet. Um zum anderen soll der Infrarotsensor vor dem Fahrzeug abgefragt werden ob sich ein Hindernis in einem bestimmten Abstand vor dem Fahrzeug befindet und den Antriebsmotor anhalten.

    Aber als ich heute das Programm aufgespielt hatte, ging irgendwie gar nichts mehr. Weder die Taste 1 um das Programm zu starten noch der Resetknopf. Und das kam mir schon ziemlich seltsam vor. Hab es dann nochmal ein paar Mal kompiliert und aufgespielt, aber immer das gleiche Problem. Die alte Version ohne Timer ging ohne Probleme.

    Man könnte das sicher auch ohne Timer machen und jeweils ne Funktion schreiben und diese vor jeder Schleife oder auch dazwischen aufrufen. Aber mit Interrupt wäre das ganze natürlich eleganter

    Wo könnte das Problem liegen? Die Werte für den Timer hab ich mir von dem Roboternetz Berechnungstool ausgeben lassen. Der Code für den Timer steht einmal ganz am Anfang und ganz am Ende. Der Rest ist im Prinzip nicht soo interessant da das ja halbwegs läuft.

    Vielen Dank schon mal!


    Code:
    'Hier wird der Timer und der Teiler festgelegt
    Config Timer1 = Timer , Prescale = 64
    
    
    
    'Hier wird das Unterprogramm festgelegt, das
    'in dem von ihnen eingestellten Intervall aufgerufen wird
    On Timer1 Timer_irq
    
    'Diese Vorgabe wurde berechnet um die genaue Intervallfrequenz zu erreichen
    '10 Interrupts pro Sekunde
    Const Timervorgabe = 40536
    
    
    'Hier werden die Timer aktiviert
    Enable Timer1
    Enable Interrupts
    
    
    Declare Sub Fahrt()
    Declare Sub Kalibrierung()
    Declare Sub Lenkung_von_rechts_zur_mitte()
    Declare Sub Lenkung_von_links_zur_mitte()
    
    Declare Function Tastenabfrage() As Byte
    
    
    $regfile = "m32def.dat"
    $framesize = 32
    $swstack = 32
    $hwstack = 32
    
    
    Dim I As Integer
    Dim N As Integer
    Dim Ton As Integer
    
    $crystal = 16000000                                         'Quarzfrequenz
    $baud = 9600
    
    Config Adc = Single , Prescaler = Auto                      'Für Tastenabfrage und Spannungsmessung
    
    Config Pina.7 = Input                                       'Für Tastenabfrage
    Porta.7 = 1                                                 'Pullup Widerstand ein
    
    
    Const Ref = 5 / 1023                                        'Für Batteriespannungsberechnung
    
    Dim Taste As Byte
    Dim Volt As Single
    
    ' Für Motorentest
    'Ports für linken Motor
    Config Pinc.6 = Output                                      'Linker Motor Kanal 1
    Config Pinc.7 = Output                                      'Linker Motor Kanal 2
    Config Pind.4 = Output                                      'Linker Motor PWM
    'Ports für rechten Motor
    Config Pinb.0 = Output                                      'Rechter Motor Kanal 1
    Config Pinb.1 = Output                                      'Rechter Motor Kanal 2
    Config Pind.5 = Output                                      'Rechter Motor PWM
    Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
    Pwm1a = 0
    Pwm1b = 0
    Tccr1b = Tccr1b Or &H02                                     'Prescaler = 8
    
    
    
    
    
    I = 0
    Sound Portd.7 , 400 , 450                                   'BEEP
    Sound Portd.7 , 400 , 800                                   'BEEP
    Sound Portd.7 , 400 , 450                                   'BEEP
    Print
    Print "**** RN-Control 1.4 *****"
    Print "Das neue Experimentier- und Roboterboard"
    Print "Weitere passende Zusatzboards bei www.robotikhardware.de"
    Print
    Do
    
    
    
    
       Taste = Tastenabfrage()
       If Taste <> 0 Then
    
          Select Case Taste
             Case 1
                Call Fahrt
    
    
          End Select
          Sound Portd.7 , 400 , 500                             'BEEP
       End If
    
       Waitms 100
    Loop
    
    End
    
    
    
    
    'Diese Unterfunktion fragt die Tastatur am analogen Port ab
    Function Tastenabfrage() As Byte
    Local Ws As Word
    
       Tastenabfrage = 0
       Ton = 600
       Start Adc
       Ws = Getadc(7)
      ' Print "Tastenabfrage anpassen!ADC Wert ws=" ; Ws
       If Ws < 500 Then
          Select Case Ws
             Case 400 To 450
                Tastenabfrage = 1
                Ton = 550
             Case 330 To 380
                Tastenabfrage = 2
                Ton = 500
             Case 260 To 305
                Tastenabfrage = 3
                Ton = 450
             Case 180 To 220
                Tastenabfrage = 4
                Ton = 400
             Case 90 To 130
                Tastenabfrage = 5
                 Ton = 350
     
          End Select
          Sound Portd.7 , 400 , Ton                             'BEEP
    
       End If
    
    
    
    End Function
    
    
    
    
    
    
    Sub Fahrt()
     'Testprogramm zur induktiven Spurführung
    
    
       Config Porta = Input
    
       Local Links As Word
       Local Rechts As Word
       Local Sensor_lichtschranke As Word
    
    
        Start Adc
    
       'Lenkungskalibrierung
    
       Call Kalibrierung
    
       'Lenkungskalibrierung Ende
    
       Portb.0 = 0                                              'Antrieb ein
       Portb.1 = 1
       Portd.5 = 1
       Pwm1a = 1023
    
          Do
    
    
             Links = Getadc(2)
             Rechts = Getadc(3)
    
    
             If Links < 700 And Rechts >= 700 Then
             '"rechts neben der Spur"
    
                Do
    
                Links = Getadc(2)
                Rechts = Getadc(3)
    
                Portc.6 = 1                                     'bestimmt Richtung  0,1 Gegen Uhrzeiger (Rechtsdrehung)
                Portc.7 = 0
                Portd.4 = 1
    
                Pwm1b = 1023
    
             Loop Until Links < 700 And Rechts < 700
             'Mitte
             Pwm1b = 0
    
             'Drehung von rechts zur Mitte
             Call Lenkung_von_rechts_zur_mitte
    
    
    
           '***************************
    
             Links = Getadc(2)
             Rechts = Getadc(3)
    
             Elseif Links >= 700 And Rechts < 700 Then
             '"links neben der Spur"
    
                Do
    
                   Links = Getadc(2)
                   Rechts = Getadc(3)
                   Portc.6 = 0                                  'bestimmt Richtung  0,1 Gegen Uhrzeiger (Rechtsdrehung)
                   Portc.7 = 1
                   Portd.4 = 1
    
                   Pwm1b = 1023
    
                Loop Until Links < 700 And Rechts < 700
             'Mitte
             Pwm1b = 0
    
             'Drehung von links zur Mitte
             Call Lenkung_von_links_zur_mitte
    
             End If
    
    
          Loop
    
    
    
    End Sub
    
    Sub Kalibrierung()
    'Programm zur Kalibrierung der Lenkung in Mittelstellung
     Local Sensor_lichtschranke As Word
    
          Portc.6 = 1                                           'bestimmt Richtung  0,1 Gegen Uhrzeiger (Rechtsdrehung)
          Portc.7 = 0
          Portd.4 = 1
    
          Wait 3
    
          Pwm1b = 0
    
          Portc.6 = 0                                           'bestimmt Richtung  0,1 Gegen Uhrzeiger (Rechtsdrehung)
          Portc.7 = 1
          Portd.4 = 1
    
          Do
             Sensor_lichtschranke = Getadc(4)
             Pwm1b = 1023
          Loop Until Sensor_lichtschranke < 800
    
          Pwm1b = 0
    
    End Sub
    
    
    
    Sub Lenkung_von_rechts_zur_mitte()
    'Programm zur Drehung des Lenkmotors von rechts zur Mitte
     Local Sensor_lichtschranke As Word
          Portc.6 = 0                                           'bestimmt Richtung  0,1 Gegen Uhrzeiger (Rechtsdrehung)
          Portc.7 = 1
          Portd.4 = 1
    
          Do
             Sensor_lichtschranke = Getadc(4)
             Pwm1b = 1023
          Loop Until Sensor_lichtschranke < 800
    
          Pwm1b = 0
    
    End Sub
    
    Sub Lenkung_von_links_zur_mitte()
    'Programm zur Drehung des Lenkmotors von links zur Mitte
    Local Sensor_lichtschranke As Word
    
          Portc.6 = 1                                           'bestimmt Richtung  0,1 Gegen Uhrzeiger (Rechtsdrehung)
          Portc.7 = 0
          Portd.4 = 1
    
          Do
             Sensor_lichtschranke = Getadc(4)
             Pwm1b = 1023
          Loop Until Sensor_lichtschranke < 800
    
          Pwm1b = 0
    
    End Sub
    
    'Timer
    Timer_irq:
      Timer1 = Timervorgabe
    
    'Hier könnte nun ihre beliebige IRQ-Routine stehen
    'Dabei sollte man darauf achten das diese nicht mehr Zeit
    'benötigt, als das Intervall zuläßt
    
       Dim Links As Word
       Dim Rechts As Word
       Dim Ifr As Word
    
    
        Links = Getadc(2)
        Rechts = Getadc(3)
    
         If Links >= 700 And Rechts >= 700 Then
                'Außerhalb Der Spur
                 Portd.5 = 0
                Pwm1a = 0
            Else
                 Portd.5 = 1
                Pwm1a = 1023
         End If
    
         'Infrarotsensor Abfrage
        Ifr = Getadc(0)
        Ifr = Ifr / 4
    
         If Ifr >= 128 Then
                Portd.5 = 0
                Pwm1a = 0
            Else
                Portd.5 = 1
                Pwm1a = 1023
    
         End If
    
       Return

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.702
    Blog-Einträge
    133
    Hallo,
    ich blick da nicht ganz durch, jedoch sind mir zwei Dinge aufgefallen.

    1. Am Anfang setzt Du den Prescaler für Timer1 auf 64. Später wird er durch "Tccr1b = Tccr1b Or &H02" auf 8 geändert
    2. Die Timervorgabe wird in der ISR gesetzt. Ungewöhnlich und beabsichtigt? Funktioniert das? Würd ich irgendwo bei der Initialisierung machen.

    PS: Die $ Compiler Direktiven würd ich auch an den Anfang setzen, um es dem Compiler leichter zu machen

    EDIT Zwei Zeilen über der TCCR1B zuweisung wird der Timer1 nochmal auf Phase Correct PWM konfiguriert. Denke, das da noch eine Überarbeitung nötig ist

    Gruß
    Searcher
    Geändert von Searcher (27.06.2011 um 20:06 Uhr)
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    21.04.2011
    Beiträge
    24
    Hi Searcher,

    Danke für die Hinweise!
    Ja ich weiß, ich hätte mal noch ein paar mehr Kommentare in den Code schreiben sollen, damit klarer wird was da überhaupt passiert :-/

    Das Bild des FTS in dem verlinkten Post auf der 2. Seite ist zwar nicht mehr ganz aktuell da dort weder die Sensorik für die Lenkachse noch die Sensorik für die Spurführung eingebaut ist, aber für die Erklärung dürfte es aureichen.

    Also kurz zum Programm: Vorne am FTS ist ein IFR-Sensor. Der hängt am Port 0. Dann gibts für die Spurführung zwei nebeneinder befindliche Spulen, die sich unter dem Fahrzeug befinden und einen Kupferdraht abtasten, auf dem ein Impuls läuft. Sie hängen am Port 2 und 3 und heißen im Programm Links und Rechts, bzw werden die analogen Werte unter diesen Variablennamen abgespeichert. Sind beide Spulen direkt über dem Draht, wird eine bestimmte Spannung von jedem Sensor ausgegeben die einem analogen Wert von so 400 bis 600 entspricht. Ist ein Sensor auserhalb des Drahtes, wird ein analoger Wert von 777 ausgegeben. Also wenn z.b. der linke Sensor 600 und der rechte Sensor 777 zeigt, weiß das Programm, dass das FTS rechts von der Spur ist und lenkt entsprechend.

    Um dann wieder für die Geradeausfahrt die Mittelstellung der Lenkachse zu finden haben wir ne Lichtschranke an Port 4, die sich direkt über dem roten Zahnrad der Lenkachse befindet. Die zeigt eine Spannung an wenn das rote Zahnrad nicht in der Mitte ist und keine Spannung, wenn es in der Mitte ist. Deswegen das "Loop Until Sensor_lichtschranke < 800". Wir haben auch noch nen Poti an der Lenkachse, um nen bestimmten Lenkwinkel zu erreichen, aber der wird im Moment nicht benutzt. Die Spurfolgung hat auch so ganz gut geklappt.

    Zu 1.: Ah okay, ist mir gar nicht aufgefallen. Ich hatte das Programm ursprünglich aus dem RN-Control Testprogramm gebastelt. Kann ich die Zeile mit dem "Tccr1b" dann einfach weglassen? Oder braucht man das?
    Zu 2.: Den Quellcode für die Timevorgabe hab ich direkt vom Programm rnAVR von roboternetz.de übernommen, das mir auch die Werte für den Prescaler und die Timevorgabe gegeben hat. Ich weiß nicht wie alt das Programm ist und ob es fehlerfreien Quellcode erzeug, hab es über die Suchfunktion gefunden. Ich kenn mich mit Interrupts leider gar nicht aus und hab das am Wochenende mal in nem Buch bzw im RN-Wiki nachgelesen. Also ob es funktioniert kann ich nicht genau sagen, da sich mit dem Timer gar nichts mehr getan hat.

    Kann es vielleicht auch sein dass der Quellcode im ISR zu lang ist und der Prozessor es gar nicht schafft den 10 Mal pro Sekunde abzuarbeiten und es deswegen Probleme gibt, sprich er noch gar nicht fertig ist ihn abzuarbeiten, ihn aber erneut aufrufen will? Ich hab auch irgendwo mal gelesen dass man da eigentlich keine allzu langen Befehle reinschreiben sollte. Eigentlich würde es auch reichen wenn er nur ein Interrupt pro Sekunde hat.

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.702
    Blog-Einträge
    133
    Hallo,

    Den Quellcode für die Timevorgabe hab ich direkt vom Programm rnAVR von roboternetz.de übernommen, das mir auch die Werte für den Prescaler und die Timevorgabe gegeben hat
    Hab ich nicht überprüft; wird aber OK sein.

    Denke, daß das eigentlich Problem ist, das Du den Timer1 für deinen Timerinterrupt benutzen willst. Ich hatte in meiner ersten Antwort noch ein EDIT hinzugefügt. Der Timer1 wird wohl auch noch für Motor PWM gebraucht.

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    21.04.2011
    Beiträge
    24
    Ah Danke!

    Oh, das ist natürlich blöd mit dem PWM. Daran will ich lieber nicht rumfummeln.
    Hm dann werd ich das am besten mal überarbeiten und einfach Timer0 für den Interrupt benutzen, auch wenn dort das niedrigste 61 Interrupts pro Sekunde sind.

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.702
    Blog-Einträge
    133
    Hi,
    Kann es vielleicht auch sein dass der Quellcode im ISR zu lang ist und der Prozessor es gar nicht schafft den 10 Mal pro Sekunde abzuarbeiten
    Bin selbst (noch?) kein Bascom Freak und deshalb sollten meine Aussagen besser bestätigt werden:

    In der ISR wird wohl die meiste Zeit mit den GETADC verbraten werden. Der ADC ist mit Prescale=Auto konfiguriert. Hab das mal im Simulator nachgeschaut. Bascom macht daraus einen ADC Takt von 125000Hz. Für eine Single Conversion werden 13 ADC-Takte gebraucht also ca 104µs. Nun schätze ich ganz grob, daß die Abarbeitung der ISR sicher unter 1ms bleibt.

    Abgesehen davon bin ich selbst mit dem Bascom Kommando GETADC in einer ISR nicht glücklich geworden. Bin gespannt auf Deine Erfahrung.

    Wenn Dir 60 Mal pro Sekunde mit Timer0 zu schnell ist, könnte man einen Zähler in der ISR hochzählen lassen und nur jedes sechstes Mal die komplette Routine durchlaufen lassen. Dann hat man zwar auch 60 Interrupts, wobei aber nur bei 10 pro Sekunde viel Zeit verbraucht wird.

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

Ähnliche Themen

  1. Probleme mit ATTiny25 und Timer1
    Von Henry im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 26.11.2009, 21:24
  2. Timer1- Probleme mit timer Startwert
    Von C2H6O im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 14.11.2009, 00:07
  3. Timer1 bei ATTiny45 Probleme
    Von ScorpionXIII im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 8
    Letzter Beitrag: 08.11.2007, 16:53
  4. Timer1 Uhr
    Von orph im Forum PIC Controller
    Antworten: 9
    Letzter Beitrag: 16.09.2006, 16:44
  5. Probleme Mega16 Timer1 Interrupt
    Von skyrider im Forum AVR Hardwarethemen
    Antworten: 0
    Letzter Beitrag: 16.04.2005, 15:49

Berechtigungen

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

LiFePO4 Speicher Test