A function generator is one of those tools that you will use a lot when making electronic circuits. And you can find them quite readily online for a whole range of prices, depending on the quality that you are looking for. This time around though, I wanted to see how feasible it might be to make one yourself. The challenge for this project will be making it fully analog and out of discrete components.
Now, when making this function generator, we need to accomplish a few things. Let’s use my digital generator as an example. We need to be able to select the frequency in which the output oscillates, we need to be able to adjust the amplitude of the output frequency, and we need to be able to choose what the shape the output should be, with the most basic options being square, triangle, and sine.
Designing an oscillator circuit isn’t the most difficult thing to do. I’ve made a video about generating sine waves for example. The sine wave could be shaped into a square wave with a comparator and then further shaped into a triangle using an op-amp integrator. The problem here would be making the circuit adjustable. Take an LC based oscillator, such as the hartley, for example. The resonant frequency is equal to 1 divided by 2 * pi * sqrt(LC). To make this frequency adjustable, we’d have to source either an adjustable capacitor or an adjustable inductor.
Adjustable versions of these components are not always the easiest thing to get your hands on. But they certainly do exist. The problem now would be finding an adjustable component with a suitable value. On DigiKey, I found an adjustable capacitor with a range of 20pF to 600pF. Assuming we use a 400uH inductor, that gives us a frequency range of 56kHz to 10kHz. This isn’t a very large range. It could be extended perhaps with a switch using different components attached, but that approach can start to get ugly especially with these small value reactive components. My point here is that creating a circuit with a large adjustable frequency range is the challenge of this project.
Instead, I took inspiration from one of my own previous projects. In my class-D amplifier video, I needed to include a ramp wave for use in the PWM generator. It worked by taking advantage of the linear relationship between the current flowing into a capacitor and the slope of the voltage. Here, a constant current source would charge the capacitor at a constant rate, giving us a nice ramp up. Then a schmitt trigger would quickly reset the capacitor’s voltage once it reached a maximum value.
This circuit had three different ways in which the frequency could be adjusted. First, we would adjust the size of the capacitor itself. A larger capacitor would slow the rate at which the voltage increases. Second, we could adjust the value of the current flowing. A larger current would increase the rate in which we charge the capacitor. And finally, we could adjust the voltage at which the schmitt trigger resets the capacitor. A smaller voltage would mean a higher frequency since the schmitt trigger would reset the voltage more often.
The challenge now would be adapting the ramp design into a triangular design. We already have the ramp up, we just need to make a ramp down instead of a sudden jump down. I started in LTspice by rebuilding certain aspects of the ramp generator. I made a schmitt trigger from an op-amp and placed two current sources. This design technically worked, but only at lower frequencies. I was having issues with the current sources turning on and off quickly enough. This wasn’t an issue in the ramp generator since the single current source was always on.
After a few revisions, I came up with this design. Differential amplifiers are very fast transistor circuits and they have current outputs, which makes this perfect for our need for a current output. Basically, each pair acts as a voltage comparator. When the schmitt trigger is high, the upper differential pair directs current through the transistor on the left. This current is equal to the current of the current source. This current can then be mirrored over the the transistor’s path. Meanwhile, the lower different pair uses the opposite type of transistor, so the current flows through the right transistor, so the mirror has no current flowing. On the low side of the schmitt trigger, the opposite happens.
Both differential pairs share a current source. This way, we don’t have to worry about matching the currents between both. I designed this current source to roughly have a current of 10mA, give or take a few milliamps.
I was still having issues with the speed of my schmitt trigger though, so I decided to redesign the entire thing. At the core, what we need is a circuit to switch the current sources whenever a voltage threshold has been reached, with an upper and lower voltage. For convenience, I decided that the voltage thresholds should be symmetrical. For example, +5 and -5 volts. This way, the waveform is centered around zero by default.
In order to detect when these threshold voltages have been reached, I used differential amplifiers acting as comparators. The specific voltage thresholds are determined by a resistor divider. Now that we have the comparators, we just need a way to latch the output either high or low until the other comparator latches it in the other direction.
To achieve this, we can use a transistor circuit that utilizes positive feedback. This is a two transistor latch circuit. Here’s how it works: when we initally power up, both transistors are off and nothing really happens, which leaves the output high. Once we apply a current to the base of the NPN transistor it turns on and pulls the output low. This in turn activates the PNP transistor. This PNP transistor keeps the NPN transistor on even after we’ve removed the initial input current. To make the output high again, we simply pull the input down to the negative rail. This will divert all current that would have gone into the NPN and it turns off. This also turns off the PNP. Then all that’s left is the pull-up resistor.
Connecting the differential pairs to the circuit is easy enough. The pair that detects the positive voltage can simply run into the input, since we are looking for a current input. The negative pair needs an output transistor that will starve the NPN of its current. It’s important to include the 100 ohm resistor to maintain its switching speed. This is because the transistor will go into saturation when it’s on, and we need a quick way for the charges on the base to leave. Without this, the transistor will stay on for longer than it should.
With this, we have the equivalent of a schmitt trigger with a fast enough speed for our purposes. It also conveniently provides us with a square wave output. Now all that’s left is to decide how we will select which method we will use to select a frequency. I didn’t want to go with adjusting the current source since higher currents would lead to us wasting a lot more power. I figured a hybrid approach between adjusting the voltage level and adjusting the capacitor value would work best.
When I say adjusting the capacitor value, I don’t mean using one of those adjustable capacitors, but rather having a switch that will select one of three capacitors. The three capacitors would have values of 1nF, 100nF, and 10uF. It’s worth mentioning now that these capacitors will be film capacitors, since cheaper ceramic capacitors change their capacitance with different voltages. This would cause some non-linearity. Luckily, film capacitors don’t have this problem nearly as much.
Now let’s talk about how we can adjust the voltage thresholds. Originally I had planned on simply adjusting the voltage thresholds directly, by having a voltage divider with two taps, and a potentiometer in the middle. This would work, but it comes with problems once we start having a smaller and smaller difference between the thresholds. It also means that changing the frequency also changes the amplitude of the output triangle. Instead, I opted to always have voltage thresholds at +/-5 volts. This way we can have a constant output amplitude.
To adjust the frequency now with fixed threshold voltages, I placed an op-amp circuit with adjustable gain. Increasing the gain means that the threshold is reached more quickly, which means we get a higher frequency. This does mean that we have to design an op-amp though.
Here’s what I came up with. It’s a folded cascode differential amplifier. The bias voltage for the cascode is formed with these two diodes in series with a 10k resistor. The output stage is a bit different than what I normally go for since it is made up of two emitter followers before reaching the output transistors. The resistor and capacitor provide stability against higher frequencies. The combination of the cascode, the improved current mirror that uses four transistors instead of just two, and the output stage have allowed me to push the maximum frequency of the op-amp higher than my previous designs. As you can see from my AC analysis, the op-amp is able to both maintain the 50x gain and have minimal phase shift up to 1MHz, which was one of my targets for the project.
To top off the project, I wanted to see if I could add sine wave functionality. I copied this circuit from a Texas Instruments document, and it works well here in the simulator. This kind of circuit is called a sine shaper, and it takes advantage of the logarithmic nature of bipolar transistors to approximate a sine wave based off of a triangular input. Two more op-amps were added to first amplify the sine wave to a +/-5 volt output and also another to buffer the output. These op-amps are identical to the one I presented previously.
With the simulations and schematic complete, I created a layout for a PCB and ordered it through JLCPCB. Now we can get to soldering. You might notice a whole bunch of other components that I didn’t mention in the simulation portion of the video. This is because I had originally planned to give the whole circuit a power supply coming from mains and then to put it in a case. As you’ll see, I didn’t end up doing this, but I did solder together all of the discrete components. I also used through hole components. I did this for two reasons: first, it’s a lot easier to match the transistors when the leads are long like this. Second, and more importantly, I have several hundred of these transistors, and I kind of need to use them. If you plan on replicating this project at home, I recommend that you use surface mount components and use matched pair ICs. It’ll make the everything much easier.
Anyways, like I mentioned, I needed to match several transistor pairs before soldering them. This is especially important in all of the differential pairs and the current mirrors since mismatching in the transistors can cause a lot of problems.
With that complete, let me show you what the resulting circuit looks like. I added a couple of emitter resistors on the current source transistor emitters to allow for symmetry adjust and slight current adjustment. When testing the circuit at first, I got this really odd behavior on the output, but then I realized that I forgot the power supply capacitors. After soldering those in, the circuit really started working.
As you can see, I can cleanly adjust the frequency. There is a slight problem though, if I increase the op-amp’s gain beyond unity, we start getting this little spike at the top and bottom of the triangle. And further increasing the gain causes it to widen. I believe that the spike is caused by the current source switching, as it perfectly lines up with the square wave. It isn’t very noticeable at unity since we aren’t amplifying it. But once the gain increases, it gets amplified along with the triangle.
This actually is a big problem at the highest frequency setting, where the spike gets amplified to the point of dominating the waveform. This actually limits the maximum frequency of the function generator, which is really unfortunate. I tried a few things to fix the spike problem, such as adding more compensation capacitance and adding an input resistor to the op-amp. Unfortunately none of these worked. I did also try adjusting the frequency by instead directly changing the voltage thresholds. This does fix the problem to a certain extent, but the amplitude is no longer constant.
I decided to leave it at that, since the circuit almost works perfectly. I suppose another fix could be changing the current flow, but that would require some additional circuitry and it’d be easier to make a new design with a new PCB. I would like to mention the sine shaper quickly. It doesn’t really work as I had expected it would. Like I mentioned, it worked in the simulator but not in circuit. I think a portion of the problem is that the following amplifer has some sort of problem. I didn’t fix this since the sine wave wasn’t necessarily the point of the video anyways. Perhaps in another iteration I could fix it.
But let’s get back to the point, I wanted to design a function generator with a wide frequency range. Regardless of how the triangle, square, or sine wave look, let’s test the capabilities of my design. Using the low-speed setting, we get a minimum frequency of 17Hz and a maximum of 918Hz. The medium speed setting has a minimum frequency of 1.8kHz and a maximum of 81kHz. Finally, the high-speed setting has a minimum of 140kHz and a maximum of 968kHz. As you can see we nearly reached 1MHz, if you are ok with using the square wave. So basically, we have a range of 968kHz, which I’d say makes this project, at least partly, a success.
I’m very confident that if the spikes were removed from the triangle, I could push the frequency beyond the 1MHz mark. I’d like say again that the current adjustment method is a good candidate for fixing the problem. Perhaps in another part.
Well, that covers it for this project. It doesn’t work as well as I had planned at the beginning, but it functions well as a proof of concept. If you’ve enjoyed this video and learned something new, please consider subscribing so that you can see my future videos. Also, visit my buymeacoffee page. With your support I can keep making these videos. I’d like to thank our channel members: Mr. devNull, Cognisent, Mark, and Alex Nygren. You all have made this video possible. Thanks for watching, have a good one!