Ви не увійшли.
Давно зробив собі погодну станцію на нано, bme та датчику со2 та світлодіодної матриці. Працює 5 років чудово. Вирішив додати плюшок з рядком, що біжить, але пам'яті в нано не вистачає. Переробив на esp32. Датчики та годинник ds3231 запитані від 3.3 вольта. І тут почалися проблеми - годинник через кілька годин починає показувати не коректний час.
Типо 45 годин 87 хвилин 2189 рік.
У цьому датчики працюють нормально.
Замінив модуль годинника, поставив нову батарейку, випаяв резистор у ланцюгу підзарядки батарейки (вичитав, що з літій краще не заряджати) – жодних змін. З годинником працюю з бібліотекою WIRE, щоби була можливість коригувати час.
Чи уст які міркування, може хто стикався?
Неактивний
То може сам чіп глючить?
Взагалі якщо wifi доступне, зробіть синхронізацію часу по NTP і буде вам щастя
Саме годинник ds3231.
зараз на них 2165 рік, 25 годин, 104 місяць))))
Десь неправильно інтерпретуєте прочитанні значення. У DS3231 календар та годинник у BCD форматі. Наприклад, на місяць відводиться всього 5 біт, так що 104 вона ніяк не може видавати.
Показуйте код.
Неактивний
хоча раз годинник мінявся, і все одно через кілька годин глючить.. або щось переповнюється, або щось несподіване робиться з глобальними змінними під час переривання.
Така поведінка тільки після переходу на esp32 (півроку як почав з нею грати)))
У ванній блок управління світлом і витяжкою та блок управління шторою на балконі працюють на дуньках вже по 8 років без нарікань.
Годинник підключений за тим же принципом, час коригується.
Ось з ESP32 щось не ладиться.
Неактивний
#include <Wire.h>
#define DS3231_I2C_ADDRESS 0x68
/////////// годинник //////////
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
byte decToBcd(byte val)
{
return ((val / 10 * 16) + (val % 10));
}
byte bcdToDec(byte val)
{
return ((val / 16 * 10) + (val % 16));
}
void setDateDs3231(byte second, // 0-59
byte minute, // 0-59
byte hour, // 1-23
byte dayOfWeek, // 1-7
byte dayOfMonth, // 1-28/29/30/31
byte month, // 1-12
byte year) // 0-99
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.write(decToBcd(dayOfWeek));
Wire.write(decToBcd(dayOfMonth));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
void getDateDs3231(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
*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 setup()
{
Serial.begin(115200);
Wire.begin();
}
void loop()
{
getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
Serial.print(year);
Serial.print("-");
Serial.print(hour);
Serial.print(':');
Serial.print(minute);
Serial.print(':');
Serial.println(second);
}
Неактивний
Припускаю що читати час раз в секунду було б нормально. І можливо операцію читання треба якось завершувати? Не може бути таке що на AVR воно завершувалося по якомусь таймауту , а esp більш швидка і встигає кудись не вписатись? що там в даташітах пишуть?
Спробую раз на секунду зчитувати час.
А тепер нові фокуси - при вимкненні живлення і повторному включенні годинник показує час відключення))))
На якомусь російському форумі вчора зустрів таку проблему.
Писали про запуск та зупинку осциллятора.
Неактивний
static byte prevSecond = 0;
if (millis() - prevSecond >= 1000)
{
getDateDs3231(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
prevSecond = millis();
}
Теж саме - при вимкненні живлення годинник зупиняється (((((
Остання редакція vvr (2025-02-23 15:13:43)
Неактивний
Деякі недоліки в приведеному коді є, але не такі щоб призводили до результату що спостерігається.
Які "сирі" значення повертає Wire.read() ?
Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
for (int i = 0; i < 7; i++)
Serial.println(Wire.read());
Неактивний
ну, всяке можливе. можна спробувати кварц поміняти. я б взагалі отримував час через wifi і не парився
vvr пише:Теж саме - при вимкненні живлення годинник зупиняється (((((
А ви часом ніде не записали одиницю в біт EOSC?
Здампте вміст всіх регістрів та подивіться вже, що там робиться.
Я навіть не знаю, як з ними працювати, ніколи не стикався.
Нічого тада не записував
Неактивний
*year = bcdToDec(Wire.read());
не повинно тут виходити 165.
до речі
byte year) // 0-99
з якого року починається відлік часу? 16 нагадує -1 по модулю 16.
На дисплей виводиться 2000+year)))
Тобто змінна year має значення 165. Воно може бути отримане від bcdToDec() при аргументі 255: 15*10 + 15.
У вас або Wire.read() повертає -1 (немає даних в буфері), або відвалилась SDA і читаються всі одиниці.
Спершу додайте перевірку результату Wire.read() на -1. Якщо що, Wire.read() повертає int, а не byte.
Якщо там проблема зі зʼєднанням по I²C, то аналізувати подальший код немає сенсу, поки цю проблему не буде виправлено. Нажаль, Wire - жахливо написана бібліотека, і з нею діагностувати помилки комунікації не так то просто.
Доречі, назви функцій bcdToDec() та decToBcd() невдалі, BCD саме по собі Dec. Назви мали би бути щось типу bcdToInt() та intToBcd().
Не дуже розумію, навіщо читати значення в BCD, конвертувати його в число, а потім число знову в BCD, щоб відображати на дисплеї. Але то таке.
Я навіть не знаю, як з ними працювати, ніколи не стикався.
Так само як читаєте регістри годинника та календаря, тільки всі 19 регістрів:
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();
size_t len = Wire.requestFrom(DS3231_I2C_ADDRESS, 19);
Serial.print("requestFrom() = ");
Serial.println(len);
for (int i = 0; i<19; i++) {
Serial.print(i, HEX);
Serial.print("h: ");
Serial.println(Wire.read());
}
Нічого тада не записував
Значить якось записалось. Це найперша очевидна причина зупинки осцилятора при живленні від батарейки.
Відʼєднайте зовнішнє живлення та батарейку. На пару секунд закоротіть контакти гнізда куди вона підключається, щоб розрядити ємності. Вставте батарейку назад.
Неактивний
vvr пише:На дисплей виводиться 2000+year)))
Відʼєднайте зовнішнє живлення та батарейку. На пару секунд закоротіть контакти гнізда куди вона підключається, щоб розрядити ємності. Вставте батарейку назад.
тепер час не зупиняється))))
Неактивний