Go Down

Topic: Library for DAC855X Digital to Analogic converters by Texas Instruments (Read 2120 times) previous topic - next topic

renatoia

Hello! I recently purchased some Texas Instruments DAC8552 chips, but I do not get the proper libraries for Uno. I have achieved something similar here and here, but I do not know if it will be compatible. Can someone help me?
Thanks!

[EDIT 17.12.18] The project resulted in good results! The library is now available on GitHub!

Thanks for the contributions!
Following in this post, you can follow the development of the project.
Renato Ianhez - Professor (www.unipam.edu.br) - Forensic Scientist (www.pc.mg.gov.br).
Patos de Minas - MG - Brazil

renatoia

After a lot of searching on Github and other pages, I was able to build something ... Look, I'm a beginner, and I need your suggestions to make this code work ...
First, the libraries:
DAC8552.h
Code: [Select]
/*************************************************************************
**  Device: DAC8552                                                  **
**  File:   DAC8552.h - Biblioteca para obter valor de voltagem DAC    **
*************************************************************************/


#ifndef DAC8552_h
#define DAC8552_h

#include "Arduino.h"

class DAC8552
{
  public:
    DAC8552(int DIN, int SCK, int SS, boolean DAC, boolean DAC1);   
    void setValue(int Value);

  private:
    int _DATAOUT;
    int _SPICLOCK;
    int _SLAVESELECT;
    boolean _DAC;
boolean _DAC1;
                                             
    void sendSPIHeader();
    void mandaSPI(int Value);
    void sendSPIClock();
};

#endif


DAC8552.ccp
Code: [Select]
/*************************************************************************
**  Device: DAC8552                                                  **
**  File:   DAC8552.h - Biblioteca para saída analógica              **
**************************************************************************/
#include "DAC8552.h"
#include "Arduino.h"

DAC8552::DAC8552(int DIN, int SCK, int SS, boolean DAC, boolean DAC1)  //Seleção dos pinos e das saídas
{
 _DATAOUT = DIN;
 _SPICLOCK = SCK;
 _SLAVESELECT = SS;
 _DAC = DAC;
 _DAC1 = DAC1;
 
 pinMode(_DATAOUT,OUTPUT);
 pinMode(_SPICLOCK,OUTPUT);
 pinMode(_SLAVESELECT,OUTPUT);

}

//************************************************************************
void DAC8552::setValue(int Value) {
  sendIntValueSPI(Value);
}
//************************************************************************
void DAC8552::sendSPIClock() {
  digitalWrite(_SPICLOCK, HIGH);
  digitalWrite(_SPICLOCK, LOW);
  delay(1);
}

//************************************************************************
void DAC8552::sendSPIHeader() {
// bit 23 Adress reservado = 0
 digitalWrite(_DATAOUT,LOW);
 sendSPIClock();
// bit 22 Adress reserved = 0
  digitalWrite(_DATAOUT,LOW);
  sendSPIClock();
// bit 21 Output on Channel B
 digitalWrite(_DATAOUT,_DAC1);
 sendSPIClock();
// bit 20 Output on Channel A
 digitalWrite(_DATAOUT,_DAC);
 sendSPIClock();
// bit 19 Don't care bit
  digitalWrite(_DATAOUT,LOW);
  sendSPIClock();
// bit 18 Buffer selection
  digitalWrite(_DATAOUT,DAC);
  sendSPIClock();
// bit 17 and 16 Power down mode - sets as Normal
  digitalWrite(_DATAOUT,LOW);
  sendSPIClock();
  digitalWrite(_DATAOUT,LOW);
  sendSPIClock();

  }
 
//************************************************************************
void DAC8552::mandaSPI(int value) {
 // initiate data transfer with 8552
 digitalWrite(_SLAVESELECT,LOW);
 
 // send 8 bit header
 sendSPIHeader();
 
  // send data
  for(int i=16;i>=0;i--){
    digitalWrite(_DATAOUT,((Value&(1<<i)))>>i);
    sendSPIClock();
  }
 
  // finish data transfer
  digitalWrite(_SLAVESELECT,HIGH);
}
 


And the test:
Code: [Select]
#include <DAC8552.h>

DAC8552 SaidaA(11, 13, 10, HIGH, LOW); //Seta a saída para canal A

int LeituraA;

void setup() {
 Serial.begin(9600);
}

void loop() {
  for(int i=0; i<65535; i++)
  {
    SaidaA.mandaSPI(i);
    LeituraA = analogRead(0);
    Serial.println(LeituraA);
    delay(1000);
  }
}


