I have recently been working on a more advanced version of my EasyTTL stimulator, this time including a dimming control for the TTL output. This is crucial if we wish to control our LED brightness for optogenetics.
Quick lesson on electronics: how do we adjust the brightness of an LED? The typical answer is to say “Adjust the voltage across the LED, or adjust the resistance of the circuit”, and in the simplest terms this will change the power the LED can use. But, it’s not a reliable way to do this, because of the exponential increase in light output across a narrow voltage range (Figure 1); with the LED I’ve shown here, a voltage change of 0.5 V will take you from very low current and negligible light output to maximal output. Furthermore, LED’s get hot during use, which changes their properties and makes them produce more light at the same voltage – this is not only terrible for ensuring precise brightness output, it can also lead to runaway heating and the LED burning out.
So, how do we fix this? This is really the whole point of using a TTL control device. The LED (or laser) is set up to drive a constant current (and it’s the current which determines the actual amount of light being produced), and then you pulse a controlling input to switch the light source on and off as you please. What this means is that a TTL is a very simple digital signal, on or off, with no information about the intensity of the signal.
So, what is an easy way to control an LED brightness for optogenetics? One answer is to use Pulse Width Modulation (PWM), which produces small pulses within your signal, but faster than your eye can detect. Essentially, you’re turning the LED on and off very fast (hundreds or thousands of times a second), and you control the brightness by adjusting the relative levels of on and off. More “on” and it’s brighter, more “off” and it’s dimmer. Simples.
Here’s how I’ve put PWM control into an Arduino Uno (Figure 2). It uses a potentiometer (also known as a variable resistor), but rather than connect directly to the LED output, we connect this to an analog input on the Arduino. The Arduino can then read the value of the potentiometer and using software we can drive an appropriate PWM output on our TTL signal.
See below for the code I wrote to control the circuit. We very simply set the LED as an output and the potentiometer as an analog input (read as “sensorValue”) – the reading needs to be adjusted by a factor of 4 to take into account the change in “bit” rate; essentially it reads the analog input on a different scale than it drives PWM output. Helpfully, Arduino has a built-in PWM function called “analogWrite”, which will drive a 490 Hz PWM based on your value.
Setting up a PWM manually is of course possible, but more of a pain. However, it is something I am likely to do in the future because, as the sharp-eyed among you may have noticed, 490 Hz produces PWM widths of around 1 ms, so it only works for pulses that are longer than that. In fact, I wouldn’t want to use it for pulses much shorter than 10 ms, because it will make the brightness output unstable from one pulse to the next. However, for the immediate future, I’m not overly bothered because I never use a pulse shorter than 10 ms anyway and the PWM produces fantastic brightness control at those speeds.
I hope you’ve found this post interesting, and I would absolutely recommend any readers to buy themselves an Arduino and some components and try this out, see how easy it is to control your LED brightness for optogenetics. However, if you do want an easy-to-use TTL driver for your optogenetics system but don’t want the hassle of building one yourself, I am planning to build some myself and make them available on this website at a reasonable cost.
EDIT 3/9/21: Doing some further investigations today, I found that the Arduino Mega has 980 Hz PWM control from pins 4 and 13, so I will connect 2 of the TTL outputs from my EasyTTL Mega device to those pins instead. This means that you will have access to higher resolution PWM control from TTL outputs 1 and 2, and should work well with on-times of 5 ms, and would probably be acceptable (but not perfect) for 2 ms on-times.