Arduino Polska Forum

Pełna wersja: Powtarzanie co X godzin
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2
Witam,

W układzie mam podłączone RTC i chciałbym aby jeden z pinów wyjściowych (np 6) zmieniał stan z niskiego na wysoki co x godzin, po czym wracał do stanu niskiego. Gdzie x będzie początkowo zdefiniowaną zmienną najchętniej typu int. Będzie to aktywowało przekaźnik z czasówką.
Czy ktoś może podpowiedzieć mi jak to zrobić, uwzględniając że zawsze liczy od 6 rano?
Zagadnienie dodatkowe, jak uzależnić żeby relayHeat działał tylko i wyłącznie gdy glight jest włączone?

Poniżej podaję cały kod gdyby był potrzebny.
Z góry dziękuję za pomoc.
Kod:
#include <LCDWIKI_GUI.h> //Core graphics library
#include <LCDWIKI_KBV.h> //Hardware-specific library
#include <SPI.h>
#include <DHT.h>
#include <Wire.h>
#include "Sodaq_DS3231.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <DS18B20.h>

LCDWIKI_KBV mylcd(ILI9486,40,38,39,-1,41);

#define  BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

#define relayGrowlight 2
#define relayWhitelight 3
#define relayHeat 4
#define relayFan 5
#define relayMist 6
#define relayWater 7

#define SENSOR_1 8
#define SENSOR_1_Type DHT22
#define SENSOR_2 9
#define SENSOR_2_Type DHT22
#define ONE_WIRE_BUS 10

int tempMin = 28;
int tempMax = 30;
int humMin = 60;
int humMax = 80;
int wlightOn_hour = 12;
int wlightOn_min = 0;
int wlightOff_hour = 20;
int wlightOff_min = 05;
int glightOn_hour = 6;
int glightOn_min = 30;
int glightOff_hour = 12;
int glightOff_min = 00;

float wlightOn = (60 * wlightOn_hour) + wlightOn_min;
float wlightOff = (60 * wlightOff_hour) + wlightOff_min;
float glightOn = (60 * glightOn_hour) + glightOn_min;
float glightOff = (60 * glightOff_hour) + glightOff_min;
float currentTime;

boolean glightVal, wlightVal, heatVal, fanVal, mistVal, waterVal;
boolean glightVal_tmp, wlightVal_tmp, heatVal_tmp, fanVal_tmp, mistVal_tmp, waterVal_tmp;
boolean light_1st = 0;


float hum1, temp1, hum1_tmp, temp1_tmp;
float hum2, temp2, hum2_tmp, temp2_tmp;

String tempState, humState, tempState_tmp, humState_tmp;
String dateString, timeString,  dayString;
String dateStringTmp, timeStringTmp, dayStringTmp;

DHT dht_1(SENSOR_1, SENSOR_1_Type);
DHT dht_2(SENSOR_2, SENSOR_2_Type);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DS18B20 ds(10);

void setup(void)
{
  mylcd.Init_LCD();
  mylcd.Fill_Screen(BLACK);
  dht_1.begin();
  dht_2.begin();
  rtc.begin();
  Wire.begin();
  pinMode(relayGrowlight, OUTPUT);
  pinMode(relayWhitelight, OUTPUT);
  pinMode(relayHeat, OUTPUT);
  pinMode(relayFan, OUTPUT);
  pinMode(relayMist, OUTPUT);
  pinMode(relayWater, OUTPUT);
  sensors.begin();


  wlightVal_tmp = !(digitalRead(relayWhitelight));
  glightVal_tmp = !(digitalRead(relayGrowlight));
  heatVal_tmp = !(digitalRead(relayHeat));
  fanVal_tmp = !(digitalRead(relayFan));
  mistVal_tmp = !(digitalRead(relayMist));
  waterVal_tmp = !(digitalRead(relayWater));


  mylcd.Set_Rotation(1);
  mylcd.Fill_Screen(BLACK);
  mylcd.Set_Text_Mode(0);
  mylcd.Set_Text_colour(WHITE);
  mylcd.Set_Text_Back_colour(BLACK);
  mylcd.Set_Text_Size(2);

  mylcd.Print_String("Temp1:", 15, 10);
  mylcd.Print_String("Wilg1:", 15, 30);
  mylcd.Print_String("Temp2:", 15, 50);
  mylcd.Print_String("Wilg2:", 15, 70);
   
  mylcd.Print_String("RELAYS", 40, 120);
  mylcd.Print_String("GrowLight:",15, 150);
  mylcd.Print_String("WhiteLight:",15, 170);
  mylcd.Print_String("Heat1:",15, 190);
  mylcd.Print_String("Fan:",15, 210);
  mylcd.Print_String("Mist:",15, 230);
  mylcd.Print_String("Water:",15, 250);


}

void loop()
{
 
  //while (ds.selectNext())
   //uint8_t address[8];
//ds.getAddress(address);
// for (uint8_t i = 0; i < 8; i++);
  ds.doConversion();
  rtc.begin();
  DateTime now = rtc.now(); //get the current date-time
  currentTime = (60 * int(now.hour())) + int(now.minute());
 
  hum1 = dht_1.readHumidity();
  temp1 = dht_1.readTemperature();
  hum2 = dht_2.readHumidity();
  temp2 = ds.getTempC();

  glightVal = digitalRead(relayGrowlight);
  wlightVal = digitalRead(relayWhitelight);
  heatVal = digitalRead(relayHeat);
  fanVal = digitalRead(relayFan);
  mistVal = digitalRead(relayMist);
  waterVal = digitalRead(relayWater);

  mylcd.Set_Text_colour(WHITE);
 
  if (temp1 == temp1_tmp)
  {
    goto wilgotnosc;
    }
    else {
     mylcd.Print_Number_Float(temp1,2,100,10,'.',5,' ');
        temp1_tmp = temp1;
    }

  if (hum1 == hum1_tmp)
  {
    goto temperatura2;
    }
    else {
  wilgotnosc:
      mylcd.Print_Number_Float(hum1,2,100,30,'.',5,' ');
        hum1_tmp = hum1;

  }
 
temperatura2:
  if (temp2 == temp2_tmp)
  {
    goto wilgotnosc2;
  }
  else {
       mylcd.Print_Number_Float(temp2,2,100,50,'.',5,' ');
         temp2_tmp = temp2;
  }
  wilgotnosc2:
  if (hum2 == hum2_tmp)
  {
    goto data;
  }
  else {
      mylcd.Print_String("", 100, 70);
        mylcd.Print_Number_Float(hum2,2,100,70,'.',5,' ');
          hum2_tmp = hum2;
  }
  data:
   dayString = getDayOfWeek(now.dayOfWeek());
  dateString = String(now.date()) + "/" + String(now.month()) + "/" + (String(now.year())).substring(2) + " "; //use substring to extract last two digits of the year (to save space)

  if (now.minute() < 10)
  {
    timeString = String(now.hour()) + ":0" + String(now.minute()); //add "0" before 0-9 minutes
  }
  else  {
    timeString = String(now.hour()) + ":" + String(now.minute());
  }

  //Print out Day, Date and Time
  if (dayString == dayStringTmp)
  {
    goto wysData;
  }
  else {
        mylcd.Print_String(dayString, 250, 270);
    dayStringTmp = dayString;
  }

wysData:

  if (dateString == dateStringTmp)
  {
    goto wysCzas;
  }
  else {
        mylcd.Print_String(dateString,1, 270);
    dateStringTmp = dateString;
  }

wysCzas:

  if (timeString == timeStringTmp)
  {
    goto relays;
  }
  else {
        mylcd.Print_String(timeString,150, 270);
    timeStringTmp = timeString;
  }

relays:

  mylcd.Print_String(relayState(glightVal),145, 150);
  mylcd.Print_String(relayState(wlightVal),145, 170);
  mylcd.Print_String(relayState(heatVal),145, 190);
  mylcd.Print_String(relayState(fanVal),145, 210);
  mylcd.Print_String(relayState(mistVal),145, 230);
  mylcd.Print_String(relayState(waterVal),145, 250);
  //Checking temperature

    if (temp2 < tempMin)
  {
    tempState = "Low temperature ";

     if (heatVal == 1)
    {
      digitalWrite(relayHeat, 0);
      heatVal = 0;
    }
  }
   else if (temp2 >= tempMax)
  {
    tempState = "High temperature";

    if (heatVal == 0)
    {
      digitalWrite(relayHeat, 1);
      heatVal = 1;
    }

  }
  else {
    tempState = "Temperature OK  ";
  }

  if (heatVal == heatVal_tmp)
  {
    goto printState;
  }
  else
  {
  
    heatVal_tmp = heatVal;
  }

printState:
  if (tempState == tempState_tmp)
  {
    goto checkHum;
  }
  else
  {
   // mylcd.Print_String(tempState_tmp,125, 190);
  
    if (tempState == "Temperature OK  ")
    {
      mylcd.Set_Text_colour(GREEN);
    }
    else
    {
      mylcd.Set_Text_colour(RED);
    }
    mylcd.Print_String(tempState,195, 190);
    tempState_tmp = tempState;
  }


checkHum:
  //Checking humidity
  if (hum1 < humMin)
  {
    humState = "Low humidity ";
  }
  else if (hum1 >= humMax)
  {
    humState = "High humidity";
  }

  else
  {
    humState = "Humidity OK  ";
  }

  if (humState == humState_tmp)
  {
    goto wlightTimer;
  }
  else
  {
       
    if (humState == "Humidity OK  ")
    {
      mylcd.Set_Text_colour(GREEN);
    }
    else
    {
      mylcd.Set_Text_colour(RED);
    }
    mylcd.Print_String(humState,195, 210);
    humState_tmp = humState;

  }

wlightTimer:

  if (wlightOn <= currentTime < wlightOff)
  {
    if (wlightVal == 1)
    {
      digitalWrite(relayWhitelight, 0);
      wlightVal = 0;
    }
  }

  if (wlightOn > currentTime || wlightOff <= currentTime)
  {
    if (wlightVal == 0)
    {
      digitalWrite(relayWhitelight, 1);
      wlightVal = 1;
    }
  }
  if (light_1st == 0)
  {
   
    light_1st = 1;
  }
 
  if (wlightVal == wlightVal_tmp)
  {
    goto glightTimer;
  }
    else {
   
    wlightVal_tmp = wlightVal;
  }
glightTimer:

  if (glightOn <= currentTime < glightOff)
  {
    if (glightVal == 1)
    {
      digitalWrite(relayGrowlight, 0);
      glightVal = 0;
    }
  }

  if (glightOn > currentTime || glightOff <= currentTime)
  {
    if (glightVal == 0)
    {
      digitalWrite(relayGrowlight, 1);
      glightVal = 1;
    }
  }
  if (light_1st == 0)
  {
  
    light_1st = 1;
  }

   if (glightVal == glightVal_tmp)
  {
    goto wentylator;
  }
  else {
  
    glightVal_tmp = glightVal;
  }
wentylator:
if (hum1 < humMax)
  {
        if (fanVal == 0)
    {
      digitalWrite(relayFan, 1);
      fanVal = 1;
    }
  }
  else if (hum1 >= humMax)
  {

    if (fanVal == 1)
    {
      digitalWrite(relayFan, 0);
      fanVal = 0;
    }

  }
else {

  }

  if (fanVal == fanVal_tmp)
  {
    goto koniec;
  }
  else
  {
  
    fanVal_tmp = fanVal;
  }
koniec:  
  delay(2000);

}
void setRTCTime()
{
  DateTime dt(2020, 11, 28, 19, 0, 0, 6); // Year, Month, Day, Hour, Minutes, Seconds, Day of Week
  rtc.setDateTime(dt); //Adjust date-time as defined 'dt' above
}

String getDayOfWeek(int i)
{
  switch (i)
  {
    case 1: return "Poniedzialek"; break;
    case 2: return "Wtorek"; break;
    case 3: return "Sroda"; break;
    case 4: return "Czwartek"; break;
    case 5: return "Piatek"; break;
    case 6: return "Sobota"; break;
    case 7: return "Niedziela"; break;
    default: return "Poniedzialek"; break;
  }
}

String relayState(int x)
{
  switch (x)
  {
    case 0: return "ON "; break;
    case 1: return "OFF"; break;
    default: return "ON "; break;
  }
}
A czytałeś przykłady dla DS3231 bo ma taką możliwość...

Np..

/*
DS3231: Real-Time Clock. Alarm simple
Read more: www.jarzebski.pl/arduino/komponenty/zegar-czasu-rzeczywistego-rtc-DS3231.html
GIT: https://github.com/jarzebski/Arduino-DS3231
Web: http://www.jarzebski.pl
© 2014 by Korneliusz Jarzebski
*/

#include <Wire.h>
#include <DS3231.h>

DS3231 clock;
RTCDateTime dt;
boolean isAlarm = false;
boolean alarmState = false;
int alarmLED = 4;

void alarmFunction()
{
Serial.println("*** INT 0 ***");
isAlarm = true;
}

void setup()
{
Serial.begin(9600);

// Initialize DS3231
Serial.println("Initialize DS3231");;
clock.begin();

// Disarm alarms and clear alarms for this example, because alarms is battery backed.
// Under normal conditions, the settings should be reset after power and restart microcontroller.
clock.armAlarm1(false);
clock.armAlarm2(false);
clock.clearAlarm1();
clock.clearAlarm2();

// Manual (Year, Month, Day, Hour, Minute, Second)
clock.setDateTime(2014, 4, 25, 0, 0, 0);

// Set Alarm1 - Every 20s in each minute
// setAlarm1(Date or Day, Hour, Minute, Second, Mode, Armed = true)
clock.setAlarm1(0, 0, 0, 10, DS3231_MATCH_S);

// Attach Interrput 0. In Arduino UNO connect DS3231 INT to Arduino Pin 2
attachInterrupt(0, alarmFunction, FALLING);

// Setup LED Pin
pinMode(alarmLED, OUTPUT);
}

void loop()
{
dt = clock.getDateTime();
Serial.println(clock.dateFormat("d-m-Y H:iConfused - l", dt));

if (isAlarm)
{
digitalWrite(alarmLED, alarmState);
alarmState = !alarmState;
clock.clearAlarm1();
}

delay(1000);
}
Dziękuję za odpowiedź. W prawdzie używam innej biblioteki ale funkcjonalności są te same. 
Też mam komendy:

rtc.enableInterrupts(18,4,0);    // interrupt at (h,m,s)
rtc.enableInterrupts(EveryMinute); //interrupt at  EverySecond, EveryMinute, EveryHour

Jeśli będę musiał użyję tej pierwszej trzy razy...
Przy okazji czy możesz mi objaśnić czemu służy linijka: 

attachInterrupt(0, alarmFunction, FALLING);

Nie rozumiem jej.
W DS3231 można ustawić dwa alarmy (różnia sie zakresem) musi być podłączony pin do przerywania i to jest to co się pytasz, SQW/INT podłączamy pod piny gdzie działa przerwanie wtedy nawet obudzi i wykona kod...

attachInterrupt(0, alarmFunction, FALLING);

To jest właśnie włączenie przerwania te "0" to INT0 chyba pin nr2 jak się nie mylę w uno. Wiec SQW/INT połączony z pinem 2 w uno. I jak dostanie sygnał to wykona się kod w "alarmFunction()"
Jak człowiek nie pyta, to umiera głupi. 
Przeczytałem to co napisałeś i mam więcej wątpliwości tylko.
Jeśli można mieć dwa alarmy to mam problem, potrzebuję aktywować dwa różne urządzenia w dwóch różnych zakresach.

Pierwsze to spryskiwacz, odpalany dwa razy od 1 do 3 razy dziennie, na kilkanaście-kilkadziesiąt sekund. Jak często i na ile dojdę metodą prób i błędów.

Drugie to generator mgły tzw fogger. Tutaj jest ciut gorzej bo chciałbym żeby włączał się rano i wieczorem na ok godzinę.

Przykład z biblioteki niby działa ale na serialprint co sekunda wyświetla "External Interrupt detected" mimo że podpięty mam tylko ekran.

Poza tym chyba patrzę w złą stronę, arduino nie musi być budzone ani wykrywać alarmów. Przecież nawet w markecie są do kupienia takie programowalne "czasówki" które zawsze o zaprogramowanej godzinie puszczają prąd na określony czas.
Na googlu nic nie mogę znaleźć, domyślam się że źle szukam.
Może ktoś napisał program do mrugnięcia diodą codziennie w południe?

Edit:
Ha, dwie minuty po poście wymyśliłem frazę dla googla i voilà:
https://starter-kit.nettigo.pl/2016/04/b...rs-16-4-0/
Wieczorkiem sprawdzę czy ma to prawo bytu.
Co ciekawe artykuł zaczyna się znajomo.
RTC DS3231 jest dość dokładnym zegarem. Można z niego wyciągać aktualną godzinę minutę i sekundę o dacie i dniu tygodnia nie wspomnę. Dodatkowo biblioteka Jarzębskiego pozwala na "odczyt" czasu UNIXowego (komenda dt.unixtime) co daje możliwość obliczania upływającego czasu podobnie jak millis() tylko co sekundę. Jest to dobre do odliczanie czasów dłuższych i to nawet jak w międzyczasie procesorek zostanie zresetowany, tylko jak użyjemy pamięci EEPROM do zapamiętania czasu startu.
Czyli zapamiętujemy czas UNIXowy w danej chwili najlepiej do pamięci EEPROM i sprawdzamy czy upłynął już czas zapamiętany + zadany i mamy już odliczanie czasu. Tu należy zwrócić uwagę, aby nie "zapamiętywać" zbyt często do pamięci EEPROM procesorka bo ona się zużywa, ale dwa do 4 razy na dobę można. Przy takim rozwiązaniu trzeba poczytać o tej pamięci.
No ale mając RTC to nic prostszego jak pytać go czy już upłynęła dana godzina np
dt = clock.getDateTime(); Tu odczytujemy dane z zegarka
i zadajemy zadanie dla procesorka:
if ( dt.hour == 12 && dt.minute == 0 && dt.second >= 0)
{
a tu wpisujemy co ma robić np. o godzinie 12 w południe.
}
Dla uruchomienia mgiełki na godzinę rano i wieczorem wystarczy napisać tak
dt = clock.getDateTime();
if ( dt.hour == 6 || dt.hour == 18)
{
digitalWrite(6, HIGH); // uruchamiasz mgiełkę wysokim stanem na pinie 6
}
else
{
digitalWrite(6i, LOW); // wyłączasz mgiełkę pinem 6 stanem niskim
}

Czyli już masz rozwiązanie jak uruchamiać mgiełkę rano i wieczorem. Chyba prostsze niż z przerwaniami.
Dalej to już przykład migania niezależnego diodami, z użyciem millis, pomoże Ci na uruchamianie na określony czas innych psikaczy itp.
Ta biblioteka używa millis(); tylko jest dla leniwych. Użycie jej niesie sporo niespodzianek
(05-01-2021, 17:58)Jarewa0606 napisał(a): [ -> ]Ta biblioteka  używa millis(); tylko jest dla leniwych. Użycie jej niesie sporo niespodzianek
Piszesz oczywiście o Timers.
Naprawdę dziękuję, DZIAŁA (wydaje mi się że trochę prowizorycznie ale będę jeszcze kombinował).
Strasznie dużo satysfakcji daje działające urządzenie nawet jeśli oprawa graficzna jest zerowa.
Podpowiedzcie jeszcze proszę, oryginalny kod nie był oczywiście mój i od samego początku zawierał taki zapis:
.
.
.
digitalWrite(relayHeat, 0);
heatVal = 0;
.
.
.
String relayState(int x)
{
  switch (x)
  {
    case 0: return "ON "; break;
    case 1: return "OFF" ; break;
    default: return "ON "; break;
  }
}


Był bardzo wygodny i pozwalał na bieżąco monitorować stan przekaźników. Problem w tym że zdefiniowane piny nie wchodziły na HIGH. Czy jest jakiś zapis żeby dla wszystkich relayState jeśli jest 0 to było HIGH i analogicznie 1 = LOW? Podoba mi się gdy wyświetla mi stan przekaźników.
A co to jest??

digitalWrite(relayHeat, 0);
heatVal = 0;


To powinno być inaczej...

Powinieneś dać flagę czyli

bool flag_relay1 =false;
uint8_t relayHeat =3 ; // wyjście przekaźnika

setup(){

pinMode( relayHeat, OUTPUT);
Serial.begin(9600);
}

loop(){

digitalWrite( relayHeat, flag_relay1);

flag_relay1 =! flag_relay1;
Serial.println (flag_relay1);
delay(1000);

}


efekt zobaczysz na monitorze rs...... Może uświadomisz sobie to....
Stron: 1 2