Arduino ADSR Digital Envelope Generator

by baritonomarchetto in Circuits > Arduino

4908 Views, 5 Favorites, 0 Comments

Arduino ADSR Digital Envelope Generator

IMG_20210706_152241_risultato.jpg
IMG_20210706_152222_risultato.jpg
IMG_20210706_162121_risultato.jpg

It's incredible how many things you can accomplish with (as per today standards) tiny processors like ATmega328p with the essential help of open hardwares (who said "arduino!") and softwares. It's even more incredible how astonishing results one can have without the need to be a professional in the sector of circuit design or a full time programmer!

Some day ago I have had just the time to have fun by tinkering with an arduino-based wavetable oscillator that another brilliant project catched my attention: a digital, ADSR envelope generator running on arduino nano.

In this instructable I will show you the shield I have designed and the code modifications I have done starting from a brilliant project from "m0xpd" called ADSRduino.

As always, I will also share with you a link to have the PCB manufactured by professionals of the sector (PCBWay).

EDIT: a new, improved version of this ADSR can be found HERE (Instructables).

Background and Features

The base code of this project is a "m0xpd" (Paul Darlington) work and all credits are due to him. His ADSRduino project was more than an inspiration here, since I could learn a lot by "studying" the code he shared with us.

This project is not a mere copy of that, anyway, and I modified it towards my needs.

First of all, with respect to the original project, I made some pins swapping to have the shield compatible with a 492X DAC library so that we can change the envelope firmware with two different approaches: by modifying m0xpd code, or eventually relying on such library.

More interesting is the extention of envelope curves. The original project outputs a classic ADSR envelope, in two different modes: "normal" or looped (a.k.a. retrigger). In addition to this, I coded two new operation modes: a "biased semi-invertion" mode and a "biased quasi-invertion" to the envelope, just to show that we have only scratched the surface.

Service message: Mr. Paul, where are you? It's since 2017 you don't post anything, anywhere. Hope to read a new valuable "jotting" of yours soon.

Hardware and Design Choices

ADSR_pinout.bmp

The hardware mainly consists of an arduino nano (ATmega328p) and a MPC4921 digital to analog converter.

As I said, pins are wired differently from the original project because I wanted the shield to be also compatible with arduino MCP492X library. This library is based on default SPI library and use those specific serial programming pins.

In particular (function, original project pin -> new pin)

/CS, 6 -> 10 (could be any pin, hardware design choice)

SCK, 5 -> 13 (nano SCK)

SDI, 4 -> 11 (nano MOSI)

/LDAK, 8 -> 9 (could be any pin, hardware design choice)

Gate In, 2 -> 8

Loop mode, 3 -> 2

The complete, simplified, wiring is schematized in the (shameful) attached image.

You can switch between loop mode and single envelope mode with a latching switch connected to D2_LOOP and ground; you can switch from a classic ADSR mode to a biased semi-inverted mode with a latching switch to D3_INV and ground.

Another slight hardware modification from the original project is the voltage limiter circuit to the gate input, the original being a 5.1 zener diode to ground. This one is instead based on two schottky diodes as per Doepfer notes.

Since version 0.2 I also overvoltage/inverse voltage protected the DAC output, just in case of an involuntary connection to another module's output that could potentially kill the DAC.

A hardware switch input to trigger the envelope has also been introduced here. It's a simple switch that pulls to +5V the gate input as far as it is kept pressed. Notice that to have this working even without a gate signal grounding the pin at rest, I had to add a pulldown resistor to the microcontroller gate input (D8). As an alternative approach, I could have assigned one of the already wired spare microcontroller pins for this function and solve with two additional lines of code, but it's a simple hardware modification and avoids cpu load so it was a no brainer.

Even if the shield is built around the original ADSRduino project, being open firmware we can thing at modifications/implementations to it. This is why I also wired 4 digital and 3 analog additional pins (all left unused in the original sketch), for future uses/sketches.

Note that all digital inputs (gate_in excluded) are not voltage protected, so if you will use them to input any control voltage from an external module not working in the 0 - 5 V range you should consider to add an external voltage protecting circuit.

Even if the board is equipped with a full 8x2 IDC connector, this projects is powered by +5V only.

