Arduino-based optocompressor/gate

GroupDIY Audio Forum

Help Support GroupDIY Audio Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

efinque

Well-known member
Joined
Jan 3, 2018
Messages
350
Sup GDIY,

I've been working on an Arduino-based optocompressor while recovering from my DIY spree.

Basically it takes the audio input and the MCU lights up a LED once the signal reaches a defined threshold level. The LED then controls an LDR which feeds an audio output. The LED has a defined hold time, I've been doing tests with 10-500ms.

Here's a build pic with the volume knob, connectors, MCU board and the control circuit in place (I packed the optocoupler inside a tube which is used to hold camera negatives)

IMG-20181018-004008-818.jpg


And the finished unit with a peak LED and threshold.

IMG-20181020-180708-583.jpg


I'll post a schematic and the code later.. for now the threshold adjustment doesn't work, my serial monitor shows 1023 (=5V control voltage from the board) so I think the input pin could be damaged since I've been using the board for prototyping for about a year.

I was thinking of adding a sidechain, and a pad/potentiometer to set the hold time as well as getting rid of the threshold control (ie. making it fixed value, I used 700 which was ok for the equipment I was using, the maximum value for 10-bits is 1023) and adjusting the input instead.

Anyway, what do you think?

-ef

EDIT : here's the schematic :

optocomp.png


(my CAD didn't have a photoresistor symbol, I put a normal one there instead)

and the code :

Code:
void setup() {
  Serial.begin(9600);
  pinMode (A0, INPUT);
  pinMode (A5, INPUT);
  pinMode (10, OUTPUT);
  pinMode (13, OUTPUT);
}

void loop() {
  int controlV = analogRead(A0);
  int threshold = analogRead(A5);
  int hold = 500;
  Serial.println(controlV);
  Serial.println(threshold);
 
 if (controlV > threshold) {
    digitalWrite (10, HIGH);
    digitalWrite (13, HIGH);
    delay(hold);
      }
    else
      digitalWrite(10, LOW);
      digitalWrite(13, LOW);
  }

EDIT 2 : oh, and a make-up gain too... tbh it's more like a gate though. I tried other input pins too, maybe it's the potentiometer acting up (I pulled them off an old reverb unit as well as the connectors) At first I was doing tests with a simple Schmitt trigger but it didn't work so I put the Arduino to good use.. it didn't have enough I/O for a synth project I was planning anyway.
 
To make the device work more like a compressor, you need to use a proportional control mechanism. Right now, you have two gains: on and off, but a compressor needs a continuously variable range of gains. I know little about the Arduino, but I assume it has an analog output that could be used to drive the opto LED, rather than the digital output.

To make this work more like a real compressor, you could use a register somewhere to store the value of the gain reduction value, which is the value sent to the analog output, which then drives the opto's LED. So, a larger register value will mean a brighter LED and thus more gain reduction.

One way to make this work: Run some periodic update cycle and adjust the gain reduction value at each cycle. If the output exceeds threshold, then add some number to the register's value. The amount you add per update cycle will be the attack time. Also, at every update cycle, you need to decrease the value stored in the register, and this amount is the release rate. At all times, the register's value is sent to the DAC output and that is sent to the LED in the opto.

A problem with optos is that there's no simple control law that relates LED current to photocell resistance. To overcome that problem, you drive the level detector with the compressor's output, after gain reduction, and not the pre-compressed input signal. In this way, the processor will turn the gain down when the output signal gets larger than the threshold. This is known as a feedback limiter, and this is the topology of all opto compressor / limiters. As such, there is really no ratio at all - the processor goes from 1:1 at threshold to infinity:1 deep above threshold, with values between the two extremes depending on how much gain reduction is being done.

There are a lot of details to hammer out, but yes, what you have now is more like a gate or a ducker, and not an opto. Best of luck!
 
Monte McGuire said:
To make the device work more like a compressor, you need to use a proportional control mechanism. Right now, you have two gains: on and off, but a compressor needs a continuously variable range of gains.

I had a hunch this wouldn't be as easy as it looks.. for example, the compression ratio varies significantly with the input level or is hard to measure. The LDR isn't instant though, nor is the LED so they bring their own spice in the soup.

I know little about the Arduino, but I assume it has an analog output that could be used to drive the opto LED, rather than the digital output.

That's something I didn't even think.. but I have a feeling the GPIO can pick up interference from neighbouring pins.

To make this work more like a real compressor, you could use a register somewhere to store the value of the gain reduction value, which is the value sent to the analog output, which then drives the opto's LED. So, a larger register value will mean a brighter LED and thus more gain reduction.

I'm not following.. almost but not quite. I'm familiar with arrays in C but the one I tried for storing note values didn't work.

One way to make this work: Run some periodic update cycle and adjust the gain reduction value at each cycle. If the output exceeds threshold, then add some number to the register's value. The amount you add per update cycle will be the attack time. Also, at every update cycle, you need to decrease the value stored in the register, and this amount is the release rate. At all times, the register's value is sent to the DAC output and that is sent to the LED in the opto.

Sounds a bit too complicated for a compressor to me..

A problem with optos is that there's no simple control law that relates LED current to photocell resistance. To overcome that problem, you drive the level detector with the compressor's output, after gain reduction, and not the pre-compressed input signal. In this way, the processor will turn the gain down when the output signal gets larger than the threshold. This is known as a feedback limiter, and this is the topology of all opto compressor / limiters. As such, there is really no ratio at all - the processor goes from 1:1 at threshold to infinity:1 deep above threshold, with values between the two extremes depending on how much gain reduction is being done.

The problem with making a feedback compressor is that the output signal is VERY low... I measured noise floors in the serial monitor around 200 which is roughly 1V with 5V input. Another thing is matching LDR's, or use one to drive a dual opamp for stereo?

There are a lot of details to hammer out, but yes, what you have now is more like a gate or a ducker, and not an opto. Best of luck!

Thanks! Originally I needed a limiter/leveler for a speaker crossover but it turned out the way it did.. I was thinking of using it for squashing drum tracks etc in the studio, ran some program as well as some source material through it, it's not much of a mastering compressor..

EDIT : one option would be to use a tube like in the LA2-A.. the problem is I've never done a tube circuit.

EDIT 2 : it produces an interesting effect too when the delay-command is placed before the optocoupler LED write.. but it wasn't what I was looking for either so I left the code as it is.
 
kooma said:
dont you need resistors with those leds?

No.. the digital pins supply 5V when defined as outputs.

and could you just use pwm in arduino? louder music->brighter light.

I've built a couple of different bass synthesizer/sequencer prototypes with this particular board (Uno rev3) and afaik you can't because of the high/low logic.. tone libraries work with a pitch based on 50% duty cycles defined in hz.

Here's a link to a dev thread regarding the sequencer on Arduino forum (there's also the code).. but like I stated earlier I ran out of I/O as it would've been 4-step (edit : I may build it in the future with a Mega or a GPIO shield)

