PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Drehgeber mit 2 Spuren handlen?



EDatabaseError
11.09.2006, 22:46
Gibt es irgentwo einen code wie ich einen inkrementalen drehgeber mit 2 spuren über interrupts handlen kann???

Int0 = 1. Spur
Int1 = 2. Spur

Mfg

tobi

teslanikola
11.09.2006, 23:10
Gibt es irgentwo einen code wie ich einen inkrementalen drehgeber mit 2 spuren über interrupts handlen kann???


Hmm geben tuts das sicher irgendwo, die welt ist ja scholießlich groß, und da ich denke dass du das auch bist könntest du ja versuchen dier auch was zu schrieben und wenn du wo nicht weiterkommst, dann gibts hier immer offene Ohren.

Also sag wo hängts und wir versuchens zu lösen, so ne "habe-fertig"-Lösung bringt dir für dich persönlich eher nix.

EDatabaseError
11.09.2006, 23:21
öhm... also die ganze Geschichte.
Ich habe einen Drehgeber bei dem ich derzeit nur die A Spur nehme. Leider wackelt das medium sehr. Ergebnis = statt 512 Inkremente habe ich 1231 oder so. Deshalb benötige ich die B Spur um das zu analysieren und auf 512 +-1 zu kommen.

Ich hab mir das Prinzip so gedacht:
2 Interrupteingänge

-Wenn beide null alle hilfsvariablen vergessen
-Wenn erster int kommt bspw. Spur A -> merken
-wenn zweiter int kommt bspw. Spur B -> merken
-die reihenfolge analysieren und dann addieren oder subtrahieren.

leider arbeitet das programm größtenteils mit interrupts dies hat zur folge das die haupt do loop schleife nur jede sekunde ausgelöst wird. Da man bei einem interrupt nur ansteigend oder abfallend detektieren kann, weiß ich leider nicht wie ich meinen gedankenfluß realisieren soll.

Mfg
tobi

EDatabaseError
11.09.2006, 23:32
ahh ich habe da eine idee

Pseudocode:


A as Bit
B as Bit

SpurA as INT0
SpurB as INT1

OnSpurA:
A = 1
if B = 1 then
-1
a = 0
b = 0
end if
return

OnSpurB:
B = 1
if a = 1 then
+1
a = 0
b = 0
end if
return

teslanikola
11.09.2006, 23:34
Also ich kenne mich jetzt nicht so direkt mit dem Output deines Drehgeber s aus, aber ich denke mal der ist bei dem magnetischen ne sinusartige kurve oder ist das sogar schon digitalisiert?

naja wenns ein Sinus ist, dann würde ich in den Interruptroutinen auf jedenfall mal warten bis der Int-Pin wieder auf Low liegt, um sicherzustellen das er bei einem schlehten signal auch nur ein inc zählt, das dürfte schonmal die genauigkeit heben. Wenn du beide Spuren benutzt würde ich das eher so machen: du schaust in dem Interrupt dert als erstes kommt, ob danach die 2. spur kommt, wenn da aber vorher die selbe spur nochmal kommt kannste den puls getrost übersehen weil es ein fehler ist, das mit dem Subtrahieren und addieren hale ich für zu aufwendig, vlt tuts auch ein smith-trigger am Int-Eingang, oder ein glättungskondensator wirkt manchmal echt wunder hau mal so 10-100nF gegen Graund an die Spuren, das dürfte schon einiges bringen, war bei mir acuhmal so, weil ubder leitungen und so weiter ziehste bei Motoren schnell ordentlichen Signalmüll rein.

EDatabaseError
11.09.2006, 23:37
http://www.heise.de/ct/04/22/236/bild5.jpg der ist so aufgebaut wie meiner...


mit meinem pseudoprinzip sollte es doch gehen :-s oder

teslanikola
11.09.2006, 23:40
mit meinem pseudoprinzip sollte es doch gehen oder


so wie ich ihn verstanden hab zählt sein µC die Singale nicht richtig

