Digital Signal Generator PCB
6th September 2026
This is a PCB version of my earlier digital signal generator that generates a crystal accurate square-wave signal from 2Hz to approximately 33.5MHz in precise steps of 2Hz. The frequency is continuously adjustable over this range using a rotary encoder, or you can enter an exact frequency using a numeric keypad, with the frequency displayed on an OLED display:

The Digital Signal Generator, based on an AVR16EB28, generates a square wave of from 2Hz
to approximately 33.5MHz in precise steps of 2Hz.
The earlier version was built on a breadboard and based on an SPDIP version of the AVR32EB28 microcontroller. This version uses essentially the same circuit but using surface-mount components, including an SSOP version of the microcontroller. I've also added an on/off switch, a 3.3V regulator, and space for a LiPo battery to make the project completely self-contained.
For a description of the principles of operation see the previous article Digital Signal Generator.
Operation
The Digital Signal Generator works as follows: you enter the frequency you want, in Hz, on the numeric keypad as a sequence of up to eight digits, and press *. The display then shows the actual frequency that will be generated, and generates the square waves on the outputs. You can then adjust the frequency up or down in steps using the rotary encoder. Initially the step size is 2Hz, but you can toggle the step size between 2Hz and 1000Hz by pressing the rotary encoder knob. Pressing # clears the current input and stops the output.
The signal generator has a range of 2Hz to 33554430Hz. The outputs are provided between WO0 and GND, and WO1 and GND. Because these are out of phase you can get a waveform of the same frequency but twice the amplitude between WO0 and WO1.
The circuit
Here's the circuit of the PCB version of the Digital Signal Generator:

The circuit of the Digital Signal Generator, based on an AVR16EB28.
Power supply
The circuit runs from a supply of 3.3V from a regulator. I suggest powering it from a 3.7V LiPo battery, and there's space on the PCB for a 150mAh battery and a 2-pin JST connector it can connect to. You can charge it using a Lipo charger such as Adafruit's Micro Lipo [1].
Rotary encoder
A variety of different rotary encoders will fit the PCB; the one I've specified in the parts list is available from Adafruit or its distributors, and includes a suitable knob.
Crystal oscillator
The crystal I used is a 4.194304MHz SMD type with an accuracy of 20ppm, and a load capacitance of 18pF [2].
Unlike the earlier ATmega processors the new AVR series don't support an external high-frequency crystal, so it's necessary to provide a crystal oscillator with its output connected to the EXTCLK input.
A novel feature of this circuit is that it uses the Event System to construct a crystal oscillator from two spare I/O pins. It defines PC3 as an inverted input, PC2 as an event output EVOUTC, and then links them internally using an event channel. The crystal is connected between PC3 and PC2, and the output PC2 is connected to the EXTCLK input on PA0.
Recent AVR processors allow you to configure digital inputs either in Schmitt Trigger mode (the default) or in TTL input mode. I tested the stability of this crystal oscillator in both modes, and with a range of different component values. With PC3 in Schmitt Trigger mode the oscillator only operated with a 1MΩ feedback resistor and if the load capacitors were omitted. In TTL mode the oscillator operated correctly with a range of capacitor values, from none to 30pF, with or without the feedback resistor. I've therefore recommended TTL input mode, a 1MΩ feedback resistor, and 18pF load capacitors.
Here's the parts list (click to expand):
Parts list
| Qty | Item | Value | Size | Typical parts |
| 1 | SMD resistor | 470Ω | 0805 | Yageo RC0805JR-07470RL |
| 1 | SMD resistor | 1kΩ | 0805 | Yageo RC0805JR-071KL |
| 1 | SMD resistor | 3.3kΩ | 0805 | Yageo RC0805JR-073K3L |
| 1 | SMD resistor | 4.7kΩ | 0805 | Yageo RC0805JR-074K7L |
| 2 | SMD resistor | 6.8kΩ | 0805 | Yageo RC0805JR-076K8L |
| 2 | SMD resistor | 22kΩ | 0805 | Yageo RC0805JR-0722KL |
| 2 | SMD resistor | 1MΩ | 0805 | Yageo RC0805JR-071ML |
| 2 | Ceramic capacitor | 18pF | 0805 | Yageo CC0805JRNPO9BN180 |
| 1 | Ceramic capacitor | 1µF | 0805 | Murata GCM21BR71E105KA56K |
| 2 | Ceramic capacitor | 10µF | 0805 | Murata GRM21BR61E106KA73L |
| 1 | Crystal | 4.194304MHz | 12.5 x 4.6mm | QCS4.194304F18B23M |
| 1 | Microcontroller | AVR16EB28 | SSOP-28 | AVR16EB28-I/SS |
| 1 | Voltage regulator | AP2112-3.3 | SOT-23-5 | AP2112K-3.3TRG1 |
| 12 | Push buttons | Tactile | 6 x 6mm | FSM4JH |
| 1 | On/off switch | SPDT | 0.1" pitch | SPDT Slide Switch |
| 1 | Rotary Encoder | PEC11-4215F-S24 | 12mm | Rotary Encoder + Extras |
| 1 | I2C OLED Display | 128x32 | 1.5 x 0.45" | 0.91" 128x32 OLED Display Module White |
| 1 | LiPo Battery | 150mAh | LP402025 | 150mAh 3.7V LiPo Battery |
| 1 | JST PH Connector | 2-pin | 2.0mm pitch | 2.0mm Pitch Connector Kit - JST PH Compatible |
| 2 | PCB | Double-sided | 81.3 x 40.6mm | See below |
Construction
I designed a PCB in Eagle and sent it to JLCPCB for production.

The front panel of the Digital Signal Generator, showing the OLED display, rotary encoder,
and push button keypad.
I soldered the surface-mount components using a Miniware MHP50-B5 50x50mm hotplate [3] [4] at 235°C with Chip Quik SMD291AX10T3 solder paste. It's probably a good idea to test the board before adding the through-hole components because it will be easier to rework the board.
I then soldered the through-hole components, including the push buttons, rotary encoder, pin header, and display. I attached the display in position with a double-sided foam pad. Finally I secured the LiPo battery in position with double-sided sticky tape:

The back of the completed Digital Signal Generator, showing the LiPo battery.
Back panel
I've also given details of a plain PCB the same size for use as a back panel; you can attach the boards together using 12mm M2.5 threaded pillars and M2.5 screws [5].
I checked the output of the Digital Signal Generator over its range using my 100MHz Frequency Meter.
The program
For an explanation of the program see the original article, Digital Signal Generator.
The only addition to the PCB version is the interrupt-service routine to handle the rotary encoder switch, which is used to toggle between a step size of 2Hz or 1000Hz. I used a pin on a separate port for the switch, PF1, so it could use a separate interrupt service routine:
ISR (PORTF_PORT_vect) {
Stepsize = 1002 - Stepsize; // Toggle between 2 & 1000
// Wait 255 cycles once button released for debounce
uint8_t count = 0;
while (count < 255) {
count++;
if ((PORTF.IN & PIN1_bm) == 0) count = 0; // Still pressed
}
PORTF.INTFLAGS = PIN1_bm; // Clear interrupt flag
}
Installing the program
First install Spence Konde's DxCore from GitHub: see DxCore - Installation. I used version 1.6.2.
Then, in the Arduino IDE:
- Choose the AVR EB-series (no bootloader) option under the DxCore heading on the Board menu.
- Check that the subsequent options are set as follows (ignore any other options):
Board: "AVR EB-series (no bootloader)"
Chip: "AVR16EB28"
Clock Speed: "20 MHz internal"
You can leave the other options at their defaults, the first option on each submenu.
- Connect a UPDI programmer to the UPDI, GND, and VDD pins.
The recommended way to upload the program is to use a 3.3V Serial board, such as the SparkFun FTDI Basic board [6] connected with a Schottky diode as follows. You can substitute a 4.7kΩ resistor for the Schottky diode:

- Set Programmer to the "SerialUPDI - Normal: 230400 baud (recommended)" option.
- Select the USB port corresponding to the USB to Serial board in the Port menu.
- Select Burn Bootloader to reset the fuses (in case they were changed for an earlier project).
- Click Upload to upload the program to the AVR16EB28.
Resources
Here's the program for the Digital Signal Generator PCB: Digital Signal Generator PCB Program.
Get the Eagle or Gerber files for the PCBs here: https://github.com/technoblogy/digital-signal-generator.
- ^ Micro Lipo - USB LiIon/LiPoly charger on Adafruit.
- ^ QCL4.194304F18B23B on Farnell.
- ^ MHP50-B5 on Adafruit.
- ^ MHP50-B5 on AliExpress.
- ^ Black Nylon Screw and Stand-off Set – M2.5 Thread on The Pi-Hut.
- ^ SparkFun FTDI Basic Breakout - 3.3V on Sparkfun.
blog comments powered by Disqus
