2 Attachment(s)
12F683 interrupt on change improvement?
I have a project using three 12F683s controlled by a 16F883 master. The goal of the project is to track the RPM of 4 independant propellers on a quadcopter using an IR photodiode and emitter (i.e. a beam breaker). When the propeller blade crosses between the IR photodiode and emitter, the voltage at the interrupt pin drops to ~0.7V (a 3.3k resistor to GND). When the blade moves out of the way, the voltage at the interrupt pin increases to ~4.8V. The IR setups for the 16F883 and the 12F683s are effectively identical (same wire lengths, same IR components, resistors, etc). The 16F883 drives an 8Mhz xtal osc with the osc2 pin tied to the osc1 pins of the 12F683s (short distance). The 16F883 starts the process and takes a pin high that tells the 12F683s to start logging data. The 16F883 also begins logging data. I opted to use 4 PICs as the props can spin around 9000RPM, which is ~300 interrupts per second (2 blades per prop) and I'm not sure how I'd get it to work with interrupts occuring that frequently and occasionally falling on top of each other.
My problem is that the 12F683s are not that reliable and the data is poor, however the 16F883 seems to be logging the blade interrupts great. Below are 2 examples of a 25 second run:
Attachment 10035
Attachment 10036
As is apparent, the 883 is doing great, but the 12F683s are not (data from all 12F683s is similar). The IR max and min voltages are meeting the high/low logic requirements (0.7V low, 4.8V high) and the IR setups are effectively the same for all 4 PICs, so I'm wondering if there's some register or code modification I can do to improve the 12F683 interrupts? Or is this more of a hardware issue between the 16F883 and 12F683?
Below is the code for the 12F683 PICs. The code and interrupt for the 16F883 is similar (identical interrupt routine in fact). Thanks in advance for any help or suggestions!
Dave
Code:
'PIC-12F683
#CONFIG
__config _FOSC_EC & _WDT_OFF & _CP_OFF & _MCLRE_OFF & _PWRTE_ON & _CPD_OFF &_FCMEN_OFF &_IESO_OFF
#ENDCONFIG
DEFINE OSC 8
'Initialize Regsters:
TRISIO =%101111 'I or O; MCLR is pin3
CMCON0 = 7 'Analog comparators off
ADCON0 = 0
ANSEL = 0 'all inputs digital, the adcin command automatically converts it to analog
CCP1CON=%00000000 'disable PWM mode
IOC=%00000100
OPTION_REG=%11000000 ' Interrupt on rising edge INTEDG bit, disable internal pullups
'pins and variables
EE_DAT var GPIO.1
EE_CLK var GPIO.0
INT_PIN VAR GPIO.2
MODEPIN VAR GPIO.3 'MCLR
OUTPIN VAR GPIO.4 'OUTPIN also hooked up to an LED
wsave var byte $20 SYSTEM
wsave1 var byte $A0 SYSTEM
pausetime1 var word
pausetime2 var word
hbfix var byte
ibit var bit
n var byte
wconfig var byte
address var word
wbit var bit
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP interrupts
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler GPC_INT, _PULSE_WIDTH, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_DISABLE GPC_INT ; disable external (INT) interrupts
wconfig=%10100000
'At 8Mhz with 1:1 prescaler
T1CON = %00000000 ' Prescaler = 1:1, timer off
low OUTPIN
pause 500
waitforstart:
OUTPIN=INT_PIN 'toggles LED on OUTPIN to make sure IR sensor is reading high (clear) or low (blade in the way)
if MODEPIN=1 then waitforstart
high OUTPIN
wbit=0 'initial write bit setting to make sure eeprom is written every other interrup
TMR1H = 0
TMR1L = 0
ibit=0
address=0
@ bsf T1CON, TMR1ON ' Start timer
@ INT_ENABLE GPC_INT ; enable external (INT) interrupts
main:
if MODEPIN=1 then waitforstart
if ibit=0 then main
@ INT_DISABLE GPC_INT ; disable external (INT) interrupts
if pausetime2.lowbyte=0 then pausetime2.highbyte=hbfix
if wbit=1 then
I2CWRITE EE_DAT,EE_CLK,wconfig,address,[pausetime1,pausetime2]
endif
pausetime1=pausetime2
address=address+2 'effectively adding 4 to address between eeprom writes
if address=0 then done 'if 0 at this point, rollover of address has occured and eeprom is full
wbit=~wbit
ibit=0
@ INT_ENABLE GPC_INT ; enable external (INT) interrupts
goto main
done:
input EE_CLK
input EE_DAT
low OUTPIN
pause 10
if MODEPIN=0 then done
goto waitforstart
'---[INT - interrupt handler]---------------------------------------------------
PULSE_WIDTH:
pausetime2.highbyte = TMR1H
pausetime2.lowbyte = TMR1L
hbfix = TMR1H
ibit=1
@ INT_RETURN
end
Re: 12F683 interrupt on change improvement?
I had thought - should I be using "INT_INT" instead of "GPC_INT"? It is set up using GPIO.2 as the interrupt pin, which is the dedicated INT pin per the datasheet. Can you set up an interrupt on GPIO.2 as you would any of the other viable GPIOs OR as the dedicated external interrupt? Looking at the INTCON register, seems like you can set bit 3 (GPIE) for any GPIO interrupt or bit 4 (INTE) specific to GP2/INT? Seems to compile OK with "INT_INT"...? I'm trying to understand the differences if they are both viable methods to set it up?
Re: 12F683 interrupt on change improvement?
Quote:
should I be using "INT_INT" instead of "GPC_INT"?
i would
you are not using IOC correctly since the gpio is never read in the isr to clear the change condition
4.2.3 INTERRUPT-ON-CHANGE
Each of the GPIO pins is individually configurable as an
interrupt-on-change pin. Control bits IOCx enable or
disable the interrupt function for each pin. Refer to
Register 4-5. The interrupt-on-change is disabled on a
Power-on Reset.
For enabled interrupt-on-change pins, the values are
compared with the old value latched on the last read of
GPIO. The ‘mismatch’ outputs of the last read are OR’d
together to set the GPIO Change Interrupt Flag bit
(GPIF) in the INTCON register (Register 2-3).
This interrupt can wake the device from Sleep. The
user, in the Interrupt Service Routine, clears the
interrupt by:
a) Any read or write of GPIO. This will end the
mismatch condition, then,
b) Clear the flag bit GPIF.
A mismatch condition will continue to set flag bit GPIF.
Reading GPIO will end the mismatch condition and
allow flag bit GPIF to be cleared. The latch holding the
last read value is not affected by a MCLR nor
Brown-out Reset. After these resets, the GPIF flag will
continue to be set if a mismatch is present.
Re: 12F683 interrupt on change improvement?
Hi Dave,
How clean is the output from your photodiode?
I have been working on a similar setup recently using an encoder wheel and photointerrupter.
I had greater success feeding the MCU's input pin via a schmitt-trigger buffer (SN74LVC1G17 or similar).
I hope this helps.
Cheers
Barry