Помогите разобраться с DS3231

Odissey1
Offline
Зарегистрирован: 03.03.2019

Помогите разобраться.  Почему не выводится в монитор порта, время и дата?(пустая строка, потом строка Sleep, потом строка Wake UP и опять пустая строка. Хотя таймер работает. С ардуинкой только знакомлюсь. Пробовал другой скетч с таймером, таже ерунда, а если залить просто время, то выводится .

#include <DS3231.h>
#include <avr/sleep.h> 
#include <avr/power.h>

#define WakePin          2

DS3231 clock;
RTCDateTime dt;

void rtcUp() { }

void(*resetFunc) (void) = 0;

void setSleepTimer(int mins) {
  uint8_t hours = mins / 60;
  uint8_t mins_left = mins - hours * 60;
  dt = clock.getDateTime();
  uint8_t hnow = dt.hour;
  uint8_t mnow = dt.minute;
  uint8_t sec = dt.second;
  mnow += mins_left;
  if (mnow >= 60) {
    mnow -= 60;
    hnow += 1;
  }
  hnow += hours;
  if (hnow > 23) {
    hnow -= 24;
  }
  clock.setAlarm1(0, hnow, mnow, sec, DS3231_MATCH_H_M_S);
}


void sleepNow() {
  ADCSRA = 0;
  power_all_disable();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  attachInterrupt(0, rtcUp, LOW);
  sleep_enable();  
  sleep_mode();  
  sleep_disable();
  power_all_enable();
  detachInterrupt(0);
}


void setup() {
  pinMode(WakePin, INPUT_PULLUP);
  Serial.begin(9600);
  clock.begin();
  clock.enableOutput(false);
  clock.armAlarm1(false);
  clock.armAlarm2(false);
  clock.clearAlarm1();
  clock.clearAlarm2();
}

void loop() {
  dt = clock.getDateTime();
  Serial.println(clock.dateFormat("d-m-Y H:i:s - l", dt));
  setSleepTimer(1);
  Serial.println("Sleep");
  delay(100);
  sleepNow();
  Serial.println("Wake UP");
  //resetFunc();
}

 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Вы сами-то можете что-то прочитать на этой картинке?

Odissey1
Offline
Зарегистрирован: 03.03.2019

Скетч я выложил ниже, что бы его можно было прочитать. А на картинке изображение с монитора порта. На ктоторой видно пропуски времени и даты.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Odissey1 пишет:

 с монитора порта. На ктоторой видно пропуски времени и даты.

И Вы можете прочитать, что там написано? ну, тогда читайте и решайте свою проблему сами.

Когда узнаете о существовании операций Copy и Paste - возвращайтесь.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

— Ну скажи что-нибудь, ты же у нас самый сообразительный.

— Я могу сказать только, что один из них Женя.



"Ирония судьбы, или С легким паром!"

ямогу сказать только одно

clock.dateFormat("d-m-Y H:i:s - l", dt)

 

возвращает пустую строку :)

 

Odissey1
Offline
Зарегистрирован: 03.03.2019

xDriver пишет:

 

ямогу сказать только одно

clock.dateFormat("d-m-Y H:i:s - l", dt)

 

возвращает пустую строку :)

 

А что не так в этой строке? Задается формат вывода даты и время.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

ссылку на библиотеку DS3231 дайте.

Odissey1
Offline
Зарегистрирован: 03.03.2019

xDriver пишет:

ссылку на библиотеку DS3231 дайте.

https://github.com/jarzebski/Arduino-DS3231

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

Не совсем понятно, для чего автор библиотеки возвращает результат выполнения dateFormat указывающий на на буфер, который выделялся в стеке.
Опасный код, если передавать результат в другую функцию, у которой на старте будут инициализированы переменные в стеке, то обратившись к полученному результату из dateFormat можно попасть неизвестно куда.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Алексей. пишет:

автор библиотеки возвращает результат выполнения dateFormat указывающий на на буфер, который выделялся в стеке.

Хрена се!

Andrey12
Andrey12 аватар
Offline
Зарегистрирован: 26.12.2014

ЕвгенийП пишет:

Хрена се!

А не могли бы вы пояснить будет ли работать такой код? Работать то он работает, hello arduino выводит, но по сути выходя из функции  foo() переменная buffer вроде как не должна существовать? Но скорее я что то с указателями не понял.

char* foo()
{
    char buffer[255];
    buffer[0] = 0;

    sprintf(buffer, "%s", "hello arduino"); 

    return buffer;
}


void setup(void) {
    Serial.begin(9600);
    Serial.println(foo());
}

void loop(void) {
    delay(1000);
}

 

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

Andrey12 пишет:

ЕвгенийП пишет:

Хрена се!

А не могли бы вы пояснить будет ли работать такой код? Работать то он работает, hello arduino выводит, но по сути выходя из функции  foo() переменная buffer вроде как не должна существовать? Но скорее я что то с указателями не понял.

char* foo()
{
    char buffer[255];
    buffer[0] = 0;

    sprintf(buffer, "%s", "hello arduino"); 

    return buffer;
}


void setup(void) {
    Serial.begin(9600);
    Serial.println(foo());
}

void loop(void) {
    delay(1000);
}

 

Работает по тому, что компилятор для единственного вызова foo решил сделать её inline, фактически буфер из foo оказался в стеке setup.

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

ЕвгенийП пишет:

Хрена се!

Нравятся мне эти библиотеки, много нового узнаншь, порой хочется сказать авторам "Хорошая трава у вас." но не решаюсь однако, может я чего то и не понял или упустил.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Andrey12 пишет:

А не могли бы вы пояснить будет ли работать такой код? 

Я дополню коллегу из поста #11.

В принципе, даже, если бы она не была inline, в таком виде это всё равно бы работало.

Переменная «не должна существовать» в том смысле, что память, выделенная под неё, при выходе из функции объявляется свободной и её может занять кто угодно. А возвращённый указатель по-прежнему на неё указывает.

Но в Вашем примере, никто не успел эту память загадить и потому в ней остаётся тоже, что туда прописала функция, и всё выглядит нормально. Вот если бы Вы между вызовом функции и печатью, вставили что-нибудь, что тоже хватает свободную память из стека и туда пишет, вот тогда бы она у Вас не сработала, т.к. память была бы уже загажена.

Т.е. такое использование памяти ведёт не к немедленному краху, а к появлению труднообъяснимых фантомных глюков, которые появляются и исчезают трудно объяснимым образом, при внесении каких-то совершенно безобидных изменений в программу.

b707
Offline
Зарегистрирован: 26.05.2017

ЕвгенийП  - а можно еще чуть уточнить ?

То, что подобное использование буфера есть говнокод - для меня совершенно очевидно. Но что изменится, если мы выделим под возвращаемое значение обьект типа String? - для меня и это выглядит неправильным, однако помню дискуссиию, где вроде бы именно Вы обьясняли, что с обьектами так делать можно. Не могли бы Вы пояснить?

Если плохо сформулировал - не отвечайте, так и скажите. Тогда либо постараюсь спросить правильнее, либо оставим вопрос на потом

Andrey12
Andrey12 аватар
Offline
Зарегистрирован: 26.12.2014

ЕвгенийП пишет:

Я дополню коллегу из поста #11.

Т.е. такое использование памяти ведёт не к немедленному краху, а к появлению труднообъяснимых фантомных глюков, которые появляются и исчезают трудно объяснимым образом, при внесении каких-то совершенно безобидных изменений в программу.

Благодарю за разъянения. Все таки лыжи не едут, а я понял правильно :-) Данные будут существовать пока не затруться.
Я обычно в таких случаях объявляю буфер, передаю в функцию ссылку на буфер, в функции буфер заполняю и потом использую по надобности.

sadman41
Offline
Зарегистрирован: 19.10.2016

Со стрингом всё будет точно так же - если в него копировать сразу, то всё будет ОК. А ежели посреди копирования какая-нить функция из прерывания будет нуждаться выделении памяти и похерит \0 в возвращаемом буфере, то получится зависание. Или ребут. Или как повезёт. 

Системные функции сделаны иначе:

char* func (char* buff, ... , ...) {
  ...
  return buff;
}

Таким образом, если память и будет подпорчена, то явно пользователем(погроммистом).

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:

Со стрингом всё будет точно так же - если в него копировать сразу, то всё будет ОК.

Системные функции сделаны иначе:

Не, Гриш, как правильно обращаться с буфером - я знаю. Я спрашивал вот про такой вариант:

String foo()
{
    String a;
    a =  "hello arduino"; 

    return a;
}


void setup(void) {
    Serial.begin(9600);
    Serial.println(foo());
}

void loop(void) {
    delay(1000);
}

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

я правильно понимаю, что у ТС конструкция

Serial.println(clock.dateFormat("d-m-Y H:i:s - l", dt))

с данной библиотекой, сработае правильно в 99% случаев ?

b707
Offline
Зарегистрирован: 26.05.2017

xDriver пишет:

я правильно понимаю, что у ТС конструкция

Serial.println(clock.dateFormat("d-m-Y H:i:s - l", dt))

с данной библиотекой, сработае правильно в 99% случаев ?

если не учитывать случаи нехватки памяти (нафига там выделяется 255 символов?????) - то скорее да, чем нет

sadman41
Offline
Зарегистрирован: 19.10.2016

b707 пишет:

Не, Гриш, как правильно обращаться с буфером - я знаю. Я спрашивал вот про такой вариант:

Тут я не копенгаген, стрингами не пользуюсь, в классы не лезу без необходимости.

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:

Тут я не копенгаген, стрингами не пользуюсь, в классы не лезу без необходимости.

 у меня точно так же :)

Начал тебе писать... и вроде бы сам нашел ответ на свой вопрос.

С классами так работать можно, если внутри класса нет ссылочных переменных. При возврате класса из функции в этом месте основной программы создается новый экземпляр, в который копируется возвращаемое значение.После этого экземпляр, созданный внутри функции - уничтожается и с памятью все нормально.

Пусть опытные поправят, если где неверно написал

Odissey1
Offline
Зарегистрирован: 03.03.2019

Кто то может мне дать ответ, что я делаю не так. Почему команда Serial.println(clock.dateFormat("d-m-Y H:i:s - l", dt)), в монитор порта выводит пустую строку. Но при этом таймер работает исправно. 

b707
Offline
Зарегистрирован: 26.05.2017

Odissey1 пишет:

Кто то может мне дать ответ, что я делаю не так. Почему команда Serial.println(clock.dateFormat("d-m-Y H:i:s - l", dt)), в монитор порта выводит пустую строку. Но при этом таймер работает исправно. 

когда компилируете полный код - там пишется сколько он занимает во флеше и ОЗУ. Какие там цифры?

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

b707 пишет:
что изменится, если мы выделим под возвращаемое значение обьект типа String? - для меня и это выглядит неправильным, однако помню дискуссиию, где вроде бы именно Вы обьясняли, что с обьектами так делать можно. Не могли бы Вы пояснить?

Если возвращать сам объект, а не ссылку, то можно (но тоже - говнокод). Но здесь мы касаемся очень тонких вещей!

Что действительно произойдёт при возврате из функции, на самом деле зависит от миллиона причин. От наличия или отстутствия конструкторов копирования и конструкторов перемещения, от того, по какому стандарту сделан компилятор, т.к. это т.н. "семантика перемещения" ("move semantics") - она сейчас развивается и стандарты 11-го, 14-го и 17-го годов сильно различаются в этой части.

В каком-то случае при возврате из фунции, будет создан новый объект и именно он будет возвращён. В другом случае (если есть конструктор копирования или перемещения) локальный объект может быть скопироваи/перемещён в возвращаемый. Там много очень тонких вещей. Вы на самом деле коснулись материи, которая сейчас активно развивается и меняется.

На самой заре ООП в этом случае требовалось создавать новый объект. Но это большие расходы. Появилась идея "конструкторов копирования", но это тоже решает не все проблемы. Особенно трудно, когда конструкторы и деструкторы имеют побочные эффекты. Тогда появилась "семантика перемещения" и понятие prvalue (наряду с rvalue и lvalue), но и тут много граблей, т.к., например, вызывающий код и вызываемая функция могут находиться в разных ядрах, или, того хлеще, в разных узлах кластера - там проблемы растут комом.

Здесь (в классе String) всё реализовано через копирование, но заметьте, от каких неуловимых нюансов зависит, что же реально будет происходить. Сравните два кода ниже:

String convert(const int n) {
  String s("n = ");
  s += n;
  return s;
}

void setup(void) {
  Serial.begin (57600);
  Serial.println("Fun begins!");
  String res;
  res = convert(321);
  Serial.println(res);
}

void loop(void) {}
String convert(const int n) {
  String s("n = ");
  s += n;
  return s;
}

void setup(void) {
  Serial.begin (57600);
  Serial.println("Fun begins!");
  String res = convert(321);
  Serial.println(res);
}

void loop(void) {}
Fun begins!
Const #1: 2294
GetMem: object @2294; size: 1 - Ok; addr: 592
Const #1: 2288
GetMem: object @2288; size: 5 - Ok; addr: 596
GetMem: object @2288; size: 8 - Ok; addr: 596
Freeing buffer of: 2294
Destructor of object @: 2288
n = 321
Destructor of object @: 2294
Freeing buffer of: 2294
Fun begins!
Const #1: 2294
GetMem: object @2294; size: 5 - Ok; addr: 592
GetMem: object @2294; size: 8 - Ok; addr: 592
n = 321
Destructor of object @: 2294
Freeing buffer of: 2294

Вся разница в том, что строки №№ 10 и 11 левого скетча объедины в одну - строка №10 правого. Никакой другой разницы нет.

А теперь давайте посмотрим на трассировку вызовов конструкторов, деструкторов и запросов/освобождения памяти (листинги под кодами).

Слева мы видим, что res в функции setup и s в функции convert - это два разных объекта с адресами 2294 И 2288 соответственно. В момент возврата из функции, буфер объекта res (addr 592) был освобождён, а буфер объекта s (addr 596) не освобождался (!!!) а просто был переназначен объекту res. Т.е. получается, что (нумерация строк по левому листингу)

1. В строке 3 запрошена память для объекта res
2. В строке 5 запрошена память для объекта s
3. В строке 7 освобождена память объекта res
4. Буфер объекта s переназначен объекту res (это копирование)
5. В строке 11 освобождена память объекта res

Т.е. получается, что у нас два объекта, мы под оба запрашивали буферы, но освобождали только у одного объекта, зато дважды. А буфер второго объекта по ходу дела перекочевал к первому.

А вот в правом примере, изменения в коде казалось бы плёвые, но что имеем внутри!!! Здесь у нас s и res - это просто один и тот же объект с адресом 2294. А казалось бы, ничего толком и не менялось в коде-то.

В общем, в конечном итоге оно сработает нормально. Но что будет внутри - это очень сложные вещи, которые, к тому же, прямо на наших глазах меняются. Современное состояние вопроса (стандарт 17-го года) можно почитать в статьях, посвящённым семантике перемещения и prvalue.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

b707 пишет:
При возврате класса из функции в этом месте основной программы создается новый экземпляр, в который копируется возвращаемое значение.
Так было в тёплые - ламповые времена. А сейчас ... см правый пример из моего поста выше :)

Andrey12
Andrey12 аватар
Offline
Зарегистрирован: 26.12.2014

Odissey1 пишет:

Кто то может мне дать ответ, что я делаю не так. Почему команда Serial.println(clock.dateFormat("d-m-Y H:i:s - l", dt)), в монитор порта выводит пустую строку. Но при этом таймер работает исправно. 

А попробуйте пример из вашей библиотеки который называется DS3231_dateformat.ino залить в ардуино и посмотреть что выводит.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

И, да, b707, если Вы подумаете. что в правом примере из #24 получился один объект из-за inline, то нет. Можно вынести функцию в другой файл, вызвать как extern - результат тот же. Ничего не изменится.

b707
Offline
Зарегистрирован: 26.05.2017

Евгений. спасибо огромное!

Odissey1
Offline
Зарегистрирован: 03.03.2019

b707 пишет:

Odissey1 пишет:

Кто то может мне дать ответ, что я делаю не так. Почему команда Serial.println(clock.dateFormat("d-m-Y H:i:s - l", dt)), в монитор порта выводит пустую строку. Но при этом таймер работает исправно. 

когда компилируете полный код - там пишется сколько он занимает во флеше и ОЗУ. Какие там цифры?

Скетч использует 7794 байт (25%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 676 байт (33%) динамической памяти, оставляя 1372 байт для локальных переменных. Максимум: 2048 байт.
 
Odissey1
Offline
Зарегистрирован: 03.03.2019

Andrey12 пишет:

Odissey1 пишет:

Кто то может мне дать ответ, что я делаю не так. Почему команда Serial.println(clock.dateFormat("d-m-Y H:i:s - l", dt)), в монитор порта выводит пустую строку. Но при этом таймер работает исправно. 

А попробуйте пример из вашей библиотеки который называется DS3231_dateformat.ino залить в ардуино и посмотреть что выводит.

b707
Offline
Зарегистрирован: 26.05.2017

Одиссей - вы плохо соображаете или плохо запоминаете? Вам уже в начале обсуждения сказали, что на Ваших скринах ничего не видно! -Не надо эту фигню постить - выкладывайте вывод программы как текст, уважайте других участников!

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

Если кратко, DS3231 у вас не работает.

b707
Offline
Зарегистрирован: 26.05.2017

xDriver пишет:

Если кратко, DS3231 у вас не работает.

а это не библиотека кривая? - по-моему. вместо форматированной даты она справку по формату выдает

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

/*
  DS3231: Real-Time Clock. Date Format
  Read more: www.jarzebski.pl/arduino/komponenty/zegar-czasu-rzeczywistego-rtc-ds3231...
  GIT: https://github.com/jarzebski/Arduino-DS3231
  Web: http://www.jarzebski.pl
  (c) 2014 by Korneliusz Jarzebski
*/

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

DS3231 clock;
RTCDateTime dt;

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

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

  // Set sketch compiling time
  clock.setDateTime(__DATE__, __TIME__);

  // Set from UNIX timestamp
  // clock.setDateTime(1397408400);

  // Manual (YYYY, MM, DD, HH, II, SS
  // clock.setDateTime(2014, 4, 13, 19, 21, 00);
}

void loop()
{
  dt = clock.getDateTime();

  Serial.print("Long number format:          ");
  Serial.println(clock.dateFormat("d-m-Y H:i:s", dt));

  Serial.print("Long format with month name: ");
  Serial.println(clock.dateFormat("d F Y H:i:s",  dt));

  Serial.print("Short format witch 12h mode: ");
  Serial.println(clock.dateFormat("jS M y, h:ia", dt));

  Serial.print("Today is:                    ");
  Serial.print(clock.dateFormat("l, z", dt));
  Serial.println(" days of the year.");

  Serial.print("Actual month has:            ");
  Serial.print(clock.dateFormat("t", dt));
  Serial.println(" days.");

  Serial.print("Unixtime:                    ");
  Serial.println(clock.dateFormat("U", dt));

  Serial.println();

  delay(1000);
}

нее, часы "заводятся" и выводится та-же dt (RTCDateTime). 

Odissey1
Offline
Зарегистрирован: 03.03.2019

xDriver пишет:

Если кратко, DS3231 у вас не работает.

Почему тогда это скетч работает?

// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"

RTC_DS3231 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup () {


  Serial.begin(9600);

  delay(3000); // wait for console opening

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

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
}

void loop () {
    DateTime now = rtc.now();
    
    Serial.print(now.year(), DEC);
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(" (");
    Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
    Serial.print(") ");
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
    
    Serial.print(" since midnight 1/1/1970 = ");
    Serial.print(now.unixtime());
    Serial.print("s = ");
    Serial.print(now.unixtime() / 86400L);
    Serial.println("d");
    
    // calculate a date which is 7 days and 30 seconds into the future
    DateTime future (now + TimeSpan(7,12,30,6));
    
    Serial.print(" now + 7d + 30s: ");
    Serial.print(future.year(), DEC);
    Serial.print('/');
    Serial.print(future.month(), DEC);
    Serial.print('/');
    Serial.print(future.day(), DEC);
    Serial.print(' ');
    Serial.print(future.hour(), DEC);
    Serial.print(':');
    Serial.print(future.minute(), DEC);
    Serial.print(':');
    Serial.print(future.second(), DEC);
    Serial.println();
    
    Serial.println();
    delay(3000);
}

sadman41
Offline
Зарегистрирован: 19.10.2016

Почему вы всех мучаете, требуя рассказать, почему велосипед с квадратными колёсами не едет, а с круглыми едет? Попробуйте сами разобраться - это же ваше хобби. Накидайте отладочных выводов в библиотеку и локализуйте проблему.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

потому что тут

#include "RTClib.h"

а там

#include <DS3231.h>

ну если разжевать - используются разные библиотеки  DS3231.

 

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

Небыло под рукой модуля ds3231 поэтому в примере выкинул его инициализацию, только задал статический RTCDateTime
 

Небыло под рукой модуля ds3231 поэтому в примере выкинул его инициализацию, только задал статический RTCDateTime
/*
  DS3231: Real-Time Clock. Date Format
  Read more: www.jarzebski.pl/arduino/komponenty/zegar-czasu-rzeczywistego-rtc-ds3231...
  GIT: https://github.com/jarzebski/Arduino-DS3231
  Web: http://www.jarzebski.pl
  (c) 2014 by Korneliusz Jarzebski
*/

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

DS3231 clock;
RTCDateTime dt = {
  .year = 2019,
  .month = 3,
  .day = 4,
  .hour = 22,
  .minute = 35,
  .second = 15,
  .dayOfWeek = 1,
  .unixtime = 1551727746
};

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

void loop()
{
  Serial.print("Long number format:          ");
  Serial.println(clock.dateFormat("d-m-Y H:i:s", dt));

  Serial.print("Long format with month name: ");
  Serial.println(clock.dateFormat("d F Y H:i:s",  dt));

  Serial.print("Short format witch 12h mode: ");
  Serial.println(clock.dateFormat("jS M y, h:ia", dt));

  Serial.print("Today is:                    ");
  Serial.print(clock.dateFormat("l, z", dt));
  Serial.println(" days of the year.");

  Serial.print("Actual month has:            ");
  Serial.print(clock.dateFormat("t", dt));
  Serial.println(" days.");

  Serial.print("Unixtime:                    ");
  Serial.println(clock.dateFormat("U", dt));

  Serial.println();
  Serial.println();

  delay(10000);
}

По хорошему не хочет работать, вывод:

Long number format:          
Long format with month name: 
Short format witch 12h mode: 
Today is:                     days of the year.
Actual month has:             days.
Unixtime:   

А под давлением? в DS3231::dateFormat сделал буфер статическим

char* DS3231::dateFormat(const char* dateFormat, RTCDateTime dt)
{
static char buffer[255];

Так то лучше, вывод:

Long number format:          04-03-2019 22:35:15
Long format with month name: 04 March 2019 22:35:15
Short format witch 12h mode: 4th Mar 19, 10:35pm
Today is:                    Monday, 62 days of the year.
Actual month has:            31 days.
Unixtime:                    1551727746

Не очень хороший тон, возвращать указатели которые смотрят на стек.

Slsvok47
Offline
Зарегистрирован: 03.06.2018

Спасибо помогло, но при компиляции есть предупреждения типа

warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

             return "Unknown";

char *DS3231::strDayOfWeek(uint8_t dayOfWeek)
{
    switch (dayOfWeek) {
        case 1:
            return "Monday";
            break;
        case 2:
            return "Tuesday";
            break;
        case 3:
            return "Wednesday";
            break;
        case 4:
            return "Thursday";
            break;
        case 5:
            return "Friday";
            break;
        case 6:
            return "Saturday";
            break;
        case 7:
            return "Sunday";
            break;
        default:
            return "Unknown";
    }
}

Как это можно исправить?

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Например, явно преобразовать константы к char *

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

Дык там тот же треш с возвратом указателя смотрящего на стек.
Мало того, что автор библиотеки не объявил возвращаемый указатель как константный, так и у нестатического метода, который не меняет значения класса, не добавил декларацию const для метода.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Алексей. пишет:

Дык там тот же треш с возвратом указателя смотрящего на стек.

Явно описанные константы вроде ("Monday") - не стек, с ними всё в порядке.

Алексей. пишет:

автор библиотеки не объявил возвращаемый указатель как константный

Нет смысла возвращать константый указатель (всё равно компилятор проигнорирует). Здесь нужно возвращать указатель на константу (т.е. сам по себе указатель не костантный, но он указывает на костантное содержимое). Вот сравните три записи. И, кстати, попробуйте скомпилировать и посмотрите на какие строки будут предупреждения (и какие), а на какие - нет.

char const * getstr1(void) { return "kaka"; }
const char * getstr2(void) { return "kaka"; }
char * const getstr3(void) { return "kaka"; }

Алексей. пишет:

у нестатического метода, который не меняет значения класса, не добавил декларацию const для метода.

Это да.

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

ЕвгенийП пишет:
Явно описанные константы вроде ("Monday") - не стек, с ними всё в порядке.
Да, константа, вы правы, и не стеке.
ЕвгенийП пишет:
Нет смысла возвращать константый указатель (всё равно компилятор проигнорирует). Здесь нужно возвращать указатель на константу (т.е. сам по себе указатель не костантный, но он указывает на костантное содержимое).
И тут я лажанулся, указатель на константу за константный указатель выдал, блин. Старый буквоед, поспешил с выхлопом ;))