From ac1266736519ab3c3e5cb9c23a6e95bcc492f08d Mon Sep 17 00:00:00 2001 From: Ton Huisman Date: Mon, 17 Aug 2026 17:08:01 +0200 Subject: [PATCH] [Storage] Add support for PCF8583 RTC with 240 bytes SRAM --- lib/Adafruit_RTClib/src/RTClib.cpp | 181 ++++++++++++++++++ lib/Adafruit_RTClib/src/RTClib.h | 34 ++++ src/Custom-sample.h | 3 +- src/ESPEasy/eeprom/Helpers/RTCSRAMStorage.cpp | 41 ++++ src/src/CustomBuild/define_plugin_sets.h | 15 ++ src/src/DataTypes/TimeSource.cpp | 7 +- src/src/DataTypes/TimeSource.h | 5 + src/src/Helpers/ESPEasy_time.cpp | 43 +++++ src/src/WebServer/AdvancedConfigPage.cpp | 20 +- src/src/WebServer/EepromVarPage.cpp | 2 +- src/src/WebServer/I2C_Scanner.cpp | 4 +- 11 files changed, 348 insertions(+), 7 deletions(-) diff --git a/lib/Adafruit_RTClib/src/RTClib.cpp b/lib/Adafruit_RTClib/src/RTClib.cpp index e465752c2..1c51a5971 100644 --- a/lib/Adafruit_RTClib/src/RTClib.cpp +++ b/lib/Adafruit_RTClib/src/RTClib.cpp @@ -1546,6 +1546,187 @@ void RTC_PCF8563::writeSqwPinMode(Pcf8563SqwPinMode mode) { } // END RTC_PCF8563 implementation +// START RTC_PCF8583 implementation + +// Code inspired by https://github.com/xoseperez/pcf8583 + +/**************************************************************************/ +/*! + @brief Start I2C for the PCF8583 and test succesful connection + @details Use altAddress() before calling begin() to use the alternate address (0x51) + @return True if Wire can find PCF8583 or false otherwise. +*/ +/**************************************************************************/ + +boolean RTC_PCF8583::begin(TwoWire *wireInstance) { + RTCWireBus = wireInstance; + RTCWireBus->beginTransmission(_addr); + if (RTCWireBus->endTransmission() == 0) { + return true; + } + return false; +} + +void RTC_PCF8583::altAddress() { + _addr = PCF8583_ADDRESS_1; +} + +/**************************************************************************/ +/*! + @brief Check the status of the VL bit in the VL_SECONDS register. + @details The PCF8583 does not support voltage-low detector. + @return False +*/ +/**************************************************************************/ + +boolean RTC_PCF8583::lostPower(void) { + return false; // Not supported +} + +/**************************************************************************/ +/*! + @brief Set the date and time + @param dt DateTime to set +*/ +/**************************************************************************/ +void RTC_PCF8583::adjust(const DateTime &dt) { + + uint16_t year = dt.year() - PCF8583_BASE_YEAR; + const uint8_t offset = year & 0xFC; + year -= offset; + RTCWireBus->beginTransmission(_addr); + RTCWireBus->_I2C_WRITE(PCF8583_VL_SECONDS); // start at location 2, VL_SECONDS + RTCWireBus->_I2C_WRITE(bin2bcd(dt.second())); + RTCWireBus->_I2C_WRITE(bin2bcd(dt.minute())); + RTCWireBus->_I2C_WRITE(bin2bcd(dt.hour())); + RTCWireBus->_I2C_WRITE(bin2bcd(dt.day()) | (year < 6)); + RTCWireBus->_I2C_WRITE(bin2bcd(0)); // skip weekdays + RTCWireBus->_I2C_WRITE(bin2bcd(dt.month())); + RTCWireBus->_I2C_WRITE(bin2bcd(dt.year() - 2000)); + RTCWireBus->endTransmission(); + + RTCWireBus->beginTransmission(_addr); + RTCWireBus->_I2C_WRITE(PCF8583_OFFSET_YEAR); // Update offset and year + RTCWireBus->_I2C_WRITE(offset); + RTCWireBus->_I2C_WRITE(year); + RTCWireBus->endTransmission(); +} + +/**************************************************************************/ +/*! + @brief Get the current date/time + @return DateTime object containing the current date/time +*/ +/**************************************************************************/ + +DateTime RTC_PCF8583::now() { + RTCWireBus->beginTransmission(_addr); + RTCWireBus->_I2C_WRITE((byte)PCF8583_VL_SECONDS); + RTCWireBus->endTransmission(); + + RTCWireBus->requestFrom(_addr, (size_t)6); + const uint8_t ss = bcd2bin(RTCWireBus->_I2C_READ() & 0x7F); + const uint8_t mm = bcd2bin(RTCWireBus->_I2C_READ() & 0x7F); + const uint8_t hh = bcd2bin(RTCWireBus->_I2C_READ() & 0x3F); + const uint8_t d_r = RTCWireBus->_I2C_READ(); + const uint8_t d = bcd2bin(d_r & 0x3F); + const uint16_t year = d_r >> 6; + RTCWireBus->_I2C_READ(); // skip 'weekdays' + const uint8_t m = bcd2bin(RTCWireBus->_I2C_READ() & 0x1F); + + const uint8_t last = read_i2c_register(_addr, PCF8583_LAST_YEAR, RTCWireBus); + uint8_t offset = read_i2c_register(_addr, PCF8583_OFFSET_YEAR, RTCWireBus); + + // we have changed the year: happy new year!!! + if (last != year) { + + // we have overflowed the year value: update the offset + if (last > year) { + offset += 4; + write_i2c_register(_addr, PCF8583_OFFSET_YEAR, offset, RTCWireBus); + } + + write_i2c_register(_addr, PCF8583_LAST_YEAR, year, RTCWireBus); + } + const uint16_t y = PCF8583_BASE_YEAR + offset + year; + + return DateTime(y, m, d, hh, mm, ss); +} + +/**************************************************************************/ +/*! + @brief Resets the STOP bit in register Control_1 +*/ +/**************************************************************************/ +void RTC_PCF8583::start(void) { + const uint8_t ctlreg = read_i2c_register(_addr, PCF8583_CONTROL_1, RTCWireBus); + write_i2c_register(_addr, PCF8583_CONTROL_1, ctlreg & 0x7F, + RTCWireBus); +} + +/**************************************************************************/ +/*! + @brief Sets the STOP bit in register Control_1 +*/ +/**************************************************************************/ +void RTC_PCF8583::stop(void) { + const uint8_t ctlreg = read_i2c_register(_addr, PCF8583_CONTROL_1, RTCWireBus); + write_i2c_register(PCF8523_ADDRESS, PCF8583_CONTROL_1, ctlreg | 0x80, + RTCWireBus); +} + +/**************************************************************************/ +/*! + @brief Is the PCF8583 running? Check the STOP bit in register Control_1 + @return 1 if the RTC is running, 0 if not +*/ +/**************************************************************************/ +uint8_t RTC_PCF8583::isrunning() { + const uint8_t ctlreg = read_i2c_register(_addr, PCF8583_CONTROL_1, RTCWireBus); + return !(ctlreg >> 7); // bit 7 = 0 => running +} + +/**************************************************************************/ +/*! + @brief Read data from the PCF8583's NVRAM + @param buf Pointer to a buffer to store the data - make sure it's large + enough to hold size bytes + @param size Number of bytes to read + @param address Starting NVRAM address, from 0 to 235 +*/ +/**************************************************************************/ +void RTC_PCF8583::readnvram(uint8_t *buf, uint8_t size, uint8_t address) { + const int addrByte = PCF8583_NVRAM + address; + RTCWireBus->beginTransmission(_addr); + RTCWireBus->_I2C_WRITE(addrByte); + RTCWireBus->endTransmission(); + + RTCWireBus->requestFrom(_addr, size); + for (uint8_t pos = 0; pos < size; ++pos) { + buf[pos] = RTCWireBus->_I2C_READ(); + } +} + +/**************************************************************************/ +/*! + @brief Write data to the PCF8583 NVRAM + @param address Starting NVRAM address, from 0 to 248 + @param buf Pointer to buffer containing the data to write + @param size Number of bytes in buf to write to NVRAM +*/ +/**************************************************************************/ +void RTC_PCF8583::writenvram(uint8_t address, uint8_t *buf, uint8_t size) { + const int addrByte = PCF8583_NVRAM + address; + RTCWireBus->beginTransmission(_addr); + RTCWireBus->_I2C_WRITE(addrByte); + for (uint8_t pos = 0; pos < size; ++pos) { + RTCWireBus->_I2C_WRITE(buf[pos]); + } + RTCWireBus->endTransmission(); +} + +// END RTC_PCF8583 implementation + /**************************************************************************/ /*! @brief Convert the day of the week to a representation suitable for diff --git a/lib/Adafruit_RTClib/src/RTClib.h b/lib/Adafruit_RTClib/src/RTClib.h index 6642b25f9..fb7d78103 100644 --- a/lib/Adafruit_RTClib/src/RTClib.h +++ b/lib/Adafruit_RTClib/src/RTClib.h @@ -59,6 +59,16 @@ class TimeSpan; ///< temperature value #define DS3232_NVRAM 0x14 ///< Start of RAM registers - 236 bytes, 0x14 to 0xFF +#define PCF8583_ADDRESS 0x50 ///< I2C address for PCF8583 +#define PCF8583_ADDRESS_1 0x51 ///< Alternate I2C address for PCF8583 (A0 = high) +#define PCF8583_CONTROL_1 0x00 ///< Control and status register 1 +#define PCF8583_VL_SECONDS 0x02 ///< register address for VL_SECONDS +#define PCF8583_NVRAM 0x10 ///< Start of RAM registers - 240 bytes, 0x10 to 0xFF + +#define PCF8583_OFFSET_YEAR 0x08 +#define PCF8583_LAST_YEAR 0x09 +#define PCF8583_BASE_YEAR 2012 + /** Constants */ #define SECONDS_PER_DAY 86400L ///< 60 * 60 * 24 #define SECONDS_FROM_1970_TO_2000 \ @@ -457,6 +467,30 @@ protected: TwoWire *RTCWireBus; }; +/**************************************************************************/ +/*! + @brief RTC based on the PCF8583 chip connected via I2C and the Wire library +*/ +/**************************************************************************/ + +class RTC_PCF8583 { +public: + boolean begin(TwoWire *wireInstance = &Wire); + void altAddress(); + boolean lostPower(void); + void adjust(const DateTime &dt); + DateTime now(); + void start(void); + void stop(void); + uint8_t isrunning(); + void readnvram(uint8_t *buf, uint8_t size, uint8_t address); + void writenvram(uint8_t address, uint8_t *buf, uint8_t size); + +protected: + TwoWire *RTCWireBus; + uint8_t _addr = PCF8583_ADDRESS; +}; + /**************************************************************************/ /*! @brief RTC using the internal millis() clock, has to be initialized before diff --git a/src/Custom-sample.h b/src/Custom-sample.h index d6d740cdc..0247d3b21 100644 --- a/src/Custom-sample.h +++ b/src/Custom-sample.h @@ -31,7 +31,7 @@ // #define FEATURE_SD 1 // Enable SD card support // #define FEATURE_DOWNLOAD 1 // Enable downloading a file from an url // #define FEATURE_EEPROM_EXTERNAL 1 // Enable support for AT24Cxxx EEPROM chips AT24C32(4kB)..AT24C1024(128kB), optional: AT24C2048(256kB) and FRAM MB85RC32(4kB)..MB85RC1M(128kB), optional: MB85RC2M(256kB) -// #define FEATURE_RTC_SRAM_STORAGE 1 // Enable storing values in supported RTC Clock chip SRAM (DS1307, DS3232) +// #define FEATURE_RTC_SRAM_STORAGE 1 // Enable storing values in supported RTC Clock chip SRAM (DS1307, DS3232, PCF8583) #ifdef BUILD_GIT # undef BUILD_GIT @@ -229,6 +229,7 @@ #define FEATURE_SSDP 1 #define FEATURE_EXT_RTC 1 // Support for external RTC clock modules like PCF8563/PCF8523/DS3231/DS1307 +#define FEATURE_EXT_RTC_PCF8583 1 // As we enable External RTC clock modules, we can also include PCF8583 #define FEATURE_PLUGIN_STATS 1 // Support collecting historic data + computing stats on historic data #ifdef ESP8266 diff --git a/src/ESPEasy/eeprom/Helpers/RTCSRAMStorage.cpp b/src/ESPEasy/eeprom/Helpers/RTCSRAMStorage.cpp index b1e42f6a9..7c6fd8a5d 100644 --- a/src/ESPEasy/eeprom/Helpers/RTCSRAMStorage.cpp +++ b/src/ESPEasy/eeprom/Helpers/RTCSRAMStorage.cpp @@ -21,6 +21,10 @@ uint8_t checkRTCSRAMEnabled() { const ExtTimeSource_e extRtcType = Settings.ExtTimeSource(); if ((ExtTimeSource_e::DS1307 == extRtcType) || + # if FEATURE_EXT_RTC_PCF8583 + (ExtTimeSource_e::PCF8583 == extRtcType) || + (ExtTimeSource_e::PCF8583a == extRtcType) || + # endif // if FEATURE_EXT_RTC_PCF8583 (ExtTimeSource_e::DS3232 == extRtcType)) { // RTC with SRAM Configured? return static_cast(Settings.ExtTimeSource()); } @@ -39,6 +43,11 @@ uint8_t getRTCI2CAddress() { return DS1307_ADDRESS; case ExtTimeSource_e::DS3232: return DS3231_ADDRESS; + # if FEATURE_EXT_RTC_PCF8583 + case ExtTimeSource_e::PCF8583: + case ExtTimeSource_e::PCF8583a: + return PCF8583_ADDRESS; + # endif // if FEATURE_EXT_RTC_PCF8583 case ExtTimeSource_e::DS3231: case ExtTimeSource_e::PCF8523: case ExtTimeSource_e::PCF8563: @@ -65,6 +74,10 @@ uint8_t selectRTCSRAMI2CBus() { switch (type) { case ExtTimeSource_e::DS1307: + # if FEATURE_EXT_RTC_PCF8583 + case ExtTimeSource_e::PCF8583: + case ExtTimeSource_e::PCF8583a: + # endif // if FEATURE_EXT_RTC_PCF8583 I2CSelect_Max100kHz_ClockSpeed(i2cBus); break; case ExtTimeSource_e::DS3232: @@ -96,6 +109,11 @@ uint32_t getRTCSRAMSize() { return 56ul; case ExtTimeSource_e::DS3232: return 240ul; + # if FEATURE_EXT_RTC_PCF8583 + case ExtTimeSource_e::PCF8583: + case ExtTimeSource_e::PCF8583a: + return 240ul; + # endif // if FEATURE_EXT_RTC_PCF8583 case ExtTimeSource_e::DS3231: case ExtTimeSource_e::PCF8523: case ExtTimeSource_e::PCF8563: @@ -175,6 +193,20 @@ bool writeRTCSRAMSlot(uint32_t slot, } return true; } + # if FEATURE_EXT_RTC_PCF8583 + case ExtTimeSource_e::PCF8583: + case ExtTimeSource_e::PCF8583a: + { + RTC_PCF8583 rtc; + rtc.readnvram(_b, sizeof_rtcsram_slot, addr); + const SRAM_STORAGE_FLOAT_TYPE oldData = *(SRAM_STORAGE_FLOAT_TYPE *)&_b[0]; + + if (!essentiallyEqual(oldData, data)) { + rtc.writenvram(addr, (uint8_t *)&data, sizeof_rtcsram_slot); + } + return true; + } + # endif // if FEATURE_EXT_RTC_PCF8583 case ExtTimeSource_e::DS3231: case ExtTimeSource_e::PCF8523: case ExtTimeSource_e::PCF8563: @@ -210,6 +242,15 @@ SRAM_STORAGE_FLOAT_TYPE readRTCSRAMSlot(uint32_t slot) { rtc.readnvram(_b, sizeof_rtcsram_slot, addr); return *(SRAM_STORAGE_FLOAT_TYPE *)&_b[0]; } + # if FEATURE_EXT_RTC_PCF8583 + case ExtTimeSource_e::PCF8583: + case ExtTimeSource_e::PCF8583a: + { + RTC_PCF8583 rtc; + rtc.readnvram(_b, sizeof_rtcsram_slot, addr); + return *(SRAM_STORAGE_FLOAT_TYPE *)&_b[0]; + } + # endif // if FEATURE_EXT_RTC_PCF8583 case ExtTimeSource_e::DS3231: case ExtTimeSource_e::PCF8523: case ExtTimeSource_e::PCF8563: diff --git a/src/src/CustomBuild/define_plugin_sets.h b/src/src/CustomBuild/define_plugin_sets.h index 78a7f10ee..73a6c853f 100644 --- a/src/src/CustomBuild/define_plugin_sets.h +++ b/src/src/CustomBuild/define_plugin_sets.h @@ -711,6 +711,10 @@ To create/register a plugin, you have to : #undef FEATURE_EXT_RTC #endif #define FEATURE_EXT_RTC 0 + #ifdef FEATURE_EXT_RTC_PCF8583 + #undef FEATURE_EXT_RTC_PCF8583 + #endif + #define FEATURE_EXT_RTC_PCF8583 0 #ifdef FEATURE_SYSLOG #undef FEATURE_SYSLOG #endif @@ -3209,6 +3213,10 @@ To create/register a plugin, you have to : #undef FEATURE_EXT_RTC #endif #define FEATURE_EXT_RTC 0 + #ifdef FEATURE_EXT_RTC_PCF8583 + #undef FEATURE_EXT_RTC_PCF8583 + #endif + #define FEATURE_EXT_RTC_PCF8583 0 #ifndef BUILD_NO_DEBUG #define BUILD_NO_DEBUG #endif @@ -4357,6 +4365,13 @@ To create/register a plugin, you have to : #endif #endif #endif // ifndef FEATURE_RTC_SRAM_STORAGE +#ifndef FEATURE_EXT_RTC_PCF8583 + #if defined(PLUGIN_BUILD_MAX_ESP32) + #define FEATURE_EXT_RTC_PCF8583 1 // Also include PCF8583, that has 240 bytes of SRAM + #else // if defined(PLUGIN_BUILD_MAX_ESP32) + #define FEATURE_EXT_RTC_PCF8583 0 // Also include PCF8583, that has 240 bytes of SRAM + #endif // if defined(PLUGIN_BUILD_MAX_ESP32) +#endif #else // if FEATURE_EXT_RTC #define FEATURE_RTC_SRAM_STORAGE 0 // Not available #endif // if FEATURE_EXT_RTC diff --git a/src/src/DataTypes/TimeSource.cpp b/src/src/DataTypes/TimeSource.cpp index 5f462c77b..45aca6e65 100644 --- a/src/src/DataTypes/TimeSource.cpp +++ b/src/src/DataTypes/TimeSource.cpp @@ -2,13 +2,18 @@ const __FlashStringHelper* toString(ExtTimeSource_e timeSource) { - switch (timeSource) { + switch (timeSource) + { case ExtTimeSource_e::None: break; case ExtTimeSource_e::DS1307: return F("DS1307"); case ExtTimeSource_e::DS3231: return F("DS3231"); case ExtTimeSource_e::DS3232: return F("DS3232"); case ExtTimeSource_e::PCF8523: return F("PCF8523"); case ExtTimeSource_e::PCF8563: return F("PCF8563"); + #if FEATURE_EXT_RTC_PCF8583 + case ExtTimeSource_e::PCF8583: return F("PCF8583 (0x50)"); + case ExtTimeSource_e::PCF8583a: return F("PCF8583 (0x51)"); + #endif // if FEATURE_EXT_RTC_PCF8583 } return F("-"); } diff --git a/src/src/DataTypes/TimeSource.h b/src/src/DataTypes/TimeSource.h index c61afa366..461226f2d 100644 --- a/src/src/DataTypes/TimeSource.h +++ b/src/src/DataTypes/TimeSource.h @@ -11,6 +11,11 @@ enum class ExtTimeSource_e { PCF8523, PCF8563, DS3232, + #if FEATURE_EXT_RTC_PCF8583 + PCF8583, + PCF8583a, + #endif // if FEATURE_EXT_RTC_PCF8583 + }; diff --git a/src/src/Helpers/ESPEasy_time.cpp b/src/src/Helpers/ESPEasy_time.cpp index fed2d1b70..dbf4c0c7f 100644 --- a/src/src/Helpers/ESPEasy_time.cpp +++ b/src/src/Helpers/ESPEasy_time.cpp @@ -1030,6 +1030,30 @@ bool ESPEasy_time::ExtRTC_get(uint32_t& unixtime) unixtime = rtc.now().unixtime(); break; } + #if FEATURE_EXT_RTC_PCF8583 + case ExtTimeSource_e::PCF8583: + case ExtTimeSource_e::PCF8583a: + { + I2CSelect_Max100kHz_ClockSpeed(i2cBus); + RTC_PCF8583 rtc; + + if (ExtTimeSource_e::PCF8583a == Settings.ExtTimeSource()) { + rtc.altAddress(); // Set alternative address (0x51) + } + + if (!rtc.begin()) { + // Not found + break; + } + + if (rtc.lostPower() || !rtc.isrunning()) { + // Cannot get the time from the module + break; + } + unixtime = rtc.now().unixtime(); + break; + } + #endif // if FEATURE_EXT_RTC_PCF8583 } if (unixtime != 0) { @@ -1110,6 +1134,25 @@ bool ESPEasy_time::ExtRTC_set(uint32_t unixtime) } break; } + #if FEATURE_EXT_RTC_PCF8583 + case ExtTimeSource_e::PCF8583: + case ExtTimeSource_e::PCF8583a: + { + I2CSelect_Max100kHz_ClockSpeed(i2cBus); + RTC_PCF8583 rtc; + + if (ExtTimeSource_e::PCF8583a == Settings.ExtTimeSource()) { + rtc.altAddress(); // Set alternative address (0x51) + } + + if (rtc.begin()) { + rtc.adjust(DateTime(unixtime)); + rtc.start(); + timeAdjusted = true; + } + break; + } + #endif // if FEATURE_EXT_RTC_PCF8583 } if (timeAdjusted) { diff --git a/src/src/WebServer/AdvancedConfigPage.cpp b/src/src/WebServer/AdvancedConfigPage.cpp index 62392f311..47641f232 100644 --- a/src/src/WebServer/AdvancedConfigPage.cpp +++ b/src/src/WebServer/AdvancedConfigPage.cpp @@ -465,15 +465,29 @@ void addFormDstSelect(bool isStart, uint16_t choice) { void addFormExtTimeSourceSelect(const __FlashStringHelper * label, const __FlashStringHelper * id, ExtTimeSource_e choice) { addRowLabel(label); - const __FlashStringHelper * options[] = - { F("None"), F("DS1307"), F("DS3231"), F("DS3232"), F("PCF8523"), F("PCF8563")}; + const __FlashStringHelper * options[] = { + F("None"), + toString(ExtTimeSource_e::DS1307), + toString(ExtTimeSource_e::DS3231), + toString(ExtTimeSource_e::DS3232), + toString(ExtTimeSource_e::PCF8523), + toString(ExtTimeSource_e::PCF8563), + #if FEATURE_EXT_RTC_PCF8583 + toString(ExtTimeSource_e::PCF8583), + toString(ExtTimeSource_e::PCF8583a), + #endif // if FEATURE_EXT_RTC_PCF8583 + }; constexpr int optionValues[] = { static_cast(ExtTimeSource_e::None), static_cast(ExtTimeSource_e::DS1307), static_cast(ExtTimeSource_e::DS3231), static_cast(ExtTimeSource_e::DS3232), static_cast(ExtTimeSource_e::PCF8523), - static_cast(ExtTimeSource_e::PCF8563) + static_cast(ExtTimeSource_e::PCF8563), + #if FEATURE_EXT_RTC_PCF8583 + static_cast(ExtTimeSource_e::PCF8583), + static_cast(ExtTimeSource_e::PCF8583a), + #endif // if FEATURE_EXT_RTC_PCF8583 }; const FormSelectorOptions selector(NR_ELEMENTS(optionValues), options, optionValues); diff --git a/src/src/WebServer/EepromVarPage.cpp b/src/src/WebServer/EepromVarPage.cpp index e60d6882f..059570c12 100644 --- a/src/src/WebServer/EepromVarPage.cpp +++ b/src/src/WebServer/EepromVarPage.cpp @@ -103,7 +103,7 @@ void handle_eepromvars() { html_TR(); html_table_header(F("External RTC SRAM"), 300); - html_table_header(F(""), + html_table_header(toString(Settings.ExtTimeSource()), 500); html_table_header(F(""), 400); diff --git a/src/src/WebServer/I2C_Scanner.cpp b/src/src/WebServer/I2C_Scanner.cpp index 8848544a7..c9e9f1057 100644 --- a/src/src/WebServer/I2C_Scanner.cpp +++ b/src/src/WebServer/I2C_Scanner.cpp @@ -313,11 +313,13 @@ String getKnownI2Cdevice(uint8_t address) { result += F("PCF8591,MCP3221,LM75A,INA219"); break; case 0x50: + result += F("PCF8583,AT24Cxx,MB85RCxx"); + break; case 0x52: result += F("AT24Cxx,MB85RCxx"); break; case 0x51: - result += F("PCF8563,AT24Cxx,MB85RCxx"); + result += F("PCF8563,PCF8583,AT24Cxx,MB85RCxx"); break; case 0x53: result += F("ADXL345,LTR390,AT24Cxx,MB85RCxx");