How to make smooth LED transition.

You could use an EMA. Keep in mind that it introduces some latency (as do all real low-pass filters).

/*
  Exponential Moving Average filter (single-pole IIR filter)

  Difference equation:
      y[n] = k*x[n] + (1-k)*y[n-1]

    where y[n] is the filtered output at time n,
    and x[n] the raw input at time n
    y[n-1] is the previous filtered output.

  k == 0.5^shiftFac

  Fixed point arithmetic is used for speed.
    1 == 1 << (2*shiftFac)
  Two times shiftFac because otherwise, precision
  would be lost when shifting (value - filtered).

  Rounding is performed by adding 0.5 to the
  fixed point representation before converting
  to an integer.
    0.5 == 1 << (2*shiftFac - 1)
*/
class EMA {
  public:
    /* Constructor: Initialize constants */
    EMA(uint8_t shiftFac)
      : shiftFac(shiftFac), fixedPointAHalf(1 << ((shiftFac * 2) - 1)) {}

    /* Filter a new raw input value x[n] and return the filtered output y[n].
      Should be called at regular intervals for best results. */
    int32_t filter(int32_t value) {
      value = value << (shiftFac * 2);
      filtered = filtered + ((value - filtered) >> shiftFac);
      return (filtered + fixedPointAHalf) >> (shiftFac * 2);
    }

  private:
    /* Member variables */
    const uint8_t shiftFac;
    const int32_t fixedPointAHalf;
    int32_t filtered = 0;
};

EMA ema(4); // k = 0.5^4 = 0.0625

const unsigned long interval = 10000; // sample every 10 milliseconds

void measureAndFilter() {
  int x = analogRead(A0);
  int y = ema.filter(x);
  Serial.println(y);  
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  static unsigned long previousMicros = micros();
  if (micros() - previousMicros > interval) { // sample at precise interval
    measureAndFilter();
    previousMicros += interval;
  }
}

Pieter