Generate 20-30 kHz sine/cosine wave via DAC port on Arduino Due

For a research project I am doing, I need to generate a 20-30 kHz sin wave through the A0 port of an Arduino Due and cosine wave of the same frequency through the A1 port of the Due. There was an excellent demo post that I found which produced a wave at 5.5 kHz, but I do not know how to modify the code to produce a wave at the frequencies I need.

I'd start with looking up how to get sin() and cosine(). AnalogWrite the values (offset by +127) to get waves centred at 2.5V offset and 0V low 5V high.

So I looked at how to get Sin and Cosine, and from what I could find, it seems that generating a waveform table to reference is a fast and fairly accurate way of creating the needed waveforms.

Here is the code I currently have:

const uint16_t sinTable = {
0x7ff, 0x823, 0x846, 0x86a, 0x88e, 0x8b1, 0x8d5, 0x8f9, 0x91c, 0x93f,
0x963, 0x986, 0x9a9, 0x9cc, 0x9ee, 0xa11, 0xa33, 0xa56, 0xa78, 0xa9a,
0xabb, 0xadd, 0xafe, 0xb1f, 0xb40, 0xb60, 0xb81, 0xba1, 0xbc0, 0xbe0,
0xbff, 0xc1e, 0xc3c, 0xc5a, 0xc78, 0xc95, 0xcb2, 0xccf, 0xcec, 0xd08,
0xd23, 0xd3e, 0xd59, 0xd73, 0xd8d, 0xda7, 0xdc0, 0xdd8, 0xdf1, 0xe08,
0xe1f, 0xe36, 0xe4c, 0xe62, 0xe77, 0xe8c, 0xea0, 0xeb4, 0xec7, 0xeda,
0xeec, 0xefe, 0xf0f, 0xf1f, 0xf2f, 0xf3f, 0xf4d, 0xf5c, 0xf69, 0xf77,
0xf83, 0xf8f, 0xf9a, 0xfa5, 0xfaf, 0xfb9, 0xfc2, 0xfca, 0xfd2, 0xfd9,
0xfdf, 0xfe5, 0xfeb, 0xfef, 0xff3, 0xff7, 0xffa, 0xffc, 0xffd, 0xffe,
0xfff, 0xffe, 0xffd, 0xffc, 0xffa, 0xff7, 0xff3, 0xfef, 0xfeb, 0xfe5,
0xfdf, 0xfd9, 0xfd2, 0xfca, 0xfc2, 0xfb9, 0xfaf, 0xfa5, 0xf9a, 0xf8f,
0xf83, 0xf77, 0xf69, 0xf5c, 0xf4d, 0xf3f, 0xf2f, 0xf1f, 0xf0f, 0xefe,
0xeec, 0xeda, 0xec7, 0xeb4, 0xea0, 0xe8c, 0xe77, 0xe62, 0xe4c, 0xe36,
0xe1f, 0xe08, 0xdf1, 0xdd8, 0xdc0, 0xda7, 0xd8d, 0xd73, 0xd59, 0xd3e,
0xd23, 0xd08, 0xcec, 0xccf, 0xcb2, 0xc95, 0xc78, 0xc5a, 0xc3c, 0xc1e,
0xbff, 0xbe0, 0xbc0, 0xba1, 0xb81, 0xb60, 0xb40, 0xb1f, 0xafe, 0xadd,
0xabb, 0xa9a, 0xa78, 0xa56, 0xa33, 0xa11, 0x9ee, 0x9cc, 0x9a9, 0x986,
0x963, 0x93f, 0x91c, 0x8f9, 0x8d5, 0x8b1, 0x88e, 0x86a, 0x846, 0x823,
0x7ff, 0x7db, 0x7b8, 0x794, 0x770, 0x74d, 0x729, 0x705, 0x6e2, 0x6bf,
0x69b, 0x678, 0x655, 0x632, 0x610, 0x5ed, 0x5cb, 0x5a8, 0x586, 0x564,
0x543, 0x521, 0x500, 0x4df, 0x4be, 0x49e, 0x47d, 0x45d, 0x43e, 0x41e,
0x3ff, 0x3e0, 0x3c2, 0x3a4, 0x386, 0x369, 0x34c, 0x32f, 0x312, 0x2f6,
0x2db, 0x2c0, 0x2a5, 0x28b, 0x271, 0x257, 0x23e, 0x226, 0x20d, 0x1f6,
0x1df, 0x1c8, 0x1b2, 0x19c, 0x187, 0x172, 0x15e, 0x14a, 0x137, 0x124,
0x112, 0x100, 0xef, 0xdf, 0xcf, 0xbf, 0xb1, 0xa2, 0x95, 0x87,
0x7b, 0x6f, 0x64, 0x59, 0x4f, 0x45, 0x3c, 0x34, 0x2c, 0x25,
0x1f, 0x19, 0x13, 0xf, 0xb, 0x7, 0x4, 0x2, 0x1, 0x0,
0x0, 0x0, 0x1, 0x2, 0x4, 0x7, 0xb, 0xf, 0x13, 0x19,
0x1f, 0x25, 0x2c, 0x34, 0x3c, 0x45, 0x4f, 0x59, 0x64, 0x6f,
0x7b, 0x87, 0x95, 0xa2, 0xb1, 0xbf, 0xcf, 0xdf, 0xef, 0x100,
0x112, 0x124, 0x137, 0x14a, 0x15e, 0x172, 0x187, 0x19c, 0x1b2, 0x1c8,
0x1df, 0x1f6, 0x20d, 0x226, 0x23e, 0x257, 0x271, 0x28b, 0x2a5, 0x2c0,
0x2db, 0x2f6, 0x312, 0x32f, 0x34c, 0x369, 0x386, 0x3a4, 0x3c2, 0x3e0,
0x3ff, 0x41e, 0x43e, 0x45d, 0x47d, 0x49e, 0x4be, 0x4df, 0x500, 0x521,
0x543, 0x564, 0x586, 0x5a8, 0x5cb, 0x5ed, 0x610, 0x632, 0x655, 0x678,
0x69b, 0x6bf, 0x6e2, 0x705, 0x729, 0x74d, 0x770, 0x794, 0x7b8, 0x7db,
};

