DS3231 AT24C32 Real Time Clock Module Clock Module IIC RTC Module
ID: 37
Kategorie: Module
Menge: 0
Position:

Zegar czasu rzeczywistego RTC DS3231

DS3231 jest bardzo precyzyjnym ukÅ‚adem RTC sÅ‚użącym do odmierzania czasu, czÄ™sto spotykanym w niektórych moduÅ‚ach dla Arduino.

Jego ogromną zaletą jest brak konieczności podłączania zewnętrznego rezonatora kwarcowego oraz wbudowany termometr do kompensacji temperaturowej.

 

JeÅ›li przypomnimy sobie, jaki wpÅ‚yw ma temperatura na standardowy kwarc zegarkowy, stosowany w opisywanym niedawno DS1307 i jakie może mieć to skutki po upÅ‚ywie miesiÄ…ca czasu, to z pewnoÅ›ciÄ… docenicie dokÅ‚adność jakÄ… oferuje DS3231, która wynosi staÅ‚e ±2ppm w zakresie temperatur 0°C ÷ 40°C oraz ±3.5ppm w zakresie temperatur -40°C ÷ 85°C. Tak duża dokÅ‚adność gwarantuje maksymalnÄ… odchyÅ‚kÄ™ odmierzanego czasu do okoÅ‚o 1 minuty w skali roku.

DS3231 pozwala również na bezpoÅ›redni odczyt temperatury z wbudowanego termometru, konfiguracjÄ™ dwóch alarmów obsÅ‚ugujÄ…cych przerwania, a także generator przebiegu prostokÄ…tnego o zadanej czÄ™stotliwoÅ›ci 1Hz ÷ 32768Hz. Posiada również dodatkowe wyjÅ›cie o staÅ‚ym sygnale prostokÄ…tnym o czÄ™stotliwoÅ›ci 32kHz.

UkÅ‚ad DS3231 dostÄ™pny jest jedynie w obudowie SOIC:

Dokumentacja techniczna: http://www.jarzebski.pl/datasheets/DS3231.pdf

Schemat połączeń

Sposób podÅ‚Ä…czenia DS3231 jest bardzo podobny do ukÅ‚adu DS1307. PodÅ‚Ä…czamy wiÄ™c zasilanie 5V (nóżka 2) oraz masÄ™ GND (nóżka 13). Bardzo ważne jest, aby również podÅ‚Ä…czyć do masy wszystkie wyprowadzenia oznaczone jako NC (nóżki 5,6,7,8,9,10,11,12). DS3231 również komunikuje siÄ™ z Arduino za pomocÄ… magistrali I2C, a wiÄ™c Å‚Ä…czymy SCL (nóżka 16) do pinu A5, a SDA (nóżka 15) do pinu A4. Na koniec nie zapomnijmy podciÄ…gnąć linii sygnaÅ‚owych rezystorami o wartoÅ›ci 10kΩ do zasilania 5V. BateriÄ™ 3V podÅ‚Ä…czamy natomiast do VBAT (nóżka 14). WyjÅ›cia SQW/OUT oraz 32kHz,  również podciÄ…gamy rezystorami o wartoÅ›ci 10kΩ do zasilania 5V.  Jest to zabieg niezbÄ™dny, ponieważ i tutaj wyjÅ›cia dziaÅ‚ajÄ… w ukÅ‚adzie otwartego drenu. Dlatego,  jeÅ›li chcemy wykorzystać do nich diodÄ™ LED, należy podÅ‚Ä…czyć tutaj katodÄ™ - anodÄ™ zaÅ› do masy.  JeÅ›li nie planujemy korzystać z  SQW/OUT oraz wyjÅ›cia sygnaÅ‚u 32kHz, możemy pozostawić je "w powietrzu".

Ja zamiast zasilania bateryjnego wykorzystaÅ‚em napiÄ™cie 3.3V z Arduino oraz podÅ‚Ä…czyÅ‚em sobie diody LED do sygnalizacji stanów na wyjÅ›ciach z rezystorami 220Ω.

Prosty przykład

Do obsÅ‚ugi moduÅ‚ów z ukÅ‚adami DS3231 przygotowaÅ‚em bibliotekÄ™ dla Arduino, którÄ… można pobrać z repozytorium Githttps://github.com/jarzebski/Arduino-DS3231. Bazuje ona bibliotekach JeeLabs oraz Adafruit, jednak oferuje ona dodatkowe funkcje do sterowania wyjÅ›ciami SQW/OUT oraz 32kHz, ustawiania alarmów oraz formatowanie daty na wzór funkcji date() znanej z jÄ™zyka PHP.

  1. #include
  2. #include
  3.  
  4. DS3231 clock;
  5. RTCDateTime dt;
  6.  
  7. void setup()
  8. {
  9.   Serial.begin(9600);
  10.  
  11.   // Inicjalizacja DS3231
  12.   Serial.println("Initialize DS3231");;
  13.   clock.begin();
  14.  
  15.   // Ustawiany date i godzine kompilacji szkicu
  16.   clock.setDateTime(__DATE__, __TIME__);
  17. }
  18.  
  19. void loop()
  20. {
  21.   // Odczytujemy i wyswietlamy czas
  22.   dt = clock.getDateTime();
  23.  
  24.   Serial.print("Raw data: ");
  25.   Serial.print(dt.year);   Serial.print("-");
  26.   Serial.print(dt.month);  Serial.print("-");
  27.   Serial.print(dt.day);    Serial.print(" ");
  28.   Serial.print(dt.hour);   Serial.print(":");
  29.   Serial.print(dt.minute); Serial.print(":");
  30.   Serial.print(dt.second); Serial.println("");
  31.  
  32.   delay(1000);
  33. }

Formatowanie daty

JeÅ›li chcemy wyÅ›wietlić czas i datÄ™ w odpowiednim dla nas formacie, możemy skorzystać z funkcji dateFormat().

  1. #include
  2. #include
  3.  
  4. DS3231 clock;
  5. RTCDateTime dt;
  6.  
  7. void setup()
  8. {
  9.   Serial.begin(9600);
  10.  
  11.   // Inicjalizacja DS3231
  12.   Serial.println("Initialize DS3231");;
  13.   clock.begin();
  14.  
  15.   // Ustawiamy date i czas z kompilacji szkicu
  16.   clock.setDateTime(__DATE__, __TIME__);
  17.  
  18.   // Lub recznie (YYYY, MM, DD, HH, II, SS
  19.   // clock.setDateTime(2014, 4, 13, 19, 21, 00);
  20. }
  21.  
  22. void loop()
  23. {
  24.   // Odczytujemy czas i formatujemy za pomoca funkcji dateFormat
  25.   dt = clock.getDateTime();
  26.  
  27.   Serial.print("Long number format:          ");
  28.   Serial.println(clock.dateFormat("d-m-Y H:i:s", dt));
  29.  
  30.   Serial.print("Long format with month name: ");
  31.   Serial.println(clock.dateFormat("d F Y H:i:s",  dt));
  32.  
  33.   Serial.print("Short format witch 12h mode: ");
  34.   Serial.println(clock.dateFormat("jS M y, h:ia", dt));
  35.  
  36.   Serial.print("Today is:                    ");
  37.   Serial.print(clock.dateFormat("l, z", dt));
  38.   Serial.println(" days of the year.");
  39.  
  40.   Serial.print("Actual month has:            ");
  41.   Serial.print(clock.dateFormat("t", dt));
  42.   Serial.println(" days.");
  43.  
  44.   Serial.print("Unixtime:                    ");
  45.   Serial.println(clock.dateFormat("U", dt));
  46.  
  47.   Serial.println();
  48.  
  49.   delay(1000);
  50. }

Sterowanie wyjściem 32kHz oraz SQW/INT

W poniższym przykÅ‚adzie możemy zobaczyć jak wÅ‚Ä…czyć lub wyÅ‚Ä…czyć generator przebiegu prostokÄ…tnego na wyjÅ›ciu 32kHz oraz ustawić interesujÄ…cy nas przebieg prostokÄ…tny na wyjÅ›ciu SQW. SygnaÅ‚ SQW możemy wykorzystać do obsÅ‚ugi przerwania lub podÅ‚Ä…czyć diodÄ™ LED jako sygnalizator sekund, oszczÄ™dzajÄ…c tym samym cyfrowy pin Arduino. Kiedy bÄ™dziemy mieli zamiar skorzystać z alarmów to wyjÅ›cie SQW/INT bÄ™dzie nam sÅ‚użyÅ‚o wÅ‚aÅ›nie do obsÅ‚ugi przerwaÅ„.

  1. #include
  2. #include
  3.  
  4. DS3231 clock;
  5.  
  6. boolean state;
  7.  
  8. void setup()
  9. {
  10.   Serial.begin(9600);
  11.  
  12.   // Inicjalizyjemy DS3231
  13.   Serial.println("Initialize DS3231");;
  14.   clock.begin();
  15.  
  16.   // Wylaczamy wyjscie  32kHz
  17.   clock.enable32kHz(false);
  18.  
  19.   // Ustawiamy wyjscie SQW na sygnal 1Hz
  20.   clock.setOutput(DS3231_1HZ);
  21.  
  22.   // Wlaczamy wyjsscie SQW
  23.   clock.enableOutput(true);
  24.  
  25.   if (clock.isOutput())
  26.   {
  27.     Serial.println("Oscilator is enabled");
  28.   } else
  29.   {
  30.     Serial.println("Oscilator is disabled");
  31.   }
  32.  
  33.   switch (clock.getOutput())
  34.   {
  35.     case DS3231_1HZ:     Serial.println("SQW = 1Hz"); break;
  36.     case DS3231_4096HZ:  Serial.println("SQW = 4096Hz"); break;
  37.     case DS3231_8192HZ:  Serial.println("SQW = 8192Hz"); break;
  38.     case DS3231_32768HZ: Serial.println("SQW = 32768Hz"); break;
  39.     default: Serial.println("SQW = Unknown"); break; }
  40. }
  41.  
  42. void loop()
  43. {
  44.    // Wlaczamy i wylaczamy wyjscie 32kHz co 2 sekundy
  45.    clock.enable32kHz(state);
  46.    state = !state;
  47.    delay(2000);
  48. }

Odczyt temperatury z wbudowanego czujnika

DS3231 pozwala nam również na dostÄ™p do wbudowanego termometru o rozdzielczoÅ›ci 10-bitów. Co daje nam odczyt z precyzjÄ… 0.25°C i dokÅ‚adnoÅ›ciÄ… ±3°C. DomyÅ›lnie pomiar temperatury odbywa siÄ™ co 64 sekundy na potrzeby kompensacji , jednak możemy wymusić ponowny pomiar za pomocÄ… funkcji forceConversion().

  1. #include
  2. #include
  3.  
  4. DS3231 clock;
  5. RTCDateTime dt;
  6.  
  7. void setup()
  8. {
  9.   Serial.begin(9600);
  10.  
  11.   // Inicjalizyjemy DS3231
  12.   Serial.println("Initialize DS3231");;
  13.   clock.begin();
  14. }
  15.  
  16. void loop()
  17. {
  18.   // Wymuszamy konwersje temperatury, poniweaz domyslnie jest ona odswiezana co 64 sekundy
  19.   clock.forceConversion();
  20.  
  21.   Serial.print("Temperature: ");
  22.   Serial.println(clock.readTemperature());
  23.  
  24.   delay(1000);
  25. }

Konfiguracja alarmów

UkÅ‚ad pozwala na konfiguracjÄ™ dwóch alarmów, które różniÄ… siÄ™ od siebie gÅ‚ównie metodÄ… porównania czasu z ustawionym alarmem.

Alarm 1 pozwala na aktywowanie przerwania do nastÄ™pujÄ…cych dopasowaÅ„:

  • Każda sekunda
  • Dopasowanie tylko sekundy
  • Dopasowanie sekundy i minuty
  • Dopasowanie sekundy, minuty i godziny
  • Dopasowanie sekundy, minuty, godziny oraz dnia miesiÄ…ca
  • Dopasowanie sekundy, minuty, godziny oraz dnia tygodnia

