200kHz +/- 5kHz pulse output?
Anybody-
I have tried to use cog counter modules but can not seem to get a 200kHz pulse train and then vary it slightly within a few kHz. I either get jitter or have to jump by a factor of 2 up or down in frequency. However, if I use waitcnt in PASM I can get the resolution I am after. This does require a whole cog with only a few lines of code so I a kind of waste the power of the propeller. I need many of these pulse trains for my application.
Is there a way to do this with the counter feature?
I have tried to use cog counter modules but can not seem to get a 200kHz pulse train and then vary it slightly within a few kHz. I either get jitter or have to jump by a factor of 2 up or down in frequency. However, if I use waitcnt in PASM I can get the resolution I am after. This does require a whole cog with only a few lines of code so I a kind of waste the power of the propeller. I need many of these pulse trains for my application.
Is there a way to do this with the counter feature?
DAT
'---------------------------
' Assembly language routines
'---------------------------
'assembly code pulses a pin rapidly without jitter
org 0
mycode or dira, pin0
mov time, cnt
add time, period
:loop xor outa, pin0
waitcnt time, period
jmp #:loop
pin0 long |< 0
period long 400
time res 1

Comments
If you really need many it makes sense let one COG do the job even if the code-size itself is by far not reaching 496 longs!
"vary it slightly within a few kHz" is to vague.
Also, how much jitter can you tolerate ?
If you take a 80MHz Clk and output 200KHz that is /400, jitter free.
Another jitter free output is at /401, 199501.246Hz, and /399 is 200501.253
Note these are 12.5ns more and less in period.
That 12.5ns is the edge-limit, and you can get an average frequency between these values, by effectively outputting a dithered set.
If you can accept a 10 cycle average, for example, you can define to 1.25ns apparent/average edge, but the absolute edges are always on 12.5ns time slots.
Set counterA to output 10MHz on pin 0
Set counterB to output 10.2MHz on pin 0 (note the same pin is used)
Take the output from pin 0 and run it into a RC filter. The output of the RC filter will be a 200KHz triangle wave going from 1/2 Vcc to Vcc.
The high frequencies can be adjusted by very small amounts. Giving very fine adjustment in the frequency of the output of the RC filter.
The output from the RC may need to be buffered depending on what you are driving.
Here is my PropBasic code:
Bean
-Phil
This technique is very versatile. There is a wide range of frequencies and mile Hz resolution.
Better yet the qitter is nearly non existent
Duane J.
The other nice thing about using both counters is that no code is needed for it to work.
I'd like to see the output on a spectrum analyzer if someone is able to do that.
Bean
Taking the 10MHz values, we have a divide by 8 for 10Mhz and divide by 7.84313725833936821 for ~ 10.2MHz
- ie 84.3% of the time, it divides by 8, and the other 100-84.3% it divides by 7.
The Egyptian fraction of this is
1/2 + 1/3 + 1/102 + 1/290917621
The 1/2 and 1/3 you can filter, but the 1/102 is ~ 98Khz so roughly every second cycle will differ.
It could be easily re-written to do 8 outputs at ~200kHz, and probably not too much work to make the values changeable on-the-fly.
The second test involved two counters
I would think that would be better.
Or maybe a double RC filter.
Bean
Filtering, unfortunately, will not remove jitter, since the jitter sidebands are so close to the fundamental.
-Phil
Here's the spectrum of 20.02 MHz mixed with 20 MHz:
The RC filter was 5.1K/1nF.
-Phil
Could you look in close to the 200KHz signal? Maybe +-1KHz or +-100Hz or tighter?
Duane J
Bean
If we take that ~200KHz example, that will divide by 400 most of the time, and then every (appx) 111849 cycles, it will divide by 401, so a fast gated counter will show 200.000KHz most of the time, and it may catch that 199501.246Hz, for the average result of 199999.99553Hz
This is why it is better to think in the time domain, than the frequency domain.
This notwithstanding, I do know that spectral filtering (low-pass, high-pass, band-pass) will not remove jitter. The only exception might be an extremely high-Q band-pass filter. Bit it would ring so much as to render any attempts at modulation futile. An external PLL is simple to set up and the best way to go.
-Phil
This code gets the job done but you can't use the cog for anything else. (Like I had big plans for it anyway.)
I think I can get 4-6 high frequency signals out of teh Propeller with around 1-2% resolution using 2-4 cogs for supervisory control/feedback functions
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 maxFreq = 36 minFreq = 200 period = minFreq - maxFreq VAR long parameter PUB main | myCog repeat repeat parameter from minFreq to maxFreq myCog := cognew(@myCode, @parameter) waitcnt(clkfreq / period + cnt) cogstop(myCog) repeat parameter from maxFreq to minFreq myCog := cognew(@myCode, @parameter) waitcnt(clkfreq / period + cnt) cogstop(myCog) DAT '--------------------------- ' Assembly language routines '--------------------------- org 0 mycode or dira, diraval rdlong pausePin, par mov time, cnt add time, pausePin :loop xor outa, diraval waitcnt time, PausePin jmp #:loop diraval long |< 0 pausePin res 1 time res 1Kaiser-Bessel windows perform well - if you can use K-B with alpha = 3.0 or higher it should give good results.
-Phil
The second trace is 100kHz, frqa:=10737418. Here again the sigma is at the limit of detection. Puzzling though, I'd expect to see an occasional bump to 10.025 microsecond but the scope shows 10.005µs as the maximum and 9.9999µs, pretty much the same spread as the perfect divisor. I should have let it run longer. There may be interaction with the 'scope triggering. This setting should have lots of cycles of length 400 through the phase accumulator before it make a cycle of length 401.
The last trace is close to 110614 Hz, frqa := 11877087. You can see it did pick up a more variance and a larger spread. I let it run longer, but that is not the cause. The jitter was evident by eyeballing the bouncing edge of the trace on screen. I chose that frequency specifically. The first quotient is (232/frqa =361), to set the base frequency, but the remainder after the division is 0.618 which is close to (sqrt(5)+1)/2. The consequence is that the continued fraction from then on out has lots of 1s, converges slowly, jitters, and has lots of additional subharmonics. I'll go out on a limb again as I have done before, and posit that a numerical oscillator is really, in fact, a way of representing a number in the form of a continued fraction. The 'scope statistics show the expected difference between high and low periods, around 25ns (1/40MHz). It jumps back and forth often in a long repeating pattern between its two periods--361 clocks, 9.025µs cycle and 362 clocks, 9.050µs.
I may have to re-evaluate my simplistic approach. What I am trying to do is set the harmonic frequency of an inverting power supply to a value around 2e+5 Hz. The exact resolution required is not known for the resonator circuits I have. It may be that these infrequent bumps do not impact the power flow at all. It is more important for me to find the harmonic resonance frequency (as indicated by phase shift in voltage) and then operate slightly above it.
The advantage gained with the counter module feature is desirable. We are trying to run several dozen circuits in parallel and each may be tuned slightly differently.
Thanks to those who have thought about this and taken some time to actually try stuff out.
regards...sm.
You may be too fast for their stats update? If they grab a set every 50us, they will average over 5 cycles and give 5ns not 25.
Does it have a high persistence mode ?
Yes, I use the Egyptian fractions, which are the same thing.
These dT bumps only occur in the counter/adder overflow and you could fit 8 channels in a single Prop.
A counter will give you one part in 400 step size @ 80MHz and one in 500 at 100MHz
In 'set and forget' it will have max edge variations of 12.5ns, so I'd try that first and see if it is a problem.
The quasi resonant power supplies are lowish Q, so are reasonably tolerant of frequency.
If this is also your primary regulation loop, frequency step size becomes more important.
That low Q also means they are less able to smooth over many cycles.
Hardware will always beat SW in precision, by an order of magnitude, & the timer will define to 12.5ns, give you x8/chip.
Just use a lot of chips... It's only $1/channel.
Edit: Oops, typo, there are of course 8 cogs, but 16 timers, per chip, makes it ~ 50c/chan.
The other solution for "several dozen circuits" would be a moderate sized CPLD ?
That would give ~twice+ the precision, and could have no jitter at all.
The circuit is a half bridge resonator. Also, Q varies depending on the load ... initially it is low but will cycle to low-high states. Thus, I need to have some control in the setup.
The Propeller USB board is actually a good choice for signal source and controller built into one both from a cost and development time standpoint. What other chips did you have in mind?
Phil Pilgrim has recommended a PLL chip but I was hoping to avoid any additional complexity
I have worked with National Instruments FPGA and they are beaucoup expensive.
Do you have any experience with this item:
[h=3]XC2C64A CoolRunner-II CPLD[/h]http://www.xilinx.com/support/documentation/data_sheets/ds311.pdf
$15 board from http://www.seeedstudio.com/depot/xc2c64a-coolrunnerii-cpld-development-board-p-800:7a53928fa4dd31e82c6ef826f341daec.html
It may be going up the learning curve once again to understand its use.
regards,
sm
Do you have any experience with this item:
XC2C64A CoolRunner-II CPLD
$15 board from http://www.seeedstudio.com/depot/xc2c64a-coolrunnerii-cpld-development-board-p-800:7a53928fa4dd31e82c6ef826f341daec.html
It may be going up the learning curve once again to understand its use.
[/QUOTE]
I'd suggest you skip that level, and go straight to LCMXO2-1200ZE-B-EVN ($29)\
http://www.latticesemi.com/products/developmenthardware/breakoutboardevalkits.cfm?source=topnav
The XC2C64 has too few macrocells, and has no RAM.
The MachXO2 is faster, and you could easily swallow 'several dozen circuits' (simple ones) in this.
If you imagine the simplest 10 bit counters and 10 bit /N that's 20 macrocells per circuit, so a XC2C64 manages just 3 - less than a prop.
If you want to expand to control both Freq and Duty cycle or Ton/Toff, (and I would allow for that) that's ~30MC/circuit. - so over 20 would fit in that board, via simple registers.
There maybe a way to control these from RAM, which would pack even more, but RAM tends to suit fixed playback.
I have not used LUT-RAM, but I think they would be well suited for the local stores, up to 16x4 RAM in 3 slices/6LUT. 3 x DPR16X4C would give 12b read width, 16 choices, and independent host writes.
Ton.Toff would be paired, so you could have 8 pairs, one pair could be a reset value, and one a working value, and you could have sets, if you wanted to change ALL frequencies at once.
(ripple write to B set, when running from A, then all switch on their next edge to new values.
and vice versa for next update )
My only beef with Lattice is they still do not offer smaller gull-wing packages than 100pins, and only one MLF32(coming).. Grr....
Given they can do a 2.5mm x 2.5mm BGA, the die must be tiny ...
It grabs samples from data that is on the screen display between the cursors. Triggering sync? I know the glitch is there, from theory, so finding it has to be a matter of using smart triggering modes or triggering from another prop pin.
The scope does have persistent mode. Here are traces from 10MHz and 10.2MHz using the parameters from Bean's post#5. The jitter at 10.2MHz is evident both in the persistent trace and in the sigma, which becomes a larger fraction of the cycle length at higher frequencies. There is the evident bobble between 7 and 8 trips through the phsa. The time cursors that bound the measurements are shown, the start cursor being just prior to the trigger point. Sorry about the overshoot--long ground lead to the quickstart board.
'':::::::[ Jitter-free Counters ]:::::::::::::::::::::::::::::::::::::::::::::: {{{ ┌───────────────────────────────────────┐ │ Jitter-free Counter Driver │ │(c) Copyright 2012 Bueno Systems, Inc. │ │ See end of file for terms of use. │ └───────────────────────────────────────┘ This program provides jitter-free counter outputs, two per cog, up to about 300 kHz (80 MHz clock). It uses the counters and works by forcing a phsx adjustment at each transition of the output, which results in a transition every n system clocks. The half periods for the high phase and low phase are independently adjustable, with a resolution of one system clock period. This permits limited duty cycle adjustment, so long as each half period is no longer than about 133 system clocks. }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 PIN0 = 0 'Assign pin numbers. PIN1 = 1 PIN2 = 2 PIN3 = 3 PIN4 = 4 PIN5 = 5 PIN6 = 6 PIN7 = 7 NCO = %000100000 'I field for NCO counter. PUB start | i repeat i from 0 to 6 step 2 'Start four cogs for eight counters. cognew(@clock, @periods[i]) repeat while periods[6] or periods[7] 'Wait for last cog to be ready. repeat i from 0 to 7 'Assign periods. periods[i] := (200 + i) * $1_0001 repeat DAT org 0 clock mov addrb,par 'Compute address of periodb add addrb,#4 rdlong ctra,par 'Read pin for ctra. mov maska,#1 'Convert to mask. shl maska,ctra mov frqa,#1 'Frequency is one. rdlong ctrb,addrb 'Read pin for ctrb. mov maskb,#1 'Convert to mask. shl maskb,ctrb mov frqb,#1 'Frequency is one. mov dira,maska 'Set pins to output. or dira,maskb mov acc,#0 'Signal that we're ready to go. wrlong acc,par wrlong acc,addrb waitlp rdlong perioda,par wz 'Wait for non-zero periods to be loaded. if_nz rdlong periodb,addrb wz if_z jmp #waitlp mov acc,phaseadj 'Initialize phases. sub acc,perioda mov phsa,acc mov acc,phaseadj sub acc,periodb mov phsb,acc movi ctra,#NCO 'Start counters. movi ctrb,#NCO mainlp mov inp,ina 'Read the pins. and inp,dira 'Mask out all but counter outputs. xor inp,prev 'XOR with previous pin reading. test inp,maska wz 'Has pina changed? if_z jmp #testb ' No: Try pinb. rdlong perioda,par ' Yes: Read latest periods for ctra. test prev,maska wz ' Was previous input a zero? if_z shr perioda,#16 ' Yes: Use high 16 bits of period. and perioda,_0xffff ' Mask off period for other half cycle. sub perioda,phaseadj ' Subtract the phase adjust constant. sub perioda,phsa ' Subtract the current phase. neg phsa,perioda ' Write adjusted phase to phsa. testb test inp,maskb wz 'Has pina changed? if_z jmp #fixprev ' No: Update previous state. rdlong periodb,addrb ' Yes: Read latest periods for ctrb. test prev,maskb wz ' Was previous input a zero? if_nz shr periodb,#16 ' Yes: Use high 16 bits of period. and periodb,_0xffff ' Mask off period for other half cycle. sub periodb,phaseadj ' Subtract the phase adjust constant. sub periodb,phsb ' Subtract the current phase. neg phsb,periodb ' Write adjusted phase to phsb. fixprev xor prev,inp 'Update previous pin state. jmp #mainlp 'Back for more. prev long 0 'Previous pin states. Always starts out as low:low _0xffff long $ffff 'Period mask. phaseadj long $8000_0000 + 6 'Phase adjustment added to phsa is $8000_0000 - period. acc res 1 'Scratch register. inp res 1 'Input anded with pin mask and XORed with previous input. maska res 1 'Mask for pina. maskb res 1 'Mask for pinb. addrb res 1 'Address of phaseb long in hub. perioda res 1 'Half period of ctra. periodb res 1 'Half period of ctrb. periods long PIN0, PIN1 'Initialized to pin numbers. Become periods when counters are ready. long PIN2, PIN3 'Low word is length of low half-period. High word is length of high half period. long PIN4, PIN5 'Half period length is value x system clock period. long PIN6, PIN7 ''=======[ License ]=========================================================== {{{ ┌──────────────────────────────────────────────────────────────────────────────────────┐ │ TERMS OF USE: MIT License │ ├──────────────────────────────────────────────────────────────────────────────────────┤ │Permission is hereby granted, free of charge, to any person obtaining a copy of this │ │software and associated documentation files (the "Software"), to deal in the Software │ │without restriction, including without limitation the rights to use, copy, modify, │ │merge, publish, distribute, sublicense, and/or sell copies of the Software, and to │ │permit persons to whom the Software is furnished to do so, subject to the following │ │conditions: │ │ │ │The above copyright notice and this permission notice shall be included in all copies │ │or substantial portions of the Software. │ │ │ │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, │ │INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A │ │PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT │ │HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF │ │CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE │ │OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ └──────────────────────────────────────────────────────────────────────────────────────┘ }}It's not a proper object yet, but it could be made into one fairly easily.
Enjoy!
-Phil
I took a look at the wiki for Egyptian fractions, and at Wolfram, but it doesn't seem to me they are the same thing. It seems like Egyptian fractions covers a class of fractions that are written as reciprocals of integers, (1/integer), and questions revolve around how they can be added up to make other fractions in general. For example, the fractions 1/2, 1/4, 1/8, 1/16 ... would be such a class that can be added up in a general way. For arbitrary rational numbers are sums possible using a minimum number of terms. Which comes to,
I see that those fractions add up to .8431372583393682, but how did you come up with those particular values? I agree that short cycles could be filtered and that those long cycles are out of reach of a practical filter or phase lock loop. It is the numerics that I question.
The continued fraction is a sequence of divisions and remainders. Here is the development for that case of10.2MHz with clkfreq=80MHz and frqa:=547608330.
You see it is quite different numbers, but similar conclusion. The complete cycle is 2^31 cycles long, and repeats twice for one trip through phsa, because 547608330 has a factor of two that divides out. In this analysis, the pattern consists of levels of cycles that are included within levels of longer cycles. At the short end there is the alternating pattern 7878787878 as seen on the 'scope. The continued fraction suggests there is one cycle ~400 clocks long that repeats 111847 times. That is a 200kHz subharmonic.