PDA

View Full Version : Interrupt won't execute.



bison_bloke
- 24th March 2010, 23:30
Hey all, another newbie question.

I'm trying to run a servo (later to be expanded to 2 servos) with timer1 interrupts. The program compiles nicely, but never gets to the interrupt routine. I've never used interrupts or the timer before, but I've read all that I can, and just can't figure it out.

I'm running on the 16F690

Here's my code:


define OSC 4
ON INTERRUPT GOTO INTCODE


DEFINE HSER_TXSTA 20h 'SET THE TRANSMIT REGISTER TO TRANSMITTER ENABLED
DEFINE HSER_BAUD 2400 'SET BAUD RATE
'DEFINE ADCIN PARAMETERS
Define ADC_BITS 10 'SET NUMBER OF BITS IN RESULT
Define ADC_CLOCK 3 'SET CLOCK SOURCE (3=RC)
Define ADC_SAMPLEUS 50 'SET SAMPLEING TIME IN uS
define LOADER_USED 1

SELECTOR VAR BYTE 'SELECTS PROGRAM TYPE
TEMP VAR WORD 'TEMPORY VARIABLE FOR ANY USE
POSITION VAR WORD 'POSITION OF SERVO1 1250 - 2500
OFFWIDTH VAR WORD 'HOW LONG THE PULSE NEEDS TO BE OFF FOR
FREQ VAR WORD 'FREQUENCY TO RUN THE SERVOS AT
PICOSC VAR BYTE BANK0 'TO STORE OSCILLATOR FREQUENCY IN
PERIOD VAR WORD 'TEMPORY VARIABLE TO DISPLAY THE PERIOD OF PULSE
PRESCALER VAR WORD 'STORES THE TIMER1 PRESCALER VALUE
TMROFF VAR WORD 'STORES THE TIME THAT THE SERVO1 PULSE WILL BE LOW
RUN VAR BIT 'IS THE PROGRAM RUNNING

SERVO1 var PORTA.0 'OUTPUT PIN FOR SERVO1
STARTSTOP VAR PORTB.6 'INPUT PIN FOR PUSHBUTTON
TRISB.4 = 1 'INPUT FOR SELECTOR SWITCH PIN 13
TRISA.0 = 0 'MAKES PIN 19 AN OUTPUT FOR SERVO1
TRISB.6 = 1 'MAKES PIN 11 AN INPUT FOR PUSHBUTTON

PRESCALER = 8 'DEFINES THE TIMER1 PRESCALER AS 18
FREQ = 50 'CONSTANT FREQUENCY FOR THE SERVOS
RUN = 0 'TEMPORARY VARIABLE FOR SERVO RUNNING

T1CON = %00110000 'SETS THE TIMER1 VALUES - PRESCALER = 8
GIE var INTCON.7
PEIE var INTCON.6
TMR1IE var PIE1.0
TMR1ON var T1CON.0

ADCON1 = %10000010 'SET PORTA ANALOGUE AND RIGHT JUSTIFY THE RESULT

GOSUB GETOSC

MAINLOOP
GOSUB FINDPROGRAM
GOSUB STARTPULSE
'GOSUB STOPPULSE
GOTO MAINLOOP

FINDPROGRAM 'SELECTS BETWEEN SEVERAL TYPES OF MOTION
ADCIN 10, TEMP 'READ CHANNEL 10 TO TEMP
IF TEMP = 15000 THEN POSITION = 125 'USES VOLTAGE DIVIDER TO
IF TEMP 15000 AND TEMP = 22000 THEN POSITION = 150 'VARY THE VOLTAGE ON CH10.
IF TEMP 22000 AND TEMP = 35000 THEN POSITION = 175 'THIS CONVERTS AND STORES
IF TEMP 35000 AND TEMP = 47000 THEN POSITION = 200 'TO 'TEMP'.
IF TEMP 47000 AND TEMP = 60000 THEN POSITION = 225
IF TEMP 60000 THEN POSITION = 250
GOSUB SETPULSE
RETURN

DISABLE INTERRUPT
INTCODE
IF SERVO1 = 0 THEN
TMR1H = ((65535 - POSITION)256) 'EXTRACT HIGH BYTE INTO TIMER1
TMR1L = ((65535 - POSITION)-(TMR1H256)) 'EXTRACT LOW BYTE
HSEROUT [HIGH , DEC TMR1H, LOW , DEC TMR1L,10,10,13]
HIGH SERVO1
ENDIF

IF SERVO1 = 1 THEN
TMR1H = ((65535 - TMROFF)256) 'EXTRACT HIGH BYTE INTO TIMER1
TMR1L = ((65535 - TMROFF)-(TMR1H256)) 'EXTRACT LOW BYTE
HSEROUT [HIGH , DEC TMR1H, LOW , DEC TMR1L,10,10,13]
LOW SERVO1
ENDIF
RESUME
ENABLE INTERRUPT

SETPULSE
POSITION = POSITION MIN 250 'MIN POSITION LIMITED TO 0 DEGREES
POSITION = POSITION MAX 125 'MAX POSITION LIMITED TO 180 DEGREES
HSEROUT [POSITION = ,DEC POSITION,10,13]
TMROFF = (((((10000 FREQ) 10) PRESCALER)10) - POSITION)
'HSEROUT [TMROFF = ,DEC TMROFF,10,10]
'PERIOD = TMROFF + POSITION
'HSEROUT [PERIOD = ,DEC PERIOD,10,10]

RETURN

STARTPULSE
HSEROUT [PULSE STARTED,10,10]
LOW SERVO1
GIE = 1 'GLOBAL INTERRUPT ENABLE
PEIE = 1 'PERIPHRIAL INTERRUPT ENABLE
TMR1H = 255 'SETS TIMER1 TO 65535
TMR1L = 255 'NEXT TICK WILL INTERRUPT
TMR1ON = 1
RETURN

STOPPULSE
HSEROUT [PULSE STOPPED,10,10]
LOW SERVO1
PEIE =0
RETURN

GETOSC

asm
ifdef OSC
MOVECB OSC, _PICOSC
else
MOVECB 4, _PICOSC
endif
endasm
RETURN

END

Thanks for any help, the learning curve seems steep at times.

Heckler
- 25th March 2010, 00:42
Hey Bison,

Yes, very steep learning curve... but the pay off is worth it.:)

Not sure if this is your real problem or not... but on the program I have that works with a 12F683...

Instead of using "DISABLE INTERRUPT" AND "ENABLE INTERRUPT"...

I just use "DISABLE" and "ENABLE".

Again, this is for the 12F683, but I also needed this...


INTCON = %11001000 'now enable GIE,PEIE,x,x,GPIE,x,x,x

I then use this bit of code when interrupted to see if the int. was caused by the timer1 overflow or because one of the inputs (button) went low...


disable

MyInt:

inttype = PIR1 & %00000001 'check if timer1 overflow occured
if inttype = 1 then goto TimerInt

goto buttonint 'interrupt was gpio.3

I do not have the time to examine your code in detail right now but there are a couple of things to check.

good luck
Dwight

bison_bloke
- 25th March 2010, 02:04
Thanks Dwight, I tried that, but it didn't help. The interrupt isn't happening at all.

Heckler
- 25th March 2010, 03:41
Just thinking out loud now...

some possibilities:
What is the source for the timer clock?
What is the prescaler value?
Did you properly enable the timer interrupt?
(with the 12f683 it is the PIE1 reg)
INTCON reg setup correctly?

I can't remember exactly why right now... but at the end of my timer interrupt service routine I had these two lines, which clears bit 0 of these two registers. I think it clears the interupt flags so that when the "ENABLE" statement is hit(at then end of the interrupt handler code), it does not immediatly, falsely, re-interrupt.


intcon.0 = 0
PIR1.0 = 0

These are just my musings and I too am a newbie at this stuff
If all else fails then write a small snippet of code that just tests one portion of your code to try and narrow the problem down.

Do not forget to make the chip .pdf manual your best friend:)... you must, must, must read it! (a section at a time) go to the section on timers and on interupts and see what it tells you.

That, in my opinion, is really the BIG difference between the versatility of the PIC micros and of something like the basic stamp. The PIC has much to offer and therefore much to configure correctly.

Good luck
Dwight

bison_bloke
- 25th March 2010, 04:00
What is the source for the timer clock?

Internal oscillator, I think I've selected this properly, but I'm not sure.


What is the prescaler value?

It should be 8 - I hope.


Did you properly enable the timer interrupt?

I tried to. I suspect this is where I need the help.


INTCON reg setup correctly?

Once again, I'm not sure. I tried to.


Do not forget to make the chip .pdf manual your best friend:)... you must, must, must read it!

I've read this, and other sections many times, but I really am starting from scratch here. I've nutted out quite a few things, but so much of the terminology is unfamiliar to me that it's not always clear.

Heckler
- 25th March 2010, 04:04
Below is text copied from the 16f690 docs...

Section 6.7 Timer1 Interrupt
The Timer1 register pair (TMR1H:TMR1L) increments
to FFFFh and rolls over to 0000h. When Timer1 rolls
over, the Timer1 interrupt flag bit of the PIR1 register is
set. To enable the interrupt on rollover, you must set
these bits:
• TMR1ON bit of the T1CON register
• TMR1IE bit of the PIE1 register
• PEIE bit of the INTCON register
• GIE bit of the INTCON register
The interrupt is cleared by clearing the TMR1IF bit in
the Interrupt Service Routine.

