#include <Adafruit_NeoPixel.h>
#include <DHT.h>
#include <Servo.h>
Servo servo;
#define servoPin 11
int angle = 0;
int test_angle = 0;
int error_angle = 0;
unsigned long lastTimeAngle;
unsigned long lastTimeAngle2;
DHT dht(4, DHT22);
#define PIN 3
int NUMPIXELS = 16;
int predNUM = 0;
bool one = true;
int state_temp = 0;
int last_state_temp = 0;
#define CLKpin 7
#define DTpin 6
#define SWpin 5
float h, t, pred_t;
int speed = 50;
int rgb = 0;
int a = 255;
bool hum = false;
int stateCLK = 0;
int lastStateCLK;
unsigned long lastSWtime;
unsigned long lastSWtimeDolg;
unsigned long lastSWtimeDouble;
int s_double = 0;
int lastSWstate = 0;
bool vent = false;
bool dolg = false;
bool zamer = false;
bool error = false;
bool er = false;
bool erst = false;
bool test = false;
bool clear = false;
unsigned long lastTestTime;
unsigned long lastTestTime2;
Adafruit_NeoPixel pixels(16, PIN, NEO_GRB + NEO_KHZ800);
int RGB[3] = {0, 0, 0};
int nol[3] = {0, 0, 0};
bool green = false;
void setup() {
Serial.begin(9600);
pixels.begin();
dht.begin();
servo.attach(servoPin);
servo.write(0);
pinMode(CLKpin, INPUT);
pinMode(DTpin, INPUT);
pinMode(SWpin, INPUT_PULLUP);
}
void loop() {
if(!error) {
but_press();
if(!test) {
if (!vent) {
update_value();
}
if(!error) {
if(!vent) {
stateCLK = digitalRead(CLKpin);
int stateDT = digitalRead(DTpin);
if (stateCLK != lastStateCLK && stateCLK == 1){
if (stateDT != stateCLK) {
angle -= 5;
if(angle < 0) {
angle = 0;
}
}
else {
angle += 5;
if(angle > 180) {
angle = 180;
}
}
servo.write(angle);
}
lastStateCLK = stateCLK;
if(t < 18 && !hum) {
write_invert_krug();
}
else {
write_krug();
}
}
else {
ventState();
}
}
else {
return;
}
}
else {
testState();
}
}
else {
errorState();
}
}
void clearRGB() {
for(int i {0}; i < 3; i++) {
RGB[i] = 0;
}
}
void update_value() {
h = dht.readHumidity();
t = dht.readTemperature();
if(!hum) {
if(t > 18) {
state_temp = 2;
rgb = 0;
clearRGB();
NUMPIXELS = map(t, 18.1, 80, 1, 16);
}
else {
state_temp = 0;
rgb = 2;
clearRGB();
NUMPIXELS = map(t, -40, 18, 0, 15);
if(one) {
predNUM = 16;
one = false;
}
}
if(t >= 18 && t <= 25) {
state_temp = 1;
rgb = 1;
}
}
else {
angle = map(h, 0, 100, 0, 180);
servo.write(angle);
RGB[2] = a;
NUMPIXELS = map(h, 0.1, 100, 1, 16);
}
RGB[rgb] = a;
if (state_temp == 1 && last_state_temp != state_temp) {
last_state_temp = state_temp;
write_new_color(true);
}
if ((t == 0 && !hum) || (h == 0 && hum)) {
NUMPIXELS = 0;
}
if (isnan(h) || isnan(t)) {
errorState();
error = true;
return;
}
else {
if(error) {
pixels.clear();
pixels.show();
}
error = false;
}
}
void but_press() {
int butState = digitalRead(SWpin);
if(butState != lastSWstate) {
if(butState == LOW) {
if(millis() - lastSWtime > 50) {
if (s_double == 0) {
lastSWtimeDouble = millis();
}
s_double++;
test = false;
vent = false;
hum = !hum;
pixels.clear();
pixels.show();
if(hum) {
rgb = 1;
clearRGB();
predNUM = 0;
NUMPIXELS = map(h, 0.1, 100, 1, 16);
}
else {
if(t > 25) {
predNUM = 0;
}
else if(t >= 18 && t <= 25) {
predNUM = 0;
}
else {
predNUM = 15;
}
}
}
lastSWtime = millis();
}
}
lastSWstate = butState;
if(millis() - lastSWtimeDouble >= 500 && !vent) {
if (s_double != 0) {
Serial.println(s_double);
}
s_double = 0;
}
if (s_double == 2) {
vent = true;
s_double = 0;
servo.write(90);
}
if(butState == LOW) {
if(zamer) {
lastSWtimeDolg = millis();
zamer = false;
}
if(millis() - lastSWtimeDolg > 1000 && dolg) {
servo.write(180);
test = true;
dolg = false;
vent = false;
moment_write(a, a, a);
}
}
else {
zamer = true;
dolg = true;
}
}
void write_krug() {
int vrNUM = NUMPIXELS;
if(pred_t < 18 && !hum) {
write_plus(predNUM, 16, vrNUM, nol);
predNUM = 0;
}
if(predNUM > vrNUM) {
write_minus(predNUM - 1, vrNUM, vrNUM, nol);
predNUM = NUMPIXELS;
}
if(predNUM != vrNUM) {
write_plus(predNUM - 1, vrNUM, vrNUM, RGB);
predNUM = NUMPIXELS;
}
pred_t = t;
}
void write_invert_krug() {
int vrNUM = NUMPIXELS;
if(pred_t > 18) {
write_minus(predNUM - 1, 0, vrNUM, nol);
predNUM = 15;
}
if(predNUM < vrNUM) {
write_plus(predNUM, vrNUM, vrNUM, nol);
predNUM = NUMPIXELS;
}
if(predNUM != vrNUM) {
write_minus(predNUM, vrNUM, vrNUM, RGB);
predNUM = NUMPIXELS;
}
pred_t = t;
}
void write_minus(int nach, int kon, int vr_num, int massiv[3]) {
for(int i = nach; i >= kon; i--) {
update_value();
if(vr_num != NUMPIXELS) {
predNUM = vr_num;
pred_t = t;
write_krug();
return;
}
pixels.setPixelColor(i, massiv[0], massiv[1], massiv[2]);
pixels.show();
delay(speed);
}
}
void write_plus(int nach, int kon, int vr_num, int massiv[3]) {
for(int i = nach; i < kon; i++) {
update_value();
if(vr_num != NUMPIXELS) {
predNUM = vr_num;
pred_t = t;
write_krug();
return;
}
pixels.setPixelColor(i, massiv[0], massiv[1], massiv[2]);
pixels.show();
delay(speed);
}
}
void write_new_color(bool show) {
if(t <= 18) {
for(int i = 15; i >= NUMPIXELS; i--) {
pixels.setPixelColor(i, RGB[0], RGB[1], RGB[2]);
if(show) {
pixels.show();
}
}
}
else {
for(int i = 0; i < NUMPIXELS; i++) {
pixels.setPixelColor(i, RGB[0], RGB[1], RGB[2]);
if(show) {
pixels.show();
}
}
}
}
void moment_write(int r, int g, int b) {
for(int i = 0; i < 16; i++) {
pixels.setPixelColor(i, r, g, b);
pixels.show();
}
}
void miganie(int r, int g, int b) {
if(millis() - lastTestTime > 1000) {
lastTestTime = lastTestTime2 = millis();
moment_write(r, g, b);
clear = true;
}
if (millis() - lastTestTime2 > 300 && clear) {
clear = false;
pixels.clear();
pixels.show();
}
}
void testState() {
if (millis() - lastTimeAngle > 800) {
servo.write(test_angle);
if (test_angle == 0) {
test_angle = 180;
}
else if (test_angle == 180){
test_angle = 0;
}
lastTimeAngle = millis();
}
miganie(255, 255, 255);
}
void errorState() {
if (millis() - lastTimeAngle > 500 && !erst) {
erst = true;
lastTimeAngle = millis();
if (error_angle == 0) {
servo.write(0);
error_angle = 90;
}
else if (error_angle == 180) {
servo.write(180);
error_angle = 90;
}
}
pixels.clear();
pixels.show();
delay(166);
if (millis() - lastTimeAngle > 500 && erst) {
erst = false;
lastTimeAngle = millis();
if (error_angle == 90) {
servo.write(90);
if (er) {
error_angle = 180;
er = false;
}
else {
error_angle = 0;
er = true;
}
}
}
moment_write(255, 255, 0);
delay(167);
}
void ventState() {
miganie(255, 0, 255);
}