Problem with Servo Driver using DT_INST-14/TimerTemplate


Closed Thread
Results 1 to 3 of 3
  1. #1

    Default Problem with Servo Driver using DT_INST-14/TimerTemplate

    This is another attempt to create a servo driver based on instant interrupts. This one almost works, but not quite. I may attempting the imposible; if so, could someone please tell me. I really don't know how to interpret assembly routines.

    This servo driver is based on Darrel Taylor's DT_INTS-14/TimerTemplate which can be found on this Forum. It is easy to set up a 50 hz interrupt to start and repeat standard servo frames. In addition to running a servo I'm driving a brushless motor controller, which also runs on standard servo frames. Testing is done with real hardware, including a motor, controller, and servo.

    The routine shown below works as long as I do not attempt to change the motor drive pulses from full on to full off. The motor actually starts and runs at full speed. However, in order to stop the motor it is necessary to apply full off pulses. When I attempt to do this the program somehow scans through and picks up the full off setting, and applies this to the whole sequence. The result is that the motor will not start.

    Most of the code shown is just a copy of the TimerTemplate. I added the interrupt handler and the few lines in the main section.


    Code:
    'device is PIC 16F684
    
    'set registers
            '...done...
            
            DEFINE OSC 8         '8 Mhz oscillator
    
    'declare variables
            '....done...
            
    ' initialize ports and variables
            portc.1 = 0               'turn off servo
            portc.4 = 0               'initialize servo pulse low
            portc.5 = 0               'initialize throttle pulse low 
            throttlepos = 400         '2*(200) = full throttle
            servopos = 300            '2*(150) = mid range of servo
            MTtime = 100              '10.0 second motor run time
            BKtime = 15               '1.5 second brake time
            ticks = 0                 '0.02 seconds per tick
            tenths = 0                '1/10 seconds
            seconds = 0               'seconds
            sum = 0                   'total time in tenths, e.g. 100 = 10.0 sec.
    
    'arm the motor 
              'Phoenix-10 brushless motor controller requires throttle-off arming
              'for 4 seconds
              '....done...
    
    INCLUDE "DT_INTS-14 for F684.bas"    ; Base Interrupt System with wsave for F684
    INCLUDE "ReEnterPBP.bas"             ; Include if using PBP interrupts
    
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler   TMR1_INT,   ReloadTMR1,   ASM,  no    ; MUST be first
            INT_Handler   TMR1_INT,   _T1handler,   PBP,  yes
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    
    ;--- Match the desired interrupt frequency -------------------
    ;--- See http://DarrelTaylor.com/DT_INTS-14/TimerTemplate.html for more Info.
    @Freq       = 50                  ; 50 Hz Frequency of Interrupts 
    @Prescaler  = 1                   ; Timers Prescaler setting
    T1CON = $00                       ; $00 = Prescaler 1:1, TMR1 OFF
    
    @ INT_ENABLE  TMR1_INT            ; enable Timer 1 interrupts
    
    GOSUB StartTimer                  ; Start the Timer
            
            portc.1 = 1                'turn on servo power
            low Led                    'turn on led
    Main:                            
      ;   ---- Your Main Program goes here ----
    
            if sum => MTtime then     'motor fully on for 10.0 seconds
            high led                  'turn off led .. this signals end of motor run
            goto newtime1             'try to reset throttle to full off
            endif
    
    newtime1:                         ' brake motor for 1.5 seconds
           
    '        throttlepos = 200     ' 2*(100) throttle full off; brake on. This is 
                                   'the problem line. Does not work when uncommented
    
            if sum => (MTtime + BKtime) then   'motor off, braking done
            low led                            'turn on led; signals end of braking
            goto DT      
            endif
    GOTO Main
        '-------------------------------------------
    DT:     
    @ INT_DISABLE  TMR1_INT        ; disable Timer 1 interrupts
         portc.1 = 0               'turn off servo
         end                       'sleep until next power on cycle
    
    ;____This routine is Called on each TMR1 Interrupt____________________________
    
    T1handler:  'interrupts are every 20 ms. These interrupts start each servo frame
                'and also clock elapsed time. 
               
                pulsout portc.5,throttlepos   'send pulse to motor speed controller
                pulsout portc.4,servopos      'send pulse to servo (pulse range is 
                Ticks = Ticks + 1             '1 ms to 2 ms for both pulses)
            if Ticks = 5 then
               Ticks = Ticks - 5
               Tenths = Tenths + 1
                 if tenths = 10 then
                   Seconds = Seconds + 1
                   Tenths = 0
                 endif
               sum = 10*Seconds + Tenths  'calculate time in tenths of seconds
             endif
      ;   ---- ---------------------------------- ----
    @ INT_RETURN
    
    ;---[TMR1 reload - interrupt handler]-----------------------------------------
    ASM                               ; Calculate Timer Reload Constant
    ReloadInst  = 8                   ; # of Intructions used to reload timer
      if ((Prescaler == 1)||(Prescaler == 2)||(Prescaler == 4)||(Prescaler == 8))
    MaxCount    = 65536 + (ReloadInst / Prescaler)
    TimerReload = MaxCount - (OSC*1000000/4/Prescaler/Freq)
        if ((TimerReload < 0) || (TimerReload > (65535-ReloadInst)))
            error Invalid Timer Values - check "OSC", "Freq" and "Prescaler"
        endif
      else
          error Invalid Prescaler
      endif
    ENDASM
    
    @Timer1 = TMR1L                   ; map timer registers to a word variable
    Timer1       VAR WORD EXT
    TimerReload  CON EXT              ; Get the External Constant
    TMR1ON       VAR T1CON.0          ; Alias the Timers ON/OFF bit
    
    ;---Reload Timer1------
    ASM
    ReloadTMR1
        MOVE?CT  0, T1CON, TMR1ON     ;  1     stop timer
        MOVLW    LOW(TimerReload)     ;  1     Add TimerReload to the 
        ADDWF    TMR1L,F              ;  1     value in Timer1
        BTFSC    STATUS,C             ;  1/2
        INCF     TMR1H,F              ;  1
        MOVLW    HIGH(TimerReload)    ;  1
        ADDWF    TMR1H,F              ;  1
        MOVE?CT  1, T1CON, TMR1ON     ;  1     start timer
      INT_RETURN
    ENDASM
         
    ;---Start/Stop controls -----
    StartTimer:
        Timer1  = TimerReload         ; Load Timer
        TMR1ON = 1                    ; start timer
    RETURN
    
    StopTimer:
        TMR1ON = 0                    ; stop timer
    RETURN

  2. #2


    Did you find this post helpful? Yes | No

    Default

    The servo driver and brushless motor driver SW now works as intended. The motor runs for 10.0 seconds and then stops instantly. I found (after much trial and error) that commanding changes to motor speed only works when placed inside the TMT1 interrupt handler instead of the main program section.
    New handler shown below in case it may be of help to someone in the future.

    Code:
    ;____This routine is Called on each TMR1 Interrupt______________________
    
    T1handler:                               'interrupts are every 20 ms
               if sum <= MTtime then         'MTtime  = 10.0 second pre-set run time
               throttlepos = 400             'full speed pulse = 2.00 ms at 8mhz
               else
               throttlepos = 200             'zero speed pulse = 1.00 ms at 8mhz
               endif
                pulsout portc.5,throttlepos  'send pulse to motor speed controller
                pulsout portc.4,servopos     'send pulse to servo (pulse range is 
                Ticks = Ticks + 1            '1 ms to 2 ms for both pulses)
            if Ticks = 5 then
               Ticks = Ticks - 5
               Tenths = Tenths + 1
                 if tenths = 10 then
                   Seconds = Seconds + 1
                   Tenths = 0
                 endif
               sum = 10*Seconds + Tenths     'calculate time in tenths of seconds
            endif
    @ INT_RETURN

  3. #3
    malc-c's Avatar
    malc-c Guest


    Did you find this post helpful? Yes | No

    Default

    Might be worth zipping up the complete code and any schematics you have and post this in the code examples section

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts