Stránka 1 z 1

RTC DS1302 Arduino NANO a nastavení spínače LED

Napsal: 06 zář 2020, 11:02
od Kony
Ahoj, snažím se pomocí NANO a RTC DS1302 nastavit časovač rozsvícení a zhasnutí LED..
Hodiny mi fungují krásně v serial mám výstup

Kód: Vybrat vše

11:00:40.767 -> Neděle 06-09-2020 11:01:00
ale ani zaboha nemůžu přijít na to jak nastavit, aby se mi v určitý čas rozsvítila LED na D3 a následně v určený čas zase zhasla..

Kód: Vybrat vše

// Example sketch for interfacing with the DS1302 timekeeping chip.
//
// Copyright (c) 2009, Matt Sparks
// All rights reserved.
//
// http://quadpoint.org/projects/arduino-ds1302
#include <stdio.h>
#include <DS1302.h>

namespace {

// Set the appropriate digital I/O pin connections. These are the pin
// assignments for the Arduino as well for as the DS1302 chip. See the DS1302
// datasheet:
//
//   http://datasheets.maximintegrated.com/en/ds/DS1302.pdf
const int kCePin   = 5;  // Chip Enable
const int kIoPin   = 6;  // Input/Output
const int kSclkPin = 7;  // Serial Clock

// Create a DS1302 object.
DS1302 rtc(kCePin, kIoPin, kSclkPin);

String dayAsString(const Time::Day day) {
  switch (day) {
    case Time::kSunday: return "Neděle";
    case Time::kMonday: return "Pondělí";
    case Time::kTuesday: return "Úterý";
    case Time::kWednesday: return "Středa";
    case Time::kThursday: return "Čtvrtek";
    case Time::kFriday: return "Pátek";
    case Time::kSaturday: return "Sobota";
  }
  return "(unknown day)";
}

void printTime() {
  // Get the current time and date from the chip.
  Time t = rtc.time();

  // Name the day of the week.
  const String day = dayAsString(t.day);

  // Format the time and date and insert into the temporary buffer.
  char buf[50];
  snprintf(buf, sizeof(buf), "%s %02d-%02d-%04d %02d:%02d:%02d",
           day.c_str(),
           t.date, t.mon, t.yr,
           t.hr, t.min, t.sec);

  // Print the formatted string to serial so we can see the time.
  Serial.println(buf);
}

}  // namespace

void setup() {
  Serial.begin(9600);
  pinMode(3, OUTPUT);

  // Initialize a new chip by turning off write protection and clearing the
  // clock halt flag. These methods needn't always be called. See the DS1302
  // datasheet for details.
  rtc.writeProtect(false);
  rtc.halt(false);

  // Make a new time object to set the date and time.
  // Sunday, September 22, 2013 at 01:38:50.
//  Time t(2020, 9, 5, 16, 29, 50, Time::kSaturday);

  // Set the time and date on the chip.
//  rtc.time(t);
}

// Loop and print the time every second.
void loop() {
  printTime();
//  Sepnuti led
//    if ( (t.hr == 15) && (t.min == 8) && (t.sec == 0) ) { digitalWrite(3, HIGH ); };
//  Vypnuti led
//    if ( (t.hr == 15) && (t.min == 9) && (t.sec == 0) ) { digitalWrite(3, LOW ); };
  delay(1000);
}

Re: RTC DS1302 Arduino NANO a nastavení spínače LED

Napsal: 06 zář 2020, 12:27
od gilhad
Nepomuze dat do loop() zjisteni toho casu pred ty testy?

Kód: Vybrat vše

