Skip to content

UConn-Rocketry/ferda

Repository files navigation

Ferda 🚀

Holds all flight software for the UConn Propulsive Landing team's rockets. 😄

All source code utilizes Hungarian Notation.

Create features in branches originating from the dev branch. When a feature is complete, make a pull request to merge it into dev.

Table of Contents

  1. How to Run
  2. Building the Source Code
  3. Hardware Configuration
  4. Software-in-the-Loop Testing
  5. Design

How to Run

How to Run on Raspberry Pi

  1. Install git (https://git-scm.com/install/)
  2. Clone this repo.
  3. Run sudo apt update
  4. Run xargs -a linux_library_requirements.txt sudo apt-get install -y
  5. Run mkdir ThirdPartyLibraries and then cd ThirdPartyLibraries
  6. Clone WiringPi library with git clone https://github.com/WiringPi/WiringPi.git
  7. Run cd WiringPi/wiringPi
  8. Run make
  9. Run sudo make install
  10. Go back to ThirdPartyLibraries directory
  11. Clone PCA9685 library with git clone https://github.com/barulicm/PiPCA9685.git
  12. Run cd PiPCA9685
  13. Run sudo cmake --workflow --preset install
  14. Build the repo. Make sure you're in release mode because we want to use the hardware files.
  15. Create a logs folder inside the repo directory with mkdir logs
  16. Run the executable that gets created in the build/ folder. (NOTE: If working with GPS, run gps_setup.sh first)

Connecting to Raspberry Pi

In order to connect to the Raspberry Pi, it needs to be connected to Wi-Fi, and you need to know the IP address. All 3 Raspberry Pis, including the 2 RPI5s and the 1 RPI4, are automatically configured to connect to the TP-Link Archer C54 router that we bought. Once you know the IP address, run ssh host@{IP-Address}, where host is the Pi's username and the IP address is the IP address the RPI is connected to.

Troubleshooting:

  • Make sure you are connected to the same Wi-Fi as the Pi.
  • If you used the same IP address as another Pi, it will yell at you. In that case, run the command ssh-keygen -R {IP-address}.

Raspberry Pi Configuration

If you buy more Raspberry Pis, Raspberry Pi's website will help you get started (https://www.raspberrypi.com/documentation/computers/getting-started.html). The main thing is to make sure SSH, I2C, Raspberry Pi Connect, and Serial Port are enabled.

How to Run on Mac

  1. Install git (https://git-scm.com/install/)
  2. Clone this repo.
  3. Install brew with /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  4. Run brew bundle install
  5. Build the repo. Make sure you're in either debug or simulation mode.
  6. Create a logs folder inside the repo directory with mkdir logs
  7. Run the executable that gets created in the build/ folder. (NOTE: If working with GPS, run gps_setup.sh first)

How to Run on Windows

Windows is a little different because it doesn't come installed with a compiler, and since we use some POSIX libraries, we use WSL instead.

  1. Follow WSL tutorial below
  2. Follow Install Required Tools
  3. Follow Authenticate with GitHub
  4. Open a WSL session and type code .
  5. Install the WSL extension on VS Code.
  6. Install the CMake Tools extension on VS Code.
  7. Build the repo. Make sure you're in either debug or simulation mode.
  8. Create a logs folder inside the repo directory with mkdir logs
  9. Run the executable that gets created in the build/ folder. (NOTE: If working with GPS, run gps_setup.sh first)

Troubleshooting

  • Make sure all dependencies are installed

    • linux_library_requirements.txt for Linux operating systems (Raspberry Pi)
    • Brewfile for mac
  • If you get warning depend.make has modification time issue: try the commands:

    make clean
    make all
  • When SSHing into the Pi, the IP address might change, so go to the router's IP address to look at the exact IP address the Pi is connected to.

  • On Mac, if you installed the CMake Tools extension on VS Code and you have ninja installed, it might try to automatically select it. When you try to build with make, it will throw an error.

Building the Source Code

  1. Clone the repository:

    git clone https://github.com/Propulsive-Landing/ferda.git
  2. Enter the new folder:

    cd ferda
  3. Generate the build files using CMake:

    • For release:
      cmake -Bbuild -DCMAKE_BUILD_TYPE=Release .
      (this uses the actual hardware sensors)
    • For debug:
      cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug .
    • For Simulation:
      cmake -Bbuild -DCMAKE_BUILD_TYPE=Simulation .
  4. Enter the newly generated build folder:

    cd build
  5. Build the source:

    make all
  6. Run the executable inside the build folder:

    sudo ./Ferda
  7. Create a logs folder in the root of the project (without it, no logs will be saved).

Hardware Configuration

XBee Port Setup

The XBee module is a radio module that is used by our flight computer to send and receive data from ground control, such as when we want to instruct the rocket to launch or tell it to abort. To use the XBee from our Raspberry Pi, we must configure it properly. Here's how:

  1. XBee is currently (4/24/2026) configured to act as a terminal that only outputs values when there is a newline character.
  2. In hardware/RF.cpp, we configure serial port settings. Most importantly, the baud rate should be 38400, but make sure that the XBees are configured properly using XCTU software.
  3. For debugging, use stty -F /dev/{RFPort} -a to see all serial line settings because most of the time, the baud rate is not set to what the other XBee uses or echo is not turned off.
  4. Use stty to configure the device:
    stty -F /dev/ttyUSB0
    (/dev/ttyUSB0 may change per device).
  5. Configure settings:
    stty -F /dev/ttyUSB0 -settingToDisable settingToEnable
    Disable settings using a minus sign and enable settings without it.
  6. The device configuration should resemble:
    speed 38400 baud; line = 0;
    -echo
    

GPS Port Setup

We use Adafruit's GPS module with a USB-C port to help with our navigation, but first we need to configure the GPS to specific settings. Every GPS receiver uses NMEA sentences which are ASCII text strings that display information such as position, speed, and time. The ones that we care about are:

  • RMC (Recommended Minimum Specific GNSS Data)
  • GGA (Global Positioning System Fix Data) To write settings, we use the talker ID PMTK. In every PMTK sentence we write, we need to compute the checksum, which is the XOR of every bit, and end with \r\n. These configuration steps are taken care of in gps_setup.sh. For the script to work, make sure python is installed and createa virtual environment where you have installed pyserial and adafruit-circuitpython-gps
  1. In gps_setup.sh, we call gps_startup.py to make sure the GPS has a fix because, in my testing, the settings only applied if there was a fix. There are also nice libraries for dealing with Adafruit GPS in Python.
  2. Then we configure the baud rate to 9600 and disable echo.
  3. Then we use printf to write the setting, $PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n' which enables the sentences we want.
  4. Then we use printf to write the setting, $PMTK251,38400*27\r\n' which changes the baud rate to 38400.
  5. Then we need to change the baud rate for our serial port so we do stty -F "$PORT" 38400 raw -echo -ixon
  6. Lastly, we change the update rate to be 10 Hz using '$PMTK220,100*2F\r\n'.

Documentation on PMTK command packets can be found in PMTK_A11.pdf. Documentation on the NMEA sentences can be found in CD+PA1616S+Datasheet.v03.pdf.

Startup Script

We currently have 2 bash scripts

  • gps_setup.sh
  • startup.sh

gps_setup.sh is meant to configure all of the GPS settings where startup.sh is meant to run gps_setup.sh and then run the program

Camera Calibration

The camera can now load a persisted OpenCV calibration file at startup. By default it looks for ../calibration/camera_calibration.json when the executable is run from the build/ directory.

  1. Capture a set of checkerboard images from the camera at the same resolution used for flight.
  2. Build the calibration tool and run it from the build/ directory:
    ./CameraCalibrate ../calibration_images ../calibration/camera_calibration.json 9 6 0.024
    Replace 9 6 with the checkerboard inner-corner count and 0.024 with the square size in meters.
  3. Restart Ferda. If the calibration file is present and valid, the camera uses it for cv::undistortPoints(); otherwise it falls back to the current built-in constants.

The calibration output stores the camera matrix, distortion coefficients, image size, checkerboard dimensions, and RMS reprojection error. Keep one file per physical camera if the hardware changes.

Software-in-the-Loop Testing

Software-in-the-loop (SIL) testing allows you to connect your flight software to MATLAB's Simulink environment for real-time simulation. Follow the steps below to set up and run the SIL testing environment. SIL is not currently supported on Mac.

SIL Testing Using Windows + WSL2

Install WSL2 - help

To run your flight software in a Linux environment on Windows, you need to install WSL2 (Windows Subsystem for Linux). The steps can vary depending on your setup, so you may have to do some troubleshooting to install it properly. Follow these steps:

  1. Open PowerShell as Administrator and run:

    wsl --install
  2. Set up your preferred Linux distribution (e.g., Ubuntu) as your default WSL instance.

  3. Ensure WSL2 is set as the default version:

    wsl --set-default-version 2
  4. Once your distribution is set up, enter your WSL terminal and update your package list:

    sudo apt update

Install Required Tools

To build the flight software, you need to install several tools in your WSL environment:

  1. CMake – for managing the build process:

    sudo apt install cmake
  2. Make – a build automation tool:

    sudo apt install build-essential
  3. Clang – a C++ compiler:

    sudo apt install clang
  4. Git – to clone and manage your repositories:

    sudo apt install git
  5. GitHub CLI (gh) – for interacting with GitHub:

    sudo apt install gh

Authenticate with GitHub

To interact with private GitHub repositories and push code, you need to authenticate with GitHub CLI:

  1. Log in using the GitHub CLI:

    gh auth login
  2. Follow the prompts to authenticate via a web browser or with a GitHub token. Choose HTTPS as the protocol when prompted.

Get the Host and WSL IP Addresses

  1. To get the host machine's IP: Open a WSL terminal and run:

    ip route show | grep -i default | awk '{ print $3}'

    Look for the IP address under the "Ethernet adapter vEthernet (WSL)" section.

  2. To get the WSL instance's IP: In your WSL terminal, run:

    hostname -I

Clone and Build the Flight Software

  1. Clone the flight software repository in your WSL terminal and switch to the correct branch (likely dev):

    git clone https://github.com/Propulsive-Landing/ferda.git
    cd ferda
    git switch dev
  2. Build the software in simulation mode using the:

    cmake -DCMAKE_BUILD_TYPE=Simulation -DSIM_LOCAL_PORT=8002 -DSIM_SERVER_PORT=8003 -DSIM_SERVER_IP="[Insert Host IP here]" -Bbuild .
    cd build
    make all

    NOTE: Ports may change in future versions of simulation.

Configure the Simulink Model

  1. In MATLAB, open the Simulink model for flight simulation.
  2. Set the UDPSend block to the WSL IP and port 8002, and ensure the UDPReceive is set to receive from any source.
  3. Install Simulink Desktop Real-Time to run the simulation in real time using the Add-On Manager in MATLAB.
  4. Make sure you have the Real-Time Kernel installed. A guide on this is shown here
  5. Set Simulink to Connected IO mode and start the simulation.

Run the Flight Software

Switch back to WSL and run the flight software:

sudo ./Ferda

SIL Testing Using Windows (NOT TESTED)

For users who prefer running the flight software directly on Windows without WSL, you can follow this guide to set up and run the simulation loop using Windows-native tools and loopback IP. However, please note that the flight computer uses a Linux-based OS, so discrepancies may occur.

Install the Required Tools

To build and run the flight software natively on Windows, you'll need to install several development tools:

  1. CMake – Download and install from the official website: CMake.

    • Make sure to add CMake to your system path during installation.
  2. Visual Studio (or Build Tools for Visual Studio) – This will provide a C++ compiler. You can install the Desktop development with C++ workload via the Visual Studio Installer or download Build Tools for Visual Studio from here.

    • Ensure that the "MSVC" compiler and CMake support are selected during installation.
  3. Git – Download and install Git from the Git website. This will allow you to clone the repository and manage version control.

  4. GitHub CLI (gh) – Install GitHub CLI by downloading it from GitHub. Once installed, authenticate via:

    gh auth login

    Follow the prompts to authenticate with your GitHub account.

Clone and Build the Flight Software

  1. Clone the Repository: Open a Git Bash or command prompt on Windows and clone the repository:

    git clone https://github.com/Propulsive-Landing/ferda.git
    cd ferda
    git switch dev
  2. Generate the Build Files Using CMake: In your Git Bash, command prompt, or terminal of choice, configure the build for simulation mode:

    cmake -Bbuild -DCMAKE_BUILD_TYPE=Simulation -DSIM_LOCAL_PORT=8002 -DSIM_SERVER_PORT=8003 -DSIM_SERVER_IP="127.0.0.1"

    Explanation of flags:

    • -DCMAKE_BUILD_TYPE=Simulation: This flag sets the build for simulation.
    • -DSIM_LOCAL_PORT=8002: Port used to receive data from Simulink.
    • -DSIM_SERVER_PORT=8003: Port to send data to Simulink.
    • -DSIM_SERVER_IP="127.0.0.1": Since we are running everything on the same machine, use 127.0.0.1 (loopback IP).
  3. Compile the Software: Navigate to the build directory and compile the software:

    cd build
    cmake --build .

    This will generate the Ferda.exe executable file in the build folder.

  4. Create a Logs Directory (Optional): If logging is enabled, make sure you have a logs directory in the root of the project:

    mkdir logs

Configure the Simulink Model

  1. Launch MATLAB and Simulink: Open the Simulink model for flight simulation in MATLAB.

  2. Configure UDPSend/UDPReceive Blocks:

    • Set the UDPSend block to send data to the loopback IP (127.0.0.1) on port 8002.
    • Ensure that the UDPReceive block is configured to listen on port 8003.
  3. Install Simulink Desktop Real-Time: You need the Simulink Desktop Real-Time add-on to run simulations in real-time. You can install this via the Add-On Manager in MATLAB.

  4. Set Simulink to Connected IO Mode:

    • Set Simulink to Connected IO mode to simulate real-time hardware.
  5. Start the Simulation: Start the Simulink simulation.

    • The rocket should remain static until your flight software commands it.
    • Make sure your model is running in real time with 1:1 real-time to simulation

Run the Flight Software

  1. Return to the Command Prompt: Switch back to your command prompt or Git Bash.

  2. Run the Flight Software: Start the flight software by running:

    ./Ferda.exe

Notes:

  • Run Ferda (FSW) through WSL first if you're having trouble communicating with the simulation.
  • WSL can be tricky to initially set up, but there is plenty of available documentation to resolve these issues. Start here and use Google if you still are having issues.

The flight software should be connected with the Simulink simulation, sending actuator commands and receiving simulated sensor data.

Design

We have separated all of our header files into the include directory, all non-hardware files into the src directory, and all hardware files into the hardware directory. Depending on the build type that you used, we either use hardware if built in Release mode, hardware_test if built in Debug mode, or hardware_simulation if built in Simulation mode.

READMEs for src and hardware files are located in src files README and hardware files README.

If you add a new sensor, it belongs in the 3 hardware directories

All config files listed below are in the ferda directory but should at some point be in a Config folder:

  • Angles.csv
  • Height.csv
  • Translation.csv
  • linux_library_requirements.txt
  • Brewfile

We do have a tests folder, but it has not been touched in a while. If you generate any unit tests, they should go here.

For all our GPIO pin handling, we have switched over to WiringPi because it was the easiest library to use. For more information about Raspberry Pi's GPIO look here GPIO

For all our PWM handling, we wanted to use hardware PWM signals, but depending on which Raspberry Pi we are using, it can have a maximum of 4 hardware PWM GPIO pins. We decided to buy PCA9685 boards, which can generate hardware PWM signals. For more information about the PCA9685 look here PCA9685

Flow

  1. Look for command through RF.cpp
  2. Change mode based on command

Architecture

We use the State machine pattern where we have defined several modes/states and one while loop in main. We use RF to change modes but modes can also change based on a condition in the code as well.

For our current Mode Flow, see here

In Mode.hpp, we define the Modes:

enum Phase
    {
        Standby,
        Calibration,
        ActuatorCalibration,
        TestTVC,
        ChirpTVC,
        Idle,
        Launch,
        Land,
        Terminate,
        Abort,
        Safe,
        HotfireIdle,
        ASITest,
        WaterFlow,
        ThreeSecondHotfire
    };

In RF.hpp, a subset of the commands look like below where Command is an enum where we add the RF command

 if (input_line == "ABORT")
            ParsedCommand = RF::Command::ABORT;
        else if (input_line == "ABORT_PAD")
            ParsedCommand = RF::Command::ABORT_PAD;
        else if (input_line == "ABORT_GROUND")
            ParsedCommand = RF::Command::ABORT_GROUND;
        else if (input_line == "TestTVC")
            ParsedCommand = RF::Command::TestTVC;
        else if (input_line == "ChirpTVC")
            ParsedCommand = RF::Command::ChirpTVC;
        else if (input_line == "Idle")
            ParsedCommand = RF::Command::Idle;
        else if (input_line == "Standby")
            ParsedCommand = RF::Command::Standby;

In Main.cpp, the while loop looks like:

while (mode.Update(navigation, controller, gps, igniter, imu, magnetometer, valveControl,  sparkPlug, pressureTransducer, loadCell, camera))
    {
    }

We either exit out of the while loop when the Mode is Terminate which returns false from Update() or if we hit Abort, before we ignite, then we exit the program right then and there

Ground Control Communication

This is the flight software that runs on the Raspberry Pi, but like I've mentioned in Flow, the flight software is expecting to see commands through the radio, which is where Ground Control comes in. All Ground Control is found in Ground Control GitHub Link. To communicate with the rocket, we use ground control and the XBees.

About

Holds all flight software for the UConn Propulsive Landing team rockets.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages