PWPS Servo Problem



THE BOOK of DT's INTERRUPTS is an organization of interrupt service routines and other works written by Darrel Taylor, RIP.

Interrupt routines are arranged per Darrel's original list. Darrel Taylor's Instant Interrupts are an extension of the work of Tim Box whom in October of 2002 wrote INT_CTRL.pbp

Many of the forum members felt this is a long overdue project.

THE BOOK of DT's INTERRUPTS
will be a valuable resource and a tribute to Darrel Taylor the "Fanatical Contributor".

THE BOOK of DT's INTERRUPTS is located at http://dt.picbasic.co.uk/

+ Reply to Thread
Results 1 to 11 of 11
  1. #1

    Default PWPS Servo Problem

    Hi Folks,
    I actually discovered a problem with DT PWPS servo pulse generator.
    If I use hardware USART (hserin) for receiving commands from Bluetooth module and the PWPS plugin is active (generating servo pulse) and I send a series of commands the PIC freezes. I think it is a collision with TMR1 because USART and PWPS use TMR1 interrupts.
    Strangely with PIC16F688 all work with no issues, but with PIC16F1824 causes this strange behavior. These PICs are pin-compatible and interchangeable.
    Then I try PIC12F1840 and same strange issues with freezing occurred. If I switch off PWPS the problem disappears.
    On older PIC16F688 USART receiving and PWPS work perfectly as I said.
    Has anyone encountered this problem?

  2. #2
    Join Date
    May 2013
    Location
    australia
    Posts
    2,118


    Did you find this post helpful? Yes | No

    Default Re: PWPS Servo Problem

    I think it is a collision with TMR1 because USART and PWPS use TMR1 interrupts.
    why would the uart need a TMR1 interrupt ?

    code ?
    Warning I'm not a teacher

  3. #3


    Did you find this post helpful? Yes | No

    Default Re: PWPS Servo Problem

    Hi Richard,

    I don't know, I'm just guessing.

    Here the code for PIC 16F688 working just fine:
    Code:
    '*  Notes   : PIC16F688                                         *
    '****************************************************************
    #CONFIG
    cfg = _INTRC_OSC_NOCLKOUT
    cfg&= _WDT_ON
    cfg&= _PWRTE_OFF
    cfg&= _MCLRE_OFF
    cfg&= _CP_OFF
    cfg&= _CPD_OFF
    cfg&= _BOD_ON
    cfg&= _IESO_ON
    cfg&= _FCMEN_ON
      __CONFIG cfg
    #ENDCONFIG
    
    DEFINE OSC 4 
    OSCCON = %01100100
    
    ANSEL =  0           ; set all digital
    TRISA = %00000000    ; PORT A all output
    TRISC = %00100001    ; PORT C.5 input RX, C.0 safety, rest output
    CMCON0 = 7
    
    ; def_ports:
    PWPSpin       var portc.1  ; servo signal OUTPUT (must be defined before PWPS_Servo.INC) 
    safety        var portc.0  ; safety leash magnetic switch
    
    ; def_vars:
    n             var byte 
    cmd           var byte 
    
    ; def HW USART:
    DEFINE HSER_BAUD 9600		; Set Baud rate to 9600bps
    DEFINE HSER_CLROERR 1 		; Clear overflow error automatically
    DEFINE HSER_TXSTA 24h       ; Set receive register to TX en
    define HSER_SPBRG 25
    DEFINE HSER_SPBRGH 1
    DEFINE HSER_RCSTA 90h
    
    ; def ext libr:
    include "PWPS_Servo.INC"                    ; Software Servo PWM module
    
    init:                                       ; vars start values
    position      = 1
    cmd           = 245
    n             = 0
    
    gosub StartPWPS                             ; start PWPS module 
    
    Main:                                                      
    
    hSerin 20,lost, [wait("Q"),dec cmd]         ; wait for Q and then for CMD
    
    if cmd = 155 then                           ; increment servoimpulse
    Position=Position+1
    if Position > 1199 then Position = 1200     ; max servoimpulse lenght 2us
    gosub SetPWPS
    endif
    
    if cmd = 145 then                           ; decrement servoimpulse
    Position=Position-1
    if Position < 1 then Position = 1           ; min servoimpulse lenght 1us
    gosub SetPWPS
    n=n+1                                       ; long press decrement  
    if n=255 then                               ; switch to minimum servoimpulse after cca. 3. sec.
    position=1
    endif
    endif
    
    if cmd = 245 then                            ; if transmitter is switched OFF servoimpulse to nimimum
    Position=1
    gosub SetPWPS
    endif
    
    if safety = 1 then                           ; if safety switch is OFF servoimpulse to nimimum
    Position=1
    gosub SetPWPS
    endif
    
    goto main
    
    lost:                                        
    n=0                                           ; clear long press counter value to 0
    if safety = 1 then                            ; if safety switch is OFF servoimpulse to nimimum
    Position=1
    gosub SetPWPS
    endif
    goto main
    Here the code for PIC 16F1824 it causes collisions, the code is the same except config:
    Code:
     
    '*  Notes   : PIC16F1824                                        *
    '****************************************************************
    
    #CONFIG
      __config  _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
      __config  _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF
    #ENDCONFIG
    
    DEFINE OSC 4     ; Use a 4 MHZ internal clock 
    OSCCON = %01101000
    
    ANSELA  = 0
    ANSELC  = 0 
    TRISA = %000000   
    TRISC = %00100001 ; PORT C.5 input RX, C.0 safety, rest output
    CM1CON0 = 0       ; Disable comparator 1
    CM2CON0 = 0       ; Disable comparator 2
    OPTION_REG.7=1    ; Disable weak pull ups
    APFCON0.7=0
    APFCON0.2=0
    
    
    ; def_ports:
    PWPSpin       var portc.1  ; servo signal OUTPUT (must be defined before PWPS_Servo.INC) 
    safety        var portc.0  ; safety leash magnetic switch
    
    ; def_vars:
    n             var byte 
    cmd           var byte 
    
    ; def HW USART:
    DEFINE HSER_BAUD 9600		; Set Baud rate to 9600bps
    DEFINE HSER_CLROERR 1 		; Clear overflow error automatically
    DEFINE HSER_TXSTA 24h       ; Set receive register to TX en
    define HSER_SPBRG 25
    DEFINE HSER_SPBRGH 1
    DEFINE HSER_RCSTA 90h
    
    ; def ext libr:
    include "PWPS_Servo.INC"                    ; Software Servo PWM module
    
    init:                                       ; vars start values
    position      = 1
    cmd           = 245
    n             = 0
    
    gosub StartPWPS                             ; start PWPS module 
    
    Main:                                                      
    
    hSerin 20,lost, [wait("Q"),dec cmd]         ; wait for Q and then for CMD
    
    if cmd = 155 then                           ; increment servoimpulse
    Position=Position+1
    if Position > 1199 then Position = 1200     ; max servoimpulse lenght 2us
    gosub SetPWPS
    endif
    
    if cmd = 145 then                           ; decrement servoimpulse
    Position=Position-1
    if Position < 1 then Position = 1           ; min servoimpulse lenght 1us
    gosub SetPWPS
    n=n+1                                       ; long press decrement  
    if n=255 then                               ; switch to minimum servoimpulse after cca. 3. sec.
    position=1
    endif
    endif
    
    if cmd = 245 then                            ; if transmitter is switched OFF servoimpulse to nimimum
    Position=1
    gosub SetPWPS
    endif
    
    if safety = 1 then                           ; if safety switch is OFF servoimpulse to nimimum
    Position=1
    gosub SetPWPS
    endif
    
    goto main
    
    lost:                                        
    n=0                                           ; clear long press counter value to 0
    if safety = 1 then                            ; if safety switch is OFF servoimpulse to nimimum
    Position=1
    gosub SetPWPS
    endif
    goto main
    Here is the PWPS include file:
    PWPS_Servo.INC.txt
    Last edited by louislouis; - 5th July 2022 at 10:45.

  4. #4
    Join Date
    May 2013
    Location
    australia
    Posts
    2,118


    Did you find this post helpful? Yes | No

    Default Re: PWPS Servo Problem

    What those two chips have in common is auto context save for interrupts.
    i simulated the 1824 and the problem was not experienced, but who would trust a simulator



    try this for 12f1840/16f1824 removing bogus context save/restore code


    Code:
    '****************************************************************'*  Name    : PWPS_Servo.INC     Pulse Width Position Servo     *
    '*  Author  : Darrel Taylor                                     *
    '*  Date    : 5/1/2003                                          *
    '*  Version : 1.0                                               *
    '*  Notes   :                                                   *
    '*          :                                                   *
    '****************************************************************
    
    
    DEFINE INTHAND INT_CODE                 ' Tell PBP Where the code starts on an interrupt
    
    
    ;wsave       VAR BYTE    $20     SYSTEM          '$20 Save location for the W register if in bank0
    ;wsave1      VAR BYTE    $A0     SYSTEM          ' Save location for the W register if in bank1
    ;wsave2      VAR BYTE    $120    SYSTEM          ' Save location for the W register if in bank2
    ;wsave3      VAR BYTE    $1A0    SYSTEM          ' Save location for the W register if in bank3
    ;ssave       VAR BYTE    Bank0   SYSTEM          ' Save location for the STATUS register
    ;psave       VAR BYTE    Bank0   SYSTEM          ' Save location for the PCLATH register
    
    
    W1                  var word                    ' Temporary variable
    y                   var byte                    ' Temporary variable
    PulseTicks1ms       var word                    ' # of Ticks for 1ms
    TicksPeruSx100      var word                    ' # of Timer Ticks to = 1 us * 100
    uS50Hz              var word                    ' # of Ticks for 50 Hz with prescaler
    PicOSC              var byte Bank0              ' OSC value, Usable in PBP
    OffTimePrescaler    var byte                    ' Timer1 Prescale value during OFF period
    Position            var word          ' 0 - 900   0 = 1.05ms   900 = 1.95ms
    T1CONoff            var byte Bank0
    TMR1_ON_TICKS       var word          ' # of Tmr ticks for On Time
    TMR1_OFF_TICKS      var word          ' # of Tmr ticks for Off Time
    TMR1_ON_VAL         var word Bank0    ' # to load TMR1 for On Time
    TMR1_OFF_VAL        var word Bank0    ' # to load TMR1 for Off Time
    
    
    DataFlags           var byte Bank0
    Valid               var DataFlags.0   ' 1 if Freq is valid - Set by CalcPWPS:
    PWPSenabled         var DataFlags.1   ' shows if PWPS is running or not
    PWPSstate           var DataFlags.2   ' Current state of PWPS output high or low
    
    
    GIE                 var INTCON.7
    PEIE                var INTCON.6
    TMR1IE              var PIE1.0
    TMR1ON              var T1CON.0
    
    
    goto GetOsc
    
    
    ' ------------------------------------------------------------------------
    asm
    INT_CODE
          ;if (CODE_SIZE <= 2)
          ;  movwf   wsave              ; copy W to wsave register
          ;  swapf   STATUS,W           ; swap status reg to be saved into W
          ;  clrf    STATUS             ; change to bank 0 regardless of current bank
          ;  movwf   ssave              ; save status reg to a bank 0 register
          ;  movf    PCLATH,w           ; move PCLATH reg to be saved into W reg
          ;  movwf   psave       ;6     ; save PCLATH reg to a bank 0 register
          ;endif
            
            btfss   PIR1, TMR1IF       ; is TMR1IF set?   Timer1 Interrupt Flag
            GOTO  NoTimerInt           ; No.  Bypass timer load
            btfss   _Valid             ; Is Freq valid?
            GOTO  NoPWPS               ; No.  Halt PWPS
            btfss   _PWPSenabled       ; is Software PWM enabled?
            GOTO  NoPWPS               ; No.  Halt PWPS
                                       ; Yes, then Set output and reload Timer1
            btfss   _PWPSstate         ; Is Output High?
            GOTO  TurnON      ;9/15    ; No.
    
    
    TurnOFF
            bcf     _PWPSpin            ; Set PWPSpin Low
            bcf     _PWPSstate          ;
            MOVF    _T1CONoff,W         ;    Load OFF Period Prescaler and Turn off timer
            MOVWF   T1CON               ;  
            MOVF    _TMR1_OFF_VAL,W     ;  1
            ADDWF   TMR1L,F             ;  1    reload timer with Off Period value
            BTFSC   STATUS,C            ;  1/2
            INCF    TMR1H,F             ;  1
            MOVF    _TMR1_OFF_VAL+1,W   ;  1
            ADDWF   TMR1H,F             ;  1
            BSF     T1CON,TMR1ON        ;  1    Turn it back on
            GOTO  TimerDone   ;13/28
    
    
    TurnON  
            bsf     _PWPSpin            ; Set PWPSpin High
            bsf     _PWPSstate          ;
            CLRF    T1CON               ;    Clear Prescaler and Turn off timer
            MOVF    _TMR1_ON_VAL,W      ;  1
            ADDWF   TMR1L,F             ;  1    reload timer with On Period value
            BTFSC   STATUS,C            ;  1/2
            INCF    TMR1H,F             ;  1
            MOVF    _TMR1_ON_VAL+1,W    ;  1
            ADDWF   TMR1H,F             ;  1
            bsf     T1CON,TMR1ON        ;  1     Turn it back on
            GOTO  TimerDone
    NoPWPS
            bcf     T1CON,TMR1ON        ; Turn off timer
            bcf     _PWPSpin            ; Idle PWPSpin Low
    TimerDone        
            bcf     PIR1, TMR1IF ; 1/29         ; Clear Timer1 Interrupt Flag
    NoTimerInt    
            ;Movf    psave,w             ; Restore the PCLATH reg
            ;Movwf   PCLATH
            ;swapf   ssave,w             ; Restore the STATUS reg			
            ;movwf   STATUS
            ;swapf   wsave,f
            ;swapf   wsave,w    ; 6/35   ; Restore W reg
           
        Retfie                          ; Exit the interrupt routine	
    
    
    endasm
    ' ------------------------------------------------------------------------
    
    
    StartPWPS:  ' Set Position before calling
        low PWPSpin     ' Set PWPSpin to Output and idle Low
        GIE = 1         ' Global Interrupt Enable
        PEIE = 1        ' Peripheral Interrupt Enable
        TMR1H = 255    ' Load TMR1 with 65535, First tick will cause
        TMR1L = 255    ' an interrupt that will load TMR1_???_VAL 
    
    
    SetPWPS:   ' Set Position before calling
        Position = Position min 1200    ' Make sure we don't go to far
        gosub CalcPWPS
        if Valid = 1 then
          PWPSenabled = 1
          lookdown OffTimePrescaler,[1,2,4,8],y
          lookup y,[0,1,2,3],y
          T1CONoff = y << 4
          TMR1_ON_VAL = 65535 - TMR1_ON_TICKS + 7   ' Value to load in Timer1 for ON period
          TMR1_OFF_VAL = 65535 - TMR1_OFF_TICKS + 7 ' Value to load in Timer1 for OFF period 
          TMR1IE = 1    ; Enable Timer1 Interrupts
          T1CON = 1     ; Turn Timer1 on (no prescaler)
        endif
    return
    
    
    StopPWPS
        TMR1IE = 0
        TMR1ON = 0
        low PWPSpin             ' Idle output Low
        PWPSstate = 0
        PWPSenabled = 0
    return
    
    
    CalcPWPS: ' Set Position before calling 0-900
        Valid = 1
        y = 99
        LookDown PicOSC,[4,   8,   10,   12,   16,   20,   24,   25,   32,   33,   40],y
        if y = 99 then OSCnotFound
        ;LookUp2  y,[ 1050, 2100, 2625, 3150, 4200, 5250, 6300, 6562, 8400, 8660, 10500],PulseTicks1ms
        LookUp2  y,[ 900, 1800, 2250, 2700, 3600, 4500, 5400, 5625, 7200, 7425, 9000],PulseTicks1ms
        lookup2  y,[  100,  200,  250,  300,  400,  500,  600,  625,  800,  825,  1000],TicksPeruSx100
        lookup   y,[    1,    1,    1,    1,    2,    2,    2,    2,    4,    4,    4],OffTimePrescaler
        Lookup2  y,[20000,40000,50000,60000,40000,50000,60000,62000,40000,41000,50000],uS50Hz
        W1 = TicksPeruSx100 * Position
        W1 = Div32 100
        TMR1_ON_TICKS = W1 + PulseTicks1ms
        TMR1_OFF_TICKS = uS50Hz - (TMR1_ON_TICKS / OffTimePrescaler)
    return
    
    
    OSCnotFound:
      Valid = 0
    return
    
    
    
    
    GetOsc:                  ' Retreive defined OSC value on Reset
      asm
        ifdef OSC
           MOVE?CB   OSC, _PicOSC
        else
           MOVE?CB   4, _PicOSC
        endif
      endasm
    Warning I'm not a teacher

  5. #5


    Did you find this post helpful? Yes | No

    Default Re: PWPS Servo Problem

    Unfortunately, same behavior. After sending the command via Bluetooth (I send the command for example: hserout ["Q",dec 155,10,11] in a loop while the pushbutton is pressed). After a while, the servo output is incrementing and then suddenly freezes the PIC.

  6. #6


    Did you find this post helpful? Yes | No

    Default Re: PWPS Servo Problem

    I tested the PIC12F1840 and PIC16F1824 with software serial input. PIC frequency set to 8MHz as required PBP at 9600 baud.
    It's working, but the response is kinda slow.
    Code:
    '*  Notes   : PIC16F1824                                        *
    '****************************************************************
    
    #CONFIG
      __config  _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
      __config  _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF
    #ENDCONFIG
    
    DEFINE OSC 8     ; Use a 8 MHZ internal clock 
    OSCCON = %01110000
    
    ANSELA  = 0
    ANSELC  = 0 
    TRISA = %000000   
    TRISC = %00100001 ; PORT C.5 input RX, C.0 safety, rest output
    CM1CON0 = 0       ; Disable comparator 1
    CM2CON0 = 0       ; Disable comparator 2
    OPTION_REG.7=1    ; Disable weak pull ups
    APFCON0.7=0
    APFCON0.2=0
    
    
    ; def_ports:
    PWPSpin       var portc.1  ; servo signal OUTPUT (must be defined before PWPS_Servo.INC) 
    safety        var portc.0  ; safety leash magnetic switch
    
    ; def_vars:
    n             var byte 
    cmd           var byte 
    
    ; def ext libr:
    include "PWPS_Servo.INC"                    ; Software Servo PWM module
    include "modedefs.bas"                         ; modedefs must be after PWPS_Servo.INC otherwise it doesn't work
    
    init:                                       ; vars start values
    position      = 1
    cmd           = 245
    n             = 0
    
    gosub StartPWPS                             ; start PWPS module 
    
    Main:                                                      
    
    Serin2 portc.5,84,20,lost, [wait("Q"),dec cmd]         ; wait for Q and then for CMD
    
    if cmd = 155 then                           ; increment servoimpulse
    Position=Position+1
    if Position > 1199 then Position = 1200     ; max servoimpulse lenght 2us
    gosub SetPWPS
    endif
    
    if cmd = 145 then                           ; decrement servoimpulse
    Position=Position-1
    if Position < 1 then Position = 1           ; min servoimpulse lenght 1us
    gosub SetPWPS
    n=n+1                                       ; long press decrement  
    if n=255 then                               ; switch to minimum servoimpulse after cca. 3. sec.
    position=1
    endif
    endif
    
    if cmd = 245 then                            ; if transmitter is switched OFF servoimpulse to nimimum
    Position=1
    gosub SetPWPS
    endif
    
    if safety = 1 then                           ; if safety switch is OFF servoimpulse to nimimum
    Position=1
    gosub SetPWPS
    endif
    
    goto main
    
    lost:                                        
    n=0                                           ; clear long press counter value to 0
    if safety = 1 then                            ; if safety switch is OFF servoimpulse to nimimum
    Position=1
    gosub SetPWPS
    endif
    goto main
    Then I tested even only the PWPS run alone on PIC16F1824 and via serial terminal from PC sent a serial command and the PIC freezes.

    Then I tested what if I stop TMR1 (of course PWPS stopped working) but the HW usart works without problems.

    Something is wrong with this PWPS include but I can't figure out what.

  7. #7
    Join Date
    May 2013
    Location
    australia
    Posts
    2,118


    Did you find this post helpful? Yes | No

    Default Re: PWPS Servo Problem

    how sure are you that your code is compiled with the modified inc as i suggested ?

    if you examine the lst file generated and search for NoTimerInt
    do you see

    Name:  Screenshot 2022-07-06 104811.jpg
Views: 48
Size:  178.6 KB


    pbp can be tricky if multiple versions of inc files exist, sometimes the "wrong" version can be used inadvertently
    Last edited by richard; - 6th July 2022 at 01:55.
    Warning I'm not a teacher

  8. #8


    Did you find this post helpful? Yes | No

    Default Re: PWPS Servo Problem

    100% sure, here is my LST file:
    Servo_Mod_INC.LST.txt

  9. #9


    Did you find this post helpful? Yes | No

    Default Re: PWPS Servo Problem

    Even in proteus 8 simulator appears the same behavior. After sending a few commands the PWPS stops working and the PIC freezes.
    I tested PIC12F1840, that's strange.

  10. #10
    Join Date
    May 2013
    Location
    australia
    Posts
    2,118


    Did you find this post helpful? Yes | No

    Default Re: PWPS Servo Problem

    Yes a hserin timeout that is too small causes some grief even the odd reset, i had to increase it to 300 for hand typed input for a successful
    test.
    my previous tests had the timeout commented out because i cannot type at that rate
    Warning I'm not a teacher

  11. #11


    Did you find this post helpful? Yes | No

    Default Re: PWPS Servo Problem

    Not helped at all, I try timeouts from 200, 300 up to 600 still freezes.

    I go hunting a few 16F688 PICs in SMD package and stay with these chips in this application.
    Last edited by louislouis; - 7th July 2022 at 09:34.

Similar Threads

  1. servo/motor problem
    By griffin in forum mel PIC BASIC
    Replies: 10
    Last Post: - 10th February 2009, 20:07
  2. Servo motor problem
    By dboy in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 20th September 2008, 15:54
  3. servo driver problem
    By al000y in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 7th February 2007, 10:17
  4. Servo Pulser problem
    By al000y in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 24th January 2007, 12:48
  5. servo pulse problem...
    By tonkgang in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 7th April 2006, 16:12

Posting Permissions

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