Showing posts with label Multiplexing. Show all posts
Showing posts with label Multiplexing. Show all posts

Tuesday, June 18, 2024

DAC8565 and 16ch sample and hold

I intend to use the DAC8565 quad 16 bit DAC for the XM8, I've even bought 20 of them on breakout board and written a test - but for some reason, I haven't written anything about it.

Right now I'm making the final CV mux board, so I had to retest my program. For some reason though, it doesn't complie anymore?

In my code I'm using SPI.send24 as well as SPI.hasInterruptFlagSet, SPI.clearInterruptFlag and SPI.enableInterrupt. 

I can't find ANYTHING about send24 anywhere, and very little about the others. But I found another SPI project locally, SPI-master, that has the send24 code. It says it is from https://www.pjrc.com/teensy/td_libs_SPI.html, but going there leads nowhere. Not sure what has happened, I feel completely gaslit!

Anyway - I copied the SPI-master into my project to get send24. As for the interrupt stuff, it's not really necessary as it only makes it possible to listen to send completes to trigger Load dac - and this can be done in software without penalty anyway, by adding it to the setting of the last DAC channel.


Ok, so how do we use the DAC8565.

The following pin config works:

pin 1,2, 7 and 8 are the four output channels

pin 3, Vref H, is the high reference voltage. It outputs the internal reference voltage (2.5V) if the internal voltage reference is used, and should be connected to ground through a 150nF cap. If using an external voltage reference instead, it can have an additional 4.8uF (!) cap to ground for reduced noise.

It is important to note that the max output when using the internal reference is 2.5V. To get a 5V output, we need to use an external 5V reference.

It is also important to note that the external reference CANNOT be higher than the Analog voltage AVDD, or the output will be clipped. 

Pin 4, AVdd, power for the analog parts. It may be 3v3 if using the internal 2.5V reference as output, or 5V if using an external reference.

Pin 5, Vref L, the low reference voltage. Usually connected to GND

Pin 6, GND

Pin 9: !Sync. = SPI Chip select

Pin 10: Serial clock

Pin 11: D in, Serial data. Connect to master MOSI

