[SOLVED] Which board for dual (CCT) 12-bit Fast PWM dimming

I want to dim a CCT LED strip (2700K - 7000K) using 12-bit Fast PWM to substantially reduce flicker. This can be done for a regular white LED strip with any old Uno as per below, using pin 9, but for CCT LED strip dimming, I need this functionality twice, so to speak. Which board would you suggest to buy?

const byte pinPotentiometer = A0;
const byte pinLDB500LW = 9;
const unsigned int dutyCycleValues[512] = {
  0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   1,   1,   1,   1,   1,   2,
  2,   2,   3,   3,   3,   4,   4,   4,   5,   5,   6,   6,   7,   7,   8,   9,
  9,  10,  11,  11,  12,  13,  13,  14,  15,  16,  17,  18,  19,  20,  21,  21,
  23,  24,  25,  26,  27,  28,  29,  30,  32,  33,  34,  35,  37,  38,  40,  41,
  42,  44,  45,  47,  48,  50,  52,  53,  55,  57,  58,  60,  62,  64,  66,  67,
  69,  71,  73,  75,  77,  79,  81,  83,  85,  88,  90,  92,  94,  96,  99, 101,
  103, 106, 108, 111, 113, 116, 118, 121, 123, 126, 129, 131, 134, 137, 140, 142,
  145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 175, 178, 182, 185, 188, 191,
  195, 198, 202, 205, 208, 212, 215, 219, 223, 226, 230, 234, 237, 241, 245, 249,
  252, 256, 260, 264, 268, 272, 276, 280, 284, 288, 293, 297, 301, 305, 310, 314,
  318, 323, 327, 332, 336, 341, 345, 350, 354, 359, 364, 368, 373, 378, 383, 388,
  393, 397, 402, 407, 412, 417, 423, 428, 433, 438, 443, 449, 454, 459, 465, 470,
  475, 481, 486, 492, 497, 503, 509, 514, 520, 526, 531, 537, 543, 549, 555, 561,
  567, 573, 579, 585, 591, 597, 603, 610, 616, 622, 629, 635, 641, 648, 654, 661,
  667, 674, 680, 687, 694, 700, 707, 714, 721, 728, 735, 741, 748, 755, 762, 769,
  777, 784, 791, 798, 805, 813, 820, 827, 835, 842, 850, 857, 865, 872, 880, 887,
  895, 903, 911, 918, 926, 934, 942, 950, 958, 966, 974, 982, 990, 998, 1006, 1015,
  1023, 1031, 1039, 1048, 1056, 1065, 1073, 1082, 1090, 1099, 1107, 1116, 1125, 1133, 1142, 1151,
  1160, 1169, 1178, 1187, 1196, 1205, 1214, 1223, 1232, 1241, 1250, 1260, 1269, 1278, 1287, 1297,
  1306, 1316, 1325, 1335, 1344, 1354, 1364, 1373, 1383, 1393, 1403, 1413, 1422, 1432, 1442, 1452,
  1462, 1472, 1483, 1493, 1503, 1513, 1523, 1534, 1544, 1554, 1565, 1575, 1586, 1596, 1607, 1617,
  1628, 1639, 1649, 1660, 1671, 1682, 1693, 1704, 1715, 1726, 1737, 1748, 1759, 1770, 1781, 1792,
  1804, 1815, 1826, 1838, 1849, 1860, 1872, 1883, 1895, 1907, 1918, 1930, 1942, 1953, 1965, 1977,
  1989, 2001, 2013, 2025, 2037, 2049, 2061, 2073, 2085, 2097, 2110, 2122, 2134, 2147, 2159, 2172,
  2184, 2197, 2209, 2222, 2234, 2247, 2260, 2273, 2285, 2298, 2311, 2324, 2337, 2350, 2363, 2376,
  2389, 2402, 2416, 2429, 2442, 2455, 2469, 2482, 2496, 2509, 2523, 2536, 2550, 2563, 2577, 2591,
  2605, 2618, 2632, 2646, 2660, 2674, 2688, 2702, 2716, 2730, 2744, 2758, 2773, 2787, 2801, 2816,
  2830, 2844, 2859, 2873, 2888, 2903, 2917, 2932, 2947, 2961, 2976, 2991, 3006, 3021, 3036, 3051,
  3066, 3081, 3096, 3111, 3126, 3142, 3157, 3172, 3188, 3203, 3218, 3234, 3249, 3265, 3281, 3296,
  3312, 3328, 3343, 3359, 3375, 3391, 3407, 3423, 3439, 3455, 3471, 3487, 3503, 3519, 3536, 3552,
  3568, 3585, 3601, 3618, 3634, 3651, 3667, 3684, 3700, 3717, 3734, 3751, 3767, 3784, 3801, 3818,
  3835, 3852, 3869, 3886, 3904, 3921, 3938, 3955, 3973, 3990, 4007, 4025, 4042, 4060, 4077, 4095,
};

