diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino
index 3f88ba690..7739e9a0b 100644
--- a/sonoff/_changelog.ino
+++ b/sonoff/_changelog.ino
@@ -6,6 +6,7 @@
* Add Zigbee more support - collect endpoints and clusters, added ZigbeeDump command
* Add initial support for shutters by Stefan Bode (#288)
* Add command to MCP230xx: sensor29 pin,0/1/2 for OFF/ON/TOGGLE
+ * Add initial support for PCF8574 I2C I/O Expander (currently output only) by Stefan Bode
*
* 6.6.0.13 20190922
* Add command EnergyReset4 x,x to initialize total usage for two tarrifs
diff --git a/sonoff/settings.h b/sonoff/settings.h
index c11926855..4f808586d 100644
--- a/sonoff/settings.h
+++ b/sonoff/settings.h
@@ -93,8 +93,8 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t spare27 : 1;
uint32_t spare28 : 1;
uint32_t spare29 : 1;
- uint32_t shutter_mode : 1; // bit 30 (v6.6.0.15) - SetOption80 - Enable shutter support
- uint32_t spare31 : 1;
+ uint32_t shutter_mode : 1; // bit 30 (v6.6.0.14) - SetOption80 - Enable shutter support
+ uint32_t pcf8574_ports_inverted : 1; // bit 31 (v6.6.0.14) - SetOption81 - Invert all ports on PCF8574 devices
};
} SysBitfield3;
@@ -376,7 +376,6 @@ struct SYSCFG {
uint16_t ina226_r_shunt[4]; // E20
uint16_t ina226_i_fs[4]; // E28
uint16_t tariff[4][2]; // E30
-
uint16_t shutter_opentime[MAX_SHUTTERS]; // E40
uint16_t shutter_closetime[MAX_SHUTTERS]; // E48
int16_t shuttercoeff[5][MAX_SHUTTERS]; // E50
@@ -384,8 +383,9 @@ struct SYSCFG {
uint8_t shutter_set50percent[MAX_SHUTTERS]; // E7C
uint8_t shutter_position[MAX_SHUTTERS]; // E80
uint8_t shutter_startrelay[MAX_SHUTTERS]; // E84
+ uint8_t pcf8574_config[MAX_PCF8574]; // E88
- uint8_t free_e88[368]; // E88
+ uint8_t free_e90[360]; // E90
uint32_t cfg_timestamp; // FF8
uint32_t cfg_crc32; // FFC
diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h
index 5ee19873c..46c0868e2 100644
--- a/sonoff/sonoff.h
+++ b/sonoff/sonoff.h
@@ -68,6 +68,7 @@ const uint8_t MAX_XDSP_DRIVERS = 32; // Max number of allowed display dri
const uint8_t MAX_XDRV_DRIVERS = 96; // Max number of allowed driver drivers
const uint8_t MAX_XSNS_DRIVERS = 96; // Max number of allowed sensor drivers
const uint8_t MAX_SHUTTERS = 4; // Max number of shutters
+const uint8_t MAX_PCF8574 = 8; // Max number of PCF8574 devices
const uint8_t MAX_RULE_MEMS = 5; // Max number of saved vars
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
diff --git a/sonoff/xdrv_27_shutter.ino b/sonoff/xdrv_27_shutter.ino
index e7eaa4250..989a522bd 100644
--- a/sonoff/xdrv_27_shutter.ino
+++ b/sonoff/xdrv_27_shutter.ino
@@ -107,8 +107,6 @@ void ShutterInit(void)
Shutter.mask = 0;
//Initialize to get relay that changed
Shutter.old_power = power;
- char shutter_open_chr[10];
- char shutter_close_chr[10];
bool relay_in_interlock = false;
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Accuracy digits: %d"), Settings.shutter_accuracy);
@@ -164,9 +162,11 @@ void ShutterInit(void)
Shutter.real_position[i] = ShutterPercentToRealPosition(Settings.shutter_position[i], i);
//Shutter.real_position[i] = Settings.shutter_position[i] <= 5 ? Settings.shuttercoeff[2][i] * Settings.shutter_position[i] : Settings.shuttercoeff[1][i] * Settings.shutter_position[i] + Settings.shuttercoeff[0,i];
Shutter.start_position[i] = Shutter.real_position[i];
- dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr);
- dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr);
+ char shutter_open_chr[10];
+ dtostrfd((float)Shutter.open_time[i] / 10 , 1, shutter_open_chr);
+ char shutter_close_chr[10];
+ dtostrfd((float)Shutter.close_time[i] / 10, 1, shutter_close_chr);
AddLog_P2(LOG_LEVEL_INFO, PSTR("SHT: Shutter %d (Relay:%d): Init. Pos: %d [%d %%], Open Vel.: 100 Close Vel.: %d , Max Way: %d, Opentime %s [s], Closetime %s [s], CoedffCalc: c0: %d, c1 %d, c2: %d, c3: %d, c4: %d, binmask %d, is inverted %d, shuttermode %d"),
i, Settings.shutter_startrelay[i], Shutter.real_position[i], Settings.shutter_position[i], Shutter.close_velocity[i], Shutter.open_max[i], shutter_open_chr, shutter_close_chr,
Settings.shuttercoeff[0][i], Settings.shuttercoeff[1][i], Settings.shuttercoeff[2][i], Settings.shuttercoeff[3][i], Settings.shuttercoeff[4][i],
diff --git a/sonoff/xdrv_28_pcf8574.ino b/sonoff/xdrv_28_pcf8574.ino
new file mode 100644
index 000000000..6b651a296
--- /dev/null
+++ b/sonoff/xdrv_28_pcf8574.ino
@@ -0,0 +1,248 @@
+/*
+ xdrv_28_pcf8574.ino - PCF8574 I2C support for Sonoff-Tasmota
+
+ Copyright (C) 2019 Stefan Bode
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see