Merge branch 'A4988_Stepper' of https://github.com/Leuselator/Sonoff-Tasmota into A4988_Stepper

This commit is contained in:
Tim Leuschner 2019-09-08 17:31:35 +02:00
commit 2345828b39
13 changed files with 741 additions and 153 deletions

View File

@ -1,4 +1,8 @@
/*********************************************************************************************\ /*********************************************************************************************\
* 6.6.0.11 20190907
* Change Settings crc calculation allowing short term backward compatibility
* Add support for up to 4 INA226 Voltage and Current sensors by Steve Rogers (#6342)
*
* 6.6.0.10 20190905 * 6.6.0.10 20190905
* Redesign Tuya support by Shantur Rathore (#6353) * Redesign Tuya support by Shantur Rathore (#6353)
* Add command Reset 99 to reset bootcount to zero (#684, #6351) * Add command Reset 99 to reset bootcount to zero (#684, #6351)

View File

@ -147,9 +147,9 @@
#define D_START "Start" #define D_START "Start"
#define D_STD_TIME "STD" #define D_STD_TIME "STD"
#define D_STOP "Stop" #define D_STOP "Stop"
#define D_SUBNET_MASK "Maschera sottorete" #define D_SUBNET_MASK "Maschera Subnet"
#define D_SUBSCRIBE_TO "Sottoscrivi a" #define D_SUBSCRIBE_TO "Sottoscrivi a"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from" #define D_UNSUBSCRIBE_FROM "Cancella da"
#define D_SUCCESSFUL "Riuscito" #define D_SUCCESSFUL "Riuscito"
#define D_SUNRISE "Alba" #define D_SUNRISE "Alba"
#define D_SUNSET "Tramonto" #define D_SUNSET "Tramonto"
@ -161,16 +161,16 @@
#define D_TRANSMIT "Trasmesso" #define D_TRANSMIT "Trasmesso"
#define D_TRUE "Vero" #define D_TRUE "Vero"
#define D_TVOC "TVOC" #define D_TVOC "TVOC"
#define D_UPGRADE "aggiornamento" #define D_UPGRADE "Aggiornamento"
#define D_UPLOAD "Invio" #define D_UPLOAD "Invio"
#define D_UPTIME "Uptime" #define D_UPTIME "Uptime"
#define D_USER "Utente" #define D_USER "Utente"
#define D_UTC_TIME "UTC" #define D_UTC_TIME "UTC"
#define D_UV_INDEX "Indice UV" #define D_UV_INDEX "Indice UV"
#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_1 "Basso"
#define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_2 "Medio"
#define D_UV_INDEX_3 "High" #define D_UV_INDEX_3 "Alto"
#define D_UV_INDEX_4 "Danger" #define D_UV_INDEX_4 "Pericolo"
#define D_UV_INDEX_5 "BurnL1/2" #define D_UV_INDEX_5 "BurnL1/2"
#define D_UV_INDEX_6 "BurnL3" #define D_UV_INDEX_6 "BurnL3"
#define D_UV_INDEX_7 "OoR" #define D_UV_INDEX_7 "OoR"
@ -186,7 +186,7 @@
#define D_WARNING_MINIMAL_VERSION "ATTENZIONE Questa versione non supporta il salvataggio delle impostazioni" #define D_WARNING_MINIMAL_VERSION "ATTENZIONE Questa versione non supporta il salvataggio delle impostazioni"
#define D_LEVEL_10 "level 1-0" #define D_LEVEL_10 "level 1-0"
#define D_LEVEL_01 "level 0-1" #define D_LEVEL_01 "level 0-1"
#define D_SERIAL_LOGGING_DISABLED "Log seriale disabilitato" #define D_SERIAL_LOGGING_DISABLED "Log Seriale disabilitato"
#define D_SYSLOG_LOGGING_REENABLED "Syslog ri-abilitato" #define D_SYSLOG_LOGGING_REENABLED "Syslog ri-abilitato"
#define D_SET_BAUDRATE_TO "Baudrate impostato a" #define D_SET_BAUDRATE_TO "Baudrate impostato a"
@ -198,11 +198,11 @@
#define D_OSWATCH "osWatch" #define D_OSWATCH "osWatch"
#define D_BLOCKED_LOOP "Ciclo Bloccato" #define D_BLOCKED_LOOP "Ciclo Bloccato"
#define D_WPS_FAILED_WITH_STATUS "WPSconfig Fallito con stato" #define D_WPS_FAILED_WITH_STATUS "WPSconfig Fallito con stato"
#define D_ACTIVE_FOR_3_MINUTES "attivo per 3 minuti" #define D_ACTIVE_FOR_3_MINUTES "Attivo per 3 minuti"
#define D_FAILED_TO_START "partenza fallita" #define D_FAILED_TO_START "partenza fallita"
#define D_PATCH_ISSUE_2186 "Patch issue 2186" #define D_PATCH_ISSUE_2186 "Patch issue 2186"
#define D_CONNECTING_TO_AP "Connessione ad AP" #define D_CONNECTING_TO_AP "Connessione ad AP"
#define D_IN_MODE "in modalità" #define D_IN_MODE "In modalità"
#define D_CONNECT_FAILED_NO_IP_ADDRESS "Connessione fallita, indirizzo IP non ricevuto" #define D_CONNECT_FAILED_NO_IP_ADDRESS "Connessione fallita, indirizzo IP non ricevuto"
#define D_CONNECT_FAILED_AP_NOT_REACHED "Connessione fallita, AP non raggiungibile" #define D_CONNECT_FAILED_AP_NOT_REACHED "Connessione fallita, AP non raggiungibile"
#define D_CONNECT_FAILED_WRONG_PASSWORD "Connessione fallita, password AP non corretta" #define D_CONNECT_FAILED_WRONG_PASSWORD "Connessione fallita, password AP non corretta"
@ -259,8 +259,8 @@
#define D_PULLUP_ENABLE "No Button/Switch pull-up" #define D_PULLUP_ENABLE "No Button/Switch pull-up"
#define D_ADC "ADC" #define D_ADC "ADC"
#define D_GPIO "GPIO" #define D_GPIO "GPIO"
#define D_SERIAL_IN "Serial In" #define D_SERIAL_IN "Seriale In"
#define D_SERIAL_OUT "Serial Out" #define D_SERIAL_OUT "Seriale Out"
#define D_WIFI_PARAMETERS "Parametri Wifi" #define D_WIFI_PARAMETERS "Parametri Wifi"
#define D_SCAN_FOR_WIFI_NETWORKS "Scansione delle reti wifi" #define D_SCAN_FOR_WIFI_NETWORKS "Scansione delle reti wifi"
@ -283,30 +283,30 @@
#define D_FULL_TOPIC "Full Topic" #define D_FULL_TOPIC "Full Topic"
#define D_LOGGING_PARAMETERS "Parametri Logging" #define D_LOGGING_PARAMETERS "Parametri Logging"
#define D_SERIAL_LOG_LEVEL "Seriale livello di log" #define D_SERIAL_LOG_LEVEL "Livello di log Seriale"
#define D_WEB_LOG_LEVEL "Web livello di log" #define D_WEB_LOG_LEVEL "livello di log Web"
#define D_SYS_LOG_LEVEL "Sys livello di log" #define D_SYS_LOG_LEVEL "livello di log Sys"
#define D_MORE_DEBUG "Debug aggiuntivo" #define D_MORE_DEBUG "Debug aggiuntivo"
#define D_SYSLOG_HOST "Syslog host" #define D_SYSLOG_HOST "Syslog host"
#define D_SYSLOG_PORT "Syslog porta" #define D_SYSLOG_PORT "Syslog porta"
#define D_TELEMETRY_PERIOD "Periodo Telemetria" #define D_TELEMETRY_PERIOD "Periodo Telemetria"
#define D_OTHER_PARAMETERS "Altri parametri" #define D_OTHER_PARAMETERS "Altri parametri"
#define D_TEMPLATE "Template" #define D_TEMPLATE "Modello"
#define D_ACTIVATE "Activate" #define D_ACTIVATE "Attivare"
#define D_WEB_ADMIN_PASSWORD "Password Amministratore Web" #define D_WEB_ADMIN_PASSWORD "Password Amministratore Web"
#define D_MQTT_ENABLE "Abilita MQTT" #define D_MQTT_ENABLE "Abilita MQTT"
#define D_FRIENDLY_NAME "Nome confidenziale" #define D_FRIENDLY_NAME "Nome amichevole"
#define D_BELKIN_WEMO "Belkin WeMo" #define D_BELKIN_WEMO "Belkin WeMo"
#define D_HUE_BRIDGE "Hue Bridge" #define D_HUE_BRIDGE "Hue Bridge"
#define D_SINGLE_DEVICE "dispositivo singolo" #define D_SINGLE_DEVICE "dispositivo singolo"
#define D_MULTI_DEVICE "dispositivo multiplo" #define D_MULTI_DEVICE "dispositivo multiplo"
#define D_CONFIGURE_TEMPLATE "Configure Template" #define D_CONFIGURE_TEMPLATE "Configurare Modello"
#define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_PARAMETERS "Parametri Modello"
#define D_TEMPLATE_NAME "Name" #define D_TEMPLATE_NAME "Nome"
#define D_BASE_TYPE "Based on" #define D_BASE_TYPE "Baseto nel"
#define D_TEMPLATE_FLAGS "Options" #define D_TEMPLATE_FLAGS "Opzioni"
#define D_SAVE_CONFIGURATION "Salva configurazione" #define D_SAVE_CONFIGURATION "Salva configurazione"
#define D_CONFIGURATION_SAVED "Configurazione salvata" #define D_CONFIGURATION_SAVED "Configurazione salvata"
@ -464,12 +464,12 @@
#define D_PARTICALS_BEYOND "Particelle" #define D_PARTICALS_BEYOND "Particelle"
// xsns_32_mpu6050.ino // xsns_32_mpu6050.ino
#define D_AX_AXIS "Accel. X-Axis" #define D_AX_AXIS "Accel. Asse-X"
#define D_AY_AXIS "Accel. Y-Axis" #define D_AY_AXIS "Accel. Asse-Y"
#define D_AZ_AXIS "Accel. Z-Axis" #define D_AZ_AXIS "Accel. Asse-Z"
#define D_GX_AXIS "Gyro X-Axis" #define D_GX_AXIS "Gyro Asse-X"
#define D_GY_AXIS "Gyro Y-Axis" #define D_GY_AXIS "Gyro Asse-Y"
#define D_GZ_AXIS "Gyro Z-Axis" #define D_GZ_AXIS "Gyro Asse-Z"
// xsns_34_hx711.ino // xsns_34_hx711.ino
#define D_HX_CAL_REMOVE "Rimuovere peso" #define D_HX_CAL_REMOVE "Rimuovere peso"

View File

@ -65,8 +65,8 @@
#define D_BY "por" // Write by me #define D_BY "por" // Write by me
#define D_BYTES "Bytes" #define D_BYTES "Bytes"
#define D_CELSIUS "Celsius" #define D_CELSIUS "Celsius"
#define D_CHANNEL "Channel" #define D_CHANNEL "Canal"
#define D_CO2 "Dióxido de carbono" #define D_CO2 "CO2"
#define D_CODE "Código" // Button code #define D_CODE "Código" // Button code
#define D_COLDLIGHT "Luz fria" #define D_COLDLIGHT "Luz fria"
#define D_COMMAND "Comando" #define D_COMMAND "Comando"
@ -93,14 +93,14 @@
#define D_FALLBACK_TOPIC "Tópico para retornar" #define D_FALLBACK_TOPIC "Tópico para retornar"
#define D_FALSE "Falso" #define D_FALSE "Falso"
#define D_FILE "Arquivo" #define D_FILE "Arquivo"
#define D_FLOW_RATE "Flow rate" #define D_FLOW_RATE "Quociente de vazão"
#define D_FREE_MEMORY "Memória livre" #define D_FREE_MEMORY "Memória livre"
#define D_FREQUENCY "Frequência" #define D_FREQUENCY "Frequência"
#define D_GAS "Gás" #define D_GAS "Gás"
#define D_GATEWAY "Gateway" #define D_GATEWAY "Gateway"
#define D_GROUP "Grupo" #define D_GROUP "Grupo"
#define D_HOST "Anfitrião" #define D_HOST "Host"
#define D_HOSTNAME "Nome do anfitrião" #define D_HOSTNAME "Nome do Host"
#define D_HUMIDITY "Umidade" #define D_HUMIDITY "Umidade"
#define D_ILLUMINANCE "Luminância" #define D_ILLUMINANCE "Luminância"
#define D_IMMEDIATE "Imediato" // Button immediate #define D_IMMEDIATE "Imediato" // Button immediate
@ -167,10 +167,10 @@
#define D_USER "Usuário" #define D_USER "Usuário"
#define D_UTC_TIME "UTC" #define D_UTC_TIME "UTC"
#define D_UV_INDEX "Índice UV" #define D_UV_INDEX "Índice UV"
#define D_UV_INDEX_1 "Low" #define D_UV_INDEX_1 "Baixo"
#define D_UV_INDEX_2 "Mid" #define D_UV_INDEX_2 "Médio"
#define D_UV_INDEX_3 "High" #define D_UV_INDEX_3 "Alto"
#define D_UV_INDEX_4 "Danger" #define D_UV_INDEX_4 "Perigro"
#define D_UV_INDEX_5 "BurnL1/2" #define D_UV_INDEX_5 "BurnL1/2"
#define D_UV_INDEX_6 "BurnL3" #define D_UV_INDEX_6 "BurnL3"
#define D_UV_INDEX_7 "OoR" #define D_UV_INDEX_7 "OoR"
@ -178,7 +178,7 @@
#define D_UV_POWER "UV Power" #define D_UV_POWER "UV Power"
#define D_VERSION "Versão" #define D_VERSION "Versão"
#define D_VOLTAGE "Voltagem" #define D_VOLTAGE "Voltagem"
#define D_WEIGHT "Weight" #define D_WEIGHT "Peso"
#define D_WARMLIGHT "Luz quente" #define D_WARMLIGHT "Luz quente"
#define D_WEB_SERVER "Servidor WEB" #define D_WEB_SERVER "Servidor WEB"
@ -186,7 +186,7 @@
#define D_WARNING_MINIMAL_VERSION "AVISO: esta versão não supporta configurações persistentes" #define D_WARNING_MINIMAL_VERSION "AVISO: esta versão não supporta configurações persistentes"
#define D_LEVEL_10 "nível 1-0" #define D_LEVEL_10 "nível 1-0"
#define D_LEVEL_01 "nível 0-1" #define D_LEVEL_01 "nível 0-1"
#define D_SERIAL_LOGGING_DISABLED "Registro em série desabilitado" #define D_SERIAL_LOGGING_DISABLED "Registro Serial desabilitado"
#define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado" #define D_SYSLOG_LOGGING_REENABLED "Registro do Syslog reativado"
#define D_SET_BAUDRATE_TO "Ajuste da velocidade para" #define D_SET_BAUDRATE_TO "Ajuste da velocidade para"
@ -292,7 +292,7 @@
#define D_TELEMETRY_PERIOD "Período de telemetria" #define D_TELEMETRY_PERIOD "Período de telemetria"
#define D_OTHER_PARAMETERS "Outros parâmetros" #define D_OTHER_PARAMETERS "Outros parâmetros"
#define D_TEMPLATE "Template" #define D_TEMPLATE "Modelo"
#define D_ACTIVATE "Activate" #define D_ACTIVATE "Activate"
#define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin" #define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin"
#define D_MQTT_ENABLE "MQTT habilitado" #define D_MQTT_ENABLE "MQTT habilitado"
@ -302,11 +302,11 @@
#define D_SINGLE_DEVICE "Dispositivo único" #define D_SINGLE_DEVICE "Dispositivo único"
#define D_MULTI_DEVICE "Múltiplos dispositivos" #define D_MULTI_DEVICE "Múltiplos dispositivos"
#define D_CONFIGURE_TEMPLATE "Configure Template" #define D_CONFIGURE_TEMPLATE "Configurar Modelo"
#define D_TEMPLATE_PARAMETERS "Template parameters" #define D_TEMPLATE_PARAMETERS "Parâmetros Modelo"
#define D_TEMPLATE_NAME "Name" #define D_TEMPLATE_NAME "Nome"
#define D_BASE_TYPE "Based on" #define D_BASE_TYPE "Baseado em"
#define D_TEMPLATE_FLAGS "Options" #define D_TEMPLATE_FLAGS "Opções"
#define D_SAVE_CONFIGURATION "Gravar configuração" #define D_SAVE_CONFIGURATION "Gravar configuração"
#define D_CONFIGURATION_SAVED "Configuração gravada" #define D_CONFIGURATION_SAVED "Configuração gravada"
@ -347,10 +347,10 @@
#define D_UPLOAD_ERR_7 "Envio cancelado" #define D_UPLOAD_ERR_7 "Envio cancelado"
#define D_UPLOAD_ERR_8 "Arquivo inválido" #define D_UPLOAD_ERR_8 "Arquivo inválido"
#define D_UPLOAD_ERR_9 "Arquivo muito grande" #define D_UPLOAD_ERR_9 "Arquivo muito grande"
#define D_UPLOAD_ERR_10 "Failed to init RF chip" #define D_UPLOAD_ERR_10 "Falha ao iniciar chip RF"
#define D_UPLOAD_ERR_11 "Failed to erase RF chip" #define D_UPLOAD_ERR_11 "Falha ao apagar o chip RF"
#define D_UPLOAD_ERR_12 "Failed to write to RF chip" #define D_UPLOAD_ERR_12 "Falha ao escrever o chip RF"
#define D_UPLOAD_ERR_13 "Failed to decode RF firmware" #define D_UPLOAD_ERR_13 "Falha ao decodificar o firmware de RF"
#define D_UPLOAD_ERROR_CODE "Código de erro do envio" #define D_UPLOAD_ERROR_CODE "Código de erro do envio"
#define D_ENTER_COMMAND "Inserir comando" #define D_ENTER_COMMAND "Inserir comando"
@ -472,27 +472,27 @@
#define D_GZ_AXIS "Gyro Z-Axis" #define D_GZ_AXIS "Gyro Z-Axis"
// xsns_34_hx711.ino // xsns_34_hx711.ino
#define D_HX_CAL_REMOVE "Remove weigth" #define D_HX_CAL_REMOVE "Remover peso"
#define D_HX_CAL_REFERENCE "Load reference weigth" #define D_HX_CAL_REFERENCE "Peso de referência de carga"
#define D_HX_CAL_DONE "Calibrated" #define D_HX_CAL_DONE "Calibrado"
#define D_HX_CAL_FAIL "Calibration failed" #define D_HX_CAL_FAIL "Falha na calibração"
#define D_RESET_HX711 "Reset Scale" #define D_RESET_HX711 "Redefinir escala"
#define D_CONFIGURE_HX711 "Configure Scale" #define D_CONFIGURE_HX711 "Configurar escala"
#define D_HX711_PARAMETERS "Scale parameters" #define D_HX711_PARAMETERS "Parâmetros de escala"
#define D_ITEM_WEIGHT "Item weight" #define D_ITEM_WEIGHT "Peso do Item"
#define D_REFERENCE_WEIGHT "Reference weigth" #define D_REFERENCE_WEIGHT "Peso de referência"
#define D_CALIBRATE "Calibrate" #define D_CALIBRATE "Calibrar"
#define D_CALIBRATION "Calibration" #define D_CALIBRATION "Calibração"
//xsns_35_tx20.ino //xsns_35_tx20.ino
#define D_TX20_WIND_DIRECTION "Wind Direction" #define D_TX20_WIND_DIRECTION "Direção do vento"
#define D_TX20_WIND_SPEED "Wind Speed" #define D_TX20_WIND_SPEED "Velocidade do vento"
#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg" #define D_TX20_WIND_SPEED_AVG "Velocidade média do vento"
#define D_TX20_WIND_SPEED_MAX "Wind Speed Max" #define D_TX20_WIND_SPEED_MAX "Velocidade do vento Máxima"
#define D_TX20_NORTH "N" #define D_TX20_NORTH "N"
#define D_TX20_EAST "E" #define D_TX20_EAST "L"
#define D_TX20_SOUTH "S" #define D_TX20_SOUTH "S"
#define D_TX20_WEST "W" #define D_TX20_WEST "O"
//xsns_43_hre.ino //xsns_43_hre.ino
#define D_LOG_HRE "HRE: " #define D_LOG_HRE "HRE: "
@ -663,37 +663,37 @@
#define D_LOG_WIFI "WIF: " // Wifi #define D_LOG_WIFI "WIF: " // Wifi
//SDM220 //SDM220
#define D_PHASE_ANGLE "Phase Angle" #define D_PHASE_ANGLE "Ângulo de Fase"
#define D_IMPORT_ACTIVE "Import Active" #define D_IMPORT_ACTIVE "Importar Ativo"
#define D_EXPORT_ACTIVE "Export Active" #define D_EXPORT_ACTIVE "Exportar Ativo"
#define D_IMPORT_REACTIVE "Import Reactive" #define D_IMPORT_REACTIVE "Importar Reativo"
#define D_EXPORT_REACTIVE "Export Reactive" #define D_EXPORT_REACTIVE "Exportar Reativo"
#define D_TOTAL_REACTIVE "Total Reactive" #define D_TOTAL_REACTIVE "Reativo total"
#define D_UNIT_KWARH "kVArh" #define D_UNIT_KWARH "kVArh"
#define D_UNIT_ANGLE "Deg" #define D_UNIT_ANGLE "Deg"
//SOLAXX1 //SOLAXX1
#define D_PV1_VOLTAGE "PV1 Voltage" #define D_PV1_VOLTAGE "PV1 Voltagem"
#define D_PV1_CURRENT "PV1 Current" #define D_PV1_CURRENT "PV1 Corrente"
#define D_PV1_POWER "PV1 Power" #define D_PV1_POWER "PV1 Energia"
#define D_PV2_VOLTAGE "PV2 Voltage" #define D_PV2_VOLTAGE "PV2 Voltagem"
#define D_PV2_CURRENT "PV2 Current" #define D_PV2_CURRENT "PV2 Corrente"
#define D_PV2_POWER "PV2 Power" #define D_PV2_POWER "PV2 Energia"
#define D_SOLAR_POWER "Solar Power" #define D_SOLAR_POWER "Energia Solar"
#define D_INVERTER_POWER "Inverter Power" #define D_INVERTER_POWER "Potência do Inversor"
#define D_STATUS "Status" #define D_STATUS "Status"
#define D_WAITING "Waiting" #define D_WAITING "Esperando"
#define D_CHECKING "Checking" #define D_CHECKING "Verificando"
#define D_WORKING "Working" #define D_WORKING "Trabalhando"
#define D_FAILURE "Failure" #define D_FAILURE "Falha"
#define D_SOLAX_ERROR_0 "No Error Code" #define D_SOLAX_ERROR_0 "Nenhum código de erro"
#define D_SOLAX_ERROR_1 "Grid Lost Fault" #define D_SOLAX_ERROR_1 "Erro Grid Perdida"
#define D_SOLAX_ERROR_2 "Grid Voltage Fault" #define D_SOLAX_ERROR_2 "Falha na Tensão da rede"
#define D_SOLAX_ERROR_3 "Grid Frequency Fault" #define D_SOLAX_ERROR_3 "Falha na Frequência do Grid"
#define D_SOLAX_ERROR_4 "Pv Voltage Fault" #define D_SOLAX_ERROR_4 "Pv Falha de Tensão"
#define D_SOLAX_ERROR_5 "Isolation Fault" #define D_SOLAX_ERROR_5 "Falha de Isolamento"
#define D_SOLAX_ERROR_6 "Over Temperature Fault" #define D_SOLAX_ERROR_6 "Falha de Temperatura excessiva"
#define D_SOLAX_ERROR_7 "Fan Fault" #define D_SOLAX_ERROR_7 "Falha no Ventilador"
#define D_SOLAX_ERROR_8 "Other Device Fault" #define D_SOLAX_ERROR_8 "Outra falha do dispositivo"
#endif // _LANGUAGE_PT_BR_H_ #endif // _LANGUAGE_PT_BR_H_

View File

@ -373,8 +373,10 @@ struct SYSCFG {
char mems[MAX_RULE_MEMS][10]; // 7CE char mems[MAX_RULE_MEMS][10]; // 7CE
char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b char rules[MAX_RULE_SETS][MAX_RULE_SIZE]; // 800 uses 512 bytes in v5.12.0m, 3 x 512 bytes in v5.14.0b
TuyaFnidDpidMap tuya_fnid_map[MAX_TUYA_FUNCTIONS]; // E00 32 bytes TuyaFnidDpidMap tuya_fnid_map[MAX_TUYA_FUNCTIONS]; // E00 32 bytes
uint16_t ina226_r_shunt[4]; // E20
uint16_t ina226_i_fs[4]; // E28
uint8_t free_e20[472]; // E20 uint8_t free_e30[456]; // E30
uint32_t cfg_timestamp; // FF8 uint32_t cfg_timestamp; // FF8
uint32_t cfg_crc32; // FFC uint32_t cfg_crc32; // FFC

View File

@ -274,8 +274,7 @@ const uint32_t SETTINGS_LOCATION = SPIFFS_END; // No need for SPIFFS as it uses
const uint8_t CFG_ROTATES = 8; // Number of flash sectors used (handles uploads) const uint8_t CFG_ROTATES = 8; // Number of flash sectors used (handles uploads)
uint32_t settings_location = SETTINGS_LOCATION; uint32_t settings_location = SETTINGS_LOCATION;
//uint32_t settings_crc32 = 0; uint32_t settings_crc32 = 0;
uint16_t settings_crc = 0;
uint8_t *settings_buffer = nullptr; uint8_t *settings_buffer = nullptr;
/********************************************************************************************/ /********************************************************************************************/
@ -319,27 +318,29 @@ bool SettingsBufferAlloc(void)
return true; return true;
} }
uint16_t GetSettingsCrc(void) uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size)
{ {
uint16_t crc = 0; uint16_t crc = 0;
uint8_t *bytes = (uint8_t*)&Settings;
// Fix miscalculation if previous Settings was 3584 and current Settings is 4096 as of 0x06060007
uint32_t size = (Settings.version < 0x06060007) ? 3584 : sizeof(SYSCFG);
for (uint32_t i = 0; i < size; i++) { for (uint32_t i = 0; i < size; i++) {
if ((i < 14) || (i > 15)) { crc += bytes[i]*(i+1); } // Skip crc if ((i < 14) || (i > 15)) { crc += bytes[i]*(i+1); } // Skip crc
} }
return crc; return crc;
} }
uint32_t GetSettingsCrc32(void) uint16_t GetSettingsCrc(void)
{
// Fix miscalculation if previous Settings was 3584 and current Settings is 4096 between 0x06060007 and 0x0606000A
uint32_t size = ((Settings.version < 0x06060007) || (Settings.version > 0x0606000A)) ? 3584 : sizeof(SYSCFG);
return GetCfgCrc16((uint8_t*)&Settings, size);
}
uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size)
{ {
// https://create.stephan-brumme.com/crc32/#bitwise // https://create.stephan-brumme.com/crc32/#bitwise
uint32_t crc = 0; uint32_t crc = 0;
uint8_t *bytes = (uint8_t*)&Settings;
uint32_t length = sizeof(SYSCFG) -4; // Skip crc while (size--) {
while (length--) {
crc ^= *bytes++; crc ^= *bytes++;
for (uint32_t j = 0; j < 8; j++) { for (uint32_t j = 0; j < 8; j++) {
crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320); crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320);
@ -348,6 +349,11 @@ uint32_t GetSettingsCrc32(void)
return ~crc; return ~crc;
} }
uint32_t GetSettingsCrc32(void)
{
return GetCfgCrc32((uint8_t*)&Settings, sizeof(SYSCFG) -4); // Skip crc32
}
void SettingsSaveAll(void) void SettingsSaveAll(void)
{ {
if (Settings.flag.save_state) { if (Settings.flag.save_state) {
@ -380,7 +386,7 @@ void SettingsSave(uint8_t rotate)
* stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1) * stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1)
*/ */
#ifndef FIRMWARE_MINIMAL #ifndef FIRMWARE_MINIMAL
if ((GetSettingsCrc() != settings_crc) || rotate) { if ((GetSettingsCrc32() != settings_crc32) || rotate) {
if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade) if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade)
stop_flash_rotate = 1; stop_flash_rotate = 1;
} }
@ -395,6 +401,7 @@ void SettingsSave(uint8_t rotate)
settings_location = SETTINGS_LOCATION; settings_location = SETTINGS_LOCATION;
} }
} }
Settings.save_flag++; Settings.save_flag++;
if (UtcTime() > START_VALID_TIME) { if (UtcTime() > START_VALID_TIME) {
Settings.cfg_timestamp = UtcTime(); Settings.cfg_timestamp = UtcTime();
@ -402,8 +409,8 @@ void SettingsSave(uint8_t rotate)
Settings.cfg_timestamp++; Settings.cfg_timestamp++;
} }
Settings.cfg_size = sizeof(SYSCFG); Settings.cfg_size = sizeof(SYSCFG);
// Settings.cfg_crc32 = GetSettingsCrc32(); Settings.cfg_crc = GetSettingsCrc(); // Keep for backward compatibility in case of fall-back just after upgrade
Settings.cfg_crc = GetSettingsCrc(); Settings.cfg_crc32 = GetSettingsCrc32();
ESP.flashEraseSector(settings_location); ESP.flashEraseSector(settings_location);
ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG));
@ -417,8 +424,7 @@ void SettingsSave(uint8_t rotate)
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG)); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG));
settings_crc = Settings.cfg_crc; settings_crc32 = Settings.cfg_crc32;
// settings_crc32 = Settings.cfg_crc32;
} }
#endif // FIRMWARE_MINIMAL #endif // FIRMWARE_MINIMAL
RtcSettingsSave(); RtcSettingsSave();
@ -443,7 +449,10 @@ void SettingsLoad(void)
bool valid = false; bool valid = false;
if (Settings.version > 0x06000000) { if (Settings.version > 0x06000000) {
bool almost_valid = (Settings.cfg_crc == GetSettingsCrc()); bool almost_valid = (Settings.cfg_crc32 == GetSettingsCrc32());
if (Settings.version < 0x0606000B) {
almost_valid = (Settings.cfg_crc == GetSettingsCrc());
}
// Sometimes CRC on pages below FB, overwritten by OTA, is fine but Settings are still invalid. So check cfg_holder too // Sometimes CRC on pages below FB, overwritten by OTA, is fine but Settings are still invalid. So check cfg_holder too
if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active cfg_holder if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active cfg_holder
valid = (cfg_holder == Settings.cfg_holder); valid = (cfg_holder == Settings.cfg_holder);
@ -472,7 +481,7 @@ void SettingsLoad(void)
if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h
SettingsDefault(); SettingsDefault();
} }
settings_crc = GetSettingsCrc(); settings_crc32 = GetSettingsCrc32();
#endif // FIRMWARE_MINIMAL #endif // FIRMWARE_MINIMAL
RtcSettingsLoad(); RtcSettingsLoad();

