How to dim SMD LED more than with PWM of arduino?

Hallo guys,

in my project I use an accelerometer conected with the arduino uno and some SMD LEDs. I would like that the brightness of the SMD LEDs goes along with the data of the accelerometer.

I already programed it and used the PWM of the Arduino (brightness from 1 - 255 to dim it with switching the power on and off that it seems for the human like its dimed).

My problem is now that it's not dimed enough for my use. I would like to have a smooth transition from dark to bright, but at the moment it starts already to bright. Even if I just take a single SMD LED and higher slowly the voltage it first doesn't shine and when it starts its already kind of bright.

I read on the internet that its not possible with every led to dim it at e.g. 1% of the brightness.

Do you know a possibility how to dim a SMD LED to e.g. 1% of the brightness or do you know any SMD LEDs with which it's possible?

Thank you for helping!

(I'm using: Accelerometer: Adxl345 Arduino Uno A resistor SMD LED: SMD LEDS 0603 - 1,6mm * 0,8mm warm white - 3,0V - 3,2V, 20 mA avarage brightness ca 640 mcd, Color temperature ca 3000 K)

you can increase the size of the resistor to limit it's max brightness.

You could use the good old 555 timer dimming circuit and let your microcontroller take the role of R2 and R3, or switch to a more modern type of LED that can be controlled by the FastLED library, or switch to a COB LED and then simply use a dimmable CC-PSU with its PWM input controlled by your microcontroller. See also LED fading issues here.

Arduino have a few 16 bit PWM channels, that means 65536 brightness steps, but it is a very limited resource.

Just use two PWM pins, the second with, say, a resistor of 16 times the value of the first, to the same LED.

Here is some code for 16 bit PWM on a UNO or Nano:

// It is a skeleton for handling 16 bit pwm and depending on processor there will be 2
// Analog A0 is used as a test input.

// This is for UNO and Nano processor
const byte pwm1pin = 9;     // PB1, OC1A
const byte pwm2pin = 10;    // PB2, OC1B

// This is the maximum PWM value and means the PWM frequency is around 244Hz.
// Reducing this value will increase the PWM frequency and reduce the number of steps
const uint16_t MAX_PWM_VALUE = 65535U;

//----------------------------------------------------------------------------------------------------
// Setup timers for 16 bit PWM
void initPWM() {
  noInterrupts();
  TCCR1A = 1 << WGM11 | 1 << COM1A1 | 1 << COM1B1; // set on top, clear OC on compare match
  TCCR1B = 1 << CS10  | 1 << WGM12 | 1 << WGM13;   // clk/1, mode 14 fast PWM
  ICR1 = MAX_PWM_VALUE;
  interrupts();
  pinMode(pwm1pin, OUTPUT);
  pinMode(pwm2pin, OUTPUT);
}

//----------------------------------------------------------------------------------------------------
// Set a 16 bit PWM value for a channel
void setPWM(byte no, uint16_t pwm) {
  noInterrupts();
  switch (no) {
    case 0 :
      OCR1A = pwm;
      break;
    case 1 :
      OCR1B = pwm;
      break;
  }
  interrupts();
}

//----------------------------------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.println("Starting...");
  initPWM();
}

//----------------------------------------------------------------------------------------------------
// Use A0 as test input
void loop() {
  setPWM(0, map(analogRead(A0), 0, 1023, 0, MAX_PWM_VALUE));
  delay(50);

}

There is a bit explanation to it on my website including support for ProMicro (ATmega32U4) and Mega.

There is also some code to make brightness adjustment logarithmic, this is very useful to get a better adjustment range.

Thank you HKJ-Iygte. It works well with this code!