Digital Gain Control Using AD545x Multiplying DAC - Page 1
Forum section: electronics / projects

author: H713
author_rank: Regular Contributor
timestamp: June 22, 2020, 06:16:44 am
content: Greetings,I may have bitten off more than I can chew with this one, given that I have very little experience with microcontrollers or digital electronics. It's a programmable gain amplifier using an Analog Devices multiplying DAC. This will be used as the front end of an audio power amplifier (hence the differential input). It is part of a much more complicated digital control system I am designing. This type of gain control has many advantages including precise level control and tight matching between channels.The schematic for the interesting part is attached. Nothing very original, essentially the same circuit as described here:https://www.analog.com/en/analog-dialogue/articles/high-resolution-multiplying-dacs.htmlHere is the Arduino test code for the AD5450.#include <SPI.h>int slaveSelect = 10;void setup() {pinMode(slaveSelect, OUTPUT);SPI.begin();}void loop() {ad5450Write(40);delay(1000);ad5450Write(225);delay(1000);ad5450Write(25);delay(1000);ad5450Write(0);delay(1000);}void ad5450Write(int bitlevel){digitalWrite(slaveSelect, LOW);delay(10);SPI.transfer(bitlevel);delay(10);digitalWrite(slaveSelect, HIGH);}Now for the issue I'm having. The differential input works as expected, and the DAC section sort of works. The problem I'm running into is that the DAC does not respond to the ad5450Write(225) command. In fact, it will not respond to anything above 63- theoretically, being an 8-bit DAC it should go up to 255. It simply stays at whatever it was last set to. Also of note, is that at a level of 63 the DAC section is unity gain, as if the DAC was set to a level of 255.I'm not an expert when it comes to serial communication, so it's possible I made an error in my programming. The SYNC pin (slave select) is connected to pin 10 on the Arduino Uno, the SDIN pin is connected to pin 11, and SCLK is connected to pin 13.I'm also not particularly experienced with SMD soldering, so I suppose there is the possibility that the DAC chip was damaged by overheating or ESD. Replacing the DAC is a not particularly trivial, as getting at it with a hot air station will be difficult without melting nearby IC sockets for the op-amps.I'd greatly appreciate any suggestions on what to try here, as while I have experience with C++ and analog circuit design, my experience level with digital communication and microcontrollers is relatively limited.

author: H713
author_rank: Regular Contributor
timestamp: June 22, 2020, 11:23:08 pm
content: Alright, I tried replacing the DAC, trying to be more careful about how much heat was used (and I wore an anti-static wrist strap to play it safe) and it didn't make a difference- exact same symptoms. If the digital level being transmitted is over 63, the slave select still goes low but the DAC does not respond, and 63 seems to act as a unity gain buffer. This indicates to me that it is turned all the way on as if it had received a digital input of 255. I also tried powering it off the Arduino's 5V supply pin, which also didn't change anything.

author: Bassman59
author_rank: Super Contributor
timestamp: June 22, 2020, 11:44:08 pm
content: OK, so some questions.1. Does your output op-amp use bipolar supplies or single-rail?2. You say "essentially the same circuit as shown here" but there is more than one circuit shown. Which one are you talking about? If you're using the variant that shows gain, you could be just railing the output.3. Are you following the serial data format as noted in the data sheet? It is NOT SPI! Does your SPI,transfer function shift out 8 bits at a time or 16? Because the serial format in the data sheet clearly shows 16 bit words.The two MSbs are "control bits" which set chip operation, and the data byte folllows immediately, MSb first. Those control bits are important. Also, the default is thatdata bits shift in on the falling edge of the clock. So when you shift in 0xFF (255), what you're doing is changing the edge on which the DAC shifts its data in.So shifting out 8 bits instead of 16 is your first problem. Your second problem is that you need to make sure the SPI output from the micro changes data on the rising edge so the DAC can clock it in on the falling edge. And the third problem is you need to justify the write data with the control bits coming first.READ THEDATA SHEET. It's all there.

author: H713
author_rank: Regular Contributor
timestamp: June 24, 2020, 08:23:59 am
content: Here is where I am at. The code has been changed to the following, and a few notes:#include <SPI.h>int slaveSelect = 10;void setup() {pinMode(slaveSelect, OUTPUT);SPI.begin();}void loop() {// put your main code here, to run repeatedly:ad5450Write(63);delay(1000);ad5450Write(225);delay(1000);ad5450Write(25);delay(1000);ad5450Write(0);delay(1000);}void ad5450Write(int bitlevel){digitalWrite(slaveSelect, LOW);SPI.beginTransaction(SPISettings(50000000, MSBFIRST, SPI_MODE1));SPI.transfer(0b00);SPI.transfer(bitlevel);SPI.endTransaction();digitalWrite(slaveSelect, HIGH);}Firstly, the op-amp is running on +/- 15V. Output waveform is clean. I have this configured for unity gain, and we are very far from the output rails.Now, onto the serial data format...Clearly my lack of serial communications knowledge is showing. After a bit more time re-reading the datasheet and reading some Arduino documentation, I made a few changes.SPI_MODE1 should change it to shift data out on the rising edge, so the DAC can shift on the falling edge. Hopefully I'm understanding this correctly.The first two bits in the sequence are the control bits. Setting the first two bits as 0b00 should in theory keep the DAC in its normal state. It then reads in 8 bits of data and ignores the rest of the 16 bit words, because it is an AD5450 rather than a higher resolution DAC from the same series.In actual testing, things work... sort of. It now responds to all the levels, however, at 255 it should be unity gain, in this case 2V peak. In actuality, I am seeing 30 mV.I'm not quite clear on what exactly I'm doing wrong- again, I'm still trying to figure out how some of this stuff works.

author: H713
author_rank: Regular Contributor
timestamp: June 28, 2020, 09:40:01 am
content: Here is where I am at currently. Slowly starting to understand this a bit more. After some time reading up on the Arduino SPI library (and a bit more experimentation), I was able to get it to work properly with the following code. Reducing the speed to 100 kHz makes it significantly easier to accurately view the clock and data signals on a scope, and this application doesn't need high speeds either.#include <SPI.h>int slaveSelect = 10;void setup() {pinMode(slaveSelect, OUTPUT);SPI.begin();}void loop() {// put your main code here, to run repeatedly:for(int i = 0; i <= 16383; i++){ad5450Write(i);delayMicroseconds(250);}delay(10000);}void ad5450Write(int bitlevel){// Shit that isn't gonna work:digitalWrite(slaveSelect, LOW);SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE1));SPI.transfer16(bitlevel);SPI.endTransaction();digitalWrite(slaveSelect, HIGH);}I am not completely clear on why sending 14-bit levels to an 8-bit DAC is working, however, I suspect it is because the 8-bit DAC ignores the 6 least significant bits. If anyone can clarify if this is correct, please let me know.