Note: The TMR1H:TTMR1L register pair and the
TMR1IF bit should be cleared before
enabling interrupts.

I feel your pain!:o

Dwight

LinkMTech
- 25th March 2010, 05:33
Can't help with the interupts for now but will offer a suggestion for your A/D part. I'm not sure how you got the numbers to compare and set the servo output values. Your variable "temp" will only get a value somewhere between 0 and 1023 due to the 10bit A/D.


FINDPROGRAM 'SELECTS BETWEEN SEVERAL TYPES OF MOTION
ADCIN 10, TEMP 'READ CHANNEL 10 TO TEMP
IF TEMP = 15000 THEN POSITION = 125 'USES VOLTAGE DIVIDER TO
IF TEMP 15000 AND TEMP = 22000 THEN POSITION = 150 'VARY THE VOLTAGE ON CH10.
IF TEMP 22000 AND TEMP = 35000 THEN POSITION = 175 'THIS CONVERTS AND STORES
IF TEMP 35000 AND TEMP = 47000 THEN POSITION = 200 'TO 'TEMP'.
IF TEMP 47000 AND TEMP = 60000 THEN POSITION = 225
IF TEMP 60000 THEN POSITION = 250
GOSUB SETPULSE
RETURN


I would suggest using the SELECT CASE to compare your 6 A/D value possibilities. List the "Values" in ascending order and this will set your "POSITION" value as needed.


FINDPROGRAM 'SELECTS BETWEEN SEVERAL TYPES OF MOTION
ADCIN 10, TEMP ' Note: Value returned will be anywhere from 0 to 1023
SELECT CASE TEMP
CASE Value1: POSITION = 125 'TEMP = Value1, lowest value
CASE is <= Value2: POSITION = 150 'TEMP <= Value2
CASE IS <= Value3: POSITION = 175 'TEMP <= Value3
CASE IS <= Value4: POSITION = 200 'TEMP <= Value4
CASE IS <= Value5: POSITION = 225 'TEMP <= Value5
CASE Value6: POSITION = 250 'TEMP = Value6, highest value
END SELECT
GOSUB SETPULSE
RETURN

bison_bloke
- 25th March 2010, 08:33
Thanks for the input Link, I'll have to have a look at that code, it looks smaller than mine.

The way I've done it works currently though. When I cut and pasted code it seems some characters didn't come across for some reason. the individual lines should look more like:


IF TEMP > 22000 AND TEMP <= 35000 THEN POSITION = 175

I don't know why, but the ADC values do come out between those values; they go all the way up to 65535 with full voltage. I tried to calculate how they'd come out before I coded it, but ended up just adjusting them after seeing the output. If anyone knows why that'd be interesting.

Still need help with the interrupts though.

I've since added every single registry setting I could find in, and i got it off the ground, but it's giving me very strange results. I'll post more details once the kids are in bed.:p

Acetronics2
- 25th March 2010, 09:45
Hi, BB

your code doesn't compile at all ...

from MCS ...



FATAL ERROR: Too many errors. (21)
ERROR Line 53: Bad expression or missing THEN. (AdCServo.pbp)
ERROR Line 53: Syntax error. (AdCServo.pbp)
ERROR Line 54: Bad expression or missing THEN. (AdCServo.pbp)
ERROR Line 54: Syntax error. (AdCServo.pbp)
ERROR Line 55: Bad expression or missing THEN. (AdCServo.pbp)
ERROR Line 55: Syntax error. (AdCServo.pbp)
ERROR Line 56: Bad expression or missing THEN. (AdCServo.pbp)
ERROR Line 56: Syntax error. (AdCServo.pbp)
ERROR Line 57: Bad expression or missing THEN. (AdCServo.pbp)
ERROR Line 64: Bad expression. (AdCServo.pbp)
ERROR Line 65: Bad expression. (AdCServo.pbp)
ERROR Line 66: Bad expression. (AdCServo.pbp)
ERROR Line 71: Bad expression. (AdCServo.pbp)
ERROR Line 72: Bad expression. (AdCServo.pbp)
ERROR Line 73: Bad expression. (AdCServo.pbp)
ERROR Line 82: Bad expression. (AdCServo.pbp)
ERROR Line 83: Bad expression. (AdCServo.pbp)
ERROR Line 91: Bad expression. (AdCServo.pbp)
ERROR Line 101: Bad expression. (AdCServo.pbp)


add to that most of the operators and tokens are missing, your TMR1 calculations are false ( Where's the prescaler you've set to 8, gone ??? ), TMROFF calculations also false, your HSEROUT command syntax is not correct ...
and the servo pulse values do not match 0 and 180° positions !

Ok, I stop here ...

You'd better rewrite your PROJECT on a white sheet from very start ...

Would be much better ( and quicker ) than trying to correct what you've done ...

AND I did forget last, but not least ... do not use " ON INTERRUPT " as timing is critical here ... only ASM interrupts will fit here ... IF you insist on using interrupts - that are not at all compulsory in such a project -


Alain

bison_bloke
- 25th March 2010, 09:51
As mentioned above, I've added every single register entry that I could find that was related to timer1.

The interrupt now executes, but I'm getting weird results.

Firstly here's the code for the registry entrys I've added:


T1CON = %00110001 'ENABLE X,X,PRESCALER = 8,X,X,X,TMR1ON
INTCON = %11001000 'ENABLE GIE,PEIE,x,x,GPIE,x,x,x
GIE var INTCON.7
PEIE var INTCON.6
TMR1IE var PIE1.0
TMR1ON var T1CON.0
TMR1IE = 1 '
PEIE = 1 'WHO KNOWS
GIE = 1 'WHAT ALL OF
PIR1.0 = 0 'THESE DO, BUT IT
TMR1H = 0 'DIDN'T START
TMR1L = 0 'WITHOUT THEM.

I'm thinking I've added too many, but I don't really know how they work - even after reading the datasheet several times. If anyone has any comments to make about these I'd be most grateful, I really am trying to learn.

Here's the interrupt routine again:


DISABLE' INTERRUPT
INTCODE:
IF SERVO1 = 0 THEN
HSEROUT ["FIRST IF - POSITION: ",DEC POSITION,10]
TMR1H = ((65535 - POSITION)/256) 'EXTRACT HIGH BYTE INTO TIMER1
TMR1L = ((65535 - POSITION)-(TMR1H*256)) 'EXTRACT LOW BYTE
HSEROUT ["HIGH: ", DEC TMR1H," LOW: ", DEC TMR1L,10]
SERVO1 = 1
HSEROUT ["SERVO1: ",DEC SERVO1,10,10]
ENDIF

IF SERVO1 = 1 THEN
HSEROUT ["SECOND IF - TMROFF: ",DEC TMROFF,10]
TMR1H = ((65535 - TMROFF)/256) 'EXTRACT HIGH BYTE INTO TIMER1
TMR1L = ((65535 - TMROFF)-(TMR1H*256)) 'EXTRACT LOW BYTE
HSEROUT ["HIGH: ", DEC TMR1H," LOW: ", DEC TMR1L,10,10,13]
SERVO1 = 0
HSEROUT ["SERVO1: ",DEC SERVO1,10,10]
ENDIF
INTCON.0 = 0
PIR1.0 = 0
RESUME
ENABLE' INTERRUPT

and here's the results on the serial port:

FIRST IF - POSITION: 225
HIGH: 12 LOW: 64
SERVO1: 0

This is where it gets weird. I'm trying to extract the high and low bits for timer1, ie. I want the timer to countdown for the amount of time stored in 'position'. So the timer has to equal 65535 - Position. I need to break this down into the high and low bits for tmr1H and tmr1L. So tmr1H = 65535 - position / 256 etc. (much thanks to Aratti for helping me with that).

The strange thing is the value that the PIC has calculated for high and low.

high should equal (65535 - 225(value for position is shown in serout))/256 = 255.11 (I know we'll lose the .11)

Low should equal ((65535 - 225)-(255*256) = 30
of course this last value won't be correct until the first one comes out right, but even with the first incorrect value from formula one in place it's still all wrong.

I can't figure it out. Why so far out?
It looks too simple to go wrong. I'm missing something.

Can hair be glued back in?

I can't find a smilie for crying desperately...

bison_bloke
- 25th March 2010, 09:56
Hey Ace, thanks for looking it over.

As mentioned briefly above, when I cut and pasted my code, it seems a lot of the symbols didn't come across. I'll repost here:


define OSC 4
ON INTERRUPT GOTO INTCODE


DEFINE HSER_TXSTA 20h 'SET THE TRANSMIT REGISTER TO TRANSMITTER ENABLED
DEFINE HSER_BAUD 2400 'SET BAUD RATE
'DEFINE ADCIN PARAMETERS
Define ADC_BITS 10 'SET NUMBER OF BITS IN RESULT
Define ADC_CLOCK 3 'SET CLOCK SOURCE (3=RC)
Define ADC_SAMPLEUS 50 'SET SAMPLEING TIME IN uS
define LOADER_USED 1

SELECTOR VAR BYTE 'SELECTS PROGRAM TYPE
TEMP VAR WORD 'TEMPORY VARIABLE FOR ANY USE
POSITION VAR WORD 'POSITION OF SERVO1 1250 - 2500
OFFWIDTH VAR WORD 'HOW LONG THE PULSE NEEDS TO BE OFF FOR
FREQ VAR WORD 'FREQUENCY TO RUN THE SERVOS AT
PICOSC VAR BYTE BANK0 'TO STORE OSCILLATOR FREQUENCY IN
PERIOD VAR WORD 'TEMPORY VARIABLE TO DISPLAY THE PERIOD OF PULSE
PRESCALER VAR WORD 'STORES THE TIMER1 PRESCALER VALUE
TMROFF VAR WORD 'STORES THE TIME THAT THE SERVO1 PULSE WILL BE LOW
RUN VAR BIT 'IS THE PROGRAM RUNNING?

ADCON1 = %10000010 'SET PORTA ANALOGUE AND RIGHT JUSTIFY THE RESULT

SERVO1 var PORTA.0 'OUTPUT PIN FOR SERVO1
PUSHBUTT VAR PORTA.2 'INPUT PIN FOR PUSHBUTTON
TRISB.4 = 1 'INPUT FOR SELECTOR SWITCH PIN 13
TRISA.0 = 0 'MAKES PIN 19 AN OUTPUT FOR SERVO1
TRISA.2 = 1 'MAKES PIN 17 AN INPUT FOR PUSHBUTTON

PRESCALER = 8 'DEFINES THE TIMER1 PRESCALER AS 1:8
FREQ = 50 'CONSTANT FREQUENCY FOR THE SERVOS
RUN = 0 'TEMPORARY VARIABLE FOR SERVO RUNNING

T1CON = %00110001 'ENABLE X,X,PRESCALER = 8,X,X,X,TMR1ON
INTCON = %11001000 'ENABLE GIE,PEIE,x,x,GPIE,x,x,x
GIE var INTCON.7
PEIE var INTCON.6
TMR1IE var PIE1.0
TMR1ON var T1CON.0
TMR1IE = 1 '
PEIE = 1 'WHO KNOWS
GIE = 1 'WHAT ALL OF
PIR1.0 = 0 'THESE DO, BUT IT
TMR1H = 0 'DIDN'T START
TMR1L = 0 'WITHOUT THEM.

GOSUB GETOSC

MAINLOOP:
IF PUSHBUTT = 1 THEN
HSEROUT ["HIGH.",13,10]
ELSE
HSEROUT ["LOW",13,10]
ENDIF
GOSUB FINDPROGRAM
GOSUB STARTPULSE
'GOSUB STOPPULSE
GOTO MAINLOOP

FINDPROGRAM: 'SELECTS BETWEEN SEVERAL TYPES OF MOTION
ADCIN 10, TEMP 'READ CHANNEL 10 TO TEMP
IF TEMP <= 15000 THEN POSITION = 125 'USES VOLTAGE DIVIDER TO
IF TEMP > 15000 AND TEMP <= 22000 THEN POSITION = 150 'VARY THE VOLTAGE ON CH10.
IF TEMP > 22000 AND TEMP <= 35000 THEN POSITION = 175 'THIS CONVERTS AND STORES
IF TEMP > 35000 AND TEMP <= 47000 THEN POSITION = 200 'TO 'TEMP'.
IF TEMP > 47000 AND TEMP <= 60000 THEN POSITION = 225
IF TEMP > 60000 THEN POSITION = 250
GOSUB SETPULSE
RETURN

DISABLE' INTERRUPT
INTCODE:
IF SERVO1 = 0 THEN
HSEROUT ["FIRST IF - POSITION: ",DEC POSITION,10]
TMR1H = ((65535 - POSITION)/256) 'EXTRACT HIGH BYTE INTO TIMER1
TMR1L = ((65535 - POSITION)-(TMR1H*256)) 'EXTRACT LOW BYTE
HSEROUT ["HIGH: ", DEC TMR1H," LOW: ", DEC TMR1L,10]
SERVO1 = 1
HSEROUT ["SERVO1: ",DEC SERVO1,10,10]
ENDIF

IF SERVO1 = 1 THEN
HSEROUT ["SECOND IF - TMROFF: ",DEC TMROFF,10]
TMR1H = ((65535 - TMROFF)/256) 'EXTRACT HIGH BYTE INTO TIMER1
TMR1L = ((65535 - TMROFF)-(TMR1H*256)) 'EXTRACT LOW BYTE
HSEROUT ["HIGH: ", DEC TMR1H," LOW: ", DEC TMR1L,10,10,13]
SERVO1 = 0
HSEROUT ["SERVO1: ",DEC SERVO1,10,10]
ENDIF
INTCON.0 = 0
PIR1.0 = 0
RESUME
ENABLE' INTERRUPT

SETPULSE:
POSITION = POSITION MIN 250 'MIN POSITION LIMITED TO 0 DEGREES
POSITION = POSITION MAX 125 'MAX POSITION LIMITED TO 180 DEGREES
HSEROUT ["POSITION = ",DEC POSITION,10,13]
TMROFF = (((((10000 / FREQ) * 10) / PRESCALER)*10) - POSITION)
'HSEROUT ["TMROFF = ",DEC TMROFF,10,10]
'PERIOD = TMROFF + POSITION
'HSEROUT ["PERIOD = ",DEC PERIOD,10,10]

RETURN

STARTPULSE:
HSEROUT ["PULSE STARTED",10,10]
LOW SERVO1
'GIE = 1 'GLOBAL INTERRUPT ENABLE
'PEIE = 1 'PERIPHRIAL INTERRUPT ENABLE
TMR1H = 255 'SETS TIMER1 TO 65535
TMR1L = 255 'NEXT TICK WILL INTERRUPT
TMR1ON = 1
RETURN

STOPPULSE:
HSEROUT ["PULSE STOPPED",10,10]
LOW SERVO1
PEIE =0
RETURN

GETOSC:

asm
ifdef OSC
MOVE?CB OSC, _PICOSC
else
MOVE?CB 4, _PICOSC
endif
endasm
RETURN

END

I hope it worked this time, dunno what went wrong the first time.

Acetronics2
- 25th March 2010, 10:05
Sorry to insist, but " ON INTERRUPT " can't make things work nicely ...

latency can be much over the positionning pulse length ...

so, no hope this way ...

Alain

bison_bloke
- 25th March 2010, 10:12
Fair enough Ace, I guess I'll have to nut out some ASM.


IF you insist on using interrupts - that are not at all compulsory in such a project -

Does this mean there's another way of doing this without interrupts?

Bear in mind that I need to expand this to running two servos at once.


your TMR1 calculations are false ( Where's the prescaler you've set to 8, gone ??? ),

Are you saying that my timer1 calcs are wrong because I don't have a prescaler? All the calcs were done with the idea that if you multiplied them by 8 they would come out right.

I thought T1CON = %00110001, would make the prescaler 8, have I done that wrong too?

Sorry for all the mistakes, I'm just trying to figure it out.

Jumper
- 25th March 2010, 10:22
If you have not looked at AND REJECTED the instant interupts that is made by DT (DT´s instant interupts) you should really look into that now.
It is a way to solve all problems without even knowing how to spell to ASM.

/me

Acetronics2
- 25th March 2010, 10:27
Hi, Jumper

DT Basic Interrupts are wayyy too slow, here ... and overall their execution time is not predictable for timing corrections ...

so, no joy nor !

You do have to deal with ASM ... or write the program in pure PBP, without any interrupts ...

Alain

PS: and do not forget DT Bas ints consume a lot of RAM ...

@ BB



Does this mean there's another way of doing this without interrupts?

Bear in mind that I need to expand this to running two servos at once.


I alredy built a 4 channels fail-safe in pure PBP ... 4 Channels to read and 4 channels to output ... so, your project looks quite doable.
Writing a neat timechart ... of course.

bison_bloke
- 25th March 2010, 11:24
alright Ace, I give in, you've got me in dispair with this project, I'll look for a totally different way.


I alredy built a 4 channels fail-safe in pure PBP ... 4 Channels to read and 4 channels to output ... so, your project looks quite doable.
Writing a neat timechart ... of course.

Is this something you've released that I can learn from or even adapt?

If I can't see the code, can you give me some hints about the way forward?

I don't mind all the time charts in the world, but what's it for?

I'll stop bothering you now, time for bed.

Either way, thanks for the help, it's good to know when the idea you've got is impossible, that way you can move on; even if it is disheartening. Sniff...

I'll check out DT's interrupts anyway - always learning.

Acetronics2
- 25th March 2010, 12:53
Ok BB

First of all ...

explain with clear words what your device has to do :

from which inputs (w/ details ) to which outputs ( w/details ) ...

50% of the work is here ...

Alain

PS: and stop thinking " C " ... you must think " Basic " now ! ( ROFL)

Darrel Taylor
- 25th March 2010, 18:48
DT Basic Interrupts are wayyy too slow, here ... and overall their execution time is not predictable for timing corrections ...

Too Slow???
For a Servo??? Get real.
I've run 16 servo's simultaneously with DT_INTS.

Timing not predictable??? What???
It's extremely predictable. What are you talking about?


PS: and do not forget DT Bas ints consume a lot of RAM ...

oooo, ~50 bytes to have super easy interrupts, yeah too much RAM.


alright Ace, I give in, you've got me in dispair with this project, I'll look for a totally different way.
Don't listen to Alain.
He's just being obstinate.

bison_bloke
- 25th March 2010, 22:07
I've run 16 servo's simultaneously with DT_INTS.

Does this mean there's code out there that I can directly adapt?:D:D

Where would I find this?


explain with clear words what your device has to do :

from which inputs (w/ details ) to which outputs ( w/details ) ...


I have two inputs: start/stop button and a 'selector switch' which I already have working with that if statement you see above.

I have three outputs: two servos that I need to 'bounce' independently of each other. I need them to simulate the somewhat random movements that a passenger in a car would experience whilst driving. The third input is for vibration, this is just an unbalanced DC motor - np.

I also want to run a countdown timer so that it gets turned of after 20mins.


50% of the work is here ...

So now that my project is exactly half done:p, which way do I head?

Darrel Taylor
- 26th March 2010, 00:11
Does this mean there's code out there that I can directly adapt?

Where would I find this?
Well, that program is extensive ... each channel has it's own Center Trim, Gain and 10-bit positions, with stored programmed movements.
Never released it. Because I'd have to support it. :eek:

But since you don't seem to mind ON INTERRUPT ... there's a sample at meLabs for the LAB-X1 board.
It drives 2 servos using interrupts.
Has buttons, an LCD ... sounds just like what you wanted. :)

servosx.bas
http://melabs.com/resources/samples.htm
<br>

Acetronics2
- 26th March 2010, 08:14
I have two inputs: start/stop button and a 'selector switch' which I already have working with that if statement you see above.

I have three outputs: two servos that I need to 'bounce' independently of each other. I need them to simulate the somewhat random movements that a passenger in a car would experience whilst driving. The third input is for vibration, this is just an unbalanced DC motor - np.

I also want to run a countdown timer so that it gets turned of after 20mins.



So now that my project is exactly half done:p, which way do I head?

Hi, BB

Just missing : is both servos position given by a unique " selector pot " ( 6 positions , if I have correctly understood ) , so both servos receive same driving pulse ???

Alain

For the Heading ...

I'd propose you a " system clock " @ 50 Hz ... with a timer interrupt ( very, very simple kind of interrupt ). And as 20 mins = 60000 " ticks " @ 50 Hz ... it's done

If you think to it, tasks are done in a linear way and the whole sequence is repeated @ 50 Hz ...

so, just let me an hour to open the '690 Datasheet ( never worked with this chip to the day ) ...

bison_bloke
- 26th March 2010, 09:56
Both servos will run on different signals. There will be no pots involved.

The user selects a 'program' from the selector switch, hit's start, and a predefined program controls everything from there. The servos will almost always be in different positions to each other.

Acetronics2
- 26th March 2010, 11:27
Hi,

Have a look to your PMs ... and enjoy

@ Darrel : Do not look at it ... you won't like at all ...

Alain

Acetronics2
- 26th March 2010, 15:46
Hi,

Here it is for Everyone ...

a running version with a 16F877a and EasyPic 5 .

still something to debug with HSEROUT, probably a timing issue ...



'************************************************* ***************
'* Name : AdcServo2 : the ultimate vibrator ... *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2008 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 01/10/2008 *
'* Process.: 16F877a / EasyPic5 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************'

'************************************************* *****************************
' Config
@ device HS_OSC , WDT_ON , PWRT_ON , BOD_ON , LVP_OFF , protect_OFF

'************************************************* *****************************
'Defines

DEFINE OSC 8

DEFINE INTHAND _MAINLOOP

DEFINE HSER_TXSTA 20h 'SET THE TRANSMIT REGISTER TO TRANSMITTER ENABLED
DEFINE HSER_BAUD 9600 'SET BAUD RATE
'DEFINE ADCIN PARAMETERS
DEFINE ADC_BITS 10 'SET NUMBER OF BITS IN RESULT
DEFINE ADC_CLOCK 3 'SET CLOCK SOURCE (3=RC)
DEFINE ADC_SAMPLEUS 50 'SET SAMPLEING TIME IN uS

DEFINE LCD_DREG PORTB ' I/O port where LCD is connected
DEFINE LCD_DBIT 0 ' 0, 1, 2, 3
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 4 ' Register select pin
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 5 ' Enable pin
DEFINE LCD_BITS 4 ' 4-bit data bus
DEFINE LCD_LINES 2 ' LCD has 2 character lines

'************************************************* *****************************
' Comparator Config

CMCON = %00000111

'************************************************* *****************************
' Adc Config

ADCON0 = %11000001 'SET PORTA ANALOGUE AND RIGHT JUSTIFY THE RESULT
ADCON1 = %10001110

'************************************************* *****************************
' TMR1 Config : Preset = 45543 - Prescaler 1
'
T1CON = %00000000 'SETS THE TIMER1 VALUES - PRESCALER = 1

'************************************************* *****************************
' Interupts config

INTCON = %11000000 ' GIE + PIE
PIE1 = %00000001 ' TMR1IE
PIR1 = 0
PIE2 = 0
PIR2 = 0

'************************************************* *****************************
'Variables

wsave var byte $20 system ' just to avoid a compilator error ...
wsave1 var byte $a0 system
wsave2 var byte $120 system
wsave3 var byte $1a0 system

ssave var byte Bank0 system
psave var byte Bank0 system



POSITION VAR WORD 'POSITION OF SERVO1 1250 - 2500
TEMP var word
PLOW var word 'low part of the servo signal
COUNTER var word 'Timeout counter
PRESET var word

Delay var BYTE
RUN VAR BIT 'IS THE PROGRAM RUNNING


'************************************************* *****************************
'Aliases

GIE var INTCON.7
PEIE var INTCON.6
TMR1IE var PIE1.0
TMR1IF var PIR1.0
TMR1ON var T1CON.0

'************************************************* *****************************
' Variable presets


RUN = 0 'TEMPORARY VARIABLE FOR SERVO RUNNING
POSition = 150 ' Servo @ RestPositon.
counter = 0 ' timeout counter
PRESET = 25555
TMR1H = Preset.Highbyte ' Must be initialized ...
TMR1L = Preset.Lowbyte

'************************************************* *****************************
' Constants

SELECTOR CON 0 'Assign selector ADC Input to AN0

'************************************************* *****************************
' I/Os

SERVO1 var PORTC.0 'OUTPUT PIN FOR SERVO1
STARTSTOP VAR PORTA.4 'INPUT PIN FOR PUSHBUTTON

PORTA = %00010111
PORTB = 0
PORTC = 0
PORTD = 0
PORTE = 0

TRISA = %00000011
TRISB = 0
TRISC = 0
TRISD = 0
TRISE = 0

Pause 500
LCDOUT $FE, 1 ' Clear display, cursor off

'************************************************* *****************************
'************************************************* *****************************

MAINLOOP: ' Here we start a cycle ...

TMR1on = 0 ' Reload the timer ...
TMR1H = PRESET.Highbyte
TMR1L = PRESET.Lowbyte
TMR1IF = 0
TMR1ON = 1 ' Restart the timer
GIE = 1 ' Interrupts authorized

IF run THEN ' Run Button has to be pushed for first move

FINDPROGRAM: 'SELECTS BETWEEN SEVERAL TYPES OF MOTION

ADCIN Selector , TEMP 'READ CHANNEL 10 TO TEMP

SELECT CASE TEMP

Case is < 250
POSITION = 125

Case is <= 366
POSITION = 150

Case is <= 583
POSITION = 175

Case is <= 783
POSITION = 200

Case is <= 1000
POSITION = 225

Case is > 1000
POSITION = 250

End Select

low servo1
Pulsout Servo1, position

PLOW = 20000-POSITION


IF COUNTER.5 OR ! COUNTER THEN
'HSEROUT ["HIGH =" , DEC POSITION, " LOW =", DEC PLOW, 10,10,13]
LCDOUT $FE,2 ,"Position = ",dec position," ", $FE,$C0,"TEMP = ", dec TEMP," "
Endif
else


IF COUNTER.5 OR ! COUNTER THEN
'HSEROUT ["Waiting for RUN", 10,10,13,"HIGH =" , DEC POSITION, " LOW =", DEC PLOW, 10,10,13]
LCDOUT $FE,2 ,"Waiting for RUN", $FE,$C0,"Position = ", dec position
ENDIF
endif

'************************************************* *****************************
TESTINPUTS:

Delay = 0
Button Startstop,1,255,0,Delay,0,jump ' Button active LOW !!!

IF RUN THEN COUNTER = counter + 1
IF counter => 60000 then counter = 0 :goto jump

stop ' Stop here and wait for interrupt
' to launch a new cycle
JUMP:
WHILE STARTSTOP = 0 : wend
RUN = ~run
stop ' Stop here and wait for interrupt
' to launch a new cycle
END



enjoy ...

Alain