Pages: [1]   Go Down
Author Topic: DAC doesn't give quite the right output  (Read 611 times)
0 Members and 1 Guest are viewing this topic.
Northern California (by San Francisco)
Offline Offline
Sr. Member
****
Karma: 3
Posts: 258
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm trying out a TI chip that has 8 8-bit DACs, with the chip number being TLV5628CN. Looking at the datasheet, I thought I could use the SPI commands.

But the following code gives the results that follow in the second code section. The numbers should match, but don't.

Code:

// include the SPI library:
#include <SPI.h>
#define dacInputPin 4

// set pin 9 as the slave select for the DAC:
const int dacSelectPin = 9;
int dacValue;

void setup() {

  // start serial port at 9600 bits per second
  Serial.begin(9600);

  // set the slaveSelectPin as an output:
  pinMode (dacSelectPin, OUTPUT);

  // initialize SPI:
  SPI.begin();

}

void loop() {
    // change the resistance from min to max:
    for (int level = 0; level < 256; level = level + 1) {

      dacWrite(level);
      Serial.print("  ");
      Serial.print(level);
      Serial.print("\t");     

      dacValue = analogRead(dacInputPin)/4;
      Serial.print("  ");
      Serial.print(dacValue);
      Serial.print("\n");     

      delay(10);

    }
 }

int dacWrite(int value) {

  unsigned char commandMask, byteOne, byteTwo; 

  commandMask = 0x0;
  byteOne = commandMask;
  byteTwo = value;
 
  // take the SS pin high to write to the chip:
  digitalWrite(dacSelectPin,HIGH);

  //  send in the value via SPI:
  SPI.transfer(byteOne);
  SPI.transfer(byteTwo);

  // take the SS pin low to write into DAC:
  digitalWrite(dacSelectPin,LOW);
 
  // take the SS pin high to finish the write:
  digitalWrite(dacSelectPin,HIGH);
 
}


Code:
  0   1
  1   4
  2   7
  3   10
  4   13
  5   16
  6   19
  7   22
  8   25
  9   28
  10   31
  11   34
  12   37
  13   40
  14   43
  15   46
  16   49
  17   52
  18   55
  19   58
  20   61
  21   64
  22   67
  23   70
  24   72
  25   75
  26   78
  27   81
  28   84
  29   87
  30   90
  31   93
  32   96
  33   99
  34   102
  35   105
  36   108
  37   111
  38   114
  39   117
  40   120
  41   123
  42   126
  43   129
  44   132
  45   135
  46   138
  47   141
  48   144
  49   147
  50   150
  51   153
  52   156
  53   159
  54   162
  55   165
  56   168
  57   171
  58   174
  59   177
  60   180
  61   183
  62   186
  63   189
  64   192
  65   195
  66   198
  67   201
  68   204
  69   207
  70   210
  71   212
  72   215
  73   219
  74   221
  75   224
  76   227
  77   230
  78   233
  79   236
  80   239
  81   242
  82   245
  83   248
  84   251
  85   254
  86   254
  87   254
  88   254
  89   254
  90   254
  91   254
  92   254
  93   254
  94   254
  95   254
  96   254
  97   254
  98   254
  99   254
  100   254
  101   254
  102   254
  103   254
  104   254
  105   254
  106   254
  107   254
  108   254
  109   254
  110   254
  111   254
  112   254
  113   254
  114   254
  115   254
  116   254
  117   254
  118   254
  119   254
  120   254
  121   254
  122   254
  123   254
  124   254
  125   254
  126   254
  127   254
  128   1
  129   4
  130   7
  131   10
  132   13
  133   16
  134   19
  135   22
  136   25
  137   28
  138   31
  139   34
  140   37
  141   40
  142   43
  143   46
  144   49
  145   52
  146   55
  147   58
  148   61
  149   64
  150   67
  151   70
  152   72
  153   75
  154   78
  155   81
  156   84
  157   87
  158   90
  159   93
  160   96
  161   99
  162   102
  163   105
  164   108
  165   111
  166   114
  167   117
  168   120
  169   123
  170   126
  171   129
  172   132
  173   135
  174   138
  175   141
  176   144
  177   147
  178   150
  179   153
  180   156
  181   159
  182   162
  183   165
  184   168
  185   171
  186   174
  187   177
  188   180
  189   183
  190   186
  191   189
  192   192
  193   195
  194   198
  195   201
  196   204
  197   207
  198   210
  199   213
  200   216
  201   218
  202   222
  203   225
  204   227
  205   230
  206   233
  207   236
  208   239
  209   242
  210   245
  211   248
  212   251
  213   254
  214   254
  215   254
  216   254
  217   254
  218   254
  219   254
  220   254
  221   254
  222   254
  223   254
  224   254
  225   254
  226   254
  227   254
  228   254
  229   254
  230   254
  231   254
  232   254
  233   254
  234   254
  235   254
  236   254
  237   254
  238   254
  239   254
  240   254
  241   254
  242   254
  243   254
  244   254
  245   254
  246   254
  247   254
  248   254
  249   254
  250   254
  251   254
  252   254
  253   254
  254   254
  255   254

It seems like the problem should be obvious, but I'm not finding it. Anyone else see what is happening?
Logged

0
Offline Offline
Faraday Member
**
Karma: 16
Posts: 2855
ruggedcircuits.com
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Looks like this DAC takes data in on falling clock edges, so the default SPI mode 0,0 is not right. Try switching to a 0,1 or 1,0 mode.

--
The Gadget Shield: accelerometer, RGB LED, IR transmit/receive, speaker, microphone, light sensor, potentiometer, pushbuttons
Logged

Northern California (by San Francisco)
Offline Offline
Sr. Member
****
Karma: 3
Posts: 258
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks, that does seem to be the problem. I tried changing the clock phase to falling edge, by the following:
Code:
SPCR = (1 << CPHA); // set SPI mode to send data on falling edge of clock

That got me better results, as follows:

   
Code:
  0   0
  1   0
  2   1
  3   1
  4   2
  5   3
  6   3
  7   4
  8   4
  9   5
  10   6
  11   7
  12   8
  13   9
  14   10
  15   10
  16   11
  17   12
  18   13
  19   13
  20   14
  21   14
  22   15
  23   16
  24   17
  25   18
  26   19
  27   19
  28   20
  29   21
  30   21
  31   22
  32   23
  33   24
  34   25
  35   25
  36   26
  37   27
  38   28
  39   28
  40   28
  41   30
  42   30
  43   31
  44   32
  45   33
  46   34
  47   34
  48   35
  49   35
  50   36
  51   37
  52   38
  53   39
  54   39
  55   40
  56   41
  57   42
  58   42
  59   42
  60   44
  61   45
  62   45
  63   46
  64   47
  65   48
  66   48
  67   49
  68   49
  69   50
  70   51
  71   52
  72   53
  73   54
  74   54
  75   55
  76   56
  77   56
  78   57
  79   58
  80   59
  81   60
  82   60
  83   61
  84   62
  85   62
  86   63
  87   63
  88   64
  89   65
  90   66
  91   67
  92   68
  93   68
  94   69
  95   70
  96   70
  97   71
  98   72
  99   73
  100   74
  101   74
  102   75
  103   76
  104   76
  105   77
  106   78
  107   79
  108   80
  109   80
  110   81
  111   82
  112   83
  113   83
  114   84
  115   85
  116   86
  117   86
  118   87
  119   88
  120   88
  121   89
  122   90
  123   91
  124   91
  125   92
  126   93
  127   93
  128   94
  129   95
  130   96
  131   97
  132   97
  133   97
  134   99
  135   100
  136   100
  137   101
  138   101
  139   103
  140   103
  141   104
  142   105
  143   106
  144   106
  145   107
  146   108
  147   108
  148   109
  149   110
  150   111
  151   111
  152   112
  153   113
  154   114
  155   114
  156   115
  157   116
  158   117
  159   117
  160   117
  161   119
  162   120
  163   120
  164   120
  165   122
  166   123
  167   123
  168   124
  169   125
  170   126
  171   126
  172   127
  173   127
  174   129
  175   129
  176   130
  177   130
  178   132
  179   132
  180   133
  181   134
  182   135
  183   135
  184   136
  185   137
  186   137
  187   138
  188   139
  189   140
  190   140
  191   141
  192   142
  193   143
  194   144
  195   144
  196   145
  197   146
  198   147
  199   147
  200   148
  201   149
  202   149
  203   150
  204   151
  205   152
  206   152
  207   153
  208   154
  209   155
  210   155
  211   156
  212   156
  213   158
  214   158
  215   159
  216   159
  217   161
  218   161
  219   162
  220   163
  221   164
  222   164
  223   165
  224   166
  225   167
  226   167
  227   168
  228   169
  229   169
  230   170
  231   171
  232   172
  233   173
  234   173
  235   174
  236   175
  237   176
  238   176
  239   177
  240   178
  241   179
  242   179
  243   180
  244   181
  245   182
  246   182
  247   183
  248   184
  249   184
  250   185
  251   186
  252   187
  253   187
  254   188
  255   188