The debug get a error in "SaidaA.mandaSPI(i);" "within this context"
Whats wrong with my code?
Renato Ianhez - Professor (www.unipam.edu.br) - Forensic Scientist (www.pc.mg.gov.br).
Patos de Minas - MG - Brazil

robtillaart

#2
Dec 12, 2017, 03:42 pm Last Edit: Dec 12, 2017, 03:42 pm by robtillaart
Can you post the exact error?
NOrmally it has a line number where it goes wrong.

mandaSPI() is a private function of the class, so it cannot be called directly.

try to change the testcode to
Code: (experimental, not tested) [Select]
//
// File: DAC8552demo.ino
// Author: ...
// Date: ...
// Purpose: demo sketch DAC8552
//
#include <DAC8552.h>

DAC8552 SaidaA(11, 13, 10, HIGH, LOW); //Seta a saída para canal A

int LeituraA;

void setup()
{
  Serial.begin(9600);
  Serial.println(__FILE__); // shows the name of the sketch
}

void loop()
{
  for (int i = 0; i < 65535; i++)
  {
    SaidaA.setValue(i);
    delay(100); // give it some time to settle

    // do the measurement
    LeituraA = analogRead(0);

    // print results
    Serial.print(i);
    Serial.print("\t ==> \t");
    Serial.println(LeituraA);
    delay(1000);
  }
}
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

renatoia

Thank you, robtillaart! You're right! The only fuction I can use is "setValue (int)". I'll test here!
Renato Ianhez - Professor (www.unipam.edu.br) - Forensic Scientist (www.pc.mg.gov.br).
Patos de Minas - MG - Brazil

renatoia

The error:
Code: [Select]
Arduino: 1.8.5 (Windows 10), Placa:"Arduino/Genuino Uno"

Opções de compilação alteradas, recompilando tudo
C:\Users\RENATO~1\AppData\Local\Temp\ccZO68FI.ltrans0.ltrans.o: In function `__static_initialization_and_destruction_0':

C:\Users\Renato Ianhez\Documents\Arduino\DAC_Teste\DAC8552-Teste2/DAC8552-Teste2.ino:3: undefined reference to `DAC8552::DAC8552(int, int, int, bool, bool)'

C:\Users\RENATO~1\AppData\Local\Temp\ccZO68FI.ltrans0.ltrans.o: In function `loop':

C:\Users\Renato Ianhez\Documents\Arduino\DAC_Teste\DAC8552-Teste2/DAC8552-Teste2.ino:17: undefined reference to `DAC8552::setValue(int)'

collect2.exe: error: ld returned 1 exit status

exit status 1
Erro compilando para a placa Arduino/Genuino Uno




There may be an error in the .cpp file, in the bit counting part. I did according to the DAC8552 datasheet (page 14), but since I have no experience with it, I may have been wrong there ...
Renato Ianhez - Professor (www.unipam.edu.br) - Forensic Scientist (www.pc.mg.gov.br).
Patos de Minas - MG - Brazil

robtillaart

#5
Dec 12, 2017, 07:58 pm Last Edit: Dec 12, 2017, 07:59 pm by robtillaart
Sorry to say but that library is incomplete at best for Arduino. I do not know the DAC in question and I do not see a quick fix for the code. It could be that the lib was written for another processor than Arduino. Just don't know.

The datasheet is available - http://www.ti.com/lit/ds/symlink/dac8552.pdf

A quick google did not show any library for this DAC...

Where did you find the  library?

 
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

renatoia

The codes were adapted from the DAC8554, which I found here. However, the two DACs are different, since 8552 has 2 channels and 8554 has 4. So the encoding of the initial bits is distinct, and I did not know what to do with what the datasheet calls "buffer" and the "update" of each channel (my English is via google translator).
Renato Ianhez - Professor (www.unipam.edu.br) - Forensic Scientist (www.pc.mg.gov.br).
Patos de Minas - MG - Brazil

robtillaart

Where are you from?

Have you tried to use the 8554 library code as it is?
If these 2 DACs only differ in the number of channels it might just work.
Please give it a try,


At least a quick view showed that the 8554 library has more code than the 8552 code above.
A part of the missing might explain the failing of compilation.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

A quick check showed that the DAC8554 library does compile.
I cannot test if it works as I do not have such DAC.

There is only one warning, which is not critical (but should be solved sometime)

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

renatoia

I'm from Brasil..
In fact, I compared the datasheets of both DACs and noticed that there are significant differences in the 8 control bits. In the 8552, the first 2 bits (23 and 22) are reserved, whereas in the 8554 they have address and control functions. The next two bits (21 and 20) are upgrading channels A and B to 8552 and have a similar function in 8554. Bit 19 is useless ("don't care bit") in both. Bit 18 indicates DAC (buffer select) addressing, whether for channel A or for B on 8552, while on 8554 bits 18 and 17 are used for this function (since they are 4 channels). In 8552, bits 17 and 16 control the power down for each channel, while in 8554 the same function is done by bit 16, but for all channels together.

