Colour Temp Display

The Colour Temperature Display shows the temperature by mapping it temperature to position on a colour wheel. Multiple discrete red, green and blue LEDs combine to create a vivid colour display over the temperature range of 15°C  (blue) to 25°C (red).

ColourTemp-p1The Colour Temperature Display displaying its colour for 20° C

Temperature is read from an internal sensor and its 15- 25°C temperature range is converted to a corresponding hue (using HSI colour model) that spans from 0° (red) to 240° (blue) of the colour wheel. The unit is housed in a custom enclosure made from copper-clad fibre board and translucent plexiglass.

ColourTemp-p2The underside of the Colour Temperature Display showing colour for 20° C

The electronics consist of an Arduino Nano on a circuit board with discrete transisitor drivers controlling three sets of three red, green and blue LEDs. A DS18B20 one-wire temperature sensor provides accurate temperature readings that are converted into RGB intensities, using an HSI algorithm (see below).

Circuit schematic

Circuit schematic

Temperature values are mapped to hue such that at 15°C, the corresponding hue is at 0 (red, 0°) and at 25°C hue is at 4 (blue, 240°). The RGB intensities use PWM outputs to drive the sets of LEDs. The units is powered by a 9V DC power supply.

hsi-color-modelHSI Colour Wheel

A note about HSI, HSV algorithms:

While I tried various algorithms for converting hue values to RGB intensities, compared to the HSV model, I found the HSI model provided ‘truer’ colour conversions when varying overall light intensity. Although this project does not involve adjusting the overall light intensity, I have used this model in other projects, including my Wall Clock. In this project, the intensity of light for each of the hours, minutes and seconds indicators can be adjusted by the user. The HSI algorithm proved to be most effective in maintaining hue, especially at low light levels.

 

8 thoughts on “Colour Temp Display

        1. Adrian Post author

          Yes, although you will have to drive each RGB LED separately and it will be very wasteful in power if you drive the RGB LEDs from 9v….

          Reply
    1. Adrian Post author

      Just copy this into your Arduino IDE…

      //*****************************************************************************************//
      // Temperature to Colour
      // Adrian Jones
      // May 2014
      //*****************************************************************************************//

      #include // temperature sensors use OneWire interface
      #define ONE_WIRE_BUS 8 // DS18B20 probe: Red – Vcc, Black – GND, White – D8 w/ 4.7k pullup to Vcc.
      OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices

      #include
      DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
      DeviceAddress tempSensor = { 0x28, 0x58, 0xC7, 0xE6, 0x03, 0x00, 0x00, 0x46 }; // address of DS18B20 temperature sensor
      float tempC; // measured temperature

      // LEDs
      const int rled = 10; // red LED
      const int gled = 11; // green LED
      const int bled = 9; // blue LED

      // variables
      float hue=0.0, saturation=1.0, value=1.0;
      long red,blue,green,rgbval;

      #define tempMin 15 // hue = 0 deg. (h=0) at cold temp limit
      #define hueMin 0
      #define tempMax 25 // hue = 240 deg. (h=4) at hot temp limit
      #define hueMax 4

      //*****************************************************************************************//
      // Initial Setup
      //*****************************************************************************************//
      void setup() {
      Serial.begin(57600);

      // LEDS
      pinMode(rled, OUTPUT); analogWrite(rled, 0);
      pinMode(gled, OUTPUT); analogWrite(gled, 0);
      pinMode(bled, OUTPUT); analogWrite(bled, 0);

      // temp Sensor
      sensors.begin(); // Start sensor library
      sensors.setResolution(tempSensor, 12); // set the resolution to 12 bits
      }

      //*****************************************************************************************//
      // MAIN LOOP
      //*****************************************************************************************//
      void loop() {
      sensors.requestTemperatures(); // get temperature
      tempC = constrain(sensors.getTempC(tempSensor), tempMin, tempMax); // constrain between temperature limits
      hue = map((tempC – tempMin)*1000, 0, (tempMax-tempMin)*1000, (hueMax-hueMin)*1000, 0) / 1000.0; // map to hue

      rgbval = HSV_to_RGB(hue, saturation, value);

      red = (rgbval & 0x00FF0000) >> 16;
      green = (rgbval & 0x0000FF00) >> 8;
      blue = (rgbval & 0x000000FF);

      Serial.print(“T “); Serial.print(tempC); Serial.print(“C\t”);
      Serial.print(“H “); Serial.print(hue); Serial.print(“\t”);
      Serial.print(“R “); Serial.print(red); Serial.print(“\t”);
      Serial.print(“G “); Serial.print(green); Serial.print(“\t”);
      Serial.print(“B “); Serial.print(blue); Serial.println(” “);

      analogWrite(rled, red);
      analogWrite(gled, green);
      analogWrite(bled, blue);
      delay(100);
      }

      //*****************************************************************************************//
      // SUBROUTINES
      //*****************************************************************************************//

      /* modified from Alvy Ray Smith’s site: http://www.alvyray.com/Papers/hsv2rgb.htm */
      long HSV_to_RGB( float h, float s, float v ) { // H is given on [0, 6]. S and V are given on [0, 1], RGB is returned as a 24-bit long #rrggbb
      int i;
      float m, n, f;

      if ((s<0.0) || (s>1.0) || (v<1.0) || (v>1.0)) { return 0L; } // not very elegant way of dealing with out of range: return black
      if ((h < 0.0) || (h > 6.0)) { return long( v * 255 ) + long( v * 255 ) * 256 + long( v * 255 ) * 65536; }

      i = floor(h);
      f = h – i;
      if ( !(i&1) ) { f = 1 – f; } // if i is even
      m = v * (1 – s);
      n = v * (1 – s * f);
      switch (i) {
      case 6:
      case 0: return long(v * 255 ) * 65536 + long( n * 255 ) * 256 + long( m * 255);
      case 1: return long(n * 255 ) * 65536 + long( v * 255 ) * 256 + long( m * 255);
      case 2: return long(m * 255 ) * 65536 + long( v * 255 ) * 256 + long( n * 255);
      case 3: return long(m * 255 ) * 65536 + long( n * 255 ) * 256 + long( v * 255);
      case 4: return long(n * 255 ) * 65536 + long( m * 255 ) * 256 + long( v * 255);
      case 5: return long(v * 255 ) * 65536 + long( m * 255 ) * 256 + long( n * 255);
      }
      }

      Reply

Come on... leave a comment...