DAC in Audio Codec Shield

Re: DAC in Audio Codec Shield

Postby guest » Sun Sep 23, 2012 12:57 pm

answers to your points above:

0. in needs to go to L_IN, at the solder pad, which is what it looks like you have. this bypasses the analog high-pass filter. you also need to set ADCHPD 1 in the code, which the example above does. this shuts off the digital high-pass filter on the codec.

1. with the code above, you no longer use loop(), so this shouldnt be a problem. the ISR is called automatically, at a rate set by SAMPLE_RATE. i would reccomend setting SAMPLE_RATE to the lowest value you can get away with. this will give you maximum processing time.

2. the codec on the shield can theoretically go to 24bit, but the noise level in the codec isnt much better than 16b, and your signal will probably not be any better than that as well, so to go to 24b would just make things more complicated for very little gain. also, the codecshield library isnt setup to handle 24b numbers. so some new functions would need to be written.

1. the values are int because they are 16b signed numbers coming out of the codec. that is how the codec produces the data

2. the ADC that is being referred to in the read_me is on the arduino, not the codec. so the arduino ADC is limited to 10b, but the codec ADC is 16b.

3. i would reccomend using the interrupt, as it will keep the timing better, give more processing time, and you wont have to worry if your variables are getting clobbered during the interrupt. the interrupt is required for the codec to operate. if you need to do some things in the main loop, let me know, and i can help with that. it is a bit complicated, as you need to declare some variables volatile, and then disable interrupts while certain variables are being altered. its a bit of a pain, and should be avoided.
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: DAC in Audio Codec Shield

Postby vickyjungade » Wed Sep 26, 2012 6:24 am

So we tried the library for PID by Brett Beauregard available at http://www.arduino.cc/playground/Code/PIDLibrary

Here's the code:

Code: Select all
/*
dc_controller.pde
guest openmusiclabs 9.23.12
this takes in a dc value from the codecshield, processes it, and
sends out a dc value on the codecshield.
*/


// setup codec parameters
// must be done before #includes
// see readme file in libraries folder for explanations
#define SAMPLE_RATE 88 // 44.1Khz
#define ADCS 0 // no ADCs are being used
#define ADCHPD 1 // set the codecshield to DC input

// include necessary libraries
#include <Wire.h>
#include <SPI.h>
#include <AudioCodec.h>

// create data variables for audio transfer
int left_in = 0x0000;
int left_out = 0x0000;
int right_in = 0x0000;
int right_out = 0x0000;
int last_value = 0;
int difference = 0;
int integral = 0;
int position = 0;

// so much for audio codec

// now for PID
/********************************************************
 * PID Basic Example
 ********************************************************/

#include <PID_v1.h>

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
// so much for PID

// Program variables
boolean flip = true;

void setup() {
  AudioCodec_init(); // setup codec registers
  // call this last if setting up other parts
  Serial.begin(9600);
 
  Setpoint = 12000;
 
    //turn the PID on
  myPID.SetMode(AUTOMATIC);
 
  pinMode(2, OUTPUT);
}

void loop() {
  while (1); // reduces clock jitter
 /*
  Serial.print("Input = " );                       
  Serial.print(left_in);     
  Serial.print("\t Output = ");     
  Serial.println(left_out);
  delay(3000);
  */
}

// timer1 interrupt routine - all data processed here
ISR(TIMER1_COMPA_vect, ISR_NAKED) { // dont store any registers
   
  // &'s are necessary on data_in variables
 
  AudioCodec_data(&left_in, &right_in, left_out, right_out);
 
  difference = left_in - last_value; // create a difference signal
  position = left_in; // create a position signal
  integral +=  left_in; // create an integral signal
  last_value = left_in; // backup the last value
  // do the math here for pid
  Input = -left_in;
  myPID.Compute();
  left_out = Output;
  flip = !flip;
  digitalWrite(2, flip);
 
 
  // dont forget to return from interrupt
  reti();
}



To use the code above you have to place PID_v1 folder (from the url above) into the Arduino\Libraries directory

We flipped a digital out every time we run our code to read/write and compute as above in the ISR.
What we discovered on pin 2 is that we get a frequency of 14KHz only! If we comment the whole code in ISR so that the only thing the ISR does is flip the DO, then we get a frequency of 43.86KHz

We wish to have better PID bandwidth (PID bandwidth is the rate at which you can correct the control value once you read the process variable). Right now it is 14KHz, how to improve it? Changes to #define SAMPLE_RATE 88 // 44.1Khz does not make any difference.

Is there anyway you can do it? We have to change the PID later to include more complex algorithm, so faster the merrier!
vickyjungade
 
Posts: 6
Joined: Tue Sep 18, 2012 3:33 am
Location: Dombivli, Mumbai, Maharashtra, India

Re: DAC in Audio Codec Shield

Postby guest » Wed Sep 26, 2012 9:52 am

digitalwrite() takes a really long time.

in setup() put this line:
DDRD |= 0x4; // sets pin2 to output

then replace digitalwrite with:
PORTD = (PORTD & 0x04) ^ PORTD; // toggles pin2
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: DAC in Audio Codec Shield

Postby vickyjungade » Mon Oct 01, 2012 8:44 am

Hey thanks so far.

We have combined Audio Codec & PID & are facing an issue.

Whenever we run the code the output is calculated as 0 no matter what!

However, if we comment out Audiocodecinit() (in void setup) & Audiocodecdata() (in ISR) then our pid calculates output values correctly i.e. it starts from 0 and increases till max output limits (we've given hardcoded input value for experimenting)

If we uncomment Audiocodecinit() (in void setup) & Audiocodecdata() (in ISR) then our pid calculates wrong output values i.e. output value = 0

Code: Select all
/*
dc_controller.pde
guest openmusiclabs 9.23.12
this takes in a dc value from the codecshield, processes it, and
sends out a dc value on the codecshield.
*/

// setup codec parameters
// must be done before #includes
// see readme file in libraries folder for explanations
#define SAMPLE_RATE 88 // 44.1Khz
#define ADCS 2 // no ADCs are being used
#define ADCHPD 1 // set the codecshield to DC input

// include necessary libraries
#include <Wire.h>
#include <SPI.h>
#include <AudioCodec.h>

// create data variables for audio transfer
int left_in;// = 0x0000;
int left_out;// = 0x0000;
int right_in;// = 0x0000;
int right_out;// = 0x0000;

//TEMP Serial Buffer
String SerialBuffer, temp;
char *buffer;
char TempSerial[39];
int si;

// so much for audio codec

// now for PID


#include <PID_v1.h>

//Define the aggressive and conservative Tuning Parameters
double aggKp=4, aggKi=0.2, aggKd=1;
double consKp=2, consKi=5, consKd=1;
double gap;
double Setpoint, Input, Output, Temp = 0.0;


//Specify the links and initial tuning parameters
//PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);


void setup() {
  Serial.begin(115200);
  AudioCodec_init();
  Setpoint = 50000;
  myPID.SetMode(AUTOMATIC);
  //myPID.SetSampleTime(1000);
  myPID.SetOutputLimits(0, 65535);
  //myPID.SetTunings(consKp, consKi, consKd);
}

void loop() {
  //Input = 32768 + left_in;
  Input = 45000; //32768 - left_in;

  //Input = 5.0; //left_in;
  myPID.Compute();
  Serial.println(Output);
  /*
  left_out = Output;
  if(Serial.available() > 38) {
    for(si=0; si<40; si++){
      TempSerial[si] = Serial.read();
    }
   
    Serial.flush();   
    SerialBuffer = TempSerial;
   
      if (SerialBuffer.startsWith("START ") || SerialBuffer.endsWith(" END")) {
        temp = SerialBuffer.substring(6,9);
        buffer = &temp[0];
        consKi = strtod (buffer, NULL);
        temp = SerialBuffer.substring(10,13);
        buffer = &temp[0];
        consKp = strtod (buffer, NULL);
        temp = SerialBuffer.substring(14,17);
        buffer = &temp[0];
        consKd = strtod (buffer, NULL);
        temp = SerialBuffer.substring(18,21);
        buffer = &temp[0];
        aggKi = strtod (buffer, NULL);
        temp = SerialBuffer.substring(22,25);
        buffer = &temp[0];
        aggKp = strtod (buffer, NULL);
        temp = SerialBuffer.substring(26,29);
        buffer = &temp[0];
        aggKd = strtod (buffer, NULL);
        temp = SerialBuffer.substring(30,35);
        buffer = &temp[0];
        Setpoint = strtod (buffer, NULL);
        Serial.println("OUTPUT");
     }
      else {
        Serial.println("Err1");
      }

  }

  /*
  gap = abs(Setpoint-Input); //distance away from setpoint
 
  if(gap<10)
  {  //we're close to setpoint, use conservative tuning parameters
    myPID.SetTunings(consKp, consKi, consKd);
  }
  else
  {
     //we're far from setpoint, use aggressive tuning parameters
     myPID.SetTunings(aggKp, aggKi, aggKd);
  }

 //AudioCodec_data(&left_in, &right_in, left_out, right_out);
 Serial.print("Input   : ");
 Serial.print(Input);
 Serial.print(" Output   : ");
 Serial.println(Output);
 delay(300);
     */
}

ISR(TIMER1_COMPA_vect) {
  //AudioCodec_data(&left_in, &right_in, left_out, right_out);
  //Input = left_in*3.3/32767;
  //myPID.Compute();
  //left_out = Output;

}



Any thoughts why?
vickyjungade
 
Posts: 6
Joined: Tue Sep 18, 2012 3:33 am
Location: Dombivli, Mumbai, Maharashtra, India

Re: DAC in Audio Codec Shield

Postby guest » Mon Oct 01, 2012 12:06 pm

audiocodec_init() kills the delay timer. the codec needs to be run at a very consistent timing interval, or it stops sending data, and the delay timer messes with this. so you cant use delay(). this is also why audiocodec_data() needs to be in the ISR. another thing, is that variables altered in the ISR need to be declared as "volatile", otherwise the compiler doesnt know its being changed. this is probably the main thing thats causing trouble.
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: DAC in Audio Codec Shield

Postby vickyjungade » Tue Oct 02, 2012 11:17 pm

Consider this code:

Code: Select all
#define SAMPLE_RATE 88
#define ADCS 2
#define ADCHPD 1
#include <Wire.h>
#include <SPI.h>
#include <AudioCodec.h>
#include <PID_v1.h>
int left_in;
int left_out;
int right_in;
int right_out;
double Setpoint, Input, Output, Temp = 0.0;
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);

void setup() {
  Serial.begin(115200);
  AudioCodec_init();
  Setpoint = 50000;
  myPID.SetMode(AUTOMATIC);
  myPID.SetOutputLimits(0, 65535);
}

void loop() {
  Input = 45000;
  myPID.Compute();
  Serial.println(Output);
}

ISR(TIMER1_COMPA_vect) {
}



Still the output is given as zero as the line AudioCodec_init(); is present in setup. Commenting this line solves the problem.

May we request your big help in this?
vickyjungade
 
Posts: 6
Joined: Tue Sep 18, 2012 3:33 am
Location: Dombivli, Mumbai, Maharashtra, India

Re: DAC in Audio Codec Shield

Postby guest » Wed Oct 03, 2012 2:40 pm

the PID library uses the millis() counter, which requires timer0 interrupt, which audiocodec_init() disables. to re-enable the interrupt, type the following after audiocodec_init():

TIMSK0 = 0x01;

i read through the PID library, and i dont think it will be able to execute very fast. this is the code from the header file:

Code: Select all
void PID::Compute()
{
   if(!inAuto) return;
   unsigned long now = millis();
   unsigned long timeChange = (now - lastTime);
   if(timeChange>=SampleTime)
   {
      /*Compute all the working error variables*/
     double input = *myInput;
      double error = *mySetpoint - input;
      ITerm+= (ki * error);
      if(ITerm > outMax) ITerm= outMax;
      else if(ITerm < outMin) ITerm= outMin;
      double dInput = (input - lastInput);
 
      /*Compute PID Output*/
      double output = kp * error + ITerm- kd * dInput;
     
     if(output > outMax) output = outMax;
      else if(output < outMin) output = outMin;
     *myOutput = output;
    
      /*Remember some variables for next time*/
      lastInput = input;
      lastTime = now;
   }
}


first off, its operating on doubles, which take more time than ints. secondly, its checking time at each pass, which is redundant since there is already a steady clock from the codec.
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: DAC in Audio Codec Shield

Postby liner » Wed May 14, 2014 6:02 am

Hi,

I would like to use the ADC on the board and also the DAC, similarly to what has been here reported. The problem that I am facing is that I am not able to read signals from 0 to 3.3 V but rather from 250 mV to 3V. Any ideas why? and how to solve this?
I do not see why I can't read signals below 250mV if the resolution should be more than enough (16 bits)

Thanks for your time.
liner
 
Posts: 6
Joined: Fri Jun 29, 2012 2:11 am

Re: DAC in Audio Codec Shield

Postby guest » Wed May 14, 2014 4:10 pm

interesting. ive never measured the actual DC input range of the DAC or ADC. it might be that the internal opamps are not rail-to-rail, so those last values are truncated. it might be possible to reduce your input signal, so that a 0-3.3V signal gets shrunk to 1v-2.5v or so, and therefore fits in the range.

what is your test setup? how are you applying the singal, measuring the input voltage, and measuring the output values?
guest
Site Admin
 
Posts: 449
Joined: Thu May 20, 2010 11:58 pm

Re: DAC in Audio Codec Shield

Postby liner » Thu May 15, 2014 1:42 am

Hi,

Thanks for your answer. Do you have any suggestions in doing that shrink on my input signal?

In a summary, I would like to have an analogue input, read it and according to it adjust the output signal from the DAC. So, what I have done so far is to read the analog signal using the IN pins provided by the Audio Codec Shield and if the voltage is below 250 mV the read value is always the same. Only when going above 250 mV it starts to change.
liner
 
Posts: 6
Joined: Fri Jun 29, 2012 2:11 am

PreviousNext

Return to Audio Codec Shield

Who is online

Users browsing this forum: Bing [Bot] and 0 guests


cron