Analog OP, A14

Status
Not open for further replies.

gregn

New member
Hello all.

I'm new here. I just got my first Teensy board (Teensy 3.6). I have been playing around with Arduino for a while now, but I recently got a project that I needed something that was faster.... which is giving me some troubles...

I want to sample a signal (500Hz to 9KHz), calculate the frequency with an FFT and then output a voltage proportional to the frequency.

I found some FFT routines from a website in Norway... I think it's Norway... (https://www.norwegiancreations.com/2017/08/what-is-fft-and-how-can-you-implement-it-on-an-arduino/) and it works very well... it takes a single tone and outputs the frequency.

My problem is that I'm not getting the voltage to change at all with the frequency. I have wired a single pole filter on the output to 'smooth' the PWM to a DC signal... but.. I'm not getting any change in voltage...

I'm sure it's some totally newb thing that I'm missing... If anybody has any ideas, I'd really appreciate it...

Here's my source code;

Code:
#include "arduinoFFT.h"
 
#define SAMPLES 128             //Must be a power of 2
#define SAMPLING_FREQUENCY 20000 //Hz, must be less than 10000 due to ADC


 // setup the variables
arduinoFFT FFT = arduinoFFT();
 
unsigned int sampling_period_us;
unsigned long microseconds;
 
double vReal[SAMPLES];
double vImag[SAMPLES];
unsigned int pwm_op;
int cnt = 0;
int state = 0;

int analogBits = 1350;

// set up the board
void setup() {
    Serial.begin(115200);
 
    sampling_period_us = round(1000000*(1.0/SAMPLING_FREQUENCY));
    //set up the board LED to show that it's running
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, LOW);

    // set resolution to 12 bytes
    analogWriteResolution(12);
}
 
void loop() {
    cnt++;
    if (cnt>100)        // toggle LED every 100 samples to show it's running
    {
      cnt=0;
      if (state==0){
        state=1;
      }
      else{
        state=0;
      }
      digitalWrite(LED_BUILTIN, state);
    }
    else{               // otherwise, just grab a new sample.
      for(int i=0; i<SAMPLES; i++){
          microseconds = micros();    //Overflows after around 70 minutes!
     
          vReal[i] = analogRead(0);
          //vImag[i] = analogRead(1);
          vImag[i] = 0;
      
          while(micros() < (microseconds + sampling_period_us)){
          }
      }
      // FFT -- get dominant frequency
      FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
      FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
      FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
      double peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);
 
      //map freq
      pwm_op = map(peak,0,9000,0,4095);

      //dump to monitor for plotting/viewing
      Serial.println(pwm_op);

      // set A14 to voltage
      analogWrite(A14,pwm_op);          // write to A14
  
      delay(10);        //Repeat the process every .01 seconds OR:
      //while(1);       //Run code once
    }
}
 
OMG Thank you SOOO Much!!

A14 is the DAC on Teensy 3.2, but for T3.6, DACs are located on A21 and A22. With DAC you don't need to worry about filtering PWM to voltage

The teensy audio library has FFT's and methods for identifying frequencies,
https://www.pjrc.com/teensy/td_libs_Audio.html

Switched to pin 21 and BINGO!! Works like a charm. I have been messing around with this for 2 weeks. Fantastic!!

Thanks so much for the insight!!

Greg
 
Status
Not open for further replies.
Back
Top