PDA

View Full Version : Measuring pulse widths



Dangerous
- 11th June 2004, 12:43
Hi,

I have a 16F84A, and wish to count valid pulses.

The idea is this:

INTERRUPT ENABLE
ON INTERRUPT GOTO DO_INTERRUPT
Main Routine
----
----
----
Goto Main Routine

DO_INTERRUPT

Get the time since the last interrupt. If time is too short or too long, reset the counter.
If valid, add 1 to the number of pulses received.
If pulses received = 48, then I have received a valid signal.

RESUME


The problem is compounded by the fact that I have C code to do it, but want to use PICBasic. The C Code uses TMR0, TOIF and TOIF, but I can't find how to do this with PICBasic.

Please help.


Dave

Dangerous
- 12th June 2004, 11:46
Maybe I haven't asked the wrong questions.

1. How do I get the value of Timer0 on a 16F84A ?

2. How do I reset Timer0 on the same PIC.

3. How do I set the prescaler on this PIC.

4. How do I get more information on Prescalers.

Thanks in advance.

Melanie
- 12th June 2004, 13:31
The answer to all your questions is in the Datasheet for that PIC - make friends with it - and in the PBP manual...

You access the registers exactly the same way as you would in C. The Register names are used directly in PICBasic (see PBP manual section 4.10).

For example... (answering your Q1)...

The value of Timer0 is contained in Register TMR0. To read this register say into a variable you simply do...

MyVar=TMR0

to preset a value into Timer0 (answering your Q2), you do the opposite...

TMR0=MyVar

or (to preset a value say $F0)

TMR0=$F0

All the information you need on the prescaler (answering your Q3 and Q4) is in Datasheet section 2.3.2 - OPTION REGISTER.

Melanie

Dangerous
- 12th June 2004, 13:57
Melanie,

Excellent. Thank you very much. I am another grateful pupil.


Dave

Dangerous
- 13th June 2004, 12:10
I cannot get the following code to work:

It is supposed to flash a LED continuously, and when hit by a negative going pulse on RB0, go to an interrupt.

The interrupt checks if the pulse is within tolerance, and if so, increments a counter. 48 valid pulses equals a hit.

Once a hit is registered, the main code lights a different LED, and pauses for a short while.

If you can see what I am doing wrong, please let me know.

Here is the code:

' Set clock speed. Not required, but nice to have
DEFINE OSC 4

' Set Port directions
TRISB = %00000001 ' First pin is Input, the rest are Outputs

' WOW Defaults
WOW_Low_Time con 120 ' 4uS Units = 0.526 mS or 1900 Hz
WOW_High_Time con 147 ' 4uS Units = 0.588 mS or 1700 Hz
WOW_Pulses con 48 ' Number of successive pulses to count as a valid hit

True con %1
False con %0

HitPauseTime con 1 ' Number of seconds to wait when hit
RelayTime con 15 ' Time the relay is activated for (Seconds)
LivesRemaining var byte ' Number of lives remaining
DamagePerShot VAR Byte ' Amount of damage taken per hit
Hit Var bit ' If 'TRUE', indicates hit
Dead var bit ' If 'TRUE', indicates dead
ThisSensorType var byte ' Mode to run in
OverflowCount var word ' Number of times the timer has overflowed
NumberOfPulsesReceived var byte ' Number of valid pulses received
Timer0InterruptFlag var bit ' If 'TRUE', indicates greater than 1.02mS has passed since last pulse received
ElapsedTime var byte ' Time since last pulse received

HIT_LED var PORTB.2 ' First bit of Port B (ie pin 7, RB1)
TEAM_LED var PORTB.3 ' Second bit of Port B (ie pin 8, RB2)
Relay_Output VAR PORTB.4 ' Third bit of Port B (ie pin 9, RB3)

INTF VAR INTCON.1 ' Interrupt flag
T0IE var INTCON.4 ' Timer Interrupt enable
T0IF var INTCON.2 ' Timer Interrupt flag

' Available Sensor Types
Target con 1
Base con 2
Relay con 3

' Set the mode to run in
ThisSensorType = target

livesremaining = 100 ' 100 percent health
DamagePerShot = 10 ' Damage done per hit
Hit = false
Dead = false

INTCON = %00110000 ' Bit 7 - 1 GIE Enable all unmasked interrupts
' Bit 6 - 0 EEIE Disable the EE Write Complete interrupt
' Bit 5 - 1 T0IE Enable the TMR0 interrupt
' Bit 4 - 1 INTE Enable the RB0/INT external interrupt
' Bit 3 - 0 RBIE Disable the RB port change interrupt
' Bit 2 - x T0IF TMR0 register has overflowed (must be cleared in software)
' Bit 1 - x INTF The RB0/INT external interrupt occurred (must be cleared in software)
' Bit 0 - x RBIF At least one of the RB7:RB4 pins changed state (must be cleared in software)
OPTION_REG = %10000001 ' Bit 7 - 1 RBPU PORTB pull-ups are disabled
' Bit 6 - 0 INTEDG Interrupt on falling edge of RB0/INT pin
' Bit 5 - 0 T0CS Internal instruction cycle clock (CLKOUT)
' Bit 4 - 0 T0SE Increment on low-to-high transition on RA4/T0CKI pin
' Bit 3 - 0 PSA Prescaler is assigned to the Timer0 module
' Bit 2,1,0 PS2:PS0 Prescaler Rate Select bits (1:4)

On interrupt goto InterruptHandler

ENABLE Interrupt

while true
if hit = true then
hit = false
select case ThisSensorType
case target
high HIT_Led
pause HitPauseTime * 1000
low hit_led
case base
LivesRemaining = LivesRemaining - DamagePerShot
If LivesRemaining > 0 then
high HIT_Led
pause HitPauseTime * 1000
low HIT_Led
else
high HIT_Led
dead = true
ENDIF
case relay
high Relay_Output
pause RelayTime * 1000
low Relay_Output
end select
else
high TEAM_LED
high hit_led
pause 100
low TEAM_LED
low hit_led
pause 500
endif
wend

DISAble
InterruptHandler:
' Check time since last pulse
' Note here: timer0 is pre-scaled by 4, hence each count represents 4 usec
' Grab the current time (do it first to ensure greatest accuracy of pulse measurement)
ElapsedTime = TMR0

' Timer overflow interrupt
If T0IF = true then ' Timer 0 Overflow. More than 255 counts of 4uS have passed, ie 1.02mS
OverflowCount = OverflowCount + 1
T0IF = false ' Clear the overflow flag
NumberOfPulsesReceived = 0
endif

' IR input interrupt
if INTF = true then
intf = false ' Reset interrupt flag

if hit = true then ' Don't bother checking if already hit
resume
endif

if numberofpulsesreceived = 0 then ' First pulse, just reset timer
TMR0 = 0
OverflowCount = 0
NumberOfPulsesReceived = NumberOfPulsesReceived + 1
resume
endif

if (elapsedtime > wow_low_time) and (elapsedtime < wow_high_time) and (overflowcount = 0) then
numberofpulsesreceived = numberofpulsesreceived + 1

if numberofpulsesreceived > wow_pulses then
numberofpulsesreceived = 0
hit = true
else
TMR0 = 0
OverflowCount = 0
endif
else
' Out of tolerance. Reset the hit counter
numberofpulsesreceived = 0
endif
endif

resume
enable
end