LDR as digital control for analog effects - Page 1
Forum section: electronics / projects

author: reinerterig
author_rank: Contributor
timestamp: June 26, 2018, 04:39:05 am
content: I recently got myself some NSL-32s ( they are light sensitive resistors with an LED in the same packet ).The idea is that you can program a preset brightness for the LED resulting in a certain resistance or control the brightness via an encoder. I can use this in a ton of different ways to improve the functionality of my effects.The NSL-32 has a huge range of resistance going into the M-ohms so I can dial in virtually any resistance I need. But the problem is because the range is so huge it is difficult for me to be precise.I need a way to calibrate the NSL-32 and lock in the brightness of my LED to a specific range, say 1K when my encoder is fully closed and 500K when fully open.I know I can limit the brightness of my LED using the resistor from the negative leg to ground and that will certainly help lock down one half of my problem.At the moment I am using an Arduino to adjust the brightness using pwm. with a 220-ohm resistor on my LED I get about 45-ohm on the NSL-32 encoder fully open and when the encoder is fully closed it jumps around from 1M-17M-overload and stays at OL when I pull it back a bit I can get the meter to hover at .470K (470-ohms) but even then it jumps around a little bit.Does anyone have any experience with these LDRs? I would love to stability use them up to 1M.Here is the code I am using it's really straightforward./*Analog input, analog output, serial outputReads an analog input pin, maps the result to a range from 0 to 255 and usesthe result to set the pulse width modulation (PWM) of an output pin.Also prints the results to the Serial Monitor.The circuit:- potentiometer connected to analog pin 0.Center pin of the potentiometer goes to the analog pin.side pins of the potentiometer go to +5V and ground- LED connected from digital pin 9 to groundcreated 29 Dec. 2008modified 9 Apr 2012by Tom IgoeThis example code is in the public domain.http://www.arduino.cc/en/Tutorial/AnalogInOutSerial*/// These constants won't change. They're used to give names to the pins used:const int analogInPin = A0; // Analog input pin that the potentiometer is attached toconst int analogOutPin = 13; // Analog output pin that the LED is attached toint sensorValue = 0; // value read from the potint outputValue = 0; // value output to the PWM (analog out)void setup() {// initialize serial communications at 9600 bps:Serial.begin(9600);}void loop() {// read the analog in value:sensorValue = analogRead(analogInPin);// map it to the range of the analog out:outputValue = map(sensorValue, 0, 1023, 0, 255);// change the analog out value:analogWrite(analogOutPin, outputValue);// print the results to the Serial Monitor:Serial.print("sensor = ");Serial.print(sensorValue);Serial.print("\t output = ");Serial.println(outputValue);// wait 2 milliseconds before the next loop for the analog-to-digital// converter to settle after the last reading:delay(2);}

author: imacgreg
author_rank: Contributor
timestamp: June 26, 2018, 05:53:03 am
content: LDR performance can be all over the place, especially dynamically. When used in an analog compressor/limiter, the compressor is usually in a feedback configuration which helps correct for this. Check out the Urei LA-3A design. In the compressor designs, a second matched LDR is used to indicate amount of gain reduction via a meter. These were typically 2x LDR sandwiched up next to an EL panel (night-light backlight).Perhaps you could drive two matched LDRs and use an ADC to read the value of the second LDR as a kind of feedback. Or, you could have some sort of calibration sequence built in place that sweeps through the control range, reads the value of the LDR, and uses that data to more accurately control the LDR. The datasheet seems pretty light on precision.At the very least, you'd want to map the resistance vs PWM duty on a bunch of these to see if it's linear/log and how well they match.Another issue you may have is the control signal leaking into the audio path. I seem to recall this happening with the compressor, but it's not as bad because the LDR was driven by some processed version of the audio signal is was controlling.If this is an issue, using a PWM frequency >20kHz will move the fundamental to an inaudible frequency as well as all the switching harmonics, of which there will be many.Most of my experience is with the parts used in the T4B opto cell used in the LA3 and LA2 compressors. Would not be surprised if the parts you referenced have better performance.

author: Conrad Hoffman
author_rank: Super Contributor
timestamp: June 26, 2018, 03:28:02 pm
content: LEDs in control applications usually work best if driven with a V/I converter. Putting them in the FB of a medium power opamp works. The LDRs I've seen suffer from high THD, though that may not matter in your applications.

author: reinerterig
author_rank: Contributor
timestamp: June 27, 2018, 06:02:15 am
content: Before I got the LDRs I looked at a bunch of different options DIGI-Pots has a limit to the amount of voltage you can push through them --usually quite small- whereas these LDRs can take up to 60V.I solved my problem!first of all, I was using a 220-ohm resistor which gives me 22mA of current at 5V and 4mA at 1V resulting in a range of about 40-200 Ohms ( not impressive )I swapped out the resistor on the LED to a 100K giving me 0.01mA at 1V and 0.05mA at 5V taking my range up into the K-ohms ( I can't remember the exact values but the datasheet has a graph and I remember it being pretty spot on)Also, my code ranges from 0-255. 0 is a problem because that turns my LED off that's why my resistance read as an overload. So I changed it to range from 4-255 and things were way more stable. By stable I mean when applying a voltage the resistance drifts within 1ohm ( not bad at all ).I was playing around with a gain circuit a couple of days ago and I pulled out the resistor in the feedback loop and replaced it with the LDR. Using the code above the LDR reacted quickly as I changed the value of the POT and it sounded pretty stable. I changed the code to an LFO I found online ( I'll post that below ). --BTW, If anyone can point me to a lesson that can show me how to create waveforms using PWM and change the Freq. That would be appreciated.-- All in all, it was a pretty good tremolo and a solid proof of concept.// 3 phase PWM sine// (c) 2016 C. Masenas// Modified from original DDS from:// KHM 2009 / Martin Nawrath// table of 256 sine values / one sine period / stored in flash memoryPROGMEM const unsigned char sine256[] = {127,130,133,136,139,143,146,149,152,155,158,161,16 4,167,170,173,176,178,181,184,187,190,192,195,198, 200,203,205,208,210,212,215,217,219,221,223,225,22 7,229,231,233,234,236,238,239,240,242,243,244,245,247,248,249,249,250,251,252,252,25 3,253,253,254,254,254,254,254,254,254,253,253,253, 252,252,251,250,249,249,248,247,245,244,243,242,24 0,239,238,236,234,233,231,229,227,225,223,221,219,217,215,212,210,208,205,203,200,198,195,19 2,190,187,184,181,178,176,173,170,167,164,161,158, 155,152,149,146,143,139,136,133,130,127,124,121,11 8,115,111,108,105,102,99,96,93,90,87,84,81,78,76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35 ,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7, 6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5, 5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73 ,76,78,81,84,87,90,93,96,99,102,105,108,111,115,11 8,121,124};#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))int testPin = 7;int enablePin = 6 ;volatile float freq=1;const float refclk=122.549 ; // 16 MHz/510/256// variables used inside interrupt service declared as voilatilevolatile unsigned long sigma; // phase accumulatorvolatile unsigned long delta; // phase incrementbyte phase0, phase1, phase2 ;void setup(){Serial.begin(9600); // connect to the serial portSerial.println("DDS Test");pinMode(enablePin, OUTPUT); // sets the digital pin as outputpinMode(testPin, OUTPUT); // sets the digital pin as outputpinMode(12, OUTPUT); // pin9= PWM output / frequency outputpinMode(10, OUTPUT); // pin10= PWM output / frequency outputpinMode(11, OUTPUT); // pin11= PWM output / frequency outputSetup_timer2();Setup_timer1();digitalWrite(enablePin, HIGH);// the waveform index is the highest 8 bits of sigma// choose refclk as freq to increment the lsb of the 8 highest bits// for every call to the ISR of timer2 overflow// the lsb of the 8 highest bits is 1<<24 (1LL<<24 for long integer literal)delta = (1LL<<24)*freq/refclk ;}void loop(){changeFreq(3);}void changeFreq(float _freq){cbi (TIMSK2,TOIE2); // disable timer2 overflow detectfreq = _freq;delta=(1LL<<24)*freq/refclk; // update phase incrementsbi (TIMSK2,TOIE2); // enable timer2 overflow detect}//************************************************** ****************// timer2 setup// set prscaler to 1, fast PWMvoid Setup_timer2() {// Timer2 Clock Prescaler to : 1sbi (TCCR2B, CS20); // setcbi (TCCR2B, CS21); // clearcbi (TCCR2B, CS22);// Timer2 PWM Modecbi (TCCR2A, COM2A0); // clear OC2A on Compare Match, PWM pin 11sbi (TCCR2A, COM2A1);// set to fast PWMsbi (TCCR2A, WGM20); // Mode 1, phase correct PWMcbi (TCCR2A, WGM21);cbi (TCCR2B, WGM22);sbi (TIMSK2,TOIE2); // enable overflow detect}// timer1 setup (sets pins 9 and 10)// set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clockvoid Setup_timer1() {// Timer1 Clock Prescaler to : 1sbi (TCCR1B, CS10);cbi (TCCR1B, CS11);cbi (TCCR1B, CS12);// Timer1 PWM Mode set to Phase Correct PWMcbi (TCCR1A, COM1A0); // clear OC1A on Compare Match, PWM pin 9sbi (TCCR1A, COM1A1);cbi (TCCR1A, COM1B0); // clear OC1B on Compare Match, PWM pin 10sbi (TCCR1A, COM1B1);sbi (TCCR1A, WGM10); // Mode 1 / phase correct PWMcbi (TCCR1A, WGM11);cbi (TCCR1B, WGM12);cbi (TCCR1B, WGM13);}//************************************************** ****************// Timer2 Interrupt Service at 31372,550 KHz = 32uSec// this is the timebase REFCLOCK for the DDS generator// runtime : 8 microseconds ( inclusive push and pop)// OC2A - pin 11// OC1B - pin 10// OC1A - pin 9//https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWMISR(TIMER2_OVF_vect) {sbi(PORTD,testPin);sigma=sigma+delta; // soft DDS, phase accu with 32 bitsphase0=sigma >> 24; // use upper 8 bits for phase accu as frequency information// read value fron ROM sine table and send to PWM DACphase1 = phase0 +85 ;phase2 = phase0 +170 ;OCR2A=pgm_read_byte_near(sine256 + phase0); // pwm pin 11OCR1B=pgm_read_byte_near(sine256 + phase1); // pwm pin 10OCR1A=pgm_read_byte_near(sine256 + phase2); // pwm pin 9cbi(PORTD,testPin);}

author: b_force
author_rank: Super Contributor
timestamp: June 27, 2018, 01:40:55 pm
content: Just in general I wouldn't really use LDRs anymore, since they aren't RoHS compliant, which means they will or are absolute in many cases.In what kind of context can I see this project?Sound something like a tremelo/vibrato effect pedal?In that case there are a lot of (digital) volume controlled opamps en potentiometers you can use, or something like a PGA.The LM1971 is more than good enough for guitar purposes.If you don't bother going digital, there are a ton of DSP chips you can go for.

author: reinerterig
author_rank: Contributor
timestamp: June 28, 2018, 11:21:22 am
content: Quote from: b_force on June 27, 2018, 01:40:55 pmThe idea is to keep an analog signal path but have digital control.a tremolo is the easiest use for this but there are so much more applications. Chase Bliss Audio is in my opinion at the forefront of this, take a look and you will have a pretty good idea of the end goal.

author: b_force
author_rank: Super Contributor
timestamp: June 28, 2018, 11:41:28 am
content: Quote from: reinerterig on June 28, 2018, 11:21:22 amA voltage controlled amplifier (VCA) or these volume/potentiometer ICs still work in the analog domain (there is no analog to digital/digital to analog conversion), so you'll still have an analog path.The Maxim DS1882 is also a good alternative.

author: reinerterig
author_rank: Contributor
timestamp: June 28, 2018, 12:04:50 pm
content: Let's move away from amplification. What if I wanted automated filtered sweeps, or stepped delay times?

author: b_force
author_rank: Super Contributor
timestamp: June 28, 2018, 01:50:37 pm
content: Quote from: reinerterig on June 28, 2018, 12:04:50 pmWho is talking about amplification?What I am trying to tell is that a lot of things that an LDR can do, is also possible with the other examples.Another good example is a Wah (which is nothing more than a shifted bandpass filter)Although in that case just a normal potentiometer would do the job just fine

author: Bassman59
author_rank: Super Contributor
timestamp: June 28, 2018, 02:58:43 pm
content: Quote from: reinerterig on June 28, 2018, 12:04:50 pmIf the application requires a variable resistance, a digital pot will work.The deal with LDRs for audio compressors is that their response time is “interesting,” in that the resulting sound is something users like.For filter sweeps and such, then a digital pot is more precise and more repeatable. A downside is the step size; the LDR is continuous (assuming analog control of the LED), although what step precision you need is application dependent.