An AVR DDS function generator.
To make the experience fit your profile, pick a username and tell us what interests you.
Revision 1 of the DDS generator board
Adobe Portable Document Format - 18.58 kB - 03/02/2017 at 13:11
While the large touch display would be nice, the frustration with unreliable initialisation of the display has made me look at what other displays. In the parts bin I also have a 128x128 Color LCD (with a nice driver) however, it utilises 3.3V logic which has led to a change to a ESP8266 as the master MCU.
There is a number of side benefits of using the ESP8266, more flash storage (with a filesystem), Wifi and, a much faster clock speed. The filesystem has been a real boon for storing Waveforms and ll of my standard wave forms are now stored here. Wifi has come in really handy, as I already had a fairly capable piece of software for designing waveforms having a network connection provides for a simple way to get custom waveforms onto the device. The ESP8266 also comes with a mDNS library providing ZeroConf support (supported by the Python zeroconf library listening for new Funktion generator devices on my network).
There is one caveat however, limited IO pins. To build the UI, I'm leaning towards a second ATTiny to drive/handle button and rotary encoder inputs.
The initialisation sequence is complete (with both boot display and serial dump of the boot sequence) and is dropping into a main screen. Currently investigating options for building a rich GUI. I'd prefer to get an pre-built solution (or at least modify an existing one) rather than building a toolkit myself, of course this project is all about learning new skills so a simple interface toolkit might have to just be written (I spent years building GUI's for PalmOS) ryankurte's micro-gui looks like it could be a suitable base for this, customised for my situation.
On a side note I took the main DDS board along to the recent EEVBlog meetup and got some great feedback and suggestions.
When I built my first bench power supply I spent quite a bit of time searching to find a case to house my project, many are quite expensive (one option was to by a crap device from ebay/aliexpress gut it for the case) before I can accross some nice folded metals cases sold by an Australian company Wiltronics. They had a limited stock of them left @ $15AU each so I bought two. I remembered I had the second one stashed away and it will make a perfect case for this project.
Second point here is the ongoing frustration with the LCD initialisation. Once initialised (using a modified Seeed driver) it starts up, if I then switch to an Adafruit driver for the same chipset (which is a lot more efficient and provides much better response) it all works fine until you power off the LCD for a long period, afterwhich it will no longer initialise. Power cycling the display and it still initialises so I'm assuming there is some capacitance maintaining the initialisation or similar. Is annoying and difficult to debug with the display needing to be powered off some time for the issue to arrise.
It's time for decisions to be made and make them I have. I have a number of displays kicking around in the parts bin but in the end the choice was fairly obvious. The 320x240 LCD display with capacitive touch overlay is the clear winner. Along with a rotary encoder (and maybe the odd button). The display will be driven by another arduino compatible device, I'm thinking a pro mini might be a good option as this will still allow for a USB connection for debugging and control.
The LCD is a Seeed studios touch screen sheild that I purchased several years ago, at the time I ported the seeed driver to use the Adafruit GFX library, coming back to this project I found that I had not implimented rotation into the driver so this is step one, the work is mostly complete however there is still a problem with rotation of a filled rectangle that I have yet to fix (code for the library is on GitHub)
The LCD will allow for preview of waveforms etc..
The new power supply has come together really nicely, along with the DDS generator board:
There is a spot marked out for the offset pot, I didn't have the right value at the time.
Close up of just supply, one of my cleanest builds, could be condensed, but I was after separation between caps and regulators, this was the size of board I had so might as well make use of the space. Another output will be added for the master control board, I've not decided on AVR or ESP8266 so will either use the current 5V regulator or another 3.3V regulator to provide the additional power rail.
The DDS generator board has been completed, some changes where made along the way. The namely splitting the power supply input into 5V and +-9V rails along with a few other small tweaks. Next will be a round of testing with the bus pirate and then building up the new power supply.
The other big feature is a GUI tool for editing wave form tables. The tools for now allows for basic wave forms to be generated, inverted/mirrored, saved into a simple binary format that can be loaded by a micro controller or exported into a C-Array or ASM data table. I was planning one supporting custom wave tables that can be loaded via the user interface however any editor interface on the hardware is going to fiddly to use compared to a PC with mouse and keyboard.
The software is written in Python using PySide (QT) as the UI toolkit. Works on Linux/OSX/Windows.
Built up the output amplifier with the output BNC and amplitude control. Hooked up with some crock clips and is working correctly. Next step is to build up the R-2R ladder, MCU and complete the power rails. With those items done the generator will be in an alpha state.
There are still improvements to be made to the software and I'm thinking of using +-9V (or higher) to give more headroom for the op amps to operate without clipping. This will require a second power rail for the MCU.
A new power supply board is likely on the cards anyway to allow for more power rails.
Completed revision 1 of DDS output schematic and built up on breadboard/prototype. I might want to improve the power supply with more rails. Currently the power supply is only providing two +-5V rails, might be a better idea to provide a +-5 Volt for output amplifier, a separate 5V for running the AT Mega and possibly a 3.3 if I go down the path of using a ESP8266, otherwise the second 5V rail will suffice for both. Another thing that might be worth investigating is boosting the output rails to 9V to allow +-5V amplitude. Clipping starts to occur at around +-3.5V.
In this setup I'm driving the DDS generator via I2C from the bus pirate. Letting me adjust frequency and wave-forms. Giving a nice output:
I have just migrated all the firmware code into the primary repository along with a number of README docs describing function etc. The firmware is in an alpha stage now with the minimum viable functionality working. This means DDS generation of the built-in wave forms complete, I2C control of waveform output and frequency complete.
Next phase will move onto the DDS harware design getting off the development board, build the amplitude control and offset amplifiers.
In parallel I will begin work on a intially simple master I2C device to provide control, this will be an arduino initially, have yet to decide on the final device but a ESP8266 is not out of the question. The extra clock speed would be good for creating a nice user interface.
After spending several days trying to work out why my output wave looked so awful and was not at the correct frequency I extracted the code that actually generates the DDS output for closer inspection. Before it clicked the default frequency constant was not only backwards but I was writing it into the wrong registers! The DDS generation uses a 24bit step value and I was not only writing the constant into the upper two bytes I had even flipped the byte order. With the values in the correct registers I have a decent output.
The constants are calculated with a tool written in Python (included in the git repository).
Time to start working on hardware and getting off the development board!
Started building support for the I²C (TWI) interface that will be used to control the DDS Controller. And started testing sending commands to the controller. Need to add commands to adjust DDS step size and hence frequency, start/stop output, load wave tables. Later I want to add support for specifying custom wave tables.
All my testing is being done with the infinitely useful Bus Pirate, my controller is responding to a Bus Pirate address space search so it is looking like things are starting to work!
Code of course is in Github.
Become a member to follow this project and never miss any updates