Searching \ for '[PIC]: [OT]: Funky Squarewave' in subject line. ()
Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/devices.htm?key=pic
Search entire site for: '[OT]: Funky Squarewave'.

Exact match. Not showing close matches.
'[PIC]: [OT]: Funky Squarewave'
2001\05\22@085824 by

Here is one for a challenge (it's challenging
me anyway!)...

I have a square wave waveform that is missing some
pulses, these pulses have been removed to correct
the average frequency. So imagine a 4kHz squarewave
(0v/5v), that has some pulses already removed to
make it an *average* 3kHz, or 3.7kHz etc.

The master freq can be from 10Hz to 4kHz. The pulses
removed can be up to 50% of the total pulses.
Normally the pulses removed are about 1 in 10.

Here's the challenge, how to, using a PIC at 4MHz,
even up the average space between the pulses...
Using very little processing time and up to high
speeds (4kHz).

In:
__-__-__-_____-__-_____-__-__-________-__-___

Out:
__-___-___-___-___-___-___-___-___-___-___-___

The processor knows if it is a valid pulse, or
a pulse that has been skipped. It can tolerate
a delay of a few pulses but less delay is better.

Any suggestions?? :o)
-Roman

--

How quickly can the 'average' pulse rate change?

Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)

{Original Message removed}
Man, you know how to dig a hole.  If you let the timer roll over at 256
(you could fool it, though) you get interrupts at 3900Hz.  It is clearly
a bit tough to resolve anything whatever out of that.

Let's assume unlimitted power and minimize afterwards.

Solution 1, write a main line (no interrupts) isosynchronous assembly
piece of code that does the job.  I will pass, I have plans for the next
few months.

Solution 2, write code on a faster processor and do the following. use
one of the processors with a capture feature.  Keep a simple table of
pulse to pulse periods in memory. Make it a FIFO. Study the values,
choosing the lowest time, or highest frequency. Seperately, run a
combination of timer0 and intB0. When intB0 comes, clear a timer. When
timer0 rolls, increment the timer.  Use a bit of code to decide that
your timer has exceeded the target value that you determined from your
table. When you think a pulse ought to appear, turn on the output bit.
Run another timer driven by timer0 that leaves it on for 2 or 3 periods,
whatever gives you a width that you like.  I suggest oring the output
with the original stream so that you can mix the old and the new.  And

Chris~

Roman Black wrote:
{Quote hidden}

--

Bob Ammerman wrote:
>
> How quickly can the 'average' pulse rate change?

The input freq can change as much as 50% in less
than a second. At higher speeds, it changes more
slowly. It's a motorcycle speedometer.
:o)
-Roman

>
> Bob Ammerman
> RAm Systems
> (contract development of high performance, high function, low-level
> software)
>
> {Original Message removed}
Chris Eddy wrote:
>
> Man, you know how to dig a hole.  If you let the timer roll over at 256
> (you could fool it, though) you get interrupts at 3900Hz.  It is clearly
> a bit tough to resolve anything whatever out of that.

Umm, sorry I didn't mention no interrupts, clock
speed 4MHz (1us/inst) and no capture ports etc.
This is bare bones... I am pretty good at faking
timer interrupts by polling TIMER0 though.

>
> Let's assume unlimitted power and minimize afterwards.
>
> Solution 1, write a main line (no interrupts) isosynchronous assembly
> piece of code that does the job.  I will pass, I have plans for the next
> few months.

I wish I knew what that meant! :o)

> Solution 2, write code on a faster processor and do the following. use
> one of the processors with a capture feature.

Whoops, no can do. No capture port. Only TIMER0.
No interrupts, only 2 level stack, 24 registers etc.

{Quote hidden}

Ok, some of that sounds good. I know when the pulses
occur, so you are suggesting storing the last few (rough)
periods in a ram table, then using that to give a pulse
length for the current pulse??

It gets difficult keeping track of both the incoming
and outgoing pulse periods as I only have one timer,
no ints and the period changes from 100,000 counts
to 250 counts total, that has to be 3 bytes...

I was thinking of maybe generating lots of pulses
for each incoming pulse, then averaging these.
Maybe this could be done without ANY period
measuring? It's a tricky one. :o)

------------------------------------------
{Quote hidden}

--

> Chris Eddy wrote:
> >
> > Solution 1, write a main line (no interrupts) isosynchronous assembly
> > piece of code that does the job.  I will pass, I have plans for the next
> > few months.
>
Weeell, it is not very often one has to work under these circumstances.
In stricly assembly, then, let's try this.

One main loop code piece must do all tasks.  All paths of the code must
be carefully balanced out to execute in the same number of clock cycles,
to make time somewhat predictable. If possible, use TMR0 as a capture
clock, and be prepared to keep track of rollover.  This is done by
polling the input and TMR0. So now make that table of values. Put your
captured data into it FIFO style. Take the lowest table value as your
primary frequency.  You should only need 4 values in the table. If the
currently captured TMR0 time exceeds this value, you must trigger the
output.  Or the result and the original as mentioned above. If you run
into trouble with TMR0, specifically in terms of overal time scale
fitting your target speeds, then simply count main loop passes as your
base clock.  This is why you must balance clocks out and be accurate
regardless of program path flow.

One big trick that everyone should try is to do this. Write code that
tries to identify the edges of a target signal.  Toggle or repeat the
target signal back out another pin.  Put the results on your scope. You
can see amazing amounts of details when you compare the original and
your software generated trigger points. Dleays, latency, and missing
triggers are what you are looking for.  PS, this is how you uncover
silicon flaws. (A dig at Atmel).

Cancel the remainder of your life for a while.  Draw out whatever you
can to plan the software.  Experiment at times to determine what is
possible, then keep flowcharting. Now write the full program, balance
timing every time you make a change, and oh, good luck!

Chris~

--

I might consider the following:
Set timer for min period required to define placement of output pulse
(say 25 us, one pulse is about 5 timer periods wide)

Poll input pulses and timer
Count number of input pulses (N) in 1000 timer periods (25ms)
(N should be 0 to 100 or 101)
Compute number of timer periods between output pulses
(1000/N)  of course if N=0, no pulses in this interval

LOOP
Poll input pulses
Poll timer
output pulse (5 timer periods wide) each 1000/N periods
END LOOP

Either maintain running average of input pulses and update on each timer
or probably just restart count each 1024 timer periods and update
speedometer 40 times per second.

David W. Gulley
Destiny Designs

Roman Black wrote:
{Quote hidden}

--

I don't think this is as hard as it sounds. Basically you have to generate
the correct number of edges per second.

1: Determine time between consecutive edges.

2: Low-pass filter the delta-T values.

3: Generate outgoing edges spaced at the output of the delta-T.

The rest is just a SMOP (small matter of programming) :-)

Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)

--

----- Original Message -----
From: "Bob Ammerman" <RAMMERMANPRODIGY.NET>
To: <PICLISTMITVMA.MIT.EDU>
Sent: Tuesday, May 22, 2001 2:24 PM
Subject: Re: [PIC]: [OT]: Funky Squarewave

> I don't think this is as hard as it sounds. Basically you have to generate
> the correct number of edges per second.
>
> 1: Determine time between consecutive edges.
>
> 2: Low-pass filter the delta-T values.
>
> 3: Generate outgoing edges spaced at the output of the delta-T.

Er, that should be:

"3: Generate outgoing edges spaced at the output of the delta-T _filter_".

{Quote hidden}

--

> The input freq can change as much as 50% in less
> than a second. At higher speeds, it changes more
> slowly. It's a motorcycle speedometer.

So why do you need to drop some pulses from the speedometer pulse train?

********************************************************************
Olin Lathrop, embedded systems consultant in Littleton Massachusetts
(978) 742-9014, olinembedinc.com, http://www.embedinc.com

--

Olin Lathrop wrote:
>
> > The input freq can change as much as 50% in less
> > than a second. At higher speeds, it changes more
> > slowly. It's a motorcycle speedometer.
>
> So why do you need to drop some pulses from the speedometer pulse train?

Because this is the best way to correct a frequency
by X percent without having to do any period measurement
or period generation. :o)
-Roman

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

Bob Ammerman wrote:
>
> I don't think this is as hard as it sounds. Basically you have to generate
> the correct number of edges per second.
>
> 1: Determine time between consecutive edges.
>
> 2: Low-pass filter the delta-T values.
>
> 3: Generate outgoing edges spaced at the output of the delta-T.
>
> The rest is just a SMOP (small matter of programming) :-)

Thanks Bob and the other guys who offered suggestions!
Obviously one way of doing this is to measure the input
average period or frequency, then re-generate the output
frequency. This is exactly how our curent product works.
It also requires a faster processor (<12MHz) and some
nifty TIMER0 int handling to maintain good period
measuring/generating ability.

What I was really after is a QUIRKY clever way of
"smoothing" the pulse train to make it more regular
without having to constantly make accurate period
measurements, or generate accurate output periods.