View File

@ -108,6 +108,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
#define USE_ADS1115 // Add I2C code for ADS1115 16 bit A/D converter based on Adafruit ADS1x15 library (no library needed) (+0k7 code) #define USE_ADS1115 // Add I2C code for ADS1115 16 bit A/D converter based on Adafruit ADS1x15 library (no library needed) (+0k7 code)
//#define USE_ADS1115_I2CDEV // Add I2C code for ADS1115 16 bit A/D converter using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code) //#define USE_ADS1115_I2CDEV // Add I2C code for ADS1115 16 bit A/D converter using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code)
#define USE_INA219 // Add I2C code for INA219 Low voltage and current sensor (+1k code) #define USE_INA219 // Add I2C code for INA219 Low voltage and current sensor (+1k code)
//#define USE_INA226 // Enable INA226 (I2C address 0x40, 0x41 0x44 or 0x45) Low voltage and current sensor (+2k3 code)
#define USE_SHT3X // Add I2C code for SHT3x sensor (+0k6 code) #define USE_SHT3X // Add I2C code for SHT3x sensor (+0k6 code)
#define USE_TSL2561 // Add I2C code for TSL2561 sensor using library Adafruit TSL2561 Arduino (+1k2 code) #define USE_TSL2561 // Add I2C code for TSL2561 sensor using library Adafruit TSL2561 Arduino (+1k2 code)
#define USE_MGS // Add I2C code for Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code) #define USE_MGS // Add I2C code for Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code)

