Menu

18f25k22 timer1 overflow interrupt questions

Help
2017-05-27
2017-05-27
  • stan cartwright

    stan cartwright - 2017-05-27

    Hi, I'm not sure about how to go about a 50Hz timer intterupt to refresh a servo actuator and turning off interruppts or the timer1 for using glcd ssd1306.h and srf04.h.
    I need to stop and restart the timer for the srf04 to measure distance and the glcd as a line in my setup #define I2C_DISABLE_INTERRUPTS ON
    My interrupt is

    on interrupt timer1overflow Call servo
    inittimer1(OSC,PS1_2)
    Starttimer 1
    

    the interrupt and the get range are

    sub get_range ;us sensor
    ;intoff
    StopTimer 1
    do until range > 0
    range = USDistance(1)
    wait 10 ms
    loop
    ;inton
    ;settimer 1, 25535
    Starttimer 1
    end sub
    ;;;;;;;;
    sub servo ;servo interrupt
    settimer 1, 25535
    pulseout Servo_Pin , radarpos 10us
    end sub
    

    You can see my efforts. I need to use the glcd as well. Please show me the best way.

     
  • William Roth

    William Roth - 2017-05-27

    Don't think you can do it like that. Stopping the timer will stop the servo pulse. Suggest you use a CCP module for the servo function instead of Timer with interrupt/pulse out.

    What I see in the code is 1 servo. Are there more ? One Servo gives you approximately 19 ms between interrupts to do stuff. Probably not enough time to get the range info and update the display without interruption. Using a hardware CCP module to generate the Servo Pulse eliminates the need for an interrupt.

     
  • mmotte

    mmotte - 2017-05-27

    Stan,

    I have been using micro servo's for the last year just by sending them a pulse until they settle into a position. They seem to stay in that position just fine for long time (hour plus).

    This way you would not need the interrupt to send the pulses continuously to the servo.

    Example code:

    Repeat 25
                    pulseout PortA.3,A3pos2 10us
                             wait 20 ms
    End Repeat
    

    I wanted to uses only a byte for the position so that is why the time is " 10 us". So position by the book would be 100 to 200 which would be 1000us to 2000us. But the little blue servos seem to work over these limits. 60 to 240 which give a little more rotation.

    The pulse is repeated long enough for the servo to get to the position and 25 times is too much but safe. Then I don't send a pulse until a new position is needed. In my application only 2 positions are needed. I keep the times for the 4 servos and two positions each in a table and can tune both the normal position and the tripped position after mounting.

    Mike

     
  • stan cartwright

    stan cartwright - 2017-05-28

    Thanks for the feedback,appreciated. mmotte said "I have been using micro servo's for the last year just by sending them a pulse until they settle into a position. They seem to stay in that position just fine for long time (hour plus)." This is interesting as I used a servo on a robot with a us sensor mounted on the servo and it rotating left-right BUT the servo LOST position ie a variable servoposition would not be accurate...in fact the servo gone daft doing own thing.
    The documented way is servos need refreshing at least 50Hz. That works for me.
    mmotte saying "just by sending them a pulse until they settle into a position" is maybe my error ie I just pulseout servoposition,it moves but then loses it if the next pulseout is late. I will try your method with 2 to 4 pulses and see.
    The interrupt I used works ok with a sharp optical rangefinder but they sample too slow for my robot.
    The glcd is for testing variables at the mo but will be a face...the eyes and mouth sorted and animated.
    William Roth,I have thought pwm but it's too coarse and fast but using ccp is beyond me. Is it documented in gcb ie around 5% duty but precise? I can't see a way with the pwm.h but that maybe my fault (probably).and the timer stuff is hard to follow (for me).

     
  • mmotte

    mmotte - 2017-05-28

    Stan,
    "by sending them a pulse until they settle into a position" , I should have said send multiple pulses of a certain size. I thought it was infered from the code example of sending 25 pulses of "A3pos2" size. I also told you 25 was probably to high. They usually work fine with as few as 10 but your suggestion of 2 or 4 is too few. Also make sure you wait between pulses. Read code eaxample. My many different servos never drifted after doing this. I know this is not according to the "rules" but works and would save you a timer for other purposes.

    73
    M

     
  • stan cartwright

    stan cartwright - 2017-05-29

    My use is a us range finder on a servo scanning left to right to left. I need to know the position to know where an object is. The us sensor needs 10ms to settle. That is enough time for the servo to reset and lose position ie 150 is not centre. OK I could split the 10ms with pulseouts but not elegant solution and other delays in my code.
    I'll figure a method like William Roth suggested. nice one.

     
  • kent_twt4

    kent_twt4 - 2017-05-29

    How about using Timer0 for the interrupt, and make a scheduler based on the lowest common time frame. Say, set Timer0 to overflow every 5ms and use a counter in the interrupt. Then in main:

    Select Case counter
        Case 0  
            'start ultrasonic reading
        Case 1  '5 ms
            'do other stuff
        Case 2  '10 ms
            'take ultrasonic reading
        Case 3  '15 ms
            'output to glcd?
        Case 4  '20 ms
            'update servo with new CCP value
    end select
    
     
  • stan cartwright

    stan cartwright - 2017-05-29

    Thanks kent,I have learning to do with timer overflow and trigerring events on overflow or matching preset register values. As is, this works fine. I forgot to zero range. doh.

    sub get_range ;us sensor
    range=0
    do until range > 0
    StopTimer 1
    range = USDistance(1)
    settimer 1, 25535
    Starttimer 1
    wait 10 ms
    loop
    end sub
    

    The glcd I'll sort with experiment..not logic. Robots don't do much really,lots of spare time for non mechanical stuff. Cheers.
    PS as I see servos it's the pulse width input to voltage and matching the pot voltage so no pulses..no voltage...but that just my interpretation.
    ps encore une fois...settimer 1, 65534 would start it faster for missed time?

     

    Last edit: stan cartwright 2017-05-29
  • William Roth

    William Roth - 2017-05-29

    @Stan

    Some newer PIC Chips have highly configurable 16-Bit PWM Modules. These are not yet supported in GCB but you can still use these 16 Bit PWMS with a bit of datasheet reading and some experimentation.

    In the code below I have used a PIC16F1788 with 16-bit PWM6. No interrupt is nedded to generate a Servo output at 50 hz with 16-bit PWM Duty resolution. This means there are ~4000 discrete steps with a servo pulse of 500us to 2500us (Servo full range).
    .
    In your code, simply set the new duty cycle ( servo position) when necesary, After setting the duty cycle, the code MUST subsequently then load the buffer with " Set PWM6LD ON" to initiate the change.

    ''' Single Servo Control using 16-bit PWM6 on PIC16F1778
    
     #chip 16f1778, 16
     #config OSC = INTOSC
     #config MCLRE=ON,  WDTE=OFF, BOREN = Off
     #option explicit
    
     DIM PWM6_Period ALIAS PWM6PRH,  PWM6PRL As WORD
     DIM PWM6_Duty   ALIAS PWM6DCH,  PWM6DCL As WORD
    
     PWM6_Period  = 39850 '// 50 Hz
     PWM6_Duty = 0
    
     Dir PORTC.3 OUT '// PWM6 Out on PORTC.3
    
     UnLockPPS
       RC3PPS = 0x001E    'PWM6OUT > RC3
     LockPPS
    
     PWM6CLKCON = 0b00110000   '// PWM6 Clock = FOSC / 8
     PWM6CON =    0b00000000    '// Standard Mode / Module Disabled
     SET PWM6EN ON  ' Enable the PWM6 Module
    
    ''' Servo Test Full Range Sweep / Adjust duty values as needed   
    Do
          For PWM6_duty = 1000 to 5000 Step 5
               Set PWM6LD ON    '// Load PWMDCx Buffer
               Wait 5 ms
           Next
          wait 2 s
    
          For PWM6_duty = 5000 to 1000 Step - 5
               Set PWM6LD ON   '// Load PWMDCx Buffer
               Wait 5 ms
          Next
          Wait 2 s
    Loop
    
     
  • kent_twt4

    kent_twt4 - 2017-05-30

    Yes, same for a little bit older chip like the 18f1330, and others, that have the 14 bit Power PWM modules. A real bear to set up, but once initlialized, it is ready to go. A servo example with all the gory details, not set for max resolution, but more than is required:

    ;Servo code using the hardware Power PWM module of the PIC18f1330
    #chip 18f1330, 4
    #config osc=INTIO2,HPOL=HIGH,LPOL=HIGH 'set PWM polarity bit for active high
    
    #define Servo PortB.1 ;Futaba s3003 servo 
    #define forward 570   ;500?
    #define neutral 330   ;375?
    #define reverse 90    ;250?
    dim PDC0 as word alias PDC0H, PDC0L
    dim PTPER as word alias PTPERH, PTPERL
    dim forward as word
    dim neutral as word
    dim reverse as word
    init_PowerPWM
    
    Main:
    PDC0 = forward
    wait 3 s
    PDC0 = neutral
    wait 3 s
    PDC0 = reverse
    wait 3 s
    goto Main
    
    sub init_PowerPWM
      SET PTEN OFF  ;Turn off the timer base
      ;set PTCON0 bits
      SET PTOPS3 OFF  ;Time base output postscale bits
      SET PTOPS2 OFF
      SET PTOPS1 OFF
      SET PTOPS0 OFF
      SET PTCKPS1 ON  ;Time base input prescale bits
      SET PTCKPS0 OFF  ;PRESCALE bits: 11= 1/64, 10=1/16 , 01=1/4, 00=1/1 
      SET PTMOD1 OFF  ;Time base mode select bits
      SET PTMOD0 OFF  ; 00=free running, 01=single shot, 10=up/dn, 11=up/dn double update
      ;set PTCON1 bits
      SET PTDIR ON ;PWM TIME BASE count direction: 0=counts up, 1=counts down
      ;PWMCON0 PWM control register
      SET PWMEN2 OFF  ;PWM module enable bits
      SET PWMEN1 OFF  ;001 is PWM1, 110 is PWM1 &pwm3
      SET PWMEN0 ON
      SET PMOD2 OFF ;PWM output pair mode pins
      SET PMOD1 OFF ;0= independent mode
      SET PMOD0 OFF ;1 = complementary mode 
      'PWMCON1 PWM control register, no deadtime or special interrupts set
      ;*************************************************************************
      ;* PTPER = (Fcy/(Fpwm*PTMRPrescaler))-1
      ;* Fcy = Fosc/4
      ;* for 20ms or 18ms servo update
      ;* Fpwm = 1/.020 or 1/.018 = 50 or 55.55Hz
      ;* PTPER = (1000000/(50*16))-1 = 1249 (12 bit no. max (i.e. 0xFFF for 18f))
      ;*************************************************************************
      ;could up the INTOSC to 8Mhz and PTPER=2499?
      PTPER = 1249
      ;*************************************************************************
      ;* Servo duty cycle is 1-2ms over the 20ms period or,
      ;* 1/20*4*PTPER 'full reverse', 1.5/20*4*PTPER 'neutral', 2/20ms*4*PTPER 'full forward'
      ;* to get the correct duty cycle must multiply by 4 because of Q1:Q0 in PTMR register
      ;* PDCx (PDCxH and PDCxL) will be forward = 500, neutral = 375, reverse = 250 
      ;*************************************************************************
      PDC0 = 0
      ;PDC1 = 0
      ;PDC2 = 0
      SET PTEN ON   ;Start up the timer base
    end sub
    
     
  • stan cartwright

    stan cartwright - 2017-05-30

    Thanks for the code examples. I find data sheets hard reading but if the register bit names are usable in gcb then that's a start. The best I got was lowering the clock to 1mhz but the duty was still too coarse.I still haven't figured out the hpwm which does stepped pwm and anti-phase if setup right it looks like. The mega328p has modes I've not worked out,true phase I read and again the registers names are used by gcb. All on my to do list. Thanks again.

     
  • stan cartwright

    stan cartwright - 2017-06-04

    After testing this is best way for me.

    sub get_range ;us sensor
    range=0
    do until range > 0
    intoff
    range = USDistance(1)
    inton
    wait 10 ms
    loop
    end sub
    ;;;;;;;;
    sub servo ;servo interrupt
    settimer 1, 25535
    pulseout Servo_Pin , radarpos 10us
    end sub
    

    I'm not convinced 100% it's ok.I sent a vid to Evan showing the servo working and hpwm to slow the motors cos the 2 diodes don't drop enough volts from the 2 batteries. Robots are easy with GCB. I find it fun.This needs 2 seperate 5v supplies. https://youtu.be/SAvBMbFqiOc
    ps forgot the camera mic was on...won't happen again

     

    Last edit: stan cartwright 2017-06-04
  • stan cartwright

    stan cartwright - 2017-06-04

    ebay stuff and a pic and GCB. C.2 hpwm goes to both motors.

     

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.