Generating CV/Gate with Arduino

From circuitbending to homebrew stompboxes & synths, keep the DIY spirit alive!

Moderators: luketeaford, Joe., lisa, Kent

User avatar
kssm
Common Wiggler
Posts: 121
Joined: Sun Mar 31, 2013 11:49 pm

Post by kssm » Sun Jun 22, 2014 5:56 pm

stk, it's been quite some time now since you posted this, but did you ever figure out the best R and C values for your filter?

I am currently using the Arduino Pro PWM outs to generate CV for a Serge modular. For now using a DAC is out of the question and I'm trying to get the best frequency value to generate useable, steady pitches.
If you were arbitrarily using a 2.2k with a 2.2uF, using that calculator posted here that would be 32.9Hz correct?
daverj wrote:So to effectively filter out the PWM cycle frequency the filter must be set many, many octaves below the PWM cycle frequency. At the same time, the lower the frequency of the filter, the longer the settling time of the DC output.
So would a cutoff frequency of about 1/50th of 490Hz (running frequency of PWM) be sufficient? I'll go testing on my breadboard, but I'm finding this to get tedious very easily..
This thread is the closest I've found on this subject, and I'm glad to find that it's putting me in the right direction.
So far I'm using values similar to stk, and running my outputs at about 40Hz. I would be thrilled to hear any input or advise on determining the best RC values for improving on my current configuration!

User avatar
Nantonos
Super Deluxe Wiggler
Posts: 1275
Joined: Sun Mar 03, 2013 1:00 pm
Location: Boston, MA

Post by Nantonos » Mon Jun 23, 2014 10:50 am

kssm wrote: I am currently using the Arduino Pro PWM outs to generate CV for a Serge modular.
PWM is fine for stepper motors and the like. For CV for a synth, its a very inferior solution. For pitch CV, even more so. Use a DAC, they are cheap and easy.
kssm wrote:For now using a DAC is out of the question
Why is a DAC "out of the question"?
kssm wrote:and I'm trying to get the best frequency value to generate useable, steady pitches.
Don't use PWM, especially for pitch CV. Its not accurate enough, and it either produces a lot of high frequency noise or a very slow slew rate (or both!) depending on how you filter it.
ondes | current rack
I am afraid a firmware change will not be able to turn a rather expensive 16-bit DAC into a 16-bit ADC, and flip all those op-amps :)

User avatar
Nantonos
Super Deluxe Wiggler
Posts: 1275
Joined: Sun Mar 03, 2013 1:00 pm
Location: Boston, MA

Post by Nantonos » Mon Jun 23, 2014 11:12 am

jupiter8 wrote:
deastman wrote:I've been endlessly frustrated in my attempts to find a suitable but affordable DAC. Correct me if I'm wrong, but it seems that cheap 8-bit DACs aren't going to provide enough resolution for volt/oct use.
Due to the way digital works an 8 bit DAC will only have 256 possible values.
If you do 0-10 volt each step will be 4 cents (0.04 volt).
An 8-bit DAC is clearly insufficient. Think of it like this. There are 127 MIDI notes. If you used a 7-bit DAC that would be one step per note (per 100 cents) - if the DAC was theoretically perfect. Which it isn't; you need to read the datasheet for the DAC in question to see the typical and maximum values for the nonlinearity.

The calculation quoted above is incorrect. 10 volt range is 10 octaves or 1200 * 10 = 12,000 cents. Divided by 256 and assuming a theoretically perfect DAC, that is 46.8 cents error (or about half a semitone). In practice it will be quite a bit more.

There is lots of mention of making resistive string DACs. This is a really bad idea, because if you need 8 bits or less then just use a cheap 8-bit DAC. To get to 10 bits you need then you start needing 0.1% resistors which are expensive and to get beyond that you need better tolerance which is seriously expensive and totally pointless because the cheap DAC will have individually laser-trimmed resistors on the package and the entire chip costs less than two 0.05% or better resistors!
ondes | current rack
I am afraid a firmware change will not be able to turn a rather expensive 16-bit DAC into a 16-bit ADC, and flip all those op-amps :)

