The RGB LED is supposed to be controlled by PWM, how can I map the position of a potentiometer to a color combination?

  • \$\begingroup\$ You can't. The pot provides a 1-dimensional setting, which can't possibly cover all points in a 3-dimensional space. \$\endgroup\$ – Olin Lathrop Dec 31 '13 at 14:50
  • \$\begingroup\$ If you could change your requirements to "using 3 pots to control an RGB LED", this would be a very easy question to answer. \$\endgroup\$ – TimH - Codidact Dec 31 '13 at 16:37
  • \$\begingroup\$ Really guys? A single pot can easily scroll through a few bits of resolution or fixed colors. I doubt OP is asking for 128bit resolution on each channel. \$\endgroup\$ – Passerby Dec 31 '13 at 17:19
  • \$\begingroup\$ @Passe: No, he wants infinitely more than 128 bit resolution. He specifically asked for all colors (see title). You can map some values of a 3D space into a 1D space, but not all of them. \$\endgroup\$ – Olin Lathrop Dec 31 '13 at 22:50

To begin with, there is no definitive discrete set of "all colors" for an RGB LED: Each of the emitters, red, blue and green, can essentially be varied through an infinite set of interim values from fully off to fully lit.

If we were to simplify the problem statement per the convenience of fitting into Arduino's library functions for reading analog values and writing PWM values, it boils down to this:

  • The ADC pin hooked up to the potentiometer can read 1024 distinct values in an ideal case: AnalogRead() returns an integer between 0 and 1023, i.e. 10-bit unsigned value
  • The PWM pins can each accept values between 0 and 255: AnalogWrite() accepts an 8-bit unsigned integer value. Thus, 24 bits to describe all possible RGB values supported by Arduino library functions.

Thus, a reasonable approach would map the 10 bit input value to 8 x 3 = 24 bits for output.

Since the human eye is most sensitive to green, one proposed mapping would be 3 bits each, from the input value, for red and blue, 4 bits for green - each mapped to 8 bits for the red, green and blue AnalogWrite() values.

redVal = (inputVal >> 2) & 0xE0; // Values 0, 32, 64, 96 ... 224
grnVal = (inputVal << 1) & 0x78; // Values 0, 16, 32, 48 ... 240
bluVal = (inputVal << 5) & 0xE0; // Values 0, 32, 64, 96 ... 224

This would provide a simple way of traversing most of the possible RGB values within the constraints of simplicity and Arduino library functions.

The transition will not, of course, be a smooth traversal across hues. If that too is a requirement, then a color mapping into Hue-Luminescence-Saturation is called for.

| improve this answer | |

Mapping a three dimensional space to a single dimension is inherently difficult!

I'd use an HSV model and use the pot to vary H for fixed S and V. I'd Google for an algorithm to translate HSV to RGB and implement that in the Arduino.

I'm assuming you know how to connect pots to ADC inputs and read them. Also that you know how to connect RGB LEDs and drive them.

| improve this answer | |

The hardest part of the 'problem' is deciding how to map an inherently 3D colour space onto a single dimension in a way that is useful and 'meaningful'. There are many possible ways - and most will not be overly user friendly or intuitive. Here is one possible way -

Below say N1 = 9 and N2 = 10.
Here I have suggested a linear mapping with pot position and equal R G B max amplitudes. In practice some other "law" is liable to produce better results, but this is easily added as an extra level of "abstraction" to the basic system.

Have eg R increase in N1 steps across the whole pot range.
Have eg G vary from zero to max in N2 steps for each of the N1 levels of R Have eg B vary from zero to max N2 times for each step of G. B may have as many or as few levels per step in G as is desired.

Say pot has 360 degree angle variation - adjust figures to suit.
Say N1 = 9 so G varies from min to max 9 times across a 360 degree sweep so one cycle of G occurs over 360/9 = 40 degrees.
If N2 = 10 then B will increase from 0 to max every 40/10 = 4 degrees.

The end affect of this is

  • R will increase in 9 x 40 degree steps across 360 degree sweep.
  • G will vary across 0-100% once per 40 degree step.
    So eg G_10 = G_50 = G210 ...
  • B will vary across 0-100% every 4 degrees.


A full sweep of the pot will give you 0-100% of R
Across each 40 degrees R will be constant and G will vary from 0-100%.
Across each 4 degree R & G will be constant and B will vary from 0-100%.

With due care any colour combination will be able to be "dialled up" subject only to the chosen resolutions.

This will not be totally intuitive to use, but it is most unlikely that anything will be. Use of 2 or 3 pots or similar would be preferable.

| improve this answer | |

The FastLED library is great. It even has examples for Analog RGB strips. Very simply to hook up a potentiometer and have a strip cycle through Hues based on the Pot rotation.


| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.