Go Down

Topic: Stumped with a DAC (Read 724 times) previous topic - next topic

jrod1992

This is more of a cry for help than a specific problem. I'm an intern for a company out in New Mexico. My mentor and I have run into some difficulties with a particular component. I've been working on interfacing with a TLV5636 DAC (http://www.ti.com/lit/ds/symlink/tlv5636.pdf <--Datasheet) using the SPI ports on the Arduino. We were able to successfully interact with the device using a Diolan board, but when we tried to switch to an Arduino to automate the recording of the output process, we've found it won't work despite our best effort. Right now, we have a pulse generator to the FS pin on the component to enable the conversion process, since the digitalWrite was producing a lot of noise. The Vref is set at a steady 2 V, through a voltage divider stemming from the 5 V source provided by the board. A wire connects from the output pin of the DAC to an analog pin on the Arduino in order for the computer to read back what was sent out. No matter what we output digitally however, the result is always 0 V. We've checked all the inputs and voltages on an oscilloscope and they all seem to check out. The Pulse generator pulses, which breaks from both of the for loops, the clock and data is turned on from the computer, the clock extends a few cycles beyond the data stream to make sure the DAC processes enough cycles, and the voltages at Vcc and Vref are 5 V and 2 V respectively. I'm not sure whether I need to connect the AREF and GND digital pins so that could be part of the problem, but we've tried it with them connected and them disconnected so I was thinking that wasn't the issue. Basically, I'm wondering if there were any gross errors with my code or if anyone has any experience with DAC's to know of a trick that I need to do in order to get this thing running. Any advice would be greatly appreciated. Thank you.
Code: [Select]

#include <SPI.h>

const int IO = 3;
const int Analog = A0;
const int Init = A2;
const int Knit = A3;
const int size = 4096;
int Initializer = 50;
double Volts = 0;
word outputValue = 0;
byte data = 0;


void setup() {
  //set pins to output because they are addressed in the main loop
  pinMode(IO, OUTPUT);
  pinMode(Analog, INPUT);
  pinMode(Init, INPUT);
  pinMode(Knit, INPUT);
  pinMode(10, OUTPUT);
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV64);
  SPI.setDataMode(SPI_MODE3);
  Serial.begin(1200);
}

void loop() {
  //count up routine
  digitalWrite(10, LOW);
  for(int j = 0; j < 1000000; ++j){
      int Jnitializer = analogRead(Init);
      if( j > 0 && Jnitializer > 500){
         break;
      }
    }
    for(int l = 0; l < 1000000; ++l){
      int Lnitializer = analogRead(Knit);
      if( l > 0 && Lnitializer < 100){
         break;
      }
    }
   
    outputValue = 4095;
    data = highByte(outputValue);
    SPI.transfer(data);
    data = lowByte(outputValue);
    SPI.transfer(data);
    SPI.transfer(0);
    delay(100);
    Volts =  analogRead(Analog); //* VoltConversion;
    Serial.println(outputValue);
    Serial.println(Volts, 4);
    digitalWrite(10, HIGH);
  //}
SPI.end();
}

CrossRoads

You are not controlling the DAC chip select.

digitalWrite (CS,LOW);
SPI.transfer (highByte, outputValue);
SPI.transfer (lowByte, outputValue);
digitalWriteI (CS, HIGH);

take out the SPI.end statement. You only use that if you want to stop all SPI capability & use the pins for something else.
SCK must be on D13, MOSI on D11, they do not get declared, SPI.begin takes care of that.
D10 should be used for the CS and needs to be declared as an output:
byte CS =10;
then in setup:
pinMode (CS, OUTPUT);
digitalWrite (CS, HIGH); // turn off COMMs with DAC until needed.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

jrod1992

The CS is in there, but I just used 10 instead of giving it a variable name. I do realize this is fairly sloppy however on my part so I'll make sure to add that in, but I don't think giving it a variable name will impact the results, would it? Thank you for the advice.

CrossRoads

Ok, then  you have too much going on between the CS, LOW and the CS, HIGH.
You have 3 SPI.transfers, am pretty sure the third one (0) wipes out a good part of your data.
Clean it up. Get rid of the SPI.end(), I think that will stop any transfers after the first pass thru loop.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

oric_dan

Quote
we have a pulse generator to the FS pin on the component to enable the conversion process, since the digitalWrite was producing a lot of noise


I've never used that part, but a quick look at the d/s indicates you may not have
the proper timing relationship between CS going low and the FS frame sync pulse
going high.


MarkT

From the datasheet the device is sample on clock trailing/falling edge, which is SPI mode 1, not 3.

You should only send 2 bytes, that's what the datasheet shows, and control the CS line correctly.
[ I won't respond to messages, use the forum please ]

jrod1992

The transfer of the zeroes doesn't register on the DAC, so in essence we're using to keep that clock running longer than it necessarily would with just transferring the data. We're actually going to try and add another transfer of 0's to the front to get the clock running a little longer. The SPI.end() was originally put in to stop the the SPI from continuously sending out data so we could see the results of just one output from the serial monitor, but you're right, it is essentially unnecessary. I made sure to add in the CS low digitalWrite at the beginning of the loop() function and as long as that guy stays low the CS shouldn't that cover it? Along with setting it to output and sending it high at the very end of the loop too of course. I did make sure to get rid of that mode 3 part, I forgot I had that in there despite glancing at it several times, thank you for that.

MarkT

SPI is transaction based - you can't just keep the select line active and send more data, you need to release it HIGH and bring it LOW again to retrigger the device.  Some devices allow multiple transactions to run together, but that will be documented if its allowed.

BTW you don't seem to be sending the right program value bits (the first four bits are not sample values) - see "DATA FORMAT" on page 12 of the datasheet.
[ I won't respond to messages, use the forum please ]

jrod1992

Is the slave device selected when CS is high or low? I was under the impression it was low from what I read, but I could be mistaken.

For those first four bits I'm just allowing the SPI to send out zeroes with the highbyte, which would mean it runs on an external voltage reference, slow mode and normal operation. I'm assuming fast mode and power down would just complicate the process as of right now rather than fixing it.

MarkT


Is the slave device selected when CS is high or low? I was under the impression it was low from what I read, but I could be mistaken.

For those first four bits I'm just allowing the SPI to send out zeroes with the highbyte, which would mean it runs on an external voltage reference, slow mode and normal operation. I'm assuming fast mode and power down would just complicate the process as of right now rather than fixing it.


CS bar is active low, that's what the bar means.  Sometimes you see this written as NCS or CSB (not CS, CS bar).  Chip selects are active low in the SPI "standard".

You should program the control register at startup - the datasheet probably implies it will power up all zeroes, but I'd program it anyway so you are sure it is set up correctly (remember during start up all the SPI pins are floating and any junk might get picked up by the DAC - its often a good idea to add a pull-up resistor on the CS lines to prevent device activation until the microcontroller has initiliazed)  Here its simpler just to program the control register once you've set up the SPI bus.
[ I won't respond to messages, use the forum please ]

jrod1992

Thanks a lot, I'll give both of those a try!

jrod1992

So I went in and redid all the wiring for the CS portion with the resistor in place and I'm actually getting a noticeable increase when I step up the digital input for once. The only issue is the values aren't accurate, as in I plug in 4095 and I'm getting a 423 instead of the intended 1023. I'm assuming this has to do with my Vref portion. Right now I'm doing the attached code for setting the Vref. I have the AREF port on the Arduino board attached to the Vcc part of my DAC. Can anyone confirm or deny that this is correct or if this is even where the issue lies?
Code: [Select]

    data = 0b11010000; 
    SPI.transfer(data); 
    data = 0b00000010;   
    SPI.transfer(data);
   

MarkT

Yes, Vref = 2.048V I think, so outputing a value of 4095 will generate about 2.048V, so the Arduino ADC (with a reference of 5V) will read 1024 * 2.048 / 5.0 = 419.   That's close enough to 423 (the 5V reference for the Arduino is from the regulator or your USB port - not high precision).

Congrats!
[ I won't respond to messages, use the forum please ]

jrod1992

Wow, never thought I'd get this thing working. Thank you all for your help! I can end my internship here a happy man.

oric_dan

And now you're gonna leave all the rest of us in the dark as to what the
problem/solution was!

Go Up