Tuesday, July 15, 2025

Building A Color Thermometer



This month I wanted to get back onto more "hands on" stuff that was more based in the real world than the virtual one. When looking around for ideas, I found a small stash of Arduino Uno's that I got from my Creation Crate subscription a while back (by the way - I highly recommend them - the neat little projects I got each month were a lot of fun to put together - and I learn quite a lot on what the Arduino is capable of) so I wanted to find a unique project that I could make with and Arduino and whatever components I could find lurking around the workbench.

Rooting around, I came across a roll of NeoPixel programable color LEDs. These are pretty neat since you can do a lot of different light effects and you could program it so that individual LED's on the strip to light up. The original reason I had that roll was for a clock project that didn't quite pan out the way I wanted it to go. 

I also came across a DHT11 module, which is a small temperature/humidity sensor that feeds its data through a single wire data feed. 

So, with those 3 items, the obvious solution is to put together a thermometer that displays the temperature and humidity in the room as a color display. 

Since the LED's and the sensor are digitally controlled, it really makes for a simple circuit to put together - basically I just need to plug the components directly to the Arduino's power outputs and digital inputs and some fairly straight forward Arduino code should handle the rest. 

The basic premise of the project is to be a smart weather display that automatically changes light patterns based on the temperature and humidity in the room. The temperature sensor continuously monitors the air conditions and then creates different colorful lighting effects on the LED strip to show what the weather felt like.



Showing The Room Conditions

To properly visualize the room conditions I really needed to come up with an appropriate color effect that reflected how it felt in the room. 

After some playing around with the NeoPixel, I came up with the following patterns: 

  • Cold and Damp (Under 15°C with high humidity over 40%)
    • Effect: Cool Blue Pulse
      • The lights glow in cool blue tones that slowly pulse brighter and dimmer
      • Represents the feeling of being underwater or in a cold, misty environment
      • Creates a calming, cool atmosphere

  • Hot and Dry (Over 25°C with humidity under 70%)
    • Effect: Fire Flicker
      • The lights flicker in red, orange, and yellow colors like real flames
      • Each light changes randomly to create a realistic fire effect
      • Represents the dry heat of a desert or fireplace

  • Comfortable Conditions (15-25°C with moderate humidity 40-70%)
    • Effect: Calm Green Breathing
      • Soft green lights that slowly fade in and out like gentle breathing
      • Creates a peaceful, natural feeling
      • Indicates ideal living conditions

  • Hot and Humid (Over 30°C with high humidity over 70%)
    • Effect: Storm Swirl
      • Purple and magenta colors that swirl and move along the strip
      • Creates a chaotic, energetic pattern
      • Represents the unsettled feeling of hot, sticky weather

  • All Other Conditions
    • Effect: Rainbow Cycle
      • A smooth rainbow pattern that continuously moves along the strip
      • Shows all colors in a pleasing sequence
      • Acts as the default display when conditions don't match the other categories

The lighting effects are intended to be intuitive - cooler colors for cooler conditions, warmer colors for hotter conditions, and special effects for extreme or unusual combinations of temperature and humidity.


Now that I have the effects that I wanted to have to represent the conditions in the room, that next step is to start putting things together



Components

To start the project, I collected the following times




Temperature and Humidity Sensor (DHT11)
  • A small electronic sensor that measures how hot or cold it is and how much moisture is in the air
  • Takes readings every few seconds automatically
  • Connected to your Arduino microcontroller

LED Strip (NeoPixels)
  • A strip of  colorful lights that can display any color
  • For this project I'll use a string of 7 LED's
  • Each light can be controlled individually
  • Can create smooth animations and effects

Arduino Uno Microcontroller
  • The "brain" that reads the sensor data and controls the lights



Technical Details

  • Temperature Range: Celsius measurements are to be used
  • Humidity Range: Measured as relative humidity percentage (0-100%)
  • Update Speed: The lights on the NeoPixel update every 20-80 milliseconds depending on the effect
  • Power: The thermometer will runs on standard Arduino power (5V). In particular I plan on running the Arduino off the USB connector, which will allow me to apply future software updates. 
  • Installation: I am planning on enclosing the thermometer in some sort of case, but it will need to be able to have access to power and good air circulation for accurate readings.



Wiring It Up

With the components all collected, I looked at how to connect everything up.  

In reality, connecting all the components together are pretty straightforward. 

Connections to the Arduino are:
  • The positive connection from the LED was connected to the +5 port
  • Data line from the LED was inserted to the D6 socket
  • Ground on the LED was inserted into one of the Ground sockets
  • Positive connection from the DHT11 was put into the  Vcc socket
If you're more picture oriented, I've also included a handy schematic diagram below



Writing The Code 

With everything all connected, the next step is to tell the Arduino to start monitoring the output of the DHT11, check the readings it got against the display rules that I defined earlier and tell the NeoPixel LEDs to display the appropriate color display. 

The Arduino checks the temperature and humidity continuously and updates the light display in real-time. The effects needed to be smooth and change gradually as the environmental conditions changed.

To get everything to work, I put together the following program and uploaded it up to the Arduino:


#include <Adafruit_NeoPixel.h>
#include <DHT.h>

#define DHTPIN 6
#define DHTTYPE DHT11
#define LED_PIN 2
#define NUM_LEDS 7

DHT dht(DHTPIN, DHTTYPE);
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  dht.begin();
  strip.begin();
  strip.show();
}

void loop() {
  float temp = dht.readTemperature();
  float hum = dht.readHumidity();
  Serial.begin(9600);

  if (temp < 15 && hum > 40) {
    coolBluePulse();
  } else if (temp > 25 && hum < 70) {
    fireFlicker();
  } else if (temp >= 15 && temp <= 25 && hum >= 40 && hum <= 70) {
    calmBreathGreen();
    } else if (temp > 30 && hum > 70) {
    stormSwirl();
  } else {
    rainbowCycle();
  }
}

void calmBreathGreen() {
  static float brightness = 0;
  static int fadeDirection = 1;
  static unsigned long lastUpdate = 0;

  const unsigned long interval = 100;    // Slower fade timing
  const float step = 0.8;                // Smaller step for smoothness

  if (millis() - lastUpdate >= interval) {
    lastUpdate = millis();

    brightness += fadeDirection * step;

    // Reverse direction at full brightness and full darkness
    if (brightness >= 150) {
      brightness = 150;
      fadeDirection = -1;
    } else if (brightness <= 0) {
      brightness = 0;
      fadeDirection = 1;
    }

    // Set all LEDs to green with current brightness
    for (int i = 0; i < NUM_LEDS; i++) {
      strip.setPixelColor(i, strip.Color(0, (int)brightness, 0));
    }
    strip.show();
  }
}

// Effect: underwater blue pulse
void coolBluePulse() {
  static uint8_t brightness = 0;
  static int fadeDirection = 1;

  for (int i = 0; i < NUM_LEDS; i++) {
    strip.setPixelColor(i, strip.Color(0, brightness, brightness + 40));
  }
  strip.show();

  brightness += fadeDirection * 3;
  if (brightness <= 10 || brightness >= 120) fadeDirection *= -1;

  delay(40);
}

// Effect: flickering fire
void fireFlicker() {
  for (int i = 0; i < NUM_LEDS; i++) {
    int r = random(180, 255);
    int g = random(50, 100);
    strip.setPixelColor(i, strip.Color(r, g, 0));
  }
  strip.show();
  delay(80);
}

// Effect: chaotic swirl (hot & humid)
void stormSwirl() {
  static int pos = 0;
  for (int i = 0; i < NUM_LEDS; i++) {
    int val = (i + pos) % 256;
    strip.setPixelColor(i, strip.Color(val, 0, 255 - val));
  }
  strip.show();
  pos++;
  delay(50);
}

// Backup effect
void rainbowCycle() {
  static uint16_t j = 0;
  for (int i = 0; i < NUM_LEDS; i++) {
    strip.setPixelColor(i, Wheel((i * 256 / NUM_LEDS + j) & 255));
  }
  strip.show();
  j++;
  delay(20);
}

uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if (WheelPos < 85)
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  if (WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}


Once the code was uploaded, the LED's started doing their thing. To get a sense of what the effects look like, I've attached a quick video that showed all the available light effects.




At this point I had a working prototype of a color thermometer and I really like the effects that are being produced. I did have to tweak the settings a little to remove some of the gaps in the temperature and humidity rules in order to cut down the cases where it defaulted to the rainbow effect. 

As of now, while the lights are pretty cool, it's basically just a lump of glowing wires, so to make it really practical I need to properly house it. 

Next - my thermometer gets a proper home. 

No comments:

Post a Comment