Warm, cool and between
3000K is the yellowish white of a filament bulb, 6500K the bluish white of daylight. Both LEDs lit together give a white between them, and moving duty from one pin to the other moves the colour while the brightness stays put. Half of each is about 4100 K, not the 4750 K halfway would suggest.
Two whites
A white LED is a blue LED under a phosphor that turns part of the blue into yellow and red. How much it converts sets the colour temperature, given in kelvin. The warm LED, 3000K, looks like a filament bulb; the cool one, 6500K, like daylight under cloud.
Every shade between
Move the slider. The sketch behind it gives the warm pin the duty the cool pin does not have, so the two always add up to the same total. The total light stays about the same, because both LEDs run at the same current and the maker bins both for the same light; only the mix moves.
The kelvin shown is an estimate. Mixing two whites gives a colour on the straight line between them, close to the colours of a glowing body but not exactly on them, and the usual way to put a number on it is to average the two in mireds, a million divided by the kelvin. That is why half of each comes out near 4100 K rather than 4750 K: 3000 K is 333 mireds and 6500 K is 154, and halfway is 244, which is 4100 K.
The sketch below walks the same slider from warm to cool on the real board,
a step every second and a half, and prints the estimate at each step:
cool 50 %: warm 85, cool 85, about 4100 K.
What to use it for
Warm light is easier on the eyes at night and flatters wood and skin. Cool light shows colours and fine detail, a solder joint or a small print. A desk lamp that follows the time of day is one sketch: more 6500K in the morning, more 3000K in the evening.
The code
Walks the light from warm to cool in steps of ten percent, a second and a half each, with the two duties always adding up to MAX_DUTY, and prints each step's estimated colour temperature. Change WARM_PIN and COOL_PIN to the pins you wired.
/*
Dual Bright LEDs - warm to cool at one brightness TK95 / /p/tk95
Wiring. Count from the square pad on the TinkerBlock board, parts
up, header at the bottom:
GND -> GND
VCC -> 5V (VBUS on a Pico). It only feeds the LEDs, so 5V is
safe on a 3.3 V board. Never the Uno's 3.3V pin.
3000K -> D9, GPIO 25, GPIO 4 or GP14 (a PWM pin)
6500K -> D10, GPIO 26, GPIO 5 or GP15 (a PWM pin)
Uno, ESP32, ESP32-S3, Pico, in that order.
Arduino IDE
Tools > Board your board, e.g. ESP32S3 Dev Module
Tools > Port the one that appears when you plug in
Tools > USB CDC On Boot Enabled (ESP32-S3 only)
No library needed.
Serial Monitor 115200
*/
// The pins 3000K and 6500K are wired to.
// Uno: 9. ESP32: 25. ESP32-S3: 4. Pico: 14.
const int WARM_PIN = 4;
// Uno: 10. ESP32: 26. ESP32-S3: 5. Pico: 15.
const int COOL_PIN = 5;
// Two thirds of full: the cap for VCC on 5V.
const int MAX_DUTY = 170;
// The mix's colour temperature, estimated by averaging the two
// LEDs in mireds (a million over the kelvin). An approximation.
long mixKelvin(int coolPercent) {
float s = coolPercent / 100.0;
float mired = (1 - s) * (1e6 / 3000) + s * (1e6 / 6500);
return lround(1e6 / mired / 100) * 100;
}
void setup() {
// LOW first: nothing on the board holds the transistors off.
pinMode(WARM_PIN, OUTPUT);
digitalWrite(WARM_PIN, LOW);
pinMode(COOL_PIN, OUTPUT);
digitalWrite(COOL_PIN, LOW);
Serial.begin(115200);
}
void loop() {
// The two duties always add up to MAX_DUTY: the brightness stays,
// the share moves from warm to cool.
for (int p = 0; p <= 100; p += 10) {
int cool = (long)MAX_DUTY * p / 100;
int warm = MAX_DUTY - cool;
analogWrite(WARM_PIN, warm);
analogWrite(COOL_PIN, cool);
Serial.print("cool ");
Serial.print(p);
Serial.print(" %: warm ");
Serial.print(warm);
Serial.print(", cool ");
Serial.print(cool);
Serial.print(", about ");
Serial.print(mixKelvin(p));
Serial.println(" K");
delay(1500);
}
}The kelvin it prints is the mired average, an estimate, not a measurement. setup() drives both pins LOW first; MAX_DUTY is 170, the cap for VCC on 5V. The sketch compiles for an ESP32-S3, an ESP32 and an Uno.
View on GitHub · blocks/tk95-dual-bright-leds/arduino/dual_leds_mix/dual_leds_mix.ino @ v1.8The same walk from warm to cool in MicroPython, with duty_u16 and the same estimate printed at each step.
"""
Dual Bright LEDs - warm to cool at one brightness TK95 / /p/tk95
Wiring. Count from the square pad on the TinkerBlock board, parts
up, header at the bottom:
GND -> GND
VCC -> 5V (VBUS on a Pico). It only feeds the LEDs.
3000K -> GPIO 25 on an ESP32, GPIO 4 on an ESP32-S3, GP14 on a Pico
6500K -> GPIO 26 on an ESP32, GPIO 5 on an ESP32-S3, GP15 on a Pico
Thonny
Run > Configure interpreter MicroPython (ESP32) or
MicroPython (Raspberry Pi Pico)
"""
import time
from machine import Pin, PWM
# GPIO numbers. ESP32: 25 and 26. ESP32-S3: 4 and 5. Pico: 14 and 15.
WARM_PIN = 4
COOL_PIN = 5
# Two thirds of full: the cap for VCC on 5V.
MAX_DUTY = 43690
# LOW first: nothing on the board holds the transistors off.
Pin(WARM_PIN, Pin.OUT, value=0)
Pin(COOL_PIN, Pin.OUT, value=0)
warm = PWM(Pin(WARM_PIN))
cool = PWM(Pin(COOL_PIN))
for led in (warm, cool):
led.freq(1000)
led.duty_u16(0)
def mix_kelvin(percent):
# Averaged in mireds (a million over the kelvin): an approximation.
s = percent / 100
mired = (1 - s) * (1e6 / 3000) + s * (1e6 / 6500)
return round(1e6 / mired / 100) * 100
while True:
# The two duties always add up to MAX_DUTY: the brightness stays,
# the share moves from warm to cool.
for p in range(0, 101, 10):
c = MAX_DUTY * p // 100
w = MAX_DUTY - c
warm.duty_u16(w)
cool.duty_u16(c)
print("cool", p, "%: about", mix_kelvin(p), "K")
time.sleep(1.5)The pin numbers are GPIO numbers: 4 and 5 on an ESP32-S3, 25 and 26 on an ESP32, 14 and 15 on a Pico. MAX_DUTY is 43690, two thirds of 65535.
View on GitHub · blocks/tk95-dual-bright-leds/micropython/dual_leds_mix.py @ v1.8When it does not work
The two LEDs are 3.4 mm apart, so very close to them each lights its own patch. From a hand's width away the two patches overlap and blend. A sheet of paper or frosted plastic in front mixes them at any distance.
It is not meant to. The eye judges colour temperature roughly by a million divided by the kelvin, not by the kelvin, so the warm LED pulls a mix harder than its share. For a mix that looks halfway, give the cool LED more than half.
Keep the ratio and it should not, since both LEDs dim by the same share of each cycle. If one is dimmer than the other at the same duty, that is the spread between parts: the maker bins them from 45 to 70 lumens. Trim the brighter one's duty down a little.
Four wires and a sketch that shows each white and the two together.
The first light →Edit this page — content/books/dual-bright-leds/warm-cool-and-between.mdx
Questions about this product
See what other owners have asked, and read their solutions.
Dual Bright LEDs
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.