Arduino Polska Forum

Pełna wersja: Sterownik LED PWM do akwarium z pomiarem temperatur, wilgotności i ciśnienia
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2
Na początek dziękuję za pomoc koledze JasQ.
Bez jego pomocy i poświęconego czasu program by pewnie nie powstał.
Program ma za zadanie sterować oświetleniem LED dwóch kanałów za pomocą PWM symulując świt, dzień, zmierzch i noc. Do tego celu użyto pinów 9 i 10.
W linii 96 i 97 ustawiamy czas w sekundach licząc od północy włączenia trybów świtu i zmierzchu, w linii 102 ustawiamy czas w sekundach trwania świtu i zmierzchu. Za pomocą pinu 6 sterujemy przekaźnikiem który ma za zadanie podać napięcie na drivery LED. Przekaźnik jest wyłączony w trybie nocnym, drivery nie są pod napięciem.
Dodatkowo program wyświetla odczyty z czujników (temperatura otoczenia, ciśnienie atmosferyczne, wilgotność otoczenia oraz temperaturę wody w zbiorniku z sondy wodoodpornej pin 11). Wyświetlacz odtwarza dwa ekrany co 10s na jednym ekranie jest wyświetlany zegar, data, tryb świecenia i status przekaźnika, na drugim zegar, datę, odczyty z czujników.
Czas przełączania ekranów ustawiamy w linii 213, czas podajmy w ms.
Hardware:
Arduino UNO
Wyświetlacz LCD 4x20 znaków
Konwerter I2C dla wyświetlacza LCD HD44780
Zegar czasu rzeczywistego - moduł RTC DS1307 + bateria – MSX
Sonda wodoodporna z czujnikiem temperatury DS18B20
BME280 - czujnik wilgotności, temperatury oraz ciśnienia I2C/SPI - moduł Adafruit
Zasilacz impulsowy 12V / 2,1A - wtyk DC 5,5 / 2,5 mm
Moduł przekaźnika RM1 z izolacją optoelektroniczną 5V 
Drivery LED z możliwością sterowania przez PWM
Diody LED

Program:
Biblioteki i fragmenty kodu znalezione w sieci.
Kod:
#include <TimerOne.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <OneWire.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <LiquidCrystal_I2C.h>
#define BACKLIGHT_PIN 3
LiquidCrystal_I2C  lcd(0x27,2,1,0,4,5,6,7);
#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10

#define SEALEVELPRESSURE_HPA (1013.25)

OneWire  ds(11);  // on pin 11 (a 4.7K resistor is necessary)
Adafruit_BME280 bme; // I2C

const char *monthName[12] = {
"01", "02", "03", "04", "05", "06",
"07", "08", "09", "10", "11", "12"
};
byte temp[8] = //ikona temperatury
{
B00100,
B01010,
B01010,
B01110,
B01110,
B11111,
B11111,
B01110
};

byte wilg[8] = //ikona wilgotnosci
{
B00100,
B00100,
B01010,
B10001,
B10001,
B10001,
B01110,
};

byte stopnie[8] = //ikona stopni
{
   B01100,
   B10010,
   B10010,
   B01100,
   B00000,
   B00000,
   B00000,
   B00000
};

byte procent[8] = //ikona stopni
{
   B11001,
   B11001,
   B00010,
   B00100,
   B00100,
   B01000,
   B10011,
   B10011
};

byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;

unsigned long odczyt = 0;
unsigned long czas = 0;
unsigned long z = 0 ;
byte lcdx = 1;
byte strona = 1;

float temperatura ;
float wilgotnosc ;
float cisnienie ;


int ledEnable = 6; //Pin do sterowania przekaźnikiem do zasilania driverów

const int kChan0Pin = 9; // Pin PWM do sterowania LED
const int kChan1Pin = 10; // Pin PWM do sterowania LED

const long kTurnOn = 32400; // Start tu zaczyna się świt (9:00)
const long kTurnOff = 75600; // Tu ustawiamy początek zmierzchu (21:00)

const int kDayState[] = { 1023,1023 }; // daytime LED state
const int kNightState[] = { 0, 0 }; // nighttime LED state

const long kFadeDuration = 3600; // 60 minut czas świtu i zmierzchu

long ctr;

void fader(long start_time, const int start_state[], const int end_state[], int out[2]) {

float per_second_delta_0 = (float) (end_state[0]-start_state[0])/kFadeDuration;
float per_second_delta_1 = (float) (end_state[1]-start_state[1])/kFadeDuration;

long elapsed = ctr-start_time;

out[0] = start_state[0] + per_second_delta_0 * elapsed;
out[1] = start_state[1] + per_second_delta_1 * elapsed;
}

long seconds_since_midnight() {
//  setTime(21, 45, 00, 16, 2, 2015);
//set the system time to 21hrs 45min 00sec 16,Feb 2015...does not set RTC, will reset upon powerup

time_t t = now();
long hr = hour(t);
long min = minute(t);
long sec = second(t);
long total = hr * 3600 + min * 60 + sec;
return total;
}

void set_state(const int state[]) {
if (state[0] >= 0 && state[0] <= 1023) Timer1.setPwmDuty(kChan0Pin, state[0]);
if (state[1] >= 0 && state[1] <= 1023) Timer1.setPwmDuty(kChan1Pin, state[1]);
}


// status dzień/noc

String poradnia = "";
String ledonoff = "";

void determine_state() {
if ( ctr >= 0 && ctr < kTurnOn ) { // night
  set_state(kNightState);
 
  poradnia = "NIGHT/MODE ";        
  digitalWrite(ledEnable,LOW);
  ledonoff = "LED-OFF";
 
} else if ( ctr >= kTurnOn && ctr <= (kTurnOn+kFadeDuration) ) { // sunrise
int foo[2];
fader(kTurnOn, kNightState, kDayState, foo);
set_state(foo);

   poradnia = "SUNRISE/MODE";              
   digitalWrite(ledEnable, HIGH);
   ledonoff = "LED-ON ";

} else if ( ctr > (kTurnOn+kFadeDuration) && ctr < kTurnOff ) { // day
set_state(kDayState);
 
  poradnia = "DAY/MODE";              
  digitalWrite(ledEnable, HIGH);
  ledonoff = "LED-ON ";

} else if ( ctr >= kTurnOff && ctr <= (kTurnOff+kFadeDuration) ) { // sunset
int foo[2];
fader(kTurnOff, kDayState, kNightState, foo);
set_state(foo);

   poradnia = "SUNSET/MODE";              
   digitalWrite(ledEnable, HIGH);
   ledonoff = "LED-ON ";

} else if ( ctr > (kTurnOff+kFadeDuration) && ctr < 86400 ) { // night
set_state(kNightState);

   poradnia = "NIGHT/MODE";        
   digitalWrite(ledEnable,LOW);
   ledonoff = "LED-OFF";
  }
}



void setup(void) {

Serial.begin(115200);        
setSyncProvider(RTC.get);
setSyncInterval(120);
Wire.begin();
Timer1.initialize(6666);     // 150Hz PWM
pinMode(kChan0Pin, OUTPUT);    
Timer1.pwm(kChan0Pin, 0);
pinMode(kChan1Pin, OUTPUT);    
Timer1.pwm(kChan1Pin, 0);
pinMode(ledEnable,OUTPUT);   // Led control

lcd.begin(20, 4);
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
//lcd.setBacklightPin(3, HIGH);
lcd.createChar(0, temp);
lcd.createChar(1, wilg);
lcd.createChar(3, stopnie);
lcd.createChar(4, procent);

if (!bme.begin()) {while (1);}

}

void loop() {

unsigned long sek = millis()/1000 ;
if ( (millis()-czas) >= 5000 ){czas = millis(); //czas zmiany ekranów
if (strona == 2){strona = 1;}
else if(strona == 1){strona = 2;}}

ctr = seconds_since_midnight(); // Original code

determine_state();              // Original code
// Serial.print("ctr: ");
// Serial.print(ctr);           // display counter
// Serial.println();


if ( (millis()-odczyt) >= 2000 ){

temperatura = bme.readTemperature() ;
wilgotnosc = bme.readHumidity() ;
cisnienie = bme.readPressure()/100.0F ;

odczyt = millis();}

if ( !ds.search(addr)){ds.reset_search();return;}
if (OneWire::crc8(addr, 7) != addr[7]){return;}

switch (addr[0]) {
  case 0x10:
      type_s = 1;break;
  case 0x28:
      type_s = 0;break;
  case 0x22:
     type_s = 0;break;
  default:
return;
}

ds.reset();
ds.select(addr);
ds.write(0x44, 1);      

present = ds.reset();
ds.select(addr);    
ds.write(0xBE);        

for ( i = 0; i < 9; i++) {data[i] = ds.read();}

int16_t raw = (data[1] << 8) | data[0];

if (type_s) {raw = raw << 3;
if (data[7] == 0x10) {raw = (raw & 0xFFF0) + 12 - data[6];}}

else {byte cfg = (data[4] & 0x60);
  if (cfg == 0x00) raw = raw & ~7;
  else if (cfg == 0x20) raw = raw & ~3;}

celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;

switch (strona) {

case 1:

if (lcdx != 1){lcd.clear();lcdx = 1;} //czyszczenie ekranu 1

tmElements_t tm;

if (RTC.read(tm)) {

lcd.setCursor (6, 0);
LCDprint2digits(tm.Hour);
lcd.print(':');
LCDprint2digits(tm.Minute);
lcd.print(':');
LCDprint2digits(tm.Second);
lcd.setCursor (5, 1);
lcd.print(tm.Day);
lcd.print('/');
lcd.print(monthName[tm.Month-1]);
lcd.print('/');
lcd.print(tmYearToCalendar(tm.Year));
   
}

lcd.setCursor (0, 2);
lcd.write(byte(0));
lcd.print("=");
lcd.print(temperatura, 1);
lcd.write(byte(3));
lcd.print("C");

lcd.setCursor (9, 2);
lcd.print("P=");
lcd.print(cisnienie, 1);
lcd.print("hPa");

lcd.setCursor (0, 3);
lcd.write(byte(0));
lcd.print("=");
lcd.print(celsius, 1);
lcd.write(byte(3));
lcd.print("C");

lcd.setCursor (9, 3);
lcd.write(byte(1));
lcd.write("=");
lcd.print(wilgotnosc, 1);
lcd.print("%");

break;

case 2:

if (lcdx != 2){lcd.clear();lcdx = 2;} //czyszczenie ekranu 2

//tmElements_t tm;

if (RTC.read(tm)) {

lcd.setCursor (6, 0);
LCDprint2digits(tm.Hour);
lcd.print(':');
LCDprint2digits(tm.Minute);
lcd.print(':');
LCDprint2digits(tm.Second);
lcd.setCursor (5, 1);
lcd.print(tm.Day);
lcd.print('/');
lcd.print(monthName[tm.Month-1]);
lcd.print('/');
lcd.print(tmYearToCalendar(tm.Year));
   
}

 lcd.setCursor(5,2);
 lcd.print(poradnia);        
 lcd.setCursor(6,3);
 lcd.print(ledonoff);

break;

}}

void LCDprint2digits(int number) {
if (number >= 0 && number < 10) {lcd.write('0');}
lcd.print(number);
}
Plany na przyszłość to dodanie pomiaru przepływu przez filtr w celu monitorowania jego stanu czyli określenia czasu kiedy pora już go wyczyścić.
Można prosić schemat? Głównie chodzi mi ile diod poszczególnych kolorów wykorzystałeś żeby uzyskać dane pory dnia.

Wypalcowane
Schemat jest w trakcie opracowania, jak będzie gotowy oczywiście go tutaj udostępnię. Muszę jeszcze rozwiązać kilka problemów z sygnałem PWM, driver który chcę użyć wymaga PWM 10V.
Witam,

ciekawy projekt sobie dłubiesz. Masz już jakieś aktualizacje? Może filmik z działania. Nie powiem, ale projekt mi się na prawdę podoba i mam nadzieję sklecić sobie w przyszłości coś takiego, ino jeszcze sporo nauki przede mną zanim opanuję moje arduino. Będę kibicował temu projektowi.

Pozdrawiam
Powoli coś się tam dzieje, jestem na etapie składania tego w całość, właśnie montuję LEDy w profile.
Drivery mam już opanowane, od strony programu dorabiam teraz czujniki zawilgocenia, mają być pod filtrem i alarmować w razie przecieku. Z przepływomierza będę musiał chyba zrezygnować, nie mam miejsca nad lustrem wody a na zewnątrz boję się go zamontować (nie budzi zaufania pod względem szczelności).
Rozumiem, że filtr to kubełek. Trzymasz go w jakimś innym naczyniu/akwarium/wiaderku żeby w razie W mieć jeszcze czas na reakcję? Myślałeś nad powiadomieniem o przecieku np. mailowo albo sms?
Tak, jest w naczyniu i planuję dodać moduł wifi ale to dalsze plany
Dodałem do kodu dwa czujniki obecności wody (wykorzystałem do tego czujniki zawilgocenia gleby FC-28) podłączone do pinów A0 i A1 stan czujników jest wyświetlany na wyświetlaczu i dodatkowo obecność wody pod filtrem kubełkowym jest sygnalizowana buzerem podpiętym do pinu 2 Arduino.
Kod wygląda tak:
Kod:
#include <TimerOne.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <OneWire.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <LiquidCrystal_I2C.h>
#define BACKLIGHT_PIN 3
LiquidCrystal_I2C  lcd(0x27,2,1,0,4,5,6,7);
#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10

#define SEALEVELPRESSURE_HPA (1013.25)

OneWire  ds(11);  // on pin 11 (a 4.7K resistor is necessary)
Adafruit_BME280 bme; // I2C

const char *monthName[12] = {
"01", "02", "03", "04", "05", "06",
"07", "08", "09", "10", "11", "12"
};
byte temp[8] = //ikona temperatury
{
B00100,
B01010,
B01010,
B01110,
B01110,
B11111,
B11111,
B01110
};

byte wilg[8] = //ikona wilgotnosci
{
B00100,
B00100,
B01010,
B10001,
B10001,
B10001,
B01110,
};

byte stopnie[8] = //ikona stopni
{
   B01100,
   B10010,
   B10010,
   B01100,
   B00000,
   B00000,
   B00000,
   B00000
};

byte procent[8] = //ikona stopni
{
   B00000,
   B00000,
   B00000,
   B00000,
   B10001,
   B11011,
   B11111,
   B11111
};

byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;

unsigned long odczyt = 0;
unsigned long czas = 0;
unsigned long z = 0 ;
byte lcdx = 1;
byte strona = 1;

float temperatura ;
float wilgotnosc ;
float cisnienie ;
String wilgotnosc1 = "";


int ledEnable = 6;
int ledEnable7 = 7;

const int kChan0Pin = 9; // Channel 0 Pin
const int kChan1Pin = 10; // Channel 1 Pin

const long kTurnOn = 27000; // time dawn begins - 0900hrs
const long kTurnOff = 65820; // time sunset begins - 2100hrs

const int kDayState[] = { 0,0 }; // daytime LED state
const int kNightState[] = { 1023, 1023 }; // nighttime LED state

const long kFadeDuration = 300; // 60 minutes

long ctr;

void fader(long start_time, const int start_state[], const int end_state[], int out[2]) {

float per_second_delta_0 = (float) (end_state[0]-start_state[0])/kFadeDuration;
float per_second_delta_1 = (float) (end_state[1]-start_state[1])/kFadeDuration;

long elapsed = ctr-start_time;

out[0] = start_state[0] + per_second_delta_0 * elapsed;
out[1] = start_state[1] + per_second_delta_1 * elapsed;
}

long seconds_since_midnight() {
//  setTime(21, 45, 00, 16, 2, 2015);
//set the system time to 21hrs 45min 00sec 16,Feb 2015...does not set RTC, will reset upon powerup

time_t t = now();
long hr = hour(t);
long min = minute(t);
long sec = second(t);
long total = hr * 3600 + min * 60 + sec;
return total;
}

void set_state(const int state[]) {
if (state[0] >= 0 && state[0] <= 1023) Timer1.setPwmDuty(kChan0Pin, state[0]);
if (state[1] >= 0 && state[1] <= 1023) Timer1.setPwmDuty(kChan1Pin, state[1]);
}


// status dzień/noc

String poradnia = "";
String ledonoff = "";

void determine_state() {
if ( ctr >= 0 && ctr < kTurnOn ) { // night
  set_state(kNightState);
 
  poradnia = "NIGHT/MODE ";        
  digitalWrite(ledEnable,HIGH);
  digitalWrite(ledEnable7,HIGH);
  ledonoff = "LED-OFF";
 
} else if ( ctr >= kTurnOn && ctr <= (kTurnOn+kFadeDuration) ) { // sunrise
int foo[2];
fader(kTurnOn, kNightState, kDayState, foo);
set_state(foo);

   poradnia = "SUNRISE/MODE";              
   digitalWrite(ledEnable, LOW);
   digitalWrite(ledEnable7, LOW);
   ledonoff = "LED-ON ";

} else if ( ctr > (kTurnOn+kFadeDuration) && ctr < kTurnOff ) { // day
set_state(kDayState);
 
  poradnia = "DAY/MODE";              
  digitalWrite(ledEnable, LOW);
  digitalWrite(ledEnable7, LOW);
  ledonoff = "LED-ON ";

} else if ( ctr >= kTurnOff && ctr <= (kTurnOff+kFadeDuration) ) { // sunset
int foo[2];
fader(kTurnOff, kDayState, kNightState, foo);
set_state(foo);

   poradnia = "SUNSET/MODE";              
   digitalWrite(ledEnable, LOW);
   digitalWrite(ledEnable7, LOW);
   ledonoff = "LED-ON ";

} else if ( ctr > (kTurnOff+kFadeDuration) && ctr < 86400 ) { // night
set_state(kNightState);

   poradnia = "NIGHT/MODE";        
   digitalWrite(ledEnable,HIGH);
   digitalWrite(ledEnable7,HIGH);
   ledonoff = "LED-OFF";
  }
}



void setup(void) {

Serial.begin(115200);        
setSyncProvider(RTC.get);
setSyncInterval(120);
Wire.begin();
Timer1.initialize(6666);     // 150Hz PWM
pinMode(kChan0Pin, OUTPUT);    
Timer1.pwm(kChan0Pin, 1023);
pinMode(kChan1Pin, OUTPUT);    
Timer1.pwm(kChan1Pin, 1023);
pinMode(ledEnable,OUTPUT);   // Led control
pinMode(ledEnable7,OUTPUT);

lcd.begin(20, 4);
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
//lcd.setBacklightPin(3, HIGH);
lcd.createChar(0, temp);
lcd.createChar(1, wilg);
lcd.createChar(3, stopnie);
lcd.createChar(4, procent);

pinMode(A1, INPUT); //set up analog pin 1 to be input humidity
pinMode(A0, INPUT); //set up analog pin 0 to be input humidity
pinMode(2, OUTPUT); // buzer

if (!bme.begin()) {while (1);}

}

void loop() {

unsigned long sek = millis()/1000 ;
if ( (millis()-czas) >= 10000 ){czas = millis();
if (strona == 2){strona = 1;}
else if(strona == 1){strona = 2;}}

ctr = seconds_since_midnight(); // Original code

determine_state();              // Original code

if ( (millis()-odczyt) >= 2000 ){

temperatura = bme.readTemperature() ;
wilgotnosc = bme.readHumidity() ;
cisnienie = bme.readPressure()/100.0F ;

odczyt = millis();}

if ( !ds.search(addr)){ds.reset_search();return;}
if (OneWire::crc8(addr, 7) != addr[7]){return;}

switch (addr[0]) {
  case 0x10:
      type_s = 1;break;
  case 0x28:
      type_s = 0;break;
  case 0x22:
     type_s = 0;break;
  default:
return;
}

ds.reset();
ds.select(addr);
ds.write(0x44, 1);      

present = ds.reset();
ds.select(addr);    
ds.write(0xBE);        

for ( i = 0; i < 9; i++) {data[i] = ds.read();}

int16_t raw = (data[1] << 8) | data[0];

if (type_s) {raw = raw << 3;
if (data[7] == 0x10) {raw = (raw & 0xFFF0) + 12 - data[6];}}

else {byte cfg = (data[4] & 0x60);
  if (cfg == 0x00) raw = raw & ~7;
  else if (cfg == 0x20) raw = raw & ~3;}

celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;

//wilgotnosc start
{
 int s1 = analogRead(A0);
 int s2 = analogRead(A1); //take a sample
//  Serial.print(s1); Serial.print(" - ");
//  Serial.print(s2); Serial.print(" - ");

if(s1 < 400 || s2 < 400) {
//   Serial.println("Sensor in WATER");
    wilgotnosc1 = "WATER";
    digitalWrite(2, HIGH);
}
else {
 if((s1 < 600) || (s2 < 600)) {
   wilgotnosc1 = "Humidity";
   digitalWrite(2, HIGH);
 }  
else {
 if((s1 < 1000)  || (s2 < 1000)) {
    wilgotnosc1 = "Dry";
    digitalWrite(2, HIGH);
 }
else {
    wilgotnosc1 = "OK";
    digitalWrite(2, LOW);
   }
 }
}
}
//wilgotność end


switch (strona) {

case 1:

if (lcdx != 1){lcd.clear();lcdx = 1;} //czyszczenie ekranu 1

tmElements_t tm;

if (RTC.read(tm)) {

lcd.setCursor (0, 0);
LCDprint2digits(tm.Hour);
lcd.print(':');
LCDprint2digits(tm.Minute);
lcd.print(':');
LCDprint2digits(tm.Second);
lcd.setCursor (10, 0);
lcd.print(tm.Day);
lcd.print('/');
lcd.print(monthName[tm.Month-1]);
lcd.print('/');
lcd.print(tmYearToCalendar(tm.Year));
   
}

lcd.setCursor(0,1); //wilgotnosc
lcd.write(byte(4));
lcd.print("=");
lcd.print(wilgotnosc1);  //wilgotnosc

lcd.setCursor (0, 2);
lcd.write(byte(0));
lcd.print("=");
lcd.print(temperatura -1.8, 1);
lcd.write(byte(3));
lcd.print("C");

lcd.setCursor (9, 2);
lcd.print("P=");
lcd.print(cisnienie, 1);
lcd.print("hPa");

lcd.setCursor (0, 3);
lcd.write(byte(0));
lcd.print("=");
lcd.print(celsius, 1);
lcd.write(byte(3));
lcd.print("C");

lcd.setCursor (9, 3);
lcd.write(byte(1));
lcd.write("=");
lcd.print(wilgotnosc, 1);
lcd.print("%");

break;

case 2:

if (lcdx != 2){lcd.clear();lcdx = 2;} //czyszczenie ekranu 2

//tmElements_t tm;

if (RTC.read(tm)) {

lcd.setCursor (6, 0);
LCDprint2digits(tm.Hour);
lcd.print(':');
LCDprint2digits(tm.Minute);
lcd.print(':');
LCDprint2digits(tm.Second);
lcd.setCursor (5, 1);
lcd.print(tm.Day);
lcd.print('/');
lcd.print(monthName[tm.Month-1]);
lcd.print('/');
lcd.print(tmYearToCalendar(tm.Year));
   
}

 lcd.setCursor(5,2);
 lcd.print(poradnia);        
 lcd.setCursor(6,3);
 lcd.print(ledonoff);


break;

}}

void LCDprint2digits(int number) {
if (number >= 0 && number < 10) {lcd.write('0');}
lcd.print(number);
}

Oczywiście wszystkie uwagi i sugestie mile widziane.
Tak się zastanawiam że przydałoby się jeszcze zrobić żeby można było włączać i wyłączać oświetlenie (PWM na 100%) niezależnie od ustawionego harmonogramu za pomocą przycisku. Niestety nie mam pojęcia jak się za to zabrać. Macie jakiś pomysł na to?
Pin 4 do masy włącza oświetlenie na 100 % ale sprawdź timery w tych linijkach bo nie pamiętam czy 1023 to max czy min oświetlenie .

if ( digitalRead(4) == LOW ){

digitalWrite(ledEnable,HIGH);
digitalWrite(ledEnable7,HIGH);
Timer1.pwm(kChan1Pin, 1023);
Timer1.pwm(kChan0Pin, 1023);

}else{ determine_state(); }



Kod:
#include <TimerOne.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <OneWire.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <LiquidCrystal_I2C.h>
#define BACKLIGHT_PIN 3
LiquidCrystal_I2C  lcd(0x27,2,1,0,4,5,6,7);
#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10

#define SEALEVELPRESSURE_HPA (1013.25)

OneWire  ds(11);  // on pin 11 (a 4.7K resistor is necessary)
Adafruit_BME280 bme; // I2C

const char *monthName[12] = {
"01", "02", "03", "04", "05", "06",
"07", "08", "09", "10", "11", "12"
};
byte temp[8] = //ikona temperatury
{
B00100,
B01010,
B01010,
B01110,
B01110,
B11111,
B11111,
B01110
};

byte wilg[8] = //ikona wilgotnosci
{
B00100,
B00100,
B01010,
B10001,
B10001,
B10001,
B01110,
};

byte stopnie[8] = //ikona stopni
{
   B01100,
   B10010,
   B10010,
   B01100,
   B00000,
   B00000,
   B00000,
   B00000
};

byte procent[8] = //ikona stopni
{
   B00000,
   B00000,
   B00000,
   B00000,
   B10001,
   B11011,
   B11111,
   B11111
};

byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;

unsigned long odczyt = 0;
unsigned long czas = 0;
unsigned long z = 0 ;
byte lcdx = 1;
byte strona = 1;

float temperatura ;
float wilgotnosc ;
float cisnienie ;
String wilgotnosc1 = "";


int ledEnable = 6;
int ledEnable7 = 7;

const int kChan0Pin = 9; // Channel 0 Pin
const int kChan1Pin = 10; // Channel 1 Pin

const long kTurnOn = 27000; // time dawn begins - 0900hrs
const long kTurnOff = 65820; // time sunset begins - 2100hrs

const int kDayState[] = { 0,0 }; // daytime LED state
const int kNightState[] = { 1023, 1023 }; // nighttime LED state

const long kFadeDuration = 300; // 60 minutes

long ctr;

void fader(long start_time, const int start_state[], const int end_state[], int out[2]) {

float per_second_delta_0 = (float) (end_state[0]-start_state[0])/kFadeDuration;
float per_second_delta_1 = (float) (end_state[1]-start_state[1])/kFadeDuration;

long elapsed = ctr-start_time;

out[0] = start_state[0] + per_second_delta_0 * elapsed;
out[1] = start_state[1] + per_second_delta_1 * elapsed;
}

long seconds_since_midnight() {
//  setTime(21, 45, 00, 16, 2, 2015);
//set the system time to 21hrs 45min 00sec 16,Feb 2015...does not set RTC, will reset upon powerup

time_t t = now();
long hr = hour(t);
long min = minute(t);
long sec = second(t);
long total = hr * 3600 + min * 60 + sec;
return total;
}

void set_state(const int state[]) {
if (state[0] >= 0 && state[0] <= 1023) Timer1.setPwmDuty(kChan0Pin, state[0]);
if (state[1] >= 0 && state[1] <= 1023) Timer1.setPwmDuty(kChan1Pin, state[1]);
}


// status dzień/noc

String poradnia = "";
String ledonoff = "";

void determine_state() {
if ( ctr >= 0 && ctr < kTurnOn ) { // night
  set_state(kNightState);

  poradnia = "NIGHT/MODE ";        
  digitalWrite(ledEnable,HIGH);
  digitalWrite(ledEnable7,HIGH);
  ledonoff = "LED-OFF";

} else if ( ctr >= kTurnOn && ctr <= (kTurnOn+kFadeDuration) ) { // sunrise
int foo[2];
fader(kTurnOn, kNightState, kDayState, foo);
set_state(foo);

   poradnia = "SUNRISE/MODE";              
   digitalWrite(ledEnable, LOW);
   digitalWrite(ledEnable7, LOW);
   ledonoff = "LED-ON ";

} else if ( ctr > (kTurnOn+kFadeDuration) && ctr < kTurnOff ) { // day
set_state(kDayState);

  poradnia = "DAY/MODE";              
  digitalWrite(ledEnable, LOW);
  digitalWrite(ledEnable7, LOW);
  ledonoff = "LED-ON ";

} else if ( ctr >= kTurnOff && ctr <= (kTurnOff+kFadeDuration) ) { // sunset
int foo[2];
fader(kTurnOff, kDayState, kNightState, foo);
set_state(foo);

   poradnia = "SUNSET/MODE";              
   digitalWrite(ledEnable, LOW);
   digitalWrite(ledEnable7, LOW);
   ledonoff = "LED-ON ";

} else if ( ctr > (kTurnOff+kFadeDuration) && ctr < 86400 ) { // night
set_state(kNightState);

   poradnia = "NIGHT/MODE";        
   digitalWrite(ledEnable,HIGH);
   digitalWrite(ledEnable7,HIGH);
   ledonoff = "LED-OFF";
  }
}



void setup(void) {

Serial.begin(115200);        
setSyncProvider(RTC.get);
setSyncInterval(120);
Wire.begin();
Timer1.initialize(6666);     // 150Hz PWM
pinMode(kChan0Pin, OUTPUT);    
Timer1.pwm(kChan0Pin, 1023);
pinMode(kChan1Pin, OUTPUT);    
Timer1.pwm(kChan1Pin, 1023);
pinMode(ledEnable,OUTPUT);   // Led control
pinMode(ledEnable7,OUTPUT);

lcd.begin(20, 4);
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
//lcd.setBacklightPin(3, HIGH);
lcd.createChar(0, temp);
lcd.createChar(1, wilg);
lcd.createChar(3, stopnie);
lcd.createChar(4, procent);

pinMode(A1, INPUT); //set up analog pin 1 to be input humidity
pinMode(A0, INPUT); //set up analog pin 0 to be input humidity
pinMode(2, OUTPUT); // buzer

pinMode( 4, INPUT_PULLUP );


if (!bme.begin()) {while (1);}

}

void loop() {

unsigned long sek = millis()/1000 ;
if ( (millis()-czas) >= 10000 ){czas = millis();
if (strona == 2){strona = 1;}
else if(strona == 1){strona = 2;}}

ctr = seconds_since_midnight(); // Original code

if ( digitalRead(4) == LOW ){
  
  digitalWrite(ledEnable,HIGH);
  digitalWrite(ledEnable7,HIGH);
  Timer1.pwm(kChan1Pin, 1023);
  Timer1.pwm(kChan0Pin, 1023);
  
  }else{ determine_state();  }

if ( (millis()-odczyt) >= 2000 ){

temperatura = bme.readTemperature() ;
wilgotnosc = bme.readHumidity() ;
cisnienie = bme.readPressure()/100.0F ;

odczyt = millis();}

if ( !ds.search(addr)){ds.reset_search();return;}
if (OneWire::crc8(addr, 7) != addr[7]){return;}

switch (addr[0]) {
  case 0x10:
      type_s = 1;break;
  case 0x28:
      type_s = 0;break;
  case 0x22:
     type_s = 0;break;
  default:
return;
}

ds.reset();
ds.select(addr);
ds.write(0x44, 1);      

present = ds.reset();
ds.select(addr);    
ds.write(0xBE);        

for ( i = 0; i < 9; i++) {data[i] = ds.read();}

int16_t raw = (data[1] << 8) | data[0];

if (type_s) {raw = raw << 3;
if (data[7] == 0x10) {raw = (raw & 0xFFF0) + 12 - data[6];}}

else {byte cfg = (data[4] & 0x60);
  if (cfg == 0x00) raw = raw & ~7;
  else if (cfg == 0x20) raw = raw & ~3;}

celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;

//wilgotnosc start
{
int s1 = analogRead(A0);
int s2 = analogRead(A1); //take a sample
//  Serial.print(s1); Serial.print(" - ");
//  Serial.print(s2); Serial.print(" - ");

if(s1 < 400 || s2 < 400) {
//   Serial.println("Sensor in WATER");
    wilgotnosc1 = "WATER";
    digitalWrite(2, HIGH);
}
else {
if((s1 < 600) || (s2 < 600)) {
   wilgotnosc1 = "Humidity";
   digitalWrite(2, HIGH);
}  
else {
if((s1 < 1000)  || (s2 < 1000)) {
    wilgotnosc1 = "Dry";
    digitalWrite(2, HIGH);
}
else {
    wilgotnosc1 = "OK";
    digitalWrite(2, LOW);
   }
}
}
}
//wilgotność end


switch (strona) {

case 1:

if (lcdx != 1){lcd.clear();lcdx = 1;} //czyszczenie ekranu 1

tmElements_t tm;

if (RTC.read(tm)) {

lcd.setCursor (0, 0);
LCDprint2digits(tm.Hour);
lcd.print(':');
LCDprint2digits(tm.Minute);
lcd.print(':');
LCDprint2digits(tm.Second);
lcd.setCursor (10, 0);
lcd.print(tm.Day);
lcd.print('/');
lcd.print(monthName[tm.Month-1]);
lcd.print('/');
lcd.print(tmYearToCalendar(tm.Year));
  
}

lcd.setCursor(0,1); //wilgotnosc
lcd.write(byte(4));
lcd.print("=");
lcd.print(wilgotnosc1);  //wilgotnosc

lcd.setCursor (0, 2);
lcd.write(byte(0));
lcd.print("=");
lcd.print(temperatura -1.8, 1);
lcd.write(byte(3));
lcd.print("C");

lcd.setCursor (9, 2);
lcd.print("P=");
lcd.print(cisnienie, 1);
lcd.print("hPa");

lcd.setCursor (0, 3);
lcd.write(byte(0));
lcd.print("=");
lcd.print(celsius, 1);
lcd.write(byte(3));
lcd.print("C");

lcd.setCursor (9, 3);
lcd.write(byte(1));
lcd.write("=");
lcd.print(wilgotnosc, 1);
lcd.print("%");

break;

case 2:

if (lcdx != 2){lcd.clear();lcdx = 2;} //czyszczenie ekranu 2

//tmElements_t tm;

if (RTC.read(tm)) {

lcd.setCursor (6, 0);
LCDprint2digits(tm.Hour);
lcd.print(':');
LCDprint2digits(tm.Minute);
lcd.print(':');
LCDprint2digits(tm.Second);
lcd.setCursor (5, 1);
lcd.print(tm.Day);
lcd.print('/');
lcd.print(monthName[tm.Month-1]);
lcd.print('/');
lcd.print(tmYearToCalendar(tm.Year));
  
}

lcd.setCursor(5,2);
lcd.print(poradnia);        
lcd.setCursor(6,3);
lcd.print(ledonoff);


break;

}}

void LCDprint2digits(int number) {
if (number >= 0 && number < 10) {lcd.write('0');}
lcd.print(number);
}
Stron: 1 2