PDA

View Full Version : HC11 Pulse Accumulator


Mark Bresler
11-04-09, 10:23 PM
Hi,
I am having trouble using the pulse accumulator on my HC 11 Forth Board. Forth version 3.3 is being used if that makes a difference. I am trying to measure distance with Ultrasonic sensors. After the I/O pin is pulsed high, the sensor gives a high going pulse until the ultrasound signal returns. This takes about 20 milliseconds for objects 10 feet away.

I was able to implement the timer prescaler assembly code you supplied earlier, this is shown by:

B024 C@ . 3 OK

however I seem to get a pulse accumulator overflow at about 8 ms.

According to my Heathkit robot manual, sound takes 153.3 µs to travel 1 inch to an object and back. I am getting pulse accumulator overflows at about 55 inches which equals about 8.3 ms. From table 8-1 of the Motorola MC68HC11 manual, with B024 set at 3, I thought I would get 31.25 ms before overflow.

My code follows, MOR and MAND are Boolean operators on memory locations, these words have been used successfully in several projects.

2DISTANCE is the word I am having trouble with. Time to overflow is not correct, but I thought I could compensate by counting overflows however the overflow count is not correct. I have tried testing the pulse accumulator overflow bit both inside and outside the BEGIN UNTIL loop.

2EIGHTDISTANCE is a word to control a 4051 8 to 1 CMOS multiplexer allowing 8 sensors to be used.

I have stared at this problem for two days and think it is time for someone else to look at it.

Thanks in advance for your help,
Mark Bresler


: MOR ( TRS6, OR s mem loc with or filter )
( or address MOR )
DUP
ROT
SWAP
C@
OR
SWAP
C!
;

: MAND ( TRS6, AND s mem loc with and filter )
( and address MAND )
DUP
ROT
SWAP
C@
AND
SWAP
C!
;

: 2DISTANCE ( 2,8 AJR )
20 B025 C! ( Clear Pulse Accum Overflow Flag )
80 B000 MOR ( Set Port A7 for high output )
80 B026 MOR 80 B026 MOR 7F B026 MAND
( enable Port A7 output, do again, disable Port A7 )
63 B026 C! ( Set PACTL for pulse accumulator, gated time )
( 0 inhibits counting, keep real time int long )
0 B027 C! ( Clear pulse accumulator )

0 ( Initialize overflow counter )

BEGIN ( loop until output pulse finished )

B025 C@ 20 AND ( Check Overflow Flag )
IF
1+ ( Increment overflow counter )
20 B025 C! ( Clear Overflow Flag )
THEN

80 B000 C@ AND
0 =
UNTIL ( Wait until output pulse finished )
CR
." Print Overflow Flag Counter " .
." Echo finished " B027 C@ DUP . ( print output, leave on stack )
;

