Merge pull request #6005 from s-hadinger/trig_floats2

Converted double to float in rules, and replaced trigonometric functions from stdlib with smaller versions.
This commit is contained in:
Theo Arends 2019-07-01 22:03:26 +02:00 committed by GitHub
commit 998887fe30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 385 additions and 126 deletions

View File

@ -7,6 +7,7 @@
* Add define USE_DHT to my_user_config.h to save space in sonoff-basic.bin
* Change TLS+AWS IoT optimization for speed, code and memory footprint
* Add command SetOption40 0..250 to disable button functionality if activated for over 0.1 second. Needs SetOption1 1 and SetOption13 0 (#5449)
* Change converted double to float in rules, and replaced trigonometric functions from stdlib with smaller versions.
*
* 6.5.0.15 20190606
* Change pubsubclient MQTT_KEEPALIVE from 10 to 30 seconds in preparation of AWS IoT support

View File

@ -224,7 +224,7 @@ char* subStr(char* dest, char* str, const char *delim, int index)
return sub;
}
double CharToDouble(const char *str)
float CharToFloat(const char *str)
{
// simple ascii to double, because atof or strtod are too large
char strbuf[24];
@ -237,23 +237,23 @@ double CharToDouble(const char *str)
if (*pt == '-') { sign = -1; }
if (*pt == '-' || *pt=='+') { pt++; } // Skip any sign
double left = 0;
float left = 0;
if (*pt != '.') {
left = atoi(pt); // Get left part
while (isdigit(*pt)) { pt++; } // Skip number
}
double right = 0;
float right = 0;
if (*pt == '.') {
pt++;
right = atoi(pt); // Decimal part
while (isdigit(*pt)) {
pt++;
right /= 10.0;
right /= 10.0f;
}
}
double result = left + right;
float result = left + right;
if (sign < 0) {
return -result; // Add negative sign
}
@ -650,66 +650,6 @@ void ResetGlobalValues(void)
}
}
double FastPrecisePow(double a, double b)
{
// https://martin.ankerl.com/2012/01/25/optimized-approximative-pow-in-c-and-cpp/
// calculate approximation with fraction of the exponent
int e = abs((int)b);
union {
double d;
int x[2];
} u = { a };
u.x[1] = (int)((b - e) * (u.x[1] - 1072632447) + 1072632447);
u.x[0] = 0;
// exponentiation by squaring with the exponent's integer part
// double r = u.d makes everything much slower, not sure why
double r = 1.0;
while (e) {
if (e & 1) {
r *= a;
}
a *= a;
e >>= 1;
}
return r * u.d;
}
float FastPrecisePowf(const float x, const float y)
{
// return (float)(pow((double)x, (double)y));
return (float)FastPrecisePow(x, y);
}
double TaylorLog(double x)
{
// https://stackoverflow.com/questions/46879166/finding-the-natural-logarithm-of-a-number-using-taylor-series-in-c
if (x <= 0.0) { return NAN; }
double z = (x + 1) / (x - 1); // We start from power -1, to make sure we get the right power in each iteration;
double step = ((x - 1) * (x - 1)) / ((x + 1) * (x + 1)); // Store step to not have to calculate it each time
double totalValue = 0;
double powe = 1;
double y;
for (uint32_t count = 0; count < 10; count++) { // Experimental number of 10 iterations
z *= step;
y = (1 / powe) * z;
totalValue = totalValue + y;
powe = powe + 2;
}
totalValue *= 2;
/*
char logxs[33];
dtostrfd(x, 8, logxs);
double log1 = log(x);
char log1s[33];
dtostrfd(log1, 8, log1s);
char log2s[33];
dtostrfd(totalValue, 8, log2s);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("input %s, log %s, taylor %s"), logxs, log1s, log2s);
*/
return totalValue;
}
uint32_t SqrtInt(uint32_t num)
{
if (num <= 1) {

318
sonoff/support_float.ino Normal file
View File

@ -0,0 +1,318 @@
/*
support_float.ino - support for Sonoff-Tasmota
Copyright (C) 2019 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/>.
*/
double FastPrecisePow(double a, double b)
{
// https://martin.ankerl.com/2012/01/25/optimized-approximative-pow-in-c-and-cpp/
// calculate approximation with fraction of the exponent
int e = abs((int)b);
union {
double d;
int x[2];
} u = { a };
u.x[1] = (int)((b - e) * (u.x[1] - 1072632447) + 1072632447);
u.x[0] = 0;
// exponentiation by squaring with the exponent's integer part
// double r = u.d makes everything much slower, not sure why
double r = 1.0;
while (e) {
if (e & 1) {
r *= a;
}
a *= a;
e >>= 1;
}
return r * u.d;
}
float FastPrecisePowf(const float x, const float y)
{
// return (float)(pow((double)x, (double)y));
return (float)FastPrecisePow(x, y);
}
double TaylorLog(double x)
{
// https://stackoverflow.com/questions/46879166/finding-the-natural-logarithm-of-a-number-using-taylor-series-in-c
if (x <= 0.0) { return NAN; }
double z = (x + 1) / (x - 1); // We start from power -1, to make sure we get the right power in each iteration;
double step = ((x - 1) * (x - 1)) / ((x + 1) * (x + 1)); // Store step to not have to calculate it each time
double totalValue = 0;
double powe = 1;
double y;
for (uint32_t count = 0; count < 10; count++) { // Experimental number of 10 iterations
z *= step;
y = (1 / powe) * z;
totalValue = totalValue + y;
powe = powe + 2;
}
totalValue *= 2;
/*
char logxs[33];
dtostrfd(x, 8, logxs);
double log1 = log(x);
char log1s[33];
dtostrfd(log1, 8, log1s);
char log2s[33];
dtostrfd(totalValue, 8, log2s);
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("input %s, log %s, taylor %s"), logxs, log1s, log2s);
*/
return totalValue;
}
// All code adapted from: http://www.ganssle.com/approx.htm
/// ========================================
// The following code implements approximations to various trig functions.
//
// This is demo code to guide developers in implementing their own approximation
// software. This code is merely meant to illustrate algorithms.
inline float sinf(float x) { return sin_52(x); }
inline float cosf(float x) { return cos_52(x); }
inline float tanf(float x) { return tan_56(x); }
inline float atanf(float x) { return atan_66(x); }
inline float asinf(float x) { return asinf1(x); }
inline float acosf(float x) { return acosf1(x); }
inline float sqrtf(float x) { return sqrt1(x); }
inline float powf(float x, float y) { return FastPrecisePow(x, y); }
// Math constants we'll use
double const f_pi=3.1415926535897932384626433; // f_pi
double const f_twopi=2.0*f_pi; // f_pi times 2
double const f_two_over_pi= 2.0/f_pi; // 2/f_pi
double const f_halfpi=f_pi/2.0; // f_pi divided by 2
double const f_threehalfpi=3.0*f_pi/2.0; // f_pi times 3/2, used in tan routines
double const f_four_over_pi=4.0/f_pi; // 4/f_pi, used in tan routines
double const f_qtrpi=f_pi/4.0; // f_pi/4.0, used in tan routines
double const f_sixthpi=f_pi/6.0; // f_pi/6.0, used in atan routines
double const f_tansixthpi=tan(f_sixthpi); // tan(f_pi/6), used in atan routines
double const f_twelfthpi=f_pi/12.0; // f_pi/12.0, used in atan routines
double const f_tantwelfthpi=tan(f_twelfthpi); // tan(f_pi/12), used in atan routines
// *********************************************************
// ***
// *** Routines to compute sine and cosine to 5.2 digits
// *** of accuracy.
// ***
// *********************************************************
//
// cos_52s computes cosine (x)
//
// Accurate to about 5.2 decimal digits over the range [0, f_pi/2].
// The input argument is in radians.
//
// Algorithm:
// cos(x)= c1 + c2*x**2 + c3*x**4 + c4*x**6
// which is the same as:
// cos(x)= c1 + x**2(c2 + c3*x**2 + c4*x**4)
// cos(x)= c1 + x**2(c2 + x**2(c3 + c4*x**2))
//
float cos_52s(float x)
{
const float c1= 0.9999932946;
const float c2=-0.4999124376;
const float c3= 0.0414877472;
const float c4=-0.0012712095;
float x2; // The input argument squared
x2=x * x;
return (c1 + x2*(c2 + x2*(c3 + c4*x2)));
}
//
// This is the main cosine approximation "driver"
// It reduces the input argument's range to [0, f_pi/2],
// and then calls the approximator.
// See the notes for an explanation of the range reduction.
//
float cos_52(float x){
int quad; // what quadrant are we in?
x=fmodf(x, f_twopi); // Get rid of values > 2* f_pi
if(x<0)x=-x; // cos(-x) = cos(x)
quad=int(x * (float)f_two_over_pi); // Get quadrant # (0 to 3) we're in
switch (quad){
case 0: return cos_52s(x);
case 1: return -cos_52s((float)f_pi-x);
case 2: return -cos_52s(x-(float)f_pi);
case 3: return cos_52s((float)f_twopi-x);
}
}
//
// The sine is just cosine shifted a half-f_pi, so
// we'll adjust the argument and call the cosine approximation.
//
float sin_52(float x){
return cos_52((float)f_halfpi-x);
}
// *********************************************************
// ***
// *** Routines to compute tangent to 5.6 digits
// *** of accuracy.
// ***
// *********************************************************
//
// tan_56s computes tan(f_pi*x/4)
//
// Accurate to about 5.6 decimal digits over the range [0, f_pi/4].
// The input argument is in radians. Note that the function
// computes tan(f_pi*x/4), NOT tan(x); it's up to the range
// reduction algorithm that calls this to scale things properly.
//
// Algorithm:
// tan(x)= x(c1 + c2*x**2)/(c3 + x**2)
//
float tan_56s(float x)
{
const float c1=-3.16783027;
const float c2= 0.134516124;
const float c3=-4.033321984;
float x2; // The input argument squared
x2=x * x;
return (x*(c1 + c2 * x2)/(c3 + x2));
}
//
// This is the main tangent approximation "driver"
// It reduces the input argument's range to [0, f_pi/4],
// and then calls the approximator.
// See the notes for an explanation of the range reduction.
// Enter with positive angles only.
//
// WARNING: We do not test for the tangent approaching infinity,
// which it will at x=f_pi/2 and x=3*f_pi/2. If this is a problem
// in your application, take appropriate action.
//
float tan_56(float x){
int octant; // what octant are we in?
x=fmodf(x, (float)f_twopi); // Get rid of values >2 *f_pi
octant=int(x * (float)f_four_over_pi); // Get octant # (0 to 7)
switch (octant){
case 0: return tan_56s(x *(float)f_four_over_pi);
case 1: return 1.0f/tan_56s(((float)f_halfpi-x) *(float)f_four_over_pi);
case 2: return -1.0f/tan_56s((x-(float)f_halfpi) *(float)f_four_over_pi);
case 3: return - tan_56s(((float)f_pi-x) *(float)f_four_over_pi);
case 4: return tan_56s((x-(float)f_pi) *(float)f_four_over_pi);
case 5: return 1.0f/tan_56s(((float)f_threehalfpi-x)*(float)f_four_over_pi);
case 6: return -1.0f/tan_56s((x-(float)f_threehalfpi)*(float)f_four_over_pi);
case 7: return - tan_56s(((float)f_twopi-x) *(float)f_four_over_pi);
}
}
// *********************************************************
// ***
// *** Routines to compute arctangent to 6.6 digits
// *** of accuracy.
// ***
// *********************************************************
//
// atan_66s computes atan(x)
//
// Accurate to about 6.6 decimal digits over the range [0, f_pi/12].
//
// Algorithm:
// atan(x)= x(c1 + c2*x**2)/(c3 + x**2)
//
float atan_66s(float x)
{
const float c1=1.6867629106;
const float c2=0.4378497304;
const float c3=1.6867633134;
float x2; // The input argument squared
x2=x * x;
return (x*(c1 + x2*c2)/(c3 + x2));
}
//
// This is the main arctangent approximation "driver"
// It reduces the input argument's range to [0, f_pi/12],
// and then calls the approximator.
//
//
float atan_66(float x){
float y; // return from atan__s function
bool complement= false; // true if arg was >1
bool region= false; // true depending on region arg is in
bool sign= false; // true if arg was < 0
if (x <0 ){
x=-x;
sign=true; // arctan(-x)=-arctan(x)
}
if (x > 1.0){
x=1.0/x; // keep arg between 0 and 1
complement=true;
}
if (x > (float)f_tantwelfthpi){
x = (x-(float)f_tansixthpi)/(1+(float)f_tansixthpi*x); // reduce arg to under tan(f_pi/12)
region=true;
}
y=atan_66s(x); // run the approximation
if (region) y+=(float)f_sixthpi; // correct for region we're in
if (complement)y=(float)f_halfpi-y; // correct for 1/x if we did that
if (sign)y=-y; // correct for negative arg
return (y);
}
float asinf1(float x) {
float d = 1.0f - x*x;
if (d < 0.0f) { return nanf(""); }
return 2 * atan_66(x / (1 + sqrt1(d)));
}
float acosf1(float x) {
float d = 1.0f - x*x;
if (d < 0.0f) { return nanf(""); }
float y = asinf1(sqrt1(d));
if (x >= 0.0f) {
return y;
} else {
return (float)f_pi - y;
}
}
// https://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi
float sqrt1(const float x)
{
union
{
int i;
float x;
} u;
u.x = x;
u.i = (1<<29) + (u.i >> 1) - (1<<22);
// Two Babylonian Steps (simplified from:)
// u.x = 0.5f * (u.x + x/u.x);
// u.x = 0.5f * (u.x + x/u.x);
u.x = u.x + x/u.x;
u.x = 0.25f*u.x + x/u.x;
return u.x;
}

View File

@ -487,7 +487,7 @@ bool TimerCommand(void)
#ifdef USE_SUNRISE
else if (CMND_LONGITUDE == command_code) {
if (XdrvMailbox.data_len) {
Settings.longitude = (int)(CharToDouble(XdrvMailbox.data) *1000000);
Settings.longitude = (int)(CharToFloat(XdrvMailbox.data) *1000000);
}
char lbuff[33];
dtostrfd(((float)Settings.longitude) /1000000, 6, lbuff);
@ -495,7 +495,7 @@ bool TimerCommand(void)
}
else if (CMND_LATITUDE == command_code) {
if (XdrvMailbox.data_len) {
Settings.latitude = (int)(CharToDouble(XdrvMailbox.data) *1000000);
Settings.latitude = (int)(CharToFloat(XdrvMailbox.data) *1000000);
}
char lbuff[33];
dtostrfd(((float)Settings.latitude) /1000000, 6, lbuff);

View File

@ -179,7 +179,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
}
char rule_svalue[CMDSZ] = { 0 };
double rule_value = 0;
float rule_value = 0;
if (compare != COMPARE_OPERATOR_NONE) {
String rule_param = rule_name.substring(pos + strlen(compare_operator));
for (uint32_t i = 0; i < MAX_RULE_VARS; i++) {
@ -225,7 +225,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
if (temp_value > -1) {
rule_value = temp_value;
} else {
rule_value = CharToDouble((char*)rule_svalue); // 0.1 - This saves 9k code over toFLoat()!
rule_value = CharToFloat((char*)rule_svalue); // 0.1 - This saves 9k code over toFLoat()!
}
rule_name = rule_name.substring(0, pos); // "CURRENT"
}
@ -235,7 +235,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
JsonObject &root = jsonBuf.parseObject(event);
if (!root.success()) { return false; } // No valid JSON data
double value = 0;
float value = 0;
const char* str_value = root[rule_task][rule_name];
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR("RUL: Task %s, Name %s, Value |%s|, TrigCnt %d, TrigSt %d, Source %s, Json %s"),
@ -248,7 +248,7 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
// Step 3: Compare rule (value)
if (str_value) {
value = CharToDouble((char*)str_value);
value = CharToFloat((char*)str_value);
int int_value = int(value);
int int_rule_value = int(rule_value);
switch (compare) {
@ -797,15 +797,15 @@ String RulesUnsubscribe(const char * data, int data_len)
* Parse a number value
* Input:
* pNumber - A char pointer point to a digit started string (guaranteed)
* value - Reference a double variable used to accept the result
* value - Reference a float variable used to accept the result
* Output:
* pNumber - Pointer forward to next character after the number
* value - double type, the result value
* value - float type, the result value
* Return:
* true - succeed
* false - failed
*/
bool findNextNumber(char * &pNumber, double &value)
bool findNextNumber(char * &pNumber, float &value)
{
bool bSucceed = false;
String sNumber = "";
@ -818,7 +818,7 @@ bool findNextNumber(char * &pNumber, double &value)
}
}
if (sNumber.length() > 0) {
value = CharToDouble(sNumber.c_str());
value = CharToFloat(sNumber.c_str());
bSucceed = true;
}
return bSucceed;
@ -826,18 +826,18 @@ bool findNextNumber(char * &pNumber, double &value)
/********************************************************************************************/
/*
* Parse a variable (like VAR1, MEM3) and get its value (double type)
* Parse a variable (like VAR1, MEM3) and get its value (float type)
* Input:
* pVarname - A char pointer point to a variable name string
* value - Reference a double variable used to accept the result
* value - Reference a float variable used to accept the result
* Output:
* pVarname - Pointer forward to next character after the variable
* value - double type, the result value
* value - float type, the result value
* Return:
* true - succeed
* false - failed
*/
bool findNextVariableValue(char * &pVarname, double &value)
bool findNextVariableValue(char * &pVarname, float &value)
{
bool succeed = true;
value = 0;
@ -854,12 +854,12 @@ bool findNextVariableValue(char * &pVarname, double &value)
if (sVarName.startsWith(F("VAR"))) {
int index = sVarName.substring(3).toInt();
if (index > 0 && index <= MAX_RULE_VARS) {
value = CharToDouble(vars[index -1]);
value = CharToFloat(vars[index -1]);
}
} else if (sVarName.startsWith(F("MEM"))) {
int index = sVarName.substring(3).toInt();
if (index > 0 && index <= MAX_RULE_MEMS) {
value = CharToDouble(Settings.mems[index -1]);
value = CharToFloat(Settings.mems[index -1]);
}
} else if (sVarName.equals(F("TIME"))) {
value = MinutesPastMidnight();
@ -891,15 +891,15 @@ bool findNextVariableValue(char * &pVarname, double &value)
* - An expression enclosed with a pair of round brackets, (.....)
* Input:
* pointer - A char pointer point to a place of the expression string
* value - Reference a double variable used to accept the result
* value - Reference a float variable used to accept the result
* Output:
* pointer - Pointer forward to next character after next object
* value - double type, the result value
* value - float type, the result value
* Return:
* true - succeed
* false - failed
*/
bool findNextObjectValue(char * &pointer, double &value)
bool findNextObjectValue(char * &pointer, float &value)
{
bool bSucceed = false;
while (*pointer)
@ -984,15 +984,15 @@ bool findNextOperator(char * &pointer, int8_t &op)
* Calculate a simple expression composed by 2 value and 1 operator, like 2 * 3
* Input:
* pointer - A char pointer point to a place of the expression string
* value - Reference a double variable used to accept the result
* value - Reference a float variable used to accept the result
* Output:
* pointer - Pointer forward to next character after next object
* value - double type, the result value
* value - float type, the result value
* Return:
* true - succeed
* false - failed
*/
double calculateTwoValues(double v1, double v2, uint8_t op)
float calculateTwoValues(float v1, float v2, uint8_t op)
{
switch (op)
{
@ -1025,7 +1025,7 @@ double calculateTwoValues(double v1, double v2, uint8_t op)
* expression - The expression to be evaluated
* len - Length of the expression
* Return:
* double - result.
* float - result.
* 0 - if the expression is invalid
* An example:
* MEM1 = 3, MEM2 = 6, VAR2 = 15, VAR10 = 80
@ -1045,17 +1045,17 @@ double calculateTwoValues(double v1, double v2, uint8_t op)
* 2 + 1
* 3 / 2
*/
double evaluateExpression(const char * expression, unsigned int len)
float evaluateExpression(const char * expression, unsigned int len)
{
char expbuf[len + 1];
memcpy(expbuf, expression, len);
expbuf[len] = '\0';
char * scan_pointer = expbuf;
LinkedList<double> object_values;
LinkedList<float> object_values;
LinkedList<int8_t> operators;
int8_t op;
double va;
float va;
//Find and add the value of first object
if (findNextObjectValue(scan_pointer, va)) {
object_values.add(va);
@ -1154,7 +1154,7 @@ bool RulesCommand(void)
else if ((CMND_RULETIMER == command_code) && (index > 0) && (index <= MAX_RULE_TIMERS)) {
if (XdrvMailbox.data_len > 0) {
#ifdef USE_EXPRESSION
double timer_set = evaluateExpression(XdrvMailbox.data, XdrvMailbox.data_len);
float timer_set = evaluateExpression(XdrvMailbox.data, XdrvMailbox.data_len);
rules_timer[index -1] = (timer_set > 0) ? millis() + (1000 * timer_set) : 0;
#else
rules_timer[index -1] = (XdrvMailbox.payload > 0) ? millis() + (1000 * XdrvMailbox.payload) : 0;
@ -1202,7 +1202,7 @@ bool RulesCommand(void)
}
else if ((CMND_ADD == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) {
if (XdrvMailbox.data_len > 0) {
double tempvar = CharToDouble(vars[index -1]) + CharToDouble(XdrvMailbox.data);
float tempvar = CharToFloat(vars[index -1]) + CharToFloat(XdrvMailbox.data);
dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]);
bitSet(vars_event, index -1);
}
@ -1210,7 +1210,7 @@ bool RulesCommand(void)
}
else if ((CMND_SUB == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) {
if (XdrvMailbox.data_len > 0) {
double tempvar = CharToDouble(vars[index -1]) - CharToDouble(XdrvMailbox.data);
float tempvar = CharToFloat(vars[index -1]) - CharToFloat(XdrvMailbox.data);
dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]);
bitSet(vars_event, index -1);
}
@ -1218,7 +1218,7 @@ bool RulesCommand(void)
}
else if ((CMND_MULT == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) {
if (XdrvMailbox.data_len > 0) {
double tempvar = CharToDouble(vars[index -1]) * CharToDouble(XdrvMailbox.data);
float tempvar = CharToFloat(vars[index -1]) * CharToFloat(XdrvMailbox.data);
dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]);
bitSet(vars_event, index -1);
}
@ -1229,12 +1229,12 @@ bool RulesCommand(void)
if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry
char sub_string[XdrvMailbox.data_len +1];
double valueIN = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 1));
double fromLow = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 2));
double fromHigh = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 3));
double toLow = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 4));
double toHigh = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 5));
double value = map_double(valueIN, fromLow, fromHigh, toLow, toHigh);
float valueIN = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 1));
float fromLow = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2));
float fromHigh = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 3));
float toLow = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4));
float toHigh = CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 5));
float value = map_double(valueIN, fromLow, fromHigh, toLow, toHigh);
dtostrfd(value, Settings.flag2.calc_resolution, vars[index -1]);
bitSet(vars_event, index -1);
}
@ -1254,7 +1254,7 @@ bool RulesCommand(void)
return serviced;
}
double map_double(double x, double in_min, double in_max, double out_min, double out_max)
float map_double(float x, float in_min, float in_max, float out_min, float out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

View File

@ -298,7 +298,7 @@ char *script;
op++;
if (*op!='"') {
float fv;
fv=CharToDouble(op);
fv=CharToFloat(op);
fvalues[nvars]=fv;
vtypes[vars].bits.is_string=0;
if (!vtypes[vars].bits.is_filter) vtypes[vars].index=nvars;
@ -670,7 +670,7 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso
if (isdigit(*lp) || (*lp=='-' && isdigit(*(lp+1))) || *lp=='.') {
// isnumber
if (fp) *fp=CharToDouble(lp);
if (fp) *fp=CharToFloat(lp);
if (*lp=='-') lp++;
while (isdigit(*lp) || *lp=='.') {
if (*lp==0 || *lp==SCRIPT_EOL) break;
@ -839,7 +839,7 @@ char *isvar(char *lp, uint8_t *vtype,struct T_INDEX *tind,float *fp,char *sp,Jso
return lp+len;
}
} else {
if (fp) *fp=CharToDouble((char*)str_value);
if (fp) *fp=CharToFloat((char*)str_value);
*vtype=NUM_RES;
tind->bits.constant=1;
tind->bits.is_string=0;
@ -2266,7 +2266,7 @@ int16_t Run_Scripter(const char *type, uint8_t tlen, char *js) {
// mismatch was string, not number
// get the string and convert to number
lp=isvar(slp,&vtype,&ind,0,cmpstr,jo);
fvar=CharToDouble(cmpstr);
fvar=CharToFloat(cmpstr);
}
switch (lastop) {
case OPER_EQU:
@ -2398,7 +2398,7 @@ int16_t Run_Scripter(const char *type, uint8_t tlen, char *js) {
*dfvar=fparam;
} else {
// mismatch
*dfvar=CharToDouble(cmpstr);
*dfvar=CharToFloat(cmpstr);
}
} else {
// string result

View File

@ -1030,7 +1030,7 @@ bool KnxCommand(void)
while ( i != KNX_Empty ) {
KNX_addr.value = Settings.knx_GA_addr[i];
float tempvar = CharToDouble(XdrvMailbox.data);
float tempvar = CharToFloat(XdrvMailbox.data);
dtostrfd(tempvar,2,XdrvMailbox.data);
knx.write_2byte_float(KNX_addr, tempvar);

View File

@ -287,17 +287,17 @@ bool HlwCommand(void)
}
else if (CMND_POWERSET == energy_command_code) {
if (XdrvMailbox.data_len && hlw_cf_power_pulse_length) {
Settings.energy_power_calibration = ((unsigned long)(CharToDouble(XdrvMailbox.data) * 10) * hlw_cf_power_pulse_length) / hlw_power_ratio;
Settings.energy_power_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * hlw_cf_power_pulse_length) / hlw_power_ratio;
}
}
else if (CMND_VOLTAGESET == energy_command_code) {
if (XdrvMailbox.data_len && hlw_cf1_voltage_pulse_length) {
Settings.energy_voltage_calibration = ((unsigned long)(CharToDouble(XdrvMailbox.data) * 10) * hlw_cf1_voltage_pulse_length) / hlw_voltage_ratio;
Settings.energy_voltage_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data) * 10) * hlw_cf1_voltage_pulse_length) / hlw_voltage_ratio;
}
}
else if (CMND_CURRENTSET == energy_command_code) {
if (XdrvMailbox.data_len && hlw_cf1_current_pulse_length) {
Settings.energy_current_calibration = ((unsigned long)(CharToDouble(XdrvMailbox.data)) * hlw_cf1_current_pulse_length) / hlw_current_ratio;
Settings.energy_current_calibration = ((unsigned long)(CharToFloat(XdrvMailbox.data)) * hlw_cf1_current_pulse_length) / hlw_current_ratio;
}
}
else serviced = false; // Unknown command

View File

@ -225,17 +225,17 @@ bool CseCommand(void)
if (CMND_POWERSET == energy_command_code) {
if (XdrvMailbox.data_len && power_cycle) {
Settings.energy_power_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * power_cycle) / CSE_PREF;
Settings.energy_power_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * power_cycle) / CSE_PREF;
}
}
else if (CMND_VOLTAGESET == energy_command_code) {
if (XdrvMailbox.data_len && voltage_cycle) {
Settings.energy_voltage_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * voltage_cycle) / CSE_UREF;
Settings.energy_voltage_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * voltage_cycle) / CSE_UREF;
}
}
else if (CMND_CURRENTSET == energy_command_code) {
if (XdrvMailbox.data_len && current_cycle) {
Settings.energy_current_calibration = (unsigned long)(CharToDouble(XdrvMailbox.data) * current_cycle) / 1000;
Settings.energy_current_calibration = (unsigned long)(CharToFloat(XdrvMailbox.data) * current_cycle) / 1000;
}
}
else serviced = false; // Unknown command

View File

@ -604,7 +604,7 @@ bool McpCommand(void)
if (CMND_POWERSET == energy_command_code) {
if (XdrvMailbox.data_len && mcp_active_power) {
value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 100);
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 100);
if ((value > 100) && (value < 200000)) { // Between 1W and 2000W
Settings.energy_power_calibration = value;
mcp_calibrate |= MCP_CALIBRATE_POWER;
@ -614,7 +614,7 @@ bool McpCommand(void)
}
else if (CMND_VOLTAGESET == energy_command_code) {
if (XdrvMailbox.data_len && mcp_voltage_rms) {
value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10);
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10);
if ((value > 1000) && (value < 2600)) { // Between 100V and 260V
Settings.energy_voltage_calibration = value;
mcp_calibrate |= MCP_CALIBRATE_VOLTAGE;
@ -624,7 +624,7 @@ bool McpCommand(void)
}
else if (CMND_CURRENTSET == energy_command_code) {
if (XdrvMailbox.data_len && mcp_current_rms) {
value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 10);
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 10);
if ((value > 100) && (value < 80000)) { // Between 10mA and 8A
Settings.energy_current_calibration = value;
mcp_calibrate |= MCP_CALIBRATE_CURRENT;
@ -634,7 +634,7 @@ bool McpCommand(void)
}
else if (CMND_FREQUENCYSET == energy_command_code) {
if (XdrvMailbox.data_len && mcp_line_frequency) {
value = (unsigned long)(CharToDouble(XdrvMailbox.data) * 1000);
value = (unsigned long)(CharToFloat(XdrvMailbox.data) * 1000);
if ((value > 45000) && (value < 65000)) { // Between 45Hz and 65Hz
Settings.energy_frequency_calibration = value;
mcp_calibrate |= MCP_CALIBRATE_FREQUENCY;

View File

@ -184,7 +184,7 @@ bool Ade7953Command(void)
{
bool serviced = true;
uint32_t value = (uint32_t)(CharToDouble(XdrvMailbox.data) * 100); // 1.23 = 123
uint32_t value = (uint32_t)(CharToFloat(XdrvMailbox.data) * 100); // 1.23 = 123
if (CMND_POWERCAL == energy_command_code) {
if (1 == XdrvMailbox.payload) { XdrvMailbox.payload = ADE7953_PREF; }

View File

@ -151,7 +151,7 @@ bool AdcCommand(void)
// Settings.adc_param_type = my_adc0;
Settings.adc_param1 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10);
Settings.adc_param2 = strtol(subStr(sub_string, XdrvMailbox.data, ",", 3), nullptr, 10);
Settings.adc_param3 = (int)(CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000);
Settings.adc_param3 = (int)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 4)) * 10000);
} else { // Set default values based on current adc type
// AdcParam 2
// AdcParam 3

View File

@ -204,7 +204,7 @@ bool HxCommand(void)
break;
case 6: // WeightItem
if (strstr(XdrvMailbox.data, ",") != nullptr) {
Settings.weight_item = (unsigned long)(CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10);
Settings.weight_item = (unsigned long)(CharToFloat(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10);
}
show_parms = true;
break;
@ -444,7 +444,7 @@ void HandleHxAction(void)
if (WebServer->hasArg("calibrate")) {
WebGetArg("p1", stemp1, sizeof(stemp1));
Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToDouble(stemp1) * 1000);
Settings.weight_reference = (!strlen(stemp1)) ? 0 : (unsigned long)(CharToFloat(stemp1) * 1000);
HxLogUpdates();
@ -471,7 +471,7 @@ void HxSaveSettings(void)
char tmp[100];
WebGetArg("p2", tmp, sizeof(tmp));
Settings.weight_item = (!strlen(tmp)) ? 0 : (unsigned long)(CharToDouble(tmp) * 10000);
Settings.weight_item = (!strlen(tmp)) ? 0 : (unsigned long)(CharToFloat(tmp) * 10000);
HxLogUpdates();
}

View File

@ -182,7 +182,7 @@ void AzEverySecond(void)
return;
}
response_substr[j] = 0; // add null terminator
az_temperature = CharToDouble((char*)response_substr); // units (C or F) depends on meter setting
az_temperature = CharToFloat((char*)response_substr); // units (C or F) depends on meter setting
if(az_response[i] == 'C') { // meter transmits in degC
az_temperature = ConvertTemp((float)az_temperature); // convert to degF, depending on settings
} else { // meter transmits in degF
@ -232,7 +232,7 @@ void AzEverySecond(void)
return;
}
response_substr[j] = 0; // add null terminator
az_humidity = ConvertHumidity(CharToDouble((char*)response_substr));
az_humidity = ConvertHumidity(CharToFloat((char*)response_substr));
}
}