Here is an example:
Input (with missing pulses):
__-____-_________-____-____-_________-____-____

Output:
__-____-______~_______-____-______~_______-____

Ok, we have detected the missing pulse, which the
processor always knows, so all we do is delay
1/2 a pulse after the missing one, then generate a
"fake" pulse there. Then ignore the following pulse.
To do this we only need a very rough period for
a normal pulse, and then to halve it and make a very
rough delay. This has smoothed the signal a lot
with minimal period measuring or generation.
This is not quite good enough, but might be a step
in the right direction?

Like the "quirky" way of making PWM with a random
number, that sort of thing, some way of avoiding
the whole "measure period/regenerate period" stuff.
:o)
-Roman

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

Roman,

So some process is dropping M out of every N pulses?

Sounds like another place to use Bresenham.

Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)

{Original Message removed}
Bob Ammerman wrote:
>
> Roman,
>
> So some process is dropping M out of every N pulses?
>
> Sounds like another place to use Bresenham.

Ha ha! How do you think I'm getting accurate
freq corrections without doing any period measuring
stuff?? ;o)

Now I just need the "quirky" way of smoothing
the pulses and it's all over. Unfortunately most
speedos will "jump" if the pulse train misses
pulses.:o)
-Roman

> {Original Message removed}
Roman,

Do you have two different processors here? One doing the bresenham, and now
you want to do this pulse shifting thing?

Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)

{Original Message removed}
Bob Ammerman wrote:
>
> Roman,
>
> Do you have two different processors here? One doing the bresenham, and now
> you want to do this pulse shifting thing?

Hi Bob, no the input pulse train is fairly regular,
it only takes me a few insts for my modified
bresenham to drop pulses and track the average,
now I need to get the same processor to "smooth"
the output pulse train until it is acceptable.
Hopefully with minimal period measuring/generate
stuff.

This is an example:
Input (with missing pulses):
__-____-_________-____-____-_________-____-____

Output:
__-____-______~_______-____-______~_______-____

Ok, we have detected the missing pulse, which the
processor always knows, so all we do is delay
1/2 a pulse after the missing one, then generate a
"fake" pulse there. Then ignore the following pulse.
To do this we only need a very rough period for
a normal pulse, and then to halve it and make a very
rough delay. This has smoothed the signal a lot
with minimal period measuring or generation.
This is not quite good enough, but might be a step
in the right direction?

Like the "quirky" way of making PWM with a random
number, that sort of thing, some way of avoiding
the whole "measure period/regenerate period" stuff.

Maybe something like that??
:o)
-Roman

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

Ok,

The reason I asked is that perhaps there is a better way of doing the
smoothing than first bresenhamming and then trying to smooth it.

Imaging the following hardware solution:

1: build a PLL that locks to the incoming pulse train and multiplies the
frequency by N.

2: run the xN signal thru a rate multiplier to get the desired frequency.

Now, look at the software equivalent:

1: do some sort of a software PLL to multiply the rate of the incoming pulse
train by N.

2: run the the xN signal thru a bresenhammer to get the desired frequency.

Note that the bresenhamming of the xN signal gives us two advantages:

A: Much smoother spacing of the pulses (by a factor of N, I think).

B: The ability to scale the output not only down but also up relative to the
original input stream.

Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)

{Original Message removed}
On Wed, 23 May 2001, Roman Black wrote:

{Quote hidden}

I like Bob's PLL suggestion. But consider this twist: Assume that in a string of
8 pulses that there's at least two that are adjacent to another; i.e. no dropped
pulse. If you save the last 8 pulses in a circular array (or more precisely the
time between the rising edges of two consecutive pulses) and then  sort this
array you'd have the time for the minimal pulse separation.

This minimal separation can then be filtered to generate the pulse separation
for the out going wave. Then a simple phase accumulator can use this separation
to generate the out going pulses. One problem with this approach is that the
incoming and outgoing signals are not phase locked. But there is a simple trick
to fix that. Every time a rising edge is detected on the input, drive the output
high (i.e. pass the pulse through) and start a timer that is proportional to the
expected pulse separation. If the timer times out before the input pulse comes,
then assume that a pulse is being skipped. If the input pulse comes a little
later than expected (but is not skipped), then the output pulse is extended. If
the input pulse comes quite a bit later, but not quite two pulse times then you
can skip the output pulse to avoid a glitch knowing that you'll phase lock again
in a pulse or two.

Here's a median filter that places data into a circular buffer and sorts it:

http://www.dattalo.com/technical/software/pic/medfilt.html

