#include #include /* Super crude demo of a Delta-Sigma A/D. Just a very quick illustration of how the Delta-Sigma A/D integrator, comparator, and digital filter work together. Don't take too literally! I just did this one day after reading an introduction on these types of converters. */ /* conversion function. arguments are self-explanatory. */ int Convert (double vin, double *vout, int nsamples); /* Basic parameters for the "circuit" and for the test. */ #define VREF (+5.0) #define NSAMPLES (256) #define VINSTEP (0.1) int main () { int nsamples = NSAMPLES; double vout; double vin; double error, maxerror; // Percentage error /* Sweep input voltage from -VREF to +VREF with a conversion every VINSTEP. */ vin = -VREF; printf ("\nVREF is +/- %f with %d samples per conversion", VREF, nsamples); /* We'll keep track of the maximum error. */ maxerror = 0; while (vin < VREF) { Convert (vin, &vout, nsamples); error = fabs (100.0 * (vout - vin)/(2.0*VREF)); if (error > maxerror) maxerror = error; printf ("\nVIN = %f, VOUT = %f, Percent Error = %f precent", vin, vout, error); vin += VINSTEP; } printf ("\nMax Error is %f percent", maxerror); printf ("\n"); } int Convert (double vin, double *vout, int nsamples) { double vref = VREF; double integrator; int comparator; /* e.g. this is the 1-bit A/D */ double dac; /* really just -VREF or +VREF based on comparator */ /* For this trivial demo, just store the "samples" which are the comparator outputs. */ int samples[NSAMPLES]; int i; /* For computing final output. Really would be part of the digital filter. */ double sum, average; /* Initial conditions */ integrator = 0; dac = +vref; /* Sample vin nsamples times. */ for (i = 0; i < nsamples; i++) { /* Update comparator */ if (integrator > 0.0) { comparator = 1; } else { comparator = 0; } /* Update 1-bit DAC */ if (comparator == 1) { dac = +vref; } else { dac = -vref; } /* Update Integrator */ integrator = integrator + vin - dac; /* Store each output of the comparator for filtering later. */ samples[i] = comparator; // printf ("\n%d %f %d %f", i, integrator, comparator, dac); } /* Average all the comparator outputs. This is analogous to the digital filter. For a real converter, the digital filter would be some sort of FIR filter and would run continuously. Could design a simple moving average FIR filter, but really, this is where the math comes in! */ sum = 0.0; for (i = 0; i < nsamples; i++) { sum = sum + samples[i]; } /* Average is really the ratio of 1's to total number of samples. */ average = ((double)sum) / ((double)nsamples); /* Take the average and scale it to the the "span", or range from -VREF to +VREF. */ *vout = (average * 2.0 * vref) - vref; // printf ("\nFinal average over %d samples is %f. Output is %f", nsamples, average, output); return 0; }