Rotate stepper motor left and right

Discussion in 'Embedded Systems and Microcontrollers' started by bazaic, Jan 6, 2014.

  1. bazaic

    Thread Starter New Member

    Jan 6, 2014
    5
    0
    Hi. I'm trying to rotate a step-by-step motor 20 times to left and 20 times to right and on and on. I'm using a PIC 16F917. I tried to make a program, but it only rotates the motor to the left. I used 2 variables one to retain 20 and one to use like a contor. Please help me see what is wrong.

    Code ( (Unknown Language)):
    1.  
    2. #INCLUDE P16F917.INC
    3.  
    4. MPP         EQU         20H
    5. VFIX        EQU         0x70
    6.             CBLOCK      0x20
    7.             VAR
    8.             ENDC
    9.  
    10.             ORG         0000H
    11.  
    12. RESET:      GOTO        INIT
    13.  
    14.             ORG         0004H
    15.            
    16. MAIN:      
    17.             INCF        VAR,W
    18.             GOTO        RR
    19.             MOVLW       VFIX
    20.             SUBWF       VAR,W
    21.             BTFSS       STATUS,Z
    22.             GOTO        MAIN
    23.             MOVWF       0
    24.             MOVLW       VAR
    25. CALL_RL:
    26.             INCF        VAR,W
    27.             GOTO        RL
    28.             MOVLW       VFIX
    29.             SUBWF       VAR,W
    30.             BTFSS       STATUS,Z
    31.             GOTO        CALL_RL
    32.             MOVWF       0
    33.             MOVLW       VAR
    34.  
    35.             GOTO        MAIN
    36.            
    37.  
    38.  
    39. RR:         BCF         PIR1,CCP1IF
    40.             RRF         MPP,F
    41.             BCF         MPP,7
    42.             BTFSC       STATUS,C
    43.             BSF         MPP,7
    44.             MOVF        MPP,W
    45.             MOVWF       PORTD
    46.             RETFIE
    47.  
    48. RL:         BCF         PIR1,CCP1IF
    49.             RLF         MPP,F
    50.             BCF         MPP,0
    51.             BTFSC       STATUS,C
    52.             BSF         MPP,0
    53.             MOVF        MPP,W
    54.             MOVWF       PORTD
    55.             RETFIE
    56.  
    57. INIT:       MOVLW       20
    58.             MOVWF       VFIX
    59.             MOVLW       0
    60.             MOVWF       VAR
    61.  
    62.             CLRF        STATUS
    63.             MOVLW       88H
    64.             MOVWF       MPP
    65.            
    66. PD_INI:     CLRF        PORTD
    67.             BSF         STATUS,RP0
    68.             MOVLW       0FH
    69.             MOVWF       TRISD          
    70.             BCF         STATUS,RP0
    71.            
    72. INTINI:     MOVLW       0C0H
    73.             MOVWF       INTCON
    74.             BSF         STATUS,RP0
    75.             MOVLW       04H
    76.             BCF         STATUS,RP0
    77.             CLRF        PIR1
    78.            
    79. T1_INI:     MOVLW       0AH
    80.             MOVWF       T1CON
    81.             CLRF        TMR1H
    82.             CLRF        TMR1L
    83.            
    84. CCPINI:     MOVLW       0BH
    85.             MOVWF       CCP1CON
    86.             MOVLW       20H
    87.             MOVWF       CCPR1H
    88.             CLRF        CCPR1L
    89.        
    90.             BSF         T1CON,TMR1ON
    91.             RETURN
    92.             END
    93.  
     
    Last edited by a moderator: Jan 6, 2014
  2. JohnInTX

    Moderator

    Jun 26, 2012
    2,347
    1,029
    MPP and VAR are both located at 20h. Put MPP in the CBLOCK.

    After reset, you goto INIT which sets some things up but RETURNS at the end - returns to where??? In actual use, it probably returns to 0000h, restarting every time. You need some loop construct.

    MAIN is at the interrupt vector presumably servicing timer 1 interrupt. The code bumps VAR into W then jumps to RR. It will never execute anything below that (CALL_RL, RL etc.). I don't see where the incremented VAR (in W) is used as its clobbered in subsequent code. Note that incf VAR,W does NOT change the value of VAR in memory, it only increments it and places the result in W. Assuming it got past the GOTO, W is immediately clobbered by MOVLW VFIX.

    You mix interrupt code with normal code including a GOTO 0 in the interrupt routine. You can't do that. Interrupts are to service time-sensitive events (in your case time to step the motor) from anywhere in the rest of the program. The service routine gets called when the event happens, you perform the function then return(with retfie) to the rest of the program. Since the interrupt can happen anywhere, you must save the context of the interrupted program (W, STATUS etc) and restore it before retfie. You do not do any context saving in the interrupt code, a sure recipe for disaster.

    I would recommend that you revisit your design and create a good flow chart. Desk check the design by manually running through the flow chart with your finger. Find those places that don't make sense i.e. the RETURN at the end of INIT. Use better names i.e. MAIN is a name that everyone associates with the main program, not an interrupt.

    Use descriptive names for your variables. VAR means what, a variable? I get that. What is its function? If it counts motor steps then name it MotorStepCounter. It will help you as you write and debug your code and also help others who are trying to understand it.

    Use comments. After desk checking the flow chart, start writing your code by adding the comments FIRST i.e. ;Initialize timer 1 to 10msec interrupt, ;Step the motor clockwise by pulsing RD0 or whatever. Then under each comment block, add the code that makes it happen using the flow chart as a guide.

    I think the fact that the motor runs at all is sheer luck so far but don't lose heart. Review your design, flow it out and trace the logic. Post the flow chart, revised code and schematic. We can go from there.

    Good luck!
     
    Last edited: Jan 6, 2014
    bazaic likes this.
  3. bazaic

    Thread Starter New Member

    Jan 6, 2014
    5
    0
    I used your advice and I wrote the program again. Do you think that now it is correct?

    Code ( (Unknown Language)):
    1.  
    2. #INCLUDE P16F917.INC
    3.  
    4. MPP             EQU         20H
    5. MOTORSTEPCOUNTER    EQU     24H
    6. ROTATEFIXEDNUMBER   EQU     30H
    7. SELECTROTATION      EQU     34H
    8.            
    9.  
    10.             ORG     0000H
    11.  
    12. RESET:          GOTO        INIT
    13.  
    14.             ORG     0004H                   ;JUMP ADDRESS FROP CCP IT OCCURS WHEN TMR1H = CCPR1H AND TMR1L = CCPR1L
    15.    
    16. MAIN:           DECFSZ      SELECTROTATION,0            ;IF SELECTROTATION=0 THE MOTOR ROTATES ON THE RIGHT,ELSE THE MOTOR ROTATES ON THE LEFT                                             
    17.             GOTO        LEFT_ROTATION
    18.                                         ;THE ROUTINE FOR RIGHT ROTATION
    19. RIGHT_ROTATION:        
    20.             INCF        MOTORSTEPCOUNTER,f          ;INCREMENT MOTORSTEPCOUNTER AND SAVE THE CHANGE IN MOTORSTEPCOUNTER
    21.             BCF         PIR1,CCP1IF             ;DELETE INTRERRUPT "FLAG"
    22.             RRF         MPP,F                   ;ROTATE MPP VARIABLE THROUGH CARRY
    23.             BCF         MPP,7                   ;PUT ON 0 THE BIT ENTERED FROM CARRY IN BIT 7 OF MPP
    24.             BTFSC       STATUS,C                ;IF CARRY=0, BIT 7 REMAINS THE SAME
    25.             BSF     MPP,7                   ;ROTATE MPP WITHOUT CARRY
    26.             MOVF        MPP,W                   ;MPP IS TAKEN OUT ON PORT D
    27.             MOVWF       PORTD
    28.             MOVLW       MOTORSTEPCOUNTER            ;PUT IN W MOTORSTEPCOUNTER
    29.             SUBWF       ROTATEFIXEDNUMBER,0         ;SUBSTRACT: ROTATEFIXEDNUMBER-MOTORSETPCOUNTER
    30.             BTFSS       STATUS,Z                ;IF MOTORSTEPCOUNTER<ROTATEFIXEDNUMBER THEN WE RETURN TO GOTO $
    31.             RETFIE
    32.             MOVWF       0                   ;ELSE WE MAKE MOTORSTEPCOUNTER=0 AND THEN WE RETFIE TO GOTO $
    33.             MOVLW       MOTORSTEPCOUNTER
    34.             MOVWF       1
    35.             MOVLW       SELECTROTATION
    36.             RETFIE
    37.                                    
    38.  
    39.  
    40.                                         ;THE ROUTINE FOR LEFT ROTATION
    41.                                         ;IT IS ALMOST THE SAME LIKE FOR THE RIGHT
    42. LEFT_ROTATION:
    43.             MOVLW       MOTORSTEPCOUNTER
    44.             ADDLW       1
    45.             MOVWF       MOTORSTEPCOUNTER
    46.             BCF         PIR1,CCP1IF
    47.             RLF         MPP,F
    48.             BCF         MPP,0
    49.             BTFSC       STATUS,C
    50.             BSF     MPP,0
    51.             MOVF        MPP,W
    52.             MOVWF       PORTD
    53.             MOVLW       MOTORSTEPCOUNTER
    54.             SUBWF       ROTATEFIXEDNUMBER,W
    55.             BTFSS       STATUS,Z
    56.             RETFIE
    57.             MOVWF       0
    58.             MOVLW       MOTORSTEPCOUNTER
    59.             MOVWF       0
    60.             MOVLW       SELECTROTATION
    61.             RETFIE
    62.  
    63.            
    64.                                         ;INITIALIZE ROTATEFIXEDNUMBER AND MOTORSTEPCOUNTER
    65. INIT:           MOVLW       20
    66.             MOVWF       ROTATEFIXEDNUMBER
    67.             MOVWL       0
    68.             MOVWF       SELECTROTATION
    69.             MOVLW       0
    70.             MOVWF       MOTORSTEPCOUNTER
    71.                                         ;INITIALIZE MPP
    72.                                         ;THE CODE BELOW I USED IT TO ROTATE THE MOTOR TO THE RIGHT SIDE AND IT WORKED;
    73.             CLRF        STATUS
    74.             MOVLW       88H
    75.             MOVWF       MPP
    76.  
    77.            
    78. PD_INI:         CLRF        PORTD
    79.             BSF     STATUS,RP0
    80.             MOVLW       0FH
    81.             MOVWF       TRISD          
    82.             BCF     STATUS,RP0
    83.            
    84.  
    85. INTINI:         MOVLW       0C0H
    86.             MOVWF       INTCON
    87.             BSF     STATUS,RP0
    88.             MOVLW       04H
    89.             BCF     STATUS,RP0
    90.             CLRF        PIR1
    91.            
    92.  
    93. T1_INI:         MOVLW       0AH
    94.             MOVWF       T1CON
    95.             CLRF        TMR1H
    96.             CLRF        TMR1L
    97.            
    98. CCPINI:         MOVLW       0BH
    99.             MOVWF       CCP1CON
    100.             MOVLW       20H
    101.             MOVWF       CCPR1H
    102.             CLRF        CCPR1L
    103.        
    104.             BSF     T1CON,TMR1ON
    105.             GOTO        $
    106.             END
    107.    
    108.    
    109.  
     
    Last edited by a moderator: Jan 7, 2014
  4. JohnInTX

    Moderator

    Jun 26, 2012
    2,347
    1,029
    I don't think it assembles due to the MOVWL instruction.
    Have you tried it?
    What are you using for IDE, assembler and debug?

    After getting it to assemble, review the MOV-- instructions in the instruction set. You have confused some of them. For example:
    Code ( (Unknown Language)):
    1.         MOVWF    0
    2.         MOVLW    MOTORSTEPCOUNTER
    3.         MOVWF    0
    4.         MOVLW    SELECTROTATION
    does not clear the two registers.
    Code ( (Unknown Language)):
    1.         MOVLW    MOTORSTEPCOUNTER
    2.         ADDLW    1
    3.         MOVWF    MOTORSTEPCOUNTER
    does not add 1 to MOTORSTEPCOUNTER. It actually writes 25h to MOTORSTEPCOUNTER every time. Do you see why?
    Finally, review the ,F and ,W destination indicators:
    does not decrement SELECTROTATION because the result is placed in WREG.

    EDIT: Looking at it again I see that you use DECFSZ SELECTROTATION as a left/right flag so placing the result in W is OK. However, the logic is wrong. When it =1, decrementing it will cause the code to fall through to RIGHT_ROTATION but at the end of the 20 steps to the right, you load it to 1 again instead of 0 to make it turn left. Actually, using a single-bit flag here would be more appropriate and easier to follow.

    There are some other problems but lets start with those.
    Have fun!
     
    Last edited: Jan 8, 2014
  5. bazaic

    Thread Starter New Member

    Jan 6, 2014
    5
    0
    I made some changes. how do I make the substract 20-valueof(RotateMotorCounter)? and do a conditional jump after?

    I mean here
    Code ( (Unknown Language)):
    1.             MOVLW       MOTORSTEPCOUNTER            ;PUT IN W MOTORSTEPCOUNTER
    2.             SUBLW       14H                     ;SUBSTRACT: ROTATEFIXEDNUMBER-MOTORSETPCOUNTER
    3.             BTFSS       STATUS,Z                ;IF MOTORSTEPCOUNTER<ROTATEFIXEDNUMBER THEN WE RETURN TO GOTO $
    4.             GOTO        RETURNROTATE
    Code ( (Unknown Language)):
    1. #INCLUDE P16F917.INC
    2.  
    3. MPP             EQU         20H
    4. MOTORSTEPCOUNTER    EQU     24H
    5.  
    6. SELECTROTATION      EQU     34H
    7.            
    8.  
    9.             ORG     0000H
    10.  
    11. RESET:      GOTO        INIT
    12.  
    13.             ORG     0004H                   ;JUMP ADDRESS FROP CCP IT OCCURS WHEN TMR1H = CCPR1H AND TMR1L = CCPR1L
    14.    
    15. MAIN:       DECFSZ      SELECTROTATION,0            ;IF SELECTROTATION=0 THE MOTOR ROTATES ON THE RIGHT,ELSE THE MOTOR ROTATES ON THE LEFT                                             
    16.             GOTO        LEFT_ROTATION
    17.                                         ;THE ROUTINE FOR RIGHT ROTATION
    18. RIGHT_ROTATION:        
    19.             INCF        MOTORSTEPCOUNTER,f          ;INCREMENT MOTORSTEPCOUNTER AND SAVE THE CHANGE IN MOTORSTEPCOUNTER
    20.             BCF         PIR1,CCP1IF             ;DELETE INTRERRUPT "FLAG"
    21.             RRF         MPP,F                   ;ROTATE MPP VARIABLE THROUGH CARRY
    22.             BCF         MPP,7                   ;PUT ON 0 THE BIT ENTERED FROM CARRY IN BIT 7 OF MPP
    23.             BTFSC       STATUS,C                ;IF CARRY=0, BIT 7 REMAINS THE SAME
    24.             BSF         MPP,7                   ;ROTATE MPP WITHOUT CARRY
    25.             MOVF        MPP,W                   ;MPP IS TAKEN OUT ON PORT D
    26.             MOVWF       PORTD
    27.             MOVLW       MOTORSTEPCOUNTER            ;PUT IN W MOTORSTEPCOUNTER
    28.             SUBLW       14H                     ;SUBSTRACT: ROTATEFIXEDNUMBER-MOTORSETPCOUNTER
    29.             BTFSS       STATUS,Z                ;IF MOTORSTEPCOUNTER<ROTATEFIXEDNUMBER THEN WE RETURN TO GOTO $
    30.             GOTO        RETURNROTATE
    31.             MOVLW       00H                 ;ELSE WE MAKE MOTORSTEPCOUNTER=0 AND THEN WE RETFIE TO GOTO $
    32.             MOVWF       MOTORSTEPCOUNTER
    33.             MOVLW       02H
    34.             MOVWF       SELECTROTATION
    35.             GOTO        RETURNROTATE
    36.                                    
    37.  
    38.  
    39.                                         ;THE ROUTINE FOR LEFT ROTATION
    40.                                         ;IT IS ALMOST THE SAME LIKE FOR THE RIGHT
    41. LEFT_ROTATION:
    42.             INCF        MOTORSTEPCOUNTER,f
    43.             BCF         PIR1,CCP1IF
    44.             RLF         MPP,F
    45.             BCF         MPP,0
    46.             BTFSC       STATUS,C
    47.             BSF         MPP,0
    48.             MOVF        MPP,W
    49.             MOVWF       PORTD
    50.             MOVF        MOTORSTEPCOUNTER
    51.             SUBLW       14H
    52.             BTFSC       STATUS,Z
    53.             GOTO        RETURNROTATE
    54.             MOVLW       00H
    55.             MOVWF       MOTORSTEPCOUNTER
    56.             MOVLW       01H
    57.             MOVWF       SELECTROTATION
    58.             GOTO        RETURNROTATE
    59.  
    60.            
    61.                                         ;INITIALIZE ROTATEFIXEDNUMBER AND MOTORSTEPCOUNTER
    62. INIT:      
    63.             MOVLW       02H
    64.             MOVWF       SELECTROTATION
    65.             MOVLW       00H
    66.             MOVWF       MOTORSTEPCOUNTER
    67.                                         ;INITIALIZE MPP
    68.                                         ;THE CODE BELOW I USED IT TO ROTATE THE MOTOR TO THE RIGHT SIDE AND IT WORKED;
    69.             CLRF        STATUS
    70.             MOVLW       88H
    71.             MOVWF       MPP
    72.  
    73.            
    74. PD_INI:     CLRF        PORTD
    75.             BSF     STATUS,RP0
    76.             MOVLW       0FH
    77.             MOVWF       TRISD          
    78.             BCF     STATUS,RP0
    79.            
    80.  
    81. INTINI:     MOVLW       0C0H
    82.             MOVWF       INTCON
    83.             BSF     STATUS,RP0
    84.             MOVLW       04H
    85.             BCF     STATUS,RP0
    86.             CLRF        PIR1
    87.            
    88.  
    89. T1_INI:     MOVLW       0AH
    90.             MOVWF       T1CON
    91.             CLRF        TMR1H
    92.             CLRF        TMR1L
    93.            
    94. CCPINI:     MOVLW       0BH
    95.             MOVWF       CCP1CON
    96.             MOVLW       20H
    97.             MOVWF       CCPR1H
    98.             CLRF        CCPR1L
    99.        
    100.             BSF     T1CON,TMR1ON
    101.  
    102. RETURNROTATE:   MOVLW       0C0H        ;ACTIVATE INTRERRUPTS
    103.                 MOVWF       INTCON
    104.                 GOTO        $
    105.                 END
     
  6. JohnInTX

    Moderator

    Jun 26, 2012
    2,347
    1,029
    I am not sure why you made the changes you did but the code in post #3 is workable, this one is not.

    The primary problem is that you GOTO out of the interrupt routine to the non-interrupt routine. You can't do that, period. Interrupts push the interrupted routine's return address on the stack, retfie pops the stack and resumes execution of the interrupted routine. GOTO leaves the stack pushed. This code will run exactly 8 times before stack overflow and then the program is crashed. Again, if its running at all its pure luck.

    To continue, stop writing code then:
    Write and post a flow chart. EDIT: this is important, I flowed out your code by printing it, traceing the flow with a red pen, and found the problems in a jiffy. Your latest revision restores some problems that you had in the original code that likely would have jumped out in a good flow chart.
    Re-read my posts until you understand the points presented. If you have questions about any points, I will answer them. EDIT: I don't mean to sound harsh here but you've missed some important things.
    Revert to your post #3 code, its interrupt uses the stack correctly. EDIT: I also have it up as a project here and we can fix it together.

    For your specific question:
    Code ( (Unknown Language)):
    1.  
    2.   MOVLW MOTORSTEPCOUNTER
    3.   SUBLW 14h ; subtract W from LITERAL value (14h - motor steps so far)
    4.   BTFSS STATUS,Z
    5.   GOTO RETURNROTATE
    MOVLW MOTORSTEPCOUNTER
    This is incorrect. MOVLW puts the ADDRESS of the variable (24h) into W, not its value. To get its value use
    Code ( (Unknown Language)):
    1.  
    2.   MOVF MOTORSTEPCOUNTER,W ; move value into W
    3.   SUBLW 14h ; subtract W from LITERAL value (14h - motor steps so far)
    4.   BTFSS STATUS,Z ; skip when Z set (they are equal)
    5.   GOTO IRQreturn ; has not counted to 20 yet. Done, jump to the RETFIE
    6.  
    7.   ; process the next step then..
    8.  
    9.   GOTO IRQreturn ; jump to the RETFIE
    10.  
    11.  ; more code etc
    12.  
    13. IRQreturn:
    14.  RETFIE ; return to the interrupted code - pops the stack, reenables the interrupt
    A few more things:
    Using DECFSZ as a flag is discouraged as its counter-intuitive. I see you modified the code but its still wrong, mainly because its more complicated than it has to be. Use a one bit flag:

    Code ( (Unknown Language)):
    1.  
    2.  SELECTROTATION equ 34h ; LSbit =1 rotates left, 0 rotates right
    3.  
    4. IRQservice:  ; used to be called MAIN
    5.  btfsc SELECTROTATION,0 ; check flag bit
    6.  goto LEFT_ROTATION ; flag is 1, go left
    7.  
    8. RIGHT_ROTATION:
    9.   ; do right 20 times then
    10.  bsf SELECTROTATION,0 ; set flag to go left
    11.  goto IRQreturn
    12.  
    13. LEFT_ROTATION:
    14.  ; do left 20 times then..
    15.  bcf SELECTROTATION,0 ; clear flag to go right
    16.  goto IRQreturn
    17.  
    18. IRQreturn:
    19.  RETFIE
    Note how the flag can only have 2 states and the motor can only run 2 directions. Nice fit. Using a full byte and inspecting its value by counting has its uses, just not here.

    There are more things to do here but let's get it back on track first then clean up the rest.

    Carry on.
     
    Last edited: Jan 8, 2014
  7. bazaic

    Thread Starter New Member

    Jan 6, 2014
    5
    0
    Sorry that I reply so late. I hope the code is better than the rest I posted.
    Code ( (Unknown Language)):
    1. #INCLUDE P16F917.INC
    2.  
    3. MPP             EQU         20H
    4. MOTORSTEPCOUNTER    EQU     24H
    5.  
    6. SELECTROTATION      EQU     34H
    7.            
    8.  
    9.             ORG     0000H
    10.  
    11. RESET:      GOTO        INIT
    12.  
    13.             ORG     0004H                   ;JUMP ADDRESS FROP CCP IT OCCURS WHEN TMR1H = CCPR1H AND TMR1L = CCPR1L
    14.    
    15. MAIN:       BTFSC       SELECTROTATION,0            ;IF SELECTROTATION=0 THE MOTOR ROTATES ON THE RIGHT,ELSE THE MOTOR ROTATES ON THE LEFT                                             
    16.             GOTO        LEFT_ROTATION
    17.                                         ;THE ROUTINE FOR RIGHT ROTATION
    18. RIGHT_ROTATION:        
    19.             INCF        MOTORSTEPCOUNTER,f          ;INCREMENT MOTORSTEPCOUNTER AND SAVE THE CHANGE IN MOTORSTEPCOUNTER
    20.             BCF         PIR1,CCP1IF             ;DELETE INTRERRUPT "FLAG"
    21.             RRF         MPP,F                   ;ROTATE MPP VARIABLE THROUGH CARRY
    22.             BCF         MPP,7                   ;PUT ON 0 THE BIT ENTERED FROM CARRY IN BIT 7 OF MPP
    23.             BTFSC       STATUS,C                ;IF CARRY=0, BIT 7 REMAINS THE SAME
    24.             BSF         MPP,7                   ;ROTATE MPP WITHOUT CARRY
    25.             MOVF        MPP,W                   ;MPP IS TAKEN OUT ON PORT D
    26.             MOVWF       PORTD
    27.             MOVF        MOTORSTEPCOUNTER,W                      ;PUT IN W MOTORSTEPCOUNTER
    28.             SUBLW       14H             ;SUBSTRACT: ROTATEFIXEDNUMBER-MOTORSETPCOUNTER
    29.             BTFSS       STATUS,Z                ;IF MOTORSTEPCOUNTER<ROTATEFIXEDNUMBER THEN WE RETURN TO GOTO $
    30.             GOTO        IRQRETURN
    31.             MOVLW       00H                 ;ELSE WE MAKE MOTORSTEPCOUNTER=0 AND THEN WE RETFIE TO GOTO $
    32.             MOVWF       MOTORSTEPCOUNTER
    33.             BSF         SELECTROTATION,0
    34.             GOTO        IRQRETURN
    35.                                    
    36.  
    37.  
    38.                                         ;THE ROUTINE FOR LEFT ROTATION
    39.                                         ;IT IS ALMOST THE SAME LIKE FOR THE RIGHT
    40. LEFT_ROTATION:
    41.             INCF        MOTORSTEPCOUNTER,f
    42.             BCF         PIR1,CCP1IF
    43.             RLF         MPP,F
    44.             BCF         MPP,0
    45.             BTFSC       STATUS,C
    46.             BSF         MPP,0
    47.             MOVF        MPP,W
    48.             MOVWF       PORTD
    49.             MOVF        MOTORSTEPCOUNTER,W
    50.             SUBLW       14H
    51.             BTFSS       STATUS,Z
    52.             GOTO        IRQRETURN
    53.             MOVLW       00H
    54.             MOVWF       MOTORSTEPCOUNTER
    55.             BCF         SELECTROTATION,0
    56.             GOTO        IRQRETURN
    57.  
    58. IRQRETURN:
    59.             RETFIE
    60.  
    61.            
    62.                                         ;INITIALIZE ROTATEFIXEDNUMBER AND MOTORSTEPCOUNTER
    63. INIT:      
    64.             MOVLW       02H
    65.             MOVWF       SELECTROTATION
    66.             MOVLW       00H
    67.             MOVWF       MOTORSTEPCOUNTER
    68.                                         ;INITIALIZE MPP
    69.                                         ;THE CODE BELOW I USED IT TO ROTATE THE MOTOR TO THE RIGHT SIDE AND IT WORKED;
    70.             CLRF        STATUS
    71.             MOVLW       88H
    72.             MOVWF       MPP
    73.  
    74.            
    75. PD_INI:     CLRF        PORTD
    76.             BSF     STATUS,RP0
    77.             MOVLW       0FH
    78.             MOVWF       TRISD          
    79.             BCF     STATUS,RP0
    80.            
    81.  
    82. INTINI:     MOVLW       0C0H
    83.             MOVWF       INTCON
    84.             BSF     STATUS,RP0
    85.             MOVLW       04H
    86.             BCF     STATUS,RP0
    87.             CLRF        PIR1
    88.            
    89.  
    90. T1_INI:     MOVLW       0AH
    91.             MOVWF       T1CON
    92.             CLRF        TMR1H
    93.             CLRF        TMR1L
    94.            
    95. CCPINI:     MOVLW       0BH
    96.             MOVWF       CCP1CON
    97.             MOVLW       20H
    98.             MOVWF       CCPR1H
    99.             CLRF        CCPR1L
    100.        
    101.             BSF     T1CON,TMR1ON
    102.                 GOTO        $
    103.                 END
    104.    
    105.    
     
  8. bazaic

    Thread Starter New Member

    Jan 6, 2014
    5
    0
    This is the flow chart..a sketch
     
  9. JohnInTX

    Moderator

    Jun 26, 2012
    2,347
    1,029
    Better! I'll go through some things and post an update. There are lots of little things that will take more time to describe than to fix, and you still can see what I mean..

    In the meantime, please read section 16.3.4 CONTEXT SAVING DURING INTERRUPTS in the datasheet.
     
    Last edited: Jan 12, 2014
  10. atferrari

    AAC Fanatic!

    Jan 6, 2004
    2,648
    764
    Hola bazaic,

    I did not read your last version but, prior actually rotating the stepper, you should replace that part by flashing a LED, say red for right and green for left so you know the interrupts scheme is working. Do you actually need them?

    For the test above, sure you could need a delay somewhere so you can see what is going on.

    Later, I would test the rotations alone (no interrupts), separately, to make sure you are actually able in both directions.

    I can not check now, how I actually did it some 15 years ago(?), but I recall, rotating a stepper by outputting a binary value, of the type maybe B'00010001' which was previously rotated left or right as needed.

    Let me tell you, the whole code was extremely short / simple including LEFT, RIGHT, STOP, DISCONNECT.

    One question: where do you keep track in what part of the table of sucessive values you are at every step?

    I do not recall if the stepper was bipolar or unipolar. Sorry.

    Code should be commented.
     
  11. JohnInTX

    Moderator

    Jun 26, 2012
    2,347
    1,029
    It runs under MPSIM..

    I added interrupt context save/restore so you could see how its done. I also fixed up some things in init e.g. sequence of initializing interrupts etc. Most replaced code is commented out in place so you can see what I did. There is more I would recommend doing but this is a big chunk to digest. See what you think.

    Code ( (Unknown Language)):
    1.     #INCLUDE P16F917.INC
    2.  
    3.     radix    hex            ; make sure we know how our numbers get evaluated
    4.     ERRORLEVEL -.302    ; suppress bank notices
    5.  
    6.     ;******************** CONFIGURATION  ************************
    7.  
    8. ;#define DEBUG_WITH_MPSIM ; uncomment this to run in MPSIM (sets TIMER1 to internal clock below)
    9.  
    10. stepsLEFT    equ    .20    ; define how many steps each way..
    11. stepsRIGHT    equ    .20
    12.  
    13.     MESSG "Be sure to disable WDT if its not to be used"
    14.  
    15.     ;******************** BANK 0 RAM  **************************
    16.     cblock    20h
    17. MPP:                1        ; Motor step pattern
    18. MOTORSTEPCOUNTER:    1        ; Counts motor steps
    19. SELECTROTATION:        1        ; Flags:
    20.                             ; Bit 0: 1=Left 0=Right
    21.  
    22.     ;-------------------  INTERRUPT CONTEXT SAVE  ------------
    23. IRQsaveSTATUS:        1        ; saves status register during IRQ
    24. IRQsavePCLATH:        1        ; saves PCLATH during IRQ
    25.     endc
    26.  
    27.     ;*******************  COMMON RAM  ******************
    28.     cblock 71h                ; 70h is reserved for debuggers (PICKit, ICD etc).
    29. IRQsaveW:            1        ; Save W regardless of IRQ bank        
    30.     endc            
    31.  
    32.  
    33.     ;****************** CODE STARTS  ****************************
    34.         ORG         0000H
    35.  
    36. RESET:    
    37.         clrf        PCLATH    ; paranoia strikes deep
    38.         GOTO         INIT
    39.  
    40.     ;*********************** INTERRUPT SERVICE  *****************
    41.         ORG        0004H    
    42.                         ;JUMP ADDRESS FROP CCP IT OCCURS WHEN TMR1H = CCPR1H AND TMR1L = CCPR1L    
    43. serviceIRQ:    
    44.         ;---------------------
    45.         ; First, save context
    46.         movwf    IRQsaveW        ; save W in common RAM
    47.         swapf    STATUS,W        ; get STATUS to W without changing flags
    48.         clrf    STATUS            ; select RAM BANK 0
    49.         movwf    IRQsaveSTATUS    ; save STATUS (its swapped)
    50.         movf    PCLATH,W        
    51.         movwf    IRQsavePCLATH    ; save PCLATH
    52.         clrf    PCLATH            ; ensure ROM page 0 for IRQ routines before any jumps/calls    
    53.  
    54.         ;---------------------
    55.         ; Verify interrupt source - deferred until later
    56.     ;    btfss    PIR1,CCPIF        ; from CCP?
    57.     ;    goto    svcIRQerror        ; no.. handle invalid interrupt
    58.  
    59.         ;---------------------
    60.         ; Service TIMER1
    61.         bcf        PIR1,CCP1IF        ; clear flag early
    62.  
    63.         BTFSC        SELECTROTATION,0    ;IF SELECTROTATION=0 THE MOTOR ROTATES ON THE RIGHT,ELSE THE MOTOR ROTATES ON THE LEFT                                                
    64.         GOTO        LEFT_ROTATION
    65.        
    66.                                         ;THE ROUTINE FOR RIGHT ROTATION
    67. RIGHT_ROTATION:            
    68.     ;    INCF        MOTORSTEPCOUNTER,F        ; ** not yet **INCREMENT MOTORSTEPCOUNTER AND SAVE THE CHANGE IN MOTORSTEPCOUNTER
    69.     ;    BCF         PIR1,CCP1IF                ;DELETE INTRERRUPT "FLAG"
    70.         RRF         MPP,F                     ;ROTATE MPP VARIABLE THROUGH CARRY
    71.         BCF         MPP,7                     ;PUT ON 0 THE BIT ENTERED FROM CARRY IN BIT 7 OF MPP
    72.         BTFSC        STATUS,C                ;IF CARRY=0, BIT 7 REMAINS THE SAME
    73.         BSF            MPP,7                    ;ROTATE MPP WITHOUT CARRY
    74.         MOVF        MPP,W                    ;MPP IS TAKEN OUT ON PORT D
    75.         MOVWF        PORTD
    76.  
    77.         INCF        MOTORSTEPCOUNTER,F    ; keep parts of a function together
    78.         MOVF        MOTORSTEPCOUNTER,W        ;PUT IN W MOTORSTEPCOUNTER
    79.     ;    SUBLW        14H                        ;SUBSTRACT: ROTATEFIXEDNUMBER-MOTORSETPCOUNTER
    80.         sublw        stepsRIGHT                ; avoid literals in the code
    81.         BTFSS        STATUS,Z                ;IF MOTORSTEPCOUNTER<ROTATEFIXEDNUMBER THEN **DONE
    82.         GOTO        IRQRETURN
    83.  
    84.     ;    MOVLW        00H                        ;ELSE WE MAKE MOTORSTEPCOUNTER=0 AND THEN
    85.     ;    MOVWF        MOTORSTEPCOUNTER
    86.         clrf        MOTORSTEPCOUNTER        ; better
    87.         BSF            SELECTROTATION,0
    88.         GOTO        IRQRETURN
    89.                                             ;THE ROUTINE FOR LEFT ROTATION                                            
    90.                                             ;IT IS ALMOST THE SAME LIKE FOR THE RIGHT
    91. LEFT_ROTATION:
    92.     ;    INCF        MOTORSTEPCOUNTER,F
    93.     ;    BCF         PIR1,CCP1IF
    94.         RLF         MPP,F
    95.         BCF         MPP,0
    96.         BTFSC        STATUS,C
    97.         BSF            MPP,0
    98.         MOVF        MPP,W
    99.         MOVWF        PORTD
    100.  
    101.         INCF        MOTORSTEPCOUNTER,F
    102.         MOVF        MOTORSTEPCOUNTER,W
    103.     ;    SUBLW        14H    
    104.         sublw        stepsLEFT
    105.         BTFSS        STATUS,Z
    106.         GOTO        IRQRETURN
    107.  
    108.     ;    MOVLW        00H
    109.     ;    MOVWF        MOTORSTEPCOUNTER
    110.         clrf        MOTORSTEPCOUNTER        ; better
    111.         BCF            SELECTROTATION,0
    112.         GOTO        IRQRETURN
    113.  
    114.         ;-------------------
    115.         ; Restore context
    116. IRQRETURN:
    117.         clrf        STATUS            ; ensure RAM bank 0
    118.         movf        IRQsavePCLATH,W
    119.         movwf        PCLATH            ; restore PCLATH
    120.  
    121.         swapf        IRQsaveSTATUS,W ; restore STATUS and bank
    122.         movwf        STATUS
    123.  
    124.         swapf        IRQsaveW,F        ; swap save W so that we can..
    125.         swapf        IRQsaveW,W        ; swap it again into W without changing STATUS flags
    126.                
    127.         RETFIE                        ; return from IRQ with system restored
    128.  
    129.  
    130.         ;**************** INITIALIZE SYSTEM  ***************************    
    131.  
    132.                                     ;INITIALIZE ROTATEFIXEDNUMBER AND MOTORSTEPCOUNTER
    133. INIT:                                ; power on reset clears things but I like to enforce it
    134.         clrf    INTCON                ; kill interupts
    135.         clrf    STATUS                ; select bank 0    
    136.  
    137.     ;    MOVLW    02H
    138.     ;    MOVWF    SELECTROTATION        ; ?? - its a flag
    139.         bcf        SELECTROTATION,0    ; init rotation direction to RIGHT
    140.  
    141.     ;    MOVLW    00H
    142.     ;    MOVWF    MOTORSTEPCOUNTER
    143.         clrf    MOTORSTEPCOUNTER
    144.                                     ;INITIALIZE MPP
    145.     ;    CLRF    STATUS
    146.         MOVLW    88H            ; init the motor step pattern
    147.         MOVWF    MPP    
    148.    
    149. ;PD_INI: <---- Dont use labels if nothing jumps to or calls it, use a comment instead
    150.         ;----------------------------
    151.         ; Init IO        
    152.         CLRF    PORTD            ; init all step outputs to 0
    153.  
    154.         BSF        STATUS,RP0            
    155.         MOVLW    0FH                ; step outputs on RD7-RD4
    156.         MOVWF    TRISD        
    157.         BCF        STATUS,RP0
    158.        
    159. ;INTINI:        
    160.     ;    MOVLW    0C0H            ; don't enable interrupts before you config the timer/ccp        
    161.     ;    MOVWF    INTCON
    162.     ;    BSF        STATUS,RP0      ; this is missing movwf PIE1..    
    163.     ;    MOVLW    04H
    164.     ;    BCF        STATUS,RP0
    165.     ;    CLRF    PIR1
    166.            
    167.         ;----------------------------
    168.         ; Init Timer 1
    169. ;T1_INI:
    170.     ifdef DEBUG_WITH_MPSIM
    171.         movlw    00h                ; use 00h for debugging with MPSIM
    172.     else    
    173.         MOVLW    0AH                ; normal operation: not gated, 1:1 prescale, timer OFF, LP clock
    174.     endif
    175.                    
    176.         MOVWF    T1CON
    177.         CLRF    TMR1H            ; start at 0
    178.         CLRF    TMR1L
    179.        
    180.         ;----------------------------
    181.         ; Init CCP    
    182. ;CCPINI:        
    183.         MOVLW    0BH                ; Compare mode using TMR1 w/reset
    184.         MOVWF    CCP1CON
    185.         MOVLW    20H                ; set CCP1 to 2000h
    186.         MOVWF    CCPR1H
    187.         CLRF    CCPR1L
    188.  
    189.         ;----------------------------
    190.         ; Init Interrupts
    191.         bcf        PIR1,CCP1IF        ; clear the flag (timer is OFF so it will stay 0)
    192.    
    193.         banksel    PIE1            ; another way to select bank 1 - I don't like it but there is is..
    194.         clrf    PIE2            ; disable unused interrupts
    195.         movlw    B'00000100'        ; enable CCP1IF, disable others
    196.         movwf    PIE1    
    197.         banksel    PIR1            ; re-select bank 0
    198.        
    199.         bsf        INTCON,PEIE        ; enable peripheral interrupt (CCP1)
    200.         BSF        T1CON,TMR1ON    ; start the timer
    201.  
    202.         bsf        INTCON,GIE        ; enable global IRQs LAST
    203.  
    204. MAIN:
    205.         nop                        ; main loop :)
    206.         nop
    207.         GOTO        MAIN
    208.  
    209.         END
    The .zip is from MPLAB 8.x and might read better in the edit window.

    Have fun!
     
    Last edited: Jan 12, 2014
Loading...