Archiv verlassen und diese Seite im Standarddesign anzeigen : ENCODER Befehl zu langsam
Dr.Ice2000
20.08.2006, 01:54
Hallo,
ich habe versucht den Encoder Befehl praktisch wie in der Hilfe angegeben zu benutzen. Das funktioniert auch ganz ausgezeichnet wenn ich wirklich langsam drehe, sobald ich etwas schneller werde wird nur noch ab und zu etwas gezählt.
Gibt es eine Möglichkeit den Befehl mit einem Interrupt zu nutzen ?
Ich habe schon andere Vorschläge hier aus dem Forum versucht, aber die bringen nicht so gute Resultate wie der Bascom Befehl.
Ach so, ich nutze einen ATMega32 und einen Schrittmotor mit einem LM393 als Drehgeber.
Beste Grüße
Markus
Das Voll-dekodieren ist, wenn's schneller geht, ein absoluter Full-Time-Job. Du mußt mal ausrechnen, wieviel Impulse du nun tatsächlich brauchst und dann sehen, ob sich das überhaupt ausgehen KANN.
Der Code von Bascom ist ja eigentlich nicht sehr lang.
https://www.roboternetz.de/wissen/index.php/Bascom_Inside-Code#.28Quadratur-.29_ENCODER
Beim Interrupt isses ja auch nicht so, daß auf einmal ein Wunder geschieht. Die Minimallösung wäre, von jedem Encoder ein Signal auf INT0
bzw INT1 zu legen, und im Interrupt das andere Signal zu checken, ob's rauf oder runter geht.
Rechne wirklich mal nach, was für Erfordernisse du tatsächlich hast.
Dr.Ice2000
20.08.2006, 14:51
Danke erst einmal für die Antwort Robert !
Ich drehe das Ding von Hand und über den LM393 liefert der Stepper den ich als Encoder "missbrauche" nur 12 Impulse pro Umdrehung.
Das ganze soll als Eingabe in einem DDS Generator dienen und da schubst man den Knopf halt schon mal an. Das schafft die ENCODER Routine aber nicht.
Ich habe schon mit optischen Encodern gearbeitet, allerdings über eine Interruptroutine. Da schaffe ich es selbst mit schnellem drehen nicht das Zählen aus dem Takt zu bringen obwohl ich da von dem optischen Encoder bis zu 500 Impulse pro Umdrehung bekomme.
Leider hab ich mit der Abfrage, die ich dort benutzt habe kein Glück gehabt, damit habe ich Probleme bei der Richtungsabfrage seltsamerweise.
Naja ich werde dann mal weiterbasteln, vieleicht finde ich ja auch den Fehler in meiner alten Routine.
Danke,
Markus
Also eigentlich sollten auch 500 Impulse / sek nicht das große Problem für einen Mikrocontroller darstellen.
Vielleicht solltest du mal die minimallösung von Picnic austesten.
Also, mit dieser beschaulichen Geschwindigkeit sollten alle Varianten klarkommen, möcht' man meinen.
Jetzt müßte man von deinem Programm wohl etwas mehr wissen, glaub ich. Vielleicht ist ja wo eine Ecke drinnen ?
Dr.Ice2000
20.08.2006, 16:26
Danke nochmal für eure Mühe !
Hier das Programm, das mit meinem optischen Encoder einwandfrei funktioniert:
$regfile = "m32def.dat"
$crystal = 8000000
$baud = 9600
Ddrd.2 = 0 'Eingänge mit Pullup für Drehgeber
Portd.2 = 1
Ddrd.4 = 0
Portd.4 = 1
On Int0 Onint0
Mcucr.isc00 = 1 'INT0 bei FALLING + RISING
Mcucr.isc01 = 0
Gimsk.int0 = 1
Dim Drehgeber As Long 'wird von ISR (INT0) verändert
Dim Drehgeber_alt As Long
Drehimpuls1 Alias Pind.2
Drehimpuls2 Alias Pind.4
Onint0:
If Drehimpuls2 <> Drehimpuls1 Then 'test phase B
If Divider1 = 9 Then 'soll 9 sein
Divider1 = 0
Incr Drehgeber
Else
Incr Divider1
Divider2 = 0
End If
Else
If Divider2 = 9 Then 'Soll 9 sein
Divider2 = 0
Decr Drehgeber
Else
Incr Divider2
Divider1 = 0
End If
End If
Return
Den Divider hab ich nur drin um die über 500 Impulse pro Umdrehung auf ein Maß zu bringen, dasss man auch von Hand drehen kann :-)
So und hier der Versuch mit dem Bascom Befehl :
$regfile = "m32def.dat" ' specify the used micro
$crystal = 8000000 ' used crystal frequency
$baud = 19200 ' use baud rate
$hwstack = 32 ' default use 32 for the hardware stack
$swstack = 10 ' default use 10 for the SW stack
$framesize = 40 ' default use 40 for the frame space
Config Lcd = 20 * 4a , Chipset = Ks077 '20*4 LCD DIP
Config Lcdpin = Pin , Db4 = Porta.4 , Db5 = Porta.5 , Db6 = Porta.6 , Db7 = Porta.7 , E = Porta.3 , Rs = Porta.2
Cls
Locate 1 , 1
Lcd "Encoder test"
Dim B As Byte
Dim Wert As Integer
Dim Divider1 As Integer
Dim Divider2 As Integer
Wert = 100
'we have dimmed a byte because we need to maintain the state of the encoder
Portb = &B11 ' activate pull up registers
Do
B = Encoder(pind.3 , Pind.2 , Links , Rechts , 0)
' ^--- 1 means wait for change which blocks programflow
' ^--------^---------- labels which are called
' ^-------^---------------------------- port PINs
Lcd B
Locate 4 , 1
Lcd "" ; Wert ; " "
Waitms 10
Loop
End
'so while you can choose PINB0 and PINB7,they must be both member of PINB
'this works on all PIN registers
Links:
Locate 2 , 1
Lcd "left rotation "
Decr Wert
Return
Rechts:
Locate 2 , 1
Lcd "right rotation "
Incr Wert
Return
End
Das ist praktisch genau der Code aus der Hilfe.
Gruß Markus
Nun, "Waitms 10" nach jeder Abfrage (ohne change WAIT) ist nicht zweckmäßig, da geht ihm ja was verloren.
Dr.Ice2000
20.08.2006, 16:59
Das habe ich gerade einmal auskommentiert, nützt aber nicht viel. Sobald ich den Knopf ein bischen "andrehe", so wie man das von Funkgeräten kennt z.B. verliert er den Takt und erkennt auch die Drehrichtung nicht sauber.
Ich vermute aber so langsam vieleicht ein Problem mit meiner Hardware, wobei die Signale auf dem Oszilloskop eigentlich ganz ok aussehen.
ich werde aber morgen mal mit einem Speicheroszi messen, dann kann ich auch die Abstände sehen, die kommen auf meinem analogen Oszi nicht so gut raus.
Vielen Dank erst mal
Markus
Do
B = Encoder(pind.3 , Pind.2 , Links , Rechts , 1)
--- 1 means wait for change which blocks programflow
Lcd B
Locate 4 , 1
Lcd "" ; Wert ; " "
Loop
End
Probier's mal mit "WAIT" beim "ENCODE"
Dr.Ice2000
20.08.2006, 18:00
Hi
hab ich auch versucht, wird aber nicht schneller, hält mir nur das Programm an.
mfG
Markus
mmhhh. Dann nehm' ich an, daß die LCD Befehle zu lange brauchen.
Da wärst du mit der interrupt-Methode dann wirklich besser dran
Hallo zusammen,
im Anhang ist eine Routine , die einen Encoder über eine state machine voll decodiert und damit die VOLLE Auflösung liefert. (d.h. bei JEDEM H/L Übergang wird rauf oder runter gezählt). Durch Speichern der Interrupts in Int_cnt und Abarbeiten in den While- Schleifen gehen auch bei schnellem Drehen keine Impulse verloren.
Millenniumpilot
21.08.2006, 11:50
Hallo,
vielen Dank für Deinen gelungenen "Einstand" hier. Herzlich willkommen in Forum.
Gruß Dirk
Dr.Ice2000
21.08.2006, 23:19
Hallo,
ich habe auch die Statemachine versucht, funktioniert für mich leider auch nicht, ich denke ich habe wohl doch ein Hardwareproblem, denn mit einem anderen Drehgeber funktioniert es. An das Speicheroszi komme ich leider in nächster Zeit nicht ran, aber ich werde mal andere Hardwarelösungen versuchen um meinen Steppermotor zu benutzen.
Ich wünsche euch noch viel Spaß und nochmals vielen Dank !!!
Ach so, das Programm muss für die aktuellen Bascom Versionen etwas geändert werden, denn Bascom hat "ENCODER" ja jetzt als reservierten Befehl, das sollte man also nicht mehr als Variable verwenden.
MfG
Markus
'-----------------------------------------------------------------
' (c) 2003 Manfred Fleischmann
' full quad encoder implementation with state machine
'-----------------------------------------------------------------
$regfile = "m32def.dat"
$crystal = 16000000
Ddrd.1 = 0 ' axial in
Ddrd.2 = 0 ' coder in
Ddrd.3 = 0 ' coder in
Portd.1 = 0 ' axial pullup
Portd.2 = 0 ' coder pullup
Portd.3 = 0 ' coder pullup
Const True = 1
Const False = 0
Dim Int_cnt As Byte
Dim Encoder1 As Bit ' Encoder ist ein reserviertes Wort in Bascom
Dim Rx_freq As Single
Dim Old As Byte
Dim New As Byte
Dim Calc As Byte
Enable Interrupts
Enable Int0 ' Enable the interrupt 1 / 2
Enable Int1
Mcucr = 00000101 ' Interrupt 0 und 1 bei logical change auslösen
On Int0 Int_encoder ' Labels for the Interrupt routine
On Int1 Int_encoder
INt_cnt = 128 ' Initialisierung
Encoder1 = True
Old = 3
Do ' Main Program Loop ************************************************** **************************
If Encoder1 = True Then
While INt_cnt > 128
Rx_freq = Rx_freq + 10
Decr INt_cnt
Wend
While INt_cnt < 128
Rx_freq = Rx_freq - 10
Incr INt_cnt
Wend
Encoder1 = False
End If
Loop ' END MAIN ************************************************** **************************
'***************** Encoder Interrupt Routine ***************************************
Int_encoder:
Encoder1 = True ' Frequenz muß nachgeführt werden
New = Pind
Calc = Old.2 Xor New.3 ' berechne FSM
Calc = Calc * 2
Decr Calc
INt_cnt = INt_cnt + Calc
Old = New
Return
End
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.