Shrink sensors code size by 5k using local pow

This commit is contained in:
Theo Arends 2020-05-15 14:17:11 +02:00
parent 6573802f83
commit bafe8a137f

View File

@ -57,7 +57,7 @@ bool MutichannelGasSensor::isError()
unsigned char MutichannelGasSensor::getVersion() unsigned char MutichannelGasSensor::getVersion()
{ {
if(get_addr_dta(CMD_READ_EEPROM, ADDR_IS_SET) == 1126) // get version if(get_addr_dta(CMD_READ_EEPROM, ADDR_IS_SET) == 1126) // get version
{ {
__version = 2; __version = 2;
return __version; return __version;
@ -105,66 +105,66 @@ START:
return 0; return 0;
} }
} }
Wire.requestFrom(i2cAddress, (uint8_t)2); Wire.requestFrom(i2cAddress, (uint8_t)2);
unsigned int dta = 0; unsigned int dta = 0;
unsigned char raw[10]; unsigned char raw[10];
int cnt = 0; int cnt = 0;
while(Wire.available()) while(Wire.available())
{ {
raw[cnt++] = Wire.read(); raw[cnt++] = Wire.read();
} }
if(cnt == 0)goto START; if(cnt == 0)goto START;
dta = raw[0]; dta = raw[0];
dta <<= 8; dta <<= 8;
dta += raw[1]; dta += raw[1];
switch(addr_reg) switch(addr_reg)
{ {
case CH_VALUE_NH3: case CH_VALUE_NH3:
if(dta > 0) if(dta > 0)
{ {
adcValueR0_NH3_Buf = dta; adcValueR0_NH3_Buf = dta;
} }
else else
{ {
dta = adcValueR0_NH3_Buf; dta = adcValueR0_NH3_Buf;
} }
break; break;
case CH_VALUE_CO: case CH_VALUE_CO:
if(dta > 0) if(dta > 0)
{ {
adcValueR0_CO_Buf = dta; adcValueR0_CO_Buf = dta;
} }
else else
{ {
dta = adcValueR0_CO_Buf; dta = adcValueR0_CO_Buf;
} }
break; break;
case CH_VALUE_NO2: case CH_VALUE_NO2:
if(dta > 0) if(dta > 0)
{ {
adcValueR0_NO2_Buf = dta; adcValueR0_NO2_Buf = dta;
} }
else else
{ {
dta = adcValueR0_NO2_Buf; dta = adcValueR0_NO2_Buf;
} }
break; break;
default:; default:;
} }
return dta; return dta;
@ -173,7 +173,7 @@ START:
unsigned int MutichannelGasSensor::get_addr_dta(unsigned char addr_reg, unsigned char __dta) unsigned int MutichannelGasSensor::get_addr_dta(unsigned char addr_reg, unsigned char __dta)
{ {
int trys = 0; int trys = 0;
START: START:
__send_error = false; __send_error = false;
Wire.beginTransmission(i2cAddress); Wire.beginTransmission(i2cAddress);
Wire.write(addr_reg); Wire.write(addr_reg);
@ -185,25 +185,25 @@ START:
return 0; return 0;
} }
} }
Wire.requestFrom(i2cAddress, (uint8_t)2); Wire.requestFrom(i2cAddress, (uint8_t)2);
unsigned int dta = 0; unsigned int dta = 0;
unsigned char raw[10]; unsigned char raw[10];
int cnt = 0; int cnt = 0;
while(Wire.available()) while(Wire.available())
{ {
raw[cnt++] = Wire.read(); raw[cnt++] = Wire.read();
} }
if(cnt == 0)goto START; if(cnt == 0)goto START;
dta = raw[0]; dta = raw[0];
dta <<= 8; dta <<= 8;
dta += raw[1]; dta += raw[1];
return dta; return dta;
} }
@ -269,7 +269,7 @@ int16_t MutichannelGasSensor::readR0(void)
int16_t rtnData = 0; int16_t rtnData = 0;
rtnData = readData(0x11); rtnData = readData(0x11);
if(rtnData > 0) if(rtnData > 0)
res0[0] = rtnData; res0[0] = rtnData;
else else
@ -327,6 +327,30 @@ int16_t MutichannelGasSensor::readR(void)
** Returns: ** Returns:
float value - concentration of the gas float value - concentration of the gas
*********************************************************************************************************/ *********************************************************************************************************/
float MutichannelGasSensor_pow(float a, float 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 MutichannelGasSensor::calcGas(int gas) float MutichannelGasSensor::calcGas(int gas)
{ {
@ -338,7 +362,7 @@ float MutichannelGasSensor::calcGas(int gas)
if(readR0() >= 0) r0_inited = true; if(readR0() >= 0) r0_inited = true;
else return -1.0f; else return -1.0f;
} }
if(readR() < 0) if(readR() < 0)
return -2.0f; return -2.0f;
@ -353,65 +377,65 @@ float MutichannelGasSensor::calcGas(int gas)
int A0_0 = get_addr_dta(6, ADDR_USER_ADC_HN3); int A0_0 = get_addr_dta(6, ADDR_USER_ADC_HN3);
int A0_1 = get_addr_dta(6, ADDR_USER_ADC_CO); int A0_1 = get_addr_dta(6, ADDR_USER_ADC_CO);
int A0_2 = get_addr_dta(6, ADDR_USER_ADC_NO2); int A0_2 = get_addr_dta(6, ADDR_USER_ADC_NO2);
int An_0 = get_addr_dta(CH_VALUE_NH3); int An_0 = get_addr_dta(CH_VALUE_NH3);
int An_1 = get_addr_dta(CH_VALUE_CO); int An_1 = get_addr_dta(CH_VALUE_CO);
int An_2 = get_addr_dta(CH_VALUE_NO2); int An_2 = get_addr_dta(CH_VALUE_NO2);
ratio0 = (float)An_0/(float)A0_0*(1023.0-A0_0)/(1023.0-An_0); ratio0 = (float)An_0/(float)A0_0*(1023.0-A0_0)/(1023.0-An_0);
ratio1 = (float)An_1/(float)A0_1*(1023.0-A0_1)/(1023.0-An_1); ratio1 = (float)An_1/(float)A0_1*(1023.0-A0_1)/(1023.0-An_1);
ratio2 = (float)An_2/(float)A0_2*(1023.0-A0_2)/(1023.0-An_2); ratio2 = (float)An_2/(float)A0_2*(1023.0-A0_2)/(1023.0-An_2);
} }
float c = 0; float c = 0;
switch(gas) switch(gas)
{ {
case CO: case CO:
{ {
c = pow(ratio1, -1.179)*4.385; //mod by jack c = MutichannelGasSensor_pow(ratio1, -1.179)*4.385; //mod by jack
break; break;
} }
case NO2: case NO2:
{ {
c = pow(ratio2, 1.007)/6.855; //mod by jack c = MutichannelGasSensor_pow(ratio2, 1.007)/6.855; //mod by jack
break; break;
} }
case NH3: case NH3:
{ {
c = pow(ratio0, -1.67)/1.47; //modi by jack c = MutichannelGasSensor_pow(ratio0, -1.67)/1.47; //modi by jack
break; break;
} }
case C3H8: //add by jack case C3H8: //add by jack
{ {
c = pow(ratio0, -2.518)*570.164; c = MutichannelGasSensor_pow(ratio0, -2.518)*570.164;
break; break;
} }
case C4H10: //add by jack case C4H10: //add by jack
{ {
c = pow(ratio0, -2.138)*398.107; c = MutichannelGasSensor_pow(ratio0, -2.138)*398.107;
break; break;
} }
case GAS_CH4: //add by jack case GAS_CH4: //add by jack
{ {
c = pow(ratio1, -4.363)*630.957; c = MutichannelGasSensor_pow(ratio1, -4.363)*630.957;
break; break;
} }
case H2: //add by jack case H2: //add by jack
{ {
c = pow(ratio1, -1.8)*0.73; c = MutichannelGasSensor_pow(ratio1, -1.8)*0.73;
break; break;
} }
case C2H5OH: //add by jack case C2H5OH: //add by jack
{ {
c = pow(ratio1, -1.552)*1.622; c = MutichannelGasSensor_pow(ratio1, -1.552)*1.622;
break; break;
} }
default: default:
break; break;
} }
if(2==__version)ledOff(); if(2==__version)ledOff();
return isnan(c)?-3:c; return isnan(c)?-3:c;
} }
@ -474,7 +498,7 @@ void MutichannelGasSensor::doCalibrate(void)
a0 = get_addr_dta(CH_VALUE_NH3); a0 = get_addr_dta(CH_VALUE_NH3);
a1 = get_addr_dta(CH_VALUE_CO); a1 = get_addr_dta(CH_VALUE_CO);
a2 = get_addr_dta(CH_VALUE_NO2); a2 = get_addr_dta(CH_VALUE_NO2);
Serial.print(a0); Serial.print(a0);
Serial.print('\t'); Serial.print('\t');
Serial.print(a1); Serial.print(a1);
@ -482,44 +506,44 @@ void MutichannelGasSensor::doCalibrate(void)
Serial.print(a2); Serial.print(a2);
Serial.println('\t'); Serial.println('\t');
ledOn(); ledOn();
int cnt = 0; int cnt = 0;
for(i=0; i<20; i++) for(i=0; i<20; i++)
{ {
if((a0 - get_addr_dta(CH_VALUE_NH3)) > 2 || (get_addr_dta(CH_VALUE_NH3) - a0) > 2)cnt++; if((a0 - get_addr_dta(CH_VALUE_NH3)) > 2 || (get_addr_dta(CH_VALUE_NH3) - a0) > 2)cnt++;
if((a1 - get_addr_dta(CH_VALUE_CO)) > 2 || (get_addr_dta(CH_VALUE_CO) - a1) > 2)cnt++; if((a1 - get_addr_dta(CH_VALUE_CO)) > 2 || (get_addr_dta(CH_VALUE_CO) - a1) > 2)cnt++;
if((a2 - get_addr_dta(CH_VALUE_NO2)) > 2 || (get_addr_dta(CH_VALUE_NO2) - a2) > 2)cnt++; if((a2 - get_addr_dta(CH_VALUE_NO2)) > 2 || (get_addr_dta(CH_VALUE_NO2) - a2) > 2)cnt++;
if(cnt>5) if(cnt>5)
{ {
break; break;
} }
delay(1000); delay(1000);
} }
ledOff(); ledOff();
if(cnt <= 5)break; if(cnt <= 5)break;
delay(200); delay(200);
} }
Serial.print("write user adc value: "); Serial.print("write user adc value: ");
Serial.print(a0);Serial.print('\t'); Serial.print(a0);Serial.print('\t');
Serial.print(a1);Serial.print('\t'); Serial.print(a1);Serial.print('\t');
Serial.print(a2);Serial.println('\t'); Serial.print(a2);Serial.println('\t');
unsigned char tmp[7]; unsigned char tmp[7];
tmp[0] = 7; tmp[0] = 7;
tmp[1] = a0>>8; tmp[1] = a0>>8;
tmp[2] = a0&0xff; tmp[2] = a0&0xff;
tmp[3] = a1>>8; tmp[3] = a1>>8;
tmp[4] = a1&0xff; tmp[4] = a1&0xff;
tmp[5] = a2>>8; tmp[5] = a2>>8;
tmp[6] = a2&0xff; tmp[6] = a2&0xff;
write_i2c(i2cAddress, tmp, 7); write_i2c(i2cAddress, tmp, 7);
} }
} }
@ -563,7 +587,7 @@ void MutichannelGasSensor::display_eeprom()
Serial.println("ERROR: display_eeprom() is NOT support by V1 firmware."); Serial.println("ERROR: display_eeprom() is NOT support by V1 firmware.");
return ; return ;
} }
Serial.print("ADDR_IS_SET = "); Serial.println(get_addr_dta(CMD_READ_EEPROM, ADDR_IS_SET)); Serial.print("ADDR_IS_SET = "); Serial.println(get_addr_dta(CMD_READ_EEPROM, ADDR_IS_SET));
Serial.print("ADDR_FACTORY_ADC_NH3 = "); Serial.println(get_addr_dta(CMD_READ_EEPROM, ADDR_FACTORY_ADC_NH3)); Serial.print("ADDR_FACTORY_ADC_NH3 = "); Serial.println(get_addr_dta(CMD_READ_EEPROM, ADDR_FACTORY_ADC_NH3));
Serial.print("ADDR_FACTORY_ADC_CO = "); Serial.println(get_addr_dta(CMD_READ_EEPROM, ADDR_FACTORY_ADC_CO)); Serial.print("ADDR_FACTORY_ADC_CO = "); Serial.println(get_addr_dta(CMD_READ_EEPROM, ADDR_FACTORY_ADC_CO));
@ -581,7 +605,7 @@ float MutichannelGasSensor::getR0(unsigned char ch) // 0:CH3, 1:CO, 2:NO
Serial.println("ERROR: getR0() is NOT support by V1 firmware."); Serial.println("ERROR: getR0() is NOT support by V1 firmware.");
return -1; return -1;
} }
int a = 0; int a = 0;
switch(ch) switch(ch)
{ {
@ -590,19 +614,19 @@ float MutichannelGasSensor::getR0(unsigned char ch) // 0:CH3, 1:CO, 2:NO
Serial.print("a_ch3 = "); Serial.print("a_ch3 = ");
Serial.println(a); Serial.println(a);
break; break;
case 1: // CO case 1: // CO
a = get_addr_dta(CMD_READ_EEPROM, ADDR_USER_ADC_CO); a = get_addr_dta(CMD_READ_EEPROM, ADDR_USER_ADC_CO);
Serial.print("a_co = "); Serial.print("a_co = ");
Serial.println(a); Serial.println(a);
break; break;
case 2: // NO2 case 2: // NO2
a = get_addr_dta(CMD_READ_EEPROM, ADDR_USER_ADC_NO2); a = get_addr_dta(CMD_READ_EEPROM, ADDR_USER_ADC_NO2);
Serial.print("a_no2 = "); Serial.print("a_no2 = ");
Serial.println(a); Serial.println(a);
break; break;
default:; default:;
} }
@ -612,31 +636,31 @@ float MutichannelGasSensor::getR0(unsigned char ch) // 0:CH3, 1:CO, 2:NO
float MutichannelGasSensor::getRs(unsigned char ch) // 0:CH3, 1:CO, 2:NO2 float MutichannelGasSensor::getRs(unsigned char ch) // 0:CH3, 1:CO, 2:NO2
{ {
if(__version == 1) if(__version == 1)
{ {
Serial.println("ERROR: getRs() is NOT support by V1 firmware."); Serial.println("ERROR: getRs() is NOT support by V1 firmware.");
return -1; return -1;
} }
int a = 0; int a = 0;
switch(ch) switch(ch)
{ {
case 0: // NH3 case 0: // NH3
a = get_addr_dta(1); a = get_addr_dta(1);
break; break;
case 1: // CO case 1: // CO
a = get_addr_dta(2); a = get_addr_dta(2);
break; break;
case 2: // NO2 case 2: // NO2
a = get_addr_dta(3); a = get_addr_dta(3);
break; break;
default:; default:;
} }
float r = 56.0*(float)a/(1023.0-(float)a); float r = 56.0*(float)a/(1023.0-(float)a);
return r; return r;
} }
@ -645,12 +669,12 @@ float MutichannelGasSensor::getRs(unsigned char ch) // 0:CH3, 1:CO, 2:NO
// 2. change adc value of R0 to default // 2. change adc value of R0 to default
void MutichannelGasSensor::factory_setting() void MutichannelGasSensor::factory_setting()
{ {
unsigned char tmp[7]; unsigned char tmp[7];
unsigned char error; unsigned char error;
unsigned char address = 0; unsigned char address = 0;
for(address = 1; address < 127; address++ ) for(address = 1; address < 127; address++ )
{ {
// The i2c_scanner uses the return value of // The i2c_scanner uses the return value of
@ -661,11 +685,11 @@ void MutichannelGasSensor::factory_setting()
if (error == 0) if (error == 0)
{ {
// change i2c to 0x04 // change i2c to 0x04
Serial.print("I2C address is: 0x"); Serial.print("I2C address is: 0x");
Serial.println(address, HEX); Serial.println(address, HEX);
Serial.println("Change I2C address to 0x04"); Serial.println("Change I2C address to 0x04");
dta_test[0] = CMD_CHANGE_I2C; dta_test[0] = CMD_CHANGE_I2C;
dta_test[1] = 0x04; dta_test[1] = 0x04;
write_i2c(address, dta_test, 2); write_i2c(address, dta_test, 2);
@ -680,15 +704,15 @@ void MutichannelGasSensor::factory_setting()
unsigned int a0 = get_addr_dta(CMD_READ_EEPROM, ADDR_FACTORY_ADC_NH3); unsigned int a0 = get_addr_dta(CMD_READ_EEPROM, ADDR_FACTORY_ADC_NH3);
unsigned int a1 = get_addr_dta(CMD_READ_EEPROM, ADDR_FACTORY_ADC_CO); unsigned int a1 = get_addr_dta(CMD_READ_EEPROM, ADDR_FACTORY_ADC_CO);
unsigned int a2 = get_addr_dta(CMD_READ_EEPROM, ADDR_FACTORY_ADC_NO2); unsigned int a2 = get_addr_dta(CMD_READ_EEPROM, ADDR_FACTORY_ADC_NO2);
tmp[0] = 7; tmp[0] = 7;
tmp[1] = a0>>8; tmp[1] = a0>>8;
tmp[2] = a0&0xff; tmp[2] = a0&0xff;
tmp[3] = a1>>8; tmp[3] = a1>>8;
tmp[4] = a1&0xff; tmp[4] = a1&0xff;
tmp[5] = a2>>8; tmp[5] = a2>>8;
tmp[6] = a2&0xff; tmp[6] = a2&0xff;
delay(100); delay(100);
write_i2c(i2cAddress, tmp, 7); write_i2c(i2cAddress, tmp, 7);
delay(100); delay(100);
@ -699,13 +723,13 @@ void MutichannelGasSensor::change_i2c_address(unsigned char addr)
dta_test[0] = CMD_CHANGE_I2C; dta_test[0] = CMD_CHANGE_I2C;
dta_test[1] = addr; dta_test[1] = addr;
write_i2c(i2cAddress, dta_test, 2); write_i2c(i2cAddress, dta_test, 2);
Serial.print("FUNCTION: CHANGE I2C ADDRESS: 0X"); Serial.print("FUNCTION: CHANGE I2C ADDRESS: 0X");
Serial.print(i2cAddress, HEX); Serial.print(i2cAddress, HEX);
Serial.print(" > 0x"); Serial.print(" > 0x");
Serial.println(addr, HEX); Serial.println(addr, HEX);
i2cAddress = addr; i2cAddress = addr;
} }