View File

@ -20,6 +20,6 @@
#ifndef _SONOFF_VERSION_H_ #ifndef _SONOFF_VERSION_H_
#define _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_
const uint32_t VERSION = 0x0606000A; const uint32_t VERSION = 0x0606000B;
#endif // _SONOFF_VERSION_H_ #endif // _SONOFF_VERSION_H_

View File

@ -438,12 +438,15 @@ void GetFeatures(void)
#ifdef USE_IBEACON #ifdef USE_IBEACON
feature5 |= 0x00000004; // xsns_52_ibeacon.ino feature5 |= 0x00000004; // xsns_52_ibeacon.ino
#endif #endif
#ifdef USE_A4988_Stepper #ifdef USE_SML_M
feature5 |= 0x00000008; // xdrv_25_A4988.ino feature5 |= 0x00000008; // xsns_53_sml.ino
#endif
#ifdef USE_INA226
feature5 |= 0x00000010; // xsns_54_ina226.ino
#endif
#ifdef USE_A4988_Stepper
feature5 |= 0x00000020; // xdrv_25_A4988.ino
#endif #endif
// feature5 |= 0x00000010;
// feature5 |= 0x00000020;
// feature5 |= 0x00000040; // feature5 |= 0x00000040;
// feature5 |= 0x00000080; // feature5 |= 0x00000080;

