logo elektroda
logo elektroda
X
logo elektroda

Generator - wobulator on Arduino UNO/NANO + AD9833 possibly ESP32 Wemos D1

Bucefal76 3108 4

TL;DR

  • A function generator and primitive wobulator uses the AD9833 programmable SPI generator with Arduino UNO/NANO or ESP32 Wemos D1 R32 as controller.
  • A serial console selects waveform, frequency, and up to two channels, while the ESP32 DAC or an MCP4725 generates a ramp for oscilloscope sweep control.
  • The output amplitude is normalised to 1V p-p, despite the AD9833 producing about 600mV p-p for sine and triangle and rail-to-rail for square.
  • An analogue mixer with a common-emitter stage for sine/triangle, a resistor path for square, and an emitter follower replaces the earlier X9C103S attenuation idea.
  • The current prototype is breadboard-based, and extra transistors plus USB-board power reduced maximum frequency, so cleaner analogue supply and buffering remain open improvements.
Generated by the language model.
ADVERTISEMENT
Treść została przetłumaczona polish » english Zobacz oryginalną wersję tematu
📢 Listen (AI):
  • Edit: 03-10-2025:
    I have corrected the circuit diagram for normalising the output signals, and refined the buffer (emitter secondary) which was causing some problems.

    Just for fun, I committed a function generator, sine, triangle and rectangle based on the AD9833 programmable generator (SPI).

    Oscilloscope screen displaying a yellow triangular wave with a frequency of 998 Hz and a peak amplitude of 1.22 V. .

    Oscilloscope screen displaying a sine wave signal with a frequency of 998 Hz and peak value of 1.23 V. .

    Oscilloscope waveform displaying a square wave on a Hantek screen. .

    The project uses a choice of Arduino UNO/ NANO or ESP32 in Wemos D1 R32 (or suitable clones) as the generator controller.
    In addition, the CPU of course implements the operator interface, in this case the simplest possible in the form of a serial port character console.
    It is possible to select the type of signal, frequency, enable or disable a given channel (maximum 2).

    View of PuTTY console with text interface of the signal generator. .

    For now, I only have it in prototype form plugged into a contact board:

    Functional generator prototype with oscilloscope Hantek. .

    Additionally, I used the ESP32 DAC output or an external DAC (MCP4725, i2C) plugged into the UNO/NANO to generate a "ramp signal" to control the second channel of the oscilloscope. So that the oscilloscope moves the amplitude of the generator output while the programmable generator changes the frequency of the sine wave on the first input, in a preset range with a preset step. This creates a sort of primitive wobulator:



    .

    The problem with the AD9833 circuit is the difference in amplitude of the generated signal, for the sine and triangle it is 600mV p-p, and for the rectangle it is practically rail to rail.
    I wondered how to solve this elegantly to have the same amplitude regardless of the type of signal chosen. My first idea was to use an electronic potentiometer controlled from the procec (X9C103S). It varied the attenuation of the signal (equalised downwards) depending on the selected waveform type.

    In the end, I chose a slightly more complex solution involving the design of an analogue circuit that creates two signal paths.
    On one of these paths is an amplifier with a common emitter (for sine and triangle). On the other path, a resistor (mounting potenciometer) suppresses the rectangle before entering the signal mixer. Then there is already an output emitter secondary. In general the circuit may be so-so, my experience in electronics is to have read the electronics course from EP :) .

    Electronic schematic of a function generator based on the AD9833. .

    Obviously, inserting this number of transistors in the output worsened the parameters of the maximum frequency achieved by the generator.
    The power supply to the analogue part is drawn directly from the CPU board, which is certainly not the most optimal solution.
    That is, we power the generator from the same PC on the USB port with which we chat via the character console.
    I would welcome suggestions on how to improve.

    In the current edition of the schematic with the corrected secondary, the output signal is set to be a nice 1V p-p.

    You can find the software at this link: https://github.com/bucefal76/signal_generator_ad9833
    Ready to compile under VSC with PlatformIO (ESP supported on Arduino framework not native ESP32).
    The exact generator configuration is there, see README.md, further Include/ModuleConfig.hpp.

    I will warn you in advance that it may be a bit too complex at first glance for an amateur Arduino sketcher.
    If one feels like rummaging around inside, it is worth reading about MVC to start with: https://pl.wikipedia.org/wiki/Model-View-Controller

    Cool? Ranking DIY
    About Author
    Bucefal76
    Level 17  
    Offline 
    Bucefal76 wrote 422 posts with rating 449, helped 2 times. Live in city Bielsko-Biała. Been with us since 2016 year.
  • ADVERTISEMENT
  • #2 21461551
    rb401
    Level 39  
    Cool project. Especially when it comes to wobuloscopic measurements, which somehow have lost their popularity these days. It's a shame, because they carry a lot of information.
    But in truth, here in today's reality, an oscilloscope is not a necessary component of a measurement system, which anyway in these measurements does not present the waveform but only the envelope.
    And if we already have a microcontroller here, then instead of a DAC generating the Y-axis (which has to be adjusted appropriately in the oscilloscope and converted into frequency somehow), a peak rectifier connected to the ADC would be more useful. Then the system would have full information about the characteristics and it could be displayed on the display, or a file could be sent with the measurement results (e.g. under Excel) or a graphical file with the axis descriptions for viewing on the computer. Faster and more convenient.
  • ADVERTISEMENT
  • #3 21461589
    IS
    Level 19  
    The ADC in the ESP32 is a misunderstanding. Would have to add an external converter.
  • ADVERTISEMENT
  • #4 21461939
    Urgon
    Level 38  
    AVE...

    In a podcast about DDS generators from a few years ago I mentioned a minor flaw in the modules with AD9833, well the output filter is wrong in them. It might be worth bypassing it and seeing if that solves the amplitude difference problem?

    The project itself is interesting and useful, although I'm not a big fan of the Arduino environment....
  • #5 21467175
    gulson
    System Administrator
    Thanks for sharing the project, quite a few things on ESP32 are implemented :) .
    I couldn't find a frequency range or precision anywhere?
    Send a packet and I'll send a small gift.
