From 55610efcb2d19c28e46ec4b23197a7bf477d69f0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:03:40 +0100 Subject: [PATCH] Support for up to four DS3502 Support for up to four DS3502 digital potentiometers with command ``Wiper 0..127`` --- BUILDS.md | 5 ++ CHANGELOG.md | 3 +- I2CDEVICES.md | 1 + RELEASENOTES.md | 3 +- tasmota/my_user_config.h | 3 +- tasmota/settings.h | 2 +- tasmota/settings.ino | 2 +- tasmota/support_features.ino | 4 +- tasmota/tasmota.h | 1 + tasmota/tasmota_configurations.h | 1 + tasmota/tasmota_configurations_ESP32.h | 2 + tasmota/xdrv_61_ds3502.ino | 95 ++++++++++++++++++++++++++ tools/decode-status.py | 4 +- 13 files changed, 118 insertions(+), 8 deletions(-) create mode 100644 tasmota/xdrv_61_ds3502.ino diff --git a/BUILDS.md b/BUILDS.md index bb31c8b0b..cbf2ecea3 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -127,6 +127,7 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up | USE_SCD30 | - | - / x | - | x | - | - | | USE_SCD40 | - | - / x | - | - | - | - | | USE_SPS30 | - | - / - | - | - | - | - | +| USE_ADE7880 | - | - / - | - | - | - | - | | USE_ADE7953 | - | x / x | x | x | - | x | | USE_VL53L0X | - | - / x | - | x | - | - | | USE_VL53L1X | - | - / - | - | - | - | - | @@ -162,9 +163,13 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up | USE_EZORTD | - | - / - | - | - | - | - | | USE_SEESAW_SOIL | - | - / - | - | - | - | - | | USE_TOF10120 | - | - / - | - | - | - | - | +| USE_BM8563 | - | - / - | - | - | - | - | | USE_AM2320 | - | - / - | - | - | - | - | | USE_T67XX | - | - / - | - | - | - | - | | USE_HM330X | - | - / - | - | - | - | - | +| USE_HDC2010 | - | - / - | - | - | - | - | +| USE_PCF85363 | - | - / - | - | - | - | - | +| USE_DS3502 | - | - / - | - | - | - | - | | | | | | | | | | Feature or Sensor | l | t | k | s | i | d | Remarks | USE_SPI | - | - / - | - | - | - | x | diff --git a/CHANGELOG.md b/CHANGELOG.md index cd31aee42..6dfd97924 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,9 @@ All notable changes to this project will be documented in this file. ## [11.0.0.4] ### Added -- command ``RtcNtpserver 0/1`` to enable Tasmota NTP server when enabled by define ``RTC_NTP_SERVER`` +- Command ``RtcNtpserver 0/1`` to enable Tasmota NTP server when enabled by define ``RTC_NTP_SERVER`` - NeoPool JSON modules, power module, cell info, chlorine, conductivity and ionization +- Support for up to four DS3502 digital potentiometers with command ``Wiper 0..127`` ### Changed - Consolidate three RTC chip drivers (DS3231, BM8563, PCF85363) into one driver updating RTC as soon as possible after restart diff --git a/I2CDEVICES.md b/I2CDEVICES.md index da66f9f3f..cb3d0ab83 100644 --- a/I2CDEVICES.md +++ b/I2CDEVICES.md @@ -100,3 +100,4 @@ Index | Define | Driver | Device | Address(es) | Description 64 | USE_HDC2010 | xsns_94 | HDC2010 | 0x40 | Temperature and Humidity sensor 65 | USE_ADE7880 | xnrg_23 | ADE7880 | 0x38 | Energy monitor 66 | USE_PCF85363 | xsns_99 | PCF85363 | 0x51 | Real time clock + 67 | USE_DS3502 | xdrv_61 | DS3502 | 0x28 - 0x2B | Digital potentiometer diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 1805121ce..9c562f064 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -112,8 +112,9 @@ The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmo - NeoPool commands ``NPpHMin``, ``NPpHMax``, ``NPpH``, ``NPRedox``, ``NPHydrolysis``, ``NPIonization``, ``NPChlorine`` and ``NPControl`` [#15015](https://github.com/arendst/Tasmota/issues/15015) - NeoPool system voltages display - TasmotaSerial implement ``end()`` +- Support for up to four DS3502 digital potentiometers with command ``Wiper 0..127`` - Support for ADE7880 3 phase energy monitor as used in Shelly 3EM [#13515](https://github.com/arendst/Tasmota/issues/13515) -- Support for PCF85363 RTC as used in Shelly 3EM (#13515) +- Support for PCF85363 RTC as used in Shelly 3EM [#13515](https://github.com/arendst/Tasmota/issues/13515) - Full RTC chip integration and synchronisation when using UBX (=GPS), NTP or manual time - NeoPool JSON modules, power module, cell info, chlorine, conductivity and ionization - ESP32 Berry always enable rules diff --git a/tasmota/my_user_config.h b/tasmota/my_user_config.h index 50fdc7d81..06b0155a8 100644 --- a/tasmota/my_user_config.h +++ b/tasmota/my_user_config.h @@ -668,11 +668,12 @@ // #define USE_AM2320 // [I2cDriver60] Enable AM2320 temperature and humidity Sensor (I2C address 0x5C) (+1k code) // #define USE_T67XX // [I2cDriver61] Enable Telaire T67XX CO2 sensor (I2C address 0x15) (+1k3 code) // #define USE_HM330X // [I2cDriver63] Enable support for SeedStudio Grove Particule sensor (I2C address 0x40) (+1k5 code) -// #define USE_HDC2010 // [I2cDriver64] Enable HDC2010 temperature/humidity sensor (I2C address 0x40) (+1k5 code) // #define HM330X_DEFAULT_ADDRESS 0x40 // Option: change default I2C address for HM330X used in SeedSTudio Particucle Sensor // #define HM330X_WARMUP_DELAY 30 // Option: change warmup delay during which data are not read from sensor after a power up // #define HM330X_HIDE_OUT_OF_DATE false // Option: change to true to hide data from web GUI and SENSOR while sensor is asleep +// #define USE_HDC2010 // [I2cDriver64] Enable HDC2010 temperature/humidity sensor (I2C address 0x40) (+1k5 code) // #define USE_PCF85363 // [I2cDriver66] Enable PCF85363 RTC (I2C address 0x51) (+0k7 code) +// #define USE_DS3502 // [I2CDriver67] Enable DS3502 digital potentiometer (I2C address 0x28 - 0x2B) (+0k4 code) // #define USE_DISPLAY // Add I2C Display Support (+2k code) #define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0 diff --git a/tasmota/settings.h b/tasmota/settings.h index 90f637db9..51c10d7d7 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -626,8 +626,8 @@ typedef struct { uint8_t switchmode[MAX_SWITCHES_SET]; // 4A9 uint8_t free_4c5[5]; // 4C5 - uint8_t ex_interlock[4]; // 4CA MAX_INTERLOCKS = MAX_RELAYS / 2 (Legacy) + uint8_t ds3502_state[MAX_DS3502]; // 4CA uint16_t influxdb_port; // 4CE power_t interlock[MAX_INTERLOCKS_SET]; // 4D0 MAX_INTERLOCKS = MAX_RELAYS / 2 int8_t shutter_tilt_config[5][MAX_SHUTTERS]; //508 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 7309106e9..3170ad42c 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1435,7 +1435,7 @@ void SettingsDelta(void) { Settings->switchmode[i] = (i < 8) ? Settings->ex_switchmode[i] : SWITCH_MODE; } for (uint32_t i = 0; i < MAX_INTERLOCKS_SET; i++) { - Settings->interlock[i] = (i < 4) ? Settings->ex_interlock[i] : 0; + Settings->interlock[i] = (i < 4) ? Settings->ds3502_state[i] : 0; } } if (Settings->version < 0x09020007) { diff --git a/tasmota/support_features.ino b/tasmota/support_features.ino index 7c4e1aea6..488ccd283 100644 --- a/tasmota/support_features.ino +++ b/tasmota/support_features.ino @@ -800,7 +800,9 @@ void ResponseAppendFeatures(void) #if defined(USE_I2C) && defined(USE_PCF85363) feature8 |= 0x01000000; // xsns_96_pcf85393.ino #endif -// feature8 |= 0x02000000; +#if defined(USE_I2C) && defined(USE_DS3502) + feature8 |= 0x02000000; // xdrv_61_ds3502.ino +#endif // feature8 |= 0x04000000; // feature8 |= 0x08000000; diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h index 406aace85..5bae64353 100644 --- a/tasmota/tasmota.h +++ b/tasmota/tasmota.h @@ -92,6 +92,7 @@ const uint8_t MAX_I2C_DRIVERS = 96; // Max number of allowed i2c drivers const uint8_t MAX_SHUTTERS = 4; // Max number of shutters const uint8_t MAX_SHUTTER_KEYS = 4; // Max number of shutter keys or buttons const uint8_t MAX_PCF8574 = 4; // Max number of PCF8574 devices +const uint8_t MAX_DS3502 = 4; // Max number of DS3502 digitsal potentiometer devices const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 512 characters const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules const uint16_t VL53LXX_MAX_SENSORS = 8; // Max number of VL53L0X sensors diff --git a/tasmota/tasmota_configurations.h b/tasmota/tasmota_configurations.h index fec5287a3..6fa08d974 100644 --- a/tasmota/tasmota_configurations.h +++ b/tasmota/tasmota_configurations.h @@ -151,6 +151,7 @@ //#define USE_T67XX // [I2cDriver61] Enable Telaire T67XX CO2 sensor (I2C address 0x15) (+1k3 code) //#define USE_HDC2010 // [I2cDriver64] Enable HDC2010 temperature/humidity sensor (I2C address 0x40) (+1k5 code) //#define USE_PCF85363 // [I2cDriver66] Enable PCF85363 RTC (I2C address 0x51) (+0k7 code) +//#define USE_DS3502 // [I2CDriver67] Enable DS3502 digital potentiometer (I2C address 0x28 - 0x2B) (+0k4 code) //#define USE_SPI // Hardware SPI using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK) in addition to two user selectable GPIOs(CS and DC) //#define USE_RC522 // Add support for MFRC522 13.56Mhz Rfid reader (+6k code) diff --git a/tasmota/tasmota_configurations_ESP32.h b/tasmota/tasmota_configurations_ESP32.h index 23abf625d..d0b8a0d3e 100644 --- a/tasmota/tasmota_configurations_ESP32.h +++ b/tasmota/tasmota_configurations_ESP32.h @@ -243,6 +243,7 @@ //#define USE_AM2320 // [I2cDriver60] Enable AM2320 temperature and humidity Sensor (I2C address 0x5C) (+1k code) //#define USE_T67XX // [I2cDriver61] Enable Telaire T67XX CO2 sensor (I2C address 0x15) (+1k3 code) //#define USE_PCF85363 // [I2cDriver66] Enable PCF85363 RTC (I2C address 0x51) (+0k7 code) +//#define USE_DS3502 // [I2CDriver67] Enable DS3502 digital potentiometer (I2C address 0x28 - 0x2B) (+0k4 code) //#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code) //#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code) @@ -378,6 +379,7 @@ //#define USE_EZOPMP // [I2cDriver55] Enable support for EZO's PMP sensor (+0k3 code) - Shared EZO code required for any EZO device (+1k2 code) //#define USE_SEESAW_SOIL // [I2cDriver56] Enable Capacitice Soil Moisture & Temperature Sensor (I2C addresses 0x36 - 0x39) (+1k3 code) //#define USE_PCF85363 // [I2cDriver66] Enable PCF85363 RTC (I2C address 0x51) (+0k7 code) +//#define USE_DS3502 // [I2CDriver67] Enable DS3502 digital potentiometer (I2C address 0x28 - 0x2B) (+0k4 code) #define USE_SPI // Hardware SPI using GPIO12(MISO), GPIO13(MOSI) and GPIO14(CLK) in addition to two user selectable GPIOs(CS and DC) //#define USE_RC522 // Add support for MFRC522 13.56Mhz Rfid reader (+6k code) diff --git a/tasmota/xdrv_61_ds3502.ino b/tasmota/xdrv_61_ds3502.ino new file mode 100644 index 000000000..a8d05f6b4 --- /dev/null +++ b/tasmota/xdrv_61_ds3502.ino @@ -0,0 +1,95 @@ +/* + xdrv_61_ds3502.ino - DS3502 digital potentiometer support for Tasmota + + SPDX-FileCopyrightText: 2022 Theo Arends and f-reiling + + SPDX-License-Identifier: GPL-3.0-only +*/ + +#ifdef USE_I2C +#ifdef USE_DS3502 +/*********************************************************************************************\ + * DS3502 - digital potentiometer (https://datasheets.maximintegrated.com/en/ds/DS3502.pdf) + * + * I2C Address: 0x28 .. 0x2B +\*********************************************************************************************/ + +#define XDRV_61 61 +#define XI2C_67 67 // See I2CDEVICES.md + +#define USE_DS3502_ADDR 0x28 + +#define DS3502_REG_MODE 0x02 +#define DS3502_REG_WIPER 0x00 + +struct DS3502 { + uint8_t address[MAX_DS3502]; + uint8_t max_devices; +} Ds3502; + +void Ds3502SetWiper(uint32_t idx) { + I2cWrite8(Ds3502.address[idx], DS3502_REG_WIPER, Settings->ds3502_state[idx] & 0x7F); +} + +void Ds3502Detect(void) { + Ds3502.max_devices = 0; + uint8_t ds3502_address = USE_DS3502_ADDR; + while (ds3502_address < USE_DS3502_ADDR + MAX_DS3502) { + if (I2cSetDevice(ds3502_address)) { + I2cSetActiveFound(ds3502_address, "DS3502"); + Ds3502.address[Ds3502.max_devices] = ds3502_address; + Ds3502.max_devices++; + } + ds3502_address++; + } + for (uint32_t idx = 0; idx < Ds3502.max_devices; idx++) { + I2cWrite8(Ds3502.address[idx], DS3502_REG_MODE, 0x80); // Mode 1 - Write to non-volatile storage only + Ds3502SetWiper(idx); // Restore state + } +} + +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + +const char kDS3502Commands[] PROGMEM = "|" // No Prefix + "Wiper" ; + +void (* const DS3502Command[])(void) PROGMEM = { + &CmndWiper }; + +void CmndWiper(void) { + // Wiper 0..127 + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= Ds3502.max_devices)) { + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 127)) { + Settings->ds3502_state[XdrvMailbox.index -1] = XdrvMailbox.payload; + Ds3502SetWiper(XdrvMailbox.index -1); // Set wiper + } + ResponseCmndIdxNumber(Settings->ds3502_state[XdrvMailbox.index -1]); + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xdrv61(uint8_t function) { + if (!I2cEnabled(XI2C_67)) { return false; } + + bool result = false; + + if (FUNC_INIT == function) { + Ds3502Detect(); + } + else if (Ds3502.max_devices) { + switch (function) { + case FUNC_COMMAND: + result = DecodeCommand(kDS3502Commands, DS3502Command); + break; + } + } + return result; +} + +#endif // USE_DS3502 +#endif // USE_IC2 \ No newline at end of file diff --git a/tools/decode-status.py b/tools/decode-status.py index a0d0b77ec..32f1b8ec5 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -263,7 +263,7 @@ a_features = [[ "USE_HRG15","USE_VINDRIKTNING","USE_SCD40","USE_HM330X", "USE_HDC2010","USE_LSC_MCSL","USE_SONOFF_SPM","USE_SHIFT595", "USE_SDM230","USE_CM110x","USE_BL6523","USE_ADE7880", - "USE_PCF85363","","","", + "USE_PCF85363","USE_DS3502","","", "","","","" ]] @@ -292,7 +292,7 @@ else: obj = json.load(fp) def StartDecode(): - print ("\n*** decode-status.py v11.0.0.3 by Theo Arends and Jacek Ziolkowski ***") + print ("\n*** decode-status.py v11.0.0.4 by Theo Arends and Jacek Ziolkowski ***") # print("Decoding\n{}".format(obj))