void setup()
{
  pinMode(pinLDB500LW, OUTPUT);

  TCCR1A = (1 << COM1A1) | (1 << WGM11);
  TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);

  ICR1 = 4095;

  OCR1A = 0;
}

void loop()
{
  int readingPotentiometer = analogRead(pinPotentiometer) / 2;

  OCR1A = dutyCycleValues[readingPotentiometer];
}

Um. Timer1 on the ATmega328p has TWO output compare pins (Arduino pins 9 and 10) - can't you get pin 10 working just by setting setting up OCR1B as well?

What do you consider "fast".

What frequency is the LED controller/driver able to handle.
With 12-bit PWM, the controller can see 4000 times the frequency of base PWM.
(how narrow is the pulse at PWM 1 or PWM or 4094).

In my experience you won't see "flicker' above ~150Hz, but you see some strobing with fast moving things, like pouring water or fast hand movements.
I run my downlights at 12-bit/500HZ and have no problems with flicker.
Use the default ~1kHz of pin 5,6 of an Arduino Uno R3 or Nano v3.
I doubt you see any difference if you go higher.

@westfw @Wawa

Fast PWM is the Uno's 16-bit timer's (Timer 1) variable frequency mode, so with 16MHz / 4096 (TOP value) I obtain a frequency of 3,9kHz.

I was under the impression that, when 16-bit Timer 1 is "used up" to Fast PWM on pin 9, I cannot Fast PWM (with the same frequency) on another pin - but maybe that's wrong?

Research has shown that TLM ("flicker") can be perceived (not "seen") at far higher frequencies than 2kHz, particularly by young children or people with migraine, but also other individuals, particularly with rapid eye movements.

@Lagom

const byte pinPotentiometer = A0;
const byte pinLDB500LW = 9;
const unsigned int dutyCycleValues[512] = {
  0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   1,   1,   1,   1,   1,   2,
  2,   2,   3,   3,   3,   4,   4,   4,   5,   5,   6,   6,   7,   7,   8,   9,
  9,  10,  11,  11,  12,  13,  13,  14,  15,  16,  17,  18,  19,  20,  21,  21,
  23,  24,  25,  26,  27,  28,  29,  30,  32,  33,  34,  35,  37,  38,  40,  41,
  42,  44,  45,  47,  48,  50,  52,  53,  55,  57,  58,  60,  62,  64,  66,  67,
  69,  71,  73,  75,  77,  79,  81,  83,  85,  88,  90,  92,  94,  96,  99, 101,
  103, 106, 108, 111, 113, 116, 118, 121, 123, 126, 129, 131, 134, 137, 140, 142,
  145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 175, 178, 182, 185, 188, 191,
  195, 198, 202, 205, 208, 212, 215, 219, 223, 226, 230, 234, 237, 241, 245, 249,
  252, 256, 260, 264, 268, 272, 276, 280, 284, 288, 293, 297, 301, 305, 310, 314,
  318, 323, 327, 332, 336, 341, 345, 350, 354, 359, 364, 368, 373, 378, 383, 388,
  393, 397, 402, 407, 412, 417, 423, 428, 433, 438, 443, 449, 454, 459, 465, 470,
  475, 481, 486, 492, 497, 503, 509, 514, 520, 526, 531, 537, 543, 549, 555, 561,
  567, 573, 579, 585, 591, 597, 603, 610, 616, 622, 629, 635, 641, 648, 654, 661,
  667, 674, 680, 687, 694, 700, 707, 714, 721, 728, 735, 741, 748, 755, 762, 769,
  777, 784, 791, 798, 805, 813, 820, 827, 835, 842, 850, 857, 865, 872, 880, 887,
  895, 903, 911, 918, 926, 934, 942, 950, 958, 966, 974, 982, 990, 998, 1006, 1015,
  1023, 1031, 1039, 1048, 1056, 1065, 1073, 1082, 1090, 1099, 1107, 1116, 1125, 1133, 1142, 1151,
  1160, 1169, 1178, 1187, 1196, 1205, 1214, 1223, 1232, 1241, 1250, 1260, 1269, 1278, 1287, 1297,
  1306, 1316, 1325, 1335, 1344, 1354, 1364, 1373, 1383, 1393, 1403, 1413, 1422, 1432, 1442, 1452,
  1462, 1472, 1483, 1493, 1503, 1513, 1523, 1534, 1544, 1554, 1565, 1575, 1586, 1596, 1607, 1617,
  1628, 1639, 1649, 1660, 1671, 1682, 1693, 1704, 1715, 1726, 1737, 1748, 1759, 1770, 1781, 1792,
  1804, 1815, 1826, 1838, 1849, 1860, 1872, 1883, 1895, 1907, 1918, 1930, 1942, 1953, 1965, 1977,
  1989, 2001, 2013, 2025, 2037, 2049, 2061, 2073, 2085, 2097, 2110, 2122, 2134, 2147, 2159, 2172,
  2184, 2197, 2209, 2222, 2234, 2247, 2260, 2273, 2285, 2298, 2311, 2324, 2337, 2350, 2363, 2376,
  2389, 2402, 2416, 2429, 2442, 2455, 2469, 2482, 2496, 2509, 2523, 2536, 2550, 2563, 2577, 2591,
  2605, 2618, 2632, 2646, 2660, 2674, 2688, 2702, 2716, 2730, 2744, 2758, 2773, 2787, 2801, 2816,
  2830, 2844, 2859, 2873, 2888, 2903, 2917, 2932, 2947, 2961, 2976, 2991, 3006, 3021, 3036, 3051,
  3066, 3081, 3096, 3111, 3126, 3142, 3157, 3172, 3188, 3203, 3218, 3234, 3249, 3265, 3281, 3296,
  3312, 3328, 3343, 3359, 3375, 3391, 3407, 3423, 3439, 3455, 3471, 3487, 3503, 3519, 3536, 3552,
  3568, 3585, 3601, 3618, 3634, 3651, 3667, 3684, 3700, 3717, 3734, 3751, 3767, 3784, 3801, 3818,
  3835, 3852, 3869, 3886, 3904, 3921, 3938, 3955, 3973, 3990, 4007, 4025, 4042, 4060, 4077, 4095,
};