void setup() {
analogWriteResolution(12);
}
void loop() {
int k=90;
for(int i=0; i<360; i++) {
k++;
if(k>= 360) k=0;
analogWrite(DAC1, sinTable*);*
analogWrite(DAC0, sinTable[k]);
delay(1);
}
}
I think this should work to produce the appropriate waveforms, but I just don’t know how to finagle the timing in order to achieve the frequencies I want.
DAC_Sine_Due.ino (2.62 KB)

What kind of research? I have sinewave generator somewhere, have to look if I could modified it for quadrature mode.

Specifically, I'm going to be using this output in conjunction with an amplifier to drive an oscillating magnetic field within a pair of Helmholtz coils.

Fantastic. Hm, can’t insert the code

The message has the following error or errors that must be corrected before continuing:
The message exceeds the maximum allowed length (9000 characters).

Attaching.
Enjoy.

Timer_Dac_Pdc_500k_quadMode_1b.ino (10.1 KB)

Thanks a billion! I'll let you know if I run into any errors.

This is incredibly embarrassing, but I mistakenly wrote kHz instead of Hz :confused: Would this code be able to work in that range of frequencies?

Have you read short intro in the sketch? Code able to generate from 21 Hz to 199 999 Hz. You simply open serial monitor and send nnf, for example "25f" + send button.

About 10 seconds after posting the above comment I re-read realized that it could. Thanks again.

I'm now trying to use the code to generate waves in the 1-20 Hz range, but I'm unsure of how to modify the code to achieve the result I would need. Do you have any suggestions/solutions?

You need to modify this part of code:

      if (in_Byte == 'f') // end delimiter 
      {
//        if ((user_intf > 20) && (user_intf < 200000)) 
        if ((user_intf > 0) && (user_intf < 200000))

I think should be fine starting from 1 Hz.

Thanks a ton!

Hi guys! I am using this code to run a stepper motor with analog sin and cos. Is there an easy way I can change the voltage out of the pins? (now I get +-1V and I would like +-5V) Also, is there a way to increase the current output? I would like to have ~0.2A per pin. I thought about using a transistor and a 1K resistor. Am I missing something?

Thanks a lot! this really helped

llea:
(now I get ±1V and I would like ±5V)

You won’t output a negative voltage from the DAC peripheral without adding some electronic.

For a bipolar output (and input), there is this tutorial:

Magician: Fantastic. Hm, can't insert the code Attaching. Enjoy.

I tried this code. Thanks for the code but when I put it on a scope I got strange results going from 10000f to 10001f

At 10000f everything looks fine on the scope.

Fast Mode = 0 freq_inhz = 10000 freq_intc = 26 approximation = 10096

At 10001f everything looks stair stepped badly. Giant stair steps (like 4)

Fast Mode = 1 freq_inhz = 10001 freq_intc = 262 approximation = 10019

Just thought it was interesting.