t-Cad1-ard.png
 
sorry, I dont want to be rude, but what!?
you cant use PWM-pin on arduino to control led brightnes?
what kind of leds are you using? normal leds would need resistor with 5v.
 
Agreed on both points.

Interesting idea though!

You might want to do some input conditioning, to also protect the input pins of the arduino. And maybe add a knob on one of the analog inputs to allow one to set speed.
But it is interesting, you could have the arduino also react automatically and differently to slower and quicker signals.
 
Here's the revised schematic.. I removed the threshold control via code for good.

optocomp.png


And the code :

Code:
void setup() {
  Serial.begin(9600);
  pinMode (A0, INPUT);
  pinMode (10, OUTPUT);
  pinMode (13, OUTPUT);
}

void loop() {
  int controlV = analogRead(A0);
  int hold = 100;
  Serial.println(controlV);
 
 if (controlV > 300) {
    digitalWrite (10, HIGH);
    digitalWrite (13, HIGH);
    delay(hold);
      }
    else
      digitalWrite(10, LOW);
      digitalWrite(13, LOW);
  }

So it's a bit simpler now, but it works. If someone wishes to use it just remove the serial bits. Sort of Robinson Crusoe-esque, except to fully qualify as one it'd need something found on friday.
 
kooma said:
sorry, I dont want to be rude, but what!?
you cant use PWM-pin on arduino to control led brightnes?
what kind of leds are you using? normal leds would need resistor with 5v.

I've used PWM to control a servo, that's about it.. it was tedious and somehow confusing though. Some people do put resistors on LED grounds though.
 
Jarno said:
You might want to do some input conditioning, to also protect the input pins of the arduino.

Yes I was thinking a software reset if the input peaks at 1023.

And maybe add a knob on one of the analog inputs to allow one to set speed.
But it is interesting, you could have the arduino also react automatically and differently to slower and quicker signals.

It's not a tremolo.. but very close to one if you duplicate the code to make the LED blink.
 
efinque said:
I've used PWM to control a servo, that's about it.. it was tedious and somehow confusing though. Some people do put resistors on LED grounds though.
You need resistors. And you can control brightness with PWM, the IDE even comes with an example sketch called 'fade' that shows you how.
 
