Frequency generator

Thread Starter

cmartinez

Joined Jan 17, 2007
8,783
Frequency is the inverse of period, so I don't see a drastic change in programming complexity. One way to shortcut things is with a lookup table. It's only 65,000 entries to type in; how hard can it be?

ak
The minimum number of cycles per half square wave that I need (working with a 14.7456 MHz oscillator) is 123, to obtain the 60 kHz that I want for maximum frequency. The maximum number of cycles is 377,303. That requires the use of a three-byte number. Since I'm trying to work with 2^11 divisions (2,048), the dividend requires the use of two bytes. The code I wrote, which is based on the long binary division algorithm, requires close to two thousand cycles to divide a three-byte number by a two-byte one. This is simply not practical.

And as for a look up table, I have already considered that. Thing is that the total memory available in the device I'm trying to use is 4kB, and that is short of the 6kB needed for a three-byte look up table for this task. I cannot think of a way to make the table any smaller, other than compressing it to two bytes, and then adding the third byte as an exception in the algorithm for very low frequencies.

I am, however, working on a non-continuous function that looks promising, that might give me a close approximation the linear output frequency that I want.
 

AnalogKid

Joined Aug 1, 2013
12,158
The minimum number of cycles per half square wave that I need (working with a 14.7456 MHz oscillator) is 123, to obtain the 60 kHz that I want for maximum frequency. The maximum number of cycles is 377,303. That requires the use of a three-byte number. Since I'm trying to work with 2^11 divisions (2,048), the dividend requires the use of two bytes. The code I wrote, which is based on the long binary division algorithm, requires close to two thousand cycles to divide a three-byte number by a two-byte one. This is simply not practical.
But - you go through all of that only when the frequency changes. There is nothing in post #1 about a sweep generator. Is that what you are going for?

ak
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,783
There is nothing in post #1 about a sweep generator. Is that what you are going for?
I'm not familiar with the term.

What I'd like is to be able to change frequencies instantly. Say, perform the calculations while the low side of the wave is active, and then change the wave's period accordingly in the next execution.
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,783
So, an arbitrary wave generator?
Arbitrary in the sense of any frequency. But always square waves of 0-5VDC. 50% duty cycle is not a must, it could vary between 25% and 75% if that helps to simplify things.

And yes, BR, preferably integer numbers. Although that is "negotiable"
 

dendad

Joined Feb 20, 2016
4,641

AnalogKid

Joined Aug 1, 2013
12,158
The 8038 was great for what it was, but at its heart it is an R-C oscillator not too different from a 555, and not nearly precise or stable enough to produce a 1-of-65,000 frequency based on an external signal.

ak
 

atferrari

Joined Jan 6, 2004
5,015
That's why I'm eagerly waiting for Agustín to clarify his comment about using two mcu's for this task. I'd really like to know how he did it.
I created a dual generator thus the 2 micros. They are 2 function generators driven by a common xtal, ensuring that both signals keep a stable phase difference between them. They are the evolution of code published by Tom Napier (seems it disappeared from the Web) implementing an NCO generator. Problem is that frequencies are fixed in the firmware.

Sure, one alone will create one output still with preprogrammed fixed frequencies. LUT at work.

My lab's PC is down so I have to dig in my backup to see if I can retrieve the code.
 

SgtWookie

Joined Jul 17, 2007
22,230
I bought a very similar kit a few years back; all the AMT parts were installed. Works great. I didn't check the output very well, but for what it does vs what it cost, it was difficult to beat.
In my basement I have 100% of everything needed to grow a circuit for this application from scratch. But not for $16 and not with a display and not in 2 hours. That kit is completely sick.

ak
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,783
I finally did it. Due to the very limited resources that I had (both material and "analogically intellectual"), I was forced to do it the only way I knew how, and that was through programming.

What I did is I generated a lookup table of bytes ordered sequentially representing the amount of cycles that an AT89LP4052 MCU had to wait before changing the state of the frequency output pin. The lowest frequencies could only be represented by a three-byte number. And since my goal was to produce 2^11 - 1 (2,047) different frequencies, a lookup table with 2,047 entries of three bytes each would've taken about 6 KB, which is considerably larger than the 4KB capacity of my MCU of choice.
But after playing with the numbers in an Excel sheet, I found out that only the first 6 frequencies in the table are need to use the three bytes. That is, the number of cycles in those 6 first frequencies are all larger than FFFFH. But from the 6th frequency step to entry number 882 the frequencies can be represented by two byte numbers, and only one byte is needed from entry 883 to entry 2,047.

That allowed me to create a look up table with just 2,935 bytes. And after that I wrote an algorithm that would locate the byte array needed to generate the desired frequency depending if 3, 2 or just one byte is needed. In the case of two bytes, the third (most significant) byte is always set as zero, and if only one byte is needed then both the MSB and middle byte are also set as zero.

In the end, the whole program size ended up being 3,406 bytes, which fits perfectly in my 4KB MCU's