Since this is part of a median filter the middle of the sorted data instead of
the minimum is of interest. But it might give you (or some one else) some ideas.

Scott

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

If I understand correctly you have an input pulse train from some
kind of sensor and an output pulse train, and you wish to scale
the output frequency to be some percentage of the input freqency to
drive a motorbike tacho of some sort.

Question. Is this just for display, or is it a control system.

If its just for display, and you are using a midrange pic with
timers etc, why not just set up a timer to generate the output
frequency. Then just increment or decrement the timer preset
according to the number of input pulses counted.

Now, count the number of input pulses, call that PulseCountIn
each timer interrupt count the output pulses, call that PulseCountOut.

Suppose you wanted the output frequency to be 83% of the input freq.
when the PulseCountIn gets to 100, compare the PulseCountOut to 83
if too many pulses, then increment the timer preset value. Otherwise
decrement the timer preset value.

Obviously this will track input changes, but probably lag a bit
depending on the actual numbers and the gate time. Also you could
make the amount to increment/decrement proportional to the count
error to track a bit faster.

I realize that a faster cpu could do an exact version of this and
be more precise, but this should work at relatively low clock rates
and leaves cpu time to do other things.

4 Khz, would give 100 counts in 25 ms.

Again, if this is a control system, then the reaction time of the
above approach might well screw the control. There is a line in the
film blade runner, "reaction time is important, so pay attention"

Ray Gardiner raydsp.com.au
[ 2001 ]

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

Dear PICers,

Combining Ray Gardiner's ideas with Bob Ammerman's clever ideas, we have a
frequency-locked-loop (FLL).

Basic idea: Count both input pulses and output pulses. Try to force both to be
equal.

[tangential rambling]
I've been told there used to be a guy at electric power stations who watched 2
clocks.
The "reference" clock always told the exact time ( traceable to the National
Bureau of Standards, which has since been renamed NIST).
The other was a simple, cheap electric clock running off the power lines from
his station. It would run fast or slow when the power grid ran above or below
the precisely 60 Hz.
The guy would tweak the generators at his plant to try to get both clocks to
read the same time (more or less).
[/tangential rambling]

* Output pulse generator, generate a pulse every P (variable period) cycles.
* Input pulse counter: every input pulse, add Ki (constant) to a 24 bit error
counter.
* Output pulse counter: every output pulse, subtract Ko (constant) from that 24
bit error counter.
* Hope the counter doesn't overflow :-).

Then periodically tweak P:
* When error counter is negative (too many output pulses), make P bigger (slow
down output frequency).
* When error counter is positive (too many input pulses), make P shorter (speed
up output frequency).

You can have some complicated PID method of adjusting P if you want. Or do
something simple like increment/decrement P once every 8 input pulses.

This forces the output frequency (at steady state) to converge on
output frequency = Ki/Ko * input frequency.
.

* no need to measure periods with any kind of accuracy. Just count pulses.
* Jitter in input pulses is completely ignored.
* If the output frequency uses a hardware timer, it has very low jitter, and can
change frequency very smoothly.
* Initial output frequency when you first turn it on might be *way* off.
* After a step change in input frequency, might take a long time to settle.
* After a step change in input frequency, might cause output frequency to
overshoot, maybe even oscillate, if the "tweak P" code isn't properly tuned.

If you *know* a step change in input frequency just occurred, you might be able
jump immediately to almost exactly the correct output frequency by directly
forcing period P to the (estimated) new frequency. Then let it slowly converge.

--
David Cary

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

Since you say they are missing to average out the frequency, you know over
how long a period they are averaged. Therefore have the PIC output pulses
at a quick estimate of that speed for the current period of averaging, and
when the period will have passed you will have the exact value, and adjust
the output accordingly. I don't know of any 'faster' way to do this once
the 'averaging period'. Borrowing pulses from the previous averaging
period to estimate the next is not so good imho (since you can't tell when
they are coming this can lead to jitter in the output).

It would be much more usefull if the input pulses would come 'bunched' at
the end or the beginning of an 'averaging period'.

Peter

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics

Thanks everyone for the great ideas. Especially Bob
Ammerman, David Cary and Peter L. Peres.

I think I may have found a solution going with one of
my first ideas which Bob also mentioned, in theory:

* regular input pulses
* measure input period (rough)
* generate 4 or 8 pulses per input pulse (rough)
* do the pulse subtract (bresenham) on the fast pulses
* divide by 4 or 8 and make output pulses.

I think this is the best yet, as calcs are almost
non-existant. The input period can be measured manually
using TIMER0, as can the high speed pulses, x8 and /8
are very quick calcs compared to most math, there
is basically zero lag (less than 1 input pulse lag)
and per-pulse changes of many % can be tolerated but
should settle quickly when the input pulse freq
steadies. It also easily maintains a zero freq error

But David's suggestion of a free-generated freq
output with a error variable constantly tuning it
is intruiging, and I will check out some systems
based on this over the next few days.

Most of this stuff is fairly easy with fast PICs
that have peripherals, but with a lowly 4MHz 505
and considering MOST of my rom is ratio tables
this gets challenging! Thanks again!
:o)
-Roman

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

Roman Black wrote:
<SNIP>
> * regular input pulses
> * measure input period (rough)
> * generate 4 or 8 pulses per input pulse (rough)
> * do the pulse subtract (bresenham) on the fast pulses
> * divide by 4 or 8 and make output pulses.
>
> I think this is the best yet, as calcs are almost
> non-existant. The input period can be measured manually
> using TIMER0, as can the high speed pulses, x8 and /8
> are very quick calcs compared to most math, there
> is basically zero lag (less than 1 input pulse lag)
> and per-pulse changes of many % can be tolerated but
> should settle quickly when the input pulse freq
> steadies. It also easily maintains a zero freq error
>
<SNIP>

I may be missing some detail.  You have not indicated over what range
these pulses may be missing (is the condition of NO pulses valid?).
Also is 4Khz the 0 or is it the Max (since this is a speedometer
application)?

It seems (to me) that the easy way is:

Timer_Count = xxx          ; set to value to use for timer 'tic'
N = yyy                    ; Set for number of input pulses to average
tics_per_high = zzz        ; Number of tics in output pulse high time
input_tic_count = 0        ; tics since last input pulse
output_tic_count = 0       ; tics since last output pulse
last_input = 0             ; Last value read from input stream
Clear Timer                ; Reset the timer to 0

tics_per_one = nnn         ; Initialize the tics per output period
;  (set to some valid starting value)
tics_per_high = hhh        ; Number of tics in output pulse high time
tics_per_low  = nnn-hhh    ; Number of tics in output pulse low time

Main_Loop
call check_timer
call check_input
call do_output
goto Main_Loop

check_timer
if timer >= Timer_Count               ; See if a 'tic' has occurred
input_tic_count += 1               ; increment count since input
output_tic_count += 1              ;  same for output
end if
return

check_input
read input                              ; check the state of the input
if input = 1 and last_input = 0         ; detect rising edge of input
tics_per_one = input_tic_count/N    ; use shift if N is power of 2
input_tic_count -= tics_per_one     ; subtract 1/N of the counts
end if
last_input = input                      ; for use on next check_input
return

do_output
if output = 0
if output_tic_count <= tics_per_low    ; ready to go high?
output_tic_count = 0
set output = 1
end if
else
if output_tic_count <= tics_per_high   ; ready to go low?
output_tic_count = 0
set output = 0
end if
end if
return

I did this hurriedly, so may have missed something, but there are
minimal calculations, the output reflects the input over the last N+
cycles (some delay is added using the box filter), if N is a power of
two, the divide becomes a right shift.

Anyway,
Good Luck
David W. Gulley
Destiny Designs

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

----- Original Message -----
From: "Roman Black" <fastvidEZY.NET.AU>
To: <PICLISTMITVMA.MIT.EDU>
Sent: Thursday, May 24, 2001 5:54 AM
Subject: Re: [PIC]: [OT]: Funky Squarewave

{Quote hidden}

Roman,

You can combine the last two of these by just changing your Bresenham ratio.

Bob Ammerman
RAm Systems
(contract development of high performance, high function, low-level
software)

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

Hi David, thanks for the help, but what looks
good and simple in psuedo C becomes tricky when
you only have one timer, no timer overflow flag,
no interupts and need to work with a input pulse
train of only 125 instructions between edge changes.

This pretty much rules out all the obvious solutions
of timing inputs and outputs using ticks or any
other timer solution.

A appreciate your help and the time you spent typing
in the helpful solution but I think I've got it
handled now with the best solution possible given all
the hardware limitations. Zero-error, zero-lag ratio
systems over a huge range are pretty tricky to do
with very little PIC.

Thanks again, and thanks to the others who helped!
:o)
-Roman

David W. Gulley wrote:
{Quote hidden}

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

More... (looser matching)
- Last day of these posts
- In 2001 , 2002 only
- Today
- New search...