📢 Listen (AI):

FAQ

TL;DR: This FAQ shows hobbyists how to build a simple AD9833 function generator and primitive wobulator with 1 V p-p normalized output; as one expert noted, "Cool project." It covers Arduino UNO/NANO, ESP32 Wemos D1 R32, MCP4725 sweep generation, and the main analog-stage tradeoffs. [#21461551]

Why it matters: It turns a low-cost DDS module and a simple microcontroller board into a practical bench tool for waveform generation and basic frequency-response viewing.

Option Built-in DAC for sweep ADC comment in thread Software note
Arduino UNO/NANO No Not discussed Uses external MCP4725 when DAC is needed
ESP32 Wemos D1 R32 Yes Internal ADC called inadequate for accurate reading Supported in PlatformIO on Arduino framework
UNO/NANO + MCP4725 Yes, external Not discussed Used for wobulator-style X/Y sweep control

Key insight: The thread's core lesson is that waveform generation is easy with AD9833, but usable output needs analog conditioning. Normalizing sine, triangle, and square to the same level mattered more than adding features.

Quick Facts

  • The revised analog stage sets the generator output to a clean 1 V p-p after the schematic correction and output-buffer refinement. [#21461309]
  • The raw AD9833 output differs strongly by waveform: about 600 mV p-p for sine and triangle, but nearly rail-to-rail for square wave. [#21461309]
  • The project supports up to 2 channels, lets you choose waveform and frequency, and uses a serial character console as the operator interface. [#21461309]
  • For wobulator-style work, the sweep signal can come from the ESP32 DAC or an external MCP4725 over I²C attached to UNO/NANO. [#21461309]
  • One reviewer noted that classic wobuloscopic measurements still show the circuit envelope well, even though modern setups may replace the oscilloscope Y-drive with ADC capture. [#21461551]

How do I build a simple function generator and wobulator with an Arduino UNO or NANO, an AD9833 module, and an MCP4725 DAC?

Use the AD9833 as the waveform source and the MCP4725 as the sweep-voltage source. 1. Connect Arduino UNO or NANO to the AD9833 over SPI and to the MCP4725 over I²C. 2. Add the analog output stage that normalizes waveform amplitude. 3. Use the serial console to select waveform, frequency, and channel state, then feed the DAC ramp to the oscilloscope sweep input for wobulator-style viewing. The project was built as a breadboard prototype first. [#21461309]

What frequency range and frequency precision can this AD9833 generator achieve when controlled by Arduino UNO, NANO, or ESP32 Wemos D1 R32?

The thread does not state a frequency range or precision figure. A later reply explicitly says the reader could not find the range or precision anywhere, so no verified numeric limit appears in the discussion. The safest answer is that these values are undocumented in this thread and must be taken from the repository configuration or measured on hardware. [#21467175]

Why does the AD9833 output have about 600 mV p-p for sine and triangle but nearly rail-to-rail for square wave?

Because the module presents different native output behavior for its waveform modes. The author measured about 600 mV p-p for sine and triangle, while the square wave came out practically rail to rail, creating a large mismatch at the output. That mismatch is why the project added separate analog paths instead of using one fixed output stage for every waveform. [#21461309]

What's the best way to normalize AD9833 output amplitude so sine, triangle, and square waves all come out at the same 1 V p-p level?

The thread favors analog conditioning with two separate paths and a final output buffer. Sine and triangle go through a common-emitter amplifier, while square wave is attenuated with a resistor trimmer before both paths are mixed and buffered. After the corrected schematic and refined output stage, the author set the final output to 1 V p-p. This approach equalizes upward and downward instead of only attenuating everything. [#21461309]

How can I use the ESP32 DAC output or an external MCP4725 to generate an oscilloscope sweep signal for primitive wobulator measurements?

Use the DAC to generate a ramp that drives the oscilloscope sweep while the AD9833 steps frequency on the measured signal. The thread describes using the ESP32 built-in DAC or an MCP4725 I²C DAC on UNO/NANO so the oscilloscope moves along one axis as the generator sweeps frequency on the other input. That creates a primitive wobulator view of response versus frequency. [#21461309]

What is a wobulator and how is it used with an oscilloscope to view a circuit's frequency response envelope?

"Wobulator" is a measurement setup that sweeps frequency over a range, while a display shows the resulting response envelope rather than the detailed waveform. In this thread, the generator changes sine-wave frequency in preset steps, and a DAC-driven signal moves the oscilloscope axis so the screen shows amplitude versus frequency. One commenter notes that wobuloscopic measurements still carry a lot of information even today. [#21461551]

What is an emitter follower (called 'emitter secondary' in some descriptions) and why would it be used at the output of an AD9833 signal conditioner?

"Emitter follower" is a transistor output stage that buffers a signal, keeps voltage gain near unity, and lowers output impedance. Here it sits after the waveform-conditioning network so the mixed signal can leave the generator more cleanly and at a controlled level. The author refined this output buffer because the earlier version caused problems, then updated the schematic accordingly. [#21461309]

AD9833 analog output conditioning vs digital attenuation with an X9C103S potentiometer — which approach is better for equalizing waveform amplitudes?

The analog conditioning approach is the one actually chosen in the project. The author first considered an X9C103S digital potentiometer to attenuate the output depending on waveform type, but then switched to a two-path analog design with amplification for sine and triangle plus attenuation for square. That design achieved the desired 1 V p-p normalized output in the corrected version. [#21461309]

How much do added transistor stages and a common-emitter amplifier reduce the maximum usable frequency in an AD9833 generator?

The thread confirms that the extra transistor stages reduce the maximum usable frequency, but it gives no numeric cutoff. The author states that adding this number of transistors at the output worsened the maximum frequency parameters of the generator. So the real answer here is qualitative: the conditioning solved amplitude matching, but it traded away some high-frequency performance. [#21461309]

What problems can the incorrect output filter on common AD9833 modules cause, and how do I bypass or redesign that filter?

A wrong output filter can distort the expected output behavior and may contribute to the observed amplitude mismatch. One commenter specifically says common AD9833 modules have an incorrect output filter and suggests bypassing it first to see whether that improves the amplitude problem. In practice, the thread recommends treating the module filter as a suspect stage before redesigning the rest of the analog chain. [#21461939]

ESP32 internal ADC vs external ADC for wobuloscopic measurements — which is better for reading a peak detector accurately?

An external ADC is the better fit if you want accurate peak-detector readings. The thread's strongest statement is blunt: the ESP32 ADC is a misunderstanding, so you would need to add an external converter. That makes the ESP32 attractive for its DAC, but not for measurement accuracy on the input side without extra hardware. [#21461589]

How would I replace the oscilloscope Y-axis DAC method with a peak rectifier and ADC so the microcontroller can save or plot the measured response?

Replace the sweep-to-oscilloscope method with a peak rectifier feeding an ADC, then store or display the measured envelope directly. A commenter explains that the oscilloscope in this use case shows only the envelope, so the microcontroller can capture that information itself and then send a file, draw a graph, or export results for Excel. This makes the system faster and more convenient for documentation. [#21461551]

What is MVC in the context of an Arduino or ESP32 generator project, and why would this software architecture make the code more complex but easier to extend?

"MVC" is a software architecture that separates data handling, user interface, and control logic, which makes features easier to extend but increases initial code structure. The author warns that the code may look too complex for an amateur Arduino sketcher and explicitly recommends reading about MVC before digging into the project. That tradeoff fits a multi-board project with console UI and configurable modules. [#21461309]

Which controller is a better fit for this AD9833 project: Arduino UNO/NANO or ESP32 Wemos D1 R32, considering DACs, ADCs, and software support in PlatformIO?

ESP32 Wemos D1 R32 is the better fit if you want a built-in DAC, but UNO/NANO stays viable with an external MCP4725. The thread says ESP32 support exists in PlatformIO on the Arduino framework, not native ESP32, and it also uses the ESP32 DAC directly for sweep generation. The main downside is measurement input, because another reply rejects the ESP32 internal ADC for accurate reading. [#21461309]

What are the best ways to improve power supply quality and reduce noise when the AD9833 analog stage is powered from the same USB-connected CPU board?

The first improvement is to stop sharing the analog-stage supply directly with the USB-powered controller board. The author says the analog section currently takes power straight from the CPU board, which is "certainly not the most optimal solution," and notes that both generator power and console link come from the same PC USB port. In this thread, that shared USB supply is the main named noise and performance weakness. [#21461309]
Generated by the language model.
ADVERTISEMENT