mirror of https://github.com/arendst/Tasmota.git
Merge branch 'A4988_Stepper' of https://github.com/Leuselator/Sonoff-Tasmota into A4988_Stepper
This commit is contained in:
commit
2345828b39
|
@ -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
|
||||
* Redesign Tuya support by Shantur Rathore (#6353)
|
||||
* Add command Reset 99 to reset bootcount to zero (#684, #6351)
|
||||
|
|
|
@ -147,9 +147,9 @@
|
|||
#define D_START "Start"
|
||||
#define D_STD_TIME "STD"
|
||||
#define D_STOP "Stop"
|
||||
#define D_SUBNET_MASK "Maschera sottorete"
|
||||
#define D_SUBNET_MASK "Maschera Subnet"
|
||||
#define D_SUBSCRIBE_TO "Sottoscrivi a"
|
||||
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
|
||||
#define D_UNSUBSCRIBE_FROM "Cancella da"
|
||||
#define D_SUCCESSFUL "Riuscito"
|
||||
#define D_SUNRISE "Alba"
|
||||
#define D_SUNSET "Tramonto"
|
||||
|
@ -161,16 +161,16 @@
|
|||
#define D_TRANSMIT "Trasmesso"
|
||||
#define D_TRUE "Vero"
|
||||
#define D_TVOC "TVOC"
|
||||
#define D_UPGRADE "aggiornamento"
|
||||
#define D_UPGRADE "Aggiornamento"
|
||||
#define D_UPLOAD "Invio"
|
||||
#define D_UPTIME "Uptime"
|
||||
#define D_USER "Utente"
|
||||
#define D_UTC_TIME "UTC"
|
||||
#define D_UV_INDEX "Indice UV"
|
||||
#define D_UV_INDEX_1 "Low"
|
||||
#define D_UV_INDEX_2 "Mid"
|
||||
#define D_UV_INDEX_3 "High"
|
||||
#define D_UV_INDEX_4 "Danger"
|
||||
#define D_UV_INDEX_1 "Basso"
|
||||
#define D_UV_INDEX_2 "Medio"
|
||||
#define D_UV_INDEX_3 "Alto"
|
||||
#define D_UV_INDEX_4 "Pericolo"
|
||||
#define D_UV_INDEX_5 "BurnL1/2"
|
||||
#define D_UV_INDEX_6 "BurnL3"
|
||||
#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_LEVEL_10 "level 1-0"
|
||||
#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_SET_BAUDRATE_TO "Baudrate impostato a"
|
||||
|
@ -198,11 +198,11 @@
|
|||
#define D_OSWATCH "osWatch"
|
||||
#define D_BLOCKED_LOOP "Ciclo Bloccato"
|
||||
#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_PATCH_ISSUE_2186 "Patch issue 2186"
|
||||
#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_AP_NOT_REACHED "Connessione fallita, AP non raggiungibile"
|
||||
#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_ADC "ADC"
|
||||
#define D_GPIO "GPIO"
|
||||
#define D_SERIAL_IN "Serial In"
|
||||
#define D_SERIAL_OUT "Serial Out"
|
||||
#define D_SERIAL_IN "Seriale In"
|
||||
#define D_SERIAL_OUT "Seriale Out"
|
||||
|
||||
#define D_WIFI_PARAMETERS "Parametri Wifi"
|
||||
#define D_SCAN_FOR_WIFI_NETWORKS "Scansione delle reti wifi"
|
||||
|
@ -283,30 +283,30 @@
|
|||
#define D_FULL_TOPIC "Full Topic"
|
||||
|
||||
#define D_LOGGING_PARAMETERS "Parametri Logging"
|
||||
#define D_SERIAL_LOG_LEVEL "Seriale livello di log"
|
||||
#define D_WEB_LOG_LEVEL "Web livello di log"
|
||||
#define D_SYS_LOG_LEVEL "Sys livello di log"
|
||||
#define D_SERIAL_LOG_LEVEL "Livello di log Seriale"
|
||||
#define D_WEB_LOG_LEVEL "livello di log Web"
|
||||
#define D_SYS_LOG_LEVEL "livello di log Sys"
|
||||
#define D_MORE_DEBUG "Debug aggiuntivo"
|
||||
#define D_SYSLOG_HOST "Syslog host"
|
||||
#define D_SYSLOG_PORT "Syslog porta"
|
||||
#define D_TELEMETRY_PERIOD "Periodo Telemetria"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Altri parametri"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_TEMPLATE "Modello"
|
||||
#define D_ACTIVATE "Attivare"
|
||||
#define D_WEB_ADMIN_PASSWORD "Password Amministratore Web"
|
||||
#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_HUE_BRIDGE "Hue Bridge"
|
||||
#define D_SINGLE_DEVICE "dispositivo singolo"
|
||||
#define D_MULTI_DEVICE "dispositivo multiplo"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_CONFIGURE_TEMPLATE "Configurare Modello"
|
||||
#define D_TEMPLATE_PARAMETERS "Parametri Modello"
|
||||
#define D_TEMPLATE_NAME "Nome"
|
||||
#define D_BASE_TYPE "Baseto nel"
|
||||
#define D_TEMPLATE_FLAGS "Opzioni"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Salva configurazione"
|
||||
#define D_CONFIGURATION_SAVED "Configurazione salvata"
|
||||
|
@ -464,12 +464,12 @@
|
|||
#define D_PARTICALS_BEYOND "Particelle"
|
||||
|
||||
// xsns_32_mpu6050.ino
|
||||
#define D_AX_AXIS "Accel. X-Axis"
|
||||
#define D_AY_AXIS "Accel. Y-Axis"
|
||||
#define D_AZ_AXIS "Accel. Z-Axis"
|
||||
#define D_GX_AXIS "Gyro X-Axis"
|
||||
#define D_GY_AXIS "Gyro Y-Axis"
|
||||
#define D_GZ_AXIS "Gyro Z-Axis"
|
||||
#define D_AX_AXIS "Accel. Asse-X"
|
||||
#define D_AY_AXIS "Accel. Asse-Y"
|
||||
#define D_AZ_AXIS "Accel. Asse-Z"
|
||||
#define D_GX_AXIS "Gyro Asse-X"
|
||||
#define D_GY_AXIS "Gyro Asse-Y"
|
||||
#define D_GZ_AXIS "Gyro Asse-Z"
|
||||
|
||||
// xsns_34_hx711.ino
|
||||
#define D_HX_CAL_REMOVE "Rimuovere peso"
|
||||
|
|
|
@ -65,8 +65,8 @@
|
|||
#define D_BY "por" // Write by me
|
||||
#define D_BYTES "Bytes"
|
||||
#define D_CELSIUS "Celsius"
|
||||
#define D_CHANNEL "Channel"
|
||||
#define D_CO2 "Dióxido de carbono"
|
||||
#define D_CHANNEL "Canal"
|
||||
#define D_CO2 "CO2"
|
||||
#define D_CODE "Código" // Button code
|
||||
#define D_COLDLIGHT "Luz fria"
|
||||
#define D_COMMAND "Comando"
|
||||
|
@ -93,14 +93,14 @@
|
|||
#define D_FALLBACK_TOPIC "Tópico para retornar"
|
||||
#define D_FALSE "Falso"
|
||||
#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_FREQUENCY "Frequência"
|
||||
#define D_GAS "Gás"
|
||||
#define D_GATEWAY "Gateway"
|
||||
#define D_GROUP "Grupo"
|
||||
#define D_HOST "Anfitrião"
|
||||
#define D_HOSTNAME "Nome do anfitrião"
|
||||
#define D_HOST "Host"
|
||||
#define D_HOSTNAME "Nome do Host"
|
||||
#define D_HUMIDITY "Umidade"
|
||||
#define D_ILLUMINANCE "Luminância"
|
||||
#define D_IMMEDIATE "Imediato" // Button immediate
|
||||
|
@ -167,10 +167,10 @@
|
|||
#define D_USER "Usuário"
|
||||
#define D_UTC_TIME "UTC"
|
||||
#define D_UV_INDEX "Índice UV"
|
||||
#define D_UV_INDEX_1 "Low"
|
||||
#define D_UV_INDEX_2 "Mid"
|
||||
#define D_UV_INDEX_3 "High"
|
||||
#define D_UV_INDEX_4 "Danger"
|
||||
#define D_UV_INDEX_1 "Baixo"
|
||||
#define D_UV_INDEX_2 "Médio"
|
||||
#define D_UV_INDEX_3 "Alto"
|
||||
#define D_UV_INDEX_4 "Perigro"
|
||||
#define D_UV_INDEX_5 "BurnL1/2"
|
||||
#define D_UV_INDEX_6 "BurnL3"
|
||||
#define D_UV_INDEX_7 "OoR"
|
||||
|
@ -178,7 +178,7 @@
|
|||
#define D_UV_POWER "UV Power"
|
||||
#define D_VERSION "Versão"
|
||||
#define D_VOLTAGE "Voltagem"
|
||||
#define D_WEIGHT "Weight"
|
||||
#define D_WEIGHT "Peso"
|
||||
#define D_WARMLIGHT "Luz quente"
|
||||
#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_LEVEL_10 "nível 1-0"
|
||||
#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_SET_BAUDRATE_TO "Ajuste da velocidade para"
|
||||
|
@ -292,7 +292,7 @@
|
|||
#define D_TELEMETRY_PERIOD "Período de telemetria"
|
||||
|
||||
#define D_OTHER_PARAMETERS "Outros parâmetros"
|
||||
#define D_TEMPLATE "Template"
|
||||
#define D_TEMPLATE "Modelo"
|
||||
#define D_ACTIVATE "Activate"
|
||||
#define D_WEB_ADMIN_PASSWORD "Senha de WEB Admin"
|
||||
#define D_MQTT_ENABLE "MQTT habilitado"
|
||||
|
@ -302,11 +302,11 @@
|
|||
#define D_SINGLE_DEVICE "Dispositivo único"
|
||||
#define D_MULTI_DEVICE "Múltiplos dispositivos"
|
||||
|
||||
#define D_CONFIGURE_TEMPLATE "Configure Template"
|
||||
#define D_TEMPLATE_PARAMETERS "Template parameters"
|
||||
#define D_TEMPLATE_NAME "Name"
|
||||
#define D_BASE_TYPE "Based on"
|
||||
#define D_TEMPLATE_FLAGS "Options"
|
||||
#define D_CONFIGURE_TEMPLATE "Configurar Modelo"
|
||||
#define D_TEMPLATE_PARAMETERS "Parâmetros Modelo"
|
||||
#define D_TEMPLATE_NAME "Nome"
|
||||
#define D_BASE_TYPE "Baseado em"
|
||||
#define D_TEMPLATE_FLAGS "Opções"
|
||||
|
||||
#define D_SAVE_CONFIGURATION "Gravar configuração"
|
||||
#define D_CONFIGURATION_SAVED "Configuração gravada"
|
||||
|
@ -347,10 +347,10 @@
|
|||
#define D_UPLOAD_ERR_7 "Envio cancelado"
|
||||
#define D_UPLOAD_ERR_8 "Arquivo inválido"
|
||||
#define D_UPLOAD_ERR_9 "Arquivo muito grande"
|
||||
#define D_UPLOAD_ERR_10 "Failed to init RF chip"
|
||||
#define D_UPLOAD_ERR_11 "Failed to erase RF chip"
|
||||
#define D_UPLOAD_ERR_12 "Failed to write to RF chip"
|
||||
#define D_UPLOAD_ERR_13 "Failed to decode RF firmware"
|
||||
#define D_UPLOAD_ERR_10 "Falha ao iniciar chip RF"
|
||||
#define D_UPLOAD_ERR_11 "Falha ao apagar o chip RF"
|
||||
#define D_UPLOAD_ERR_12 "Falha ao escrever o chip RF"
|
||||
#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_ENTER_COMMAND "Inserir comando"
|
||||
|
@ -472,27 +472,27 @@
|
|||
#define D_GZ_AXIS "Gyro Z-Axis"
|
||||
|
||||
// xsns_34_hx711.ino
|
||||
#define D_HX_CAL_REMOVE "Remove weigth"
|
||||
#define D_HX_CAL_REFERENCE "Load reference weigth"
|
||||
#define D_HX_CAL_DONE "Calibrated"
|
||||
#define D_HX_CAL_FAIL "Calibration failed"
|
||||
#define D_RESET_HX711 "Reset Scale"
|
||||
#define D_CONFIGURE_HX711 "Configure Scale"
|
||||
#define D_HX711_PARAMETERS "Scale parameters"
|
||||
#define D_ITEM_WEIGHT "Item weight"
|
||||
#define D_REFERENCE_WEIGHT "Reference weigth"
|
||||
#define D_CALIBRATE "Calibrate"
|
||||
#define D_CALIBRATION "Calibration"
|
||||
#define D_HX_CAL_REMOVE "Remover peso"
|
||||
#define D_HX_CAL_REFERENCE "Peso de referência de carga"
|
||||
#define D_HX_CAL_DONE "Calibrado"
|
||||
#define D_HX_CAL_FAIL "Falha na calibração"
|
||||
#define D_RESET_HX711 "Redefinir escala"
|
||||
#define D_CONFIGURE_HX711 "Configurar escala"
|
||||
#define D_HX711_PARAMETERS "Parâmetros de escala"
|
||||
#define D_ITEM_WEIGHT "Peso do Item"
|
||||
#define D_REFERENCE_WEIGHT "Peso de referência"
|
||||
#define D_CALIBRATE "Calibrar"
|
||||
#define D_CALIBRATION "Calibração"
|
||||
|
||||
//xsns_35_tx20.ino
|
||||
#define D_TX20_WIND_DIRECTION "Wind Direction"
|
||||
#define D_TX20_WIND_SPEED "Wind Speed"
|
||||
#define D_TX20_WIND_SPEED_AVG "Wind Speed Avg"
|
||||
#define D_TX20_WIND_SPEED_MAX "Wind Speed Max"
|
||||
#define D_TX20_WIND_DIRECTION "Direção do vento"
|
||||
#define D_TX20_WIND_SPEED "Velocidade do vento"
|
||||
#define D_TX20_WIND_SPEED_AVG "Velocidade média do vento"
|
||||
#define D_TX20_WIND_SPEED_MAX "Velocidade do vento Máxima"
|
||||
#define D_TX20_NORTH "N"
|
||||
#define D_TX20_EAST "E"
|
||||
#define D_TX20_EAST "L"
|
||||
#define D_TX20_SOUTH "S"
|
||||
#define D_TX20_WEST "W"
|
||||
#define D_TX20_WEST "O"
|
||||
|
||||
//xsns_43_hre.ino
|
||||
#define D_LOG_HRE "HRE: "
|
||||
|
@ -663,37 +663,37 @@
|
|||
#define D_LOG_WIFI "WIF: " // Wifi
|
||||
|
||||
//SDM220
|
||||
#define D_PHASE_ANGLE "Phase Angle"
|
||||
#define D_IMPORT_ACTIVE "Import Active"
|
||||
#define D_EXPORT_ACTIVE "Export Active"
|
||||
#define D_IMPORT_REACTIVE "Import Reactive"
|
||||
#define D_EXPORT_REACTIVE "Export Reactive"
|
||||
#define D_TOTAL_REACTIVE "Total Reactive"
|
||||
#define D_PHASE_ANGLE "Ângulo de Fase"
|
||||
#define D_IMPORT_ACTIVE "Importar Ativo"
|
||||
#define D_EXPORT_ACTIVE "Exportar Ativo"
|
||||
#define D_IMPORT_REACTIVE "Importar Reativo"
|
||||
#define D_EXPORT_REACTIVE "Exportar Reativo"
|
||||
#define D_TOTAL_REACTIVE "Reativo total"
|
||||
#define D_UNIT_KWARH "kVArh"
|
||||
#define D_UNIT_ANGLE "Deg"
|
||||
|
||||
//SOLAXX1
|
||||
#define D_PV1_VOLTAGE "PV1 Voltage"
|
||||
#define D_PV1_CURRENT "PV1 Current"
|
||||
#define D_PV1_POWER "PV1 Power"
|
||||
#define D_PV2_VOLTAGE "PV2 Voltage"
|
||||
#define D_PV2_CURRENT "PV2 Current"
|
||||
#define D_PV2_POWER "PV2 Power"
|
||||
#define D_SOLAR_POWER "Solar Power"
|
||||
#define D_INVERTER_POWER "Inverter Power"
|
||||
#define D_PV1_VOLTAGE "PV1 Voltagem"
|
||||
#define D_PV1_CURRENT "PV1 Corrente"
|
||||
#define D_PV1_POWER "PV1 Energia"
|
||||
#define D_PV2_VOLTAGE "PV2 Voltagem"
|
||||
#define D_PV2_CURRENT "PV2 Corrente"
|
||||
#define D_PV2_POWER "PV2 Energia"
|
||||
#define D_SOLAR_POWER "Energia Solar"
|
||||
#define D_INVERTER_POWER "Potência do Inversor"
|
||||
#define D_STATUS "Status"
|
||||
#define D_WAITING "Waiting"
|
||||
#define D_CHECKING "Checking"
|
||||
#define D_WORKING "Working"
|
||||
#define D_FAILURE "Failure"
|
||||
#define D_SOLAX_ERROR_0 "No Error Code"
|
||||
#define D_SOLAX_ERROR_1 "Grid Lost Fault"
|
||||
#define D_SOLAX_ERROR_2 "Grid Voltage Fault"
|
||||
#define D_SOLAX_ERROR_3 "Grid Frequency Fault"
|
||||
#define D_SOLAX_ERROR_4 "Pv Voltage Fault"
|
||||
#define D_SOLAX_ERROR_5 "Isolation Fault"
|
||||
#define D_SOLAX_ERROR_6 "Over Temperature Fault"
|
||||
#define D_SOLAX_ERROR_7 "Fan Fault"
|
||||
#define D_SOLAX_ERROR_8 "Other Device Fault"
|
||||
#define D_WAITING "Esperando"
|
||||
#define D_CHECKING "Verificando"
|
||||
#define D_WORKING "Trabalhando"
|
||||
#define D_FAILURE "Falha"
|
||||
#define D_SOLAX_ERROR_0 "Nenhum código de erro"
|
||||
#define D_SOLAX_ERROR_1 "Erro Grid Perdida"
|
||||
#define D_SOLAX_ERROR_2 "Falha na Tensão da rede"
|
||||
#define D_SOLAX_ERROR_3 "Falha na Frequência do Grid"
|
||||
#define D_SOLAX_ERROR_4 "Pv Falha de Tensão"
|
||||
#define D_SOLAX_ERROR_5 "Falha de Isolamento"
|
||||
#define D_SOLAX_ERROR_6 "Falha de Temperatura excessiva"
|
||||
#define D_SOLAX_ERROR_7 "Falha no Ventilador"
|
||||
#define D_SOLAX_ERROR_8 "Outra falha do dispositivo"
|
||||
|
||||
#endif // _LANGUAGE_PT_BR_H_
|
||||
|
|
|
@ -373,8 +373,10 @@ struct SYSCFG {
|
|||
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
|
||||
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_crc32; // FFC
|
||||
|
|
|
@ -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)
|
||||
|
||||
uint32_t settings_location = SETTINGS_LOCATION;
|
||||
//uint32_t settings_crc32 = 0;
|
||||
uint16_t settings_crc = 0;
|
||||
uint32_t settings_crc32 = 0;
|
||||
uint8_t *settings_buffer = nullptr;
|
||||
|
||||
/********************************************************************************************/
|
||||
|
@ -319,27 +318,29 @@ bool SettingsBufferAlloc(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
uint16_t GetSettingsCrc(void)
|
||||
uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size)
|
||||
{
|
||||
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++) {
|
||||
if ((i < 14) || (i > 15)) { crc += bytes[i]*(i+1); } // Skip 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
|
||||
uint32_t crc = 0;
|
||||
uint8_t *bytes = (uint8_t*)&Settings;
|
||||
|
||||
uint32_t length = sizeof(SYSCFG) -4; // Skip crc
|
||||
while (length--) {
|
||||
while (size--) {
|
||||
crc ^= *bytes++;
|
||||
for (uint32_t j = 0; j < 8; j++) {
|
||||
crc = (crc >> 1) ^ (-int(crc & 1) & 0xEDB88320);
|
||||
|
@ -348,6 +349,11 @@ uint32_t GetSettingsCrc32(void)
|
|||
return ~crc;
|
||||
}
|
||||
|
||||
uint32_t GetSettingsCrc32(void)
|
||||
{
|
||||
return GetCfgCrc32((uint8_t*)&Settings, sizeof(SYSCFG) -4); // Skip crc32
|
||||
}
|
||||
|
||||
void SettingsSaveAll(void)
|
||||
{
|
||||
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)
|
||||
*/
|
||||
#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)
|
||||
stop_flash_rotate = 1;
|
||||
}
|
||||
|
@ -395,6 +401,7 @@ void SettingsSave(uint8_t rotate)
|
|||
settings_location = SETTINGS_LOCATION;
|
||||
}
|
||||
}
|
||||
|
||||
Settings.save_flag++;
|
||||
if (UtcTime() > START_VALID_TIME) {
|
||||
Settings.cfg_timestamp = UtcTime();
|
||||
|
@ -402,8 +409,8 @@ void SettingsSave(uint8_t rotate)
|
|||
Settings.cfg_timestamp++;
|
||||
}
|
||||
Settings.cfg_size = sizeof(SYSCFG);
|
||||
// Settings.cfg_crc32 = GetSettingsCrc32();
|
||||
Settings.cfg_crc = GetSettingsCrc();
|
||||
Settings.cfg_crc = GetSettingsCrc(); // Keep for backward compatibility in case of fall-back just after upgrade
|
||||
Settings.cfg_crc32 = GetSettingsCrc32();
|
||||
|
||||
ESP.flashEraseSector(settings_location);
|
||||
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));
|
||||
|
||||
settings_crc = Settings.cfg_crc;
|
||||
// settings_crc32 = Settings.cfg_crc32;
|
||||
settings_crc32 = Settings.cfg_crc32;
|
||||
}
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
RtcSettingsSave();
|
||||
|
@ -443,7 +449,10 @@ void SettingsLoad(void)
|
|||
|
||||
bool valid = false;
|
||||
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
|
||||
if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active 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
|
||||
SettingsDefault();
|
||||
}
|
||||
settings_crc = GetSettingsCrc();
|
||||
settings_crc32 = GetSettingsCrc32();
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
|
||||
RtcSettingsLoad();
|
||||
|
|
|
@ -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_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_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_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)
|
||||
|
|
|
@ -20,6 +20,6 @@
|
|||
#ifndef _SONOFF_VERSION_H_
|
||||
#define _SONOFF_VERSION_H_
|
||||
|
||||
const uint32_t VERSION = 0x0606000A;
|
||||
const uint32_t VERSION = 0x0606000B;
|
||||
|
||||
#endif // _SONOFF_VERSION_H_
|
||||
|
|
|
@ -438,12 +438,15 @@ void GetFeatures(void)
|
|||
#ifdef USE_IBEACON
|
||||
feature5 |= 0x00000004; // xsns_52_ibeacon.ino
|
||||
#endif
|
||||
#ifdef USE_A4988_Stepper
|
||||
feature5 |= 0x00000008; // xdrv_25_A4988.ino
|
||||
#ifdef USE_SML_M
|
||||
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
|
||||
|
||||
// feature5 |= 0x00000010;
|
||||
// feature5 |= 0x00000020;
|
||||
// feature5 |= 0x00000040;
|
||||
// feature5 |= 0x00000080;
|
||||
|
||||
|
|
|
@ -1687,8 +1687,8 @@ void HandleBackupConfiguration(void)
|
|||
|
||||
WSSend(200, CT_STREAM, "");
|
||||
|
||||
uint16_t cfg_crc = Settings.cfg_crc;
|
||||
Settings.cfg_crc = GetSettingsCrc(); // Calculate crc (again) as it might be wrong when savedata = 0 (#3918)
|
||||
uint32_t cfg_crc32 = Settings.cfg_crc32;
|
||||
Settings.cfg_crc32 = GetSettingsCrc32(); // Calculate crc (again) as it might be wrong when savedata = 0 (#3918)
|
||||
|
||||
memcpy(settings_buffer, &Settings, sizeof(Settings));
|
||||
if (Web.config_xor_on_set) {
|
||||
|
@ -1708,7 +1708,7 @@ void HandleBackupConfiguration(void)
|
|||
|
||||
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];
|
||||
if (buffer_version > 0x06000000) {
|
||||
uint32_t buffer_size = settings_buffer[3] << 8 | settings_buffer[2];
|
||||
uint16_t buffer_crc = settings_buffer[15] << 8 | settings_buffer[14];
|
||||
uint16_t crc = 0;
|
||||
for (uint32_t i = 0; i < buffer_size; i++) {
|
||||
if ((i < 14) || (i > 15)) { crc += settings_buffer[i]*(i+1); } // Skip crc
|
||||
if (buffer_version > 0x0606000A) {
|
||||
uint32_t buffer_crc32 = settings_buffer[4095] << 24 | settings_buffer[4094] << 16 | settings_buffer[4093] << 8 | settings_buffer[4092];
|
||||
valid_settings = (GetCfgCrc32(settings_buffer, buffer_size -4) == buffer_crc32);
|
||||
} 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 {
|
||||
valid_settings = (settings_buffer[0] == CONFIG_FILE_SIGN);
|
||||
}
|
||||
|
|
|
@ -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 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 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.tenth_second++;
|
||||
if (30 == Energy.tenth_second) {
|
||||
Energy.tenth_second = 0;
|
||||
}
|
||||
|
||||
if ((Energy.tenth_second % 10) == 0) {
|
||||
Energy.fifth_second++;
|
||||
if (5 == Energy.fifth_second) {
|
||||
Energy.fifth_second = 0;
|
||||
|
||||
XnrgCall(FUNC_ENERGY_EVERY_SECOND);
|
||||
|
||||
|
@ -209,15 +206,9 @@ void Energy100ms(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (Energy.tenth_second &1) {
|
||||
XnrgCall(FUNC_EVERY_200_MSECOND);
|
||||
}
|
||||
|
||||
if ((Energy.tenth_second % 3) == 0) {
|
||||
XnrgCall(FUNC_EVERY_300_MSECOND);
|
||||
}
|
||||
}
|
||||
|
||||
void EnergySaveState(void)
|
||||
{
|
||||
Settings.energy_kWhdoy = (RtcTime.valid) ? RtcTime.day_of_year : 0;
|
||||
|
@ -728,7 +719,7 @@ void EnergySnsInit(void)
|
|||
Energy.kWhtoday_delta = 0;
|
||||
Energy.period = Energy.kWhtoday_offset;
|
||||
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:
|
||||
XnrgCall(FUNC_LOOP);
|
||||
break;
|
||||
case FUNC_EVERY_250_MSECOND:
|
||||
XnrgCall(FUNC_EVERY_250_MSECOND);
|
||||
break;
|
||||
#ifdef USE_ENERGY_MARGIN_DETECTION
|
||||
case FUNC_SET_POWER:
|
||||
Energy.power_steady_counter = 2;
|
||||
|
|
|
@ -78,7 +78,7 @@ struct SDM220 {
|
|||
|
||||
/*********************************************************************************************/
|
||||
|
||||
void SDM120Every300ms(void)
|
||||
void SDM120Every250ms(void)
|
||||
{
|
||||
bool data_ready = Sdm120Modbus->ReceiveReady();
|
||||
|
||||
|
@ -262,8 +262,8 @@ int Xnrg09(uint8_t function)
|
|||
case FUNC_INIT:
|
||||
Sdm120SnsInit();
|
||||
break;
|
||||
case FUNC_EVERY_300_MSECOND:
|
||||
if (uptime > 4) { SDM120Every300ms(); }
|
||||
case FUNC_EVERY_250_MSECOND:
|
||||
if (uptime > 4) { SDM120Every250ms(); }
|
||||
break;
|
||||
|
||||
#ifdef USE_SDM220
|
||||
|
|
|
@ -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
|
|
@ -86,17 +86,22 @@ a_setoption = [[
|
|||
],[
|
||||
"Key hold time (ms)",
|
||||
"Sonoff POW Max_Power_Retry",
|
||||
"Tuya dimmer device id",
|
||||
"(not used) Tuya MCU device id",
|
||||
"(not used) mDNS delayed start (Sec)",
|
||||
"Boot loop retry offset (0 = disable)",
|
||||
"RGBWW remap",
|
||||
"IR Unknown threshold",
|
||||
"CSE7766 invalid power margin",
|
||||
"Ignore hold time (s)",
|
||||
"Number of Tuya relays",
|
||||
"(not used) Number of Tuya MCU relays",
|
||||
"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",
|
||||
"Generic ESP8285 GPIO enabled",
|
||||
|
@ -113,12 +118,13 @@ a_setoption = [[
|
|||
"Do not use retain flag on HOLD messages",
|
||||
"Do not scan relay power state at restart",
|
||||
"Use _ instead of - as sensor index separator",
|
||||
"Disable Dimmer slider control",
|
||||
"(not used) Disable Dimmer slider control",
|
||||
"Disable Dimmer range 255 slider control",
|
||||
"Enable buzzer when available",
|
||||
"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_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","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
"","","","",
|
||||
|
|
Loading…
Reference in New Issue