At first, I know the existence of a digital pot. 'Problem' is you need an IC to achieve this and also want to keep the circuits completly separated (and simple). Also want to use it with an Arduino audio project without external IC (got already a MCU that can do the 'settings' job). So I came up with the idea to use a led and a photoresistor to seperate circuits and avoid fixed 'digital' steps, just like a normal pot resistor, keep it smooth and natural but without the analog fail/aging problems.

Made two (quick!) drafts, one with simple hardware like an opacity wheel and one with use of an Arduino: enter image description here

I figure out the basics of this idea using light to control volume is not a new one, found this: http://www.tortugaaudio.com/evolution-of-ldr-volume-control/ And the Lightspeed Passive Attenuator: http://diyaudioprojects.com/Solid/DIY-Lightspeed-Passive-Attenuator/

Try to find the component they are using, a led with a photoresistor but could not find it. I started to experiment with existing components, like this one (made an experimental board of an old canon printer, a board with two optical sensors, cut in half and added to audio sockets) to figure out it will work anyway:

enter image description here

The experiment succeed really well, very intresting to see it is actually working. The volume reduces when you put an object between the optical sensors or limit voltage input does the same. Except ...... one side of the amplitude is chopped off. Because there are only four pins, the receiver could be an opto-resistor, however it seems to be a diode? Just listen to this soundtrack what happend:

enter image description here Wave file: https://drive.google.com/file/d/0B2l-eQoHefcVdXRlUkM1bXJYek0/view?usp=sharing

Wave file (left+right combined): https://drive.google.com/file/d/0B2l-eQoHefcVVzZ3aWVrZ0hMVjg/view?usp=sharing


Althought I can make the component myself by replacing the opto-resistor-diode with a photosensor I wonder if these components are available somewhere. Because available space is an issue, it would be handy it is a compact component (with four legs) sized like a opto-coupler for example. Any ideas? Any partnumbers?

  • \$\begingroup\$ I think the components you use (U1 and U2) have photodiodes or phototransistors in them, not resistors (too slow). So in essense you have built a rectifier. Hence the squaring off. I know this works great with real LDRs. No clue where to harvest them though. \$\endgroup\$
    – peter
    Commented Oct 30, 2016 at 16:30

3 Answers 3


Admirable attempt, and good debugging effort. Your Cannon opto-couplers are different animals than those described in the link you provided. They do use an infra-red diode to provide the light, but the photo-sensitive element is not a resistive one, but is a silicon photo-transistor. The current it provides only flows one-way - hence the clipped waveforms that yield highly distorted audio.
The photo-sensitive element in your link is a cadmium-sulphide or cadmium-selenide photoresistor. It is a resistor that allows current in both directions in a reasonably linear way. Search terms like photocell optocoupler might help.
Some currently available part #'s: NSL-33-007 from LUNA optoelectronics is a dual-channel photocell optocoupler.
NSL-32H-103 from LUNA optoelectronics is a single-channel version.

  • \$\begingroup\$ I would not use a photo-interrupter. Designing the rotary varying window is too complicated, I think. Just use a dual-element LDR-based photoisolator, like the Vactrol VTL5C3/2, and vary the LED current. \$\endgroup\$
    – Rich S
    Commented Oct 30, 2016 at 19:29
  • \$\begingroup\$ @RichS: I don't want to use a photo-interrupter, just figure out in the example I build for this experiment. The components you are talking about are pretty expensive. Can you tell me what the difference between these versions (VTL5C1 .. VTL5C4)? \$\endgroup\$
    – Codebeat
    Commented Oct 31, 2016 at 1:25
  • \$\begingroup\$ @Erwinus Perkin Elmer's data sheet states:"VTL5C4 features a very low “on” resistance, fast response time, with a smaller temperature coefficient of resistance than VTL5C1." Since your application is a fairly static volume control, either would likely be OK - they both have a wide dynamic range. \$\endgroup\$
    – glen_geek
    Commented Oct 31, 2016 at 2:16

Google "Vactrol" , then left-click "More images for vactrol" for exactly what you need.

Here's an example:

enter image description here

Also, check out the Fairchild H11F1 for a different solution.

  • \$\begingroup\$ Hai, thanks, that are names, pretty expensive too! Now I understand why there are so many people that want to clone these devices (show up in search results) and these components are not used frequently. Read some info about photosensors in general, tempature, colorspectrum (nm) sensitivity. I don't care much about the slowness of photosensors, so maybe I can build one myself on the cheap. What kind of LED do you recommend to use (nm)? There is a table here - resistorguide.com/photoresistor - but can't figure out what's the best to do. Thanks in advance. \$\endgroup\$
    – Codebeat
    Commented Oct 31, 2016 at 1:18

After some months: Thanks go to EM Fields, which points me into the right direction. Vactrols are not cheap components and only available at some stores. So I decide to build my own vectrols and this can be done on the cheap ;-) and it works pretty well!

I ordered some different LDR's, some LEDS in China (about less than 3 euro's for a couple of bags with 50 LDR's and 200 LED's) and start some experiments with those. There are people that claim LED color matters when building vectrols, the white ones seems to be the best to use because they are the brightest of all. there are some forum guys that claim not to use bright LED's, well, I don't agree because of resistance, you need a very bright light to get low resistance. You cannot achieve this with old fashion LEDs.

I have tested different LDR's and there resistance can be deviate between models and same models. To be sure the LDR's have the same/closest/lowest restistance, test it with a bright LED lamb and an ohm meter.