View File

@ -1687,8 +1687,8 @@ void HandleBackupConfiguration(void)
WSSend(200, CT_STREAM, ""); WSSend(200, CT_STREAM, "");
uint16_t cfg_crc = Settings.cfg_crc; uint32_t cfg_crc32 = Settings.cfg_crc32;
Settings.cfg_crc = GetSettingsCrc(); // Calculate crc (again) as it might be wrong when savedata = 0 (#3918) Settings.cfg_crc32 = GetSettingsCrc32(); // Calculate crc (again) as it might be wrong when savedata = 0 (#3918)
memcpy(settings_buffer, &Settings, sizeof(Settings)); memcpy(settings_buffer, &Settings, sizeof(Settings));
if (Web.config_xor_on_set) { if (Web.config_xor_on_set) {
@ -1708,7 +1708,7 @@ void HandleBackupConfiguration(void)
SettingsBufferFree(); SettingsBufferFree();
Settings.cfg_crc = cfg_crc; // Restore crc in case savedata = 0 to make sure settings will be noted as changed Settings.cfg_crc32 = cfg_crc32; // Restore crc in case savedata = 0 to make sure settings will be noted as changed
} }
/*-------------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------------*/
@ -2093,12 +2093,13 @@ void HandleUploadLoop(void)
unsigned long buffer_version = settings_buffer[11] << 24 | settings_buffer[10] << 16 | settings_buffer[9] << 8 | settings_buffer[8]; unsigned long buffer_version = settings_buffer[11] << 24 | settings_buffer[10] << 16 | settings_buffer[9] << 8 | settings_buffer[8];
if (buffer_version > 0x06000000) { if (buffer_version > 0x06000000) {
uint32_t buffer_size = settings_buffer[3] << 8 | settings_buffer[2]; uint32_t buffer_size = settings_buffer[3] << 8 | settings_buffer[2];
uint16_t buffer_crc = settings_buffer[15] << 8 | settings_buffer[14]; if (buffer_version > 0x0606000A) {
uint16_t crc = 0; uint32_t buffer_crc32 = settings_buffer[4095] << 24 | settings_buffer[4094] << 16 | settings_buffer[4093] << 8 | settings_buffer[4092];
for (uint32_t i = 0; i < buffer_size; i++) { valid_settings = (GetCfgCrc32(settings_buffer, buffer_size -4) == buffer_crc32);
if ((i < 14) || (i > 15)) { crc += settings_buffer[i]*(i+1); } // Skip crc } else {
uint16_t buffer_crc16 = settings_buffer[15] << 8 | settings_buffer[14];
valid_settings = (GetCfgCrc16(settings_buffer, buffer_size) == buffer_crc16);
} }
valid_settings = (buffer_crc == crc);
} else { } else {
valid_settings = (settings_buffer[0] == CONFIG_FILE_SIGN); valid_settings = (settings_buffer[0] == CONFIG_FILE_SIGN);
} }

View File

@ -88,7 +88,7 @@ struct ENERGY {
unsigned long kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily unsigned long kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
unsigned long period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily unsigned long period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily
uint8_t tenth_second = 0; uint8_t fifth_second = 0;
uint8_t command_code = 0; uint8_t command_code = 0;
uint8_t data_valid = 0; uint8_t data_valid = 0;
@ -165,16 +165,13 @@ void EnergyUpdateTotal(float value, bool kwh)
/*********************************************************************************************/ /*********************************************************************************************/
void Energy100ms(void) void Energy200ms(void)
{ {
Energy.power_on = (power != 0) | Settings.flag.no_power_on_check; Energy.power_on = (power != 0) | Settings.flag.no_power_on_check;
Energy.tenth_second++; Energy.fifth_second++;
if (30 == Energy.tenth_second) { if (5 == Energy.fifth_second) {
Energy.tenth_second = 0; Energy.fifth_second = 0;
}
if ((Energy.tenth_second % 10) == 0) {
XnrgCall(FUNC_ENERGY_EVERY_SECOND); XnrgCall(FUNC_ENERGY_EVERY_SECOND);
@ -209,15 +206,9 @@ void Energy100ms(void)
} }
} }
if (Energy.tenth_second &1) {
XnrgCall(FUNC_EVERY_200_MSECOND); XnrgCall(FUNC_EVERY_200_MSECOND);
} }
if ((Energy.tenth_second % 3) == 0) {
XnrgCall(FUNC_EVERY_300_MSECOND);
}
}
void EnergySaveState(void) void EnergySaveState(void)
{ {
Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0; Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0;
@ -728,7 +719,7 @@ void EnergySnsInit(void)
Energy.kWhtoday_delta = 0; Energy.kWhtoday_delta = 0;
Energy.period = Energy.kWhtoday_offset; Energy.period = Energy.kWhtoday_offset;
EnergyUpdateToday(); EnergyUpdateToday();
ticker_energy.attach_ms(100, Energy100ms); ticker_energy.attach_ms(200, Energy200ms);
} }
} }
@ -907,6 +898,9 @@ bool Xdrv03(uint8_t function)
case FUNC_LOOP: case FUNC_LOOP:
XnrgCall(FUNC_LOOP); XnrgCall(FUNC_LOOP);
break; break;
case FUNC_EVERY_250_MSECOND:
XnrgCall(FUNC_EVERY_250_MSECOND);
break;
#ifdef USE_ENERGY_MARGIN_DETECTION #ifdef USE_ENERGY_MARGIN_DETECTION
case FUNC_SET_POWER: case FUNC_SET_POWER:
Energy.power_steady_counter = 2; Energy.power_steady_counter = 2;

