Starting with modular synths, DAC Question - Page 1
Forum section: electronics / beginners

author: calli
author_rank: Regular Contributor
timestamp: December 01, 2019, 05:12:08 pm
content: Hi,I stumbled into that rabbit hole... There is so much fun to build yourself in that modular synth regionSo I thought first build something digital/analog to get my hands dirty and stay a bit in my comfort zone, so I am doing a LFO (low frequency oscillator) generating waveforms with an arduino. That part works, I use a MCP4921 12-bit DAC.So have a look at the attachments, on low frequencies (note the Time/Div) I get a banana curve?! I swear I only add constant values to my variable an would expect a linear sawtooth curve...Is the MCP4921 not linear? Or do I have an error here?My loop looks like so (codensed to the bare minimum, real one has some more stuff but error is the same):Code:void loop(){x = x + 1;if (x>=4096) x=0;myDac.analogWrite(x);delayMicroseconds(20);}Later I may come here to ask some OpAmp Questions, but so far I can generate the CVs with them ok and also drive stuff with it, also build my vactrol etcCheers,Carsten

author: Kjelt
author_rank: Super Contributor
timestamp: December 01, 2019, 05:15:15 pm
content: Be carefull or your livingroom will end up like this

author: calli
author_rank: Regular Contributor
timestamp: December 01, 2019, 05:24:50 pm
content: Yea... I guess not as I am a loser at musicalityAnd I do not play the lottery.Carsten

author: Kjelt
author_rank: Super Contributor
timestamp: December 01, 2019, 05:25:38 pm
content: But to answer your question i dont know this dac but if i look fast in the datasheet you can not just put 0...4095 through spi since it expects 16 bits where some bits have a change in behaviour like the 2x gain which will interpret 0..2047 differently from 2048..4095 reread the datasheet or place the full code here.

author: MarkF
author_rank: Super Contributor
timestamp: December 01, 2019, 07:09:25 pm
content: I have used the MCP4822 DACs with a SPI interface and the MCP4921 interface is similar.Like @Kjelt says, you must pack the 12-bit DAC value into two bytes. See the datasheet.The code snippet you posted is doing an analog output via an Andrino PWM pin.You MUST instead setup and use the SPI library to send data to the MCP4921.The data format is:

author: calli
author_rank: Regular Contributor
timestamp: December 01, 2019, 07:20:46 pm
content: I am usinghttps://github.com/michd/Arduino-MCP492Xas library. Seems to handle that.However, I also tried it the hard way and same result, "banana".Code:#include <MCP492X.h> // Include the library#define PIN_SPI_CHIP_SELECT_DAC 9 // Or any pin you'd like to useMCP492X myDac(PIN_SPI_CHIP_SELECT_DAC);#define DATAOUT 11 //MOSI#define SPICLOCK 13 //sck#define SLAVE1 9 //ss#define PIN_SPI_CHIP_SELECT_DAC 9 // Or any pin you'd like to use#define LED 8#define FREQ A0#define ATTE A1#define FAST 7unsigned int freq = 0;unsigned int atte = 0;unsigned int x = 0;unsigned int fast = 4;void setup() {myDac.begin();pinMode(SLAVE1, OUTPUT);pinMode(FAST, INPUT_PULLUP);pinMode(LED, OUTPUT);Serial.begin(57600);}int dir = 1;// siplified versionvoid sloop(){x = x + 1;if (x >= 4096) x = 0;myDac.analogWrite(x);delayMicroseconds(20);}// "Production" :)void loop() {if (digitalRead(FAST)){fast = 3;freq = (analogRead(FREQ)) + 1;}else{fast = 0;freq = (analogRead(FREQ)) + 1;}if (x % 8 == 0){freq = (analogRead(FREQ)) + 1; // Maybe IRQ?atte = (analogRead(ATTE)) + 1; // Maybe IRQ?}x = x - (freq << fast);/*Serial.print(x >> 4);Serial.print(" ");Serial.println(atte);*/// using overflow of unsigned int as wraparound, could be malious but see above simple versionmyDac.analogWrite((x >> 4)); //Simple again//myDac.analogWrite(map(x>>4,0,4096,0,atte<<2)); // attenuate using Map and a second potiif (fast == 0){delayMicroseconds(1024 - freq);}}

author: MarkF
author_rank: Super Contributor
timestamp: December 01, 2019, 07:57:47 pm
content: Some of this may be wrong or unnecessary. I rarely do Arduino code.Code:// set pin 10 as CS for DAC:const int CSpin = 10;// DAC valueint value = 0;void setup(){// set Chip Select as output:pinMode(CSpin, OUTPUT);// initialize SPI:SPI.begin();SPI.setDataMode(SPI_MODE0);SPI.setBitOrder(LSBFIRST);}void loop(){// Set CS lowdigitalWrite(CSpin, LOW);// Transfer value// (you will need to 'OR' in additional bits for the 2nd output)SPI.transfer16(value);// Set CS highdigitalWrite(CSpin, HIGH);// Increment DAC valueif ( (++value) > 4095 ) value = 0;// DelaydelayMicroseconds(10);}

author: jhpadjustable
author_rank: Frequent Contributor
timestamp: December 01, 2019, 08:00:12 pm
content: Cute vactrolBut, you should really post a schematic. In particular, where is your Vref coming from?

author: calli
author_rank: Regular Contributor
timestamp: December 01, 2019, 08:05:20 pm
content: Yea, thats the hard way. Tried that also.I feel the vref thingy could be a thing.C!

author: dmills
author_rank: Super Contributor
timestamp: December 01, 2019, 08:06:07 pm
content: I think its simpler then that, try switching the scope to DC coupling!Regards, Dan.

author: calli
author_rank: Regular Contributor
timestamp: December 01, 2019, 08:21:30 pm
content: Quote from: dmills on December 01, 2019, 08:06:07 pmOh man....Thanks!