PDA

View Full Version : Inconsistant time using interupts



Mark J
- 28th September 2010, 14:58
Hi guys,

Im currently using Darrels DT_HID include file to control the USB aspects of my project and it works great :cool: and I am also using his DT_INTS-18 include and have setup my PWM routine in an INT_INT interupt and it works but with 1 slight thing that I cant for the life of me figure out.

Whats happening is that my project can set the pwm down to 1 millisecond and im using both channels for the pwm (its to control 2 DC powerheads for a marine reef tank) and have hooked up 2 LEDS to the pins (RC1 & RC2) and they flash away happily but they dont keep a constant rate, you can see them slow down for any period of time from a fraction of a second to maybe a second.

I have tried changing to different interupts and either they dont swap over or when I tried TMR0 (I think it was) they ran about 10 times faster than they should and I got errernous twitching on port A 1 & 2.

Im using an 18F2455 with a 4Mhz xtal and have a dallas DS18S20+ temp probe constantly reading the temp and displaying the info on an LCD screen (Hence why I used the interupt for the pwm routines otherwise because of the LCD and its pauses it needs etc, it ran way too slow)

Here are my settings for the ports etc.

ADCON0 = 0 'Set ADCON0
ADCON1 = %00001111 'Set D i/o
CMCON = 7 'Disable Comparators
CCP1CON = %00001100 'set pwm
CCP2CON = %00001100 'set pwm
TRISA = %00000000 'set PORTA as all output
TRISB = %00000000 'set PORTB as all output
TRISC = %00000000 'set PORTC as all output
PR2 = 63
T2CON = %00000110 ' Start Timer2, Prescaller 1:16


and here is the interupt setup using Darrels routines.

INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas"

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler USB_Handler
INT_Handler INT_INT, _Do_WaveMakers, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
endasm


My wavemaker code is a bit long winded looking but it works (probably an easier way to do it, but this is the way I could figure it out etc, and it dosnt take long to execute because its using case's so it only does 1 section per powerhead at a time)


Do_WaveMakers:

if PHWAVEBOX = 0 then 'No wavebox mode so we ramp up and down the power
select case PH1PHASE
case 0 'Ramp up the powerhead
PH1TIMER = PH1TIMER +1
if PH1TIMER >= 100 then '10th of a second count
PH1TIMER = 0
PH1PWR = PH1PWR + (ramp_step/10) 'now add calculated step value
endif
if PH1PWR > PHMAX then
PH1PWR = PHMAX
PH1PHASE = 1
endif
case 1 'At MAX power so hold there for duration
if PH1TIME < PHSECS then
if PH1TIME = (PHSECS/2) -2 and PHOVER = 2 then
PH2PWR = PHMIN
PH2PHASE = 0
PH2TIME = 0
endif
PH1TIMER = PH1TIMER + 1
if PH1TIMER = 1000 then
PH1TIME = PH1TIME + 1
PH1TIMER = 0
endif
else
PH1TIMER = ramp_step
PH1TIME = 0
PH1PHASE = 2
endif
case 2 'Ramp down the power to MIN value
PH1TIMER = PH1TIMER - 1
if PH1TIMER <= 0 then
PH1TIMER = 100
PH1PWR = PH1PWR - (ramp_step/10)
endif
if PH1PWR < PHMIN or PH1PWR > PHMAX then 'Need to have the > PHMAX as it can go below 0 which is higher than the MAX ;)
PH1PWR = PHMIN
PH1PHASE = 3
endif
case 3 'At MIN power so hold again
if PH1TIME < PHSECS AND PHOVER = 1 then 'Unless we are using the together mode (3) then we dont wait
PH1TIMER = PH1TIMER + 1
if PH1TIMER = 1000 then
PH1TIME = PH1TIME + 1
PH1TIMER = 0
endif
elseif PH1TIME < PHMSECS and PHOVER = 0 then
PH1TIMER = PH1TIMER + 1
if PH1TIMER = 1000 then
PH1TIME = PH1TIME + 1
PH1TIMER = 0
endif
elseif PH1TIME < PHSECS and PHOVER = 2 then
PH1TIMER = PH1TIMER + 1
if PH1TIMER = 1000 then
PH1TIME = PH1TIME + 1
PH1TIMER = 0
endif
else
PH1TIMER = 0
PH1TIME = 0
PH1PHASE = 0
endif
end select

select case PH2PHASE
case 0 'Ramp up the powerhead
PH2TIMER = PH2TIMER +1
if PH2TIMER >= 100 then '10th of a second count
PH2TIMER = 0
PH2PWR = PH2PWR + (ramp_step/10) 'now add calculated step value
endif
if PH2PWR > PHMAX then
PH2PWR = PHMAX
PH2PHASE = 1
endif
case 1 'At MAX power so hold there for duration
if PH2TIME < PHSECS then
PH2TIMER = PH2TIMER + 1
if PH2TIMER = 1000 then
PH2TIME = PH2TIME + 1
PH2TIMER = 0
endif
else
PH2TIMER = ramp_step
PH2TIME = 0
PH2PHASE = 2
endif
case 2 'Ramp down the power to MIN value
PH2TIMER = PH2TIMER - 1
if PH2TIMER <= 0 then
PH2TIMER = 100
PH2PWR = PH2PWR - (ramp_step/10)
endif
if PH2PWR < PHMIN or PH2PWR > PHMAX then 'Need to have the > PHMAX as it can go below 0 which is higher than the MAX ;)
PH2PWR = PHMIN
PH2PHASE = 3
PH2TIME = 0
endif
case 3 'At MIN power so hold again
if PHOVER = 2 and PH1PHASE = 3 then
PH1PWR = PHMIN
PH1PHASE = 0
PH1TIME = 0
endif
if PH2TIME < PHSECS AND PHOVER = 1 then 'Unless we are using the together mode (3) then we dont wait
PH2TIMER = PH2TIMER + 1
if PH2TIMER = 1000 then
PH2TIME = PH2TIME + 1
PH2TIMER = 0
endif
elseif PH2TIME < PHMSECS and PHOVER = 0 then
PH2TIMER = PH2TIMER + 1
if PH2TIMER = 1000 then
PH2TIME = PH2TIME + 1
PH2TIMER = 0
endif
elseif PH2TIME < PHMSECS and PHOVER = 2 then
PH2TIMER = PH1TIMER + 1
if PH2TIMER = 1000 then
PH2TIME = PH2TIME + 1
PH2TIMER = 0
endif
else
PH2TIMER = 0
PH2TIME = 0
PH2PHASE = 0
endif
end select
else 'Wavebox mode

select case PH1PHASE
case 0
if PH1TIME < PHMSECS then
PH1TIME = PH1TIME + 1
else
PH1PHASE = 1
PH1TIME = 0
PH1PWR = PHMIN
endif
case 1
if PH1TIME < PHMSECS then
PH1TIME = PH1TIME + 1
else
PH1PHASE = 0
PH1TIME = 0
PH1PWR = PHMAX
endif
end select

select case PH2PHASE
case 0
if PH2TIME < PHMSECS then
PH2TIME = PH2TIME + 1
else
PH2PHASE = 1
PH2TIME = 0
PH2PWR = PHMIN
endif
case 1
if PH2TIME < PHMSECS then
PH2TIME = PH2TIME + 1
else
PH2PHASE = 0
PH2TIME = 0
PH2PWR = PHMAX
endif
end select
endif
CCPR1L = PH1PWR >>2
CCP1CON.5 = PH1PWR.1
CCP1CON.4 = PH1PWR.0

CCPR2L = PH2PWR >>2
CCP2CON.5 = PH2PWR.1
CCP2CON.4 = PH2PWR.0

@ INT_RETURN


Ive tried using DISABLE and ENABLE at each end, and even INTCON.6 = 0,INTCON = 1 to try to stop anything that could be possibly interferring with the routine when its executed etc, but didnt seem to make any difference.

The main loop basically just calls the temp sensor to see if its alive, then if it is, reads the temp and sets a couple of pins depending on some settings, displays the temp on the screen, and then if the plugged flag is true using Darrels HID routine calls the USB but only when its plugged in.

Hope someone can shed some light onto my problem as im out of ideas on what else I can try.

It couldnt be anything to it been on a breadboard could it? as I remember reading somewhere about breadboards not been brilliant for certain things etc.

Many thanks in advance,

Mark.

Darrel Taylor
- 29th September 2010, 20:57
Mark,

I'm thinking that maybe you need to move the USB interrupts to Low Priority, so that it won't interfere with the PWM interrupts.

Like this ...
DEFINE USE_LOWPRIORITY 1

INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas"

ASM
;----[High Priority Interrupts]-----------------------------------------------
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _Do_WaveMakers, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor

;----[Low Priority Interrupts]------------------------------------------------
INT_LIST_L macro ; IntSource, Label, Type, ResetFlag?
INT_Handler USB_Handler
endm
INT_CREATE_L ; Creates the Low Priority interrupt processor
endasm


And you may need to synchronize loading the CCP registers with Timer2.
Or, use HPWM10 ... http://www.picbasic.co.uk/forum/showthread.php?t=6300&p=37805#post37805


HTH,

Mark J
- 29th September 2010, 21:04
Well, after hammering away at this for ages, I tried allsorts, TMR0,TMR1 timers with no avail as it dosnt help when I cant fully follow the datasheets for them etc (maybe one day it'll click! :rolleyes:)

In the end I removed the

CCPR1L = PH1PWR >>2
CCP1CON.5 = PH1PWR.1
CCP1CON.4 = PH1PWR.0

CCPR2L = PH2PWR >>2
CCP2CON.5 = PH2PWR.1
CCP2CON.4 = PH2PWR.0


from the interupt and as a last ditch attempt simply stuck in 2 HPWM functions in my main loop like this:


HPWM 1,PH1PWR,1000
HPWM 2,PH2PWR,1000


and crossed everything I could as it was a total shot in the dark and bingo! it works :D

I was getting really fed up with not been able to crack it, but just shows that sometimes going back to simpleton mode works lol!!!

Was surprised no one could offer any tips though, but in some ways it can help to be out on a limb and forces you to keep hammering away as it can pay off (thankfully while ive still got hair on my head :D)

Mark

Mark J
- 29th September 2010, 21:17
LOL,

Sorry Darrel, I never saw your post until just now! obviously the time it took me to actually write my last post was when you were writing yours too lol...

I'm going to bench test the code to triple check its doing what it should do, and if not i'll definately give your low level interupt a try.

Thats one thing I never thought about to be honest, as I did try to get the low level interupt working when I first was playing with your includes etc, but I never got it working (the usual, download the files, stick in the project and NOT read the instructions fully!:o Hmmm.. the phrase 'Look before you leap' springs to mind hehe...)

Mark

Sneaky-geek
- 15th November 2010, 14:51
Hi Mark,
Just wondering if there was any progress?

Tnx,

Sneaky-geek

Mark J
- 20th November 2010, 21:10
Hi Sneaky,

sorry its taken a while to reply, but touch wood, it seems to be running ok at the mo! I removed all the PWM calls from the interupt and put them in the main loop and it seems to be working as it should.

When I get the project finally finished, i'll probably have a play by making the USB interupts low priority like Darrel mentioned previously in the thread.
If I do and its still fine, i'll pop a reply to let everyone know etc.

Mark.
(been having probs hardware side dropping 24v dc to 12v without either having to use a huge heatsink etc, as everything ive tried so far keeps popping lol, but will be trying a step down regulator as soon as funds allow as it needs a few other parts to go with it and a redesign of the PCB, then etch etc etc.)