News:

Let's find out together what makes a PIC Tick!

Main Menu

Help with : On_Hardware_Interrupt 16F1827

Started by wessie, Jul 29, 2021, 01:04 PM

Previous topic - Next topic

wessie

Hi All - I've attempted to write a program to control 2 RC servos. The basics of the program is to monitor the pneumatic pressures and to open the undercarriage doors then lowering the gear if the pressure drops below a certain pressure. The program also monitors the input from the RC Transmitter to either retract or lower the gear depending on the switch position on the transmitter i.e incoming PWM.
With the switch in the gear down positions the servos moves to its pre-determined position as captured during the programing sub-routine and is stable, but when I select the gear up position, the servos moves to the correct position and then after a while servo 1 just sporadically moves to the gear down position and then after a few second back to gear up position. There is no set timing pattern - just happens whenever.
I've tried different servos, but it is always servo 1 doing this.
I've tried slowing down the frequency of the interrupt, saving different variables ect. but servo 1 still does its own thing.
Below is my code. I would appreciate any suggestions. Tx

;-------------------------------------------------------------------------------
;**** Added by Fuse Configurator ****
; Use the Fuse Configurator plug-in to change these settings

Device = 16F1827

Config1 FOSC_INTOSC, WDTE_OFF, PWRTE_OFF, MCLRE_ON, CP_OFF, CPD_OFF, BOREN_OFF, CLKOUTEN_OFF, IESO_OFF, FCMEN_OFF
Config2 WRT_OFF, PLLEN_OFF, STVREN_OFF,LVP_OFF

;**** End of Fuse Configurator Settings ****
;-------------------------------------------------------------------------------
'
         Xtal = 8
         Declare Optimiser_Level = 1         
'ADC
         Declare Adin_Res = 10       ' 10-bit ADC result required
         Declare Adin_Tad = FRC      ' RC OSC chosen
         Declare Adin_Stime = 50     ' Allow 50us sample time
'Variables
         Dim Lop As Word            'For To Loops
         Dim RCC As Word            'Current Pulse Width
         Dim RAW As Word            'Voltage measured from sensor
         Dim SAF As Word            'Safty pressure stored
         Dim GUP As Word            'Gear up stored value
         Dim GDN As Word            'Gear down stored value
         Dim S1V As Word            'Servo1 value
         Dim S2V As Word            'Servo2 value
         Dim S1D As Word            'Servo 1 down travel adjust
'Define rest of pins
         Symbol LED PORTB.0          'LED
         Symbol PRS PORTA.1          'Pressure (AN1)
         Symbol RC PORTB.2           'RC Input from receiver
         Symbol BUT PORTB.3          'Button
         Symbol SV1 PORTB.4          'Servo Pin - Doors
         Symbol SV2 PORTB.5          'Servo Pin - Gear
         Symbol PreLoad = 0x63       'pre load value to start counting from
         Symbol GIE = INTCON.7       'Global Interrupt Enable
         Symbol TMR0IE INTCON.5      'TMR0 Overflow Interrupt Enable
         Symbol TMR0IF INTCON.2      'TMR0 Overflow Interrupt Flag
'
'Initialize Ports and Variables
INIT:
        On_Hardware_Interrupt GoTo ISR_Handler
        TRISB = %00001110          'PortB
        ADCON1 = %10110000         'Right Justified,Frc,Internal Vref=VDD
        ADCON0 = %00001000         'Set AN1
        OSCCON = %01110000         '8Mhz
'        OSCCON = %01101000         '4Mhz
        OSCTUNE = %00000000        'tune osc         
'
'Prescaler set at 8MHz for 20ms interrupt.
        OPTION_REG = %11000111      'Timer0, 1:256
        INTCON = %00000000          'All interrupt off
'
        For Lop = 1 To 4
        High LED:DelayMS 200:Low LED:DelayMS 200
        Next
        GoTo START
'
ISR_Handler:
        Context Save S1V,S2V,RCC
            If TMR0IF = 1 Then      'Was it a Timer0 overflow that triggered the Interrupt?
                TMR0IE = 0          'Turn interrupt off
                Servo SV1, S1V      'set servo1 at value
                Servo SV2, S2V      'set servo2 at value
                Clear TMR0
                TMR0 = PreLoad      'pre-load timer 0
                TMR0IF = 0          'clear interrupt flag
                TMR0IE = 1          'start the timer again
            EndIf
        Context Restore
'
START:
'Check jumper for programming
        If BUT = 0 Then
        High LED:DelayMS 1000:Low LED:DelayMS 1000:High LED:DelayMS 1000:Low LED
        GoTo PROG  'If jumper is on
        EndIf
'
'Read all variable values from eprom
        SAF = ERead 00         'Read Fail Safe pressure
        GDN = ERead 10         'Gear down value
        GUP = ERead 20         'Gear Up value
        GUP = (GUP / 2) * 10   'to calculate the correct PW for servo
        GDN = (GDN / 2) * 10   'at 8mHz puls it is double
        S1D = GDN - 100        'adjust servo 1 travel.
'
        TMR0 = PreLoad
        GIE = 1            'Enable Global Interupt
        TMR0IE = 1         'start interupt timer
'
'put door open / gear down position
TT:
        For Lop = 1 To 2000:DelayMS 1: Next    '2sec delay
        S1V = S1D      'Doors open
        For Lop = 1 To 2000:DelayMS 1: Next    '2sec delay
        S2V = GDN      'Gear Down
'
'now check that Tx switch if in gear down position
'delays are done in 1ms intervals as the interrupt triggers every 20ms (50Hz)
CHKTX:
        High LED
        For Lop = 1 To 500:DelayMS 1: Next    '500ms delay
        RCC = PulsIn RC,1           'measure pulse width from TX
        Low LED
        For Lop = 1 To 100:DelayMS 1: Next    '100ms delay
'
        If GDN > 1500 And RCC > 300 Then GoTo MAIN
        If GDN < 1500 And RCC < 300 Then GoTo MAIN

        GoTo CHKTX          'catch all

'
PROG:
'set low pressure, set gear up and down travel
'set jumper, turn on Tx with gear down selected
'after LED rapid flash select gear up
'when LED stays solid, switch off and remove jumper
'
'read low pressure safety
        RAW = ADIn 1                       'Read the ADC  AN1
        DelayMS 10                         'Adjust for 20ms bandwidth
        EWrite 00, [RAW]
        DelayMS 1000
'read gear down value from, Tx
        RCC = PulsIn RC,1           'measure pulse width from TX
        EWrite 10, [RCC]
        DelayMS 1000
'rapid flash to indicate gear up must be selected.
        For Lop = 1 To 20
            High LED:DelayMS 50:Low LED:DelayMS 100
        Next
'read gear up Value from, Tx
        RCC = PulsIn RC,1           'measure pulse width from TX
        EWrite 20, [RCC]
        DelayMS 1000
'High LED and Stop program
        High LED
        Stop
'
MAIN:
'Flash LED
        Toggle LED
'Check pressure
        RAW = ADIn 1                       'Read the ADC  AN1
        If RAW < SAF Then GoTo FixDN
'Read TX gear posision
        RCC = PulsIn RC,1                    'measure pulse width from TX
        For Lop = 1 To 10:DelayMS 1: Next    '10ms delay
'
        If GDN > 1500 And RCC > 300 Then GoTo GEARDN
        If GDN < 1500 And RCC < 300 Then GoTo GEARDN
GEARUP:
        S2V = GUP  'Gear Up
        For Lop = 1 To 5000:DelayMS 1: Next    '5 sec delay
        S1V = GUP  'Door Closed
        GoTo MAIN
'
GEARDN:
        S1V = S1D      'Doors open
        For Lop = 1 To 2000:DelayMS 1: Next    '2sec delay
        S2V = GDN      'Gear Down
        GoTo MAIN
'
FixDN:
        High LED
        S1V = S1D      'Doors open
        For Lop = 1 To 2000:DelayMS 1: Next    '2sec delay
        S2V = GDN      'Gear Down
'
        End

top204

#1
The Servo command is a blocking command with a delay inside it, so it should not be placed within an interrupt, and may cause timing problems.

What will be required for servos to be altered via an interrupt is a set of timings within the interrupt itself that create timed pulses but do not block.

See the demo program here: "C:\Users\User Name\PDS\Samples\New Samples\Multi_Servo_Controller" for ideas.

wessie