User avatar
kssm
Common Wiggler
Posts: 121
Joined: Sun Mar 31, 2013 11:49 pm

Post by kssm » Mon Jun 23, 2014 11:15 pm

Nantonos wrote:
kssm wrote: I am currently using the Arduino Pro PWM outs to generate CV for a Serge modular.
PWM is fine for stepper motors and the like. For CV for a synth, its a very inferior solution. For pitch CV, even more so. Use a DAC, they are cheap and easy.
kssm wrote:For now using a DAC is out of the question
Why is a DAC "out of the question"?
kssm wrote:and I'm trying to get the best frequency value to generate useable, steady pitches.
Don't use PWM, especially for pitch CV. Its not accurate enough, and it either produces a lot of high frequency noise or a very slow slew rate (or both!) depending on how you filter it.
Thanks Nantonos! I agree that using DACs is the best option for synth CVs. I mentioned "out of the question" mainly because I have no more pins to use up for the SPI.
It's fine if I end up adding a few more components to the mix and make a second order filter to improve on the ripple/response tradeoff--as long as I don't hear the stepping anymore. (I've got the noise out good now, but with a slower response like you mentioned.)
Even though most information about RC filters are for simple first order filters, it seems increasingly true that it's not suitable for using with modular synths. I'm still wondering if it's possible or worth my time to keep my current pin configuration (I'd really like to, but no more pins for SPI) and try a second order filter? It doesn't have to be super precise in terms of tracking pitch.

User avatar
Nantonos
Super Deluxe Wiggler
Posts: 1275
Joined: Sun Mar 03, 2013 1:00 pm
Location: Boston, MA

Post by Nantonos » Tue Jun 24, 2014 10:56 am

Understand about running out of pins. Dual, quad, or octal DACs can help here as they give 2 (or 4, or 8) CV outputs while still just using 3 pins (CLK, MOSI, and CS).

Also understand that people's requirements vary for how closely they want pitch to track and over how many octaves. I guess I am just reacting against the all-to-common tendency for Arduino projects to just use PWM (often because they think it needs no external chips, until they discover the need for filtering) and I think this misleads new users as to the appropriate choices.

Datasheets for a DAC typically give the settling time, in microseconds. Its a lot better than the many-milliseconds portamento slew you get from agressively filtering PWM.

Is it the (huge) Arduino Pro or the (smaller)Arduino Pro Mini that you are using? The former is a cut-down Arduino Uno while the latter is an Arduino copy of the Teensy 2.0 except with only 14 digital pins (Teensy 2.0 has 25; Teensy++ has 46), no USB, half the memory, etc.

If you do want a higher order filter, check out this third order Sallen-Key filter designer.
ondes | current rack
I am afraid a firmware change will not be able to turn a rather expensive 16-bit DAC into a 16-bit ADC, and flip all those op-amps :)

User avatar
Neutron7
Oldschool bleeper
Posts: 1950
Joined: Sun May 23, 2010 12:24 pm

Post by Neutron7 » Tue Jun 24, 2014 1:10 pm

there is a trick to get more resolution fast from arduino PWM. it uses 7 bits on 2 PWM outputs mixed by 2 precision resistors for a nice 14 bits resolution.

MOZZI:

http://sensorium.github.io/Mozzi/learn/output/

they also have libraries and stuff. you could then make a level shifter/amplifier for the full range of CV output.

gate, i have found you can almost always just use an arduino pin to directly drive synth gsates, but i would protect it with a buffer, or at least over/undervoltage diodes and a current limiting resistor, just in case someone accidentally plugs it in to an output.

If you are looking to get a DAC, and you are using a mega, i would go with a parallel 12 bit DAC. then you can write directly to ports in your ISR instead of sending out bits one by one with SPI or another serial interface.

say you have a nice 400khz serial interface, and a dual 12 bit DAC. now you have to send out at least 3 bytes through serial for each sample.

