DAC doesn't give quite the right output

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.

// 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);
  
}
  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?

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

Thanks, that does seem to be the problem. I tried changing the clock phase to falling edge, by the following:

SPCR = (1 << CPHA); // set SPI mode to send data on falling edge of clock

That got me better results, as follows:

  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.

Daanii:
...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.)

Thanks for your comments.

davekw7x:
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.

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

I hate to repeat myself but

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.

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:

    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.

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.