Creating that Excel sheet was essential to the project, since it also allowed me to experiment with different oscillator frequencies, and output frequency ranges. Plus I created a small formula that outputs the code needed to represent that table exactly as assembly would interpret it.

Here's a screen cap of said worksheet.

upload_2017-5-14_21-49-34.png

My thanks to everyone who took the time to help me out in this thread.
 

frpr666

Joined Feb 2, 2010
53
Hi ,
I can see in the speadsheet that the frequencies do not have to be precise integer number.
It is similar to the baudrate generator example from DS where you didn't get exact speed for UART like 19200 bps but the speed close enough to the desired speed.
Maybe you can further simplify the nonlinear function by piecewise linear function.
like:
if(x<x1)
{
y=a1*x-b1;
}
...
else
{
y=a2*x-b2;
}
// where a1,a2,b1,b2,x1,... are constants.
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,783
Hi ,
I can see in the speadsheet that the frequencies do not have to be precise integer number.
It is similar to the baudrate generator example from DS where you didn't get exact speed for UART like 19200 bps but the speed close enough to the desired speed.
Maybe you can further simplify the nonlinear function by piecewise linear function.
like:
if(x<x1)
{
y=a1*x-b1;
}
...
else
{
y=a2*x-b2;
}
// where a1,a2,b1,b2,x1,... are constants.
No, they don't have to be. But they do have to follow a linear function. Your calculations are correct, except that they take way too many cycles and would only work for very low frequencies.
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,783
Back to this thread, this time trying to improve on what I've already developed.

I'm still convinced that the fastest and simplest way of doing this is through a lookup table. Calculating the delay time needed to generate a square wave of a desired frequency involves a long division routine that I'd rather not implement in my program. This because the routine would take far too long, and my goal is to obtain an instantaneous change in frequency when desired. That is, the next square wave segment of a different frequency must be executed immediately after the previous one without a glitch, regardless of the desired change.

What I've decided now is to implement a simple serial protocol to the frequency-generating MCU, instead of the current parallel one. That is, at this moment I'm requesting the desired frequency by inputing a binary value at 11 of the pins of the MCU, which is then immediately referenced to an internal lookup table and the desired frequency is then output at another pin. The remaining pins of the MCU are used for other purposes that I'd rather not discuss here.

So what I'm about to do now, is change the way things are working at this point. I'm going to use one pin to signal a reset of the MCU, effectively setting the desired output frequency to zero, another pin to increment/decrement the desired output frequency in integer steps, and a pin that will read if the next frequency step will be incremented or decremented. This way I'll no longer be limited to an 11-bit number of frequency steps, but rather by the amount of memory available in the MCU to store the lookup table. The disadvantage to this arrangement is that in order to reach a certain frequency, all of the previous frequencies must be executed first. But that's ok, because this application is intended for motion control, and abruptly jumping from a low to a high frequency is not only not needed, but also undesirable.

So my question here is, is there a fast, simple-to-program MCU out there that I could use for this purpose? I'm currently using a single-cycle 8051 MCU that's very fast and reliable, but it works at 22 MHz tops. And I'd like an MCU with similar single-cycle characteristics, if possible, but running at least at 150 to 200 MHz. Or what about PGAs? Would it be possible to build something like this using PGA's instead?
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,783
I've finally built and tested my MCU-based frequency generator, and it's working beautifully. It's capable of cleanly and accurately generating 5V square waves from 10.54 Hz to 50.04 Khz in increments of 24.43 Hz. And it does it without a glitch when transitioning from one frequency to another because all of the lookup table operations and calculations take place during the high part of the square wave, without affecting the wave's period. That's not too shabby for motion control :)

Also, I've noticed that a better algorithm can be implemented if the lookup table were arranged in a certain way. But that would take more memory. Right now I'm using an 89LP4052 (8051 architecture) MCU running at 22.1184 MHz with 4 KB available program memory. If I were to use an AT89LP51ED2 with 64KB, I'm sure my system could accomplish a frequency as high as 65 KHz, and as low as 1 Hz, with a two-fold improvement in resolution.... and I already have a couple of those chips with me... but my stupid mikroProg programmer from Mikroelectronica does not support it, even though in their website it says that the device supports "8-bit Atmel AT89 (8051) microcontrollers" ... I've already contacted them regarding this issue, and they answered that they have no plans of supporting that chip in the near future :mad: ...

One of the few devices I've found capable of programming the AT89LP51ED2 costs almost $600 dlls ... and with another brand it can go over $1,900.00 dlls! :eek:
 

philba

Joined Aug 17, 2017
959
I'm a bit late to this whole thing but if lookup table size is an issue, how about looking at the Cortex M4 processors? They are the basis of a number of teensys. For $20 you can get an Arduino IDE compatible board with 256K bytes of flash. For $30, you can get a Megabyte of flash. Lots of system resources as well.
 
Top