Go Down

Topic: RGB Thermometer needs more drastic change (Read 5966 times) previous topic - next topic

acegard

Sep 09, 2013, 04:40 pm Last Edit: Sep 09, 2013, 04:43 pm by acegard Reason: 1
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:
Code: [Select]
               //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.

jack wp

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?

acegard

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).

Grumpy_Mike

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.

Paul__B

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.

PaulRB

#5
Sep 10, 2013, 12:07 am Last Edit: Sep 10, 2013, 12:09 am by PaulRB Reason: 1
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

acegard

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

jack wp

map() can change one group of numbers to another group of numbers. Have you looked at it in
http://arduino.cc/en/Reference/HomePage ?
If you don't understand how it works after looking it up, let us know your question.

acegard

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.

acegard

#9
Sep 10, 2013, 03:37 am Last Edit: Sep 10, 2013, 03:41 am by acegard Reason: 1
After looking at this page, I believe I know what map() does. Now, would I map it like this:
Code: [Select]
intensity = map(intensity, fromLow, fromHigh, toLow, toHigh);

Or by using this:

Code: [Select]
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)?

jack wp

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

Code: [Select]

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?

acegard

Yes! Yes yes yes.  XD Thank you.

I think I now understand map():

Code: [Select]
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.

jack wp

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.

acegard

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

jack wp

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

Go Up