merlin said:
You need resistors. And you can control brightness with PWM, the IDE even comes with an example sketch called 'fade' that shows you how.

Yes but the one I came across uses analogWrite.. this one's digital.
 
If you are using the arduino just to light up an LED once the signal reaches a threshold, why not simply use a comparator as a threshold detector and a RC time constant to keep the LED ON the required time?
 
user 37518 said:
If you are using the arduino just to light up an LED once the signal reaches a threshold, why not simply use a comparator as a threshold detector and a RC time constant to keep the LED ON the required time?

Originally I bought the Arduino to do some tests for a mixer console build I've been planning.
 
Digging up this old thread as I started going through some old builds and had a better look at the prototype unit since I have some spare time now.. (I don't have access to an IDE as I don't have a PC for the time being so I can't do much about it code-wise)

First of all it could be programmed to do all kinds of things (maybe put different hold values in other pins and jump the LED wiring from them, ie. via a rotary switch) but the conversion from gate to comp requires tinkering the code (ie. in a compressor the control circuit LED is on all the time and it goes low when the threshold is exceeded which ducks the signal) by declaring the optocoupler LED pin high in the loop and using the "if" statement with the threshold value to turn it off.

Another is external CV which requires a separate input jack to the threshold pin.

It can be "bypassed" by wiring the input via ground (it could be worked around with either a resistor in series or simply lifting the ground wire) as I was thinking of putting a NC relay in the output so when the input hits a certain value it opens it, but it isn't much of a unit for live stuff imo, more suitable for studio work (I was thinking of reamping some guitar tracks etc through it from a multitrack recorder)

Another downside is it has no make-up gain whatsoever so it needs a fair bit of drive from whatever is connected to it.. I probed the LDR with a DMM, in room light inside insulation tape it's about 120kOhm, probably like 10-20kOhm with the LED on (I'll try later with a battery/PSU) which I think is enough for VCA if it had an opamp.

I read finding a matched pair of LDRs for stereo operation is like winning the lottery so the VCA opamp stuff is relevant.

EDIT : regarding the brightness control it could be done with analogWrite to the control circuit LED I think but it needs to be coded so that when the input signal gets louder the LED goes dim in relation.. tbh I don't know what the C programming equivelant would be, as the code would have to complement (reverse) the input value (for example according to datasheets CD4035B shift registers have a TRUE/COMP pin which complements the contents of the register), ie. at signal input value 1023 the LED pin output is 0 and at input 0 the LED output is 1023; at input 512 the output is 512, at input 256 the output is 768, at input 768 the output is 256.. then you'd interpolate the rest of the values within the code.

EDIT 2 : there's a function in C called "bitwise NOT" declared with a tilde ~ which does exactly this, ie. in a 3-bit system 001 would become 110 and so on, the Arduino DAC is 10-bit though so 0000000001 returns 1111111110.. note that I wasn't or still am very good at programming though.
 
[quote author=boji]Or just make some tables and reference var's to suit.[/quote]

Yes or use a VU meter in dot mode via resistors to drive the threshold pin like in my VCA compressor sketch.

8LbLLZZ.png


EDIT : to further theorize the analog LED output route; the hold feature could cause some additional issues and erratic behaviour as you'd read the input value, then complement it to the LED and hold it for 50-100ms, in which time the input has changed (ie. in audio program material like music which I designed this device for in the first place)

EDIT 2 : or better yet, put it in a 1RU 19" case and expand it to a 6ch gate.. I've never multitracked drums though.
 
This thread showed up, still working on it?

You could use the PMW signal from the Arduino and pulse the led, take a look at a circuit i toke from a RANE DJ mixer it might help you, to convert the PWM signal into a control signal/voltage for the led. some thinkering might be needed as the leds needs 20mA.

Pass the Audio signal through a Full WAVE rectifier, Analog Devices, education: Full wave rectifier and feed that into the Analog read pin.
You might wanna put 2 inverting opamp in front of this circuit and the other one on the back to be able to scale the rectified audio to 3V for better digital resolution of the ADC. 10 bit? but the algorythm has to be quite clever since the binary world is totally abrupt. either 1 or 0, but nothing in between, yet.

... and i would put the "vactrol" in the same matter as in the LA-A2, LA-A3, LA-A4 and like the FET in the UREI1176 compressor, to GND.
 

Attachments

  • Rane PWM signal.jpeg
    Rane PWM signal.jpeg
    88.3 KB · Views: 11
Last edited:
Back
Top