LDR's slow in response? Well, I don't agree, they pick up the PWM pulse signal very well (sounds like the question's left+right-combined-example with more detail) and you need to change the frequency of the pulse signal otherwise the setup is useless (see later this writing what I have done to achieve this).

When the LED is at full brightness I reached (see setup below for two channel vectrol with only ONE LED) about 100-120 Ohms and is very good and useful comparing to what I measured before with the LED lamb. Some resistance is not that bad when using it with an amp (input impedance) like i do.

I changed the schematic to this:

schematic rotary encoder and vectrol arduino

Also build a test-device, an USB digital/analog audio volume control with use of a SparkFun DigiSpark (Arduino attiny85). Build a digital volume control before, so I just needed to change the code a bit. See also this instructable: http://www.instructables.com/id/Digispark-Volume-Control/ . The version of code I'm using is more advanced because I improved the code and added some extra features like buttons.

This is the device I made, a tiny volume knob with swivel usb connector base, so you can hook it up at any angle without a cable to your laptop or battery pack. This is a setup with just ONE LED and TWO LDR's.


Custom LED

The LED i'm using is not that custom, I just used a dremel to modify a regular 5mm LED, make/made it custom! To cut the 'overhead' away, be careful not dremel it too thin. I used a dremel with sandpaper chuck/finish. Test it with a 3V button cell after chopping before install it into final circuit.

I figured out there is a dead spot on these LED's. You can see it very clearly at the picture example above, the LDR's are positioned at the left-over of the bulb side of the LED, not on the bottom (= dead spot). Because LDR's are very sensitive, you have to workaround these dead spots to avoid you are unable to get maximum results.

PWM frequency problem

Altought it works very well at first attempt, the audio sounds like a mp3 with many artifacts (low bitrate). This will not happen when you use a battery to power the LED. The LDR's responding to the PWM frequency, so there are gaps in the audio because the LDR's resistance is fluctuating very fast between high and low (on/off) resistance.

First, I found this: https://provideyourown.com/2011/analogwrite-convert-pwm-to-voltage/ , use a high-pass filter to avoid these PWM pulse gaps.

You need components for this and you need to calculate the right capacitance of the capacitor to use. So I thought, can I change the PWM frequency? YES, you can!

Add this function to your sketch and call this function in the setup routine.

void setMaxPWM()
   /* Attiny85 PWM modification

       Or you can use the PWM library:
       Video  : Arduino PWM Tutorial #2 - How to Set PWM Frequency Accurately - Julian Ilett
       library: https://code.google.com/archive/p/arduino-pwm-frequency-library/downloads
                NOTICE: This library cannot be installed directly from zip, you need to
                extract the PWM directory first and zip it again. After this, put the zip
                into to libraries directory and install the zip via the Arduino IDE.      

    Control Register A for Timer/Counter-0 (Timer/Counter-0 is configured using two registers: A and B)
    TCCR0A is 8 bits: [COM0A1:COM0A0:COM0B1:COM0B0:unused:unused:WGM01:WGM00]
    2<<COM0A0: sets bits COM0A0 and COM0A1, which (in Fast PWM mode) clears OC0A on compare-match, and sets OC0A at BOTTOM
    2<<COM0B0: sets bits COM0B0 and COM0B1, which (in Fast PWM mode) clears OC0B on compare-match, and sets OC0B at BOTTOM
    3<<WGM00: sets bits WGM00 and WGM01, which (when combined with WGM02 from TCCR0B below) enables Fast PWM mode
    TCCR0A = 2<<COM0A0 | 2<<COM0B0 | 3<<WGM00;

    Control Register B for Timer/Counter-0 (Timer/Counter-0 is configured using two registers: A and B)
    TCCR0B is 8 bits: [FOC0A:FOC0B:unused:unused:WGM02:CS02:CS01:CS00]
    0<<WGM02: bit WGM02 remains clear, which (when combined with WGM00 and WGM01 from TCCR0A above) enables Fast PWM mode
    1<<CS00: sets bits CS01 (leaving CS01 and CS02 clear), which tells Timer/Counter-0 to not use a prescalar
    TCCR0B = 0<<WGM02 | 1<<CS00;

    // ---------------------------------------
    // Below we don't use (and need) these because it will screw up the usb connection
    Control Register for Timer/Counter-1 (Timer/Counter-1 is configured with just one register: this one)
    TCCR1 is 8 bits: [CTC1:PWM1A:COM1A1:COM1A0:CS13:CS12:CS11:CS10]
    0<<PWM1A: bit PWM1A remains clear, which prevents Timer/Counter-1 from using pin OC1A (which is shared with OC0B)
    0<<COM1A0: bits COM1A0 and COM1A1 remain clear, which also prevents Timer/Counter-1 from using pin OC1A (see PWM1A above)
    1<<CS10: sets bit CS11 which tells Timer/Counter-1  to not use a prescalar
    //TCCR1 = 0<<PWM1A | 0<<COM1A0 | 1<<CS10;

    General Control Register for Timer/Counter-1 (this is for Timer/Counter-1 and is a poorly named register)
    GTCCR is 8 bits: [TSM:PWM1B:COM1B1:COM1B0:FOC1B:FOC1A:PSR1:PSR0]
    1<<PWM1B: sets bit PWM1B which enables the use of OC1B (since we disabled using OC1A in TCCR1)
    2<<COM1B0: sets bit COM1B1 and leaves COM1B0 clear, which (when in PWM mode) clears OC1B on compare-match, and sets at BOTTOM
    //GTCCR = 1<<PWM1B | 2<<COM1B0;

The example above is for the attiny only and doesn't need a library. The PWM frequency is now above hearing limit (ultra sound frequency) and the audio sounds great! I just show you that vactrols are awesome and the Arduino concept is awesome but overall the Attiny85 capabilities are awesome either (and the community ofcourse that share topics like you and me).

Next thing to do is the problem of analogWrite, the resolution of analogWrite. Because between ON and OFF there is a very high difference, if you do analogWrite( PB1, 1 ); you discover that this is a on/off state instead of a smooth transisition between 0 and >1.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.