Search code examples
maxminarduino-uno

How do I read the max and min value from DDS module in Arduino?


I am currently outputting a sine wave signal using a DDS module that I bought from Amazon. I downloaded a library to run the DDS module using Arduino uno. I want to measure max and min value coming off the DDS at two different frequency. How do I read the max and min in the loop? I get a single value Analog read which is not helpful.

#include <AD9850SPI.h>
#include <SPI.h>

const int W_CLK_PIN = 13;
const int FQ_UD_PIN = 8;
const int RESET_PIN = 9;

double freq = 10000000;
double trimFreq = 124999500;

int phase = 0;

void setup(){
  DDS.begin(W_CLK_PIN, FQ_UD_PIN, RESET_PIN);
  DDS.calibrate(trimFreq);
}

void loop(){
  DDS.setfreq(freq, phase); 
  double num = analogRead(A0);   // Measure max and min ?
  DDS.setfreq(freq + 500, phase);
  double num1 = analogRead(A0);   // Measure max and min ? 

  DDS.down();
}

Solution

  • You should be able to do some extra setup then replace min/max values as needed, something like:

    
    // To store/calc minima/maxima.
    
    double minNum, maxNum, minNum1, maxNum1;
    bool first = true;
    
    void loop(){
        DDS.setfreq(freq, phase); 
        double num = analogRead(A0);
        
        DDS.setfreq(freq + 500, phase);
        double num1 = analogRead(A0);
    
        if (first) {
            // First reading is min/max by definition.
    
            minNum = maxNum = num;
            minNum1 = maxNum1 = num1;
            first = false;
        } else {
            // Otherwise set min/max based on comparisons.
    
            if (num < minNum) minNum = num;
            else if (num > maxNum) maxNum = num;
    
            if (num1 < minNum1) minNum1 = num1;
            else if (num1 > maxNum1) maxNum1 = num1;
        }
    
        // At this point, you have to (up-to-date) min/max for each variable,
        // process it as you see fit.
    
        DDS.down();
    }
    

    If you need to do a lot of samples at each frequency, that's a slightly modified version, which can be done with a state machine in the loop function:

    
    // Samples for each frequency and things for state machine.
    
    #define SAMPLES 10000
    
    #define ST_INIT     0
    #define ST_FREQ_1   1
    #define ST_FREQ_2   2
    #define ST_DONE     3
    
    double minNum, maxNum;
    int samples, state = ST_INIT;
    
    void loop () {
        switch (state) {
        case ST_INIT:
            // Initial setup for state FREQ_1.
    
            samples = SAMPLES;
            DDS.setfreq(freq, phase); 
            minNum = maxNum = analogRead(A0);
            state = ST_FREQ_1;
            break;
        case ST_FREQ_1:
            // Collect samples until done, then output and set up for FREQ_2.
    
            if (--samples < 1) {
                process("Freq # 1", minNum, maxNum);
                samples = SAMPLES;
                DDS.setfreq(freq + 500, phase); 
                minNum = maxNum = analogRead(A0);
                state = ST_FREQ_2;
            } else {
                double num = analogRead(A0);
                if (num < minNum)
                    minNum = num;
                else if (num > maxNum)
                    maxNum = num;
            }
            break;
        }
        case ST_FREQ_2:
            // Collect samples until done, then output and stop.
    
            if (--samples < 1) {
                process("Freq # 2", minNum, maxNum);
                DDS.down();
                state = ST_DONE;
            } else {
                double num = analogRead(A0);
                if (num < minNum)
                    minNum = num;
                else if (num > maxNum)
                    maxNum = num;
            }
            break;
        case ST_DONE:
        default:
            // Infinite looping with no action when all samples collected
            // for both frequencies.
            break;
        }
    }
    

    You just need to add the process(const char *freq, double minVal, double maxVal) function to output results.


    For a more descriptive way of looking at that code, consider that the loop function is simply called continuously by the Arduino processing loop, which is functionally:

    int main() {
        setup();
        while (true) {
            loop();
        }
    }
    

    Also consider that those variable defined outside of loop (and setup) maintain their last-set values on subsequent calls to loop.

    So, the first time loop is called, the state is ST_INIT and it will execute that part of the switch statement. That will:

    • set it up to use the first frequency;
    • initialise the sample count to the desired value;
    • read the first value, assigning that to both minimum and maximum;
    • change the state to ST_FREQ_1; and
    • break, causing eventual exit from the function.

    Subsequent calls to loop have the state ST_FREQ_1 so will execute the second part of the switch. This:

    • decrements the sample count. If that has reached zero, it then:
      • outputs the results of the fist set of samples;
      • sets it up to use the second frequency;
      • initialises the sample count to the desired value;
      • reads the first value, assigning that to both minimum and maximum; and
      • changes the state to ST_FREQ_2.
    • If it hasn't reached zero, it simply reads another sample and adjusts the current min/max based on that.
    • Either way, it then breaks, causing eventual exit from the function.

    Exactly the same thing happens for sampling the second frequency except, at the end, we simply change the state to ST_DONE, and don't have to set up anything for a third frequency ( so we shut down DDS).

    The loop function will continue to be called but, in the final state, it does nothing but return.