Adding a gradient to Temperature sensitive RGB LEDs

Hey everyone,
I'm making a project around an LM355Z temperature sensor module. At the moment, any noise in the sensor makes the LEDs flicker noticeably so I want to do something to fix that.

The Temp sensor connects to an arduino UNO, which drives 3 NPN transistors (R, G and B).

Is there some code I could write to make the flickering smoother? or would it be better to add some kind of capacitor somewhere (either between the sensor and the arduino or between the arduino and the transistor gates)?

Please post real schematics, not toy Fritzings.
When noise is present, attack the noise at the source.
Decoupling capacitors are often needed..... Just to know where to attach them.

1 Like

How are the transistors driven and what are they supposed to do? Please post the code, using code tags, and a schematic diagram.

Transistors are NPN driven from the arduino with 860 ohm resistors to the gates.
Not sure how to draw a schematic on a computer, so have this whiteboard drawing :stuck_out_tongue:
D8,9 and 10 are digital pins and A1 and A0 are analog pins to the arduino.

Here's the code, all the LCD isn't connected atm
sketch_may04b.ino (1018 Bytes)

1 Like

Replied to another comment:
Transistors are NPN driven from the arduino with 860 ohm resistors to the gates.
Not sure how to draw a schematic on a computer, so have this whiteboard drawing :stuck_out_tongue:
D8,9 and 10 are digital pins and A1 and A0 are analog pins to the arduino.

Here's the code, all the LCD isn't connected atm
sketch_may04b.ino (1018 Bytes)

1 Like

Thanks for the nice schematic. Please post your sketch in line, using code tags.

The sketch you attached does not use the sensor data. What makes you think "noise" is an issue?

+1 on the nice schematic. Exemplary.

Now you might post the code here, use the Autoformat tool in the IDE if you need to, then use the Copy for Forum tool in the IDE, then paste here in a new posting.

a7

Whoops, uploaded the wrong code.

/*
  TEMPERATURE SENSITIVE PC CASE

  The aim of this project is to make
  a PC case with RGB LEDs that change
  colour based on the temperature of
  the case. This code was designed on
  an arduino UNO/atmega328p using a
  TMP36 as the temperature sensor, a
  16x2 LCD and NPN transistors to use
  for PWM to control the LEDs.

  The circuit is designed for 5v.
*/

//import Liquid Crystal library
//this supplies the arduino with the code needed to run the LCD display2
#include <LiquidCrystal.h>

//initialise the LCD
//this tells the arduino which pins to use for sending data to the display
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//define the sensor pins
//this tells the arduino which pins the inputs are tied to
//sensorPin leads to the TMP36
const int sensorPin = 0;
//potPin leads to the 250k pot
const int potPin = 1;

//define the variables
//this will tell the arduino where to save the sensor data
byte rValue, gValue, bValue;
int switchState, tempReading, potDisplay;
float tempC, Voltage, Kelvin, Celsius, potReading;


//allocate the LED transistors to pins
//these pins must be able to do PWM
const int rPin = 10;
const int bPin = 6;
const int gPin = 9;

void setup()
{
  //start the serial monitor
  //this allows us to print and read data for debugging
  Serial.begin(9600);

  //turn on the LCD
  //this tells the arduino where to supply power
  lcd.begin(16, 2);
  // print these words to the LCD to ensure it boots properly:
  lcd.print("HELP IM AN LCD!");
  lcd.clear();

  //define inputs/outputs
  //this tells the arduino whether to send or recieve data/power
  pinMode (rPin, OUTPUT);
  pinMode (bPin, OUTPUT);
  pinMode (gPin, OUTPUT);
  pinMode (sensorPin, INPUT);
  pinMode (potPin, INPUT);
}

void loop()
{
  //read the potentiometer to determine the brightness of the LEDs
  potReading = analogRead(potPin);
  //divide by 1024 to allow for easy maths later on
  //potReading variable must be a float to allow for decimals
  potReading /= 1024;

  Voltage = analogRead(sensorPin);
  Kelvin = analogRead(sensorPin) * (0.489);      // Read analog voltage and convert it to Kelvin (0.489 = 500/1023)
  tempC = Kelvin - 273;

  //print the temp to the LCD
  lcd.setCursor(0, 0);
  lcd.print(tempC);
  lcd.print(" degrees");

  //print to serial for debugging
  Serial.print(tempC); Serial.println(" degrees C");
  debug();
  //then constrain the temp to be within 0-90 to easily split the gradient
  tempC = constrain(tempC, 0, 90);
  //map the values to bytes usable for PWM and asign colours
  //PWM does not allow for numbers outside of 0-255
  if (tempC < 60) {
    if (tempC < 30) {
      //fade between blue and green
      blueGreen();
    }
    else {
      //fade between green and yellow
      greenYellow();
    }
  }
  else {
    //fade between yellow and red
    yellowRed();
  }
  //write these values as PWM to the transistors
  ledWrite();
}
//GRADIENT FUNCTIONS
void blueGreen() {
  rValue = 0;
  gValue = 255;
  bValue = map (tempC, 0, 30, 255, 0);
}

void greenYellow() {
  rValue = map(tempC, 30, 60, 0, 255);
  gValue = 255;
  bValue = 0;
}

void yellowRed() {
  rValue = 255;
  gValue = map(tempC, 30, 60, 255, 0);
  bValue = 0;
}

void ledWrite() {
  analogWrite (rPin, rValue * potReading);
  analogWrite (gPin, gValue * potReading);
  analogWrite (bPin, bValue * potReading);
}

void debug() {
  if (tempC > 100) {
    lcd.clear();
    lcd.print("SENSOR ERROR");
  }
}

You're right, I uploaded the wrong code.
This is the correct sketch.

/*
  TEMPERATURE SENSITIVE PC CASE

  The aim of this project is to make
  a PC case with RGB LEDs that change
  colour based on the temperature of
  the case. This code was designed on
  an arduino UNO/atmega328p using a
  TMP36 as the temperature sensor, a
  16x2 LCD and NPN transistors to use
  for PWM to control the LEDs.

  The circuit is designed for 5v.
*/

//import Liquid Crystal library
//this supplies the arduino with the code needed to run the LCD display2
#include <LiquidCrystal.h>

//initialise the LCD
//this tells the arduino which pins to use for sending data to the display
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//define the sensor pins
//this tells the arduino which pins the inputs are tied to
//sensorPin leads to the TMP36
const int sensorPin = 0;
//potPin leads to the 250k pot
const int potPin = 1;

//define the variables
//this will tell the arduino where to save the sensor data
byte rValue, gValue, bValue;
int switchState, tempReading, potDisplay;
float tempC, Voltage, Kelvin, Celsius, potReading;


//allocate the LED transistors to pins
//these pins must be able to do PWM
const int rPin = 10;
const int bPin = 6;
const int gPin = 9;

void setup()
{
  //start the serial monitor
  //this allows us to print and read data for debugging
  Serial.begin(9600);

  //turn on the LCD
  //this tells the arduino where to supply power
  lcd.begin(16, 2);
  // print these words to the LCD to ensure it boots properly:
  lcd.print("HELP IM AN LCD!");
  lcd.clear();

  //define inputs/outputs
  //this tells the arduino whether to send or recieve data/power
  pinMode (rPin, OUTPUT);
  pinMode (bPin, OUTPUT);
  pinMode (gPin, OUTPUT);
  pinMode (sensorPin, INPUT);
  pinMode (potPin, INPUT);
}

void loop()
{
  //read the potentiometer to determine the brightness of the LEDs
  potReading = analogRead(potPin);
  //divide by 1024 to allow for easy maths later on
  //potReading variable must be a float to allow for decimals
  potReading /= 1024;

  Voltage = analogRead(sensorPin);
  Kelvin = analogRead(sensorPin) * (0.489);      // Read analog voltage and convert it to Kelvin (0.489 = 500/1023)
  tempC = Kelvin - 273;

  //print the temp to the LCD
  lcd.setCursor(0, 0);
  lcd.print(tempC);
  lcd.print(" degrees");

  //print to serial for debugging
  Serial.print(tempC); Serial.println(" degrees C");
  debug();
  //then constrain the temp to be within 0-90 to easily split the gradient
  tempC = constrain(tempC, 0, 90);
  //map the values to bytes usable for PWM and asign colours
  //PWM does not allow for numbers outside of 0-255
  if (tempC < 60) {
    if (tempC < 30) {
      //fade between blue and green
      blueGreen();
    }
    else {
      //fade between green and yellow
      greenYellow();
    }
  }
  else {
    //fade between yellow and red
    yellowRed();
  }
  //write these values as PWM to the transistors
  ledWrite();
}
//GRADIENT FUNCTIONS
void blueGreen() {
  rValue = 0;
  gValue = 255;
  bValue = map (tempC, 0, 30, 255, 0);
}

void greenYellow() {
  rValue = map(tempC, 30, 60, 0, 255);
  gValue = 255;
  bValue = 0;
}

void yellowRed() {
  rValue = 255;
  gValue = map(tempC, 30, 60, 255, 0);
  bValue = 0;
}

void ledWrite() {
  analogWrite (rPin, rValue * potReading);
  analogWrite (gPin, gValue * potReading);
  analogWrite (bPin, bValue * potReading);
}

void debug() {
  if (tempC > 100) {
    lcd.clear();
    lcd.print("SENSOR ERROR");
  }
}
1 Like

This is an integer calculation, which amplifies small differences in temperature into large differences in intensity. You specify that a 30 degree range in temperature is mapped into 255 levels of intensity.

Thus, a one degree change in temperature results in a change of 8 to 9 in LED intensity.

Furthermore, since human vision responds nonlinearly to intensity, the effect is further amplified for low levels of illumination.

I suggest to rethink how the temperature is mapped to colors and intensity. It is far more difficult that most people realize to find an effective mapping. Search for "heat map table".

I just noticed the NPN transistors are wired in an emitter follower configuration.

Someone not me should say that is fine… typically NPN transistors woukd switch from the low side.

a7

It is probably OK, but not "fine", especially if output pin voltage or Vcc is (say) 3.3V. Low side switch is preferred.

seems pretty simple to swap so i'll fix that up!

Hmm... so should the intensity be amplified the closer it is to the 'centre' of the gradient? Not sure how I could do that.

Randomly chosen example taken from many possible places to start your research:

Here is another: Code to convert temperature from Arduino's temperature sensor into heatmap RGB · GitHub

Do you mean the LM335Z, and why that sensor.
It's from the analogue times (50+ years ago), and a poor match for 5volt processors.
The LM35 or TMP36 would have been much better, because you could have used the more stable internal reference from the Uno. Best solution would be a digital DS18B20.
Leo..

Alas, the LM335z is the only one sold at jaycar and shipping from china is very inconvenient.

thank you!

The do have the DS18B20...

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.