RGB Thermometer needs more drastic change

Hello,

I am making, as a side project, a case mod thermometer for my computer using an Arduino Uno, a TMP36g sensor, and RGB LEDs. for the most part, everything is working out fine, except for the way I am actually changing the color on the LED - it's too little a change in between the increments I've set for it. (i.e., at the four main temperature increments I've set for it, there is a drastic change - it flips almost instantly from bluish to reddish - and in between those the change is too small to really be noticed until it hits the next major temperature and "flips" again.)

Here is my current code:

                //TMP36 Pin Variables
int sensorPin = 0; //the analog pin the TMP36's Vout (sense) pin is connected to
                        //the resolution is 10 mV / degree centigrade with a
                        //500 mV offset to allow for negative temperatures
 
int greenLed = 5;  // green LED pin
int redLed = 3;  // red LED pin
int blueLed = 6; //blue LED

int redIntensity = 0; //intensity of red, blue, and green
int blueIntensity = 0; 
int greenIntensity = 0;


void setup()
{
  Serial.begin(9600);  
                       
  pinMode(greenLed, OUTPUT);
  pinMode(blueLed, OUTPUT);
  pinMode(redLed, OUTPUT);
  
}
void loop()    
{
 //getting the voltage reading from the temperature sensor
 int reading = analogRead(sensorPin);  
 
 // converting that reading to voltage
 float voltage = reading * 5.0;
 voltage /= 1024.0; 
 
 //print out the reading 
 
 //Serial.print(reading);Serial.println(" reading");
 // print out the voltage
 //Serial.print(voltage); Serial.println(" volts");
 
 // now print out the temperature
 float temperatureC = (voltage - 0.5) * 100 ;  //converting from 10 mv per degree wit 500 mV offset
                                               //to degrees ((volatge - 500mV) times 100)
 //Serial.print(temperatureC); Serial.println(" degrees C");
 
 // now convert to Fahrenheight
 float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;
 Serial.print(temperatureF); Serial.println(" degrees F");
 

  if (temperatureF >= 99.99){
    blueIntensity = 30;
    greenIntensity = 170-temperatureF;
    redIntensity = temperatureF*2;
  } 
  else if (temperatureF >= 79.99){
      greenIntensity = temperatureF*2;
      redIntensity = temperatureF/3 + 20;
      blueIntensity = 59;
  } 

  else if (temperatureF >= 69.99){
        greenIntensity = temperatureF/2;
        blueIntensity = temperatureF /2 +20;
        redIntensity = 0;
  }
  else {
        // we know temperatureF must be <= 69.98 if it gets to here
        greenIntensity = temperatureF - 10;
        redIntensity = temperatureF-10;
        blueIntensity = temperatureF+10;
  }
  
  Serial.print(redIntensity);Serial.println(" Red");
  Serial.print(greenIntensity);Serial.println(" Green");
  Serial.print(blueIntensity);Serial.println(" Blue");
  Serial.println();
  
  redIntensity = constrain(redIntensity, 0, 255);
  greenIntensity = constrain(greenIntensity, 0, 255);
  blueIntensity = constrain(blueIntensity, 0, 255);
  analogWrite(redLed, redIntensity);
  analogWrite(blueLed, blueIntensity);
  analogWrite(greenLed, greenIntensity);
  
 delay(300);                                     //waiting 
}

I have been tinkering with the if-else statements and the color changing code in them for hours and cannot get it right. Does anyone have any ideas?

Thank you.

RGB leds?
Is that one component, with 4 legs?
Is it common cathode (common hooked to ground)?
Do you have a resistor on each of the three other legs, and what values?
In words, what do you expect/want to happen at different temps?

Yep, I'm using RGB LEDs (Common cathode). I have a 1kOhm resistor in series with each of the legs. I want the color of the LEDs to smoothly transition from blue to green to yellow to red as the temperature read by the sensor increases (with a temperature range of about 60 - 150 degrees Fahrenheit).

The main problem is that the perceived colour of an LED depends on other colours you can see at the same time.
You need to look up the concept of gamma correction and then look at the colour model you want to use, RGB cubic space or Hex cone space. Wikipedia is a good source of information on all three topics.
Once you know what you want to do then you can think about coading it, not before.

Or you can write - or find - a piece of code which allows you to type simple single letter commands into the serial monitor such as "r" to reduce the red, "R" to increase it and responds with the numeric values presently being delivered to the LED so that you can experiment with the colours and determine your critical points, write them down and adjust your purpose code accordingly.

Start by writing out a table on paper.

In the first column, write the important temperature points, eg. 60 and below; 70; 80; 100; 150 and above.

In the second column, write the colour you want at each temp point, eg. Blue; green; yellow; red.

In the third, fourth and fifth columns, write the red, green and blue values needed to display the desired colour.

Then amend your if/else statements to match the temperature ranges, like you have already.

In each range, use the map () function to calculate each of the red, green and blue values, refering to your table for the lower and upper limits.

You should not then need to use the constrain () function.

Paul

Thanks, that's really helpful. What exactly does the map() function do?

map() can change one group of numbers to another group of numbers. Have you looked at it in
Arduino - Home ?
If you don't understand how it works after looking it up, let us know your question.

I have tried looking it up, and I'm still not sure exactly how it's supposed to work - it doesn't seem to change the range of values a variable can take, because it doesn't actually constrain it to those values.

The example given in the reference also doesn't really tell me what it actually does - if someone could perhaps explain what it outputs and what the map() function returns that might be helpful.

Thanks for your help. I'm still kind of new to Arduino.

After looking at this page, I believe I know what map() does. Now, would I map it like this:

intensity = map(intensity, fromLow, fromHigh, toLow, toHigh);

Or by using this:

intensity = map(temperatureF, fromLow, fromHigh, toLow, toHigh);

Where, say, the temperature would be from 50 to 75 (fromLow = 50 and fromHigh = 75) and that's mapped to intensity where toLow and toHigh are the lower and upper limits of the output values for the specific color I want (say, from 128 to 255)?

Yea, that last link leaves me a bit confused to. I am no expert on map() but let me try an example.
All this is integer math with no rounding.

Say between 70 and 80 degrees, A variance of 10, you want one of the colored leds to increase PWM duty cycle from 20 to 246

pwmGreenValue = map(Temp, 70, 80, 20,246);

So at 70 degrees the pwm output should be 20.
At 75 degrees the pwm output should be half way between 20 and 246 (you do the math)
At 80 degrees the pwm output should be 246.

Does that make sense?

Yes! Yes yes yes. XD Thank you.

I think I now understand map():

int out = map(in, inLow, inHigh, outLow, outHigh);

maps the variable in, when inside a given range inLow -> inHigh, to the variable out, constraining the output of the function to outLow -> outHigh and assigning values of out based on equidistant ranges of in.

Sounds like you pretty much understand it, but, I don't think it provides constraining.
If your in is greater than the inHigh, the out will be greater than the outHigh.
If you require constraining, you meed to do it outside of map().
I am happy if I helped.

So, it does not constrain, but only provides guidelines for scaling the output range to the input range?

I believe you summed it up better than any page I have read about map() yet.
Great!

acegard:
So, it does not constrain, but only provides guidelines for scaling the output range to the input range?

Yes, you are correct. But combined with your if/else statements, you can constrain values. You know that "out" will always be between "outLow" and "outHigh" because each of your if statements are ensuring that "in" is between "inLow" and "inHigh" for each range.

Paul