void setup()
{
  pinMode(pinLDB500LW, OUTPUT);
  pinMode(10, OUTPUT);

  TCCR1A = (1 << COM1A1) | (1 << WGM11)|(1 << COM1B1);
  TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);

  ICR1 = 4095;

  OCR1A = 0;
  OCR1B = 0;
}

void loop()
{
  int readingPotentiometer = analogRead(pinPotentiometer) / 2;

  OCR1A = dutyCycleValues[readingPotentiometer];
  OCR1B = dutyCycleValues[readingPotentiometer];
}

So it's that simple? I was under the obviously wrong impression it were an "either-or" issue, either OCR1A or OCR1B. Good to know I can simply use both.

f = 16 000 000/(N * (1 + ICR1))
==> f = 16 000 000/(N * (1 + TOP))

So, TOP value = ICR1 = 4095 and NOT 4096.

@GolamMostafa I know, hence I use ICR1 = 4095;. What I meant was 4096 values, from 0 to 4095.

@Lagom


Figure-1:

I am aware of that, but I also asked if the LED driver can handle that.
You can have a high PWM frequency or a 12-bit bit depth, but can the driver do both?
2kHz and 12-bit PWM can have 62.5uS narrow pulses (8 MHz).

I'm not timer expert, but it looks to me like it should work.
SOME of the timer modes, to achieve arbtrary frequencies/etc, will require that you use one of the output compare registers as "TOP", but it looks to me as though the fast PWM mode you are using uses ICR for "TOP", so both OCR pins/registers should work as outputs...
(Worth a try, anyway!)
(You may want 4095 for TOP, btw. Starts at zero, right?)

The LED strip is switched with a MOSFET.

At 0 indeed.

Yes, ICR as TOP, both as outputs from what I've read so far. Have to wait for the CCT strips to arrive though to try it out. First with two pots to mix. Then I want to implement "dim to warm" with a single pot.

It is ICR1 register (Fig-1 of post #9).

@Lagom
An Uno R3 won't do.
Personally I buy something with an ATmega328PB since it has three 16 bit timers but a Mega2560 has four 16 bit timers and is more conventional.

@jim-p Why won't it do? Because it only has one 16-bit timer?

Should not have said won't.
I don't know much about color mixing for color temperature control but if you need to buy something and you want extra flexability such as having different frequencies and phases to the two strips then having more than one 16 bit timer might be worth the extra money.

Maybe OP should use two complementary PWM channels for the two whites.
So when you run both to opposite values, there is no light interruption, no flicker.

@Wawa A CCT LED strip is essentially two LED strips on one physical strip. The "warm" and "cold" string must be PWM'd independently, that much is certain.

In the end, I will use a joystick to control colour mix and brightness.

I fully understand that.
I suggested by setting the two channels to 10%/90% or 50:50 or 80:20, you have no light interruption. Just a tint flicker. Could be easier on the supply too.

I hope you are using bare logic-level FETs, not modules with (slow) opto couplers.