Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

i wanna your help pleaz

Status
Not open for further replies.

solidsnike

Member level 1
Joined
Apr 16, 2006
Messages
37
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
1,526
i wanna your help pleaz

i want to control two srepper motors using pic16f84a

i need the first stepper motor to move one step every one minute without stoping until the PIC senses from external sensors in this moment i neen the first to stop and the other stepper to move one step only and continues the movement of the first after that .

i know this operation is executed by the intrrupt .. but when i try to write the code i encountered problems to do that ..... pleaz i want somebody help me to write the code by assembly

note:
i'm using pic16f84a and two unipolar stepper motor
and thanks
 

Can you post the code you've got so far?
It may help to better understand what the problem is and perhaps fix it, rather than write it from scratch (although that is an option).
 

this my code... and i'm not sure is it ok or not .... i think there are many mistakes and i need your help to imroving it and thanks a lot for reply

Code:
      List   p=pic16f84a
       include <p16f84A.inc>
       __config _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF

; variables in PIC RAM
        cblock   0x0d       ; Start of block
        hours               ; counter of hours
        mins                ; counter of mins
        secs                ; counter of secs
        NbHi                
        NbLo                ; counters
        NaHi
        NaLo
        old_w               ; Context saving
        old_STATUS          ; saving the STATUS
        bitsB47             ; Storage for previous value
                            ; in port-B bits 4-7
        temp                ; Temporary storage
        fwd_step
        endc
        rp0 equ .5
;=============================
;        Reset vector
;=============================
        org 0 ; start at address 0
        goto main
;=============================
;       interrupt handler
;=============================
        org 0x04
        goto IntServ

;***********************************************
;****************   Main program****************
;***********************************************
main:
    ; Disable port-B internal pullups
    ; Interrupts on falling edge of pushbutton action
        movlw   0xbf            ;RBPU=1 Pull up not use
        movwf   OPTION_REG      ;Set OPTION_REG
        bsf     STATUS,rp0      ;Change to Bank1
        clrf    TRISA           ;Set PORTA all OUT
        movlw   0xf0            ;RB0,1,2.5=IN RB7=OUT
        movwf   TRISB           ;Set PORTB
        bcf     STATUS,rp0      ;Change to Bank0
        movlw   0x00            ;start with everything off
        movwf   PORTB            
        movwf   bitsB47         ;Store in local variable
;============================
; set up interrupts
;============================
; Clear external interrupt flag (RBIF = bit 1)
            bcf INTCON,RBIF      ; Clear flag

; Enable global interrupts (GIE = bit 7)
; Enable RB0 interrupt (RBIE = bit 4)
 
            bsf INTCON,GIE       ; Enable global int (bit 7)
            bsf INTCON,RBIE      ; Enable the RB port change                                                                                                            ; interrupt(bit 3)
;***********************************************
;**************** Motor drive   *********************;
;***********************************************
drive1   call    gofwd
               goto    drive1

;**************** Forward Drive    *********************;
gofwd   movlw   d'12'
        movwf   fwd_step        
loopf
        movlw   0x05    
        movwf   PORTB
        call    delay
        movlw   0x09    
        movwf   PORTB
        call    delay
        movlw   0x0a    
        movwf   PORTB
        call    delay
        movlw   0x06    
        movwf   PORTB
        call    delay
        decfsz  fwd_step,f
        goto    loopf
        return

  ; Interrupt Service Routine
;====================================================
; Service routine receives control whenever any of
; port-B lines 4 to 7 change state

IntServ:
; First test: make sure source is an RB4-7 interrupt
              btfss INTCON,RBIF    ; RBIF flag is interrupt
              goto notRBIF         ; Go if not RBIF origin
; Save context
              movwf old_w          ; Save w register
              swapf STATUS,w       ; STATUS to w
              movwf old_STATUS     ; Save STATUS

;=========================
;    interrupt action
;=========================
;Movement of second stepper motor

;The interrupt occurs when any of Port-B bits 4 to 7
; have changed STATUS.

            movf   PORTB,w       ; Read Port-B bits
            movwf  temp          ; Save reading
            xorwf  bitsB47,f     ; Xor with old bits,
                                 ; result in f
                                 ; Test each meaningful bit(4                                                        ; and 7)

            btfsc bitsB47,4      ; Test bit 4
            goto bit4Chng        ; Routine for changed bit 4

            btfsc bitsB47,7      ; Test bit 7
            goto bit7Chng        ; Routine for changed bit 7


bit4Chng 
         movlw   0x05    
         movwf   PORTA
         goto    restore

bit7Chng
         movlw   0x06     
         movwf   PORTA
         goto    restore
;====================================
; Storing and restoring 
;====================================
; Store new value of portB

 restore 
         movf temp,w ; This port-B value to w
         movwf bitsB47 ; Store
        ; Restore context
         swapf old_STATUS,w ; Saved status to w
         movfw STATUS ; To STATUS register
         swapf old_w,f ; Swap file register in itself
         swapf old_w,w ; re-swap back to w

 notRBIF:
         bcf INTCON,rbif ; Clear INTCON bit 0

         retfie
 

I looked briefly at your code and I think the problem is this:
you are using the rest of the lines of port b to drive one motor. If you go to page 17 of the datasheet you will see that you should not use the interrupt on change feature if you are going to use port b for other purposes. That is because the RBIF flag gets cleared whenever you read from or write to port b, which means the interrupt may not get set at all. In the latest PIC datasheets they put this in a very visible note. So first of all, change the drive of the first motor or do not use the interrupt on change. You can poll the lines, or use just RB0 as the ext interrupt.

This should not cause a problem in your code, but get in the habit of first saving the context before you do anything else in the ISR, even before you test the interrupt flags. If you got an interrupt, it's because it was enabled and if it was enabled, then you intended it to be enabled, so you will need to save the context and process an interrupt anyway. You think you are saving a few cycles by not saving/ restoring the context. Well, if you disable the interrupts you do not need, then you will not even have to enter the ISR and even do those tests.
The pin is that you can easily make mistakes and return from the ISR without saving or restoring the context. If your ISR was longer you could easily have something fall through to the notRBIF address and return with a bad context. This is just a practical advice for reliable code, not the reason why your code does not work. I think it will once you've solved the interrupt on change issue.
 

    solidsnike

    Points: 2
    Helpful Answer Positive Rating
Thank you very much for your help ... I want your help if allowed Could you help me in the work of code for this project to be benefited from your expertise in this field >>>> my problem now is using two sensors and two motors how i can solve this problem and what is type of interrupt is good to use ,I would be grateful if you

and thanks a lot
 

Since the motors are driven slowly you should have plenty of time to either poll the sensor inputs or to use the TMR0 interrupt and test the sensors in the ISR.

Assuming you are going with the latter, set up timer 0 to interrupt about every 20ms. That will give you good debouncing.
In the ISR read the sensor inputs and either act based on their state, or compare the present state with the previous one (stored previously) and see what changed. Normally this is done using the xor function, like you did.

The above makes sense when you have several inputs and don't want to waste too much time to test them all when nothing changes.
Since you only have two sensors, you might as well just test each bit and act accordingly, since this does not take too much time in the ISR.

If you are going to poll the sensors instead of using interrupts, just poll them every 20ms or so, again for debouncing. To do this you can use a different delay, of about 20ms and every time it expires you test the inputs and act accordingly.
The same 20ms can be used to create the time base for the motor control. So after each input poll just decrement a counter that tells you when you need to change the phase driver state.

This applies if the motor period is longer than 20ms. Otherwise do it the other way around. Every time you change the motor phases, decrement a counter and when zero poll the sensor inputs.

Finally, you can OR the two sensor inputs, if possible and use the INT to interrupt the micro. In the ISR test which line actually caused the interrupt and act. This makes sense if the additional H/W (the gate) is cheap or not needed (for open-drain sensors), or when the timing is so tight that you cannot afford to waste any time polling or being interrupted by TMR0 just to see that there is nothing to do.

Have I confused you yet?
 

    solidsnike

    Points: 2
    Helpful Answer Positive Rating
thanks very much for these informations , but i have a little information about that ... i mean if you can convert these information to code i can trace and simulate it I would be grateful . and i will study this information too

Note: i have two sensors : one to move the second motor forward and the other to move it backward

i prefer that if i can make this work without interrupt but i dont how i read your last reply but i didnot understand

and thanks a lot
 

Today my lunch break is almost over, so I won't have time to do it, but hopefully tomorrow I will put together something.