EDatabaseError
11.09.2006, 23:44
doch aber das rad des drehgebers läuft nicht konstant sondern wackelt ab und zu ein bissel und dann bekomme ich fehlzählungen. deshabl die 2. spur. um diese wieder auszugleichen

teslanikola
11.09.2006, 23:54
anmerkung zum Pseudo-Code:

Wenn man sich einen IRQ-Eingang sparen will, und auf die 2. IR routine auch, dann kann mans auch so machen:




Interrupt: ( Bei Steigender Flanke SpurA )

IF SpurB = 1 THEN

dec Var

ELSE

inc Var

END IF

RETURN

Der Pin an dem SpurB hängt muss kein IR sein, sonder ein normaler Port geht auch, hald als Eingang Config.. Die möglichkeit spart ne "menge" Code und man verplämpert auch nich unnötig Hardware.
In ASM sparste dir dann nochmlas zusätzlich ein paar MIP im vergleich zu BASCOM.

Aso wenn dein Rad wackelt, dann wird auch die SpurB nicht stimmen, weil si sitzt ja am gleichen rad, da solltest du dann lieber mal checken was du da mechanisch ausrichten kannst, weil Programmiertechgnisch wird das viel zu aufwendig.

EDatabaseError
12.09.2006, 00:03
Mit den 2 interrupts sollte es aber gehen denn wenn ers vorwärts wackelt dann macht er + und wenn es rückwärts wackelt macht er minus = 0. oder hab ich da nen denkfehler drin?

zu deinem code. Stimmt müsste so gehen! super idee

teslanikola
12.09.2006, 00:07
zu deinem code. Stimmt müsste so gehen! super idee


Danke für das lob.

Naja ich bin immer wenn es möglich ist so wenig wie möglich Hardware oder Speicherplatz zu verschwenden, deshalb hab ich auch ASM angefangen. Solche kleine "Tricks" machen nen Code gleich effektiver, und je wenigerr Code, umso weniger Fehler kannste reinmachen.

Das mit dem Wackeln dürfet nicht gehen, weil ist ja ein Rad, und wenns wackelt dann an beiden Spuren, könnte mich aber irren, versuch ist ja wert, kostet ja zum glück nichts ;-)

EDatabaseError
12.09.2006, 00:09
kostet leider doch :cry: an nerven da ich schon eine weile daran hirne...
aber es geht noch
ich mal kurz was warte mal

EDatabaseError
12.09.2006, 00:12
bild anschauen ;-)

Vogon
12.09.2006, 00:30
Thread mit der Auswertung der Quadratursignale?

https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=10007

Oder: http://www.piclist.com/techref/io/sensor/pos/enc/quadrature.htm

Edit - da ist noch ein guter Link:
http://www.elektrik-trick.de/sminterf.htm
http://www.mcselec.com/index.php?option=com_content&task=view&id=79&Itemid=57

googel mal mit "quadrature encoder" oder "inkrementale Drehgeber" da wirst du sicher was finden.

EDatabaseError
12.09.2006, 00:34
danke! schau ich mir morgen an!

good n8
tobi

EDatabaseError
12.09.2006, 21:19
Aaaalso, ich habe es heute mir dem prinzip Ein Interrupt mit SPur A und einen Eingang mit Spur B. Wenn der Interrupt kommt prüfe ob B da ist wenn ja + wenn nein -. Leider war das ergebnis richtig komisch. Ich hab mir bei + und - noch ne LED toggeln lassen.
Das Medium lief KONSTANT vorwärts:


++---++++------++++++++---++-+-+-++-+-+-+-+-+-++-+++-+


Das Ergebnis sa aber in etwa so aus... Und die Messung war völlig gaga.
Was mich gewundert hat. Auf der IO Platine blinkt alles im ms bereich. Meine +- LEDs blinken aber nur alle Sekunde oder so.
Liegt das an den anderen Interrupts? IMHO hat Int4 eine höhere Priorität als die Urxc's und die Timer oder?
Wäre toll wenn ich ein Statement von euch bekomme.
Ich poste wenn nötig auch mal ein bisse code.

