Sensor Basics Utility Library
These are basic features that could be used if required... But was something made in "spare time"
Source Code Location
Files:
components/sensor_board/sensor_basics/sensor_basics.h- Function declarations and documentationcomponents/sensor_board/sensor_basics/sensor_basics.c- Implementation
Dependencies:
result.h- Standard result/error code definitionsstdint.h- Integer type definitions
pH Sensor Functions
validate_ph_value()
Validates if a pH value is within the acceptable range (0-14).
/**
* @brief Validates if a pH value is within the acceptable range (0-14).
* @param ph_value The pH value to validate.
* @return RESULT_OK if the value is valid, RESULT_ERR_INVALID_DATA otherwise.
*/
result_t validate_ph_value(float ph_value);
Implementation:
result_t validate_ph_value(float ph_value) {
if (ph_value >= 0.0f && ph_value <= 14.0f) {
return RESULT_OK;
}
return RESULT_ERR_INVALID_DATA;
}
Parameters:
ph_value- Float value to validate (typical range: 0.0 to 14.0)
Return Values:
RESULT_OK- Value is within valid rangeRESULT_ERR_INVALID_DATA- Value is outside 0-14 range
Usage Example:
float ph_reading = ph_sensor.ph_value;
if (validate_ph_value(ph_reading) == RESULT_OK) {
LOG_INFO("pH sensor valid: %.2f", ph_reading);
diagnostics.ph_sensor.state = SENSOR_OPERATING;
} else {
LOG_ERROR("pH out of range: %.2f", ph_reading);
diagnostics.ph_sensor.state = SENSOR_ERROR;
diagnostics.ph_sensor.error_code = PHErrorCode_PH_INVALID_DATA;
}
Temperature Conversion Functions
celsius_to_fahrenheit()
Converts temperature from Celsius to Fahrenheit.
/**
* @brief Converts temperature from Celsius to Fahrenheit.
* @param celsius The temperature in Celsius.
* @param fahrenheit Pointer to a float where the converted Fahrenheit temperature will be stored.
* @return RESULT_OK on success, or RESULT_ERR_INVALID_ARG if fahrenheit is NULL.
*/
result_t celsius_to_fahrenheit(float celsius, float *fahrenheit);
Conversion Formula: °F = (°C × 9/5) + 32
Parameters:
celsius- Input temperature in Celsiusfahrenheit- Pointer to output variable (must not be NULL)
Return Values:
RESULT_OK- Conversion successfulRESULT_ERR_INVALID_ARG- fahrenheit pointer is NULL
Status: Currently commented out in implementation
Usage Example:
float temp_celsius = 25.0f;
float temp_fahrenheit;
if (celsius_to_fahrenheit(temp_celsius, &temp_fahrenheit) == RESULT_OK) {
LOG_INFO("Temperature: %.1f°C = %.1f°F", temp_celsius, temp_fahrenheit);
}
fahrenheit_to_celsius()
Converts temperature from Fahrenheit to Celsius.
/**
* @brief Converts temperature from Fahrenheit to Celsius.
* @param fahrenheit The temperature in Fahrenheit.
* @param celsius Pointer to a float where the converted Celsius temperature will be stored.
* @return RESULT_OK on success, or RESULT_ERR_INVALID_ARG if celsius is NULL.
*/
result_t fahrenheit_to_celsius(float fahrenheit, float *celsius);
Conversion Formula: °C = (°F - 32) × 5/9
Status: Currently commented out in implementation
IMU (Accelerometer) Functions
validate_accelerometer_value()
Validates if a single accelerometer value is within the typical range.
/**
* @brief Validates if an accelerometer value is within the typical range.
* @param accel_value The accelerometer value to validate.
* @return RESULT_OK if the value is valid, RESULT_ERR_INVALID_DATA otherwise.
*/
result_t validate_accelerometer_value(float accel_value);
Implementation:
result_t validate_accelerometer_value(float accel_value) {
if (accel_value >= -160.0f && accel_value <= 160.0f) {
return RESULT_OK;
}
return RESULT_ERR_INVALID_DATA;
}
Parameters:
accel_value- Single axis acceleration value in m/s²
Valid Range: -160.0 to +160.0 m/s² (typical ±16g sensor range)
Return Values:
RESULT_OK- Value is within valid rangeRESULT_ERR_INVALID_DATA- Value exceeds acceptable limits
Usage Example:
float accel_x = imu_data.accel[0];
if (validate_accelerometer_value(accel_x) == RESULT_OK) {
LOG_DEBUG("Accel X valid: %.2f m/s²", accel_x);
} else {
LOG_ERROR("Accel X out of range: %.2f m/s²", accel_x);
}
validate_imu_data()
Validates all three axes of accelerometer data simultaneously.
/**
* @brief Validates all three axes of accelerometer data.
* @param accel_x The acceleration value for the X-axis.
* @param accel_y The acceleration value for the Y-axis.
* @param accel_z The acceleration value for the Z-axis.
* @return RESULT_OK if all values are valid, RESULT_ERR_INVALID_DATA otherwise.
*/
result_t validate_imu_data(float accel_x, float accel_y, float accel_z);
Implementation:
result_t validate_imu_data(float accel_x, float accel_y, float accel_z) {
TRY(validate_accelerometer_value(accel_x));
TRY(validate_accelerometer_value(accel_y));
TRY(validate_accelerometer_value(accel_z));
return RESULT_OK;
}
Parameters:
accel_x- X-axis acceleration (m/s²)accel_y- Y-axis acceleration (m/s²)accel_z- Z-axis acceleration (m/s²)
Return Values:
RESULT_OK- All three axes within valid rangeRESULT_ERR_INVALID_DATA- Any axis exceeds acceptable limits
Usage Example:
if (validate_imu_data(imu_data.accel[0], imu_data.accel[1], imu_data.accel[2]) == RESULT_OK) {
LOG_INFO("IMU acceleration valid");
diagnostics.imu_sensor.state = SENSOR_OPERATING;
} else {
LOG_ERROR("IMU acceleration out of range");
diagnostics.imu_sensor.state = SENSOR_ERROR;
}
Pressure Conversion Functions
bar_to_psi()
Converts pressure from bar to psi (pounds per square inch).
/**
* @brief Converts pressure from bar to psi.
* @param bar The pressure in bar.
* @param psi Pointer to a float where the converted psi pressure will be stored.
* @return RESULT_OK on success, or RESULT_ERR_INVALID_ARG if psi is NULL.
*/
result_t bar_to_psi(float bar, float *psi);
Conversion Formula: psi = bar × 14.5038
Parameters:
bar- Pressure in barpsi- Pointer to output variable (must not be NULL)
Return Values:
RESULT_OK- Conversion successfulRESULT_ERR_INVALID_ARG- psi pointer is NULL
Status: Currently commented out in implementation
Usage Example:
float pressure_bar = 5.0f;
float pressure_psi;
if (bar_to_psi(pressure_bar, &pressure_psi) == RESULT_OK) {
LOG_INFO("Pressure: %.2f bar = %.2f psi", pressure_bar, pressure_psi);
}
psi_to_bar()
Converts pressure from psi to bar.
/**
* @brief Converts pressure from psi to bar.
* @param psi The pressure in psi.
* @param bar Pointer to a float where the converted bar pressure will be stored.
* @return RESULT_OK on success, or RESULT_ERR_INVALID_ARG if bar is NULL.
*/
result_t psi_to_bar(float psi, float *bar);
Conversion Formula: bar = psi ÷ 14.5038
Status: Currently commented out in implementation
GPS Functions
validate_gps_latitude()
Validates GPS latitude value is within valid range.
/**
* @brief Validates GPS latitude value.
* @param latitude The latitude value to validate (-90 to +90 degrees).
* @return RESULT_OK if the value is valid, RESULT_ERR_INVALID_DATA otherwise.
*/
result_t validate_gps_latitude(double latitude);
Implementation:
result_t validate_gps_latitude(double latitude) {
if (latitude >= -90.0 && latitude <= 90.0) {
return RESULT_OK;
}
return RESULT_ERR_INVALID_DATA;
}
Parameters:
latitude- Latitude in degrees (double precision)
Valid Range: -90.0 to +90.0 degrees
- Negative = South
- Positive = North
- 0° = Equator
Return Values:
RESULT_OK- Value is within valid rangeRESULT_ERR_INVALID_DATA- Value outside ±90 degrees
validate_gps_longitude()
Validates GPS longitude value is within valid range.
/**
* @brief Validates GPS longitude value.
* @param longitude The longitude value to validate (-180 to +180 degrees).
* @return RESULT_OK if the value is valid, RESULT_ERR_INVALID_DATA otherwise.
*/
result_t validate_gps_longitude(double longitude);
Implementation:
result_t validate_gps_longitude(double longitude) {
if (longitude >= -180.0 && longitude <= 180.0) {
return RESULT_OK;
}
return RESULT_ERR_INVALID_DATA;
}
Parameters:
longitude- Longitude in degrees (double precision)
Valid Range: -180.0 to +180.0 degrees
- Negative = West
- Positive = East
- 0° = Prime Meridian
- ±180° = International Date Line
Return Values:
RESULT_OK- Value is within valid rangeRESULT_ERR_INVALID_DATA- Value outside ±180 degrees
validate_gps_hdop()
Validates GPS Horizontal Dilution of Precision (HDOP) value.
/**
* @brief Validates GPS HDOP value.
* @param hdop The HDOP value to validate (0-50 typical range).
* @return RESULT_OK if the value is valid, RESULT_ERR_INVALID_DATA otherwise.
*/
result_t validate_gps_hdop(float hdop);
Implementation:
result_t validate_gps_hdop(float hdop) {
if (hdop >= 0.0f && hdop <= 50.0f) {
return RESULT_OK;
}
return RESULT_ERR_INVALID_DATA;
}
Parameters:
hdop- Horizontal dilution of precision value
Valid Range: 0.0 to 50.0
HDOP Quality Interpretation:
- <1 - Ideal
- 1-2 - Excellent
- 2-5 - Good
- 5-10 - Moderate
- 10-20 - Fair
- >20 - Poor
Return Values:
RESULT_OK- Value is within valid rangeRESULT_ERR_INVALID_DATA- Value exceeds acceptable limits
validate_gps_satellite_count()
Validates GPS satellite count is within valid range.
/**
* @brief Validates GPS satellite count.
* @param satellites The number of satellites to validate.
* @return RESULT_OK if the value is valid, RESULT_ERR_INVALID_DATA otherwise.
*/
result_t validate_gps_satellite_count(int32_t satellites);
Implementation:
result_t validate_gps_satellite_count(int32_t satellites) {
if (satellites >= 0 && satellites <= 30) {
return RESULT_OK;
}
return RESULT_ERR_INVALID_DATA;
}
Parameters:
satellites- Number of satellites in view
Valid Range: 0 to 30 satellites
Satellite Count Guidance:
- 0-3 - No/poor fix possible
- 4-5 - 3D fix possible
- 6-9 - Good coverage
- 10+ - Excellent coverage
Return Values:
RESULT_OK- Value is within valid rangeRESULT_ERR_INVALID_DATA- Negative value or exceeds 30
Usage Example (Full GPS Validation):
if (validate_gps_latitude(gps_data.latitude) == RESULT_OK &&
validate_gps_longitude(gps_data.longitude) == RESULT_OK &&
validate_gps_hdop(gps_data.hdop) == RESULT_OK &&
validate_gps_satellite_count(gps_data.satellites) == RESULT_OK) {
LOG_INFO("GPS fix valid: %.6f, %.6f (sats=%d)",
gps_data.latitude, gps_data.longitude, gps_data.satellites);
diagnostics.gps_sensor_1.state = SENSOR_OPERATING;
} else {
LOG_WARNING("GPS validation failed");
diagnostics.gps_sensor_1.state = SENSOR_ERROR;
}
Error Handling Pattern
All validation functions follow a consistent pattern:
// Check sensor data
if (validate_<sensor>_<field>(value) == RESULT_OK) {
// Data is valid - use it
diagnostics.<sensor>.state = SENSOR_OPERATING;
} else {
// Data is invalid - set error state
diagnostics.<sensor>.state = SENSOR_ERROR;
diagnostics.<sensor>.error_code = <ERROR_CODE>_INVALID_DATA;
}
TRY Macro Usage:
The implementation uses a TRY() macro for error propagation (from result.h):
// In validate_imu_data()
result_t validate_imu_data(float accel_x, float accel_y, float accel_z) {
TRY(validate_accelerometer_value(accel_x)); // Return on error
TRY(validate_accelerometer_value(accel_y)); // Return on error
TRY(validate_accelerometer_value(accel_z)); // Return on error
return RESULT_OK;
}
Implementation Status
Currently Implemented (Active):
- ✓ validate_ph_value()
- ✓ validate_accelerometer_value()
- ✓ validate_imu_data()
- ✓ validate_gps_latitude()
- ✓ validate_gps_longitude()
- ✓ validate_gps_hdop()
- ✓ validate_gps_satellite_count()
Currently Commented Out (Inactive):
- ⊘ celsius_to_fahrenheit() - Declared but not implemented
- ⊘ fahrenheit_to_celsius() - Declared but not implemented
- ⊘ bar_to_psi() - Declared but not implemented
- ⊘ psi_to_bar() - Declared but not implemented
Note: Temperature and pressure conversions are stubbed out in the current implementation. They can be enabled by uncommenting the implementation in sensor_basics.c if needed for future features.
Testing
Test Suite Location: test/sensor_board/test_sensor_basics/
Building Tests:
// Run all sensor_basics tests
pio test -e sensor_board -f test_sensor_basics
// Run with verbose output
pio test -e sensor_board -f test_sensor_basics -v
Test Coverage:
- Boundary value testing (min/max ranges)
- Edge cases (0 values, extreme values)
- Valid range acceptance
- Invalid range rejection
- NULL pointer handling for conversion functions
Integration in Main Application
Typical Usage in main.c:
// After polling a sensor
result_t poll_result = poll_gps_sensor(&gps_data);
if (poll_result == RESULT_OK) {
// Validate all GPS fields before using
if (validate_gps_latitude(gps_data.latitude) == RESULT_OK &&
validate_gps_longitude(gps_data.longitude) == RESULT_OK) {
diagnostics.gps_sensor_1.state = SENSOR_OPERATING;
// Safe to use: gps_data.latitude, gps_data.longitude
} else {
diagnostics.gps_sensor_1.state = SENSOR_ERROR;
diagnostics.gps_sensor_1.error_code = GPS_INVALID_DATA;
}
} else if (poll_result == RESULT_ERR_COMMS) {
diagnostics.gps_sensor_1.state = SENSOR_ERROR;
diagnostics.gps_sensor_1.error_code = GPS_COMMUNICATION_FAILURE;
}
No comments to display
No comments to display