Alarm 2 pozwala natomiast na aktywowanie przerwania do nastÄ™pujÄ…cych dopasowaÅ„:

  • Kazda peÅ‚na minuta
  • Dopasowanie tylko do wybranej minuty
  • Dopasowanie minuty i godziny
  • Dopasowanie do minuty, godziny oraz dnia miesiÄ…ca
  • Dopasowanie do minuty, godziny oraz dnia tygodnia

Łatwo wiÄ™c zauważyć, że Alarm 1 operuje na sekundach natomiast Alarm 2 na minutach. W ramach tego przykÅ‚adu w funkcji setup() wyÅ‚Ä…czamy i resetujemy przerwania za pomocÄ… funkcji armAlarmX(false) oraz clearAlarmX() ponieważ wartoÅ›ci te sÄ… podtrzymywane bateryjnie. W normalnej pracy oczywiÅ›cie powinniÅ›my pominąć ten fragment, ponieważ bÄ™dzie on powodowaÅ‚ kasowanie ustawieÅ„ przy powrocie gÅ‚ównego zasilania.

  1. #include
  2. #include
  3.  
  4. DS3231 clock;
  5. RTCDateTime dt;
  6.  
  7. void setup()
  8. {
  9.   Serial.begin(9600);
  10.  
  11.   // Inicjalizacja DS3231
  12.   Serial.println("Initialize DS3231");;
  13.   clock.begin();
  14.  
  15.   // Wylaczamy alarmy i resetujemy przerwania do przykladu,
  16.   // poniewaz ustawienia sa podtrzymywane bateryjnie
  17.   clock.armAlarm1(false);
  18.   clock.armAlarm2(false);
  19.   clock.clearAlarm1();
  20.   clock.clearAlarm2();
  21.  
  22.   // Ustawiamy date (Year, Month, Day, Hour, Minute, Second)
  23.   clock.setDateTime(2014, 4, 25, 0, 0, 0);
  24.  
  25.   // Ustawiamy Alarm1 na 20s kazdej minutu z dopasowaniem sekund
  26.   // setAlarm1(Date or Day, Hour, Minute, Second, Mode, Armed = true)
  27.   clock.setAlarm1(0, 0, 0, 20, DS3231_MATCH_S);
  28.  
  29.   // Usyawiamy Alarm2 - Kazda pierwsza minuta kazdej godziny z dopasowaniem do minut
  30.   // setAlarm2(Date or Day, Hour, Minute, Mode, Armed = true)
  31.   clock.setAlarm2(0, 0, 1,     DS3231_MATCH_M);
  32. }
  33.  
  34. void loop()
  35. {
  36.   // Odczytujemy date
  37.   dt = clock.getDateTime();
  38.  
  39.   Serial.println(clock.dateFormat("d-m-Y H:i:s - l", dt));
  40.  
  41.   // Sprawdzamy alaram 1
  42.   if (clock.isAlarm1())
  43.   {
  44.     Serial.println("ALARM 1 TRIGGERED!");
  45.   }
  46.  
  47.   // Sprawdzamy alaram 1
  48.   if (clock.isAlarm2())
  49.   {
  50.     Serial.println("ALARM 2 TRIGGERED!");
  51.   }
  52.  
  53.   delay(1000);
  54. }

W tym przykÅ‚adzie zademonstrowaÅ‚em jak obsÅ‚użyć alarmy programowo, jednak w repozytorium Git znajdziecie przykÅ‚ad z wykorzystaniem przerwania INT0 w Arduino UNO. PrzykÅ‚ad ten zostaÅ‚ również omówiony na filmie poniżej.

 

Materiały dodatkowe

Dokumentacja techniczna: http://www.jarzebski.pl/datasheets/DS3231.pdf
Biblioteka Arduino: https://github.com/jarzebski/Arduino-DS3231