View File

@ -78,7 +78,7 @@ struct SDM220 {
/*********************************************************************************************/ /*********************************************************************************************/
void SDM120Every300ms(void) void SDM120Every250ms(void)
{ {
bool data_ready = Sdm120Modbus->ReceiveReady(); bool data_ready = Sdm120Modbus->ReceiveReady();
@ -262,8 +262,8 @@ int Xnrg09(uint8_t function)
case FUNC_INIT: case FUNC_INIT:
Sdm120SnsInit(); Sdm120SnsInit();
break; break;
case FUNC_EVERY_300_MSECOND: case FUNC_EVERY_250_MSECOND:
if (uptime > 4) { SDM120Every300ms(); } if (uptime > 4) { SDM120Every250ms(); }
break; break;
#ifdef USE_SDM220 #ifdef USE_SDM220

568
sonoff/xsns_54_ina226.ino Normal file
View File

@ -0,0 +1,568 @@
/*
xsns_54_ina226.ino - INA226 Current Sensor support for Sonoff-Tasmota
Copyright (C) 2019 Stephen Rodgers and Theo Arends
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 <http://www.gnu.org/licenses/>.
*/
#ifdef USE_I2C
#ifdef USE_INA226
/*
* Setup a single INA226 device at address 0x40:
*
* 1. Select a module type with free I2C pins.
* 2. Configure the module to use I2C on the correct pins.
* 3. Connect your ina226 module(s) to the I2C pins.
* 4. Use the i2cscan console command to probe the modules and check they are present.
* 5. Enable the first device at I2C slave address 0x40 using the following console commands:
* a. Sensor54 11 [shunt resistance in ohms] e.g. Sensor54 11 0.1
* b. Sensor54 12 [full scale current in amperes] e.g. Sensor54 12 3.0
* c. Sensor54 2 saves the settings and restarts Tasmota. The device should show up after the system boots again.
*
* Device number to I2C slave address mapping
*
* 1 - 0x40
* 2 - 0x41
* 3 - 0x44
* 4 - 0x45
*
* This driver will not probe I2C bus for INA226 devices unless the full scale current is set for a device number.
* It will map device numbers as follows:
*
* To set shunt resistance and full scale current, use the Sensor54 command interface as follows:
*
* Sensor54 10 Return channel 1 shunt resistance and full scale current
* Sensor54 11 [shunt_resistance] Set INA226 channel 1 shunt resistance in ohms, floating point
* Sensor54 12 [full_scale_current] Set INA226 channel 1 full scale current in amperes, floating point
* Sensor54 20 Return channel 2 shunt resistance and full scale current
* Sensor54 21 [shunt_resistance] Set INA226 channel 2 shunt resistance in ohms, floating point
* Sensor54 22 [full_scale_current] Set INA226 channel 2 full scale current in amperes, floating point
* Sensor54 30 Return channel 3 shunt resistance and full scale current
* Sensor54 31 [shunt_resistance] Set INA226 channel 3 shunt resistance in ohms, floating point
* Sensor54 32 [full_scale_current] Set INA226 channel 3 full scale current in amperes, floating point
* Sensor54 40 Return channel 4 shunt resistance and full scale current
* Sensor54 41 [shunt_resistance] Set INA226 channel 4 shunt resistance in ohms, floating point
* Sensor54 42 [full_scale_current] Set INA226 channel 4 full scale current in amperes, floating point
*
* Other commands
*
* Sensor54 1 Rescan for devices and return the number of slaves found.
* Sensor54 2 Save the configuration and restart
*
*
*/
// Define driver ID
#define XSNS_54 54
#define INA226_MAX_ADDRESSES 4
#define INA226_ADDRESS1 (0x40) // 1000000 (A0+A1=GND)
#define INA226_ADDRESS2 (0x41) // 1000000 (A0=Vcc, A1=GND)
#define INA226_ADDRESS3 (0x44) // 1000000 (A0=GND, A1=Vcc)
#define INA226_ADDRESS4 (0x45) // 1000000 (A0+A1=Vcc)
#define INA226_REG_CONFIG (0x00) // Config register
#define INA226_RES_CONFIG (0x4127) // Config register at reset
#define INA226_DEF_CONFIG (0x42FF) // Our default configuration
#define INA226_CONFIG_RESET (0x8000) // Config register reset bit
#define INA226_REG_SHUNTVOLTAGE (0x01)
#define INA226_REG_BUSVOLTAGE (0x02)
#define INA226_REG_POWER (0x03)
#define INA226_REG_CURRENT (0x04)
#define INA226_REG_CALIBRATION (0x05)
typedef struct Ina226SlaveInfo_tag {
uint8_t address;
uint16_t calibrationValue;
uint16_t config;
uint8_t present : 1;
float i_lsb;
} Ina226SlaveInfo_t;
/*
* Program memory constants
*/
static const uint8_t PROGMEM probeAddresses[INA226_MAX_ADDRESSES] = {INA226_ADDRESS1, INA226_ADDRESS2, INA226_ADDRESS3, INA226_ADDRESS4};
/*
* Global Variables
*/
static char Ina226Str[] = "INA226";
static uint8_t slavesFound = 0;
static uint8_t schedule_reinit = 0;
static Ina226SlaveInfo_t slaveInfo[4] = {0};
//static uint16_t reinit_count[4];
static float voltages[4];
static float currents[4];
static float powers[4];
/*
* Log single floating point Number
*/
static void _debug_fval(const char *str, float fval, uint8_t prec = 4 )
{
char fstr[32];
dtostrfd(fval, prec, fstr);
AddLog_P2( LOG_LEVEL_NONE, PSTR("%s: %s"), str, fstr );
}
/*
* Convert 16 bit repesentation of shunt resisance to 32 bit micro ohms by looking at the msb range bit.
* If the msb is 1, the LSB's define the number of milli ohms. (Maximum shunt resistor value 32.767 ohms)
* If the msb is 0, the LSB's define the number of micro ohms. (Maximum shunt resistor value 0.032767 ohms)
*/
static uint32_t _expand_r_shunt(uint16_t compact_r_shunt)
{
uint32_t r_shunt_uohms = (compact_r_shunt & 0x8000) ?
(((uint32_t)(compact_r_shunt & 0x7FFF)) * 1000ul) :
(compact_r_shunt & 0x7FFF);
return r_shunt_uohms;
}
/*
* Set calibration value for Ina226
*/
void Ina226SetCalibration(uint8_t slaveIndex)
{
Ina226SlaveInfo_t *si = slaveInfo + slaveIndex;
I2cWrite16( si->address, INA226_REG_CALIBRATION, si->calibrationValue);
}
/*
* Test for presence of an Ina226
*/
bool Ina226TestPresence(uint8_t device)
{
// Read config
uint16_t config = I2cRead16( slaveInfo[device].address, INA226_REG_CONFIG );
//AddLog_P2( LOG_LEVEL_NONE, PSTR("Config register %04x" ), config);
if (config != slaveInfo[device].config)
return false;
return true;
}
/*
* Initialize INA226 devices
*/
void Ina226Init()
{
uint32_t i;
slavesFound = 0;
Ina226SlaveInfo_t *p = slaveInfo;
//AddLog_P2( LOG_LEVEL_NONE, "Ina226Init");
AddLog_P2( LOG_LEVEL_NONE, "Size of Settings: %d bytes", sizeof(Settings));
if (!i2c_flg)
AddLog_P2(LOG_LEVEL_DEBUG, "INA226: Initialization failed: No I2C support");
// Clear slave info data
for (i = 0; i < 4; i++){
*p = {0};
}
//AddLog_P2( LOG_LEVEL_NONE, PSTR("Sizeof Ina226Cfg: %d" ), sizeof(Ina226Cfg));
// Detect devices
for (i = 0; (i < INA226_MAX_ADDRESSES); i++){
uint8_t addr = pgm_read_byte(probeAddresses + i);
// Skip device probing if the full scale current is zero
//AddLog_P2( LOG_LEVEL_NONE, "fs_i[%d]: %d", i, Settings.ina226_i_fs[i]);
if (!Settings.ina226_i_fs[i])
continue;
//AddLog_P2( LOG_LEVEL_NONE, PSTR("INA226 trying slave address %02x" ), addr );
// Try Resetting the device
if (!I2cWrite16( addr, INA226_REG_CONFIG, INA226_CONFIG_RESET)){
AddLog_P2( LOG_LEVEL_DEBUG, "No INA226 at address: %02X", addr);
continue; // No device
}
// Read config
uint16_t config = I2cRead16( addr, INA226_REG_CONFIG );
//AddLog_P2( LOG_LEVEL_NONE, PSTR("INA226 Config register %04x" ), config);
if (INA226_RES_CONFIG != config)
continue;
config = INA226_DEF_CONFIG; // Fixme
// Set the default configuration
if (!I2cWrite16( addr, INA226_REG_CONFIG, config))
continue; // No device
// store data in slave info struct.
p = &slaveInfo[i];
// Address
p->address = addr;
// Configuration
p->config = config;
// Full scale current in tenths of an amp
//AddLog_P2( LOG_LEVEL_NONE, "Full Scale I in tenths of an amp: %u", Settings.ina226_i_fs[i]);
p->i_lsb = (((float) Settings.ina226_i_fs[i])/10.0f)/32768.0f;
//_debug_fval("i_lsb: %s", p->i_lsb, 7);
// Get shunt resistor value in micro ohms
uint32_t r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[i]);
//AddLog_P2( LOG_LEVEL_NONE, "Shunt R in micro-ohms: %u", r_shunt_uohms);
p->calibrationValue = ((uint16_t) (0.00512/(p->i_lsb * r_shunt_uohms/1000000.0f)));
// Device present
p->present = true;
//AddLog_P2( LOG_LEVEL_NONE, "INA226 Device %d calibration value: %04X", i, p->calibrationValue);
Ina226SetCalibration(i);
//AddLog_P2( LOG_LEVEL_NONE, S_LOG_I2C_FOUND_AT, Ina226Str, addr );
slavesFound++;
}
}
/*
* Read the bus voltage, and return it as a float
*/
float Ina226ReadBus_v(uint8_t device)
{
uint8_t addr = slaveInfo[device].address;
int16_t reg_bus_v = I2cReadS16( addr, INA226_REG_BUSVOLTAGE);
float result = ((float) reg_bus_v) * 0.00125f;
return result;
}
/*
* Read the shunt current, and return it as a float
*/
float Ina226ReadShunt_i(uint8_t device)
{
uint8_t addr = slaveInfo[device].address;
int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_CURRENT);
float result = ((float) reg_shunt_i) * slaveInfo[device].i_lsb;
return result;
}
/*
* Read the calculated power
*/
float Ina226ReadPower_w(uint8_t device)
{
uint8_t addr = slaveInfo[device].address;
int16_t reg_shunt_i = I2cReadS16( addr, INA226_REG_POWER);
float result = ((float) reg_shunt_i) * (slaveInfo[device].i_lsb * 25.0);
return result;
}
/*
* Read voltage, shunt voltage, current, and power registerd for a given device
*/
void Ina226Read(uint8_t device)
{
//AddLog_P2( LOG_LEVEL_NONE, "Ina226Read");
voltages[device] = Ina226ReadBus_v(device);
currents[device] = Ina226ReadShunt_i(device);
powers[device] = Ina226ReadPower_w(device);
//AddLog_P2( LOG_LEVEL_NONE, "INA226 Device %d", device );
//_debug_fval("Voltage", voltages[device]);
//_debug_fval("Current", currents[device]);
//_debug_fval("Power", powers[device]);
}
/*
* Poll sensors, and chack for sensor presence
*/
void Ina226EverySecond()
{
//AddLog_P2( LOG_LEVEL_NONE, "Ina226EverySecond");
for (uint8_t device = 0; device < INA226_MAX_ADDRESSES; device++){
// If there are slaves, and the device was present, and the device still is present, read its registers
if (slavesFound && slaveInfo[device].present && Ina226TestPresence(device)){
Ina226Read(device);
}
else {
powers[device] = currents[device] = voltages[device] = 0.0f;
// If device was present, note that it dropped off here
//if(slaveInfo[device].present){
//reinit_count[device]++;
//AddLog_P2( LOG_LEVEL_DEBUG, "INA226 Device %d dropped off, count: %d", device, reinit_count[device]);
//}
// Device no longer present
slaveInfo[device].present = false;
}
}
}
/*
* Decode a sensor command and act on it
*/
bool Ina226CommandSensor()
{
bool serviced = true;
bool show_config = false;
char param_str[64];
char *cp, *params[4];
uint8_t i, param_count, device, p1 = XdrvMailbox.payload;
uint32_t r_shunt_uohms;
uint16_t compact_r_shunt_uohms;
//AddLog_P2( LOG_LEVEL_NONE, "Command received: %d", XdrvMailbox.payload);
//AddLog_P2( LOG_LEVEL_NONE, "Command data received: %s", XdrvMailbox.data);
// Make a copy of the data and add another terminator
if (XdrvMailbox.data_len > 62){
return false;
}
strncpy(param_str, XdrvMailbox.data, XdrvMailbox.data_len + 1);
param_str[XdrvMailbox.data_len] = 0;
// Build parameter substrings (this should really be a helper function in support_command.ino)
for (cp = param_str, i = 0, param_count = 0; *cp && (i < XdrvMailbox.data_len + 1) && (param_count <= 3); i++)
if (param_str[i] == ' ' || param_str[i] == ',' || param_str[i] == 0){
param_str[i] = 0;
params[param_count] = cp;
//AddLog_P2( LOG_LEVEL_NONE, "INA226 Command parameter: %d, value: %s", param_count, params[param_count]);
param_count++;
cp = param_str + i + 1;
}
if (p1 < 10 || p1 >= 50){
// Device-less commands
switch (p1){
case 1: // Rerun init
Ina226Init();
Response_P(PSTR("{\"Sensor54-Command-Result\":{\"SlavesFound\":%d}}"),slavesFound);
break;
case 2: // Save and restart
restart_flag = 2;
Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Restart_flag\":%d}}"),restart_flag);
break;
default:
serviced = false;
}
}
else if (p1 < 50){
// Commands 10-49 tied to a particular device
device = (p1 / 10) - 1; // Leading Tens digit is device number {1-4}
switch (p1 % 10){
case 0: // Show config
show_config = true;
break;
case 1: // Set compacted shunt resistance from user input in ohms
r_shunt_uohms = (uint32_t) ((CharToFloat(params[1])) * 1000000.0f);
//AddLog_P2( LOG_LEVEL_NONE, "r_shunt_uohms: %d", r_shunt_uohms);
if (r_shunt_uohms > 32767){
uint32_t r_shunt_mohms = r_shunt_uohms/1000UL;
Settings.ina226_r_shunt[device] = (uint16_t) (r_shunt_mohms | 0x8000);
}
else
Settings.ina226_r_shunt[device] = (uint16_t) r_shunt_uohms;
//AddLog_P2( LOG_LEVEL_NONE, "r_shunt_compacted: %04X", Settings.ina226_r_shunt[device]);
show_config = true;
break;
case 2: // Set full scale current in tenths of amps from user input in Amps
Settings.ina226_i_fs[device] = (uint16_t) ((CharToFloat(params[1])) * 10.0f);
//AddLog_P2( LOG_LEVEL_NONE, "i_fs: %d", Settings.ina226_i_fs[device]);
show_config = true;
break;
default:
serviced = false;
break;
}
}
else
serviced = false;
if (show_config) {
char shunt_r_str[16];
char fs_i_str[16];
// Shunt resistance is stored in EEPROM in microohms. Convert to ohms
r_shunt_uohms = _expand_r_shunt(Settings.ina226_r_shunt[device]);
dtostrfd(((float)r_shunt_uohms)/1000000.0f, 6, shunt_r_str);
// Full scale current is stored in EEPROM in tenths of an amp. Convert to amps.
dtostrfd(((float)Settings.ina226_i_fs[device])/10.0f, 1, fs_i_str);
// Send json response
Response_P(PSTR("{\"Sensor54-device-settings-%d\":{\"SHUNT_R\":%s,\"FS_I\":%s}}"),
device + 1, shunt_r_str, fs_i_str);
}
return serviced;
}
/*
* Show data gathered from INA226 devices
*/
#ifdef USE_WEBSERVER
const char HTTP_SNS_INA226_DATA[] PROGMEM =
"{s}%s " D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"
"{s}%s " D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"
"{s}%s " D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}";
#endif // USE_WEBSERVER
void Ina226Show(bool json)
{
int i, num_found;
for (num_found = 0, i = 0; i < INA226_MAX_ADDRESSES; i++) {
// Skip uninstalled sensors
if (!slaveInfo[i].present)
continue;
num_found++;
char voltage[16];
dtostrfd(voltages[i], Settings.flag2.voltage_resolution, voltage);
char current[16];
dtostrfd(currents[i], Settings.flag2.current_resolution, current);
char power[16];
dtostrfd(powers[i], Settings.flag2.wattage_resolution, power);
char name[16];
snprintf_P(name, sizeof(name), PSTR("INA226%c%d"),IndexSeparator(), i + 1);
if (json) {
ResponseAppend_P(PSTR(",\"%s\":{\"Id\":%02x,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"),
name, i, voltage, current, power);
#ifdef USE_DOMOTICZ
if (0 == tele_period) {
DomoticzSensor(DZ_VOLTAGE, voltage);
DomoticzSensor(DZ_CURRENT, current);
}
#endif // USE_DOMOTICZ
#ifdef USE_WEBSERVER
} else {
WSContentSend_PD(HTTP_SNS_INA226_DATA, name, voltage, name, current, name, power);
#endif // USE_WEBSERVER)
}
}
}
/**
* The callback function Xsns_57() interfaces Tasmota with the sensor driver.
*
* It provides the Tasmota callback IDs.
*
* @param byte callback_id Tasmota function ID.
* @return bool Return value.
* @pre None.
* @post None.
*
*/
bool Xsns54(byte callback_id) {
// Set return value to `false`
bool result = false;
// Check if I2C interface mode is enabled
if(i2c_flg) {
// Check which callback ID is called by Tasmota
switch (callback_id) {
case FUNC_EVERY_SECOND:
Ina226EverySecond();
break;
case FUNC_INIT:
Ina226Init();
break;
case FUNC_JSON_APPEND:
Ina226Show(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
Ina226Show(0);
break;
#endif // USE_WEBSERVER
case FUNC_COMMAND_SENSOR:
if (XSNS_54 == XdrvMailbox.index) {
result = Ina226CommandSensor();
}
break;
}
} // if(i2c_flg)
// Return boolean result
return result;
}
#endif // USE_INA226
#endif // USE_I2C

View File

@ -86,17 +86,22 @@ a_setoption = [[
],[ ],[
"Key hold time (ms)", "Key hold time (ms)",
"Sonoff POW Max_Power_Retry", "Sonoff POW Max_Power_Retry",
"Tuya dimmer device id", "(not used) Tuya MCU device id",
"(not used) mDNS delayed start (Sec)", "(not used) mDNS delayed start (Sec)",
"Boot loop retry offset (0 = disable)", "Boot loop retry offset (0 = disable)",
"RGBWW remap", "RGBWW remap",
"IR Unknown threshold", "IR Unknown threshold",
"CSE7766 invalid power margin", "CSE7766 invalid power margin",
"Ignore hold time (s)", "Ignore hold time (s)",
"Number of Tuya relays", "(not used) Number of Tuya MCU relays",
"Over temperature threshold (celsius)", "Over temperature threshold (celsius)",
"Tuya MCU max dimmer value",
"(not used) Tuya MCU voltage Id",
"(not used) Tuya MCU current Id",
"(not used) Tuya MCU power Id",
"Energy Tariff1 start hour",
"Energy Tariff2 start hour",
"", "",
"","","","","","",
],[ ],[
"Timers enabled", "Timers enabled",
"Generic ESP8285 GPIO enabled", "Generic ESP8285 GPIO enabled",
@ -113,12 +118,13 @@ a_setoption = [[
"Do not use retain flag on HOLD messages", "Do not use retain flag on HOLD messages",
"Do not scan relay power state at restart", "Do not scan relay power state at restart",
"Use _ instead of - as sensor index separator", "Use _ instead of - as sensor index separator",
"Disable Dimmer slider control", "(not used) Disable Dimmer slider control",
"Disable Dimmer range 255 slider control", "Disable Dimmer range 255 slider control",
"Enable buzzer when available", "Enable buzzer when available",
"Enable multi-channels PWM instead of Color PWM", "Enable multi-channels PWM instead of Color PWM",
"", "Limits Tuya MCU dimmers to minimum of 10% (25) when enabled",
"","","","", "Enable Weekend Energy Tariff",
"","","",
"","","","", "","","","",
"","","","" "","","",""
]] ]]
@ -160,8 +166,8 @@ a_features = [[
"USE_ADE7953","USE_SPS30","USE_VL53L0X","USE_MLX90614", "USE_ADE7953","USE_SPS30","USE_VL53L0X","USE_MLX90614",
"USE_MAX31865","USE_CHIRP","USE_SOLAX_X1","USE_PAJ7620" "USE_MAX31865","USE_CHIRP","USE_SOLAX_X1","USE_PAJ7620"
],[ ],[
"USE_BUZZER","USE_RDM6300","USE_IBEACON","USE_A4988_Stepper", "USE_BUZZER","USE_RDM6300","USE_IBEACON","USE_SML_M",
"","","","", "USE_INA226","USE_A4988_Stepper","","",
"","","","", "","","","",
"","","","", "","","","",
"","","","", "","","","",