Ich hab jetzt auf der Seite hier das gefunden:

'-------------------------------------------------------------------------------
' Filename : QuadrDec_1.0.bas
' Purpose : Quadrature Decoder/Counter and Display
' Author : Ger langezaal
' Date : 5 April 2002
' Compiler : BASCOM-AVR Rev. 1.11.6.5
'
'-------------------------------------------------------------------------------
'
' Algorithm:
' Interrupt on both edges of phase A
' Test phase B in ISR
' When phase B <> phase A then decrement counter
' When phase B = phase A then increment counter
' Convert counter value to displacment units
' Format value in string and display
'
'-------------------------------------------------------------------------------
'
' Setup for AT90S2313-10
'
' INT0 edge is set to rising edge
' INT1 edge is set to falling edge
' Encoder phase A to INT0 and INT1 (PD2 and PD3)
' Encoder phase B to PD4
' Pushbutton between Portd.5 and GND (display zero)
' LCD at PortB
'
' Example for PROXXON KT150 XY table:
' Displacement/rev = 2 mm
' Encoder resolution = 20 pulses/rev
' Interrupt on both pulse edges = 40 interrupts/rev
' Dial resolution: 2 mm / 40 = 0.05 mm
' The optical encoder came from a used mouse (two available)
'
'-------------------------------------------------------------------------------
'
' Options/Compiler/Chip:
' HW Stack 48
' Soft Stack 8
' Framesize 16
'
'-------------------------------------------------------------------------------
'
$regfile = "2313def.dat"
$crystal = 10000000 '10 MHz

Dim X_axis As String * 8 'LCD format string
Dim Axis_raw As Integer 'optical pulse counter
Dim Axis_mm As Integer 'counter value converted to mm
' 'range: -327.65 to +327.65 mm

Const Enc_res = 20 * 2 'encoder resolution * 2
Const Conv_mm = 200 / Enc_res 'dial resolution = 0.05 mm

Config Portb = Output
Config Portd = Input
Portd = 255 'enable Portd pullup's

Config Lcdbus = 4
Config Lcd = 16 * 1
Config Lcdpin = Pin , Db4 = Pb.4 , Db5 = Pb.5 , Db6 = Pb.6 , Db7 = Pb.7 , E = Pb.3 , Rs = Pb.2
Cls
Cursor Off

Phase_a Alias Pind.2 'INT0 also connected to Pind.3 = INT1
Phase_b Alias Pind.4
Axis_rst Alias Pind.5 'reset counter if low

'---[ Set Interrupt logic ]-----------------------------------------------------

Mcucr = &B00001011 'set interrupt edges
On Int0 Phase_a_edge 'ISR on rising edge
On Int1 Phase_a_edge 'ISR on falling edge
Enable Int0
Enable Int1
Enable Interrupts

'---[ Initialization ]----------------------------------------------------------

Lcd "X-Axis Rev.1.0"
Waitms 1000
Cls
Axis_raw = 0

'---[ Main program loop ]-------------------------------------------------------

Do
If Axis_rst = 0 Then Axis_raw = 0 'reset counter if low

Axis_mm = Axis_raw * Conv_mm 'convert to mm
X_axis = Str(axis_mm) '
X_axis = Format(x_axis , " +0.00") 'format without leading zero's
' X_axis = Format(x_axis , "+000.00") 'format with leading zero's

Locate 1 , 1
Lcd "X " ; X_axis ; " mm" 'display
Waitms 200
Loop

'-------------------------------------------------------------------------------
End

'---[ Interrupt Service Routine ]-----------------------------------------------

Phase_a_edge: 'Interrupt on rising and falling edge
If Phase_b <> Phase_a Then 'test phase B
Decr Axis_raw 'CCW
Else
Incr Axis_raw 'CW
End If
Return

'-------------------------------------------------------------------------------




das kann ich mal testen...morgenabend


Mfg
Tobi