Perhaps the TMR0 interrupt is the easiest. You can try it yourself.
Basically, just set up TMR0 to interrupt every 20ms or so and in the ISR test the lines to see which one was driven to the active state (Hi or LO, whichever you need) and then just drive the second motor 1 step.
 

    solidsnike

    Points: 2
    Helpful Answer Positive Rating
Thank you very much for this effort .....

I will read more about TMR0 interrupt, and will wait until your return to complete this work

thanks for your help .... you are good man
 

Hi,
I modified your code slightly.
Code:
      List   p=pic16f84a 
       include <p16f84A.inc> 
       __config _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF 

;constants
TMR0_RLD     EQU D'178' ;reload value for TMR0
MASK            EQU 0xF0   ;used to mask out unused bits of port b
OPTION_CFG EQU B'10000111'  ;used to init option reg; no pullups, prescaler on TMR0 with 1:256 ratio
INTCON_CFG EQU B'10100000'  ;enable GIE and T0IE, clear all flags

; variables in PIC RAM 
        cblock   0x0d       ; Start of block 
        hours               ; counter of hours 
        mins                ; counter of mins 
        secs                ; counter of secs 
        NbHi                
        NbLo                ; counters 
        NaHi 
        NaLo 
        old_w               ; Context saving 
        old_STATUS          ; saving the STATUS 
        bitsB47             ; Storage for previous value 
                            ; in port-B bits 4-7 
        temp                ; Temporary storage 
        fwd_step 
        endc 
        rp0 equ .5 
;============================= 
;        Reset vector 
;============================= 
        org 0 ; start at address 0 
        goto main 
;============================= 
;       interrupt handler 
;============================= 
        org 0x04 


;*********************************************** 
;****************   Main program**************** 
;*********************************************** 
main: 
    ; Disable port-B internal pullups 
    ; Interrupts on falling edge of pushbutton action 
       ; movlw   0xbf            ;RBPU=1 Pull up not use 
        movlw OPTION_CFG   ;no pullups, prescaler on TMR0 with 1:256 ratio
        movwf   OPTION_REG      ;Set OPTION_REG

        movlw TMR0_RLD            ;set up TMR0 for interrupts every 20ms @4MHz clock
        movwf TMR0             ;at 16MHz load TMR0 with 0, for 16ms interrupts
 
        bsf     STATUS,rp0      ;Change to Bank1 
        clrf    TRISA           ;Set PORTA all OUT 
        movlw   0xf0            ;RB0,1,2.5=IN RB7=OUT 
        movwf   TRISB           ;Set PORTB 
        bcf     STATUS,rp0      ;Change to Bank0

        ;movlw   0x00            ;start with everything off 
        ;movwf   PORTB       
;I do not agree with that above

        movf PORTB,W          ;take the actual reading
        andlw MASK               ;clear unnecessary bits
        movwf   bitsB47         ;Store in local variable 
;============================ 
; set up interrupts 
;============================ 
        movlw INTCON_CFG   ;enable GIE and T0IE, clear all flags
        movwf INTCON         ;
;*********************************************** 
;**************** Motor drive   *********************; 
;*********************************************** 
drive1   call    gofwd 
               goto    drive1 

;**************** Forward Drive    *********************; 
gofwd   movlw   d'12' 
        movwf   fwd_step        
loopf 
        movlw   0x05    
        movwf   PORTB 
        call    delay 
        movlw   0x09    
        movwf   PORTB 
        call    delay 
        movlw   0x0a    
        movwf   PORTB 
        call    delay 
        movlw   0x06    
        movwf   PORTB 
        call    delay 
        decfsz  fwd_step,f 
        goto    loopf 
        return 

  ; Interrupt Service Routine 
;==================================================== 
; We get here on TMR0 interrupt

IntServ: 
; Save context 
              movwf old_w          ; Save w register 
              swapf STATUS,w       ; STATUS to w 
              movwf old_STATUS     ; Save STATUS 

            movlw TMR0_RLD
            movwf TMR0            ;reload TMR0 for next interrupt
            bcf INTCON, T0IF    ;clear interrupt flag

            movf   PORTB,w       ; Read Port-B bits
            andlw MASK             ;clear the other bits, because they can be in any state
            movwf temp            ;save new reading for now
            xorwf bitsB47,f      ;compare with old
            btfsc STATUS,Z       ;if anything changed, the result will not be zero, skip
            goto restore           ;if nothing changed, restore context and exit


            btfsc bitsB47,4      ; Test bit 4 
            goto bit4Chng        ; Routine for changed bit 4 

            btfsc bitsB47,7      ; Test bit 7 
            goto bit7Chng        ; Routine for changed bit 7
            goto restore          ;it must be one of the other 2 bits, ignore and exit; this was missed in the original code and I did not see it, either


bit4Chng 
         movlw   0x05    
         movwf   PORTA 
         goto    restore 

bit7Chng 
         movlw   0x06      
         movwf   PORTA 
         ;goto    restore   ;not needed, just fall through
;==================================== 
; Storing and restoring 
;==================================== 
; Store new value of portB 

 restore 
         movf temp,w ; This port-B value to w 
         movwf bitsB47 ; Store 

        ; Restore context 
         swapf old_STATUS,w ; Saved status to w 
         movfw STATUS ; To STATUS register 
         swapf old_w,f ; Swap file register in itself 
         swapf old_w,w ; re-swap back to w 
         retfie
 

    solidsnike

    Points: 2
    Helpful Answer Positive Rating
hiiii VVV

i will study this code again with these modifications.... must be understanded

thanks a lot
 

Code:
;constants 
TMR0_RLD     EQU D'178' ;reload value for TMR0 
MASK            EQU 0xF0   ;used to mask out unused bits of port b 
OPTION_CFG EQU B'10000111'  ;used to init option reg; no pullups, prescaler on TMR0 with 1:256 ratio 
INTCON_CFG EQU B'10100000'  ;enable GIE and T0IE, clear all flags

I know that from the constant above the value of after the EQU must be address from the memory not value …..when I need to insert value to a variable must use MOV instruction ….

And also the option_CFG if that mean the option register so the address of this register is in HEX (81h) … fi I need to insert value to the option reg. must I use MOV instruction for this operation >> also for INTCON

Can you explain these pleas?


Code:
main: 
    ; Disable port-B internal pullups 
    ; Interrupts on falling edge of pushbutton action 
       ; movlw   0xbf            ;RBPU=1 Pull up not use 
        movlw OPTION_CFG   ;no pullups, prescaler on TMR0 with 1:256 ratio 
        movwf   OPTION_REG      ;Set OPTION_REG 

        movlw TMR0_RLD            ;set up TMR0 for interrupts every 20ms @4MHz clock 
        movwf TMR0             ;at 16MHz load TMR0 with 0, for 16ms interrupts 
  
        bsf     STATUS,rp0      ;Change to Bank1 
        clrf    TRISA           ;Set PORTA all OUT 
        movlw   0xf0            ;RB0,1,2.5=IN RB7=OUT 
        movwf   TRISB           ;Set PORTB 
        bcf     STATUS,rp0      ;Change to Bank0 

        ;movlw   0x00            ;start with everything off 
        ;movwf   PORTB        
;I do not agree with that above


Why! you are not agree for that above?!!!

I read your modifications again and again and I confused your modifications overlaps with my code I don’t know what is the TMR0 do?

Pleaz don’t modify my code if you can write your code without mine…..and I will study yours …. Pleaz take your time for that if you can don’t hurry and specify the pins of the output and what the TMR0 do exactly?
And if you can take the delay after every step of the first motor around three minute or more…. if you can

I would be grateful for your help
 

I thought that using your code as a start was going to be easier for you, since you already know how most of it works. That was the reason I asked for it in the first place.

The constants are just that, they get loaded into W by a movlw instructions. They do not necessarily have to be memory addresses.
The use of constants is highly recommended, because they make the code easy to understand and maintain. Suppose I was wrong about the TMR0 reload value. It appears twice in the code, but if it appeared 30 times you would need to change all of them. If you forget one, you can just create a bug: the code works OK most of the time, except under certain conditions.
The same applies to OPTION_CFG, it is just the value that needs to be loaded into the option register.

The output pins are unchanged. Whatever you used in your code should still work.

Timer 0 is used to generate an interrupt every 20ms for you to read the switches on port b bits 7:4. Teh 20ms will give you good debouncing.
The 20ms was calculated for a 4MHz clock. If you are running at anothr frequency, just change the TMR0_RLD constant at the beginning of the code.

I did not agree with your previous two instructions, which I commented out. That is because you assumed the sensors to be in a certain state. What I did was actually read them and save their state. That way you know that even the very first reading thereafter will produce correct results.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top