Announcement

Collapse
No announcement yet.

ME Lab Trainer Timer1 Interrupt assistance needed

Collapse
X
 
  • Time
  • Show
Clear All
new posts

  • ME Lab Trainer Timer1 Interrupt assistance needed

    9-1_Timer1_Interrupt rev A.pbp
    I am trying to use the timer1 interrupt to determine the pulse width of a servo pulse (1 to 2 milliseconds). I plan to have about 10 servos and will need to refresh them every 20 milliseconds. Thus, I am hoping to use the interrupt so I do have to wait for the pulse to end.

    I am using the ME Labs Trainer using the PIC16F1937 as a test bed. I cannot get the attached program to enter the interrupt handler. As timing is not critical, I figure I can use the ON INTERRUPT command.

    Once I get this working, I will also use the interrupts to indicate the completion of the ADC conversion—that will eventually load the value to timer 1.

    All suggestions would be appreciated.

    Larry Cardo

  • #2
    Not sure the attachment went thru? Here it is:

    ' microEngineering Labs Trainer-1 TIMER 1 UNTERRUPT TEST
    ' PLACE A HIGH ON porta.0 FOR THE TIME DECIDED BY TIMER ONE
    'ON OVERFLOW FROM TIMER1 PLACE A LOW ON PORTA.0, BY USING INTERRUPT. THEN REPEAT.
    ' Target microcontroller: PIC16F1937
    #CONFIG
    ; set CONFIG1 for internal oscillator
    __config _CONFIG1, _FOSC_INTOSC
    ; set CONFIG2 for int osc pll controlled by OSCCON register,
    ;low-voltage programming on
    __config _CONFIG2, _PLLEN_OFF & _LVP_ON
    ; see file PIC16F1937.INFO (in PBP installation) for more options
    #ENDCONFIG
    OSCCON = %01101000 ' Set internal osc to 4MHz with a 4x PLL disabled
    DEFINE OSC 4 ' Tell PBP that the device will clock at 4MHz
    ANSELA = %00000000 ' PortA all digital
    PORTA = %00000000 ' Init all PORTA bits to low condition

    ON INTERRUPT GOTO myint ' Interrupt handler is myint, enable interrupt-checking for lines below this point.
    INTCON = %10110000 ' Enable GIE and RB0 interrupt

    T1CON = %00110000 ' Enable Timer1 with prescale value 1:8
    T1_IFLAG VAR PIR1.0 ' Give name to Timer1 interrupt flag in PIR1 register
    SER VAR PORTA.0

    T1_RUN VAR T1CON.0 ' Name the Timer1 Start/Stop control bit in T1CON register
    LOW SER
    ' Attempt to use basic interrupt to time servo
    '
    mainloop:

    If SER = 0 then 'next servo
    gosub settimer
    else
    GOTO mainloop
    Endif
    GOTO mainloop

    settimer:
    HIGH SER 'start output to servo0
    T1_RUN = 0 'STOP TIMER1
    ' Load timer1 with 0-255 lsb for time
    TMR1L = -255 ' we do not know yet what time 255 will be
    TMR1H = -200
    T1_RUN = 1 ' START TIMER
    'T1CON = %00110001 ' Start timer Enable Timer1 with prescale value 1:8
    PIE1 = %10000001 ' enable timer1 overflow interrrupt
    T1_IFLAG = 0
    return

    myint: 'INTERRUPT ROUTINE
    DISABLE ' Disable interrupt-checking for all routines placed below this line.
    T1_RUN = 0 'STOP TIMER
    T1_IFLAG = 0 ' Clear Timer1 interrupt flag
    LOW SER ' stop servo pulse
    PORTA.1 = 1 'Did we enter interrupt handler? If so light LED
    INTCON.1 = 0 ' Clear interrupt flag
    INTCON = %10110000 ' Enable GIE and RB0 interrupt
    RESUME ' Return to MAINLOOP program

    Comment


    • #3
      if you post code in code tags its much easier to interpret,ON INTERRUPT will probably never achieve your goal , use dt_ints


      __config _CONFIG2, _PLLEN_OFF & _LVP_ON
      LVP_ON can and will lead to unexpected mcu behaviour use LVP_OFF unless you know better

      Code:
      settimer: 
       HIGH SER 'start output to servo0 
       T1_RUN = 0 'STOP TIMER1
       ' Load timer1 with 0-255 lsb for time 
       TMR1L = -255 ' we do not know yet what time 255 will be 
       TMR1H = -200
       T1_RUN = 1 ' START TIMER
       'T1CON = %00110001 ' Start timer Enable Timer1 with prescale value 1:8 
      [COLOR="red"] PIE1 = %10000001 ' enable timer1 overflow interrrupt[/COLOR]  ;this will not enable timer1 interrupt
      [COLOR="blue"]needs to be
      PIE1 = 1'
      intcon.6=1;peie=1[/COLOR]  
      
       T1_IFLAG = 0
       return
      pulsein would do a better job of measuring servo pulse width , your code does not sync timer with servo pulse nor does the interrupt routine differentiate which interrupt fired (int_int or tmr1_int). are you going to measure servo pulse width or the time between servo pulses ? is the sevo pulse active high or low ? . the variable latency using on_interrupt will lead to unavoidable inaccuracy also.

      Comment


      • #4
        Richard,

        Thanks. I am not trying to measure a servo pulse width. I am trying to generate a active high pulse. The pulse length will hopefully be determined by the number I load into timer 1.

        Not sure what code tags are, but I will research them. I heard about "DT_INTS" assembly interrupt program, but I'm lost with the simple basic routine.

        Thanks for the LVP_off and PIE1 suggestions.

        I will try these changes.

        Much appreciated,

        Larry

        Comment


        • #5
          I sure its been done before ,10 servos could be interesting (difficult) 8 would be relatively straight forward i think

          i would have two timer interrupts


          isr1 (every 2.5mS) giving a 2.5 window for each servo ;[ note 2.5 x 8 = 20mS == servo refresh rate]
          set servo[x] output high (x=1-8)
          preload isr2 timer with (64k-servo_time) duration
          enable isr2


          isr2 (set to the servo[x] period in uS) (@8mhz a 16 bit timer/with clk/2 input , preset to 65536- servo time in uS )
          sets servo[x] output low
          increment servo counter to next servo
          disable isr2
          Attached Files

          Comment


          • #6
            Richard,
            Your sketch is similar to what I am intending. Rather than send out a pulse every 2.5 mS, I plan to send out a servo pulse to the next servo upon completion of the previous servo pulse. This method, I should be assured of being able to send to 10 servos, as each would not be at the max of 2.2mS--making a refresh rate variable, but less that 20 mS.

            But I still cannot get the test program to output a high going pulse depending upon the value set in timer1??????

            Thanks again for your thoughts. My current code is attached.
            Attached Files

            Comment


            • #7
              this is what I was thinking
              Code:
              '****************************************************************
              '*  Name    :servo.BAS                                      *
              '*  Author  : [select VIEW...EDITOR OPTIONS]                    *
              '*  Notice  : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
              '*          : All Rights Reserved                               *
              '*  Date    : 2/1/2016                                          *
              '*  Version : 1.0                                               *
              '*  Notes   :    pic16f1825                                               *
              '*          :                                                   *
              '****************************************************************
               
                 
              #CONFIG
                           __config        _CONFIG1,    _FOSC_INTOSC & _CP_OFF & _WDTE_ON  &  _PWRTE_ON  &  _MCLRE_ON  & _CLKOUTEN_OFF
                            __config      _CONFIG2, _PLLEN_ON & _LVP_OFF
              #ENDCONFIG
              
              
              DEFINE OSC 32
               
              include "dt_ints-14.bas"
              include "REENTERPBP.bas" 
              
              
              
              
              asm
              INT_LIST macro
                    INT_Handler   TMR0_INT,   _serv,    PBP,  yes
                    INT_Handler   TMR1_INT,   _st,      PBP,  yes
                    endm
                    INT_CREATE
              
              ENDASM
              
              
              
              
              
                inc var bit
                buffer_dirty var bit
                buffer var word
                servo var byte
                servo_t var word[8]
                
              @Timer1 = TMR1L ; map timer registers to a word variable
               Timer1 VAR WORD EXT 
               
               
               
                 OSCCON=$70
                 ANSELA=0
                 ANSELC=0
                 OPTION_REG=%11010110
                
                 TRISA = %001110
                 TRISC = 0        ' set PORTC I/O 
               
                 porta.0=1
                
               clear
               
                latc=0
              @ int_enable  TMR0_INT
              @ int_enable  TMR0_INT
               servo=0
               pie1.0=1  
               servo_t[0]=500
               servo_t[1]=600
               servo_t[2]=700
               servo_t[3]=800
               servo_t[4]=900
               servo_t[5]=1000
               servo_t[6]=1200
               servo_t[7]=2000
               inc=0
               
               
              main:
               pause 15
               if ! buffer_dirty then
               if inc then
               buffer=servo_t[0]-1
               else
               buffer=servo_t[0]+1
               endif
               if buffer > 2300 then
                inc=1
               elseif   buffer < 500  then
                inc=0
               endif 
               buffer_dirty =1
               endif
              
               
              goto main 
              
              
              
              serv:
              tmr0=tmr0+100
              latc.0[servo]=1
              Timer1 = -servo_t[servo]
              pir1.0=0
              t1con=$31
              @ int_return
               
               
              st:
              t1con=0
              latc.0[servo]=0
              servo= servo+1
              if servo ==8 then   servo=0
              if buffer_dirty then   
                  servo_t[0]=buffer
                 buffer_dirty=0
                 endif
              '    lata.4=!lata.4
              'endif
              @ int_return
              it works quite well for 8 servo's.


              I'm not sure about your plan the refresh time for each servo would then be variable and may cause issues . I thought that most servos expect a 20ms refresh rate .

              I will try your code on a 16f1825

              Comment


              • #8
                some questions

                INTCON = %10110000 ' Enable GIE and RB0 interrupt
                why ?

                you are enabling tmr0_int and int_int here and never using either

                TMR1L = -255 ' we do not know yet what time 255 will be
                TMR1H = -10
                -10 is $f6 -255 = 1 therefore tmr1= 62977 ie about 65mS @4mhz pre scale =div 8
                why ?

                Comment


                • #9
                  sort of works now (moved output to portc to suit my setup)
                  set osc to 32mhz can't see any sense in snail-pace

                  Code:
                  ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
                  ' Rev B--Using Richards suggestions 
                  'microEngineering Labs Trainer-1 TIMER 1 INTERRUPT TEST
                  ' PLACE A HIGH ON porta.0 FOR THE TIME DECIDED BY TIMER ONE
                  'ON OVERFLOW FROM TIMER1 PLACE A LOW ON PORTA.0, BY USING INTERRUPT.  THEN REPEAT.
                  ' Target microcontroller: PIC16F1937 
                  #CONFIG
                               __config        _CONFIG1,    _FOSC_INTOSC & _CP_OFF & _WDTE_ON  &  _PWRTE_ON  &  _MCLRE_ON  & _CLKOUTEN_OFF
                                __config      _CONFIG2, _PLLEN_ON & _LVP_OFF
                  #ENDCONFIG
                   
                  OSCCON=$70 
                  DEFINE OSC 32 
                   TRISA = %001110
                     TRISC = 0   
                  ON INTERRUPT GOTO myint ' Interrupt handler is myint, enable interrupt-checking for lines below this point.
                  INTCON = %11000000 ' Enable GIE 
                  @Timer1 = TMR1L ; map timer registers to a word variable
                   Timer1 VAR WORD EXT 
                  T1CON = %00110000 '  Enable Timer1 with prescale value 1:8    
                  T1_IFLAG VAR PIR1.0 ' Give name to Timer1 interrupt flag in PIR1 register
                  SER VAR PORTc.0
                  
                  T1_RUN VAR T1CON.0 ' Name the Timer1 Start/Stop control bit in T1CON register
                  LOW SER 
                  ' Attempt to use basic interrupt to time servo  
                  PIE1 = 1                                                                                              '
                  mainloop:
                  
                  If SER = 0 then      'next servo   
                        pauseus 2000
                        gosub settimer
                        PORTA.5=0
                  Endif
                  GOTO mainloop
                  
                  settimer:        
                      HIGH SER     'start output to servo0
                      
                      T1_RUN = 0  'STOP TIMER1
                      
                      Timer1=63535
                      T1_RUN = 1    ' START TIMER        
                      
                      
                     T1_IFLAG = 0  'Set Timer1 Interrupt flag to 0
                  return
                     
                   DISABLE
                  myint:  'INTERRUPT ROUTINE
                      ' Disable interrupt-checking for all routines placed below this line.
                      T1_RUN = 0    'STOP TIMER
                         
                      LOW SER             ' stop servo pulse 
                       PORTA.5=1   'Did we enter interrupt handler?   If so light LED
                        
                     
                  RESUME ' Return to MAINLOOP program
                  enable

                  Comment


                  • #10
                    Richard,
                    Thank you for the time you spent helping me “from down under”. Always wanted to visit your country and New Zealand, but at 75 the probability is looking slim. I wanted to tour your country on a motorcycle.

                    I took your tailored program and slightly modified it for my PIC16F1937 to get it to compile. The only significant changes were in the config files.

                    The scope pic is at 1 mS per division. The scope is looking at the output of PORTA.0 or the servo port. The freq of the positive pulse varies directly with the PAUSEUS command?

                    Changing the value of timer1 does not change the scope pic?

                    I like the way you removed unnecessary stuff.

                    I think we are close, but with no cigar.

                    Also attached is the “slightly modified” program. For some reason LVP will not run when set to off?

                    Larry

                    ps The number I placed in timer 1 was just a guess to see how it affected the output as I varied it. The unused instructions were a result of my lack of knowledge.
                    Attached Files

                    Comment


                    • #11
                      Code:
                      TRISA = %001110
                      is incorrect for led to work should be TRISA = %111010


                      For some reason LVP will not run when set to off?
                      try this for config ,lvp_on will turn around and bite you eventually

                      Code:
                      #CONFIG
                        __config  _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON
                        __config  _CONFIG2, _WRT_OFF & _VCAPEN_OFF & _PLLEN_ON & _STVREN_ON & _BORV_19 & _LVP_OFF
                      #ENDCONFIG


                      tested and working , although I maintain the concept is flawed

                      Code:
                      ''****************************************************************
                      '*  Name    : UNTITLED.BAS                                      *
                      '*  Author  : [select VIEW...EDITOR OPTIONS]                    *
                      '*  Notice  : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
                      '*          : All Rights Reserved                               *
                      '*  Date    : 2/15/2016                                         *
                      '*  Version : 1.0                                               *
                      '*  Notes   :                                                   *
                      '*          :                                                   *
                      '****************************************************************
                      ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
                      ' Rev B--Using Richards suggestions 
                      'microEngineering Labs Trainer-1 TIMER 1 INTERRUPT TEST
                      ' PLACE A HIGH ON porta.0 FOR THE TIME DECIDED BY TIMER ONE
                      'ON OVERFLOW FROM TIMER1 PLACE A LOW ON PORTA.0, BY USING INTERRUPT.  THEN REPEAT.
                      ' Target microcontroller: PIC16F1825 
                      #CONFIG
                                   __config        _CONFIG1,    _FOSC_INTOSC & _CP_OFF & _WDTE_ON  &  _PWRTE_ON  &  _MCLRE_ON  & _CLKOUTEN_OFF
                                    __config      _CONFIG2, _PLLEN_ON & _LVP_OFF
                      
                                    
                                    
                      #ENDCONFIG
                       
                      OSCCON=$70 
                      DEFINE OSC 32 
                       TRISA = %111010
                         TRISC = 0   
                      ON INTERRUPT GOTO myint ' Interrupt handler is myint, enable interrupt-checking for lines below this point.
                      INTCON = %11000000 ' Enable GIE 
                      @Timer1 = TMR1L ; map timer registers to a word variable
                       Timer1 VAR WORD EXT 
                        
                      T1_IFLAG VAR PIR1.0 ' Give name to Timer1 interrupt flag in PIR1 register
                      SER VAR PORTA.0
                      T1CON=0
                      '
                      LOW SER 
                      ' Attempt to use basic interrupt to time servo  
                      PIE1 = 1                                                                                              '
                      T1_IFLAG =1
                      
                      mainloop:
                      If T1_IFLAG then      'next servo
                            pauseus 500
                            T1_IFLAG = 0  'Set Timer1 Interrupt flag to 0
                            PORTA.2=0
                            gosub settimer
                      Endif      
                      
                      GOTO mainloop
                      
                      settimer:        
                          HIGH SER     'start output to servo0      
                                  
                          Timer1=64535 
                          
                          T1CON=$31 ' START TIMER  
                      return   
                         
                      
                         
                       DISABLE
                      myint:  'INTERRUPT ROUTINE
                          ' Disable interrupt-checking for all routines placed below this line.
                          T1CON=0    'STOP TIMER           
                          LOW SER             ' stop servo pulse 
                           PORTA.2=1   'Did we enter interrupt handler?   If so light LED
                            
                          
                      RESUME ' Return to MAINLOOP program
                      enable
                      Last edited by richard; 02-15-2016, 03:08 PM. Reason: incomplete code

                      Comment


                      • #12
                        just noticed you are using a ME Labs Trainer , a device I know nothing about . There is a good chance it actually employs low voltage programming . the docs should have a sample config section in them somewhere it would be best to use one of them.

                        Comment


                        • #13
                          Thanks again Richard,

                          Using your revised config settings and they are working except for LVP_OFF. For the trainer it needs to be on.

                          Still working on some weird syntax errors with TRISA AND TRISC??? and "SER VAR PORTA.0 " is saying bad date type??

                          Playing with the previous revision, I found the pulse on PORTA.0 does not change with the value set in Timer 1. But does change with pauseus. If I rem out pauseus, the scope shows a square wave of a period of 5us.

                          Will continue to work on the weird syntax errors.

                          Larry

                          Comment


                          • #14
                            IF you have any appreciable load on the outputs ie a led with too small a series resistor
                            then you will have rmw issues

                            code to avoid rmw and demo variable servo pulse

                            Code:
                            '****************************************************************
                            '*  Name    : UNTITLED.BAS                                      *
                            '*  Author  : [select VIEW...EDITOR OPTIONS]                    *
                            '*  Notice  : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
                            '*          : All Rights Reserved                               *
                            '*  Date    : 2/15/2016                                         *
                            '*  Version : 1.0                                               *
                            '*  Notes   :                                                   *
                            '*          :                                                   *
                            '****************************************************************
                            ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
                            ' Rev B--Using Richards suggestions 
                            'microEngineering Labs Trainer-1 TIMER 1 INTERRUPT TEST
                            ' PLACE A HIGH ON porta.0 FOR THE TIME DECIDED BY TIMER ONE
                            'ON OVERFLOW FROM TIMER1 PLACE A LOW ON PORTA.0, BY USING INTERRUPT.  THEN REPEAT.
                            ' Target microcontroller: PIC16F1825 
                            #CONFIG
                                         __config        _CONFIG1,    _FOSC_INTOSC & _CP_OFF & _WDTE_ON  &  _PWRTE_ON  &  _MCLRE_ON  & _CLKOUTEN_OFF
                                          __config      _CONFIG2, _PLLEN_ON & _LVP_OFF
                            
                                          
                                          
                            #ENDCONFIG
                             
                            OSCCON=$70 
                            DEFINE OSC 32
                            
                             
                             TRISA = %111010
                             TRISC = 0  
                             
                              
                            ON INTERRUPT GOTO myint ' Interrupt handler is myint, enable interrupt-checking for lines below this point.
                            INTCON = %11000000 ' Enable GIE PEIE 
                            @Timer1 = TMR1L ; map timer registers to a word variable
                            
                            
                             Timer1 VAR WORD EXT 
                             servo_t  VAR WORD
                             INC VAR    BIT
                             
                             
                             
                             
                            T1_IFLAG VAR PIR1.0 ' Give name to Timer1 interrupt flag in PIR1 register
                            SER VAR LATA.0
                            
                            INC=0
                            LOW SER
                            T1CON=0
                            PIE1 = 1                                                                                              '
                            T1_IFLAG =1
                             servo_t=500
                            
                            mainloop:
                            If T1_IFLAG then      'next servo
                                  pauseus 500
                                  T1_IFLAG = 0  'Set Timer1 Interrupt flag to 0
                                  
                                  gosub settimer
                                  if inc then
                                    servo_t=servo_t-200
                                  else
                                    servo_t=servo_t+200
                                  endif
                                 if servo_t > 2100 then
                                    inc=1
                                    LATA.2=1
                                 elseif   servo_t< 500  then
                                    inc=0
                                    LATA.2=0
                                 endif 
                            Endif      
                            
                            GOTO mainloop
                            
                            settimer:        
                                SER=1     'start output to servo0      
                                        
                                Timer1=  - servo_t 
                                
                                T1CON=$31 ' START TIMER  
                            return   
                               
                            
                               
                             DISABLE
                            myint:  'INTERRUPT ROUTINE
                                ' Disable interrupt-checking for all routines placed below this line.
                                T1CON=0    'STOP TIMER           
                                SER =0            ' stop servo pulse 
                                   
                                  
                                
                            RESUME ' Return to MAINLOOP program
                            enable

                            Comment


                            • #15
                              Hi Richard,

                              I am a little disappointed relative to the difficulty is programming a simple interrupt. Life should not be this difficult. Taking a brief break. Also looking at the assemble program DT_.

                              Thanks,

                              Larry

                              Comment

                              Working...
                              X
                              😀
                              🥰
                              🤢
                              😎
                              😡
                              👍
                              👎