- 12V Akku mit 280 Ah bauen         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: timer0 hört auf zu zählen...

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    25.09.2004
    Alter
    34
    Beiträge
    54

    timer0 hört auf zu zählen...

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo allerseits,
    ich hab ein kleines problemchen mit meinem code. mein robby hat vorne 3 taster un soll bei kollision erst ein stück zurückfahren, sich dann um ca. 90 grad (bei kollision am mittleren taster etwas mehr) drehen und dann weiterfahren. Dass das drücken eines anderen tasters bei dem ausweichvorgang auch wahrgenommen werden kann, hab ich versucht, das ganze mit timer0 zu ralisieren, was auch eigentlich ganz gut funktioniert.
    Jetzt aber zum problem: es kommt von zeit zu zeit vor, dass sich der controller einfach "neu startet" also wieder von ganz am anfang anfängt. das kann allerdings nicht an den timern liegen, da ich dieses problem auch schon mit einem anderen code hatte. und ein neues problem ist dazugekommen: es kommt vor, dass der timer auf einmal aufhört zu zählen (an unterschiedlichen werten vom zaehler).Beide motoren drehen sich dann endlos rückwärts, bis man den strom aus und wieder einschaltet. könnte es enventuell daran liegen, dass ich keine diode vor den relais habe, die den motor schalten? oder liegts an was ganz anderem?
    mfg Markus

    Code:
    $regfile = "2313def.dat"
    $crystal = 3686400
    $baud = 9600
    
    Dim Zaehler As Byte
    
    Ddrd.2 = 1                                                  'motor links vorwärts
    Ddrd.3 = 1                                                  'motor links rückwärts
    Ddrd.4 = 1                                                  'motor rechts vorwärts
    Ddrd.5 = 1                                                  'motor rechts rückwärts
    Ddrb.0 = 0                                                  'taster links vorne
    Ddrb.1 = 0                                                  'taster mitte vorne
    Ddrb.2 = 0                                                  'taster rechts vorne
    Portb.0 = 1
    Portb.1 = 1
    Portb.2 = 1
    
    Mlinksvor Alias Portd.2
    Mlinksrueck Alias Portd.3
    Mrechtsvor Alias Portd.4
    Mrechtsrueck Alias Portd.5
    
    Schalterlinks Alias Pinb.0
    Schaltermitte Alias Pinb.1
    Schalterrechts Alias Pinb.2
    
    Config Timer0 = Timer , Prescale = 1024
    Enable Timer0
    Start Timer0
    Enable Interrupts
    On Timer0 Ontimer
    
    
    Main:
    Mlinksvor = 1
    Mlinksrueck = 0
    Mrechtsvor = 1
    Mrechtsrueck = 0
    If Schalterlinks = 0 Then
    Zaehler = 0
    Gosub Links
    End If
    If Schaltermitte = 0 Then
    Zaehler = 0
    Gosub Mitte
    End If
    If Schalterrechts = 0 Then
    Zaehler = 0
    Gosub Rechts
    End If
    Goto Main
    
    Links:
    
    If Schaltermitte = 0 Then
    Zaehler = 0
    Gosub Mitte
    End If
    If Schalterrechts = 0 Then
    Zaehler = 0
    Gosub Rechts
    End If
    
    If Zaehler < 33 Then
    Mlinksvor = 0
    Mlinksrueck = 1
    Mrechtsvor = 0
    Mrechtsrueck = 1
    End If
    If Zaehler > 33 Or Zaehler = 33 Then
    Mlinksvor = 1
    Mlinksrueck = 0
    Mrechtsvor = 0
    Mrechtsrueck = 1
    End If
    If Zaehler = 83 Then
    Gosub Main
    End If
    Goto Links
    
    Mitte:
    
    If Schalterlinks = 0 Then
    Zaehler = 0
    Gosub Links
    End If
    If Schalterrechts = 0 Then
    Zaehler = 0
    Gosub Rechts
    End If
    
    If Zaehler < 33 Then
    Mlinksvor = 0
    Mlinksrueck = 1
    Mrechtsvor = 0
    Mrechtsrueck = 1
    End If
    If Zaehler > 33 Or Zaehler = 33 Then
    Mlinksvor = 1
    Mlinksrueck = 0
    Mrechtsvor = 0
    Mrechtsrueck = 1
    End If
    If Zaehler = 101 Then
    Gosub Main
    End If
    Goto Mitte
    
    Rechts:
    
    If Schalterlinks = 0 Then
    Zaehler = 0
    Gosub Links
    End If
    If Schaltermitte = 0 Then
    Zaehler = 0
    Gosub Mitte
    End If
    
    If Zaehler < 33 Then
    Mlinksvor = 0
    Mlinksrueck = 1
    Mrechtsvor = 0
    Mrechtsrueck = 1
    End If
    If Zaehler > 33 Or Zaehler = 33 Then
    Mlinksvor = 0
    Mlinksrueck = 1
    Mrechtsvor = 1
    Mrechtsrueck = 0
    End If
    If Zaehler = 83 Then
    Gosub Main
    End If
    Goto Rechts
    
    Ontimer:
    Incr Zaehler
    Print Zaehler
    Return

  2. #2
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.842
    Bitte, Kollege, du mußt deine "GOTO" und "GOSUB" kreuz und quer ein wenig zusammenräumen, bevor das noch wer sieht und tot umfällt.

    Bei dir kommt vor:
    Main:
    ....
    Gosub Links
    ..
    Innerhalb von "Links" steht u.A.
    ...
    If Zaehler = 83 Then
    Gosub Main
    End If
    Goto Links

    Irgendwann haut der COntroller den Stack weg und fängt von vorne wieder an, is ja auch nur ein Mensch
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    25.09.2004
    Alter
    34
    Beiträge
    54
    so...ich hab jetzt alle "gosub" durch "goto" ersetzt und jetzt scheint es stabiel zu laufen (auch wenn mir der unterschied zwischen den beiden nicht klar ist...werd wohl nochmal googlen).
    wenn der controller allerdings, wie du gesagt hast, von vorne wieder anfängt, dann sollte doch der timer trotzdem wieder laufen oder?
    mfg Markus

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.02.2005
    Beiträge
    175
    Hallo Markus

    Bei "Gosub" erwartet der Controller irgendwann ein "Return" - also speichert er die Rücksprungadresse.
    Da kannst Du Dir jetzt leicht ausrechnen, was bei verschachtelten Gosubs passiert...

    Anders bei "Goto" - da hüpft er hin und hat fertig!

    Eine gute und elegante Möglichkeit für Auswahlabfragen bietet auch der "Case"-Befehl. Ist auch wesentlich übersichtlicher als verschachtelte Goto´s und Gosub´s!

    Viele Grüße

    Torsten

  5. #5
    Benutzer Stammmitglied
    Registriert seit
    14.09.2005
    Alter
    68
    Beiträge
    77
    Das ist ein typisches Beispiel für das was wir Früher Spaghettiprogramme genannt haben. Und durch solch ein Programmierstiel ist schon so mancher Rechner abgestürzt.

    Vorsichtshalber kann man einen WATCHDOG einbauen. Bei deinem Programm würde der auf jeden Fall nicht arbeitslos.

    Du hast das Problem jetzt gelöst in dem du GOTOs benutzt. Aber in Wirklichkeit ist das keine Lösung, besser währe es, du würdest dich mal mit strukturierter Programmierung beschäftigen. Dann braust nur noch GOSUBs. Vielleicht in seltenen Fällen noch ein GOTO.

    Sicher wirst du dich jetzt fragen warum soll ich den GOSUB benutzten, wenn es mit GOTO doch besser klappt.

    Die Anwort ist sehr einfach. In einem etwas größerem Programm wirst du dich mit vielen GOTOs nach einer Zeit selber nicht mehr zurecht finden wenn du da mal einen Änderung machen mußt, ganz davon zu schweigen wenn ein andrer da einen Änderung machen soll.

    Meinem Rat, gewöhne dir einen sauberen Programmierstiel an, sonst wirst du noch eines Tages an deinem eigenen Programm verzweifeln.

    MFG
    Guy

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    25.09.2004
    Alter
    34
    Beiträge
    54
    Hallo Guy.
    Auch wenn die sache mit GOTO angeblich ein unsaubererprogrammierstiel ist, so erscheint es mir doch deutlich einfacher und überlichtlicher. Bei GOSUBs braucht man ja, wie Torsten_G oben geschrieben hat, irgendwann einen RETURN befehl, was bei GOTO wegfällt. So kann es doch bei einem größeren programm (mit mehreren Subs) durch den GOSUB befehl leichter zu komplikationen kommen.
    Da ich mich aber natürlich trotzdem um einen sauberen programmierstiel bemühen will, wäre es nett, wenn jemand eine seite wüsste, wo ein paar tipps zum sauberen programmieren zusammengefasst sind.
    mfg Markus

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    14.09.2005
    Alter
    68
    Beiträge
    77
    Zitat Zitat von Grillmeister Markus
    Auch wenn die sache mit GOTO angeblich ein unsaubererprogrammierstiel ist, so erscheint es mir doch deutlich einfacher und überlichtlicher.
    Hallo

    Einfacher schon, aber nicht übersichtlicher. Und einfacher auch nur bei sehr kleinen Programme und weil du den Stack nicht überflutest.

    Du hast zum Beispiel einen (On Timer0 Ontimer) in deinem Programme, wenn du jetzt in der Ontimer Routine einen GOTO rein setzt wirst du wieder einen Stacküberlauf haben, weil bei einem Interrupt Automatisch die Rücksprungadresse auf den Stack abgelegt wird, und sie so nie gelöscht wird.

    Im Grund ist es so. du sollst ein Hauptprogramm haben was in einer Schleife läuft, in dem Hauptprogramme reagierst du auf verschiedene Ereignisse wie zum Beispiel Tassendruck, dann rufst eine Unterroutine auf die diese Arbeit erledigt dann springst du wieder in die Hauptroutine zurück. So das dein Programm aus einem Mainprogramm besteht, und viele kleinen Unterprogramme.

    Du kannst auch aus einem Unterprogramm ein andres Unterprogramm aufrufen, aber immer wieder dahin zurück springen wo du herkommst.

    Was du auch vermeiden sollst ist, aus einem aufgerufenen Unterprogramm das aufrufende Unterprogramm aufrufen. Weil du dich dann in eine Endlosschleife begeben kannst die nie endet.

    So kannst du dein Programm Ablauf sehr einfach verfolgen und schnell Fehler entdecken. Mit GOTO Ist das nicht so einfach. Wenn du zum Beispiel eine Variable hast die an einer bestimmten Stelle einen falschen Wehrt hat, und du dann feststellen sollst wo der her kommt ist das nicht mehr so einfach, weil du eben hin und her springst.

    Ich habe dir mal dein Programm so umgeändert wie es aussehen sollte. Du kannst es nicht so einsetzen, es soll lediglich das Prinzip verdeutlichen.


    Code:
    $regfile = "2313def.dat"
    $crystal = 3686400
    $baud = 9600
    
    Dim Zaehler As Byte
    
    Ddrd.2 = 1                                                  'motor links vorwärts
    Ddrd.3 = 1                                                  'motor links rückwärts
    Ddrd.4 = 1                                                  'motor rechts vorwärts
    Ddrd.5 = 1                                                  'motor rechts rückwärts
    Ddrb.0 = 0                                                  'taster links vorne
    Ddrb.1 = 0                                                  'taster mitte vorne
    Ddrb.2 = 0                                                  'taster rechts vorne
    Portb.0 = 1
    Portb.1 = 1
    Portb.2 = 1
    
    Mlinksvor Alias Portd.2
    Mlinksrueck Alias Portd.3
    Mrechtsvor Alias Portd.4
    Mrechtsrueck Alias Portd.5
    
    Schalterlinks Alias Pinb.0
    Schaltermitte Alias Pinb.1
    Schalterrechts Alias Pinb.2
    
    Config Timer0 = Timer , Prescale = 1024
    Enable Timer0
    Start Timer0
    Enable Interrupts
    On Timer0 Ontimer
    
    ''Main:
    
    Do
       Mlinksvor = 1
       Mlinksrueck = 0
       Mrechtsvor = 1
       Mrechtsrueck = 0
       If Schalterlinks = 0 Then
          Zaehler = 0
          Gosub Links
       End If
       If Schaltermitte = 0 Then
          Zaehler = 0
          Gosub Mitte
       End If
       If Schalterrechts = 0 Then
          Zaehler = 0
          Gosub Rechts
       End If
    Loop
    
    Links:
    Do
    If Zaehler => 33 Then
       Mlinksvor = 1
       Mlinksrueck = 0
       Mrechtsvor = 0
       Mrechtsrueck = 1
    Else
       Mlinksvor = 0
       Mlinksrueck = 1
       Mrechtsvor = 0
       Mrechtsrueck = 1
    End If
    
    If Zaehler = 83 Then
       Return
    End If
    Loop
    
    Mitte:
    Do
    If Zaehler => 33 Then
       Mlinksvor = 1
       Mlinksrueck = 0
       Mrechtsvor = 0
       Mrechtsrueck = 1
    Else
       Mlinksvor = 0
       Mlinksrueck = 1
       Mrechtsvor = 0
       Mrechtsrueck = 1
    End If
    If Zaehler = 101 Then
       Return
    End If
    Loop
    
    Rechts:
    Do
    If Zaehler => 33 Then
       Mlinksvor = 0
       Mlinksrueck = 1
       Mrechtsvor = 1
       Mrechtsrueck = 0
    Else
       Mlinksvor = 0
       Mlinksrueck = 1
       Mrechtsvor = 0
       Mrechtsrueck = 1
    End If
    If Zaehler = 83 Then
       Return
    End If
    Loop
    
    Ontimer:
    Incr Zaehler
    Print Zaehler
    Return
    Schau dir auch mal an wie ich aus deinen Zwei (If Zaehler > 33 Or Zaehler = 33 Then If Zaehler < 33 Then ) eine mit ELSE gemacht habe. Die ist viel übersichtlicher, und zudem im Prinzip auch noch schneller.

    Ein andrer Grund ist, dass es in andren Sprachen keinen GOTO gibt. Wenn du dir den GOTO zu sehr angewöhnst wirst du beim umsteigen auf eine andere Sprache viel Schwierigkeiten haben.

    Für den Anfang würde ich dir raten mit einem Flußdiagramme zuarbeiten Googel mal nach Flußdiagramme. Eine andre und bessere Möglichkeit ist mit einem Struktogramme, aber das ist ein wenig schwieriger. Und erst wenn dein Programm im Flußdiagramme funktioniert solltest du anfangen den Code zuschreiben.

    So ich hoffe ich konnte dir ein wenig weiter helfen, und noch viel Spaß beim Progen.

    mfg
    Guy

  8. #8
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.842
    ...dir raten mit einem Flußdiagramm...
    Das ist ja grad das böse. Gerade Flußdiagramme verleiten zu unstrukturierten Monstrositäten, ganz einfach, weil sie es zulassen.
    Ganz einfach: Jeder, der "goto" reinschreibt, gibt jedesmal 5 € in die Kaffee-Kassa
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    14.09.2005
    Alter
    68
    Beiträge
    77
    Ja schon, Ich finde es für einen Anfänger aber einfacher, und allemal besser als gleich den Code zuschreiben.

    Ich bin auch nicht der Meinung, daß man den GOTO gar nicht benutzen soll, man sollte ihn nur sehr bewußt einsetzen und ihn dann gut kommentieren.

  10. #10
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    25.02.2005
    Beiträge
    175
    Gefährlich sind pikante Mischungen aus "goto" und "gosub", vor allem noch im Zusammenhang mit Interrupts.

    Wenn man in einer Subroutine ist, sollte man nicht mit einem Goto wieder aussteigen, weil eben sonst die Rücksprungadresse auf ewig gepeichert bleibt, irgendwann braucht jedes "Gosub" sein "Return"!

    Kleine Grundregel:
    Kein "Goto" in Subroutinen, dessen Ziel außerhalb der Routine liegt...

    Grüße

    Torsten

    @PicNick:
    Bild hier  

    \/ \/ \/

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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

Labornetzteil AliExpress