The function generator is based on Direct Digital Synthesis (DDS) realized with an AD9833 module which also incorporates an output amplifier AD8051 whose output amplitude is controlled by a digital potentiometer MCP41010.
An ESP32 microcontroller controls all the functions of the DDS module and also realizes the user interface comprising an I2C LCD and a rotary encoder with axial pushbutton.
The various functions of the generator are choosen by clockwise (cw) or counterclockwise (ccw) rotating the rotary encoders shaft and by clicking (click, or longclick) its pusbutton.
- AD9833 DDS Module 25 MHz Clock with AD8051 Output Amplifier and MCP41010 Digital Potentiometer
- ESP32 Microcontroller DoIt DevKit V1
- LC Display I2C 4 x 20
- Rotary Encoder with axial Pushbutton
5. User Interface and Operation
On power up Screen-0 is displayed. The settings of both channels are shown. The active channel is marked, here as 〈Chan 0〉. We see the selected wave forms, the settings of the digital potentiometer and and the actual frequencies of each channel.
The values of both channels can be set independently. The set values are not remembered between power ups. That is left for further enhacement and could be done by storing the settings in ESP32 flash memory.
The sweep frequency starts at the frequency set for channel 0 and stops at the frequency set for channel 1. The possible modes are shown below.
6. Example Waveforms
Waveform pictures are all taken with amplitude set to 133 units of the digital potentiometer, corresponding to 2000 mVpp. We see clearly the decreasing amplitude and degradation of the waveform at higher frequencies.
The statechart, created with the free tool YAKINDU™, shows the basic operation of the frequency generator.
Rotating the shaft of the rotary encoder cycles through the 4 screens.
- Screen0 : Displays the settings of both channels. Clicking the pushbutton when output signal is on toggles between the two channels. LongClicks switches on and of the output signal. Clicking when a channel is off switches to the other channel in the on-state.
- Screen1 : Allows changing mode, amplitude and frequency of channel 0 by rotating the rotary encoder shaft.
- Screen2 : Allows changing mode, amplitude and frequency of channel 1 by rotating the rotary encoder shaft.
- Screen3 : Allows changing the various settings of sweep
The next statechart shows the settings of channel 0 in more detail. The individual digits of the frequency are reached by clicking and then changing value by rotating the rotary encoders shaft.
Duration and frequency step for sweep mode are set in an analog way.
8. Program Code
My programming environment is not the native Arduino™ IDE but PlatformIO™ on top of Microsoft's Visual Studio Code™. This combination offers many advantages and allows a much better structuring of the code into several modules especially when we adopt The Object Oriented way.
The code below shows the main program. It mostly consists of comments. The setup() function in turn calls setup() of the classes AD9833FuncGen and ControlKnob and initializes the LCD. Astonishingly the main loop() consists of a single line namely the call of the loop() function of the class ControlKnob. This class realizes the Finite State Machine and handles the 4 actions onClick(), onLongClick(), onCW() and onCCW().
Interested? Please download the entire program code. The zip-file contains the complete PlatformIO project.