Sida 1 av 5
Hur styra en stegmotor med en uC
Postat: 3 april 2010, 14:19:37
av jojje
Eftersom det verkar som jag fått igång min PICkit2 nu, så kanske jag ska försöka mig på ett projekt. Det jag tänkte på var ”Hur styra en stegmotor med en uC”, sen kan man göra nåt i stil med ”Hur styra ett RC-servo med en uC”, osv osv.
Orsaken är att jag har länge tänkt på att göra nåt som styr mina kontrollerkort utan att ha datorn igång. Det har även droppat in flera mail med frågor om man kan styra en stegmotor med en uC. Någon har nog velat göra hela skiten, alltså inte blanda in mina små kort, men dom flesta vill styra ett kontrollerkort. Det är ju ganska lätt, bara Steg och Dir, men det dyker upp vissa frågor ändå. Typ ska man spara på speciella parametrar i uC eller kan man ha en init-fil som innehåller tex antal steg per varv, maxfart, vart finns ”nollan”, osv osv.
Jag skulle vilja ha en apparat som styr en motor, eller flera på en gång, som är lätt att styra. Den kan ha en fristående enhet för inställningarna. Tex där man anger vart man har Home-switchen och ha ett värde som sen läggs på. Ingen fattade nog vad jag menade, men:
Om man har en cirkelsåg och man vill styra sågbredden, så vill man kunna känna av vart är avståndet noll mellan sågklingan och motstödet? Åker man med stödet till noll, då tar det i sågklingan, så det är ju inte bra. Därför kan man lägga tex en switch 10mm ifrån, och lägga på 10 till det inställda värdet. På samma sätt vill man ha ett minvärde som stödet kan åka till. Att åka till ”Nollan” behövs annars också, tex om nåt lägger sig emellan och gör att stegmotorn inte klarar av att åka dit den ska.
En annan sak som måste bestämmas från början är vilken typ av uC ska man använda. Eftersom jag äntligen fått igång min PICkit2 och även har en Wips, så blir det PIC.
Programmet tycker jag att man kan skriva i nån typ av Basic. Stort sätt alla som programerar i Assembler, C eller nåt annat kan läsa Basic, men inte alltid tvärtom. Jag har en demo av PicBasicPro och en skarp 2.42 version av det samma. Sen har jag MicroBasicPro som klarar 2k kod om jag inte tar helt fel. Om man inte använder dom specifika sakerna som finns i PBP så spelar det kanske ingen roll vad man använder?
Jag hade även som tanke att vi kunde köra detta som ett samprojekt, där dom som vill lägger sig i med hurtiga kommentarer och snillrika ideer, men att vi försöker att hålla en struktur så det går framåt hela tiden. Helst inga typ ”om du tittar i databladet så bör du hitta hur man kan göra...” bla bla bla. Raka puckar med hårdvara och så färdiga kodförslag som man kan. Iaf jag vill inte behöva lära motorteknik på hög nivå för att köra till och från jobbet varje dag, om ni förstår vad jag menar. Klart det är viktigt att lära sig saker, men varför inte hänvisa direkt till den text man menar. Nu har jag nog trampat på många ömma tår, men det är inte alls meningen. Jag vill inte bara snöa in mig i massa faktablad om dittan å dattan.
Tror ni att det här kan vara nåt, och är det flera som vill komma ner i soffan, så vassögo å ta plats, nu siktar vi mot stjärnorna som salle sa.
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 14:45:19
av Gimbal
Kan bara flika in att styra ett RC-servo är bra mycket enklare än en stegmotor eftersom det enbart handlar om en enda puls som behöver skapas, och den kan dessutom kopplas rakt från utgången på µc till ingången på servot utan mellanliggande komponenter. Det är svårt att hitta på något enklare.
Tyvärr har jag ingen som helst aning om hur du skapar pulser med skaplig precision på en pic (kör själv avr) och dessutom med hjälp av basic så någon mer hjälp där kan jag inte komma med.
Ett RC-servo är väl inte så lämpligt ihop med sågbord kanske, men kul ändå.
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 14:57:04
av jojje
Stegmotorn styrs lättast som om den vore en lysdiod. Ett Steg = lysdioden lyser ett visst antal milisekunder, sen släcka den.
Dir är som om lysdioden är tänd hela tiden eller släckt hela tiden, alltså inga pulser eller nåt sånt, bara på eller av.
Det med RC-servo var om man skulle göra ett nytt projekt, men det blir en senare fråga.

Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 15:19:02
av AndersG
Jag har kod någonstans för att steppa, men sedan insåg jag att det var så mycket enklare med en L297..
Kod: Markera allt
;******************************************************************************
;Software License Agreement
;
;The software supplied herewith by Microchip Technology
;Incorporated (the "Company") is intended and supplied to you, the
;Company’s customer, for use solely and exclusively on Microchip
;products. The software is owned by the Company and/or its supplier,
;and is protected under applicable copyright laws. All rights are
;reserved. Any use in violation of the foregoing restrictions may
;subject the user to criminal sanctions under applicable laws, as
;well as to civil liability for the breach of the terms and
;conditions of this license.
;
;THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES,
;WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
;TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
;PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
;IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
;CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
; *******************************************************************
; PICkit 2 Lesson 7 - Reversible LEDs
;
; This shows how to read the A2D converter and display the
; High order parts on the 4 bit LED display.
; The pot on the Low Pin Count Demo board varies the voltage
; coming in on in A0.
;
; Also the switch is used to reverse the direction of rotation
;
; The A2D is referenced to the same Vdd as the device, which
; is provided by the USB cable and nominally is 5V. The A2D
; returns the ratio of the voltage on Pin RA0 to 5V. The A2D
; has a resolution of 10 bits, with 1023 representing 5V and
; 0 representing 0V.
;
; RA0 - Analog
; RA1 - Direction
; RA2 - Step
; RA3 -
; RA4 - Microstep
; *******************************************************************
; * See Low Pin Count Demo Board User's Guide for Lesson Information*
; *******************************************************************
; * NOTE: The PIC16F690 requires the AC162061 header for debugging *
; *******************************************************************
#define STEPPIN porta,2
#define DIRPIN porta,1
#define HALFPIN porta,4
;
; Decrement 16 bit value, sets Z on exit
;
; Operation: DST--
;
DEC16 MACRO DST
DECF (DST),F ; Decrement low byte
INCFSZ (DST),W ; Check for underflow
INCF (DST)+1,F ; Update
DECF (DST)+1,F ; Fixup
MOVF (DST),W
IORWF (DST)+1,W ; Set Z bit
ENDM
#include <p16F690.inc>
__config (_INTRC_OSC_NOCLKOUT & _WDT_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _BOR_OFF & _IESO_OFF & _FCMEN_OFF)
INT_VAR UDATA_SHR
w_temp RES 1 ; variable used for context saving
status_temp RES 1 ; variable used for context saving
pclath_temp RES 1 ; variable used for context saving
fsr_temp res 1
Display res 1 ; define a variable to hold the diplay
Direction res 1
LookingFor res 1
Step res 1
Steptime res 1
d1 res 1
d2 res 1
temp res 1
halfstep res 1
;**********************************************************************************************************
RESET_VECTOR CODE 0x0000 ; processor reset vector
goto start ; go to beginning of program
INT_VECTOR CODE 0x0004 ; interrupt vector location
;**********************************************************************************************************
; ISR
;**********************************************************************************************************
INTERRUPT
; Keep the actual ISR as short as possible. Current code can count pulses up to approx 15kHz
;
; Arrive here on any interrupt - first save the world...
;
movwf w_temp ; save off current W register contents
swapf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
movf PCLATH,w ; move pclath register into W register
movwf pclath_temp ; save off contents of PCLATH register
movf FSR,w ; move fsr register into W register
movwf fsr_temp ; save off contents of PCLATH register
; Actual isr code, determine cause of interrupt. Most likely first
btfss intcon, intf ; Was the cause an external interrupt? (RA2)
goto exit_interrupt ; no
; Yes, pulse arrived on RA2
banksel Step
bsf Step,1 ; Set flag to step
movlw 0x01
movwf Steptime ; Stop the currently running step (if any)
bcf intcon,intf ; Clear external interrupt flag
;
; Catch-all for interrupt exit. Restore the world as we know it.
;
exit_interrupt
movf fsr_temp,w ; retrieve copy of FSR register
movwf fsr ; restore pre-isr FSR register contents
movf pclath_temp,w ; retrieve copy of PCLATH register
movwf PCLATH ; restore pre-isr PCLATH register contents
swapf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
retfie ; return from interrupt
;**********************************************************************************************************
; END ISR
;**********************************************************************************************************
MAIN_PROG CODE
Start:
banksel TRISA
;bsf STATUS,RP0 ; select Register Page 1
movlw 0xFF
movwf TRISA ; Make PortA all input
clrf TRISC ; Make PortC all output
movlw 0x10 ; A2D Clock Fosc/8
movwf ADCON1
; bcf STATUS,RP0 ; back to Register Page 0
;bcf STATUS,RP0 ; address Register Page 2
;bsf STATUS,RP1
banksel ANSEL
movlw b'11110001' ; we want all Port A pins Analog, except RA3.. ra1
movwf ANSEL
;bcf STATUS,RP0 ; address Register Page 0
;bcf STATUS,RP1
banksel 0
movlw b'00000001'
movwf ADCON0 ; configure A2D for Channel 0 (RA0), Right justified, and turn on the A2D module
movlw 0x08
movwf Display
clrf Direction
clrf LookingFor ; Looking for a 0 on the button
clrf Step
clrf Halfstep
movlw 0
movwf PORTC
banksel INTCON
bcf INTCON, INTF ; clear interrupt flag
bsf INTCON, INTE ; mask for external interrupts, external interrupt (RA2) is on
bsf INTCON, GIE ; enable interrupts
MainLoop:
banksel PORTA
btfss DIRPIN ; Direction up?
goto GoingUp
bsf Direction,0
goto MainLoop1
GoingUp
bcf Direction,0
MainLoop1
btfss Step,1 ; Shall we step?
goto MainLoop
call Rotate
goto MainLoop
; movf Display,w ; Copy the display to the LEDs
; movwf PORTC
; nop ; wait 5uS for A2D amp to settle and capacitor to charge.
; nop ; wait 1uS
; nop ; wait 1uS
; nop ; wait 1uS
; nop ; wait 1uS
; bsf ADCON0,GO ; start conversion
; btfss ADCON0,GO ; this bit will change to zero when the conversion is complete
;; goto $-1
; banksel adresh
; movf ADRESH,w
; movwf Delay2
; ;clrf Delay2
; banksel adresl
; movf ADRESL,w
; movwf Delay1
; clrf Delay1
; ;movlw 0xfe ; Delay another 10mS plus whatever was above
; ;movlw .50
; ;movwf Delay1
; banksel delay1
;A2DDelayLoop:
; dec16 delay1
; btfss STATUS,Z
; goto A2DDelayLoop
;
Rotate:
banksel PORTA
btfss HALFPIN ; Doing halfsteps?
goto DoHalfStep
bcf Step,1 ; Clear flag to show we stepped
bcf STATUS,C ; ensure the carry bit is clear
btfss Direction,0
goto RotateLeft
RotateRight:
rrf Display,f
btfsc STATUS,C ; Did the bit rotate into the carry?
bsf Display,3 ; yes, put it into bit 3.
goto RotateWait
RotateLeft:
rlf Display,f
btfsc Display,4 ; did it rotate out of the display
bsf Display,0 ; yes, put it into bit 0
RotateWait
movf Display,w ; Copy the display to the LEDs
movwf PORTC
movlw .100
movwf Steptime
RotateWait1
call delay_500us
decfsz Steptime, f
goto RotateWait1
movlw 0
movwf PORTC
return
DoHalfStep
; Page-safe jumptable from AN556. Checks for carry when adding offset and
; adjusts PCLATH accordingly
banksel halfstep
movf halfstep,w ; Get display mode in W
andlw .7 ; Make sure it is within bounds (0..7)
movwf temp ; save in temp register
movwf halfstep
movlw LOW steptable ; Get low address of table
addwf temp,F ; add offset
movlw HIGH steptable ; Get high 5 bits of address
btfsc status,c ; Did we cross a page?
addlw 1 ; Yes, increment high address
movwf pclath ; Load high address in latch
movf temp,w
movwf pcl ; Load computed offset into program counter
steptable
goto step0 ; Jump table to display mode handlers
goto step1
goto step2
goto step3
goto step4
goto step5
goto step6
goto step7
step0
movlw b'00000001'
goto HalfstepWait
step1
movlw b'00000011'
goto HalfstepWait
step2
movlw b'00000010'
goto HalfstepWait
step3
movlw b'00000110'
goto HalfstepWait
step4
movlw b'00000100'
goto HalfstepWait
step5
movlw b'00001100'
goto HalfstepWait
step6
movlw b'00001000'
goto HalfstepWait
step7
movlw b'00001001'
goto HalfstepWait
HalfstepWait
bcf Step,1 ; Clear flag to show we stepped
btfss Direction,0
goto HalfstepLeft
HalfstepRight:
incf halfstep
goto Halfstep2
HalfstepLeft:
decf halfstep
Halfstep2
movwf PORTC
movlw .100
movwf Steptime
HalfstepWait1
call delay_500us
decfsz Steptime, f
goto HalfstepWait1
movlw 0
movwf PORTC
return
; http://www.piclist.com/techref/piclist/codegen/delay.htm
delay_5ms
movlw 0xE7
movwf d1
movlw 0x04
movwf d2
Delay_5ms_0
decfsz d1, f
goto $+2
decfsz d2, f
goto Delay_5ms_0
goto $+1
return
; Delay = 0.0005 seconds
; Clock frequency = 4 MHz
; Actual delay = 0.0005 seconds = 500 cycles
; Error = 0 %
delay_500us
;499 cycles
movlw 0xA6
movwf d1
delay_500us_0
decfsz d1, f
goto delay_500us_0
;1 cycle
nop
return
end
edit: eller menade du att styra en stegmotor som redan har ett kort?
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 15:35:10
av jojje
Tror jag också, det är därför jag vill använda mina kontrollerkort. Slippa uppfinna det hjulet på nytt igen.
Tror ni att standardprocessorn (16F690) som följer med PICkit2 går att använda?
Håller man sig till en modul = en stegmotor, då blir det nog lättast och bäst.
En CNC-fräs har ju tre kanaler, X, Y och Z. Ett sågbord har också tre, sågbredd, vinkel och sågdjup.
Sen finns det massa andra applikationer man kan ha det till. Så en modul = en motorstyrning.
Jag vill gärna att man ska styra motorn på ett enkelt sätt, tex med några tryckknappar för att ställa värdet.
Det räcker med 9999 mm och en decimal, så fem 7-segmentare räcker.
Antal knappar: En knapp för att rulla siffrorna var för sig, och en för att utföra rörelsen.
Sen kan man koppla en display till det hela för att göra grundinställningarna.
Kan man spara diverse data i uC'n och det finns kvar när man startar upp den på nytt?
Edit: Svar på AndersG's Edit. Jepp.
Orsaken är att jag har länge tänkt på att göra nåt som styr mina kontrollerkort utan att ha datorn igång.
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 15:48:22
av AndersG
16f690 funkar säkert, men menar du att du vill köra fram och tillbaka med knappar??
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 15:58:21
av v-g
Jag skulle kunna slänga ihop nåt rätt enkelt, tyvärr ingen 690 att pröva på..
Bara fram+back? Hur vill styrningen ha signalerna?
Jag har ju kugghjulsklockans kod och den är ju tämligen straight forward.

Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 16:02:19
av jojje
AndersG: Bra. Nope, inte knappar på det sättet. Om vi tar ett sågbord.
För att slippa försöka ställa in 250mm, provsåga, knacka in en mm, prova, osv, så vill jag kunna ställa in 250 på displayen och sen trycka på OK, så går stegmotorn ett visst antal steg tills den har ställt in motstödet exakt på 250mm.
Vill man sen såga 176mm, så ställer man in 176 och trycker på OK, så kan man direkt såga en planka med 176mm bredd.
Jag "kom på" det när jag var hos en snickarverkstad och ville ha några MDF-bitar tillsågade. Det som tog tid var att ställa in bredden, och det blev inte likadant varje gång. Ibland orkade dom ställa in 176mm, men som oftast blev det någon eller några mm för stort eller för litet. Jag hittade en brädgård som hade en styrd sågklinga, med det var så långt att åka dit. Min nuvarande local dealer vill gärna bygga om sin stora såg med stegmotorer men han säger det blir för dyrt, uppåt 20 tusen. Jag sa en gång att det fixar jag, men nu är det några år sen.
v-g: Du är nog inne på samma sak som AndersG kanske.
Hur vill styrningen ha signalerna?
Som vanliga lysdioder kanske? Det är det jag försökt förklara några inlägg ovanför.
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 16:37:02
av jojje
Det jag gärna skulle vilja ha svar på nu är:
Kan man spara diverse data i uC'n och det finns kvar när man startar upp den på nytt?
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 16:47:06
av sneaky
Kort svar, ja. Längre svar, avdelning 10.0 i databladet. Står även i sammanfattningen om dess egenskaper på sidan 3-4.
Finns med största sannolikhet funktioner för det i den miljö/språk du använder.
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 17:05:02
av AndersG
Hur skulle det vara med en display och en 4x4 knappsats? 1..9, x,y,z,f, så att:
1 0 0 F X = Sätter X Freedrate till 100
1 0 0 X = Gå till X=100
etc.
En 16F690 har litet för få pinnar för detta dock, såvida du inte kopplar display och t-bord seriellt.
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 17:08:09
av limpan4all
Ja, man kan spara data väldigt enkelt, i internt E2PROM eller en extern dito, man kan även spara data i internt FLASH-minne.
Men det är ju lite beroende av vilken CPU man väljer.
Jag skulle lösa detta problem med en ATMEGA168 eller en ATMEGA128 beroende på hur mycket "lull-lull" som krävs, blir lätt lite "pin-torsk" i MEGA168 med extern LCD.
Sen så kan man ju välja om man skall ha det som ett CPU-kort med integrerad stegmotorkontrollerkrets eller om man bara skall lägga ut DIR + STEP signaler gärna OPTO-isolerat via 6N137 eller liknande kan ju vara bra att ha. Går man på externa DIR + STEP så finns ju Gecko 203V mfl för starkare motorer än 51´or dvs för högre strömmar...
Som vanligt dock så är det jobbiga "användarinterfacet" hur skall det se ut? Hur skall det fungera? Användarmanual måste skrivas. Testning mot EMC direktiven? Testning mot lågspäningsdirektiven? Testning mot arbetsskyddsdirektiven?
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 17:08:49
av jojje
Tackar sneaky, jag hittade det i databladet och troligtvis även i PBP. Är det rätt?
Kod: Markera allt
WRITE Address,Value
Write Value to the on-chip EEPROM at the specified Address. This instruction may only be used with a PICmicro that has an on-chip EEPROM data area such as the PIC16F84, PIC16C84 and the PIC16F87x series. WRITE is used to set the values of the on-chip EEPROM at runtime. To set the values of the on-chip EEPROM at programming-time, use the DATA or EEPROM statement. Each WRITE is self-timed and takes about 10 milliseconds to execute on a PICmicro.
If interrupts are used in a program, they must be turned off (masked, not DISABLEd) before executing a WRITE, and turned back on (if desired) after the write instruction is complete. An interrupt occurring during a WRITE may cause it to fail. WRITE will not work on devices with on-chip I2C interfaced serial EEPROM like the 12CE67x and 16CE62x parts. Use the I2CWRITE instruction instead.
Example
WRITE 5,B0 ' Send value in B0 to EEPROM location 5
See Also
READ
I2CREAD
I2CWRITE
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 17:15:37
av jojje
Jo AndersG, men jag tror och hoppas det räcker med färre knappar. Sen blir det lättare för mig att skriva kod. Jag får kanske bättre översikt så här i början. Får försöka fixa hårdvaran först, hmm...
Det limpan skriver om var ju kul, men ...

Hittar inte någon av dom kretsarna i programerbara kretsar i varken PBP eller nån annan.
Helst skulle man vilja ha en stor display, men antingen blir texten för liten, eller den blir för dyr.
Re: Hur styra en stegmotor med en uC
Postat: 3 april 2010, 17:19:00
av limpan4all
Jag läste tydligare, du har ju för avsikt att göra det med PIC kretsar, jag ligger i AVR träsket till skillnad från PIC träsket så det är ju inte helt applicerbart...
Men delen om testning är tyvärr helt adekvat.