Welcome to the AresPayload wiki!

Update: Dec 19, 2025
Author: Mann Patel
Note: Documentation reflects the Osiris Payload

Table of Contents

  1. Ares Payload
  2. System Architecture
  3. Data Flow
  4. Task Details
  5. State Machine Details
  6. Communication Interfaces
  7. Getting Started
  8. Example Usage
  9. Key Design Patterns
  10. Development Notes
  11. Hardware Naming Convention
  12. Future Enhancements

Overview

The Osiris Payload System is an embedded flight computer designed for rocket payloads. It runs on an STM32H7 microcontroller using FreeRTOS and manages sensor data collection, state transitions, and hardware control throughout a rocket's flight.

System Architecture

High-Level Design

The system follows a task-based architecture using FreeRTOS, where different subsystems run as independent tasks that communicate via command queues. A state machine manages the flight phases and controls hardware accordingly.

flowchart TD A[Main System
main_system.cpp] A -->|Initializes all tasks| B[Tasks] A -->|Initializes all tasks| C[Drivers]

Core Components

Sensors are named after Nintendo characters (God knows why?) :(
  1. Mario & Luigi: LPS22HH barometer
  2. Bowser: MS5611 barometer
  3. Toopy & Binoo: LSM6DSO IMUs

1. Task System

The system uses multiple FreeRTOS tasks that run concurrently:

Task Priority Purpose
FlightTask 2 Main flight logic and state machine coordination
IMUTask 2 Reads IMU (Inertial Measurement Unit) data
BaroTask 2 Reads barometer/pressure sensor data
DebugTask 2 Handles debug output via UART
CubeTask 2 Framework task (Cube++ RTOS wrapper)

2. State Machine (OsirisSM)

The flight computer transitions through 5 states during operation:

PRELAUNCH -> LAUNCH -> DROGUE -> MAIN -> POSTLAUNCH

Each state controls different hardware peripherals and responds to different commands.

3. Sensor Drivers

Barometers

IMU (Inertial Measurement Unit)

4. Hardware Control (GPIO)

The system controls various hardware via GPIO pins:

Data Flow

flowchart LR S[Sensors] T[Tasks] C[Commands] SM[State Machine] HC[Hardware Control] DS[Data Structures] S --> T T --> C C --> SM SM --> HC SM -->|reads/writes| DS S -->|writes| DS

Command Structure

Tasks communicate using a Command object with:

Data Structures

typedef struct BarometerData {
    float marioPressure;        // LPS22HH U3
    float marioTemperature;
    float luigiPressure;        // LPS22HH U4
    float luigiTemperature;
    uint32_t bowserPressure;    // MS5611
    uint32_t bowserTemperature;
} BarometerData;

typedef struct IMUData {
    float xAccel;
    float yAccel;
    float zAccel;
} IMUData;

Task Details

FlightTask

IMUTask

BaroTask

DebugTask

State Machine Details

State Transitions

flowchart TD PRE[PRELAUNCH] LAUNCH[LAUNCH] DROGUE[DROGUE] MAIN[MAIN] POST[POSTLAUNCH] PRE -->|OSC_PRELAUNCH_TO_LAUNCH| LAUNCH LAUNCH -->|OSC_LAUNCH_TO_DROGUE| DROGUE DROGUE -->|OSC_DROGUE_TO_MAIN| MAIN MAIN -->|OSC_MAIN_TO_POSTLAUNCH| POST

State Behaviors

PRELAUNCH

LAUNCH

DROGUE

MAIN

POSTLAUNCH

Emergency Override

From any state, you can return to PRELAUNCH using:

OSC_ANY_TO_PRELAUNCH

Communication Interfaces

SPI (Serial Peripheral Interface)

I2C

UART

Getting Started

System Initialization

The system boots through main_system.cpp:

void run_main() {
    // 1. Initialize all tasks
    CubeTask::Inst().InitTask();
    DebugTask::Inst().InitTask();
    FlightTask::Inst().InitTask();
    IMUTask::Inst().InitTask();
    BaroTask::Inst().InitTask();

    // 2. Print boot info
    SOAR_PRINT("\n-- SOAR SYSTEM --\n");

    // 3. Test sensors (example)
    Command testIMU(REQUEST_COMMAND, IMU_REQUEST_LIN_ACC);
    IMUTask::Inst().GetEventQueue()->Send(testIMU);

    // 4. Start FreeRTOS scheduler
    osKernelStart();
}

Task Configuration

Task priorities and stack sizes are defined in SystemDefines.hpp:

// All tasks currently have priority 2
constexpr uint8_t FLIGHT_TASK_RTOS_PRIORITY = 2;
constexpr uint8_t IMU_TASK_RTOS_PRIORITY = 2;
constexpr uint8_t BARO_TASK_RTOS_PRIORITY = 2;

// Stack sizes (in words)
constexpr uint16_t FLIGHT_TASK_STACK_DEPTH_WORDS = 512;
constexpr uint16_t IMU_TASK_STACK_DEPTH_WORDS = 512;
constexpr uint16_t BARO_TASK_STACK_DEPTH_WORDS = 512;

Example Usage

Requesting IMU Data

// Create a command to request linear acceleration
Command cmd(REQUEST_COMMAND, IMU_REQUEST_LIN_ACC);

// Send to IMU task
IMUTask::Inst().GetEventQueue()->Send(cmd);

// IMUTask will respond by sending IMUData to FlightTask

Controlling Hardware

// Open solenoid valve 1
Command cmd(CONTROL_ACTION, OSC_OPEN_SOL1);
FlightTask::Inst().GetEventQueue()->Send(cmd);

// Close solenoid valve 1
Command cmd2(CONTROL_ACTION, OSC_CLOSE_SOL1);
FlightTask::Inst().GetEventQueue()->Send(cmd2);

Reading Barometer Data

// Request new barometer sample
Command cmd(REQUEST_COMMAND, BARO_REQUEST_NEW_SAMPLE);
BaroTask::Inst().GetEventQueue()->Send(cmd);

// Request debug output of barometer values
Command cmd2(REQUEST_COMMAND, BARO_REQUEST_DEBUG);
BaroTask::Inst().GetEventQueue()->Send(cmd2);

Key Design Patterns

1. Singleton Pattern

Each task uses Task::Inst() to access a single instance:

FlightTask::Inst().GetEventQueue()->Send(command);

2. Command Pattern

All inter-task communication uses Command objects with specific command types

3. State Pattern

Flight logic organized into distinct states with entry/exit handlers

4. Hardware Abstraction

GPIO operations wrapped in namespace functions:

GPIO::LED_GREEN::On();
GPIO::SOL1::Off();