PWPS Servo Problem


+ 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