: 2EIGHTDISTANCE ( AJR5 )
( use # on stack to select sensor, leave distance on stack )
C7 B000 MAND ( clr multiplexer address )
8 * B000 MOR ( Shift # on stack, output multiplexer address )
2DISTANCE ( Leave distance on stack )
;

B025 C@ . D0 OK

ABOUT 54 " gives these readings:
6 2EIGHTDISTANCE
Print Overflow Flag Counter 0 Echo finished F4 OK
6 2EIGHTDISTANCE
Print Overflow Flag Counter 1 Echo finished F4 OK

ABOUT 59.5 " gives these readings:

6 2EIGHTDISTANCE
Print Overflow Flag Counter 1 Echo finished C OK
B025 C@ . F0 OK

RMDumse
11-05-09, 10:32 AM
Hi Mark, I haven't descended into the details of your code yet, but already have a question in my mind of why use the Pulse Accumulator? If I were measuring a pulse width on HC11, I'd probably use an input capture timer. The Pulse Accumulator counts incoming pulses and is only 8 bits. What is hooked to PA7, the Pulse Accumulator input? What is the Pulse Accumulator counting in your setup?

Mark Bresler
11-05-09, 05:22 PM
Hi Mark, I haven't descended into the details of your code yet, but already have a question in my mind of why use the Pulse Accumulator? If I were measuring a pulse width on HC11, I'd probably use an input capture timer. The Pulse Accumulator counts incoming pulses and is only 8 bits. What is hooked to PA7, the Pulse Accumulator input? What is the Pulse Accumulator counting in your setup?

PA7 is connected to the common pin of an eight input multiplexer. I used the Pulse accumulator because I thought that was the only method to measure pulse width. If there is another way I am open to suggestion.
Thanks,
Mark

RMDumse
11-05-09, 06:16 PM
So you have a multiplexer infront of PA7, so i would take it you intend to read 8 different sonars?

The Pulse Accumulator counts pulses coming into PA7, but not how long the pulse is coming into PA7, so it is probably not suitable for this use. I would imagine your count is always 1 (although perhaps you said in your original post).

The way I'd approach this problem is use one of the input capture pin. I'd capture the timer when the pulse fired. I'd use the input capture to find out when it ended, and I'd watch for overflows to see how many addition 65536 counts overflowed, and difference between start capture and end capture wouldn be the total time.

Mark Bresler
11-06-09, 09:23 AM
Hi,
The system is working well up to about 55”, after which it overflows. From the speed of sound, this is about 8 ms. The pulse accumulator is set for gated time accumulation, and gives about 4.5 counts per inch. The ultrasonic sensors work to about 120" which takes about 20 ms. I thought that loading 3 into location B024 would slow overflow to 31.25 ms, failing that, I attempted to increment a number on the stack when the overflow bit was set, clear the overflow bit and time another 8 ms. Then I would shift this number and add it to the pulse accumulator register. For some reason I was not able to read and reset the overflow bit properly.

Thanks for looking into this,
Mark

RMDumse
11-06-09, 07:21 PM
Sorry for being a little dull on this Mark. In all my years of HC11 use, I've never used the PA in this manner. Think I am beginning to understand the setup.

Here's a thought. The time it takes to go around the BEGIN UNTIL loop is not trivial. So let's say you you check the overflow flag, and it is set the moment after you then check to see if PA7 was low. It could be set and you exit the loop without seeing it as so. Could that be part of the problem?

Maybe you need to check for PA7 low first in the loop. (But then you would have to swap up the count, and before the until swap it back down and bring up the boolean for the until.) Or check one last time after the loop.

What do you think, is the count just off by being under by 1 in a certain range reading? Am I getting the point now?

Mark Bresler
11-06-09, 11:27 PM
Here's a thought. The time it takes to go around the BEGIN UNTIL loop is not trivial. So let's say you you check the overflow flag, and it is set the moment after you then check to see if PA7 was low. It could be set and you exit the loop without seeing it as so. Could that be part of the problem?

That might be part of it. I can check again whether being inside vs outside the BEGIN UNTIL loop matters.

Maybe you need to check for PA7 low first in the loop. (But then you would have to swap up the count, and before the until swap it back down and bring up the boolean for the until.) Or check one last time after the loop.

What do you think, is the count just off by being under by 1 in a certain range reading? Am I getting the point now?[/QUOTE]

The count wraps around past 55" such that 60" gives the same reading as 5". As I see it, either the count time needs to be extended to 20 ms. or I need to keep track of the number of overflows

Thanks,
Mark

RMDumse
11-07-09, 12:44 AM
Let me restate what I think is happening.

Let's say you are in that loop. You check overflow, you check PA7. Around and around. Now as you move your target back, let's say you hit the point where you check overflow and it isn't set. Now you check PA7 low and it is. But between the time you read overflow and now, it got set. You exit the loop with the overflow count low by 1. So 60" looks like 5", because the overflow flag was set, but not caught in the loop.

So a possible fix is to check one last time outside the loop to see if there was an overflow.

It is of course still necessary to check inside the loop as well, incase there are two or three overflows for even longer distance. But to handle the case where you get out of the loop with the overflow set but not checked, you check one final time before figuring your distance.

Mark Bresler
11-12-09, 02:52 PM
hi,
I have reread the Motorola book on the HC11. In gated time accumulator mode, the signal on PA7 enables an 8-bit counter driven by the E clock divided by 64. The E clock is the crystal frequency divided by four, with a 8 MHz crystal this causes an overflow in a little over 8 ms. This section is not affected by the Real time interrupt rate bits or the timer prescaler bits. Because I need to time up to 20 ms, the timer might overflow once or twice.

This is the latest version of my code, the outer BEGIN UNTIL loop tests for a low on PA7, while the inner BEGIN UNTIL loop tests for a low on PA7 or a pulse accumulator overflow which increments the overflow counter.

: 9DISTANCE ( 2,8 AJR )
F0 B025 C! ( Clear Pulse Accum Overflow Flag )
80 B000 MOR ( Set Port A7 for high output )
80 B026 MOR 80 B026 MOR 7F B026 MAND
( enable Port A7 output, do again, disable Port A7 )
63 B026 C! ( Set PACTL for pulse accumulator, gated time )
( 0 inhibits counting, keep real time int long )
0 ( Initialize overflow counter )
BEGIN 0 B027 C! ( Clear pulse accumulator )
BEGIN ( loop until output pulse finished )
80 B000 C@ AND 0 = 20 B025 C@ AND OR
UNTIL ( Wait until output pulse finished OR overflow)

B025 C@ 20 AND ( Check Overflow Flag )
IF 1+ ( Increment overflow counter )
F0 B025 C! ( Clear Overflow Flag )
THEN 80 B000 C@ AND 0 =
UNTIL ( Wait until output pulse finished )

CR ." Print Overflow Flag Counter " DUP .
CR ." Echo finished " B027 C@ . ( print output )
CR ." HEX Full Distance " 100 * B027 C@ + DUP .
( Shift overflow bits, add Pulse Accumulator)
4 * 11 / DECIMAL CR ." Decimal Full Distance " .
HEX
;

after the BEGIN UNTIL loops are finished, the readings are converted into distance in inches.

This gives accurate readings until overflow occurs. Around overflow an extra count sometimes occurs on the overflow. Readings just after the first overflow are a little low, but accuracy improves near the second overflow.

I am wondering whether I need some machine code to test for overflow and increment the counter rather than doing it in FORTH.

A little more background: I used the pulse accumulator because both PA2 and PA7 were available but PA7 could output a trigger pulse and then read the pulse, while the timer associated with PA2 could only read a pulse.

Thanks,
Mark

RMDumse
11-12-09, 03:41 PM
Yes, I had to reread the section myself to come to the same conclusion that it is the E clock divided by 64 that is count in the Pulse Accumulator. But here is the key as I see it. When the extermal pulse goes low, the Pulse Accumulator is frozen. The counting stops. The overflows then stop as well. So your count (including a pending overflow not yet caught) are captured, and you can take your time accounting for them (to a degree). Do you agree on this reading of the manual?

If so, you need to leisurely read the overflows in the inner loop, then read it one last time outside the loop, to correct for that "just happened, but not yet counted" overflow. I think that was the bit you were missing, so if in the loop you had seen the PA7 line go low, but at the same time the overflow happened, you'd miss it. You can still pick it up by checking the flag, as that will be held, and the count in the Pulse Accumulator is also held.

I think your previous code was closer to correct. By having two loops, i think you are zeroing the Pulse Accumulator in the outer loop when it may already be advancing a few counts, so range will be lost.

Here's how I'd suggest doing this:

: CHKOFVL
B025 C@ 20 AND ( Check Overflow Flag )
IF
1+ ( Increment overflow counter )
F0 B025 C! ( Clear Overflow Flag )
THEN
;

: 9DISTANCE ( 2,8 AJR )
F0 B025 C! ( Clear Pulse Accum Overflow Flag )
80 B000 MOR ( Set Port A7 for high output )
80 B026 MOR 80 B026 MOR 7F B026 MAND
( enable Port A7 output, do again, disable Port A7 )
63 B026 C! ( Set PACTL for pulse accumulator, gated time )
( 0 inhibits counting, keep real time int long )
0 ( Initialize overflow counter )
BEGIN
CHKOFVL
80 B000 C@ AND 0=
UNTIL ( Wait until output pulse finished)
CHKOFVL

HEX
CR ." Print Overflow Flag Counter " DUP .
CR ." Echo finished " B027 C@ . ( print output )
CR ." HEX Full Distance " 40 * B027 C@ + DUP .
( Shift overflow bits, add Pulse Accumulator)
4 11 */ DECIMAL CR ." Decimal Full Distance " .
;


Note I made a CHKOFVL word and called it both in the loop, and after the loop. I let the Pulse Accumulator free run all the way through.

Note I multiplied the overflow by 40 hex instead of 100 hex, because 64 counts per overflow.

I used */ instead of doing a separate * and /, because it keeps a 32 bit intermediate value, and is less likely to loose signigicance in large number instances.

I didn't think through the meaning of the scaling 4 & 11 , and leave that to you. Remember 11 hex would be 17 decimal.

Note I moved the HEX up before the print. Otherwise, when run, HEX is executed after the print, and there is no telling what the print itself actually comes out as. That HEX executes at run time, not when compiling. I take it something ahead set HEX or those B02x address wouldn't have compiled.

Well, I am not saying this is thorough, but it covers the points I saw.