Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

Sign up (/users/sign_up?

redirect_to=%2Fpokitmeter%2Fsignal-
(/)
Projects generator-with-arduino-using-dds-and-pico-76fde9&source=nav)
News Contests Events Videos Workshops
(/projects? (/news? (/contests? (/events? (/videos? (/workshops?
ref=topnav) ref=topnav) ref=topnav) ref=topnav) ref=topnav) ref=topnav)

pokitMeter (/pokitmeter)
Published February 20, 2017 © GPL3+ (http://opensource.org/licenses/GPL-3.0)

Signal Generator with


Arduino Using DDS and
Pico
We'll create a signal generator using DDS techniques and
evaluate its performance using a picoMeter, the world's smallest
wireless DSO.

Beginner(/projects?difficulty=beginner) Full instructions provided 2 hours 12,214


LEGO MINDSTORMS
Voice Challenge:
Powered by Alexa.
$100K in prizes!
(https://www.hackster.io
/contests/alexa-lego-
(https://www.hackster.io/contests/alexa-lego-voice-challenge? voice-challenge?
source=hacksterads) source=hacksterads)
ADVERTISEMENT
(HTTP://HELP.HACKSTER.IO/KNOWLEDGEBA
ARE-THESE-ADS)

Things used in this project

Hardware components

picoMeter DSO × 1 (/products/buy/17453?


s=BAhJIhIzMzM2MSxQcm9qZWN0BjoGRUY%3D%0A)

Arduino UNO & Genuino


UNO
(/arduino/products/arduino- × 1 (/products/buy/42741?
s=BAhJIhIzMzM2MSxQcm9qZWN0BjoGRUY%3D%0A)
uno-genuino-uno?
ref=project-76fde9)

Rotary potentiometer
× 1 (/products/buy/202?
s=BAhJIhIzMzM2MSxQcm9qZWN0BjoGRUY%3D%0A)
(generic)

Software apps and online services

Arduino IDE
(/arduino/products/arduino- (https://www.arduino.cc/en/main/software
ide?ref=project-76fde9)

Story
Overview
The purpose of this project is to demonstrate the power of signal
generation using a PWM signal and the DDS (Digital Direct
Synthesis) method. We will validate the algorithm with a
picoMeter, a wireless DSO for your keychain.

If you are more interested in the DDS you can read more about it
on Wikipedia
(https://en.wikipedia.org/wiki/Direct_digital_synthesizer) or any
other website. There's plenty of info out there.

To experiment with signal generation we used Martin Nawrath's


(http://interface.khm.de/index.php/lab/interfaces-
advanced/arduino-dds-sinewave-generator/) code and we
modified it in order to generate dual tone signals. We'll be
generating a signal that results from the addition of 2 sinusoid
waves of different frequency. The resulting signal is very
interesting in shape and looks something like this:

This is the output signal generated with the Arduino PWM filtered with a low pass
filter.

The signal looks pretty much like a DTMF signal, the ones used
by the land line phones to dial a number. So DTMF generation is
one of many direct application of this code.

The mathematical equation of such signal is:

Equation 1. Mathematical expression of a dual tone signal


Wiring
The PWM output from the Arduino needs to be low passed
filtered in order to get rid of the high frequency components
coming from the PWM fast transitions. The schematics for the
low pass filter is very simple and its cut frequency was set to
2.1kHz:

Low pass filter.

Now, more important stuff, how do we play with this? The code
reads two input pins in order to control the frequency of each of
the sine waves. Those pins are the analog 0 and analog 1. We'll
need two potentiometers (10K or 100K pots will both do the job)
and connect them like this:

Connection of the frequency control pins.

By turning the pots you can control the f1 and f2 variables of


Equation 1.

Programming
The code for the Arduino 1 you can find it on the code section.
To extend the work on this area we could always add two
different signal types like a sinusoid with a square signal, or a
square signal with a triangular signal, all kids of different stuff.
The outcome could be anything, and we could create any type
of weird signals.

If you want to change that you just need to create your custom
signal table like the one on sine256[] and run that with the phase
accumulator.

The key line of code where you shape the signal you like is line
127, where the two sign waves are added.

OCR2A=(pgm_read_byte_near(sine256 + icntlow)+pgm_read_byte_near(s
ine256 + icnthigh))>>1;

I invite you to play with this code and track your signals with
picoMeter. (http://pico-meter.com/)

Cheers and good Hacks.

Schematics

Output
filter for
the (https://hacksterio.s3.amazonaws.com/uploads/attachments/263417/screen_shot_20
02-20_at_11_14_25_am_QTOwLSQTcq.png)
Arduino
1.

Input
potentiometers
(https://hacksterio.s3.amazonaws.com/uploads/attachments/263426/scree
02-20_at_11_29_15_am_hSb9SxvmR4.png)
for frequency
selection.

Code

Arduino Code for dual tone


DDS Arduino (/code_files/98416/download)
Credits
pokitMeter (/pokitmeter)
1 project • 6 followers
(/pokitmeter) Pokit is the world’s smallest wireless multimeter and DSO. A tool
you can take anywhere. Find interesting posts about tech
projects here.

Follow

Contact (/users/sign_up?
redirect_to=%2Fmessages%2Fnew%3Frecipient_id%3D163551&source=user_contact)

Comments
Please log in or sign up to comment.

(/ion-guffelkostas) Ion Guffelkostas (/ion-guffelkostas)


a year ago

Hello pokitMeter,
I would be glad if you could answer a few questions about your project,
because I wanted to test it on my Arduino once.
1.)
To save myself the manual entry of 255 sine values into an array, I tried
to do this with the following code:
-----------------------------------------------------------------------------------------------
#include <math.h>
#include <avr/pgmspace.h>
int sinusArray[] = {};

for (int i = 0; i < 255; i++)


{
const int sinusArray[i] PROGMEM = {sin((2PIi)/255)};
}
-----------------------------------------------------------------------------------------------
As you expect, this does not work for several reasons:
You can not change const variables, but variables in flash memory must
be const type.
You can not release or write to flash memory from a running program,
but a for loop can only be used in a running program.

What are the advantages of saving the sine values in flash memory and
not in the RAM or EEPROM ?
Do you know a way to realize what I wanted to do, or the manual entry is
the only possible way ?
2.)
In the comments you make some calculations that I can not understand:
In line 33, you name a "measured" PWM-clock of 31376.6 Hz, but how did
you measure it?

In line 114, you give a calculated value of 31472.55 Hz for the same
measure, I assume you calculated it with the formula f (PWM) = f (clk) / (N
* 510) from the Atmega8 user manual.
I have read the whole section in the user manual about the phase
correct PWM mode, but there is no reference to the value 510 or where it
came from. How does this value of 510 come about?

In line 117 you call a runtime of 8 milliseconds. Where did you get this
value from?
I did not find anything about runtime computation in the User Guide.

3.)
In line 73, you use an infinite loop (while (1) {}) in the "voidLoop () {}"
method. I'm surprised, because I thought so far that the "voidLoop () {}"
method itself is already an endless loop.
4.)
In lines 123 and 127 you move the value of the variable "phacculow" and
"phaccuhigh" by 24 digits to the right. I do not understand why you are
doing this, because the variable gets a completely different value then.
5.)
From line 131 to 134, you use the following code:
-----------------------------------------------------------------------------------------------
if(icnt1++ == 125) { // increment variable c4ms all 4 milliseconds
c4ms++;
icnt1=0;
}
-----------------------------------------------------------------------------------------------
I do not quite understand what this code is for.
At first I thought it was needed to reset the timer or interrupt, but I
actually thought that these would be reset automatically after reaching
the count value in the timer register, since the timer is in overflow mode.
Furthermore, I do not understand how you have calculated the values
used (125 and 4 milliseconds)
used (125 and 4 milliseconds).
Is the 4 milliseconds halfway through 8 milliseconds?
Are the 125 almost half the cycle time for the array with the 254 sine
values?
Furthermore, I am irritated that the varialbe "icnt1" appears here only
once if it is incremented and set to 0, but nowhere else in the program
code.

I apologize for the long text, it would help me if you answered only one
of the questions.

Sincerely,
Ion

More cool stuff Legal thingies About us


Community members Terms of Service (/terms) Hackster's story (/about)
(/community) Code of Conduct (/conduct) Our 2016 Maker Survey
Other community hubs Privacy Policy (/privacy) (/survey)
(/channels/communities) Cookie Policy (/cookies) Hackster for Business
Hardware Weekend (/business)
(/hardwareweekend) Support Center
(http://help.hackster.io)
Visit our Avnet family Brand Resources (/branding)
Avnet (https://www.avnet.com) Developer API
Dragon Innovation (https://hacksterio.api-
(https://www.dragoninnovation.com) docs.io/2.0)
Element14 Sitemap (/sitemap.xml.html)
We're fairly social people
(https://www.element14.com)
Maker Source  Facebook
(https://www.makersource.io) (https://www.facebook.com/hacksterio)
Newark  Instagram
(http://www.newark.com) (https://www.instagram.com/hacksterio)
 LinkedIn
(https://www.linkedin.com/company/hacksterio)
 Twitter
(https://www.twitter.com/hacksterio)
 YouTube
(https://www.youtube.com/hacksterio)
Hackster.io, an Avnet Community © 2019

You might also like