Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 3 of 3

Thread: Noise on DAC (A14) output Teensy 3.1.

  1. #1
    Junior Member
    Join Date
    Apr 2014
    Posts
    2

    Question Noise on DAC (A14) output Teensy 3.1.

    First off, I apologize if I am posting this in the wrong location as I am new to the forum.

    I am planning to use the Teensy 3.1 to modulate a VCO tuning pin. Using the default DAC configuration supplied by the library code I was able to provide fairly coarse modulation. This produces a very clean output. At the hardware level, A14 is connected to a 2-pole LC filter with a corner frequency of about 20kHz which then feeds the VCO tuning pin.

    I only need a signal with a DC level up to a few hundred mV and an AC component of around 6mV or so. I thought I would change the DAC reference from DACREF_2 (external AREF at 3.3V) to DACREF_1 which would supply an internally generated 1.2V reference and produce finer DAC step size. This did in fact change the DAC resolution but the odd thing is now there seems to be a significant amount of noise on the DAC output. There are 2 components to the noise. First is a ~6mV sine wave at ~33kHz. The second is a periodic event which appears to be some coupled switching every 3ms. The 6mV noise causes undesirable noise in my spectrum and can't be filtered because it's on the order of what I need to use for modulation. The switching noise could be snubbed with some sort of bandpass filter arrangement but I have not attempted to address this yet. What I am hoping is there is a firmware solution .

    The code is relatively simple. It creates an interval timer that at the moment just toggles a variable state which CAN be, but is currently not, used to create a high or low key for a binary FSK type modulation. The interval time is the modulation rate. Serial is used to change the DC offset for the DAC output and an LED is toggled when each serial DC value is processed. The reference voltage bit(6) in DAC0_C0 is cleared after the library call to analogWrite() so no changes to library code needed to be made. This might be the source of the trouble. See code below.

    Any thoughts would be greatly appreciated.
    Thanks, Mark

    Code:
    #define COUNT_LIM 4096
    
    //Global vars
    int inputValue = 0;             // an int to hold incoming data
    String inputString = "";        // a string to hold incoming data
    boolean valueComplete = false;  // whether the string is complete
    int fskState = LOW;
    
    // Create an IntervalTimer object 
    IntervalTimer myTimer;
    
    void setup()   
    {                
      // Initialize the DAC output pins
      analogWriteResolution(12);
    
      // Setup the Teensy LED as and output
      pinMode(13, OUTPUT);
      
      //Initialize the USB UART serial at 9600 baud with a RX buffer of 10 chars
      Serial.begin(9600);
      inputString.reserve(10);
    
    // 1/8212.28 = 1.217688632146005737748834671979e-4
    //  myTimer.begin(event_timer, 122);  // ~4106 baud
      myTimer.begin(event_timer, 30);     // Trying a higher data rate
    }
    
    // Loop forever
    void loop()                     
    {
      if(Serial.available())
        serialEvent();
        
      if(valueComplete)
      {
        //Toggle the LED
        digitalWrite(13, !digitalRead(13));
           
        // Convert the string to an int
        inputValue = inputString.toInt();
    
        //Limit the input value to 12 bits
        if(inputValue > COUNT_LIM)
          inputValue = COUNT_LIM;
        
        //Send back the new value for confirmation.
        Serial.println(inputValue);
    
        //Clear the flag and received string
        valueComplete = false;
        inputString = "";
      }
    }
    
    // Handle serial reception
    void serialEvent() 
    {
        // get the new byte:
        char inChar = (char)Serial.read();
        inputString += inChar;    
        
        //Build the decimal value of the string
        inputValue += (unsigned int)inChar;
    
        // if the incoming character is a newline, set a flag
        // so the main loop can do something about it:
        if (inChar == '\n') {
          valueComplete = true;
        }
    }
    
    // Generates the modulation clock
    void event_timer(void) 
    {
      if (fskState == LOW) 
      {
        fskState = HIGH;
      } 
      else 
      {
        fskState = LOW;
      }
    //  analogWrite(A14, inputValue + (fskState));
      analogWrite(A14, inputValue);
      DAC0_C0 &= 0b10111111;  //uses 1.2V reference for DAC instead of 3.3V
    }

  2. #2
    Junior Member
    Join Date
    Apr 2014
    Posts
    2
    So in writing the previous post I got a hint as to what was happening. After a little review of the LIB code and rewriting of my code it works much better. in setup() I initialize the DAC as before by setting the resolution but now call the lib function to set the initial DAC output which in turn configures the DAC as the lib code intends. I then clear the DACRFS bit just once. Note that the 3*fskState provides the AC voltage component needed to generate the FSK frequency deviation I am after. This will likely be parametrized at some point.

    In setup():
    Code:
    // Initialize the DAC output pins
      analogWriteResolution(12);
      analogWrite(A14, 0);  //Set the DAC output to 0.
      DAC0_C0 &= 0b10111111;  //uses 1.2V reference for DAC instead of 3.3V
    In interval timer ISR:
    Code:
    //analogWrite(A14, inputValue);
      //DAC0_C0 &= 0b10111111;  //uses 1.2V reference for DAC instead of 3.3V
      *(int16_t *)&(DAC0_DAT0L) = inputValue + (fskState * 3); //Assignment borrowed from lib
    And a shot of the final product. Sorry my scope does not have sufficient resolution to show off the tuning waveform but it's pretty boring anyway.
    Click image for larger version. 

Name:	FSK spectrum.jpg 
Views:	194 
Size:	91.8 KB 
ID:	1776

  3. #3
    Senior Member
    Join Date
    Nov 2012
    Location
    Boston, MA, USA
    Posts
    1,106
    Yes, you only want to tell it to use the internal reference once, not each time you output a value. Changing reference triggers a recalibration. I'm not sure though if repeatedly telling it to use the internal reference causes any actual change or is just ignored.

    Incidentally, Serial over USB ignores the baud rate; you get 12Mbits/s. The UARTs are on Serial1, Serial2 and Serial3.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •