Sync to testing branch

This commit is contained in:
srodgers 2019-09-05 08:20:40 -07:00
parent 407be4075f
commit 553c5e4a9c
2 changed files with 77 additions and 41 deletions

View File

@ -186,11 +186,6 @@ typedef struct {
uint32_t last_return_kWhtotal; uint32_t last_return_kWhtotal;
} EnergyUsage; } EnergyUsage;
typedef struct INA226CF {
uint32_t r_shunt;
uint16_t i_fs;
}Ina226CF;
/* /*
struct SYSCFG { struct SYSCFG {
unsigned long cfg_holder; // 000 Pre v6 header unsigned long cfg_holder; // 000 Pre v6 header
@ -372,9 +367,10 @@ struct SYSCFG {
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
uint8_t data8[32]; // E00 uint8_t data8[32]; // E00
uint16_t data16[16]; // E20 uint16_t data16[16]; // E20
Ina226CF ina226_config[4]; // E40 uint16_t ina226_r_shunt[4]; // E40
uint16_t ina226_i_fs[4]; // E48
uint8_t free_e20[416]; // E60 uint8_t free_e20[424]; // E50
// FFF last location // FFF last location

View File

@ -1,8 +1,25 @@
/*
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/>.
*/
// Conditional compilation of driver // Conditional compilation of driver
#ifdef USE_INA226 #ifdef USE_INA226
// Define driver ID // Define driver ID
#define XSNS_76 76
#define XSNS_54 54
#define INA226_MAX_ADDRESSES 4 #define INA226_MAX_ADDRESSES 4
#define INA226_ADDRESS1 (0x40) // 1000000 (A0+A1=GND) #define INA226_ADDRESS1 (0x40) // 1000000 (A0+A1=GND)
@ -24,7 +41,6 @@
typedef struct Ina226SlaveInfo_tag { typedef struct Ina226SlaveInfo_tag {
uint8_t address; uint8_t address;
uint8_t missedCount;
uint16_t calibrationValue; uint16_t calibrationValue;
uint16_t config; uint16_t config;
uint8_t present : 1; uint8_t present : 1;
@ -32,7 +48,7 @@ typedef struct Ina226SlaveInfo_tag {
} Ina226SlaveInfo_t; } Ina226SlaveInfo_t;
/* /*
* Program memory connstants * Program memory constants
*/ */
static const uint8_t PROGMEM probeAddresses[INA226_MAX_ADDRESSES] = {INA226_ADDRESS1, INA226_ADDRESS2, INA226_ADDRESS3, INA226_ADDRESS4}; static const uint8_t PROGMEM probeAddresses[INA226_MAX_ADDRESSES] = {INA226_ADDRESS1, INA226_ADDRESS2, INA226_ADDRESS3, INA226_ADDRESS4};
@ -63,6 +79,21 @@ static void _debug_fval(const char *str, float fval, uint8_t prec = 4 )
AddLog_P2( LOG_LEVEL_NONE, PSTR("%s: %s"), str, 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 * Set calibration value for Ina226
*/ */
@ -113,7 +144,7 @@ void Ina226Init()
//AddLog_P2( LOG_LEVEL_NONE, "Ina226Init"); //AddLog_P2( LOG_LEVEL_NONE, "Ina226Init");
//AddLog_P2( LOG_LEVEL_NONE, "Size of Settings: %d bytes", sizeof(Settings)); AddLog_P2( LOG_LEVEL_NONE, "Size of Settings: %d bytes", sizeof(Settings));
if (!i2c_flg) if (!i2c_flg)
AddLog_P2(LOG_LEVEL_DEBUG, "INA226: Initialization failed: No I2C support"); AddLog_P2(LOG_LEVEL_DEBUG, "INA226: Initialization failed: No I2C support");
@ -133,7 +164,7 @@ void Ina226Init()
uint8_t addr = pgm_read_byte(probeAddresses + i); uint8_t addr = pgm_read_byte(probeAddresses + i);
// Skip device probing if the full scale current is zero // Skip device probing if the full scale current is zero
if (!Settings.ina226_config[i].i_fs) if (!Settings.ina226_i_fs[i])
continue; continue;
@ -170,15 +201,19 @@ void Ina226Init()
// Configuration // Configuration
p->config = config; p->config = config;
// Full scale current in tenths of an amp // Full scale current in tenths of an amp
//AddLog_P2( LOG_LEVEL_NONE, "Full Scale I in tenths of an amp: %u", Settings.ina226_config[i].i_fs ); 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_config[i].i_fs)/10.0f)/32768.0f; p->i_lsb = (((float) Settings.ina226_i_fs[i])/10.0f)/32768.0f;
//_debug_fval("i_lsb: %s", p->i_lsb, 7); _debug_fval("i_lsb: %s", p->i_lsb, 7);
// Shunt resistance in microohm increments
//AddLog_P2( LOG_LEVEL_NONE, "Shunt R in micro-ohms: %u", Settings.ina226_config[i].r_shunt ); // Get shunt resistor value in micro ohms
p->calibrationValue = ((uint16_t) (0.00512/(p->i_lsb * ((float) Settings.ina226_config[i].r_shunt)/1000000.0f))); 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 // Device present
p->present = true; p->present = true;
//AddLog_P2( LOG_LEVEL_NONE, "INA226 Device %d calibration value: %04X", i, p->calibrationValue); AddLog_P2( LOG_LEVEL_NONE, "INA226 Device %d calibration value: %04X", i, p->calibrationValue);
Ina226SetCalibration(i); Ina226SetCalibration(i);
@ -284,7 +319,8 @@ bool Ina226CommandSensor()
char param_str[64]; char param_str[64];
char *cp, *params[4]; char *cp, *params[4];
uint8_t i, param_count, device, p1 = XdrvMailbox.payload; 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 received: %d", XdrvMailbox.payload);
//AddLog_P2( LOG_LEVEL_NONE, "Command data received: %s", XdrvMailbox.data); //AddLog_P2( LOG_LEVEL_NONE, "Command data received: %s", XdrvMailbox.data);
@ -313,12 +349,12 @@ bool Ina226CommandSensor()
switch (p1){ switch (p1){
case 1: // Rerun init case 1: // Rerun init
Ina226Init(); Ina226Init();
Response_P(PSTR("{\"Sensor76-Command-Result\":{\"SlavesFound\":%d}}"),slavesFound); Response_P(PSTR("{\"Sensor54-Command-Result\":{\"SlavesFound\":%d}}"),slavesFound);
break; break;
case 2: // Save and restart case 2: // Save and restart
restart_flag = 2; restart_flag = 2;
Response_P(PSTR("{\"Sensor76-Command-Result\":{\"Restart_flag\":%d}}"),restart_flag); Response_P(PSTR("{\"Sensor54-Command-Result\":{\"Restart_flag\":%d}}"),restart_flag);
break; break;
default: default:
@ -333,15 +369,19 @@ bool Ina226CommandSensor()
show_config = true; show_config = true;
break; break;
case 1: // Set shunt resistance in microohms from user input in ohms case 1: // Set compacted shunt resistance from user input in ohms
Settings.ina226_config[device].r_shunt = (uint32_t) ((CharToFloat(params[1])) * 1000000.0f); r_shunt_uohms = (uint32_t) ((CharToFloat(params[1])) * 1000000.0f);
//AddLog_P2( LOG_LEVEL_NONE, "r_shunt: %d", Settings.ina226_config[device].r_shunt); compact_r_shunt_uohms = (uint16_t) (r_shunt_uohms > 32767UL) ?
0x8000 | (r_shunt_uohms / 1000UL) :
r_shunt_uohms;
Settings.ina226_r_shunt[device] = r_shunt_uohms;
AddLog_P2( LOG_LEVEL_NONE, "r_shunt_compacted: %04X", Settings.ina226_r_shunt[device]);
show_config = true; show_config = true;
break; break;
case 2: // Set full scale current in tenths of amps from user input in Amps case 2: // Set full scale current in tenths of amps from user input in Amps
Settings.ina226_config[device].i_fs = (uint16_t) ((CharToFloat(params[1])) * 10.0f); Settings.ina226_i_fs[device] = (uint16_t) ((CharToFloat(params[1])) * 10.0f);
//AddLog_P2( LOG_LEVEL_NONE, "i_fs: %d", Settings.ina226_config[device].i_fs); AddLog_P2( LOG_LEVEL_NONE, "i_fs: %d", Settings.ina226_i_fs[device]);
show_config = true; show_config = true;
break; break;
@ -359,11 +399,12 @@ bool Ina226CommandSensor()
char fs_i_str[16]; char fs_i_str[16];
// Shunt resistance is stored in EEPROM in microohms. Convert to ohms // Shunt resistance is stored in EEPROM in microohms. Convert to ohms
dtostrfd(((float)Settings.ina226_config[device].r_shunt)/1000000.0, 6, shunt_r_str); 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. // Full scale current is stored in EEPROM in tenths of an amp. Convert to amps.
dtostrfd(((float)Settings.ina226_config[device].i_fs)/10.0f, 1, fs_i_str); dtostrfd(((float)Settings.ina226_i_fs[device])/10.0f, 1, fs_i_str);
// Send json response // Send json response
Response_P(PSTR("{\"Sensor76-device-settings-%d\":{\"SHUNT_R\":%s,\"FS_I\":%s}}"), Response_P(PSTR("{\"Sensor54-device-settings-%d\":{\"SHUNT_R\":%s,\"FS_I\":%s}}"),
device + 1, shunt_r_str, fs_i_str); device + 1, shunt_r_str, fs_i_str);
} }
@ -432,13 +473,13 @@ void Ina226Show(bool json)
* @post None. * @post None.
* *
*/ */
boolean Xsns76(byte callback_id) { boolean Xsns54(byte callback_id) {
// Set return value to `false` // Set return value to `false`
boolean result = false; bool result = false;
// Check if I2C interface mode // Check if I2C interface mode is enabled
// if(i2c_flg) { if(i2c_flg) {
// Check which callback ID is called by Tasmota // Check which callback ID is called by Tasmota
switch (callback_id) { switch (callback_id) {
@ -461,13 +502,12 @@ boolean Xsns76(byte callback_id) {
case FUNC_SAVE_BEFORE_RESTART: case FUNC_SAVE_BEFORE_RESTART:
break; break;
case FUNC_COMMAND_SENSOR: case FUNC_COMMAND_SENSOR:
if (XSNS_76 == XdrvMailbox.index) { if (XSNS_54 == XdrvMailbox.index) {
result = Ina226CommandSensor(); result = Ina226CommandSensor();
} }
break; break;
} }
// } // if(i2c_flg) } // if(i2c_flg)
// Return boolean result // Return boolean result
return result; return result;
} }