My main question is about the meaning of bits 21 and 20 ("control the updating of each analog output with the specified 16 bit data") and bit 18 ("controls the destination of the data"). They seem redundant to me. The goal is, in the Arduino sketch, to write only "sendtoDACout(channelX, ValueDAC)". Where X is channel A or B, and ValueDAC is a value between 0 and 65535.

In conclusion, I came across the DAC8552 because it was the only device of this type (16 bit DAC) that I found in the market of my country. I'm assembling a low-cost potentiostat to be used in my instrumental chemical analysis classes. I've made good progress with the popular MCP4725, 12-bit I2C. But as I found this better one...
In Brasil, cheap devices of the same type cost about 1 year of work by an ordinary worker (R$ 12,000.00 / U$ 4,000.00). My project wants to make one for 100 times less (R$ 120,00).
Renato Ianhez - Professor (www.unipam.edu.br) - Forensic Scientist (www.pc.mg.gov.br).
Patos de Minas - MG - Brazil

robtillaart

#10
Dec 13, 2017, 07:51 am Last Edit: Dec 13, 2017, 07:53 am by robtillaart
I know Brasil is expensive (import taxes) so I understand your need.

What I would do is make a copy of that class as a starting point.

With respect to the differences, to me they seem not blocking for the experiment

bits 23 and 22 - not used so don't care
bits 21 and 20 - same function so OK
bit 18 - address is same so OK

In 8552, bits 17 and 16 control the power down for each channel,
while in 8554 the same function is done by bit 16, but for all channels together.

Power down is important but not critical, so just not use it for a first experiment.
(unless you need them to power up!!)
Rewrite should not be too difficult.

In short the 8554 library should have a big chance of working. Give it a try.
If it not works I will try to help rewrite the lib to match the specs.

Do you have links to the datasheets?

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

#11
Dec 13, 2017, 08:27 am Last Edit: Dec 13, 2017, 08:29 am by robtillaart
Had a quick look at the lib and stripped it to something minimal to have a start.
See attachment.

you might need to tweak the SPIHeadder function to set some bits right.
please let me know is if works or not then I can do some rework this evening.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

renatoia

Thank you, Rob! (can I call it that?) Your tips are being very useful and I'm learning a lot about "modus operandi"!
Let's take the steps used in libraries:

DAC8552.h
(The comments of headings will do later)
1. Initial statements. They seem OK.
Code: [Select]
#ifndef DAC8552_h
#define DAC8552_h

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif


2. Class declaration and public functions. Here I would like to be able to pass the channel selection to the setValue function. But for now, let's find out which bit is responsible for this.
Code: [Select]
class DAC8552
{
  public:
    DAC8552(int DIN, int SCK, int SS, bool DAC, bool DAC1);   
    void setValue(int value);


3. Here we declare the internal variables and functions. Seems OK... Notice that there was a separation of the control bits (SPIHeader) from the data bits. I have doubts about the type of data sent to SPI. Is it really an integer?
Code: [Select]
private:
    int _DATAOUT;
    int _SPICLOCK;
    int _SLAVESELECT;
    boolean _DAC;
    boolean _DAC1;
                                             
    void sendSPIHeader();
    void sendtoSPI(int value);
    void sendSPIClock();
};
Renato Ianhez - Professor (www.unipam.edu.br) - Forensic Scientist (www.pc.mg.gov.br).
Patos de Minas - MG - Brazil

renatoia

Let's move on to DAC8552.cpp.
4. Header, with all the typical information, I'll do later. Initial part looks ok too.
Code: [Select]
#include "DAC8552.h"

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif


5. Here I changed the name of the pins according to their names on the chip: DIN = MISO (Uno pin 12), SCLK = SCK (pin 13) and SYNC = SS (pin 10). I include one more Boolean variable (DAC2) for bit 18. In the sketch, we will change the values in DAC, DAC1 and DAC2 to see how the output we will take. (I changed this in the .h file)
Code: [Select]
DAC8552::DAC8552(int DIN, int SCK, int SS, bool DAC, bool DAC1, bool DAC2)
{
 _DATAOUT = DIN;
 _SPICLOCK = SCK;
 _SLAVESELECT = SS;
 _DAC = DAC;
 _DAC1 = DAC1;
 _DAC2 = DAC2;
 
 pinMode(_DATAOUT,OUTPUT);
 pinMode(_SPICLOCK,OUTPUT);
 pinMode(_SLAVESELECT,OUTPUT);

}


6. That part was where I adapted the code for the 8552. The first two functions (setValue and sendSPIClock) are OK like this?
Now the sendSPIHeader(): The first two bits (23 and 22) are LOW (reserved). Bits 21 and 20 we can change in command. Bit 19 don't care. Bit 18 we can change the value in the command as well. Bits 17 and 16 will leave as LOW, without "power down" (we can activate this feature later).
Code: [Select]
void DAC8552::setValue(int value) {
  sendIntValueSPI(value);
}

void DAC8552::sendSPIClock() {
  digitalWrite(_SPICLOCK, HIGH);
  digitalWrite(_SPICLOCK, LOW);
  delay(1);
}

void DAC8552::sendSPIHeader() {
// bit 23 (reserved) = 0
 digitalWrite(_DATAOUT,LOW);
 sendSPIClock();
// bit 22 (reserved) = 0
  digitalWrite(_DATAOUT,LOW);
  sendSPIClock();
// bit 21 Output on Channel B
 digitalWrite(_DATAOUT,_DAC1);
 sendSPIClock();
// bit 20 Output on Channel A
 digitalWrite(_DATAOUT,_DAC);
 sendSPIClock();
// bit 19 Don't care bit
  digitalWrite(_DATAOUT,LOW);
  sendSPIClock();
// bit 18 Buffer selection
  digitalWrite(_DATAOUT,DAC2);
  sendSPIClock();
// bit 17 and 16 Power down mode - sets as Normal
  digitalWrite(_DATAOUT,LOW);
  sendSPIClock();
  digitalWrite(_DATAOUT,LOW);
  sendSPIClock();


7. Here, I do not know if it's correct. Notice that in the loop, i starts with 16 and goes to zero. Would not it be starting with 15?
Code: [Select]
void DAC8552::sendtoSPI(int value) {
 // initiate data transfer with 8552
 digitalWrite(_SLAVESELECT,LOW);
 // send 8 bit header
 sendSPIHeader();
  // send data
  for(int i=16;i>=0;i--){
    digitalWrite(_DATAOUT,((value&(1<<i)))>>i);
    sendSPIClock();
  }
  // finish data transfer
  digitalWrite(_SLAVESELECT,HIGH);
}
Renato Ianhez - Professor (www.unipam.edu.br) - Forensic Scientist (www.pc.mg.gov.br).
Patos de Minas - MG - Brazil

renatoia

Finally (wow!), The test program:
8. I set the Arduino pins, and the Boolean bits 21, 20 and 18. The presence of spaces in the part "DAC8552 OutputA (11, 13, 10, HIGH, LOW, LOW);" is it critical?
Code: [Select]
#include <DAC8552.h>

DAC8552 SaidaA(11, 13, 10, HIGH, LOW, LOW);

int LeituraA;

void setup()
{
  Serial.begin(9600);
  Serial.println(DAC8552Test);
}


9. This loop, I suppose, is OK. I put increments of 64 to give 1024 values.
Code: [Select]
void loop()
{
  for (int i = 0; i < 65535; i+=64)
  {
    SaidaA.setValue(i);
    delay(100); // give it some time to settle

    // do the measurement
    LeituraA = analogRead(0);

    // print results
    Serial.print(i);
    Serial.print("\t ==> \t");
    Serial.println(LeituraA);
    delay(1000);
  }
}


Verifying, result the error:
Code: [Select]
Arduino: 1.8.5 (Windows 10), Placa:"Arduino/Genuino Uno"

C:\Users\RENATO~1\AppData\Local\Temp\ccdpP4zQ.ltrans0.ltrans.o: In function `__static_initialization_and_destruction_0':

C:\Users\Renato Ianhez\Documents\Arduino\DAC_Teste\DAC8552Test3/DAC8552Test3.ino:3: undefined reference to `DAC8552::DAC8552(int, int, int, bool, bool, bool)'

C:\Users\RENATO~1\AppData\Local\Temp\ccdpP4zQ.ltrans0.ltrans.o: In function `loop':

C:\Users\Renato Ianhez\Documents\Arduino\DAC_Teste\DAC8552Test3/DAC8552Test3.ino:16: undefined reference to `DAC8552::setValue(int)'

collect2.exe: error: ld returned 1 exit status

exit status 1
Erro compilando para a placa Arduino/Genuino Uno

Este relatório teria mais informações com
"Mostrar a saida detalhada durante a compilação"
opção pode ser ativada em "Arquivo -> Preferências"


Would the error be in the "constructor" of the functions?
Renato Ianhez - Professor (www.unipam.edu.br) - Forensic Scientist (www.pc.mg.gov.br).
Patos de Minas - MG - Brazil

Go Up