• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Ustawianie daty na ds3231 RTC
#1
Witam!

Jestem początkującym więc proszę o wyrozumiałość. Mam podstawową wiedzę o Arduino lecz porykam się z problemem dotyczącym programu. Robię projekt oparty na Arduino UNO polegający na wyświetlaniu  czasu i daty oraz po kliknięciu przycisku, temperatury. Program działa lecz jest jeden problem. Przerabiałem to sam i czas jest ustawiony z komputera, więc gdy odłączam od prądu to zegar się resetuje i pokazuje godzinie o której wgrałem program. Chciałbym mieć możliwość ustawienia daty przy pomocy tact switchy. Starałem się sam przerobić program lecz nie udawało mi się to. Proszę o pomoc. Tu podaje program.
Kod:
#include <OneWire.h>
#include <DallasTemperature.h>
#include <RTClib.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

OneWire oneWire(A3); //Podłączenie do A5
DallasTemperature sensors(&oneWire); //Przekazania informacji do biblioteki

DateTime now;
char daysOfTheWeek[7][12] = {"Ndz", "Pon", "Wt", "Sr", "Czw", "Pt", "Sob"};

RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(0x3F, 16, 2);
void showDate(void);
void showTime(void);
void showDay(void);


int przycisk = 6;


void setup ()
{
 Serial.begin(9600);
 pinMode(przycisk, INPUT_PULLUP);
 lcd.begin();
 lcd.backlight();
 sensors.begin();

 if (! rtc.begin())
 {
   Serial.println("Couldn't find RTC Module");
   while (1);
 }

 if (rtc.lostPower())
 {
   Serial.println("RTC lost power, lets set the time!");
   rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
 }
 rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}

void loop ()
{

 if(digitalRead(przycisk)== LOW)
 {
   lcd.clear();
   sensors.requestTemperatures();
   lcd.setCursor(0, 0);
   lcd.print("Temp: ");
   lcd.print(sensors.getTempCByIndex(0));
   delay(4500);
   lcd.clear();
 
 }
 now = rtc.now();
 showDate();
 showDay();
 showTime();
}
 

void showDate()
{
 lcd.setCursor(0,0);
 lcd.print(now.day());
 lcd.print('-');
 lcd.print(now.month());
 lcd.print('-');
 lcd.print(now.year());
}
void showDay()
{
 lcd.setCursor(11,0);
 lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
}
void showTime()
{
 lcd.setCursor(0,1);
 lcd.print("Czas:");
 lcd.print(now.hour());
 lcd.print(':');
 lcd.print(now.minute());
 lcd.print(':');
 lcd.print(now.second());
 lcd.print("    ");
}
 
Odpowiedź
#2
Jak chcesz mieć zegar to zastosuj jakiś RTC z baterią, bateria w takich modułach wystarcza na lata, np. DS3221. W przykładach biblioteki tego modułu znajdziesz jak ustawić wszystko wysyłając 1 linijkę tekstu przez UART. Ustawienie przez przyciski wymaga zrobienia jakiegoś menu, prosty przykład znajdziesz tu: https://starter-kit.nettigo.pl/2017/04/m...aczu-16x2/.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#3
(19-01-2019, 15:04)kaczakat napisał(a): Jak chcesz mieć zegar to zastosuj jakiś RTC z baterią, bateria w takich modułach wystarcza na lata, np. DS3221. W przykładach biblioteki tego modułu znajdziesz jak ustawić wszystko wysyłając 1 linijkę tekstu przez UART. Ustawienie przez przyciski wymaga zrobienia jakiegoś menu, prosty przykład znajdziesz tu: https://starter-kit.nettigo.pl/2017/04/m...aczu-16x2/.

Cześć!
Moduł ma baterię lecz nie zapisuje daty. Dzięki za link spróbuje wgrać. Może się uda.
Pozdrawiam!
 
Odpowiedź
#4
A mi się wydaje ( to znaczy, jest to moja subiektywna opinia), że PCF8583 dla początkującego będzie łatwiejszy w obsłudze. Bardzo często się zdarza, że te chińskie moduły z DS'em są tak kiepskiej jakości, że nerwów Ci zabraknie aby to oprogramować jak należy.
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
#5
OK, jak masz RTC to po prostu wgrywa Ci ten czas z kompilacji, a potem po każdym resecie masz go wpisywanego na nowo do RTC z kodu procesora. Powinieneś RAZ wgrać szkic z ustawianiem czasu systemowego, natychmiast zakomentować linijki, które odpowiadają za ustawienie czasu i wgrać ponownie szkic (lub inny szkic, bez tego ustawiania, może za dużo przekopiowałeś z przykładowego szkicu z ustawianiem czasu, wybierz inny przykład, gdzie jest tylko odczytywany czas), teraz będzie czas tylko odczytywany. Wystarczy użyć innej biblioteki, wgrać przykład, ustawić czas z UART, potem czas będzie OK.
Ale oczywiście ustawianie czasu możesz sobie zrobić przez menu czy wysyłając UART.
PCF8583 jest fajny jak ktoś chce się nauczyć podstaw komunikacji I2C, zrobić swoje funkcje. Użyteczność jest taka sobie - nie ma kwarcu, baterii, wyboru źródła zasilania, to trzeba sobie zrobić samemu. Potem poczytać PDF, obczaić kodowanie BCD. Tak że edukacyjnie jak najbardziej, "arduinowo" wystarczy wgrać bibliotekę do precyzyjnego, gotowego modułu DS3231 z aku za 1$ i ma działać, lecimy dalej. Nie mam złych doświadczeń z DS, mam kilka modułów, różne konstrukcje (z pamięcią EEPROM i akumulatorem, takie ze zgrzaną baterią), różni sprzedawcy i wszystkie chodzą super dokładnie, mój laptop gubi więcej s w tydzień niż te DSy w rok.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#6
(19-01-2019, 23:49)kaczakat napisał(a): OK, jak masz RTC to po prostu wgrywa Ci ten czas z kompilacji, a potem po każdym resecie masz go wpisywanego na nowo do RTC z kodu procesora. Powinieneś RAZ wgrać szkic z ustawianiem czasu systemowego, natychmiast zakomentować linijki, które odpowiadają za ustawienie czasu i wgrać ponownie szkic (lub inny szkic, bez tego ustawiania, może za dużo przekopiowałeś z przykładowego szkicu z ustawianiem czasu, wybierz inny przykład, gdzie jest tylko odczytywany czas), teraz będzie czas tylko odczytywany. Wystarczy użyć innej biblioteki, wgrać przykład, ustawić czas z UART, potem czas będzie OK.
Ale oczywiście ustawianie czasu możesz sobie zrobić przez menu czy wysyłając UART.
PCF8583  jest fajny jak ktoś chce się nauczyć podstaw komunikacji I2C, zrobić swoje funkcje. Użyteczność jest taka sobie - nie ma kwarcu, baterii, wyboru źródła zasilania, to trzeba sobie zrobić samemu. Potem poczytać PDF, obczaić kodowanie BCD. Tak że edukacyjnie jak najbardziej, "arduinowo" wystarczy wgrać bibliotekę do precyzyjnego, gotowego modułu  DS3231 z  aku za 1$ i ma działać, lecimy dalej. Nie mam złych doświadczeń z DS, mam kilka modułów, różne konstrukcje (z pamięcią EEPROM i akumulatorem,  takie ze zgrzaną baterią), różni sprzedawcy i wszystkie chodzą super dokładnie, mój laptop gubi więcej s w tydzień niż te DSy w rok.
Masz racje. Moduł PCF8583 był by lepszy ale tego zegara ds3231 nie pominę więc mysle żeby go tu użyć. Znalazłem
inny przykład w którym mogę ustawić godzinę ręcznie więc to nie będzie już większy problem ale z kolei tam jest na serial monitorze pokazywana data i godzina. Jak próbowałem na LCD I2C przerobić to było "'lcd' does not name a type" więc nie wiem co jest nie tak wstawię kod w wolnej chwili możesz przejrzeć. W 30 linijce bym mógł wstawić zmienne które po kliknięciu przycisku by się zmieniały
Kod:
#include <LiquidCrystal_I2C.h>

#include <OneWire.h>
#include <DallasTemperature.h>
#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68

LiquidCrystal_I2C lcd(0x3F, 16, 2);  // Ustawienie adresu ukladu na 0x27

OneWire oneWire(A3); //Podłączenie do A3
DallasTemperature sensors(&oneWire); //Przekazania informacji do biblioteki

// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val){
 return( (val/10*16) + (val%10) );
}
 int przycisktemp = 6;
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val){
 return( (val/16*10) + (val%16) );
}
void setup(){
 Wire.begin();
 Serial.begin(9600);
  lcd.begin();  
 lcd.backlight();
  sensors.begin();
 
 // DS3231 seconds, minutes, hours, day, date, month, year
 setDS3231time(16,34,16,7,19,1,19);
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year){
 // sets time and date data to DS3231
 Wire.beginTransmission(DS3231_I2C_ADDRESS);
 Wire.write(0); // set next input to start at the seconds register
 Wire.write(decToBcd(second)); // set seconds
 Wire.write(decToBcd(minute)); // set minutes
 Wire.write(decToBcd(hour)); // set hours
 Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
 Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
 Wire.write(decToBcd(month)); // set month
 Wire.write(decToBcd(year)); // set year (0 to 99)
 Wire.endTransmission();
}
void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year){
 Wire.beginTransmission(DS3231_I2C_ADDRESS);
 Wire.write(0); // set DS3231 register pointer to 00h
 Wire.endTransmission();
 Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
 // request seven bytes of data from DS3231 starting from register 00h
 *second = bcdToDec(Wire.read() & 0x7f);
 *minute = bcdToDec(Wire.read());
 *hour = bcdToDec(Wire.read() & 0x3f);
 *dayOfWeek = bcdToDec(Wire.read());
 *dayOfMonth = bcdToDec(Wire.read());
 *month = bcdToDec(Wire.read());
 *year = bcdToDec(Wire.read());
}
void displayTime(){
 byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
 // retrieve data from DS3231
 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
 &year);
 // send it to the serial monitor
 lcd.print(hour, DEC);
 // convert the byte variable to a decimal number when displayed
lcd.print(":");
 if (minute<10){
   lcd.print("0");
 }
 lcd.print(minute, DEC);
 
 }
 
 lcd.print(" ");
 lcd.print(dayOfMonth, DEC);
 lcd.print("-");
 lce.print(month, DEC);
 lcd.print("-");
 lcd.print(year, DEC);
 lcd.setCursor(14, 0);
 switch(dayOfWeek){
 case 1:
   lcd.print("Nie");
   break;
 case 2:
   lcd.print("Pon");
   break;
 case 3:
   lcd.print("Wt");
   break;
 case 4:
   lcd.print("Sr");
   break;
 case 5:
   lcd.print("Czw");
   break;
 case 6:
   lcd.print("Pia");
   break;
 case 7:
   lcd.print("Sob");
   break;
 }
}
void loop(){
 displayTime(); // display the real-time clock data on the Serial Monitor,
 delay(1000); // every second
 if(digitalRead(przycisktemp) == LOW)
 {
   sensors.requestTemperatures();
   lcd.setCursor(0, 0);
   lcd.print("  Temperatura:  ");
   lcd.setCursor(0, 1);
   lcd.print(sensors.getTempCByIndex(0));
 }
}
 
Odpowiedź
#7
Zbyt duży bajzel żebym to ogarnął, na pewno jest literówka tu: lce.print(month, DEC);, ale klamerki {} wstawiał kotek biegnący po klawiaturze. Zrób sobie to od nowa przywiązując większą wagę gdzie funkcja/blok programu się zaczyna, gdzie kończy - jak coś kopiujesz, rób większe odstępy między funkcjami, tak byś widział, że np. część kodu Ci wisi poza funkcjami. Pamiętaj też, by przed użyciem funkcji wcześniej była jej deklaracja/definicja, najlepiej przed setup. Włącz sobie też pełne komunikaty podczas kompilacji w ustawieniach. To duży kawałek kodu, nie chcesz się udławić to połykaj mniejszymi porcjami i ostrożniej.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#8
(20-01-2019, 12:09)kaczakat napisał(a): Zbyt duży bajzel żebym to ogarnął, na pewno jest literówka tu: lce.print(month, DEC);, ale klamerki {} wstawiał kotek biegnący po klawiaturze. Zrób sobie to od nowa przywiązując większą wagę gdzie funkcja/blok programu się zaczyna, gdzie kończy - jak coś kopiujesz, rób większe odstępy między funkcjami, tak byś widział, że np. część kodu Ci wisi poza funkcjami. Pamiętaj też, by przed użyciem funkcji wcześniej była jej deklaracja/definicja, najlepiej przed setup. Włącz sobie też pełne komunikaty podczas kompilacji w ustawieniach. To duży kawałek kodu, nie chcesz się udławić to połykaj mniejszymi porcjami i ostrożniej.

Słuszna uwaga z tymi klamerkami muszę zrobić to w jakiś inny sposób.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości