/******************************************************************************
* Description:
* DPS368 going-up and down - more than a rocket!
* DIY Rocket not only for fun but learning about barometric pressure
* with the help of Arduino IDE & Infineon's KIT_DPS368_2GO (XMC1100 XMC2Go)
* https://www.hackster.io/projects/e62bd0
* 2023/12, Holger Wech
*
* Disclaimer:
* THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*******************************************************************************/
#include <Dps3xx.h>
#include <LED.h>
#include <Adafruit_NeoPixel.h>
// Dps3xx Opject
Dps3xx Dps3xxPressureSensor = Dps3xx();
//
// Altimeter
//
#define MOLAR_MASS (0.02896) // Mean molar mass of earth's air in kg/mol
#define GRAVITATIONAL_ACCEL (9.80620) // Acceleration due to gravity in m/(s^2)
#define GAS_CONSTANT (8.314) // Universal gas constant in J/Kmol
#define PRESSURE_AT_SEA_LEVEL (1013)
/* Structure for Altimeter data */
typedef struct{
float temperature;
float pressure;
float height_base_pressure;
float height_absolute;
float height_relative;
}Altimeter_t;
Altimeter_t stcAltimeter;
/*******************************************************************************
** Function Name: AltimeterReadSensorData()
********************************************************************************
** Summary:
** The function reads the actual pressure and temperature value from DPS3xx sensor
** and stores the values to dedicated global variables that can be read by functions
** AltimeterGetPressure(), AltimeterGetTemperature()
**
** \retval error code (should be CY_RSLT_SUCCESS)
*******************************************************************************/
uint32_t AltimeterGetSensorData()
{
int32_t ret1, ret2;
/*
* lets the Dps3xx perform a Single temperature measurement with the last (or standard) configuration
* The result will be written to the parameter temperature
* ret = Dps3xxPressureSensor.measureTempOnce(temperature);
* the commented line below does exactly the same as the one above, but you can also config the precision
* oversampling can be a value from 0 to 7
* the Dps 3xx will perform 2^oversampling internal temperature measurements and combine them to one result with higher precision
* measurements with higher precision take more time, consult datasheet for more information
*/
ret1 = Dps3xxPressureSensor.measureTempOnce(stcAltimeter.temperature, 7);
/*
* Pressure measurement behaves like temperature measurement
* ret = Dps3xxPressureSensor.measurePressureOnce(pressure);
*/
ret2 = Dps3xxPressureSensor.measurePressureOnce(stcAltimeter.pressure, 7);
if (ret1)
{
Serial.println("Sensor Temp error!");
return (1);
}
else if (ret2)
{
Serial.println("Sensor Pressure error!");
return (2);
}
else
{
return (0);
}
}
/*******************************************************************************
** \brief Function AltimeterReadPressure()
**
** The function returns the last read pressure sensor.
**
** \pre Call AltimeterGetSensorData() before reading the data
**
** \param [in] none
**
** \retval float stcAltimeter.pressure
*******************************************************************************/
float AltimeterReadPressure()
{
return (stcAltimeter.pressure);
}
/*******************************************************************************
** \brief Function AltimeterReadTemperature()
**
** The function returns the last read pressure sensor.
**
** \pre Call AltimeterGetSensorData() before reading the data
**
** \param [in] none
**
** \retval float stcAltimeter.temperature
*******************************************************************************/
float AltimeterReadTemperature()
{
return (stcAltimeter.temperature);
}
/*******************************************************************************
** \brief Function AltimeterReadBaseHeightPressure()
**
** The function returns the last saved AltimeterReadBaseHeightPressure.
**
** \pre AltimeterSetBaseHeight before reading the data
**
** \param [in] none
**
** \retval float stcAltimeter.height_base_pressure
*******************************************************************************/
float AltimeterReadBaseHeightPressure()
{
return (stcAltimeter.height_base_pressure);
}
/*******************************************************************************
** \brief Function AltimeterReadHeightAbsolute()
**
** The function returns the last calculated absolute height
**
** \pre Call AltimeterCalcHeightAbsolute() before reading the data
**
** \param [in] none
**
** \retval float stcAltimeter.height_absolute
*******************************************************************************/
float AltimeterReadHeightAbsolute()
{
return (stcAltimeter.height_absolute);
}
/*******************************************************************************
** \brief Function AltimeterReadHeightRelative()
**
** The function returns the last calculated relative height
**
** \pre Call AltimeterCalcHeightAbsolute() before reading the data
**
** \param [in] none
**
** \retval float stcAltimeter.height_relative
*******************************************************************************/
float AltimeterReadHeightRelative()
{
return (stcAltimeter.height_relative);
}
/*******************************************************************************
** \brief Function AltimeterSetBaseHeight()
**
** The function is called when the user chooses the base height
** what refelcts the '0 Meter' reference height and
** stores the value in stcAltimeter data structure.
** This value is used as a reference for calculation of relative height.
**
** \pre Call AltimeterGetSensorData() before reading the data
**
** \param [in] none
**
** \retval none
*******************************************************************************/
void AltimeterSetBaseHeight()
{
stcAltimeter.height_base_pressure = stcAltimeter.pressure;
}
/*******************************************************************************
** \brief Function AltimeterCalcHeightAbsolute()
**
** The function calculates the height of the sensor above sea level and
** stores the value in stcAltimeter data structure.
**
** \pre Call AltimeterGetSensorData() before calculating the height
**
** \param [in] none
**
** \retval none
*******************************************************************************/
void AltimeterCalcHeightAbsolute()
{
float pressure_ratio;
float temp_constant;
float absolute_height;
float temp_val;
/* Convert pressure in pascal to pressure in mbar */
float pressure_mbar = stcAltimeter.pressure/100;
/* Calculating the ration of pressure at sea level and current pressure */
pressure_ratio = (PRESSURE_AT_SEA_LEVEL/pressure_mbar);
/* Converting temperature from Celcius to Kelvin */
temp_val = (stcAltimeter.temperature + 273.15f);
/* Using the Barometric formula. Refer to the Blog mentioned in the readme for further details */
temp_constant = ((GAS_CONSTANT * temp_val)/(MOLAR_MASS * GRAVITATIONAL_ACCEL));
stcAltimeter.height_absolute = ((temp_constant * log(pressure_ratio)));
}
/*******************************************************************************
** \brief Function AltimeterCalcHeightRelative()
**
** The function calculates the height of the sensor above or below the
** chosen base height and stores the value in stcAltimeter data structure.
**
** \pre Call AltimeterGetSensorData() before calculating the height
**
** \param [in] none
**
** \retval none
*******************************************************************************/
void AltimeterCalcHeightRelative(void)
{
float pressure_ratio;
float temp_constant;
float relative_height;
float temp_val;
/* Absolute height difference calculation */
pressure_ratio = (stcAltimeter.height_base_pressure / stcAltimeter.pressure);
/* Converting temperature from Celcius to Kelvin */
temp_val = stcAltimeter.temperature + 273.15f;
temp_constant = ((GAS_CONSTANT * temp_val)/(MOLAR_MASS * GRAVITATIONAL_ACCEL));
stcAltimeter.height_relative = ((temp_constant * log(pressure_ratio)) * 100);
}
//
// NEOPIXEL / WS2812
//
#define WS2812_PIN 1
#define NUMPIXELS 14
Adafruit_NeoPixel pixels(NUMPIXELS, WS2812_PIN, NEO_GRB + NEO_KHZ800);
void setAllPixel(uint32_t c)
{
uint16_t i;
for (i=0; i<NUMPIXELS; i++)
{
pixels.setPixelColor(i, c);
}
}
void setPixelLeftAll(uint32_t c)
{
uint16_t i;
for (i=0; i<NUMPIXELS; i=i+2)
{
pixels.setPixelColor(i, c);
}
}
void setPixelLeft(uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3, uint32_t c4)
{
pixels.setPixelColor(4, c0);
pixels.setPixelColor(3, c1);
pixels.setPixelColor(2, c2);
pixels.setPixelColor(1, c3);
pixels.setPixelColor(0, c4);
}
void setPixelRightAll(uint32_t c)
{
uint16_t i;
for (i=1; i<NUMPIXELS; i=i+2)
{
pixels.setPixelColor(i, c);
}
}
void setPixelRight(uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3, uint32_t c4)
{
pixels.setPixelColor(5, c0);
pixels.setPixelColor(6, c1);
pixels.setPixelColor(7, c2);
pixels.setPixelColor(8, c3);
pixels.setPixelColor(9, c4);
}
//
// Simple LED just for testing
//
/* Create an LED object just for testing */
LED Led;
//
// GLOBAL VARIABLES
//
typedef enum {
RS_INIT = 0,
RS_START,
RS_FLY,
RS_BACK,
} enRocketState_t;
enRocketState_t enRocketState = RS_INIT;
void setup()
{
Led.Add( LED1 ); // Configure the LEDs
Led.Off( LED1 ); // Set default state of LEDs
Led.Add( LED2 ); // Configure the LEDs
Led.On( LED2 ); // Set default state of LEDs
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
pixels.setBrightness(255);
Serial.begin(115200);
while (!Serial);
/*
* Call begin to initialize Dps3xxPressureSensor
* The parameter 0x76 is the bus address. The default address is 0x77 and does not need to be given.
* Dps3xxPressureSensor.begin(Wire, 0x76);
* Use the line below instead of the one above to use the default I2C address.
* if you are using the Pressure 3 click Board, you need 0x76
*/
Dps3xxPressureSensor.begin(Wire);
Serial.println("Init complete!");
// Initialize Altimeter - Store Ground-Floor '0-meter' value
delay(200);
AltimeterGetSensorData();
delay(200);
AltimeterGetSensorData();
delay(200);
AltimeterGetSensorData();
delay(200);
if (0 != AltimeterGetSensorData())
{
Serial.println("*** ERROR Sensor");
}
else
{
Serial.print("Pressure : ");
Serial.print(AltimeterReadPressure());
Serial.println(" Pascal");
Serial.print("Temperature: ");
Serial.print(AltimeterReadTemperature());
Serial.println(" Celsius");
}
AltimeterCalcHeightAbsolute();
AltimeterSetBaseHeight(); // Store Ground-Floor '0-meter' value
AltimeterCalcHeightRelative();
Serial.print("Absolute Height: "); Serial.print(AltimeterReadHeightAbsolute()); Serial.println(" m");
Serial.print("Relative Height: "); Serial.print(AltimeterReadHeightRelative()); Serial.println(" m");
delay(200);
enRocketState = RS_INIT;
}
uint32_t u32Time;
uint32_t u32TimeAltimeter;
uint32_t u32InitLed;
void loop()
{
uint32_t u32HeightMeter;
u32Time = u32Time + 1;
/*
// For testing the loop timer
if (u32Time >= 50)
{
u32Time = 0;
Serial.println("1 sec");
}
*/
/*
u32TimeAltimeter = u32TimeAltimeter + 1;
if (u32TimeAltimeter >= 10)
{
//
// Altimeter Height calculation
//
if (0 != AltimeterGetSensorData())
{
Serial.println("*** ERROR Sensor");
}
else
{
AltimeterCalcHeightRelative();
//Serial.print("Relative Height: "); Serial.print(AltimeterReadHeightRelative()/100); Serial.print(" m @ Temperature: "); Serial.print(AltimeterReadTemperature()); Serial.println(" Celcius");
}
}
*/
switch (enRocketState)
{
case RS_INIT : // Ignition phase ... wait for take-off
u32InitLed = u32InitLed + 1;
//Serial.print(u32InitLed); Serial.println(" : u32InitLed");
if (2 == u32InitLed)
{
setPixelLeft (pixels.Color(20, 20, 20), pixels.Color( 50, 50, 50), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20));
setPixelRight(pixels.Color(20, 20, 20), pixels.Color( 50, 50, 50), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20));
pixels.show();
} else
if (4 == u32InitLed)
{
setPixelLeft (pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color( 50, 50, 50), pixels.Color(100,100,100), pixels.Color(20, 20, 20));
setPixelRight(pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color( 50, 50, 50), pixels.Color(50, 50, 50), pixels.Color(20, 20, 20));
pixels.show();
} else
if (6 == u32InitLed)
{
setPixelLeft (pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(200, 100, 0), pixels.Color(200, 200, 0), pixels.Color(20, 20, 20));
setPixelRight(pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(200, 100, 0), pixels.Color(200, 200, 0), pixels.Color(20, 20, 20));
pixels.show();
} else
if (10 == u32InitLed)
{
setPixelLeft (pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(100, 100, 0), pixels.Color(255, 0, 0));
setPixelRight(pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(100, 100, 0), pixels.Color(255, 0, 0));
pixels.show();
if (0 != AltimeterGetSensorData())
{
Serial.println("*** ERROR Sensor");
}
else
{
AltimeterCalcHeightRelative();
//Serial.print("Relative Height: "); Serial.print(AltimeterReadHeightRelative()/100); Serial.print(" m @ Temperature: "); Serial.print(AltimeterReadTemperature()); Serial.println(" Celcius");
}
if (AltimeterReadHeightRelative() > 35)
{
enRocketState = RS_START;
}
} else
if (15 == u32InitLed)
{
u32InitLed = 0;
setPixelLeft (pixels.Color(50, 50, 50), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20));
setPixelRight(pixels.Color(50, 50, 50), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20), pixels.Color(20, 20, 20));
pixels.show();
}
delay(20);
break;
case RS_START : // Ready for start 'hysteresis' Does it fly or not?
if (0 != AltimeterGetSensorData())
{
Serial.println("*** ERROR Sensor");
}
else
{
AltimeterCalcHeightRelative();
//Serial.print("Relative Height: "); Serial.print(AltimeterReadHeightRelative()/100); Serial.print(" m @ Temperature: "); Serial.print(AltimeterReadTemperature()); Serial.println(" Celcius");
}
if (AltimeterReadHeightRelative() > 40)
{
enRocketState = RS_FLY;
}
if (AltimeterReadHeightRelative() < 20)
{
enRocketState = RS_INIT;
}
delay(100);
break;
case RS_FLY : // Change the color depending on the height
// Get the altitude
if (0 != AltimeterGetSensorData())
{
Serial.println("*** ERROR Sensor");
}
else
{
AltimeterCalcHeightRelative();
//Serial.print("Relative Height: "); Serial.print(AltimeterReadHeightRelative()/100); Serial.print(" m @ Temperature: "); Serial.print(AltimeterReadTemperature()); Serial.println(" Celcius");
}
/*
// Height values used for the lift video, 5 floors
if (AltimeterReadHeightRelative() > 1640.0f) { setAllPixel(pixels.Color(0xFF, 0xFF, 0xFF)); }
else if (AltimeterReadHeightRelative() > 1375.0f) { setAllPixel(pixels.Color(0xFF, 0x00, 0x00)); }
else if (AltimeterReadHeightRelative() > 1110.0f) { setAllPixel(pixels.Color(0x00, 0x00, 0xFF)); }
else if (AltimeterReadHeightRelative() > 845.0f) { setAllPixel(pixels.Color(0xFF, 0x00, 0xFF)); }
else if (AltimeterReadHeightRelative() > 580.0f) { setAllPixel(pixels.Color(0x00, 0xFF, 0x00)); }
else if (AltimeterReadHeightRelative() > 315.0f) { setAllPixel(pixels.Color(0x00, 0xFF, 0xFF)); }
else if (AltimeterReadHeightRelative() > 50.0f) { setAllPixel(pixels.Color(0xFF, 0xFF, 0x00)); }
else if (AltimeterReadHeightRelative() < 20.0f) { setAllPixel(pixels.Color(0xFF, 0xFF, 0xFF)); enRocketState = RS_BACK; }
*/
if (AltimeterReadHeightRelative() > 5000.0f) { setAllPixel(pixels.Color(0xFF, 0xFF, 0xFF)); }
else if (AltimeterReadHeightRelative() > 4000.0f) { setAllPixel(pixels.Color(0xFF, 0x00, 0x00)); }
else if (AltimeterReadHeightRelative() > 3000.0f) { setAllPixel(pixels.Color(0x00, 0x00, 0xFF)); }
else if (AltimeterReadHeightRelative() > 2000.0f) { setAllPixel(pixels.Color(0xFF, 0x00, 0xFF)); }
else if (AltimeterReadHeightRelative() > 1000.0f) { setAllPixel(pixels.Color(0x00, 0xFF, 0x00)); }
else if (AltimeterReadHeightRelative() > 350.0f) { setAllPixel(pixels.Color(0x00, 0xFF, 0xFF)); }
else if (AltimeterReadHeightRelative() > 50.0f) { setAllPixel(pixels.Color(0xFF, 0xFF, 0x00)); }
else if (AltimeterReadHeightRelative() < 20.0f) { setAllPixel(pixels.Color(0xFF, 0xFF, 0xFF)); enRocketState = RS_BACK; }
pixels.show();
delay(50);
break;
case RS_BACK : // wait for restart (switch off/on)
break;
default : enRocketState = RS_INIT;
} // switch (enRocketState)
} // void loop()
/* END */
Comments
Please log in or sign up to comment.