Move lighting logic in to its own class. Add definition guards around classes.
This commit is contained in:
parent
0052ac0169
commit
a3068a2d15
6 changed files with 111 additions and 64 deletions
55
Lighting.cpp
Normal file
55
Lighting.cpp
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#include "Lighting.h"
|
||||||
|
#include <FastLED.h>
|
||||||
|
|
||||||
|
#define MAX_HEAT_INDEX 240.0
|
||||||
|
|
||||||
|
Lighting::Lighting(int ledCount, NaturalLight* naturalLight, Weather* weather, float cloudCoverLimit) {
|
||||||
|
_ledCount = ledCount;
|
||||||
|
_naturalLight = naturalLight;
|
||||||
|
_weather = weather;
|
||||||
|
_cloudCoverLimit = cloudCoverLimit;
|
||||||
|
|
||||||
|
_leds = CRGB(_ledCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Lighting::getIndexMultiplier(int now, int startTime, int endTime, bool swap) {
|
||||||
|
float a = swap ? endTime - now : now - startTime;
|
||||||
|
float b = endTime - startTime;
|
||||||
|
return constrain(a / b, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Lighting::getHeatIndex(int now) {
|
||||||
|
float indexMultiplier = now >= _naturalLight->getSunset()
|
||||||
|
? getIndexMultiplier(now, _naturalLight->getSunset(), _naturalLight->getAstronomicalTwilightEnd(), true)
|
||||||
|
: getIndexMultiplier(now, _naturalLight->getAstronomicalTwilightBegin(), _naturalLight->getSunrise(), false);
|
||||||
|
return MAX_HEAT_INDEX * indexMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Lighting::getBrightness() {
|
||||||
|
float cloudCover = (float)_weather->getCloudCover() / 100.0;
|
||||||
|
float multiplier = cloudCover * (_cloudCoverLimit / 100.0);
|
||||||
|
if (_weather->getCondition() == WeatherCondition::Other)
|
||||||
|
multiplier *= 2.0;
|
||||||
|
return 255.0 - (multiplier * 255.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lighting::update(int now) {
|
||||||
|
_heatIndex = getHeatIndex(now);
|
||||||
|
_brightness = getBrightness();
|
||||||
|
|
||||||
|
CRGB colour = ColorFromPalette(_sunrise, _heatIndex, _brightness, LINEARBLEND);
|
||||||
|
|
||||||
|
if (_weather->getCondition() == WeatherCondition::Thunder && millis() >= _nextLightningFlash) {
|
||||||
|
int flashes = random8(2, 8);
|
||||||
|
for (int i = 0; i < flashes; i++) {
|
||||||
|
FastLED.showColor(CRGB::White);
|
||||||
|
delay(random8(10, 20));
|
||||||
|
FastLED.showColor(colour);
|
||||||
|
delay(random8(40, 80));
|
||||||
|
}
|
||||||
|
_nextLightningFlash = millis() + (random8(1, 60) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
fill_solid(&_leds, _ledCount, colour);
|
||||||
|
FastLED.show();
|
||||||
|
}
|
38
Lighting.h
Normal file
38
Lighting.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#include <FastLED.h>
|
||||||
|
#include "NaturalLight.h"
|
||||||
|
#include "Weather.h"
|
||||||
|
|
||||||
|
DEFINE_GRADIENT_PALETTE(_sunrise_p) {
|
||||||
|
0, 0, 0, 0,
|
||||||
|
128, 255, 128, 0,
|
||||||
|
224, 255, 255, 0,
|
||||||
|
240, 255, 255, 255, // Hack to get around LINEARBLEND problem (for now, hopefully)
|
||||||
|
255, 255, 255, 2552
|
||||||
|
};
|
||||||
|
|
||||||
|
class Lighting {
|
||||||
|
int _ledCount;
|
||||||
|
NaturalLight* _naturalLight;
|
||||||
|
Weather* _weather;
|
||||||
|
float _cloudCoverLimit;
|
||||||
|
CRGB _leds;
|
||||||
|
CRGBPalette16 _sunrise = _sunrise_p;
|
||||||
|
long _nextLightningFlash = 0;
|
||||||
|
float _heatIndex;
|
||||||
|
float _brightness;
|
||||||
|
|
||||||
|
float _currentHeatIndex();
|
||||||
|
float getIndexMultiplier(int now, int startTime, int endTime, bool swap);
|
||||||
|
float getHeatIndex(int time);
|
||||||
|
float getBrightness();
|
||||||
|
|
||||||
|
public:
|
||||||
|
Lighting(int ledCount, NaturalLight* _naturalLight, Weather* _weather, float cloudCoverLimit);
|
||||||
|
|
||||||
|
template<uint8_t DATA_PIN> void setup() {
|
||||||
|
FastLED.addLeds<WS2811, DATA_PIN, GRB>(&_leds, _ledCount).setCorrection(TypicalSMD5050).setTemperature(Tungsten40W);
|
||||||
|
}
|
||||||
|
void update(int time);
|
||||||
|
float getCurrentHeatIndex() { return _heatIndex; }
|
||||||
|
float getCurrentBrightness() { return _brightness; }
|
||||||
|
};
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef _DAYLIGHT_h
|
#ifndef NaturalLight_h
|
||||||
#define _DAYLIGHT_h
|
#define NaturalLight_h
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#define SOLAR_EVENT_URL "http://api.sunrise-sunset.org/json?lat=%s&lng=%s&formatted=0"
|
#define SOLAR_EVENT_URL "http://api.sunrise-sunset.org/json?lat=%s&lng=%s&formatted=0"
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#ifndef Weather_h
|
||||||
|
#define Weather_h
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#define WEATHER_URL "http://api.openweathermap.org/data/2.5/weather?lat=%s&lon=%s&appid=%s"
|
#define WEATHER_URL "http://api.openweathermap.org/data/2.5/weather?lat=%s&lon=%s&appid=%s"
|
||||||
|
@ -23,3 +25,4 @@ class Weather{
|
||||||
int getCloudCover() { return _cloudCover; }
|
int getCloudCover() { return _cloudCover; }
|
||||||
WeatherCondition getCondition() { return _condition; }
|
WeatherCondition getCondition() { return _condition; }
|
||||||
};
|
};
|
||||||
|
#endif
|
68
monitor.ino
68
monitor.ino
|
@ -11,21 +11,20 @@
|
||||||
#define MQTT_SERVER "192.168.1.3"
|
#define MQTT_SERVER "192.168.1.3"
|
||||||
#define SSID "GCHQ Surveillance Van"
|
#define SSID "GCHQ Surveillance Van"
|
||||||
#define PASSWORD "cocklol."
|
#define PASSWORD "cocklol."
|
||||||
#define LIGHT_PIN D2
|
|
||||||
#define LED_COUNT 36
|
|
||||||
#define PH_TOPIC "/home/sensors/fishtank/ph"
|
#define PH_TOPIC "/home/sensors/fishtank/ph"
|
||||||
#define TEMPERATURE_TOPIC "/home/sensors/fishtank/temperature"
|
#define TEMPERATURE_TOPIC "/home/sensors/fishtank/temperature"
|
||||||
#define TEMPERATURE_PIN D5
|
#define TEMPERATURE_PIN D5
|
||||||
|
|
||||||
|
#define LED_PIN D2
|
||||||
|
#define LED_COUNT 36
|
||||||
#define LATITUDE "20.548103"
|
#define LATITUDE "20.548103"
|
||||||
#define LONGITUDE "96.916835"
|
#define LONGITUDE "96.916835"
|
||||||
#define TIMEZONE_OFFSET 27000 // 7.5 hours in seconds
|
#define TIMEZONE_OFFSET 27000 // 7.5 hours in seconds
|
||||||
#define LIGHT_INDEX_TOPIC "/home/sensors/fishtank/lightindex"
|
#define LIGHT_INDEX_TOPIC "/home/sensors/fishtank/lightindex"
|
||||||
#define BRIGHTNESS_TOPIC "/home/sensors/fishtank/brightness"
|
#define BRIGHTNESS_TOPIC "/home/sensors/fishtank/brightness"
|
||||||
|
#define CLOUD_COVER_LIMIT 50.0 // percent;
|
||||||
|
|
||||||
#define NTP_POOL "uk.pool.ntp.org"
|
#define NTP_POOL "uk.pool.ntp.org"
|
||||||
#define MAX_HEAT_INDEX 240.0
|
|
||||||
#define CLOUD_COVER_LIMIT 50.0 // percent;
|
|
||||||
|
|
||||||
void mqttCallback(char *topic, byte *payload, unsigned int length);
|
void mqttCallback(char *topic, byte *payload, unsigned int length);
|
||||||
|
|
||||||
|
@ -35,17 +34,7 @@ PubSubClient _mqttClient = PubSubClient(MQTT_SERVER, 1883, mqttCallback, _wifiCl
|
||||||
Sensors _sensors = Sensors(TEMPERATURE_PIN, TEMPERATURE_TOPIC, PH_TOPIC, _mqttClient);
|
Sensors _sensors = Sensors(TEMPERATURE_PIN, TEMPERATURE_TOPIC, PH_TOPIC, _mqttClient);
|
||||||
NaturalLight _naturalLight = NaturalLight(LATITUDE, LONGITUDE, TIMEZONE_OFFSET);
|
NaturalLight _naturalLight = NaturalLight(LATITUDE, LONGITUDE, TIMEZONE_OFFSET);
|
||||||
Weather _weather = Weather(LATITUDE, LONGITUDE);
|
Weather _weather = Weather(LATITUDE, LONGITUDE);
|
||||||
|
Lighting _lighting = Lighting(LED_COUNT, &_naturalLight, &_weather, CLOUD_COVER_LIMIT);
|
||||||
CRGB _leds[LED_COUNT];
|
|
||||||
long _nextLightningFlash = 0;
|
|
||||||
DEFINE_GRADIENT_PALETTE(_sunrise_p){
|
|
||||||
0, 0, 0, 0,
|
|
||||||
128, 255, 128, 0,
|
|
||||||
224, 255, 255, 0,
|
|
||||||
240, 255, 255, 255, // Hack to get around LINEARBLEND problem (for now, hopefully)
|
|
||||||
255, 255, 255, 255
|
|
||||||
};
|
|
||||||
CRGBPalette16 _sunrise = _sunrise_p;
|
|
||||||
|
|
||||||
void waitForWiFi() {
|
void waitForWiFi() {
|
||||||
if (WiFi.status() == WL_CONNECTED)
|
if (WiFi.status() == WL_CONNECTED)
|
||||||
|
@ -90,30 +79,7 @@ void setup() {
|
||||||
|
|
||||||
_naturalLight.update();
|
_naturalLight.update();
|
||||||
_weather.update();
|
_weather.update();
|
||||||
|
_lighting.setup<LED_PIN>();
|
||||||
FastLED.addLeds<WS2811, LIGHT_PIN, GRB>(_leds, LED_COUNT).setCorrection(TypicalSMD5050).setTemperature(Tungsten40W);
|
|
||||||
}
|
|
||||||
|
|
||||||
float getIndexMultiplier(int now, int startTime, int endTime, bool swap){
|
|
||||||
float a = swap ? endTime - now : now - startTime;
|
|
||||||
float b = endTime - startTime;
|
|
||||||
return constrain(a / b, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
float getHeatIndex() {
|
|
||||||
time_t now = time(nullptr);
|
|
||||||
float indexMultiplier = now >= _naturalLight.getSunset() ?
|
|
||||||
getIndexMultiplier(now, _naturalLight.getSunset(), _naturalLight.getAstronomicalTwilightEnd(), true) :
|
|
||||||
getIndexMultiplier(now, _naturalLight.getAstronomicalTwilightBegin(), _naturalLight.getSunrise(), false);
|
|
||||||
return MAX_HEAT_INDEX * indexMultiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
float getBrightness(){
|
|
||||||
float cloudCover = (float)_weather.getCloudCover() / 100.0;
|
|
||||||
float multiplier = cloudCover * (CLOUD_COVER_LIMIT / 100.0);
|
|
||||||
if (_weather.getCondition() == WeatherCondition::Other)
|
|
||||||
multiplier *= 2.0;
|
|
||||||
return 255.0 - (multiplier * 255.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void publishFloat(char* topic, float value){
|
void publishFloat(char* topic, float value){
|
||||||
|
@ -132,27 +98,9 @@ void doLighting() {
|
||||||
}
|
}
|
||||||
|
|
||||||
EVERY_N_SECONDS(1) {
|
EVERY_N_SECONDS(1) {
|
||||||
float index = getHeatIndex();
|
_lighting.update(time(nullptr));
|
||||||
float brightness = getBrightness();
|
publishFloat(LIGHT_INDEX_TOPIC, _lighting.getCurrentHeatIndex());
|
||||||
|
publishFloat(BRIGHTNESS_TOPIC, _lighting.getCurrentBrightness());
|
||||||
publishFloat(LIGHT_INDEX_TOPIC, index);
|
|
||||||
publishFloat(BRIGHTNESS_TOPIC, brightness);
|
|
||||||
|
|
||||||
CRGB colour = ColorFromPalette(_sunrise, index, brightness, LINEARBLEND);
|
|
||||||
|
|
||||||
if (_weather.getCondition() == WeatherCondition::Thunder && millis() >= _nextLightningFlash) {
|
|
||||||
int flashes = random8(2, 8);
|
|
||||||
for (int i = 0; i < flashes; i++) {
|
|
||||||
FastLED.showColor(CRGB::White);
|
|
||||||
delay(random8(10, 20));
|
|
||||||
FastLED.showColor(colour);
|
|
||||||
delay(random8(40, 80));
|
|
||||||
}
|
|
||||||
_nextLightningFlash = millis() + (random8(1, 60) * 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
fill_solid(_leds, LED_COUNT, colour);
|
|
||||||
FastLED.show();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#ifndef Sensors_h
|
||||||
|
#define Sensors_h
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <Adafruit_ADS1015.h>
|
#include <Adafruit_ADS1015.h>
|
||||||
#include <OneWire.h>
|
#include <OneWire.h>
|
||||||
|
@ -24,3 +26,4 @@ class Sensors {
|
||||||
void publishpH();
|
void publishpH();
|
||||||
void publishTemperature();
|
void publishTemperature();
|
||||||
};
|
};
|
||||||
|
#endif
|
Loading…
Add table
Add a link
Reference in a new issue