But it is still not quite right. I also tried changing the CPOL bit, and that led to the same results as changing the CPHA bit. Changing both bits to ones? Same results. (That's a little strange.)

I'll keep puzzling over this. But it does have me puzzled.
Logged

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

...puzzled.

What VDD are you applying to the DAC?  What voltage(s) are you applying to REF1 and REF2 on the DAC?

What makes you think that the ADC reading divided by 4 (with integer arithmetic, which throws away the lower two bits of the quotient) should be numerically equal to the DAC code byte?  (Your table values would be pretty close if the DAC reference voltage is something like 3.7 Volts.  But I still wouldn't throw away the lower two bits of the ADC readings.)


Regards,

Dave

Footnote:
It may be possible to isolate the puzzling aspects like this by something like this:

Instead of trying to figure out what's wrong with a list of 256 different words, write a particular DAC code byte, say 128.  Measure the voltage with a meter.  It should be 1/2 the DAC reference voltage for that channel, right?  If not, then you can debug the DAC end of your system.

Repeat the experiment with a code byte of 64.  Try 192.  See if the results are consistent with your expectations.

Then for a particular DAC code byte:
Read the value with analogRead() on the Arduino.  Print that integer value.  Convert to (floating point) volts in the Arduino.  Print that out. It should be (close to) the voltage you read on the meter.  If not, then you can debug the Arduino end of the system.

Anyhow, once you get the value for a few particular code bytes to meet your expectations, then run the program that gives results for all of the DAC code bytes.  (I would probably print DAC code word and expected voltage and then calculate Arduino voltage and relative error (or percent error) and print those out for each reading.)
« Last Edit: April 07, 2011, 11:44:30 am by davekw7x » Logged

Northern California (by San Francisco)
Offline Offline
Sr. Member
****
Karma: 3
Posts: 258
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for your comments.

What makes you think that the ADC reading divided by 4 (with integer arithmetic, which throws away the lower two bits of the quotient) should be numerically equal to the DAC code byte?  (Your table values would be pretty close if the DAC reference voltage is something like 3.7 Volts.  But I still wouldn't throw away the lower two bits of the ADC readings.)

Prior to testing this DAC, I tested two other DACs and three digital potentiometers, using the same approach of reading the analog input to the Arduino and dividing by 4 (to scale it from 0 to 1023 down to 0 to 255). As you note, that takes off the lower two bits, but I found that it was still very close to the digital output I sent to the device. Only in this case is there a discrepancy of more than plus or minus one.

The differences between this DAC and the other DACs and digital potentiometers are that this one does not use pure SPI, and this one is 3.3 Volts instead of 5 Volts. Following RuggedCircuit's comment, I had thought the SPI problem has been taken of.

Maybe the problem now is with the supply voltage and the reference voltage. The datasheet is a little unclear on what those should be, and I've tried various combinations. None worked. Some close, but the closest was the one I posted.

I'll keep trying.
Logged

Left Coast, USA
Offline Offline
Sr. Member
****
Karma: 7
Posts: 499
Sometimes I just can't help myself.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

...
Prior to testing this DAC, I tested two other DACs ....

I hate to repeat myself but
Quote from: davekw7x
What voltage(s) are you applying to REF1 and REF2 on the DAC?

Now, sometimes I ask questions out of idle curiosity, but in this case I actually had a reason.

The reason that I asked is that for proper operation of this particular device, the maximum value of reference voltage is VDD-1.5 Volts.  So: If you are applying 5 Volts to VDD and 3.3 Volts to REF1,REF2, it will be operating within spec.  

However...

But the full-scale voltage of the DAC will be Vref (minus 1 lsb) not 5 Volts.  If you apply 3.3 Volts to VDD, then you should not put 5 Volt logic signals (SPI Clock and SPI MOSI) to the device.  Furthermore, if you use 3.3 Volts VDD, then the reference voltage(s) should be no more than 1.8 Volts.

Here's my take on it: For most convenient use with a 5-Volt Arduino, apply 5 Volts to VDD and 3.3 Volts to Vref on the DAC.


Quote from: Daanii
...I had thought the SPI problem has been taken of.
I think that SPI can work and, in fact your values are monotonically increasing as you increment the DAC code byte, so it is (probably) OK.  I, personally wouldn't even have thought of using SPI (I would just have waded in and done it the "hard way" with bit banging), but I can't see why SPI can't work for this.

Have you tried the experiment that I suggested: Put a single DAC code byte and read the voltage with a meter?  Output voltage should be equal to

(Reference Voltage) * (DAC code word) / 256

Apply 5 Volts to VDD and 3.3 Volts to REF1 and REF2.  Write 128 to the DAC.  Read the voltage with a meter.  Should be 1.65 Volts, right?
Now, read the voltage with Arduino analogRead.  The ADC reading should be something like 338.

Anyhow convert the ADC reading to a voltage with something like this:

Code:
   const float aRef = 5.0; // Make this value equal to the Arduino VCC (nominally 5 Volts but could be off by a percent or two).
.
.   // write 128 to DAC
.
    int adcValue = analogRead(0); // Or whatever channel you use
    float adcVoltage = adcValue * aRef / 1024.0;
    Serial.print("Analog reading = ");Serial.print(adcValue);
    Serial.print(" => ");Serial.print(adcVoltage);
    Serial.println(" Volts");

Bottom line: If the full-scale 8-bit DAC voltage is equal to the full-scale 10-bit ADC voltage, then you can divide the ADC reading by 4 and it should just about match the DAC code word.  That's not the case for this particular DAC and your Arduino.  There is also a factor of (DAC Reference)/(ADC Reference)  But---See Footnote.

Regards,

Dave

Footnote:
You could, in fact, use 3.3 Volts for the Arduino ADC reference by applying 3.3 Volts to the Arduino Aref input and changing the software to use the external reference.  In fact, for best precision in any ADC operation, it's usually a Good Idea to use a reference voltage that is somewhere in the neighborhood of the maximum expected input voltage.  At any rate, the formula for converting analogRead value to voltage is what I show above.  Just change the aRef value to whatever you decide to use.
« Last Edit: April 07, 2011, 05:54:21 pm by davekw7x » Logged

Northern California (by San Francisco)
Offline Offline
Sr. Member
****
Karma: 3
Posts: 258
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the detailed comments, including the repeat of your earlier comment. You were exactly right to focus on the supply and reference voltages. Once I used 5 Volts as supply and 3.34 Volts as reference, I got the results I expected. (Which were exactly the numbers you predicted.) Those voltages were the problem -- not the SPI clocking as I thought.

So this TI chip tests out fine. But I need a voltage that varies between 0 and 5 Volts. Since I can't use 5 Volts as the reference voltage on this TI chip, and I can on the others I tested, I'll use one of them.

It's good to have solved the puzzle, though. Thank you for doing that for me.
Logged

Pages: [1]   Go Up
Jump to: