Igår började jag kolla lite närmare. Bristande arbetslust? Om man baserar den på en STM32F4 Discovery kan man komma undan med det kortet, en skaplig quad OP, spänningsmatning och lite krafs runtomkring. Mina önskemål är i första hand 0,1..20kHz sinus som helst ska orka driva en koax med 10V P-P. Liten drift är viktigare än absolut noggrannhet eftersom jag lätt kan kalibrera den. Den är tänkt att ingå i produktionstest av ett övervakningssystem för vibrationer.
Det klassiska sättet att skapa en sinus i en DDS är med en "look up table", LUT. Effektivt, billigt, bra. Och trist. När jag läste om DDS (eller egentligen NCO) på Wikipedia såg jag en länk till en polsk artikel om att använda taylorserier istället. http://mechatronika.polsl.pl/owd/pdf2009/030.pdf Då triggade mitt minne från åttiotalet och jag kollade upp maclaurinserier som fascinerade mig på universitetet. Idag skrev jag ett litet testprogram för att se hur bra det skulle fungera istf LUT och kom fram till att det definitivt är en rimlig lösning. I alla fall om man har en 168MHz Cortex-M4 "under huven".
Sju multiplikationer, fyra additioner/subtraktioner och två jämförelser per sample. En bagatell med den "DSP-funktionalitet" som finns i processorn. Sedan DMA för att i lugn och ro skyffla data till DAC.
Hur bra blir resultatet för beräkning av sinus då? Se bilden som visar absoluta felet. Duger det inte så lägg till två multiplikationer och en addition så blir det, om jag minns rätt, åtminstone en faktor 10 bättre. Till ingen nytta om man har en 12 bits DAC.

Kod: Markera allt
/* Mclaurin series 2015-12-30 */
#include <math.h>
#include <stdio.h>
double mlsin(double x);
int main(int argc, char **argv)
{
double fi, mls, s;
fi = -M_PI;
while (fi <= M_PI) {
mls = mlsin(fi);
s = sin(fi);
printf("%.8f\t%.8f\t%.8f\t%.8f\n", fi, mls, s, mls - s);
fi += (M_PI / 18000);
}
return 0;
} /* main */
double mlsin(double x)
{
double xx, p, ret;
if (x < 0.0) {
if (x < -M_PI_2) {
x = -M_PI - x;
}
} else {
if (M_PI_2 < x) {
x = M_PI - x;
}
}
xx = x * x;
p = x;
ret = p;
p *= xx;
ret -= (p * (1.0 / 6.0));
p *= xx;
ret += (p * (1.0 / 120.0));
p *= xx;
ret -= (p * (1.0 / 5040.0));
#if 0
p *= xx;
ret += (p * (1.0 / 362880.0));
#endif
return ret;
} /* mlsin */