LEDs may seem simple, but powering them with just a resistor isn't always the best idea—especially in battery-powered systems or where stable light output is crucial. In this tutorial, we'll learn how to drive an LED using constant current with the help of an op-amp circuit and control it with an Arduino. This ensures stable brightness and avoids unwanted ripple effects on photodiode/photodetectors or ADC readings.
🔍 Why Not Just a Resistor?
A typical LED setup uses a current-limiting resistor in series:
This works fine in simple, regulated systems. But problems arise when:
-
You're using an unregulated power supply with AC ripple.
-
You need precise and stable LED brightness (e.g., in optical sensing).
-
The supply voltage varies, like in battery-powered devices.
In these situations, LED current fluctuates with voltage, causing issues like:
-
Flickering LEDs,
-
Variable brightness,
-
Inconsistent readings in light sensors or ADCs.
✅ The Solution: Constant Current LED Driver
Instead of letting voltage fluctuations affect the LED, we can use a constant current source. This ensures the same current flows through the LED, regardless of voltage changes.
Here’s the formula:
\(I_{LED} = \frac{V_{REF}}{R_s} \)
Where:
-
ILED
is LED current, -
VREF
is the voltage from a reference (or Arduino PWM), -
Rs
is the sense resistor value.
💡 Arduino Application: LED Brightness Control via Constant Current
🧰 What You'll Need
-
Arduino Uno or similar
-
2N3904 or BC547 transistor
-
270-ohm resistor (Rs)
-
White LED
-
External 9V power supply
-
Capacitor (e.g., 1uF) to filter PWM
-
Breadboard and jumper wires
Circuit diagram of the setup is shown below:
🧪 Arduino Code Example
We'll output a filtered PWM signal from Arduino to act as a variable reference voltage, thus controlling the current through the LED.
const int pwmPin = 9; // PWM output for VREF (controls LED current)
const int sensorPin = A0; // ACS712 analog OUT pin
// For ACS712-5A version
const float VREF = 2.5; // No current = 2.5V
const float sensitivity = 0.185; // Volts per Amp for 5A version
void setup() {
pinMode(pwmPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
// Brighten the LED
for (int pwmValue = 0; pwmValue <= 255; pwmValue++) {
analogWrite(pwmPin, pwmValue);
readCurrent();
delayMicroseconds(1); // small delay for visibility and stability
}
// Dim the LED
for (int pwmValue = 255; pwmValue >= 0; pwmValue--) {
analogWrite(pwmPin, pwmValue);
readCurrent();
delayMicroseconds(1);
}
}
void readCurrent() {
int adcValue = analogRead(sensorPin);
float voltage = (adcValue / 1023.0) * 5.0; // Convert ADC to voltage
float current = (voltage - VREF) / sensitivity; // Calculate current in Amps
Serial.print("Current: ");
Serial.print(current, 3);
Serial.println(" A");
}
Use a 1kΩ resistor + 1µF capacitor after the PWM pin to create a low-pass filter and convert PWM to a smooth voltage (VREF). This controls the op-amp circuit.
Video demonstration
Watch the video demonstration of the circuit.
📌 Real-Life Use Case Example
Imagine you're building an optical sensor or infrared barrier where a phototransistor or LDR detects reflected LED light. If the LED current fluctuates with AC ripple or battery voltage, your sensor output will be noisy.
By using this constant current method, you get:
-
✅ More accurate light intensity readings,
-
✅ Consistent brightness over battery discharge,
-
✅ Less ripple/noise in ADC readings.
📚 Summary
Feature | Simple Resistor | Constant Current |
---|---|---|
Easy to implement | ✅ | ❌ (needs more parts) |
Current control | ❌ | ✅ |
Stable light output | ❌ | ✅ |
Use in sensing apps | ❌ | ✅ |
Works with varying supply voltage | ❌ | ✅ |
🚀 Next Steps
-
Try swapping the fixed Rs with a digital potentiometer for dynamic control.
-
Use multiple channels for driving multi-color LEDs uniformly.
-
Integrate with photoresistors or photodiodes or Laser diode for feedback control.