Remote Neopixel Temperature Gauge

Most of this was made possible by a few members of this fine community helping a complete noob out.

Now we got that out of the way, I had a problem, I needed to be able to monitor temperature remotely in various facilities, air, water, HVAC ventilation systems, etc. By remotely I mean I am on 6000 acres (yes its big), and I need to read sensors from one corner to another basically.

The accuracy of this is important, so I decided on the BME280 sensor from Bosch.

Here is the what the first prototype looked like all put together:

I wanted it to have multiple ways to view the data, so I decided on Blynk Dashboard and physical visualization.

I decided on Neopixels to physically visualize the values and this is what it looks like:

Here is how I did it.

First thing’s first, I built a little prototype that sits in an Altoids tin, it consists of:

Environmental Sensor Base Unit

  1. Particle Photon
  2. USB LiIon/LiPoly charger
  3. 3.7v 2000 mAh LiIon Battery
  4. BME280 I2C or SPI Temperature and Humidity Pressure Sensor
  5. Perma Proto Mint Tin Size
  6. Mint tin

And it looks like this all put together:

Neopixel Sensor Gauge

  1. Particle Photon
  2. Particle Neopixel Ring Kit - 24 Neopixels

Environmental Sensor Base Unit Code

// This #include statement was automatically added by the Particle IDE.
#include "CE_BME280.h"

// This #include statement was automatically added by the Particle IDE.
#include "blynk/blynk.h"

 * EnviroMon V1 connected to Blynk app
 * LDR for light level
 * BME280/BMP180 (temperature, humidity, pressure)
 * Blynk connections:
 * V11 = Light
 * V12 = Temperature
 * V13 = Humidity
 * V14 = Pressure
 * V15 = Dewpoint (calculated)
 * V20 = WiFi Signal Strength
 * V23 = Bridge.Connector ""
 * ********************************************************************************/


CE_BME280 bme; // I2C

// Bridge widget on virtual pin 1
WidgetBridge bridge1(V1);

// Home - ADU Test Blynk Local-Server Auth
char auth[] = "69696969696969696969696969";

IPAddress server_ip (192, 168, 0, 0);

//change double back to float if temp doesn't work and no particle publish event.
float bmeTemperature;
float bmePressure;
float bmeHumidity;
float Light;
float dewpoint;
int wifiStrength;
float startTime;
float currentTime;
float sensorValue;
float Temp;

void setup()
    //Blynk.begin(auth, server_ip, 8442); // Local Server Version
        String errorMessage;
        errorMessage = "Not found";
        Particle.publish("BME280 Error", errorMessage);

    startTime = millis();
void loop()
    currentTime = millis();
    if (currentTime > startTime + 2000){
        wifiStrength = WiFi.RSSI();
        Blynk.virtualWrite(V20, wifiStrength);        
        startTime = millis();

void getLight(){
    sensorValue = analogRead(A0);
    sensorValue = 0;
    for(int x = 0; x <= 2; x++){
        sensorValue = sensorValue + analogRead(A0);
    sensorValue = sensorValue / 3;
    Light = float(sensorValue) * 100 / 4095;
    Blynk.virtualWrite(V11, Light);
void getBME280Data(){
    bmeTemperature = bme.readTemperature() - 4;
    Blynk.virtualWrite(V12, bmeTemperature);
    bmeHumidity = bme.readHumidity();
    if (bmeHumidity > 1){
        Blynk.virtualWrite(V13, bmeHumidity);
    bmePressure = (bme.readPressure()/100) - 3;
    Blynk.virtualWrite(V14, bmePressure);
    dewpoint = bmeTemperature - ((100 - bmeHumidity)/5);
    Blynk.virtualWrite(V15, dewpoint);

void ppub(){
  Particle.publish("Pressure : ", String (bmePressure), 60, PRIVATE);
  Particle.publish("TempCpub : ", String (bmeTemperature), 60, PRIVATE);
  Particle.publish("Relative Humidity: ", String (bmeHumidity), 60, PRIVATE);

Remote Neopixel Ring Code

// This #include statement was automatically added by the Particle IDE.
#include "Adafruit_BME280/Adafruit_BME280.h"

// This #include statement was automatically added by the Particle IDE.
#include "neopixel/neopixel.h"

#include "application.h"


#define PIXEL_PIN D6
#define PIXEL_COUNT 24
#define PIXEL_TYPE WS2812B

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

double tmp;

void myHandler(const char *event, const char *data)
  tmp = atof(data);  // convert the incoming string literal to float and put the value in the global variable

void setup() {
    Particle.variable("TempCpub", &tmp, DOUBLE); 
    Particle.subscribe("TempCpub", myHandler, MY_DEVICES);
    while(!Serial.available() && millis() < 60000) Particle.process();    // wait for serial terminal or 60sec timeout
    strip.begin(); // Initialize the strip; // Initialize all pixels to 'off'
    strip.setBrightness(25); // Set brightness limit (value between 0-255)


void loop() {
    static uint32_t ms;
    if(millis() - ms < 5000) return; // delay while keeping cloud responsive
    ms = millis();


void temp_strip(){
    int low=10;
    int high=35;

     for(int i=0; i<strip.numPixels(); i++) {
        if(((int)tmp)>=(low+i)) strip.setPixelColor(i, strip.Color(map(i,0,strip.numPixels(),0,255),0,map(i,0,strip.numPixels(),255,0)));
        else strip.setPixelColor(i,strip.Color(0,0,0));


Up next is to build a box for Neopixel strips to add multiple sensors, I haven’t quite decided how big the final wall mount box is going to be yet. Gotta make room for Power Supply for the strips etc.


Great job!

I always loved how they made this thermostat. Never did figure out how to find something similar to the neon bar graph they used in these though.

1 Like

That Nixie tube is pure sexy!

That neon Bar graph looks like just a custom laser cut piece of acrylic and they have RGB underneath.

I’m pretty sure it’s a nixie tube of some kind, but I see what you’re saying, you could make a custom PCB and place small SMD LED lights close in a row, but you would need a chip to drive all those LED’s individually.

Ya I found the Nixie tube for sale actually, Ebay Link

Yes they are Nixi IN-13 tubes and can be bought for $5 here: But you need a 150v DC power converter to run them.