Menu

Timer 2 support

Help
2009-11-01
2013-05-30
  • Nobody/Anonymous

    Hi all, I can not find any reference to the use of timer 2 in GCB.  It does not seem to have support for the post scaler.  And it does not seem to work correctly with all the prescaler values, anybody have any experience with this ?  Regards, Ed.

     
  • Nobody/Anonymous

    Not documented but It looks like support is there in timer.h for tmr2 and tmr3.    There are only three choices for timer2 prescale, at least for the data sheet I'm looking at.  Have you tried something like InitTimer2 (16, 16)?  Here is the init sub call from timer.h.

        Sub InitTimer2 (In TMR2Pres, In TMR2Post)
        …
        …

    Worst comes to worst, set it up manually using timer.h as a guide.  Set individual register bits ON or Off (e.g. Set T2OUTPS3 On:Set T2OUTPS2 ON ….etc.).  Toggle the timer2 on and off by setting and clearing the TMR2ON bit (e.g. Set TMR2ON ON).  Then read the TMR2 register itself for the value Timer2Value = TMR2.
    Kent

     
  • Edward LaBudde

    Edward LaBudde - 2009-11-01

    Kent thanks, I have packed up my goodies for the day so I will have to do more testing tomorrow.  Thanks for the pointer will take a look at it.  I have been using a 12F683.  I think I have found another problem in the chip data files for for all the 12F devices regarding interrupts.  I do not know if this is contributing to my problem or not! 

    For GCB code:
    InitTimer2 Osc, PS2_1 'Select timer 2 clock, prescale 1,4,16
    T2CON = b'00000000' ‘Clear Timer 2
    .asm file
    ;Start of the main program
    banksel TRISIO
    bcf TRISIO,0
    bcf TRISIO,1
    bcf TRISIO,2
    movlw 1
    banksel TMR2PRES
    movwf TMR2PRES
    clrf TMR2POST
    call INITTIMER2
    clrf T2CON
    movlw 178
    movwf TIME_DELAY
    movwf TMR2
    banksel PIE1
    bsf PIE1,T2IE-------note name

    from chip data file for 12F683
    Timer2Overflow:T2IE,T2IF----- note name

    From chip data file 16F88
    Timer2Overflow:TMR2IE,TMR2IF

    What you get when you modify the chip data for the 12F683 to match 16F88
    .asm file
    ;Start of the main program
    banksel TRISIO
    bcf TRISIO,0
    bcf TRISIO,1
    bcf TRISIO,2
    movlw 1
    banksel TMR2PRES
    movwf TMR2PRES
    clrf TMR2POST
    call INITTIMER2
    clrf T2CON
    movlw 178
    movwf TIME_DELAY
    movwf TMR2
    banksel PIE1
    bsf PIE1,TMR2IE---- it is now correct!

     
  • Edward LaBudde

    Edward LaBudde - 2009-11-02

    Kent here is the code I am using.  I want to set a pulse string out with a 20 us period using timer 2

    'Chip model
    #chip 12f683, 20

    'Set the pin directions
    Dir GPIO.1 Out 'test pulse pin 6

    'Set initial parameters
    #define Test_timer GPIO.1

    'T2CON = b'00001001'  can be used to select T2CON bits manually

    InitTimer2 Osc, PS2_1,PS2_2 'Select timer 2 clock, prescale 1,4,16

    dim Time_Delay as Byte

    Time_Delay = 255 - 100 + 23  'set to 20 us and compensate for interrupt service delays (+23)

    TMR2 = Time_delay 'Set Time delay

    On Interrupt Timer2Overflow call TimerCont  ‘Send a pulse out on overflow

    Main: ‘Turn on timer 2
    set T2CON.TMR2ON = On
    Goto Main

    Sub TimerCont
    set test_timer = on 'Measure 200 ns pulse width - OK
    set test_timer = off ‘This minimizes extra delays in service routine
    TMR2 = Time_delay 'Reset Time delay
    Return


    Here is what I found

    11-02-09
    InitTimer2 Osc, PS2_1/1 same as InitTimer2 Osc, PS2_1 = 49895  Hz
    InitTimer2 Osc, PS2_4 and 16 does not work!

    Changing Timer2Overflow:T2IE,T2IF to Timer2Overflow:TMR2IE,TMR2IF
    Has no effect.

    InitTimer2 Osc, (1,1) produces “Timer2F675.txt (20): Error: Invalid variable name: (1”
    InitTimer2 Osc, (PS2_1,PS2_1) “Timer2F675.txt (20): Error: Invalid variable name: (0”

    InitTimer2 Osc, PS2_1,PS2_1 works  =49895 Hz
    InitTimer2 Osc, PS2_4,PS2_1 does not work! =49895 Hz
    InitTimer2 Osc, PS2_1,PS2_2 does not work! =49895 Hz

    .asm file for InitTimer2 Osc, PS2_1,PS2_2
    movlw 1
    banksel TMR2PRES
    movwf TMR2PRES
    clrf TMR2POST------- Is clearing not setting to 2
    call INITTIMER2

    Changing .asm file to
    movlw 1
    banksel TMR2PRES
    movwf TMR2PRES
    movlw 2
    banksel TMR2POST
    movwf TMR2POST
    call INITTIMER2
    Results in Nop!

    Direct setting of T2CON does not work right either!

    T2CON = b'00000000' = 49895 Hz - OK
    T2CON = b'00000001' = 14805 Hz – OK should be 12473 Hz
    T2CON = b'00000011' = No operation!
    T2CON = b'01000001' = Nop
    T2CON = b'00100001' = Nop
    T2CON = b'00001001' = Nop

    Conclusion
    It appears that GCB has some problems with timer 2.
    There is also a problem with direct control of T2CON bits with the 12F683
    What am I doing wrong here?

    Kent have any more ideas?

    Thanks Ed.

     
  • Nobody/Anonymous

    Hi Ed, that was a real head scratcher.  For the most part, the problem seemed to be turning on the timer2 everytime in Main:.  It definetely killed the pre and postscale action.  There still may be more work to get it into the form you are looking for.

    Kent

        'A test program to check out TMR2
        #chip 12f683,20
       
        #define test_timer GPIO.1
        dir GPIO.1 out
       
        Time_Delay = 255 - 100 + 23  'set to 20 us and compensate for interrupt service delays (+23)
        TMR2 = Time_delay    'Set Time delay
        On Interrupt Timer2Overflow call TimerCont
        count = 0
        Set T2CKPS0 On 'Set prescale to 4, options 1,4, 16
        SeT TOUTPS3 ON 'Set postscale to 8, options 1-16
        set TMR2ON On
       
        start:
        NOP
        goto start
       
        Sub TimerCont
        count = ! count
        test_timer = count
        TMR2 = Time_delay
        end sub

     
  • Edward LaBudde

    Edward LaBudde - 2009-11-02

    Kent thanks for the help, will try it tomorrow.  Regards, Ed.

     
  • Edward LaBudde

    Edward LaBudde - 2009-11-03

    Kent, you are a genius!   That solved the problem.  Timer 2 is quite flexible with the pre and post scalers as well as the PR2 register.

    I am trying to generate very precise pulse widths for calibrating test measurements.  I have one working with timer 1.  When I moved on to timer 2 is when I got bogged down.

    Can you explain what this is supposed to do and how it works?

    Sub TimerCont
    count = ! count
    test_timer = count
    end sub

    It looks like it is high except for one clock.  I wanted a short + going pulse so I used

    Sub TimerCont
    set test_timer = on 'Measure 200 ns
    set test_timer = off
    TMR2 = Time_delay
    Return

    Thanks for your help as usual. 

    BTW, the latest release solved all my complaints.  Great job Hugh!
    Best regards Ed.

     
  • kent_twt4

    kent_twt4 - 2009-11-03

    Genius, absolutely not: Sometimes motivated or determined then yes.

    The referenced code was a bad attempt to toggle the output pin.  It did not work as planned, but provided proof of pre/post scale operations.  Not sure what you would call the waveform in the analog world, but it is ugly looking.

    Did you work any more with the negative numbers and your PID?  Was needing to revisit this for a buck converter voltage feedback loop.

     
  • Edward LaBudde

    Edward LaBudde - 2009-11-03

    Kent, I found an old file that was "tested" on 02-21-09.  The issue of negative numbers require a reverse of subtration order to prevent negative numbers.  Also one has to swap "old and "new" data.  The code is not very readable.  I would now use the else fucntion to make it clearer.  I would like to be able to psot the code like your example.  If I just post the code by a "copy" "paste"  it look like crap on my screen.

    Here it the crappy code:
    'A PID controller with PWM output
    'Tested 02-21-09
    'Use at your own risk!

    'Chip model
    #chip 16F88, 8
    #config INTRC_IO

    'Set the pin directions
    dir portA.0 in 'input feedback on pin #17 from rc filter
    dir portB.0 out 'set pwm output on pin #6 filter with 10k and 10uF capacitor to simulate a 1 second plant

    'Set parameters
    Pg = 3 'set proportional gain
    Ig = 1 'set integral gain-used to control steady stae error left by the proportional term
    Dg = 1 'set dervitive gain- used to control overshoot
    command = 127 'set command input - drive to this value
    Iterm = command 'set integrator init set command to minimize errors
    Ioutn = 0 'Set integrator init use 0 initally will update on first cycle

    PWMon
    for rampcmd = 0 to command 'Ramp input to command control systems do not like step inputs
    HPWM  1, 10, rampcmd
    wait 100 ms
    if rampcmd = command then goto Ready
    next

    Ready:
    resp = readad(an0) 'get new data
    If resp > command then test=true  'Test input polarity
    'Generate Pterm
    If test = false then
    errorn = command - resp
    Pterm = errorn * Pg + command 'For resp<command
    end if
    if test = true then
    errorn = command -(resp - command) 'For resp>command
    Pterm = command - (command -errorn)*pg
    end if
    'Generate Iterm I*dt
    if test = true then
    Iterm = errorn*Ig + Ioutn 'For resp<command
    end if
    if test=false then
    errorn = resp-command
    Iterm = ioutn - errorn*Ig 'For resp>command
    end if
    'Generate Dterm D/dt
    If test=false then
    Dterm = (errorn-erroro)*Dg 'For resp<command
    erroro = errorn 'set previous error
    end if
    If test=true then
    errorn = resp-command 'For resp>command
    Dterm = (erroro-errorn)*Dg
    erroro = errorn 'set previous error
    end if

    output = Pterm  + Iterm + Dterm 'generate output

    Ioutn = Iterm 'set previuos int value
    HPWM  1, 10, output 'output PWM
    wait 1 ms 'set sample rate = dt
    goto ready

     
  • Nobody/Anonymous

    Thanks Ed, it came through fine from the monitor by email option.  To make it work on the forum post, the 101/010 icon needs to be clicked from the toolbar,….then paste or write code in the bluish box.

    When fooling with your PID code, and Santiago's negative number library, it was taking some pretty wild swings when resolving to steady state.   Also, made a very brief, and unsuccessful try ,with Hugh's 'dim as Integer', but didn't really follow up.  Will have another look, and post on a different thread if more help needed.

    Kent

     
  • Edward LaBudde

    Edward LaBudde - 2009-11-03

    Kent, tuning a PID can be difficult.  Here is how I do it.  Set Iterm and Dterm to zero.  Then adjust the Pterm until you get an overshoot to a small step input.  Then use the Dterm ti damp out the overshoot.  You only need to use the Iterm if there is a large steady state error.  The steady state error with Iterm = 0 is about 1/Pterm so if Pterm is >100 you have less than 1% error.  I wil try your "101/010" trick

       <pre><code> 'A PID controller with PWM output
    'Tested 02-21-09
    'Use at your own risk!

    'Chip model
    #chip 16F88, 8
    #config INTRC_IO

    'Set the pin directions
    dir portA.0 in 'input feedback on pin #17 from rc filter
    dir portB.0 out 'set pwm output on pin #6 filter with 10k and 10uF capacitor to simulate a 1 second plant

    'Set parameters
    Pg = 3 'set proportional gain
    Ig = 1 'set integral gain-used to control steady stae error left by the proportional term
    Dg = 1 'set dervitive gain- used to control overshoot
    command = 127 'set command input - drive to this value
    Iterm = command 'set integrator init set command to minimize errors
    Ioutn = 0 'Set integrator init use 0 initally will update on first cycle

    PWMon
    for rampcmd = 0 to command 'Ramp input to command control systems do not like step inputs
    HPWM  1, 10, rampcmd
    wait 100 ms
    if rampcmd = command then goto Ready
    next

    Ready:
    resp = readad(an0) 'get new data
    If resp > command then test=true  'Test input polarity
    'Generate Pterm
    If test = false then
    errorn = command - resp
    Pterm = errorn * Pg + command 'For resp<command
    end if
    if test = true then
    errorn = command -(resp - command) 'For resp>command
    Pterm = command - (command -errorn)*pg
    end if
    'Generate Iterm I*dt
    if test = true then
    Iterm = errorn*Ig + Ioutn 'For resp<command
    end if
    if test=false then
    errorn = resp-command
    Iterm = ioutn - errorn*Ig 'For resp>command
    end if
    'Generate Dterm D/dt
    If test=false then
    Dterm = (errorn-erroro)*Dg 'For resp<command
    erroro = errorn 'set previous error
    end if
    If test=true then
    errorn = resp-command 'For resp>command
    Dterm = (erroro-errorn)*Dg
    erroro = errorn 'set previous error
    end if

    output = Pterm  + Iterm + Dterm 'generate output

    Ioutn = Iterm 'set previuos int value
    HPWM  1, 10, output 'output PWM
    wait 1 ms 'set sample rate = dt
    goto ready>

    Kent is does not look as "pretty" as yours, but better.  Let me know if you need more help on this .  Ed.
      

     
  • Edward LaBudde

    Edward LaBudde - 2009-11-04

    Kent, I cleaned up the PID to make it "look better"  Also corrected a small error.  I still can not get the code box to work right.  What is the secret? 

    See:

        'A PID controller with PWM output
    'Neg_signed 02-21-09
    'Use at your own risk!

    'Chip model
    #chip 16F88, 8
    #config INTRC_IO

    'Set the pin directions
    dir portA.0 In 'input feedback on pin #17 from rc filter
    dir portB.0 Out 'set pwm output on pin #6 filter with 10k and 10uF capacitor to simulate a 1 second plant

    'Set parameters
    Pg = 3 'set proportional gain
    Ig = 1 'set integral gain-used to control steady stae error left by the proportional term
    Dg = 1 'set dervitive gain- used to control overshoot
    command = 127 'setCommand input - drive to this value
    Iterm =Command 'set integrator init setCommand to minimize errors
    Iout_new = 0 'Set integrator init use 0 initally will update on first cycle

    PWMon
    for Rampcmd = 0 to Command 'Ramp input toCommand control systems do not like step inputs
    HPWM  1, 10, Rampcmd
    wait 100 ms
    if Rampcmd = Command then goto Ready
    next

    Ready:
    Response = readad(an0) 'get new data
    If Response > Command then Neg_sign=true 'Neg_sign input polarity true is negative problem
    If Neg_sign = true Then
    error_new = Response -Command
    Else
    error_new = Command - Response
    end if
    'Generate Terms
    If Neg_sign = False then
    Pterm = error_new * Pg + Command 'Pterm For Response<command
    Iterm = error_new*Ig + Iout_new 'Iterm For Response<command
    Dterm = (error_new-error_old)*Dg 'DTerm For Response<command
    Else
    Pterm = Command - error_new*pg 'Pterm For Response>command
    Iterm = Iout_new - error_new*Ig 'Iterm For Response>command
    Dterm = (error_old-error_new)*Dg 'Dterm For Response>command
    end if

    error_old = error_new 'set previous error

    Output = Pterm  + Iterm + Dterm 'generate output

    Iout_new = Iterm 'set previuos int value
    HPWM  1, 10, Iutput 'output PWM
    wait 1 ms 'set sample rate = dt
    goto ready

       

     
  • kent_twt4

    kent_twt4 - 2009-11-04

    Ed, that's weird.  Didn't see any of your code in the blue box  using IE8 beta2.  Using Firefox 3.53, the first line of the code is in a blue code box, then plain text, then back to blue code box for the last five lines.  So maybe the browser has some effect, but haven't had any problems in posting from either browser.

    The preview should show you exactly how the post is formatted.  Be careful when using 'two' carriage returns, or a new paragraph, once inside the blue code box (because, the code tags will stop and normal format will resume).  Best if everything goes in on one paste, or be cognizant of the restriction and start a new code box.  So what I am saying is, writing code in the blue code box is terrible, pasting code in is alright.

    Kent

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.