so now your awesome 400khz serial output is divided by 24. now its only 16 khz :(

or you could try your luck getting the mega to do 4 mhz serial output. but then your ISR will eat up your CPU time and the rest of your code will have no time to run.

User avatar
kssm
Common Wiggler
Posts: 121
Joined: Sun Mar 31, 2013 11:49 pm

Post by kssm » Sat Jun 28, 2014 3:13 pm

Nantonos wrote:Understand about running out of pins. Dual, quad, or octal DACs can help here as they give 2 (or 4, or 8) CV outputs while still just using 3 pins (CLK, MOSI, and CS).

Also understand that people's requirements vary for how closely they want pitch to track and over how many octaves. I guess I am just reacting against the all-to-common tendency for Arduino projects to just use PWM (often because they think it needs no external chips, until they discover the need for filtering) and I think this misleads new users as to the appropriate choices.

Datasheets for a DAC typically give the settling time, in microseconds. Its a lot better than the many-milliseconds portamento slew you get from agressively filtering PWM.

Is it the (huge) Arduino Pro or the (smaller)Arduino Pro Mini that you are using? The former is a cut-down Arduino Uno while the latter is an Arduino copy of the Teensy 2.0 except with only 14 digital pins (Teensy 2.0 has 25; Teensy++ has 46), no USB, half the memory, etc.

If you do want a higher order filter, check out this third order Sallen-Key filter designer.
I had considered a DAC early in the stage of figuring out the Analog Outs, but I had already planned the functions which I should have listed earlier on: 6 Analog In with attenuators and offset, 6 Digital I/O, and 6 Analog Outs, and MIDI In/Out.
I'm using the larger Pro (5V/16MHz). All digital pins are used up for the Digital I/O and RX/TX for MIDI, leaving me the remaining pins 3,5,6,9, 10 and 11 for PWM outs.
Also pins 5 & 6 have a resolution of 980Hz instead of 490 like the rest of the pins. I know that there is a way to change the resolution of the other pins which would help especially if I were to be using a simple RC filter, but I can't find a way to do this without tying up even more pins.

Next time, I'll be using a Due. For now, I'm going to explore filters with a bit more components since they're already at hand, and I'd like to keep the functionality that my project already has. I'll post any useful results.
Also thanks for the Sallen Key design tool, I'm sure that will come in handy.

User avatar
kssm
Common Wiggler
Posts: 121
Joined: Sun Mar 31, 2013 11:49 pm

Post by kssm » Mon Jul 07, 2014 3:04 am

Update: I've got some good results now. Thanks for that Sallen Key filter designer Nantonos, it was incredibly useful.

I'll post schematics another time (or you can enter it on the filter designer), but basically I made a third order (Butterworth) filter with a 3.75Hz cutoff frequency to obtain a smooth (and high slew) CV--it's purpose being that it has very little "stepping" in between values and all of that ugly noise and odd harmonics are gone as well. It's clean, definitely useable especially for a slowly changing CV application without using an external slew.

To get better step response in between values I made another third order Bessel filter.
This link helped me to realize this particular characteristic: http://www.dspguide.com/ch3/4.htm
I used a frequency of 14Hz and the values step faster than the 3.75Hz Butterworth filter when jumping between notes (for tests I did 0 to 150, 0 to 255) If you wanted to add a slew, you can add a slew externally. With the Serge Quad Slope at max slew, it made the steps in between values pretty audibly smooth.

For now I have the best of both worlds, a steppier faster response CV, and a smoother, slow response CV, and both clean sounding without noise.

If you're in a similar predicament (no pins left to use for DACs, but have lots of resistors and caps sitting around), you could still make really useable PWM this way. It's still a struggle to balance the tradeoffs you encounter, but far better than an RC filter.

User avatar
jcarruthers
Learning to Wiggle
Posts: 16
Joined: Mon Oct 13, 2014 10:34 am

Post by jcarruthers » Mon Oct 13, 2014 1:14 pm

kssm — I'd love to see the schematic for your solution.

User avatar
jbeuckm
Learning to Wiggle
Posts: 45
Joined: Sun Oct 05, 2014 7:14 pm
Location: Sweden

Re: Try a cheap DAC

Post by jbeuckm » Sun Oct 26, 2014 8:30 pm

ringroad1 wrote:MCP4922 is less than 2 quid from Mouser and they're available in DIP. Plus it's a dual DAC, so one output could be note CV and another could be filter cutoff - is lots of fun.
I have a nicely working MIDI>CV going with the 4922, but I'm worried about the exact Vref as the supply voltage changes for any number of reasons. Have you looked at the 4822 that has an internal precision voltage reference?

User avatar
Ambriant
Common Wiggler
Posts: 67
Joined: Wed Dec 04, 2013 6:31 pm
Location: San Francisco

Ardcore

Post by Ambriant » Mon Oct 27, 2014 12:28 am

See the Ardcore sketches at 20 objects site. You can probably modify one of those sketches to fit your needs.

User avatar
Nordcore
Veteran Wiggler
Posts: 583
Joined: Fri May 10, 2013 2:05 pm
Location: Germany

Post by Nordcore » Mon Oct 27, 2014 2:00 am

Reference: LM4040. Cheap and good.
In my midi interface (ATMEGA with MCP4922 ) I used a LM317 as supply and reference. Works good enough for the 12 bit.

User avatar
kssm
Common Wiggler
Posts: 121
Joined: Sun Mar 31, 2013 11:49 pm

Post by kssm » Mon Nov 03, 2014 4:45 pm

jcarruthers wrote:kssm — I'd love to see the schematic for your solution.
http://www.magicechomusic.com/ciccs/ This is the project's ongoing documentation. No schematics posted yet, just been too busy. I can PM you a photo snapshot of the pwm schem in my notebook sometime.

User avatar
Siri
Common Wiggler
Posts: 238
Joined: Sat Mar 16, 2013 3:01 pm
Location: Montreal

Post by Siri » Mon Feb 29, 2016 1:11 am

Hi all,

I want to output CV from an MCP4922 DAC connected to a Teensy 3.2. On the schematic side, I figured it out. But for the code, not yet :confused:

For example, I was reading this post, and if I extract just this part :
void sendNote1(int key) {
int pitch1 = 0xa00L * key / 30.3;
digitalWrite(10, LOW);
SPI.transfer(0x10 + (pitch1 >> 8)); //DAC a OUTA
SPI.transfer(pitch1 & 0xff);
digitalWrite(10, HIGH);
}
Where can I get some information to understand those lines? I (think I) understand how the SPI protocol works, with the digitalwrite LOW at the begining, the HIGH at the end.
But I don't understand the "0xa00L * key /30.3", the (0x10 + (pitch1 >> 8)), and the (pitch1 & 0xff).

Basically, I'm looking for explanations about how to convert data (from an analogRead for example) to volts(CV) coming out out the DAC.

Any help would be greatly appreciated.

thanks

User avatar
mxmxmx
Super Deluxe Wiggler
Posts: 2243
Joined: Thu May 31, 2012 1:54 am
Location: berlin

Post by mxmxmx » Mon Feb 29, 2016 2:42 am

Siri wrote: Where can I get some information to understand those lines? I (think I) understand how the SPI protocol works, with the digitalwrite LOW at the begining, the HIGH at the end.
But I don't understand the "0xa00L * key /30.3", the (0x10 + (pitch1 >> 8)), and the (pitch1 & 0xff).
take a look at the MCP4922 datasheet (p24-25).

the first line is specific to what the guy wants to achieve; it simply scales the value of "key"; 0xa00 is 2560, the L suffix i'd say is mainly superfluous: pitch1 = 2560 * key / 30.3

as for the actual transfer: as per datasheet, you need to write 2 bytes, four bits of which are configuration bits and 12 are data bits. in that code you posted, 0x10 = 0b10000, translates to

00010000

bit15 = 0 -> "DAC Selection bit", in this case DAC A = 0
bit14 = 0 -> "VREF Input Buffer Control bit", in this case unbuffered = 0
bit13 = 0 -> "Output Gain Selection bit", in this case 2x = 0
bit12 = 0 -> "Output Shutdown Control bit", in this case "active mode" = 1

the remainders just spread the 12 bit data over two bytes :

right shift : pitch1 >> 8, that'll be bits 11, 10, 9, and 8
pitch1 & 0xff: masks the upper byte (& 255), and sends the rest, bits 7-0


note this is just the most vanilla way to go about it, there's slightly more efficient ways to do this with teensy 3x

User avatar
Siri
Common Wiggler
Posts: 238
Joined: Sat Mar 16, 2013 3:01 pm
Location: Montreal

Post by Siri » Mon Feb 29, 2016 9:29 pm

@mxmxmx Thanks a lot! :tu:
It's clearer now. When you say there is more efficient ways, are you talking about the spi4teensy3 library?

User avatar
mxmxmx
Super Deluxe Wiggler
Posts: 2243
Joined: Thu May 31, 2012 1:54 am
Location: berlin

Post by mxmxmx » Tue Mar 01, 2016 2:30 am

Siri wrote:@mxmxmx Thanks a lot! :tu:
It's clearer now. When you say there is more efficient ways, are you talking about the spi4teensy3 library?
efficient was probably the wrong word, but yeah, spi4teensy3 is faster. note that since your chip select is constant, you can use digitalWriteFast(..) to toggle the pin.

faster still is spififo.h. this works best if you use a hardware chip select pin, for example # 9 or 10.

for MCP4922 that'll look somewhat like so, the CS is toggled behind the scenes:
void set_DAC_A(uint16_t data) {

uint16_t _data = (0x10 << 8) | (data & 0xFFF);
SPIFIFO.write16(_data);
SPIFIFO.read();

}
and you'll have to init things somewhere, say:

SPIFIFO.begin(DAC_CS, SPI_CLOCK_24MHz, SPI_MODE0);

(though that might be too fast for the MCP4922, i think it says 20MHz max)

depending on what it is you want to do, there's still other options but any of these will do for most purposes.

User avatar
Troubleshooter
Wiggling with Experience
Posts: 366
Joined: Thu Oct 01, 2015 8:21 am
Location: Belgium

Post by Troubleshooter » Tue Mar 01, 2016 5:19 am

I have made a good working arduino 2 gate/CV/velocity with classic resistor ladders and opamps. Designed a 100x160 pcb for CNC routing.
My design has 1 processor, 2 quad opamps ,2 resistor ladders and an optocoupler for MIDI galvanic insulation.
It runs on +&-15V and contains stabilizers to +&-12V for extra stability.
Zero and gain are trimmable for both CV and Velocity.

Contra's:
Non E12 resestors needed
No pitch bend
Can not handle a lot of midi data, no problem if only sending notes into it but with a lot of midi control data the serial UART will overwlow.

Pro's
It seems to tune very well. Over the whole keyboard range.
Very good velocity response
Standard components like Atmega328, TL074, 6N13X, 7812, 7912 etc...
Great value for the money. Unbeatable...

User avatar
kssm
Common Wiggler
Posts: 121
Joined: Sun Mar 31, 2013 11:49 pm

Post by kssm » Wed Mar 02, 2016 5:38 pm

I don't mean to shift the discussion here, but do any of you have any pointers for setting up microtonal pitch scaling using Teensy or Arduino? Can you get CV precise enough for that--I guess that depends on how much tracking the oscillators can do as well. Is it just better suited for the computer?

I use Supercollider to generate these pitches, but I want to explore the use of analog oscillators with these intervals. I need no more than three octaves, but obviously a lot more pitches in between each. I'm particularly interested in pitches within the critical bandwidth, smaller, more complex intervals.

I can decipher and modify code, although there are no real examples as to how you can best program the calculations for pitch intervals on Arduino & a 12-bit DAC? I guess just choosing a fundamental and the intervals, and Arduino can do the arithmetic? Then I guess all I need to know is how that converts to voltage/ what deviations I'd be dealing with..

User avatar
Siri
Common Wiggler
Posts: 238
Joined: Sat Mar 16, 2013 3:01 pm
Location: Montreal

Post by Siri » Thu Mar 03, 2016 11:29 am

@mxmxmx Thanks! I'm working on a touch sensitive keyboard, so it has to output CV when a key is pressed. I don't know how spi4teensy3 is working, so I'll give a try to spififo.h using your example. Is there examples of code somewhere for thoses libraries, or one has to dig inside the library file to guess how it works (in general)?
thx

User avatar
mxmxmx
Super Deluxe Wiggler
Posts: 2243
Joined: Thu May 31, 2012 1:54 am
Location: berlin

Post by mxmxmx » Thu Mar 03, 2016 1:17 pm

Siri wrote:@mxmxmx Thanks! I'm working on a touch sensitive keyboard, so it has to output CV when a key is pressed. I don't know how spi4teensy3 is working, so I'll give a try to spififo.h using your example. Is there examples of code somewhere for thoses libraries, or one has to dig inside the library file to guess how it works (in general)?
thx
SPIFIFO.h isn't very documented very well. here's a working example (using a DAC8565, thus slightly more involved). what i've posted above *should* work for MCP4922 but i haven't tried.

spi4teensy comes with a few examples. it'll look fairly similar to using the default SPI library. see here, for instance (also using a DAC8565)

User avatar
Siri
Common Wiggler
Posts: 238
Joined: Sat Mar 16, 2013 3:01 pm
Location: Montreal

Post by Siri » Fri Mar 04, 2016 8:09 pm

@mxmxmx thanks I will try them out

User avatar
condor13
Common Wiggler
Posts: 54
Joined: Thu Apr 16, 2015 2:01 am
Location: Bucharest

Post by condor13 » Wed Nov 01, 2017 4:10 am

Siri wrote:@mxmxmx Thanks! I'm working on a touch sensitive keyboard, so it has to output CV when a key is pressed. I don't know how spi4teensy3 is working, so I'll give a try to spififo.h using your example. Is there examples of code somewhere for thoses libraries, or one has to dig inside the library file to guess how it works (in general)?
thx
Hey Siri. Did you manage to finish your touch sensitive keyboard? Are you wiling to share the code? I`m trying to make the same thing for a buchla.
Thanks a lot :D
"When you void a product warranty, you give up your right to sue the manufacturer if something goes wrong and accept full responsibility for whatever happens next. And then you truly own the product."

MrsWedge
Common Wiggler
Posts: 84
Joined: Thu Aug 17, 2017 7:15 am
Location: Usa

Post by MrsWedge » Wed Nov 01, 2017 5:29 am

Pwm works great. What you need is to use a base frequency above 20khz so that filtering isn't so important. This is how many motor controllers and class D amplifiers work.
An arduino is not capable of generating such a signal. One of the problems of using lower frequency and then filtering the heck out it is you won't be able to produce anything close to a square wave.

User avatar
StillNotWorking
Veteran Wiggler
Posts: 654
Joined: Thu Aug 22, 2013 3:29 pm
Contact:

Post by StillNotWorking » Wed Nov 01, 2017 7:37 am

MrsWedge wrote:Pwm works great. What you need is to use a base frequency above 20khz so that filtering isn't so important. This is how many motor controllers and class D amplifiers work.
An arduino is not capable of generating such a signal. One of the problems of using lower frequency and then filtering the heck out it is you won't be able to produce anything close to a square wave.
According to this suggestion it can be done, but with somewhat limited resolution. Mind you I've not tried it myself
https://arduino.stackexchange.com/quest ... 5khz#25623

Post Reply

Return to “Music Tech DIY”