Pin 12, IOVdd. This should match the logic level of the MCU, which for the Teensy is 3v3. However, I had some success setting this to 5V even with 3v3 output, but I get glitches when running the SPI bus at 50MHz. Also, it says in the spec sheet that 3v3 logic has a max bus speed of 25MHz (I have successfully used 50MHz on the current breadboarded circuit, and 46MHz earlier, but IOVdd must be 3v3.

I will try using 5V logic but that requires a high speed level shifter between the Teensy and the DAC.

Pin 13: !RST - when set to 0, all DAC outputs are reset to the value of RSTSEL

Pin 14: RSTSEL - reset select. If 0, DACs power up and reset to 0, if 1 they reset to the middle of the reference voltage.

Pin 15: !Enable - "Connects the SPI interface to serial port". This is currently confusing me though connecting it to 0 works fine.

Pin 16: LDAC: Load Dac. Connect to GND and control this through software or connect to MCU


Running a loop with IOVdd at 3v3, AVdd at 5V and using a 5V external reference

50MHz SPI works fine


There is significant noise on the output

The noise is however only while the SPI bus transfers. This may make it bearable even if present in the real circuit, as we can transfer the data and let the signal settle before turning on the output muxes that load the sample and hold caps.

5V IOVdd also works...

Unfortunately, we get glitches at 5V IOVdd

The glitches go away when reverting to 3v3IOVdd


With MUX

I spent a long time trying to get my 16ch CV buffer to work with the DAC. Turns out I had mislabeled pin D0, it should be next to D1, not next to GND. 

Anyway, once I got that out of the way, the 16ch board works fine:

DAC Output through opamp buffer and 470R to mux. Works great!

Output is very stable. DAC slightly overshoots when switching (meastured after the buffer I think)


I tried various combinations:

5V external reference, 470Ohm resistor directly to DAC

5V external reference, no resistor, DAC directly to mux. DAC has no problem driving the charging

2.5V internal reference, 2x positive gain op amp, 470R input resistor

5V external reference, 470R input, no buffer. Something is very wrong! Not sure exactly what.

Some closeups

Extreme closeup of 2.5V ref through 2x gain and 470R resistor.

Extreme closeup of 5V ref, buffered and 470R resistor. Pretty much the same

Extreme closeup of 5V ref direct from dac without resistor. A tad noisier?

Then some charge times:

Dac output when run as 5V ref direct from DAC without resistor. Rise time is around 5.5uS

5V ref direct from DAC without resistor. Charge time 0 to 5V for CV buffer cap. Around 1.5uS

This is as far as I got, because here I somehow killed the Teensy :-( I would have liked to have the same two checks when running with 2.5V internal reference and 2x gain through 470R. Have to look for a new Teensy

...oh, I found one. Let's go on

Cap charge time through 470R resistor, around 3.4uS

But what if we change to a 220R instead?

Cap charge time through 220R resistor, around 2.2uS

 

That's pretty good. Let's look at the DAC settling time:

Rise time from 0 to 5V, as seen at the output of the buffer after the DAC, is around 2.9uS. The drops in voltage coincides with the charging of the caps and are not present at the DAC output.

All in all, this looks very promising. For my first production version I will use a 2x positive gain buffer with a 220R charging cap.

Wednesday, February 10, 2021

CV refresh rates

My Teensy-based voice controller prototype currently has a CV refresh rate of 1kHz. In this post I noted that the OB-6 has a refresh rate of 24kHz for < 1ms attack on envelopes, and the VS-1 OB-X remake uses 48kHz. I want my controller to get closer to those numbers.

I will have 48 CVs. Refreshing them at 40kHz means I need to update the DAC at 1.92MHz. With a 600MHz processor, this leaves around 300 clock cycles per update. It may be possible but could be a little on the short side.

I have tried dividing the CVs into those that will probably be modulated by envelopes, and those that can be a bit more slow moving. I ended up with 32 that I really want to be fast. If at the same time I reduce my refresh rate to what the OB-6 is using, 24kHz, I end up with a refresh rate of 768kHz for the 32 CVs. Add inn a 1kHz+ refresh rate for the remaining 16 and we end up with approximately 800kHz. 

In a new video on the VS-1 I noted that it now has 112CVs. It uses an 8 channel DAC, which means each channel has to be updated at 14 * 48kHz = 672kHz - that's pretty close to what I'm trying to do!


Necessary changes to my circuit

Capacitance

On the 1kHz version I use a 10nF sample & hold cap for 40kHz updates. Increasing to 800kHz means I should probably use a cap with 1/20 the capacitance. Closest match would be 470pF.

I tried putting this into my prototype but I'm having issues with noise - trying to generate a 800kHz square wave for testing doesn't seem to work very well. I switched to using my function generator but still had issues. It could be just because of the breadboard, so I will try this on a beta board, but before that I simulated the circuit in LTSpice to see what it looked like there. 


Initially I had a hard time getting the simulation to work. I couldn't get a proper square wave (I tried using the opamp comparator trick to turn my sine into a sqare), and started worrying that the TL072 is not up to the task. Perhaps the slew rate is too low? 

The datasheet says that the slew rate is between 13 and 20V/uS. In our case we want to charge the cap from 0 to 5V in  1/800000s = 5V/1.25uS = 4V/uS. So the slew rate should not be a problem.

After switching to the built-in pulse generator things looked a little better, but there were heavy noise on the square after I passed it through an op amp buffer. I then realised that by adding a resistor in series with the output, I would get a simple low pass filter. The formula for the filter is 1 / (2*pi*R*C). If we use a 470pF cap, and want an 800kHz cutoff, we need to use a 424 ohm resistor. A more standard value of 390 ohm gives us cutoff at 869kHz. Bear in mind though that this is a one pole filter, so the falloff is not very steep. Still, it should do away with some of the issue.

Simulating this turned out very well indeed, and adding it to the physical circuit also worked wonders for the INPUT to the S & H. The output, however, still looked the same. Connecting a 1k resistor between the output and the scope made it look a lot better.

Input vs output when using a filter resistor

Output still has some distortion at the bottom

Input, ringing is gone


I tried reducing the cap even further to get even higher refresh rates. This did not have the intended effect and I saw the same in the physical circuit as in the simulation. We get about the same response as with the 470pF cap. It looks like we're hitting some other limitation with the op amp perhaps - could it be internal capacitance or something? I'll see if I care to look closer into it.


Top: Square wave input vs output when we don't have a filtering resistor



Square wave vs unbuffered ("ideal") input to op amps (both top and middle are equal) and filtered version  (bottom) outputs


responses - top and middle are again equal and slightly rising towards higher frequencies, bottom shows low pass filtering,


Adding a similar passive filter to the output of the others - top and bottom show same response while middle gets a bit of a resonance peak.


Clock speed

The CD4520 clock can run at speeds up to 1.5MHz. I initially thought this too slow (for 1.92MHz, the refresh rate needed for 48 CVs at 40kHz it definitely is). I tried switching to a 74HC393, but running that at 3v3 meant the clock speed had to be around the same. The logic output also looked like 2V instead of 3v3,  and looked more noisy on the scope. Increasing Vdd to 5V let me run the chip at 3MHz and the logic output increased to 4V.

Something is definitely wrong here. Maybe it is the scope, maybe it is the breadboarding, but the 393 should be capable of clock speeds > 6MHz at 2V. I will test this further with my beta controller. It could also simply be that the timer I use cannot reach higher speeds than 2-3MHz. Oh well, it seems it may not be necessary after all.

As for the CD4051 mux, it probably has some of the same speed limitations as the CD4520. In the production version I will probably use vishay DG406 or similar which will probably work better.

Also, I may try to not use a clock at all, instead directly controlling the addresses of the muxes.


Addressing

To address 48 CVs I will either use 6 8ch MUXes or 3 16ch. Unfortunately, I cannot simply clock them sequentially. I can, however, use a clock for the three/four address lines, and then use the enable pin on each to select what mux to turn on. I would then update all 3/6 channels that have the same mux address sequentially to save time. 

I could possibly also use a separate mux to select which one of the other muxes to address. Doing this would actually make it possible to clock everything from the same clock (but possibly waste some clock cycles as I can either clock 4 or 8 muxes.


Multi channel DACs

Increasing the number of DAC channels would let us do less waits and also decrease the refresh rates since we would update multiple channels in parallel. This last thing is good as it lets us use a bigger cap that will keep its charge longer, giving us a more stable output.




Sunday, December 20, 2020

Muliplexed evelopes

I've dreaded doing the envelopes for a long time, mostly because there is always something crazy happening that takes a long time to debug. But now I have a very good working prototype.

I looked at my previous post here: http://atosynth.blogspot.com/2015/02/sample-and-hold-acquisition-time.html

Using 10nF sample and hold caps I wrote (5 years ago...) that an update time of 25uF seems appropriate. I have, however, not shown the original circuit, I have to go back and check if I buffered the op amp or not - because when I redid it now I could not get the desired speed. I had to run updates for at least 50uS. When I added an opamp after the dac however, things changed. I can't see any difference even when I run updates at 16uS. 

So, I've written an arduino program that updates a dac every 25uS. This is multiplexed to as many channels as possible, and the overall refresh rate is 1kHz.  I had a lot of issues related to starting/stopping the various times and ended up with a 25uS timer running all the time, just turning off the DAC update when all channels have been updated.

The output chain goes like this:

DAC8830 -> TL07x buffer -> CD4051 mux -> output buffer, 10nF cap + TL07x 

The mux is controlled by aCD4520 clock (only two pins needed for clock, one for next and one for reset-to-zero). Before an update, the inhibit signal of the mux is raised, turning off the outputs. The clock is progressed, switching to the next output. The DAC is updated and settles in 1uS, then inhibit is turned off and the output turned on. It is left to charge the cap for the remainder of the time between DAC updates, approximately 16uS. Rinse and repeat.

I tried updating a square wave at 1kHz too, it looks surprisingly good. The edges are slightly rounded, but that seems to be an artefact of the caps as increasing the charge time does not affect it.

DAC control. 1: chip select, 2: SPI clock. 3: DAC data, 4: mux inhibit

1kHz square wave on one of the outputs

Envelope output, 1kHz sample rate

Closeup of steps. Each step is held by the sample and hold cap, the DAC is disconnected right after the start of each step



Thursday, August 2, 2018

Summer 2018 - DAC Mux, Ring mod

Summer is always kind of productive for me. While off on summer holiday to the western parts of Norway, I get time to do some electronics work. This time I've drawn up and ordered a 16 channel sample and hold circuit (DAC mux) to replace the 32 channel one used in the prototype. This one is easier to place and makes it possible to use only 16 channels for parts of the synth.

I also did a v3 of the linear VCA. This time, as for the first version, the trimmers are off-board, but the components are placed on both sides as in v2. The whole card is sort of a double width DIL thingy with the pins for one VCA on one side and the other on the other side. I imagine it possible to place it in a socket and have other parts of the circuit below it - we'll see.



Finally, I did a ring modulator based on the one from yusynth.net, which in turn is almost entirely a copy of the one in the datasheet. This one uses a surface mount MC1496. The circuit and board are finished (but untested), including logo.


Oh, and I have written a midi/sysex-based bootloader - it's almost finished. I will feel much better if I can remotely update any MPG-200 I sell. The bootloader is very simplistic and does not have any flow control, so sysex uploading must be done through a program made by me. Still better than not being able to update at all.