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
- Particle Photon
- USB LiIon/LiPoly charger
- 3.7v 2000 mAh LiIon Battery
- BME280 I2C or SPI Temperature and Humidity Pressure Sensor
- Perma Proto Mint Tin Size
- Mint tin
And it looks like this all put together:
Neopixel Sensor Gauge
- Particle Photon
- 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 "https://github.com/blynkkk/blynk-library/blob/master/examples/Widgets/Bridge/Bridge.ino"
*
* ********************************************************************************/
SYSTEM_MODE(AUTOMATIC);
#define SEALEVELPRESSURE_HPA (1017.2)
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
Blynk.begin(auth);
delay(2000);
ppub();
delay(2000);
if(!bme.begin()){
String errorMessage;
errorMessage = "Not found";
Particle.publish("BME280 Error", errorMessage);
}
startTime = millis();
}
void loop()
{
Blynk.run();
delay(200);
currentTime = millis();
if (currentTime > startTime + 2000){
wifiStrength = WiFi.RSSI();
Blynk.virtualWrite(V20, wifiStrength);
//getLight();
getBME280Data();
startTime = millis();
ppub();
}
}
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);
delay(5000);
}
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"
SYSTEM_MODE(AUTOMATIC);
SYSTEM_THREAD(ENABLED);
#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() {
Serial.begin(9600);
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
strip.show(); // 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();
temp_strip();
}
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));
}
strip.show();
}
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.