Merge branch 'development' into serial_115200

This commit is contained in:
Theo Arends 2019-09-08 12:49:21 +02:00 committed by GitHub
commit 1d39db76b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 627 additions and 44 deletions

View File

@ -1,6 +1,7 @@
/*********************************************************************************************\ /*********************************************************************************************\
* 6.6.0.11 20190907 * 6.6.0.11 20190907
* Change Settings crc calculation allowing short term backward compatibility * Change Settings crc calculation allowing short term backward compatibility
* Add support for up to 4 INA226 Voltage and Current sensors by Steve Rogers (#6342)
* Change Improve reliability of TasmotaSerial at 115200 bauds and reduce IRAM usage for Stage/pre-2.6 * Change Improve reliability of TasmotaSerial at 115200 bauds and reduce IRAM usage for Stage/pre-2.6
* *
* 6.6.0.10 20190905 * 6.6.0.10 20190905

View File

@ -341,6 +341,7 @@
// #define USE_ADS1115 // Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) based on Adafruit ADS1x15 library (no library needed) (+0k7 code) // #define USE_ADS1115 // Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) based on Adafruit ADS1x15 library (no library needed) (+0k7 code)
// #define USE_ADS1115_I2CDEV // Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code) // #define USE_ADS1115_I2CDEV // Enable ADS1115 16 bit A/D converter (I2C address 0x48, 0x49, 0x4A or 0x4B) using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code)
// #define USE_INA219 // Enable INA219 (I2C address 0x40, 0x41 0x44 or 0x45) Low voltage and current sensor (+1k code) // #define USE_INA219 // Enable INA219 (I2C address 0x40, 0x41 0x44 or 0x45) 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 // Enable SHT3x (I2C address 0x44 or 0x45) or SHTC3 (I2C address 0x70) sensor (+0k7 code) #define USE_SHT3X // Enable SHT3x (I2C address 0x44 or 0x45) or SHTC3 (I2C address 0x70) sensor (+0k7 code)
// #define USE_TSL2561 // Enable TSL2561 sensor (I2C address 0x29, 0x39 or 0x49) using library Joba_Tsl2561 (+2k3 code) // #define USE_TSL2561 // Enable TSL2561 sensor (I2C address 0x29, 0x39 or 0x49) using library Joba_Tsl2561 (+2k3 code)
// #define USE_MGS // Enable Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code) // #define USE_MGS // Enable Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code)

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

@ -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

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

View File

@ -2031,6 +2031,7 @@ void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) {
char *cp; char *cp;
uint16_t count; uint16_t count;
uint8_t vtype; uint8_t vtype;
uint8_t dprec=glob_script_mem.script_dprec;
float fvar; float fvar;
cp=srcbuf; cp=srcbuf;
struct T_INDEX ind; struct T_INDEX ind;
@ -2041,13 +2042,16 @@ void Replace_Cmd_Vars(char *srcbuf,char *dstbuf,uint16_t dstsize) {
if (*cp=='%') { if (*cp=='%') {
dstbuf[count]=*cp++; dstbuf[count]=*cp++;
} else { } else {
//char *scp=cp; if (isdigit(*cp)) {
dprec=*cp&0xf;
cp++;
}
cp=isvar(cp,&vtype,&ind,&fvar,string,0); cp=isvar(cp,&vtype,&ind,&fvar,string,0);
if (vtype!=VAR_NV) { if (vtype!=VAR_NV) {
// found variable as result // found variable as result
if (vtype==NUM_RES || (vtype&STYPE)==0) { if (vtype==NUM_RES || (vtype&STYPE)==0) {
// numeric result // numeric result
dtostrfd(fvar,glob_script_mem.script_dprec,string); dtostrfd(fvar,dprec,string);
} else { } else {
// string result // string result
} }
@ -2650,7 +2654,7 @@ int16_t Run_Scripter(const char *type, int8_t tlen, char *js) {
switch (lastop) { switch (lastop) {
case OPER_EQU: case OPER_EQU:
if (glob_script_mem.var_not_found) { if (glob_script_mem.var_not_found) {
if (!js) toLog("var not found\n"); if (!js) toLogEOL("var not found: ",lp);
goto next_line; goto next_line;
} }
*dfvar=fvar; *dfvar=fvar;
@ -3587,7 +3591,7 @@ void ScriptWebShow(void) {
if (!*lp || *lp=='#' || *lp=='>') { if (!*lp || *lp=='#' || *lp=='>') {
break; break;
} }
if (*lp!=';') {
// send this line to web // send this line to web
memcpy(line,lp,sizeof(line)); memcpy(line,lp,sizeof(line));
line[sizeof(line)-1]=0; line[sizeof(line)-1]=0;
@ -3599,11 +3603,9 @@ void ScriptWebShow(void) {
} }
cp++; cp++;
} }
Replace_Cmd_Vars(line,tmp,sizeof(tmp)); Replace_Cmd_Vars(line,tmp,sizeof(tmp));
WSContentSend_PD(PSTR("{s}%s{e}"),tmp); WSContentSend_PD(PSTR("{s}%s{e}"),tmp);
}
next_line:
if (*lp==SCRIPT_EOL) { if (*lp==SCRIPT_EOL) {
lp++; lp++;
} else { } else {
@ -3630,7 +3632,7 @@ void ScriptJsonAppend(void) {
if (!*lp || *lp=='#' || *lp=='>') { if (!*lp || *lp=='#' || *lp=='>') {
break; break;
} }
if (*lp!=';') {
// send this line to mqtt // send this line to mqtt
memcpy(line,lp,sizeof(line)); memcpy(line,lp,sizeof(line));
line[sizeof(line)-1]=0; line[sizeof(line)-1]=0;
@ -3642,11 +3644,9 @@ void ScriptJsonAppend(void) {
} }
cp++; cp++;
} }
Replace_Cmd_Vars(line,tmp,sizeof(tmp)); Replace_Cmd_Vars(line,tmp,sizeof(tmp));
ResponseAppend_P(PSTR("%s"),tmp); ResponseAppend_P(PSTR("%s"),tmp);
}
next_line:
if (*lp==SCRIPT_EOL) { if (*lp==SCRIPT_EOL) {
lp++; lp++;
} else { } else {

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_BUZZER","USE_RDM6300","USE_IBEACON","USE_SML_M",
"","","","", "USE_INA226","","","",
"","","","", "","","","",
"","","","", "","","","",
"","","","", "","","","",