Forum: Mikrocontroller und Digitale Elektronik Schrittmotor mit pic16f84a


von ... -. (dark-crisis12)


Lesenswert?

Hallo zusammen,
Bin neu hier und hab auch schon gleich ma ne Frage.
Ich hatte vor mir den oben genannten PIC für die Steuerung eines 
Schritmotors zu programmieren und zwar ist auf der rotierenden Achse des 
Motors ein runds Blatt befestigt mit einem loch andem die Lichtschranke 
beim vorbeikommen ein High Pegel zeigt.
Unter den rotierenden Blatt ist ein befestigtes Blatt mit Zaheln von 0-9 
in gleichmäsigem abstand 360° verteilt.
wenn der pic startet soll er sich unabhängig von seiner Position erst 
einmal orientieren (mit Interrupt gelöst) was auch funktioniert (er 
orientiert sich an Position 0 also die Lichtschranke). Nun soll der 
Motor wenn man Hexadezimal eine Zahl an den Ports eingibt und diese 
durch drücken des übername Taster dann auch eingelesen wird (High beim 
betätigen) (vorher Binär gewandelt funktioniert auch einbandfrei) auch 
auf diese Zahl zeigen (Es Wird Hex nur 0-9 benutz(Logisch)). Dort liegt 
der Haken wenn ich die zweite Programm hälfte also das nachdem Interrupt 
in dem Pic auch noch einfüge Kallibriert er sich zwar mit Linksdrehung 
aber schwenkt dann nach rechts um und dreht sich nurnoch wie verrückt.

Ich wies das es sich nach viel anhört hoffe allerdings dennoch das ihr 
mir helfen könnt da ich das fertige Programm dringent morgen brauche!
hier noch die benutzten Ports:
B Für das Bitmuster des Motors:
RA0= 2^0
RA1= 2^1
RA2= 2^2
RA3= 2^3

Übernahme Taster der beim drücken High Pegel gibt:
RA4

Lischtschrancke (Position0)
RB0

Standorteingabe also die hexadezimale eingabe:
RB1=2^0
RB2=2^1
RB3=2^2
RB4=2^3


Und hier noch mein Programm was nicht funktioniert:
list p=16f84
include <P16F84.inc>
ZAHL05 equ 0x0C
ZAHL5 equ 0x0D
KONST equ 0x0E
KONSTISR equ 0x0F
W_TEMP equ 0x10
STATUS_TEMP equ 0x11
TEMP_EIN equ 0x12
TEMP_AUS equ 0x13
TEMP equ 0x14
ZAHL equ 0x15

org 0x0000
goto INIT

org 0x0004
PUSH
movwf W_TEMP
swapf STATUS,0
movwf STATUS_TEMP
ISR
movlw 0x01
movwf KONSTISR
POP
swapf STATUS_TEMP,0
movwf STATUS
swapf W_TEMP,1
swapf W_TEMP,0

bcf INTCON,INTF
retfie

INIT
bsf STATUS,RP0
movlw 0x10
movwf TRISA
movlw 0xFF
movwf TRISB
bsf OPTION_REG,INTEDG
bcf STATUS,RP0
bsf INTCON,INTE
bsf INTCON,GIE

HP
movlw 0x02
movwf KONSTISR
movlw 0x04
movwf KONST
WIEDL
movf KONST,0
call TABLI
movwf PORTA
call ZEIT5
decfsz KONST,1
goto WIEDL
decfsz KONSTISR,1
goto HP
bcf INTCON,GIE
clrf TEMP_AUS

WIED0
btfss PORTB,0
goto WIED0
movf PORTB,0
andlw 0x1E
movwf TEMP_EIN
rrf TEMP_EIN,1
movlw 0x05
subwf TEMP_EIN,0
movwf TEMP
movf TEMP_EIN,0
movwf TEMP_AUS
btfss STATUS,C
goto POS1
goto POS2
POS1
call LINKS
goto WIED
POS2
call RECHTS

WIED
btfss PORTA,4
goto WIED
movf PORTB,0
andlw 0x1E
movwf TEMP_EIN
rrf TEMP_EIN,1
movf TEMP_AUS,0
subwf TEMP_EIN,0
movwf TEMP
movf TEMP_EIN,0
movwf TEMP_AUS
btfss STATUS,C
goto POS9
goto POS10
POS9
call LINKS
goto WIED
POS10
call RECHTS
goto WIED

ZEIT05
movlw 0x7D
movwf ZAHL05
WIED1
nop
decfsz ZAHL05,1
goto WIED1
return

ZEIT5
movlw 0x0A
movwf ZAHL5
nop
WIED2
call ZEIT05
decfsz ZAHL5,1
goto WIED2
return

TABRE
addwf PCL,1
nop
retlw 0x06
retlw 0x05
retlw 0x09
retlw 0x0A

TABLI
addwf PCL,1
nop
retlw 0x09
retlw 0x05
retlw 0x06
retlw 0x0A

LINKS
POS5
movlw 0x14
movwf ZAHL
POS3
movlw 0x04
movwf KONST
POS4
movf KONST,0
call TABLI
movwf PORTA
call ZEIT5
decfsz KONST,1
goto POS4
decfsz ZAHL,1
goto POS3
decfsz TEMP,1
goto POS5
return

RECHTS
POS6
movlw 0x14
movwf ZAHL
POS7
movlw 0x04
movwf KONST
POS8
movf KONST,0
call TABRE
movwf PORTA
call ZEIT5
decfsz KONST,1
goto POS8
decfsz ZAHL,1
goto POS7
decfsz TEMP,1
goto POS6
return

Ende
end

Ach und Arbeiten tue ich mit MPLAB.
Hoffe ihr könnt mir bald helfen das Program zum laufen zu bekommen!
Danke im Vorraus!!!

von MaWin (Gast)


Lesenswert?

Ich hab mir nicht alles angeguckt, aber:

org 0x0004
PUSH            <- die Instruktion kenne ich nicht, der 18f84 auch 
nicht, und als Label wird das auch nicht verwendet, es sieht so aus als 
ob du das aus einem anderen Programm übernommen hast ohne es zu 
verstehen
movwf W_TEMP
swapf STATUS,0
movwf STATUS_TEMP
ISR<- die Instruktion kenne ich nicht, der 18f84 auch nicht, und als 
Label wird das auch nicht verwendet, es sieht so aus als ob du das aus 
einem anderen Programm übernommen hast ohne es zu verstehen

movlw 0x01
movwf KONSTISR
POP<- die Instruktion kenne ich nicht, der 18f84 auch nicht, und als 
Label wird das auch nicht verwendet, es sieht so aus als ob du das aus 
einem anderen Programm übernommen hast ohne es zu verstehen

swapf STATUS_TEMP,0
movwf STATUS
swapf W_TEMP,1
swapf W_TEMP,0

bcf INTCON,INTF
retfie

Nehmen wir also an, diese Interrupt-Routine setzt erfolgreich KONSTISR 
auf 1 wenn ein Interrupt ausgelöst wurde

INIT
bsf STATUS,RP0
movlw 0x10
movwf TRISA
movlw 0xFF
movwf TRISB
bsf OPTION_REG,INTEDG
bcf STATUS,RP0
bsf INTCON,INTE  <- RB= liefert Interrupt
bsf INTCON,GIE   <-  Interrupts erlaubt

HP
movlw 0x02    <-  2 mal
movwf KONSTISR
movlw 0x04    <- je 4 Schritte
movwf KONST
WIEDL
movf KONST,0
call TABLI
movwf PORTA
call ZEIT5
decfsz KONST,1
goto WIEDL
decfsz KONSTISR,1
goto HP
bcf INTCON,GIE   <- Interrupts verboten

Wie kommst du dadrauf, daß in dieser kurzen Zeit von nur 2 Vollschritten 
dein Zeiger so weit gelaufen ist, daß der Interrupt ausgelöst wurde ? Es 
gibt keinen Rücksprung nach INIT, HP oder WIEDL.

clrf TEMP_AUS

WIED0
btfss PORTB,0  <- wann soll sich der ändern, wenn nicht passiert ?
goto WIED0

Du kannst nicht PB0 sowohl an die Lichtschranke für den Zeiger als auch 
an den Taster für das Einlesen der Sollposition gekoppelt haben, also 
ist der Taster woanders, also wird man ewig auf PB0=1 warten, hier 
sollte wohl RA4 getestet werden.

movf PORTB,0
andlw 0x1E
movwf TEMP_EIN
rrf TEMP_EIN,1
movlw 0x05   <- keine Ahnung warum du nun 5 abziehst
subwf TEMP_EIN,0
movwf TEMP
movf TEMP_EIN,0  ; ab hier weiß der Geier was du treibst
movwf TEMP_AUS
btfss STATUS,C
goto POS1
goto POS2
POS1
call LINKS  ; warum links
goto WIED
POS2
call RECHTS  ; warum rechts, ich dachte du drehst nun links bis di dort 
bist

WIED
btfss PORTA,4
goto WIED
movf PORTB,0
andlw 0x1E
movwf TEMP_EIN
rrf TEMP_EIN,1
movf TEMP_AUS,0
subwf TEMP_EIN,0
movwf TEMP
movf TEMP_EIN,0
movwf TEMP_AUS
btfss STATUS,C
goto POS9
goto POS10
POS9
call LINKS
goto WIED
POS10
call RECHTS
goto WIED

ZEIT05
movlw 0x7D
movwf ZAHL05
WIED1
nop
decfsz ZAHL05,1
goto WIED1
return

ZEIT5
movlw 0x0A
movwf ZAHL5
nop
WIED2
call ZEIT05
decfsz ZAHL5,1
goto WIED2
return

TABRE
addwf PCL,1
nop
retlw 0x06
retlw 0x05
retlw 0x09
retlw 0x0A

TABLI
addwf PCL,1
nop
retlw 0x09
retlw 0x05
retlw 0x06
retlw 0x0A

LINKS
POS5
movlw 0x14
movwf ZAHL
POS3
movlw 0x04
movwf KONST
POS4
movf KONST,0
call TABLI
movwf PORTA
call ZEIT5
decfsz KONST,1
goto POS4
decfsz ZAHL,1
goto POS3
decfsz TEMP,1
goto POS5
return

RECHTS
POS6
movlw 0x14
movwf ZAHL
POS7
movlw 0x04
movwf KONST
POS8
movf KONST,0
call TABRE
movwf PORTA
call ZEIT5
decfsz KONST,1
goto POS8
decfsz ZAHL,1
goto POS7
decfsz TEMP,1
goto POS6
return


Vergiss die Interrupts, vergiss das Linksdrehen, prüfe nur PB0 
(Lichtschranke) als Nullposition und drehe rechts:

HP:
movlw 0x04    <- je 4 Teilschritte pro Vollschritt
movwf KONST

Label1:      ; drehe rechts bis PB0 = 0

call onesteptotheright
btfsz PORTB,0
goto Label1

Label2:      ; drehe rechts bis PB0 = 1

call onesteptotheright
btfss PORTB,0
goto Label1

WIED0
btfss PORTA,4  <- warte auf Tastendruck
goto WIED0

movf PORTB,0
andlw 0x1E
movwf TEMP_EIN
rrf TEMP_EIN,1 ; nun wissen wir auf welche Ziffer positioniert werden 
soll

; ich weiß aber nicht ob deine Skala mit Ziffer 1 oder
; Ziffer 0 beginnt angenommen die erste Position ist 1

Label3:

movlw x    <-- x steht für Anzahl Viertelschritte pro Ziffer, z.B. 40
movwf KONSTISR

Label4:

call onesteptotheright

decfsz KONSTISR
goto Label4

decfsz TEMP_EIN
goto Label3

stop:
goto stop

onesteptotheright:
movf KONST,0 ; aktuellen Viertelschritt an Schrittmotor
call TABRE
movwf PORTA
call ZEIT5
decfsz KONST,1
return
movlw 0x04    ; nächster Schritt wieder 4
movwf KONST
return

das sollte reichen, zusammen mit deinen Subroutinnen TABRE und ZEIT5

von ... -. (dark-crisis12)


Lesenswert?

Mein Ziffernblatt fängt mit 0 an dort ist auch die Lichtschrancke.
Mir fällt auch grad auf das ich dir eine Information verschwiegen habe 
und zwar soll der Motor von Zahl zur Zahl nicht einfach von z.b. 3 nach 
8 in eine richtung drehen sonder er soll von Zahl zu Zahl immer den 
kürzesten weg nehemen.
Deswegen ziehe ich die hälfte also 5 ab und überprüfe die c flag ist sie 
gesetzt dann eine linksdrehung zur nächsten Zahl wenn nicht dann eine 
Rechtsdrehung zur nächsten Zahl.
Echt doof von mir das ich das vergessen hab reinzuschreiben XD SORRY!

von ... -. (dark-crisis12)


Lesenswert?

Ansich war das Ziel ja ein Programm zu bauen wobei der Motor sich beim 
einschalten auf 0 (Lichtschranke) kaliebriert und dann bei eingabe einer 
position diese anfährt und bei der eingabe einer neuen Position die neue 
auff dem kürzesten weg von der alten aus anfährt.
die Positions eingabe sollte mit drücken des Tasters übernommen werden.

von MaWin (Gast)


Lesenswert?

Dann brauchst du bloss

stop:
goto stop

gegen

WIED1
btfsc PORTA,4  <- warte auf Taste losgelassen
goto WIED1
goto Label1

und natürlich das zweite
goto Label1
gegen
goto Label2
korrigieren.

Nur dreht er eben immer rechtsrum. Klappt das, kannst
du ja auf kürzesten Weg umbauen.

von ... -. (dark-crisis12)


Lesenswert?

Habs endekt soryy Danke nochmal für die Hilfe!!!

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.