teslanikola
12.09.2006, 21:48
häng mal deine 2 Spuren ans oszi ob da auch die erwünschten signale kommen, wenn nicht dann Problem, wenn ja dann gehts an den Code, nur um mal ne Feherlwquelle auszuschließen

EDatabaseError
12.09.2006, 21:52
si, das habe ich morgen vor mit dem oszi. was mich aber wundert ist das die IO Leds schnell und die +- LEDs nur so langsam blincken?


'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~'
Tfla:
If I4 = 1 Then
Decr Inksens
Toggle Ledrot
End If
If I4 = 0 Then
Incr Inksens
Toggle Ledgruen
End If
Return

Thms:
Timer3 = 53036 '100 ms
Gosub Motorstatus
'Waitms 10
'Gosub Info
Return

Tini: 'Zeitroutinen (jede sekunde)
Timer1 = 3036

Second = Second + 1
If Second = 60 Then Gosub Addminute
If Minute = 60 Then Gosub Addhour
If Hour = 24 Then Gosub Addday

If Day = 31 Then
Select Case Month
Case 1 : Gosub Addmonth
Case 3 : Gosub Addmonth
Case 5 : Gosub Addmonth
Case 7 : Gosub Addmonth
Case 8 : Gosub Addmonth
Case 10 : Gosub Addmonth
Case 12 : Gosub Addmonth
End Select
End If
If Day = 30 Then
Select Case Month
Case 2 : Gosub Addmonth
Case 4 : Gosub Addmonth
Case 6 : Gosub Addmonth
Case 9 : Gosub Addmonth
Case 11 : Gosub Addmonth
End Select
End If

If Month = 12 Then Gosub Addyear

Tresult = Format(str(hour) , "00") + ":" + Format(str(minute) , "00") + ":" + Format(str(second) , "00")

Dresult = Format(str(year) , "00") + "." + Format(str(month) , "00") + "." + Format(str(day) , "00")
Return

Addminute:
Minute = Minute + 1
Second = 0
Return

Addhour:
Hour = Hour + 1
Minute = 0
Return

Addday:
Day = Day + 1
Hour = 0
Return

Addmonth:
Month = Month + 1
Day = 0
Return

Addyear:
Year = Year + 1
Month = 0
Return 'Ende

Tjoy:
Gosub Fehlerquit
Return

Tterminal:
Toggle Ledgruen
Y = Udr
Terminalpos = Terminalpos + 1
If Terminalpos < 4 Then Buffer1 = Buffer1 + Chr(y)
If Chr(y) = "[" Then
Terminalpos = 0
Buffer1 = ""
End If
If Chr(y) = "]" Then
Gosub Rscomm1
End If
Toggle Ledrot
Return

Tauswerten:
I = Udr1
Answerposition = Answerposition + 1
If Answerposition < Nextanswersize Then
Antwort(answerposition) = I
End If
Return
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~'
hier all meine Interrupt codes.

mfg

EDatabaseError
15.09.2006, 23:06
aaalso ich hab das ganze nun mit einem anderen chip gemacht und siehe da es geht. Es lag an den vielen anderen Interrupts die meist Zeitgleich kamen.

Mfg

teslanikola
16.09.2006, 13:15
sehen sie Agent Gibbs, es funktioniertt doch, SIR. Ich hohle ihn einen Kaffe.

EDatabaseError
16.09.2006, 17:36
*g* danke aber verschütte ihn nich gleich wieder ;-)

/ME hat sich nun ein bissel Ätzzubehör besorgt und machtseine Platine nu ohne Kabelsalat. Werde mich sicher bald mit irgentwelchen Problemen in Richtung Dauer beim Entwickeln etc. bei euch melden. Aber das ist ein anderes Thema.

Mfg

teslanikola
16.09.2006, 17:58
*g* danke aber verschütte ihn nich gleich wieder


Ich wars nicht, das war Toni!!!!

EDatabaseError
16.09.2006, 18:41
:lol:

Mfg
Tobi