// ...
void loop() {
  printTime();
Time t = rtc.time();
//  Sepnuti led
    if ( (t.hr == 15) && (t.min == 8) && (t.sec == 0) ) { digitalWrite(3, HIGH ); };
//  Vypnuti led
    if ( (t.hr == 15) && (t.min == 9) && (t.sec == 0) ) { digitalWrite(3, LOW ); };
//  ...

Re: RTC DS1302 Arduino NANO a nastavení spínače LED

Napsal: 06 zář 2020, 13:34
od AstroMiK
V tomhle zápisu existuje určité riziko, že se LED nerozsvítí (případně nezhasne).

Jde o to, že zjišťování času v RTC se provádí s periodou o něco málo delší, než 1 sekunda.
Je tam "delay(1000)" a ještě k tomu se musí přičíst nějaké zpoždění pro komunikaci s RTC a nějaké zpoždění na vyhodnocení podmínek.

Takže se může stát, že při průchodu první smyčkou bude skutečný čas 15:07:59.999 a v následující smyčce bude skutečný čas 15:08:01.001.
Protože RTC ukládá čas jen v celých sekundách, bude čas 15:08:00 přeskočený a k rozsvícení nedojde.

Nejjednodušší řešení by bylo zkrátit tu pauzu, aby bylo zajištěno, že perioda čtení času bude vždycky kratší než sekunda.


Jiné řešení by bylo převádět hodiny, minuty a sekundy na jedno číslo:

Kód: Vybrat vše

 unsigned long  n = (t.hr * 3600) + (t.min * 60) + (t.sec);
A v podmínkách pak testovat tohle číslo pomocí "větší" a "menší"

Kód: Vybrat vše

if (n >= 54480 and n <  54540)  digitalWrite(3, HIGH );
else                            digitalWrite(3, LOW );


PS:
Někdy se pro převod používá jednodušší násobení:

Kód: Vybrat vše

unsigned long  n = (t.hr * 10000) + (t.min * 100) + (t.sec);
V podmínkách se pak zadává čitelnějí formát času:

Kód: Vybrat vše

if (n >= 150800 and n <  150900)  digitalWrite(3, HIGH );    // 150800 = 15:08:00  ; 150900 = 15:09:00
else                              digitalWrite(3, LOW );

Re: RTC DS1302 Arduino NANO a nastavení spínače LED

Napsal: 06 zář 2020, 19:46
od pavel1tu
JJ, jak píše AstroMik, použít to násobení, kdy 195732 je 19h57min32s
a testovat => a =< , ne rovno == to prostě nebude fungovat hlavně při případném restartu arduina
(toto zapínání/vypínání podle času používám i ve zveřejněném projektu akvarium)

Ještě doporučím prozkoumat jak fungují "tásky" (část programy se provede jednou za určitý čas),
popřípadě na to použít knihovnu, která nabízí i další funkce, klidně pomohu, poradím (v tom akváriu to používám).

PS: z RTC stačí vyčítat čas jednou za 10s/30s/minutu, pokud si nehrajete na milisekundy, mne se při vyčítání bez pauzy dle tásku Arduina někdy RTC i kousnul.

Re: RTC DS1302 Arduino NANO a nastavení spínače LED

Napsal: 06 zář 2020, 20:23
od AstroMiK
Ještě drobné doplnění.

Pozor na přechody přes půlnoc.
Když bude čas zapnutí vyšší, než čas vypnutí (například rozsviť ve 22:00 a zhasni v 02:00), tak by ta podmínka nefungovala.

Musela by se zapsat opačně.

Něco jako:

Kód: Vybrat vše

unsigned long zapni = 220000;
unsigned long vypni = 020000;

unsigned long n = (t.hr * 10000) + (t.min * 100) + (t.sec);

if (zapni < vypni)                                              // Zapnuto jen v ramci jednoho dne
  {
    if (n >= zapni and n < vypni)    digitalWrite(3, HIGH );    // Zapnuto
    else                             digitalWrite(3, LOW );     // Vypnuto
  }
else                                                            // Zapnuto pres pulnoc
  {
    if (n < zapni and n >= vypni)    digitalWrite(3, LOW );     // Vypnuto
    else                             digitalWrite(3, HIGH );    // Zapnuto
  }