-         

Ergebnis 1 bis 6 von 6

Thema: Toggle Problem

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    17.03.2007
    Beiträge
    6

    Toggle Problem

    Anzeige

    Hallo,

    ich möchte dass beim 5. Impuls am Portb.1, der Ausgang Portc.1 auf 1 geht.
    Wie programmiert man sowas am besten?
    Ich habe schon einiges versucht, aber es funktioniert nicht.
    Ist eine Toggle-Abfrage am Eingang überhaupt möglich und wie?

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.09.2004
    Ort
    Düsseldorf
    Beiträge
    3.948
    Für dein Problem gibt es eine Menge Lösungen.

    Du kannst zb. die Flanken manuell oder mit Interrupt (Pinchange) detektieren,Zählen und dann beim 5. Mal deinen Ausgang zu setzen.
    Gruß
    Ratber

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    17.03.2007
    Beiträge
    6
    ja, manuell mit Flanken hört sich gut an , aber wie müßte das Programm konktret aussehen, bräuchte da mal ein Beispiel

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.09.2004
    Ort
    Düsseldorf
    Beiträge
    3.948
    Ja,woher kommen die Impulse ?
    Taste oder ein sauberes Signal ?

    Für ne Taste reicht dieser Codeschnipsel aus

    Code:
    Do              'Hauptschleife
    Debounce Pinb.1 , 1 , Taste , Sub
    Loop
    
    Taste:
    Incr X
    If x >= 5 then Set Portc.1
    Return

    Bei einem anderen Signal würde das prinzipiell auch reichen aber wenn das sehr kurz ist dann muß das Programm schnell reagieren können und ein Poll würde evtl. nicht mehr reichen.(Mit Config Debounce ist da noch einwenig rauszuholen)
    Da wäre ein Interruptbetrieb sinvoller.
    Das geht natürlich nur wenn der Controller auch einen Externen Int besitzt.

    Also zb. so:

    Code:
    Config Int0 = Rising
    On Int0 Taste
    Enable Interrupts
    
    Do              'Hauptschleife
    
    Loop
    
    Taste:
    Incr X
    If x >= 5 then Set Portc.1
    Return
    Natürlich ist es nicht fein in einer Interruptroutine groß herumzurechnen.
    Der Grund ist das es Zeit kostet (LCD oder Serielle Ausgaben sind besonders Tödlich) und in dieser Zeit ein Weiteres Ereignis verloren gehen kann bzw. sich so mehrere Interrupts verschachteln können und dann der Stack überläuft usw. usw.
    Deswegen gilt für Int. "Halte dich kurz"
    Man kann also nur ein Flag setzen und die Abfrage dann woanders hinsetzen.


    Zb. So

    Code:
    Config Int0 = Rising
    On Int0 Taste
    Enable Interrupts
    
    Do              'Hauptschleife
    If x >= 5 then Set Portc.1
    Loop
    
    Taste:
    Incr X
    Return
    So,das reicht ja wohl erstmal zum Spielen.
    Gruß
    Ratber

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    17.03.2007
    Beiträge
    6
    ja, das war erst mal sehr hilfreich.
    Die Impulse kommen von einem Encoder eines Motors, der 15 Impulse pro Sekunde gibt, von daher muß die Verarbeitung doch sehr schnell gehen.
    Ich möchte einfach nur die Impulse zählen, um sie dann abfragen zu können.
    Das erste Beispiel funktioniert zwar, aber irgendwie nicht auf Flanken und nicht für diese Impulsgeschwindigkeit.

    Die Beispiele mit den Interupts habe ich nicht zum laufen bekommen, da scheint noch was zu fehlen, oder?

    Ich benutze den Atmega 16, wie ist das denn überhaupt mit den Interupts, ist der Int0 einem bestimmten Pin zugeordnet?

    Kann man eine Flankenauswertung auch ohne Interupts machen?

    Hier das Programm das nicht funktioniert:


    Code:
    $regfile = "m16def.dat"
    $framesize = 32
    $swstack = 32
    $hwstack = 32
    $crystal = 8000000
    
     Dim X As Byte
    
     Config Portc.1 = Output
    
    Config Int0 = Rising
    On Int0 Taste
    Enable Interrupts
    
    Do              'Hauptschleife
    If X >= 5 Then Set Portc.1
    Loop
    
    Taste:
    Incr X
    Return

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.09.2004
    Ort
    Düsseldorf
    Beiträge
    3.948
    Die Impulse kommen von einem Encoder eines Motors, der 15 Impulse pro Sekunde gibt, von daher muß die Verarbeitung doch sehr schnell gehen.
    Das ginge noch locker "Zufuß" aber dann muß man ganz genau auf die Programmlaufzeiten achten das auch alle Impulse mitbekommen werden.


    Ich möchte einfach nur die Impulse zählen, um sie dann abfragen zu können.
    Ja,entweder im Programm zählen oder per Timer als Zähler (Läuft unabhängig)


    Das erste Beispiel funktioniert zwar, aber irgendwie nicht auf Flanken und nicht für diese Impulsgeschwindigkeit.
    Doch das reagiert auf Steigende Flanken.
    Sollte so funktionieren.
    Bei 15 Hz sind das 66ms pro Puls.
    Debounce ist standardmässig auf 20ms eingestellt.
    Sollte also so gradenoch gehen.
    Wenn das Signal nicht "Prellt" (Dafür ist Debounce ja eigentlich da) kannst du die Zeit auf 1 setzen.
    Wie gesagt,mit Int ist es wesentlich eleganter.



    Ich benutze den Atmega 16, wie ist das denn überhaupt mit den Interupts, ist der Int0 einem bestimmten Pin zugeordnet?
    Ja,so isses.
    Beim M16 ist Int0 auf Pin D.2
    Steht aber alles im Datenblatt


    Kann man eine Flankenauswertung auch ohne Interupts machen?
    Ja,ganz zufuß mit Merkern für den derzeitigen Zustand und ständige Abfragen.
    Das ist aber völlige Verschwendung von Resourcen.
    Ich nehme mal an dein Controller soll ausser Impulse zählen noch was anderes machen.
    Da wirst du bald das Problem bekommen das du vieleicht Impulse verpast weil gerade was anderes gemacht wird.
    Da müßtest du schon sehr vorsichtig und umständlich Programieren.
    Mit Int oder Timer-Zähler ist es sooooo kinderleicht.

    Hier das Programm das nicht funktioniert:
    Ja,mein Fehler und auch deiner.

    Da fehlt noch "Enable int0" von mir.
    Und du hast einen fehler bei der Port-/Pindefinition gemacht.

    Mit "Config Portx Input/Output/X/&bxxxxxxxx" wird immer der gesammte Port configuriert.
    Einzelne Pinne werden mit "Config Pinx.y = Input/Output" konfiguriert.



    Hier,ich habs mal etwas umgeschrieben.

    Code:
    $regfile = "m16def.dat"
    $framesize = 32
    $swstack = 32
    $hwstack = 32
    $crystal = 8000000
    
     Dim X As Byte
    
     Config Pinc.1 = Output
     Config Pind.2 = Input
    
    Config Int0 = Rising
    On Int0 Taste
    Enable Int0
    Enable Interrupts
    
    Do              'Hauptschleife
     If X >= 5 Then
      Toggle Portc.1
      X = 0
      End If
    Loop
    
    Taste:
     Incr X
    Return
    Bei jeder steigenden Flanke wird x um eins erhöht.
    Bei X=5 wird Pin C.1 umgeschaltet (Toggle) und x wieder auf 0 gesetzt.
    Eine LED am Pin C.1 sollte bei deinen 15 Hz vom Geber mit ca. 2.5Hz blinken.
    So kannst du besser sehen ob das Signal auch wirklich ankommt.
    Bei der Konfiguration des Int0 kannst du ja mal mit Rising/Falling/Change probieren.


    Wie gesagt beim M16 ist der Int0 auf Pin D.2 (Und Int1 auf D.3. Mehr hat er nicht)
    Mit anderen gehts nicht.

    Nochwas:

    Auch wenn beim AVR alle freien Pinne beim einschalten auf "Eingang" mit aktiviertem Pullup stehen solltest du die genutzten Portpinne dennoch configurieren.

    Die Zeile "Config Pind.2 = Input" sollte also trotzdem da stehen.

    Einen hab ich noch:

    Da ja wie gesagt die internen Pullups standardmäßig aktiviert sind bringen nach Vcc geschaltete Signale ohne "Pulldown" natürlich kein brauchbares Signal.
    Ein 1-10K Widerstand von Pin D.2 nach Masse bringt da abhilfe wenn der Geber es nicht anders kann.

    LEs dir mal die Befehlsreferenz durch und experimentier damit.
    Damit lernt mal viel.
    Gruß
    Ratber

Berechtigungen

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