Project tutorial

Signal Generator with Arduino Using DDS and Pico © GPL3+

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

• 11,973 views
• 1 comment
• 12 respects

Components and supplies

 picoMeter DSO
×1
 Arduino UNO & Genuino UNO
×1
 Rotary potentiometer (generic)
×1

Apps and online services

 Arduino IDE

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 or any other website. There's plenty of info out there.

To experiment with signal generation we used Martin Nawrath's 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:

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:

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:

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:

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(sine256 + icnthigh))>>1;
``````

I invite you to play with this code and track your signals with picoMeter.

Cheers and good Hacks.

Code

Arduino Code for dual tone DDSArduino
```/*
*
* DDS Sine Generator mit ATMEGS 168
* Timer2 generates the  31250 KHz Clock Interrupt
*
* KHM 2009 /  Martin Nawrath
* Kunsthochschule fuer Medien Koeln
* Academy of Media Arts Cologne

*/

#include "avr/pgmspace.h"

// table of 256 sine values / one sine period / stored in flash memory
PROGMEM  prog_uchar sine256[]  = {
127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124

};
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

int ledPin = 13;                 // LED pin 7
int testPin = 7;
int t2Pin = 6;
byte bb;

double dfreqlow;
double dfreqhigh;
// const double refclk=31372.549;  // =16MHz / 510
const double refclk=31376.6;      // measured

// variables used inside interrupt service declared as voilatile

volatile byte icnt1;             // var inside interrupt
volatile byte c4ms;              // counter incremented all 4ms
volatile byte icntlow;              // var inside interrupt
volatile unsigned long phacculow;   // pahse accumulator
volatile unsigned long tword_mlow;  // dds tuning word m

volatile byte icnthigh;              // var inside interrupt
volatile unsigned long phaccuhigh;   // pahse accumulator
volatile unsigned long tword_mhigh;  // dds tuning word m

void setup()
{
pinMode(ledPin, OUTPUT);      // sets the digital pin as output
Serial.begin(115200);        // connect to the serial port
Serial.println("DDS Test");

pinMode(6, OUTPUT);      // sets the digital pin as output
pinMode(7, OUTPUT);      // sets the digital pin as output
pinMode(11, OUTPUT);     // pin11= PWM  output / frequency output

Setup_timer2();

// disable interrupts to avoid timing distortion
cbi (TIMSK0,TOIE0);              // disable Timer0 !!! delay() is now not available
sbi (TIMSK2,TOIE2);              // enable Timer2 Interrupt

dfreqlow=1000.0;                    // initial output frequency = 1000.o Hz
dfreqhigh=1100.0;                    // initial output frequency = 1000.o Hz
tword_mlow=pow(2,32)*dfreqlow/refclk;  // calulate DDS new tuning word
tword_mhigh=pow(2,32)*dfreqhigh/refclk;  // calulate DDS new tuning word

}

void loop()
{
while(1) {

if (c4ms > 250) {                 // timer / wait fou a full second
c4ms=0;

cbi (TIMSK2,TOIE2);              // disble Timer2 Interrupt
tword_mlow=pow(2,32)*dfreqlow/refclk;  // calulate DDS new tuning word
tword_mhigh=pow(2,32)*dfreqhigh/refclk;  // calulate DDS new tuning word
sbi (TIMSK2,TOIE2);              // enable Timer2 Interrupt

Serial.print(dfreqlow);
Serial.print("  ");

}

sbi(PORTD,6); // Test / set PORTD,7 high to observe timing with a scope
cbi(PORTD,6); // Test /reset PORTD,7 high to observe timing with a scope
}
}
//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM,  16000000/510 = 31372.55 Hz clock
void Setup_timer2() {

// Timer2 Clock Prescaler to : 1
sbi (TCCR2B, CS20);
cbi (TCCR2B, CS21);
cbi (TCCR2B, CS22);

// Timer2 PWM Mode set to Phase Correct PWM
cbi (TCCR2A, COM2A0);  // clear Compare Match
sbi (TCCR2A, COM2A1);

sbi (TCCR2A, WGM20);  // Mode 1  / Phase Correct PWM
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}

//******************************************************************
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect) {

sbi(PORTD,7);          // Test / set PORTD,7 high to observe timing with a oscope

phacculow=phacculow+tword_mlow; // soft DDS, phase accu with 32 bits
icntlow=phacculow >> 24;     // use upper 8 bits for phase accu as frequency information
// read value fron ROM sine table and send to PWM DAC

phaccuhigh=phaccuhigh+tword_mhigh; // soft DDS, phase accu with 32 bits
icnthigh=phaccuhigh >> 24;     // use upper 8 bits for phase accu as frequency information
// read value fron ROM sine table and send to PWM DAC

if(icnt1++ == 125) {  // increment variable c4ms all 4 milliseconds
c4ms++;
icnt1=0;
}

cbi(PORTD,7);            // reset PORTD,7
}
```

Schematics

• 1 project
• 6 followers

Published on

February 20, 2017

Members who respect this project

and 5 others

See similar projects
you might like

A Tone Generator With LCD Display!

Project tutorial by cronenborg

• 4,397 views
• 12 respects

Arduino Oscilliscope

Project tutorial by Seth Proaps

• 3,284 views
• 1 comment
• 7 respects

Random Number Generator with 8x8 LED Matrix and Arduino

Project tutorial by LAGSILVA

• 2,153 views
• 13 respects

• 30,865 views
• 105 respects

Arduino Due Arbitrary Waveform Generator

Project tutorial by BruceEvans

• 11,731 views
• 26 respects

by Ameduino

• 6,906 views