Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5cfb45d
Use custom board definition
nateinaction Sep 7, 2025
74bf7a6
Initial IMU component generation
hrfarmer Aug 28, 2025
b4203c9
Initial imu data pull
nateinaction Sep 7, 2025
f110ce2
Reading magnetic field data
nateinaction Sep 7, 2025
8e30497
Add new telemetry for accel and angvel
nateinaction Sep 8, 2025
f4c903f
Acceleration and AngularVelocity telemetry working
nateinaction Sep 8, 2025
4caa93c
Add temp
nateinaction Sep 8, 2025
55eeb0a
Improve documentation
nateinaction Sep 9, 2025
981de3e
Update FprimeZephyrReference/Components/Imu/docs/sdd.md
nateinaction Sep 9, 2025
e44fa63
Add LIS2MDL driver & implement in Imu component (#16)
hrfarmer Sep 18, 2025
8478ca1
Create lsm6dso driver component & implementation (#17)
asiemsen Sep 18, 2025
d064a09
Spit out common helpers and types from drivers, standardize port name…
nateinaction Sep 18, 2025
4e3cb5b
Merge branch 'main' of github.com:Open-Source-Space-Foundation/proves…
nateinaction Sep 18, 2025
c0424fb
Merge branch 'main' of github.com:Open-Source-Space-Foundation/proves…
nateinaction Sep 18, 2025
d66c949
Remove unnecessary board files
nateinaction Sep 18, 2025
4ad69fc
remove fpp helper file
asiemsen Sep 22, 2025
36d5278
finished renaming to build
asiemsen Sep 22, 2025
d8fce1f
add parentheses for clearer intentions
asiemsen Sep 22, 2025
516d730
remove FW_ASSERTs
asiemsen Sep 22, 2025
8e4e8d2
clear throttle after successful device ready check
asiemsen Sep 23, 2025
991b010
adding telemetry to lis2mdlManager
asiemsen Sep 23, 2025
b73dec0
Merge branch 'main' into imu2_PR_changes_saidi
hrfarmer Sep 26, 2025
cac1bfc
fix fprime files to match new names & telemetry structure
hrfarmer Sep 26, 2025
8a395c2
edit cpp implementation files to output telemetry
hrfarmer Sep 26, 2025
ac7fd7b
formatting
hrfarmer Sep 26, 2025
f1e5405
Merge pull request #27 from Open-Source-Space-Foundation/imu2_PR_chan…
nateinaction Sep 27, 2025
8fed4e3
clear throttle, configure lsm6 sensor, read->get
nateinaction Sep 27, 2025
adf6b8e
Add IMU tests
nateinaction Sep 27, 2025
19042fb
Add type hinting
nateinaction Sep 28, 2025
5b41b97
Comment fix
nateinaction Sep 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions FprimeZephyrReference/Components/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@

add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/FatalHandler")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Watchdog")
add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/Imu/")
36 changes: 36 additions & 0 deletions FprimeZephyrReference/Components/Imu/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
####
# F Prime CMakeLists.txt:
#
# SOURCES: list of source files (to be compiled)
# AUTOCODER_INPUTS: list of files to be passed to the autocoders
# DEPENDS: list of libraries that this module depends on
#
# More information in the F´ CMake API documentation:
# https://fprime.jpl.nasa.gov/latest/docs/reference/api/cmake/API/
#
####

# Module names are derived from the path from the nearest project/library/framework
# root when not specifically overridden by the developer. i.e. The module defined by
# `Ref/SignalGen/CMakeLists.txt` will be named `Ref_SignalGen`.

register_fprime_library(
AUTOCODER_INPUTS
"${CMAKE_CURRENT_LIST_DIR}/Imu.fpp"
SOURCES
"${CMAKE_CURRENT_LIST_DIR}/Imu.cpp"
# DEPENDS
# MyPackage_MyOtherModule
)

### Unit Tests ###
# register_fprime_ut(
# AUTOCODER_INPUTS
# "${CMAKE_CURRENT_LIST_DIR}/Imu.fpp"
# SOURCES
# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ImuTestMain.cpp"
# "${CMAKE_CURRENT_LIST_DIR}/test/ut/ImuTester.cpp"
# DEPENDS
# STest # For rules-based testing
# UT_AUTO_HELPERS
# )
101 changes: 101 additions & 0 deletions FprimeZephyrReference/Components/Imu/Imu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// ======================================================================
// \title Imu.cpp
// \brief cpp file for Imu component implementation class
// ======================================================================

#include "FprimeZephyrReference/Components/Imu/Imu.hpp"

#include <Fw/Types/Assert.hpp>

namespace Components {

// ----------------------------------------------------------------------
// Component construction and destruction
// ----------------------------------------------------------------------

Imu ::Imu(const char* const compName) : ImuComponentBase(compName) {
// Initialize the LIS2MDL sensor
lis2mdl = device_get_binding("LIS2MDL");
FW_ASSERT(device_is_ready(lis2mdl));

// Initialize the LSM6DSO sensor
lsm6dso = DEVICE_DT_GET_ONE(st_lsm6dso);
FW_ASSERT(device_is_ready(lsm6dso));

// Configure the LSM6DSO sensor
struct sensor_value odr = {.val1 = 12, .val2 = 500000}; // 12.5 Hz
FW_ASSERT(sensor_attr_set(lsm6dso, SENSOR_CHAN_ACCEL_XYZ, SENSOR_ATTR_SAMPLING_FREQUENCY, &odr) == 0);
FW_ASSERT(sensor_attr_set(lsm6dso, SENSOR_CHAN_GYRO_XYZ, SENSOR_ATTR_SAMPLING_FREQUENCY, &odr) == 0);
}

Imu ::~Imu() {}

// ----------------------------------------------------------------------
// Handler implementations for typed input ports
// ----------------------------------------------------------------------

void Imu ::run_handler(FwIndexType portNum, U32 context) {
// Fetch new data samples from the sensors
sensor_sample_fetch_chan(lsm6dso, SENSOR_CHAN_ACCEL_XYZ);
sensor_sample_fetch_chan(lsm6dso, SENSOR_CHAN_GYRO_XYZ);
sensor_sample_fetch_chan(lis2mdl, SENSOR_CHAN_MAGN_XYZ);
sensor_sample_fetch_chan(lsm6dso, SENSOR_CHAN_DIE_TEMP);

// Output sensor values via telemetry
this->tlmWrite_Acceleration(this->get_acceleration());
this->tlmWrite_AngularVelocity(this->get_angular_velocity());
this->tlmWrite_MagneticField(this->get_magnetic_field());
this->tlmWrite_Temperature(this->get_temperature());
}

F64 Imu ::sensor_value_to_f64(const struct sensor_value& val) {
return val.val1 + val.val2 / 1000000.0f;
}

Components::Imu_Acceleration Imu ::get_acceleration() {
struct sensor_value x;
struct sensor_value y;
struct sensor_value z;

sensor_channel_get(lsm6dso, SENSOR_CHAN_ACCEL_X, &x);
sensor_channel_get(lsm6dso, SENSOR_CHAN_ACCEL_Y, &y);
sensor_channel_get(lsm6dso, SENSOR_CHAN_ACCEL_Z, &z);

return Components::Imu_Acceleration(this->sensor_value_to_f64(x), this->sensor_value_to_f64(y),
this->sensor_value_to_f64(z));
}

Components::Imu_AngularVelocity Imu ::get_angular_velocity() {
struct sensor_value x;
struct sensor_value y;
struct sensor_value z;

sensor_channel_get(lsm6dso, SENSOR_CHAN_GYRO_X, &x);
sensor_channel_get(lsm6dso, SENSOR_CHAN_GYRO_Y, &y);
sensor_channel_get(lsm6dso, SENSOR_CHAN_GYRO_Z, &z);

return Components::Imu_AngularVelocity(this->sensor_value_to_f64(x), this->sensor_value_to_f64(y),
this->sensor_value_to_f64(z));
}

Components::Imu_MagneticField Imu ::get_magnetic_field() {
struct sensor_value x;
struct sensor_value y;
struct sensor_value z;

sensor_channel_get(lis2mdl, SENSOR_CHAN_MAGN_X, &x);
sensor_channel_get(lis2mdl, SENSOR_CHAN_MAGN_Y, &y);
sensor_channel_get(lis2mdl, SENSOR_CHAN_MAGN_Z, &z);

return Components::Imu_MagneticField(this->sensor_value_to_f64(x), this->sensor_value_to_f64(y),
this->sensor_value_to_f64(z));
}

F64 Imu ::get_temperature() {
struct sensor_value temp;

sensor_channel_get(lsm6dso, SENSOR_CHAN_DIE_TEMP, &temp);

return this->sensor_value_to_f64(temp);
}
} // namespace Components
48 changes: 48 additions & 0 deletions FprimeZephyrReference/Components/Imu/Imu.fpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
module Components {
@ IMU Component for F Prime FSW framework.
passive component Imu {
sync input port run: Svc.Sched

@ Acceleration reading in m/s^2
struct Acceleration {
x: F64
y: F64
z: F64
}

@ Telemetry channel for acceleration
telemetry Acceleration: Acceleration

@ Angular velocity reading in rad/s
struct AngularVelocity {
x: F64
y: F64
z: F64
}

@ Telemetry channel for angular velocity
telemetry AngularVelocity: AngularVelocity

@ Magnetic field reading in gauss
struct MagneticField {
x: F64
y: F64
z: F64
}

@ Telemetry channel for magnetic field
telemetry MagneticField: MagneticField

@ Telemetry channel for temperature in degrees Celsius
telemetry Temperature: F64

###############################################################################
# Standard AC Ports: Required for Channels, Events, Commands, and Parameters #
###############################################################################
@ Port for requesting the current time
time get port timeCaller

@ Port for sending telemetry channels to downlink
telemetry port tlmOut
}
}
75 changes: 75 additions & 0 deletions FprimeZephyrReference/Components/Imu/Imu.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// ======================================================================
// \title Imu.hpp
// \brief hpp file for Imu component implementation class
// ======================================================================

#ifndef Components_Imu_HPP
#define Components_Imu_HPP

#include "FprimeZephyrReference/Components/Imu/ImuComponentAc.hpp"

#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/kernel.h>

namespace Components {

class Imu final : public ImuComponentBase {
public:
// ----------------------------------------------------------------------
// Component construction and destruction
// ----------------------------------------------------------------------

//! Construct Imu object
Imu(const char* const compName);

//! Destroy Imu object
~Imu();

private:
// ----------------------------------------------------------------------
// Handler implementations for typed input ports
// ----------------------------------------------------------------------

//! Handler implementation
void run_handler(FwIndexType portNum, //!< The port number
U32 context //!< The call order
) override;

// ----------------------------------------------------------------------
// Helper methods
// ----------------------------------------------------------------------

//! Convert a Zephyr sensor_value to an Fprime F64
F64 sensor_value_to_f64(const struct sensor_value& val);

// ----------------------------------------------------------------------
// IMU access methods
// ----------------------------------------------------------------------

//! Get the acceleration reading from the IMU
Components::Imu_Acceleration get_acceleration();

//! Get the angular velocity reading from the IMU
Components::Imu_AngularVelocity get_angular_velocity();

//! Get the magnetic field reading from the IMU
Components::Imu_MagneticField get_magnetic_field();

//! Get the temperature reading from the IMU
F64 get_temperature();

// ----------------------------------------------------------------------
// Member variables
// ----------------------------------------------------------------------

//! Zephyr device stores the initialized LIS2MDL sensor
const struct device* lis2mdl;

//! Zephyr device stores the initialized LSM6DSO sensor
const struct device* lsm6dso;
};

} // namespace Components

#endif
98 changes: 98 additions & 0 deletions FprimeZephyrReference/Components/Imu/docs/sdd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Components::Imu

The IMU (Inertial Measurement Unit) component provides sensor data related to motion and orientation of the craft. It interfaces with two sensors: the LIS2MDL magnetometer and the LSM6DSO accelerometer/gyroscope to provide acceleration, angular velocity, magnetic field, and temperature measurements.

## Usage Examples

The IMU component is designed to be scheduled periodically to collect sensor data and output telemetry. It operates as a passive component that responds to scheduler calls.

### Diagrams

```mermaid
sequenceDiagram
participant Scheduler
participant IMU
participant Telemetry

Scheduler->>IMU: run
IMU->>Telemetry: Output sensor data
```

### Typical Usage

1. The component is instantiated and initialized during system startup
2. The scheduler calls the `run` port at regular intervals (configured at 12.5 Hz)
3. On each run call, the component:
- Fetches fresh sensor samples from both IMU sensors
- Converts sensor data to F Prime data structures
- Outputs telemetry for acceleration, angular velocity, magnetic field, and temperature

## Class Diagram

```mermaid
classDiagram
namespace Components {
class ImuComponentBase {
<<Auto-generated>>
}
class Imu {
- lis2mdl: device*
- lsm6dso: device*
+ Imu(char* compName)
+ ~Imu()
- run_handler(FwIndexType portNum, U32 context)
- sensor_value_to_f64(sensor_value* val): F64
- get_acceleration(): Imu_Acceleration
- get_angular_velocity(): Imu_AngularVelocity
- get_magnetic_field(): Imu_MagneticField
- get_temperature(): F64
}
}
ImuComponentBase <|-- Imu : inherits
```


## Port Descriptions
| Name | Type | Description |
|---|---|---|
| run | sync input | Scheduler port that triggers sensor data collection and telemetry output |
| timeCaller | time get | Port for requesting current system time |
| tlmOut | telemetry | Port for sending telemetry data to downlink |

## Component States
| Name | Description |
|---|---|
| Initialized | Component has been constructed and both IMU sensors are ready |
| Running | Component is actively collecting sensor data when scheduled |
| Error | One or both sensors failed initialization (assertion failure) |

## Sequence Diagrams
Add sequence diagrams here

## Telemetry
| Name | Description |
|---|---|
| Acceleration | Telemetry channel for acceleration in m/s^2 |
| AngularVelocity | Telemetry channel for angular velocity in rad/s |
| MagneticField | Telemetry channel for magnetic field in gauss |
| Temperature | Telemetry channel for temperature in degrees Celsius |

## Unit Tests
Add unit test descriptions in the chart below
| Name | Description | Output | Coverage |
|---|---|---|---|
|---|---|---|---|

## Requirements
Add requirements in the chart below
| Name | Description | Validation |
|---|---|---|
| AccelerationTelemetry | The component shall provide acceleration telemetry in m/s^2 | Verify telemetry output matches expected values from sensor datasheet |
| AngularVelocityTelemetry | The component shall provide angular velocity telemetry in rad/s | Verify telemetry output matches expected values from sensor datasheet |
| MagneticFieldTelemetry | The component shall provide magnetic field telemetry in gauss | Verify telemetry output matches expected values from sensor datasheet |
| TemperatureTelemetry | The component shall provide temperature telemetry in degrees Celsius | Verify telemetry output matches expected values from sensor datasheet |

## Change Log
| Date | Description |
|---|---|
| 2025-9-9 | Initial IMU component |
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ telemetry packets ReferenceDeploymentPackets {
ReferenceDeployment.watchdog.WatchdogTransitions
}

packet Imu id 6 group 4 {
ReferenceDeployment.imu.Acceleration
ReferenceDeployment.imu.AngularVelocity
ReferenceDeployment.imu.MagneticField
}


} omit {
CdhCore.cmdDisp.CommandErrors
Expand All @@ -57,4 +63,6 @@ telemetry packets ReferenceDeploymentPackets {
CdhCore.version.CustomVersion08
CdhCore.version.CustomVersion09
CdhCore.version.CustomVersion10
# Reserving temp telemetry for future use
ReferenceDeployment.imu.Temperature
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include <zephyr/drivers/gpio.h>

static const struct gpio_dt_spec ledGpio = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
static const struct gpio_dt_spec ledGpio = GPIO_DT_SPEC_GET(DT_NODELABEL(led0), gpios);

// Allows easy reference to objects in FPP/autocoder required namespaces
using namespace ReferenceDeployment;
Expand Down
Loading