// * oXs_sdp3x.cpp *** Version, in der die DEBUG Einfügungen entfernt wurden. ****************
// * Damit ist die Datenbearbeitung übersichtlicher erkennbar. ******** Tempo 17.Mai 2020 ****
#include "oXs_sdp3x.h"
extern unsigned long micros( void ) ;
extern unsigned long millis( void ) ;
extern void delay(unsigned long ms) ;
OXS_SDP3X::OXS_SDP3X(uint8_t addr)
{ // constructor
_addr=addr;
}
//***************** Setup the SDP3X sensor **************************************************
void OXS_SDP3X::setup()
{
airSpeedData.airSpeed.available = false ;
I2c.begin() ;
I2c.timeOut( 80); //initialise the time out in order to avoid infinite loop
// set the sensor in continous mode with averaging (send a command 0X3615)
I2c.write(_addr, (uint8_t) 0X36 , (uint8_t) 0X15);
delay(20); // wait 20msec in order to get the first data (datasheet says 8 msec)
// read the sensor to get the initial temperature and the scaling factor
I2CErrorCodeSdp3x = I2c.read( _addr, 9 ) ; //read 9 bytes from the device;
nextPressureReadMillis = millis() + 2; //
nextAirSpeedMillis = nextPressureReadMillis + 200 ;
if (I2CErrorCodeSdp3x == 0)
{
data[0] = I2c.receive() ; // discard diffPressure
data[1] = I2c.receive() ; // discard diffPressure
//int16_t dp_raw = (int16_t)data[0] << 8 | data[1];
data[0] = I2c.receive() ; // discard this byte = CRC
data[0] = I2c.receive() ;
data[1] = I2c.receive() ;
airSpeedData.temperature4525 = ((int16_t)data[0] << 8 | data[1]) / 200.0 ;
// sdp3x use a scale factor of 200 for temp
temperatureKelvinSdp3x = 273.15 + airSpeedData.temperature4525 ; // in Kelvin
data[0] = I2c.receive() ; // discard this byte = CRC
data[0] = I2c.receive() ;
data[1] = I2c.receive() ;
dpScaleSdp3x = 966.0 / 1013.0 / ((int16_t)data[0] << 8 | data[1]);
// datasheet correction of 966/actual pressure in mbar; it is estimated with 1013
}
} //end of setup
//****** readSensor - Read differential pressure + temperature from the 4525DO ************
void OXS_SDP3X::readSensor()
{
unsigned long airSpeedMillis = millis() ;
if ( airSpeedMillis >= nextPressureReadMillis)
{ // do not read the sensor if there is less than 0.5 msec since previous read
nextPressureReadMillis = airSpeedMillis + 2 ;
I2CErrorCodeSdp3x = I2c.read( _addr, 2 ) ; //read 2 bytes from the device;
if( I2CErrorCodeSdp3x == 0)
{ // when no read error, we calculate
data[0] = I2c.receive() ;
data[1] = I2c.receive() ;
airSpeedData.difPressureAdc_zero = ((int16_t) (data[0] << 8) + data[1] )
* dpScaleSdp3x ; // diffPressure in pa
#define FILTERING_SDP3X_MIN 0.01 // oXs Filter aus, wenn MIN=MAX=1 hier gesetzt.
#define FILTERING_SDP3X_MAX 0.1 // oXs Filter aus, wenn MIN=MAX=1 hier gesetzt.
#define FILTERING_SDP3X_MIN_AT 10 // when abs is less than MIN_AT , apply MIN
#define FILTERING_SDP3X_MAX_AT 100 // when abs is more than MAX_AT , apply MAX
// (interpolation in between)
float abs_deltaDifPressure = abs(airSpeedData.difPressureAdc_zero-smoothDifPressure);
if (abs_deltaDifPressure <= FILTERING_SDP3X_MIN_AT)
{
expoSmooth_auto = FILTERING_SDP3X_MIN ;
}
else if (abs_deltaDifPressure >= FILTERING_SDP3X_MAX_AT)
{
expoSmooth_auto = FILTERING_SDP3X_MAX ;
}
else
{
expoSmooth_auto = FILTERING_SDP3X_MIN + (FILTERING_SDP3X_MAX - FILTERING_SDP3X_MIN)
* (abs_deltaDifPressure - FILTERING_SDP3X_MIN_AT)
/ (FILTERING_SDP3X_MAX_AT - FILTERING_SDP3X_MIN_AT) ;
}
smoothDifPressure += expoSmooth_auto
* ( airSpeedData.difPressureAdc_zero - smoothDifPressure ) ; //
// calculate airspeed based on pressure, altitude and temperature
// airspeed (m/sec) = sqr(2 * differential_pressure_in_Pa / air_mass_kg_per_m3)
// air_mass_kg_per_m3 = pressure_in_pa / (287.05 * (Temp celcius + 273.15))
// so airspeed m/sec = sqr( 2 * 287.05 * differential_pressure_pa
// * (temperature Celsius + 273.15) / pressure_in_pa )
// so at 15° and 1013hpa in cm/sec = 127.79 (=sqr(2*287.05*288.15/101300))
// or rawAirSpeed cm/sec = 2396 * sqrt( (float) abs(smoothDifPressureAdc)
// * temperatureKelvin / actualPressure) );
// in cm/sec ; actual pressure must be in pa (so 101325 about at sea level)
#ifdef AIRSPEED_AT_SEA_LEVEL_AND_15C
airSpeedData.smoothAirSpeed = 127.79 * sqrt( (float) ( abs(smoothDifPressure) ) );
// indicated airspeed is calculated at 15 Celsius and 101325 pascal
#else
airSpeedData.smoothAirSpeed = 2396.0 * sqrt( (float) ( abs(smoothDifPressure)
* temperatureKelvinSdp3x / actualPressure) );
// in cm/sec ; actual pressure must be in pa (so 101325 about at sea level)
#endif
if (smoothDifPressure < 0) airSpeedData.smoothAirSpeed = - airSpeedData.smoothAirSpeed;
// apply the sign
} // end no error on I2C
if (airSpeedMillis > nextAirSpeedMillis)
{ // publish airspeed only once every xx ms
nextAirSpeedMillis = airSpeedMillis + 200 ;
if ( airSpeedData.smoothAirSpeed > 0)
{ // normally send only if positive and greater than 300 cm/sec,
// otherwise send 0 but for test we keep all values to check for drift
#ifdef AIRSPEED_IN_KMH
// uncomment this line if AIR speed has to be in knot instead of km/h
airSpeedData.airSpeed.value = airSpeedData.smoothAirSpeed * 0.36 ;
// from cm/sec to 1/10 km/h
#else
airSpeedData.airSpeed.value = airSpeedData.smoothAirSpeed * 0.1943844492 ;
// from cm/sec to 1/10 knot/h
#endif
}
else
{
airSpeedData.airSpeed.value = 0 ;
}
airSpeedData.airSpeed.available = true ;
} // end of process every xx millis
} // end of process every 2 millis
} // End of readSensor
**********************************************************************************************
**********************************************************************************************
// * 0Xs_sdp3x.h ***** Version, in der die DEBUG Einfügungen entfernt wurden. ****************
// * Damit ist die Datenbearbeitung übersichtlicher erkennbar. ******** Tempo 17.Mai 2020 ****
#ifndef OXS_sdp3x_h
#define OXS_sdp3x_h
#include <Arduino.h>
#include "oXs_config_basic.h"
#include "oXs_config_advanced.h"
#include "oXs_config_macros.h"
#include "I2C.h"
#include "oXs_4525.h"
/*
struct AIRSPEEDDATA
{
float temperatureSdp3x; // in Celsius , used when compensation is calculated
float difPressure; // in Pa
struct ONE_MEASUREMENT airSpeed ; // in 1/10 km/h or 1/10 knots (no decimal)
float smoothAirSpeed ; //cm/sec ; use in glider ratio
//unsigned long lastCommand2Micros ; // used to avoid some task
// (reading voltage sensor, currentsensor, ..) when barometric data should
// be soon available for reading
// = micro divided by 2 to avoid overflow on comparison
};
*/
extern float actualPressure ;
class OXS_SDP3X
{
public:
OXS_SDP3X(uint8_t addr) ;
AIRSPEEDDATA airSpeedData ;
void setup();
void readSensor();
private:
uint8_t _addr;
uint8_t I2CErrorCodeSdp3x ;
float dpScaleSdp3x; // differential pressure scale factor
uint8_t data[2]; // get 2 bytes returned by SDP3X
float temperatureKelvinSdp3x; // in Kelvin
//float difPressure; // in Pa
float smoothDifPressure ; // in Pa
float expoSmooth_auto ;
unsigned long nextAirSpeedMillis ; //next time that airspeed must be available
unsigned long nextPressureReadMillis ; // next time that pressure can be read
// (datasheet says O.5msec)
}; // end class OXS_SDP3X
extern int32_t test1Value ;// used in order to test the transmission of any value
extern bool test1ValueAvailable ;
extern int32_t test2Value ;// used in order to test the transmission of any value
extern bool test2ValueAvailable ;
extern int32_t test3Value ;// used in order to test the transmission of any value
extern bool test3ValueAvailable ;
#endif // OXS_SDP3X
**********************************************************************************************
**********************************************************************************************