LED Color Spectrum Controlled by Potentiometer.

Hi,

So I just got my Arduino Board for Christmas, so I’m trying to code on my own now. What my ultimate goal for this is to have it so that you can sing into a microphone only to have it display the corresponding color.

But for now, I only have a potentiometer, so I am trying to control it so that as you spin the potentiometer it will display a color, going throughout the entire spectrum. But I am not seeing where I’m going wrong in my code…it is green for a vast majority of the time I spin, until I get to the very last part, I think it’s the maximum value of the potentiometer. Once it gets to the very last part it changes to blue, with absolutely no transition. It should be blending through the colors as I spin it.

Here is the code, there are only 768 colors and 1024 values from the potentiometer, which is how I got those values.

const int sensorPin = 0;
const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN = 11;

void setup()
{
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
}

void loop()
{
  int sensorValue;
  sensorValue = analogRead(sensorPin);
  int color;
  color = (sensorValue + 1) / 1024 * 768 - 1;
  int redIntensity;
  int greenIntensity;
  int blueIntensity;
  if (color <= 255)
  {
    redIntensity = 255 - color;
    greenIntensity = color;
    blueIntensity = 0;
  }
  else if (color <= 511)
  {
    redIntensity = 0;
    greenIntensity = 255 - (color - 256);
    blueIntensity = (color - 256);
  }
  else
  {
    redIntensity = (color - 512);
    greenIntensity = 0;
    blueIntensity = 255 - (color - 512);
  }
  
  analogWrite(RED_PIN, redIntensity);
  analogWrite(BLUE_PIN, blueIntensity);
  analogWrite(GREEN_PIN, greenIntensity);
}

Thanks in advance!

Hi

Your formula says (sensorValue + 1) / 1024 * 768 - 1, and when i fill that out in Google, its calculator comes up with this formula: (((sensorValue + 1) / 1024) * 768) - 1 (i filled out 1023 for sensorValue for Google to understand what i want).
This seems to work out to what you want for different sensorValue values.
I don't know if the compiler comes up with the same formula (but i guess it should).
If not, then try to put the braces in those places and see what happens then.

You can also send sensorValue over serial to your pc and have a look in IDE's serial monitor (button on most right position in the blue bar on top).
Serial monitor can be a huge help when debugging.
Might be a bit of a large step yet, but it can really help to find out what's going on.

You want the colors to fade this way:
Red (0) to yellow (128) to green (255) to blue (512) to purple (768), right ?

MAS3:
I don’t know if the compiler comes up with the same formula (but i guess it should).

It should be able to check with the Serial Monitor, right?

MAS3:
Serial monitor can be a huge help when debugging.

I tried adding that so that I could view it…so I slapped this chunk into my code.

  Serial.print("Sensor Value: ");
  Serial.print(sensorValue);
  Serial.print("  Color: ");
  Serial.print(color);

I put that at the way bottom, so the full code now looks like this:

const int sensorPin = 0;
const int RED_PIN = 9;
const int GREEN_PIN = 10;
const int BLUE_PIN = 11;

void setup()
{
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
}

void loop()
{
  int sensorValue;
  sensorValue = analogRead(sensorPin);
  int color;
  color = (sensorValue + 1) / 1024 * 768 - 1;
  int redIntensity;
  int greenIntensity;
  int blueIntensity;
  if (color <= 255)
  {
    redIntensity = 255 - color;
    greenIntensity = color;
    blueIntensity = 0;
  }
  else if (color <= 511)
  {
    redIntensity = 0;
    greenIntensity = 255 - (color - 256);
    blueIntensity = (color - 256);
  }
  else
  {
    redIntensity = (color - 512);
    greenIntensity = 0;
    blueIntensity = 255 - (color - 512);
  }
  
  analogWrite(RED_PIN, redIntensity);
  analogWrite(BLUE_PIN, blueIntensity);
  analogWrite(GREEN_PIN, greenIntensity);
  Serial.print("Sensor Value: ");
  Serial.print(sensorValue);
  Serial.print("  Color: ");
  Serial.print(color);
}

But it is not reading anything back to me in the Serial Monitor. It’s just a blank page.

MAS3:
You want the colors to fade this way:
Red (0) to yellow (128) to green (255) to blue (512) to purple (768), right ?

Yea, something like that!

You didn't start the serial stream. That is why you aren't getting anything on the monitor.

Try adding this into the setup bracket:

Serial.begin(9600);

Also, to make things better readable, change the last line of your print 'routine' as follows.

  Serial.print("Sensor Value: ");
  Serial.print(sensorValue);
  Serial.print("  Color: ");
  Serial.println(color);

The println adds a linefeed, so that the every iteration gets its own line instead of all in one large line.

Aha! There's the problem, thanks for helping with with the Serial Monitor! Don't know how to fix it, but I found it. The color is always -1, unless it is blue in which case it's 767...

The potentiometer's value is moving, just not the colors, is there some 'Sto' like function that I'm missing?

Or is this all that it should need?

  int color;
  color = (sensorValue + 1) / 1024 * 768 - 1);

Try to put those braces in:
(((sensorValue + 1) / 1024) * 768) - 1
Also, in above code you're missing one opening brace (.

Nada.

I even went overboard when that didn't work and added extra braces.

  color = ((((sensorValue + 1) / 1024) * 768) - 1);

Also, in above code you're missing one opening brace (.

Now there are 4 openings and 4 closings.

(1 / 1024)*768 = 0.75
What if you do:

 color = (((sensorValue + 1) *0.75) - 1);

?
Might be faster too.

That works! Interesting how that fixed it, but thank you!

I got it working, had hints of red, and then I added a buzzer to it, I think I burnt out the red bulb...oops.

you might check the HSL / HUE colorpspace and convert it back to RGB.
see also - Need help with RGB rainbow colors - #16 by robtillaart - Programming Questions - Arduino Forum -

Teddy1:
I got it working, had hints of red, and then I added a buzzer to it, I think I burnt out the red bulb...oops.

Did you use a resistor to limit the current through the LED ?
If not, do so for all LEDs from now on.
If you do not limit the current, then you might burn a LED.
You also might burn the output of you Arduino, because is it not supposed to handle more than 20 mA per output.
And there is also a maximum current for all outputs added (i don't know the number off by heart, but with 3 LED s and a buzzer you're not there yet).
These are things you need to consider, because you might destroy parts of the processor of your Arduino if you mess this up.

MAS3:
(1 / 1024)*768 = 0.75
What if you do:

 color = (((sensorValue + 1) *0.75) - 1);

?
Might be faster too.

Hi all,

No, it will be slower in fact. Not that you will be able to notice, but slower.

By using a value with decimal places, the Arduino will have to use floating point maths functions and these are much slower than integer maths functions.

The reason the original code did not work was because both the value to the right and the value to the left of the “/” were both integers. In this situation, the Arduino will integer divide rather than floating point divide because it is more efficient.

In integer division, anything less than 1024, when divided by 1024, will give zero. Only 1024 / 1024 will give 1.

MAS3 was on the right track but went one step too far. X / 1024 * 768 is the same as X / 4 * 3. It is also the same as X * 3 / 4, and that would be a good way to do it. 1 * 3 / 4 = 0, 2 * 3 / 4 = 1, and so on up to 1023 * 3 / 4 = 767. This gets you what you want without floating point maths!

Paul

Hi, isn't the association between sensorValue and color linear?
If so why not calculate, by hand, out a couple of points, then use MAP function.

Tom....... :slight_smile:

TomGeorge:
Hi, isn't the association between sensorValue and color linear?
If so why not calculate, by hand, out a couple of points, then use MAP function.
Tom....... :slight_smile:

becausae it is nonlinear you might need multimap - Arduino Playground - MultiMap -

That makes sense, didn't even consider integer or floating point.
Thanks for explaining that; this is exactly why i'm learning by answering other people's questions.

MAS3 was on the right track but went one step too far. X / 1024 * 768 is the same as X / 4 * 3. It is also the same as X * 3 / 4, and that would be a good way to do it. 1 * 3 / 4 = 0, 2 * 3 / 4 = 1, and so on up to 1023 * 3 / 4 = 767. This gets you what you want without floating point maths!

That works! I didn’t notice the speed, but that makes some sense too.

Did you use a resistor to limit the current through the LED ?

I originally did a 330 Ohm, and then I plugged in a piezo buzzer and the red areas started to get spotty, so I figured that that was because the piezo took power, so I downgraded to a 100 Ohm. Still nada. I’m back at 330.

Also, it seemed to be working, and then I realized, that it should be red to blue, possibly red to red. But I just realized that it is going blue to blue. I think in the code it makes sense that it should go from red to blue…

  if (color <= 255)
  {
    redIntensity = 255 - color;
    greenIntensity = color;
    blueIntensity = 0;
  }
  else if (color <= 511)
  {
    redIntensity = 0;
    greenIntensity = 255 - (color - 256);
    blueIntensity = (color - 256);
  }
  else
  {
    redIntensity = (color - 512);
    greenIntensity = 0;
    blueIntensity = 255 - (color - 512);
  }

Actually, doing the math it looks like it should go red to red. Because the first one would be redIntensity=255-0. And the last would be redIntensity=767-512=255. And the blueIntensity=255-(767-512)=0. Any thoughts on that?

Teddy1:
I originally did a 330 Ohm, and then I plugged in a piezo buzzer and the red areas started to get spotty, so I figured that that was because the piezo took power, so I downgraded to a 100 Ohm. Still nada. I'm back at 330.

Also if you remove the buzzer ?
You've got plenty of pins.
Connect the buzzer to its own pin.
But you always need to know what parts you're using before connecting them.
If you put 2 parts in parallel to each other to 1 output pin, the output current will go up and you need to remember that.

Also, it seemed to be working, and then I realized, that it should be red to blue, possibly red to red. But I just realized that it is going blue to blue. I think in the code it makes sense that it should go from red to blue...

Actually, doing the math it looks like it should go red to red. Because the first one would be redIntensity=255-0. And the last would be redIntensity=767-512=255. And the blueIntensity=255-(767-512)=0. Any thoughts on that?

You're going from 0 to 1023 with your sensorValue.
But because you're subtracting from 255 with red, you're not starting with all off (or 0), so that's good.
Also, you're not using all possible colors, because by the way you are converting you are omitting white (all on).

But to find out what's happening with your colors, extend your debugging a bit and show some more values on serial monitor.

You're going from 0 to 1023 with your sensorValue.
But because you're subtracting from 255 with red, you're not starting with all off (or 0), so that's good.
Also, you're not using all possible colors, because by the way you are converting you are omitting white (all on).

But to find out what's happening with your colors, extend your debugging a bit and show some more values on serial monitor.

I have my serial monitor telling me the value of color..and it has the full range..it goes from 0 to 767, with every number in between. Oh silly me. I flip-flopped the color pins.