Attention: The DAC output is only partially short circuit protected with a 1K ohm resistor. During the insertion of a plug into the jack socket a short circuit between DAC out and GND is made for a short time. This is not a problem if the DAC out is at zero while patching (envelope "at rest"), but, worst case scenario, it could kill the DAC if loop mode is engaged or the envelope is triggered. The resistor should be enought to protect against shorts, anyway: at max output (+5V), we have a 5 mA current, but keep this in mind because a current limiting resistor is not effective as an opamp buffer would be.

Sketch and Biased Semi-Invertion

IMG_20210706_183135_risultato.jpg
IMG_20210706_183158_risultato.jpg

The code is well documented both in m0xpd dedicated page and the sketch itself. It's verbose (in a good way!) and you should read it: it's great value. I kept my additions as verbose as possible, just to simplify future mods.

The envelope invertion coded is not exactly the ususal ADSR invertion, but what I should probably call a "biased semi-invertion". Works like this:

- Attack phase starts at maxium, positive value (+5V) and goes down to "zero" according to user defined velocity

- Decay starts at zero and drives to sustain level (not an inverted sustain level!)

- Decay starts from sustain leven and drives toward zero (not +5V).

All levels/times are set by acting on dedicated potentiometers.

It's "biased" since voltage is always in the 0 - 5V ballpark and doesn't go negative.

Attached images are actual non-inverted and semi-inverted biased envelope images and should clarify the biased semi invertion thing.

Here follows a link to the "modified" sketch (github). Upload it to your arduino NANO the usual way.

https://github.com/baritonomarchetto/Programmable-...

I also made a simple sketch to check DAC functionality: it loops the DAC output to 0V, then 2V, then 5V at a frequency of 1Hz. This comes handy if you have the suspect your DAC is malfunctioning. You will find this sketch at the previous link too.

Would it be possible to code a classic inverted envelope without additional hardware?

Well, yes and no. For what concerns the release driving toward +5V instead of 0V, there are no problems. It can be easily done with a couple of lines of code if you want to keep the semi-invertion option too, or even easier if you don't. Another story is having the envelope span the 0 to -5V range with the current hardware. This could be achieved with the addition of an opamp in inverting configuration at the DAC output, anyway.

EDIT: Github repository now hosts a new version of the sketch (ProgEnvGen_V1b.ino). Use a non latching switch/button in place of the latching switch connected to D3 to cycle between the ADSR modes: normal, biased semi-inverted and biased quasi-inverted. I called it "quasi" inverted because the sustain level still acts the usual way.

EDIT 2: a new, improved version of this ADSR can be found HERE (Instructables).

Hey: the silkscreen shows an ASDR envelope, not ADSR!

Glad you noticed it, yes, that's another "special" feature I will describe in a week or two because I have not the time now, must deal with climate changes, overpopulation and things like that, you know... nuclear holocaust eventually? Are you still reading? ehm ... ok. A feature is not. Sorry. What a fool. I moved without the needed attention the envelope phases names wrong during the n-th redistribution of components. Good eye anyway :)

Don't worry: the linked board has that error fixed (and some improvement too)!

PCB and Components List

IMG_20210708_090053_risultato.jpg

You can have your PCB manufactured at the following link (PCBWay):

https://www.pcbway.com/project/shareproject/Arduin...

Select a nice color, place your order, have it shipped to you, source components, assemble it and have fun in the process!

All components values are silkscreened on the PCB to make assembly easier.

Here is the list of components required to populate the PCB:

- 1X Arduino nano 328p

- 1X MCP4921 12 bit DAC

- 1X 8 pin IC socket

- 2X BAT42 Schottky diode

- 1X 8x2 IDC connector

- 4X 10K ohm potentiometers

- 3X 1000 ohm ressitors

- 1X 10K ohm resistor

- 2X latching switches

- 2X mono jack, female

The board is intended to be mounted perpendicular to the front panel. If your case is not deep enought, you can lock the board on the case bottom and use wires to gain electrical connection with elements (potentiometers, buttons, jacks and so on) on the front panel.

EDIT: a link to the new version of the PCB can be found HERE (Instructables).

Acknowledgments

The PCB pictured in this instructable was sponsored by those nice girls and guys at PCBWay - PCB Prototype the Easy Way. Their customers service is excellent and PCBs of the best quality.

Thanks!