N4 Flight Software N4
Flight software used for the N4 flight computers
|
This contains the main driver code for the flight computer. More...
#include <Arduino.h>
#include <Wire.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <TinyGPSPlus.h>
#include <SFE_BMP180.h>
#include <FS.h>
#include <SD.h>
#include <SPIFFS.h>
#include <CSV_Parser.h>
#include "defs.h"
#include "mpu.h"
#include "SerialFlash.h"
#include "logger.h"
#include "data_types.h"
#include "states.h"
#include "system_logger.h"
#include "system_log_levels.h"
#include "wifi-config.h"
#include "kalman_filter.h"
#include "ring_buffer.h"
#include "custom_test_states.h"
Macros | |
#define | BMP_CHECK_BIT 0 |
#define | IMU_CHECK_BIT 1 |
#define | FLASH_CHECK_BIT 2 |
#define | GPS_CHECK_BIT 3 |
#define | SD_CHECK_BIT 4 |
#define | SPIFFS_CHECK_BIT 5 |
#define | TEST_HARDWARE_CHECK_BIT 6 |
#define | BAUDRATE 115200 |
#define | NAK_INTERVAL 4000 |
#define | SOH 0x01 |
#define | EOT 0x04 |
#define | ACK 0x06 |
#define | NAK 0x15 |
#define | CAN 0x18 |
#define | MAX_CMD_LENGTH 10 |
#define | MAX_CSV_LENGTH 256 |
#define | FORMAT_SPIFFS_IF_FAILED 1 |
#define | ALTITUDE 1525.0 |
Enumerations | |
enum | OPERATION_MODE { SAFE_MODE = 0 , ARMED_MODE } |
enum | DAQ_STATES { HANDSHAKE = 0 , RECEIVE_TEST_DATA , CONFIRM_TEST_DATA , FINISH_DATA_RECEIVE } |
This enum holds the states during flight computer test mode. More... | |
enum | TEST_STATES { DATA_CONSUME = 0 , DONE_TESTING } |
Functions | |
void | drogueChuteDeploy () |
fires the pyro-charge to deploy the drogue chute Turn on the drogue chute ejection circuit by running the GPIO HIGH for a preset No. of seconds. Default no. of seconds to remain HIGH is 5 | |
void | mainChuteDeploy () |
fires the pyro-charge to deploy the main chute Turn on the main chute ejection circuit by running the GPIO HIGH for a preset No. of seconds Default no. of seconds to remain HIGH is 5 | |
void | initDynamicWIFI () |
create dynamic WIFI | |
float | kalmanFilter (float z) |
Kalman filter estimated value calculation. | |
char | feedRowParser () |
bool | rowParserFinished () |
void | listDir (fs::FS &fs, const char *dirname, uint8_t levels) |
uint8_t | initTestGPIO () |
Inititialize the GPIOs. | |
uint8_t | InitSPIFFS () |
uint8_t | initSD () |
void | SwitchLEDs (uint8_t red_state, uint8_t green_state) |
Switch the LEDS states. | |
void | InitXMODEM () |
Initiate XMODEM protocol by sending a NAK command every 4 seconds until the transmitter returns an ACK signal. | |
void | SerialEvent () |
void | ParseSerial (char *) |
void | checkRunTestToggle () |
Sample the RUN/TEST toggle pins to check whether the flight computer is in test-DAQ mode, TEST mode or FLIGHT mode. If in DAQ mode, set the DAQ flag If in TEST mode, define the TEST flag FLIGHT mode is activated by completely removing the jumper. | |
void | checkSubSystems () |
void | readFile (fs::FS &fs, const char *path) |
void | readStateFile (fs::FS &fs, const char *path) |
void | readSubSystemStateFile (fs::FS &fs, const char *path) |
void | writeFile (fs::FS &fs, const char *path, const char *message) |
void | appendFile (fs::FS &fs, const char *path, const char *message) |
void | deleteFile (fs::FS &fs, const char *path) |
void | readTestDataFile () |
void | initDataFiles () |
void | buzz () |
Buzz the buzzer for a given buzz_interval This function is non-blocking. | |
void | blink_200ms (uint8_t led_pin) |
implements non-blocking blink | |
void | ParseSerialBuffer (char *buffer) |
void | ParseSerialNumeric (int value) |
Parse the received serial command if it is a digit We are only interested in numeric values being sent by the transmitter to us, the receiver. | |
void | handshakeSerialEvent () |
Receive serial message during handshake. | |
void | receiveTestDataSerialEvent () |
Receive serial message during RECEIVE_TEST_DATA state Data received in this state is the actual test data. It is saved into the test flash memory. | |
void | prepareForDataReceive () |
this function prepares the flight computer to receive test data depending on the state, it tries to establich link between flight computer and sending PC receives the actual data confirm the actual data | |
PubSubClient | client (wifi_client) |
uint8_t | MQTTInit (const char *broker_IP, uint16_t broker_port) |
uint8_t | BMPInit () |
Initialize BMP180 barometric sensor. | |
uint8_t | GPSInit () |
Initialize the GPS connected on Serial2. | |
void | readAccelerationTask (void *pvParameter) |
Read acceleration data from the accelerometer. | |
void | readAltimeterTask (void *pvParameters) |
Read atm pressure data from the barometric sensor onboard. | |
void | readGPSTask (void *pvParameters) |
Read the GPS location data and altitude and append to telemetry packet for transmission. | |
void | kalmanFilterTask (void *pvParameters) |
Filter data using the Kalman Filter. | |
void | checkFlightState (void *pvParameters) |
check various condition from flight data to change the flight state | |
void | flightStateCallback (void *pvParameters) |
performs flight actions based on the current flight state | |
void | debugToTerminalTask (void *pvParameters) |
debug flight/test data to terminal, this task is called if the DEBUG_TO_TERMINAL is set to 1 (see defs.h) | |
void | logToMemory (void *pvParameter) |
log the data to the external flash memory | |
void | MQTT_TransmitTelemetry (void *pvParameters) |
send flight data to ground | |
void | MQTT_Reconnect () |
Try reconnecting to MQTT if connection is lost. | |
void | MQTTInit (const char *broker_IP, int broker_port) |
Initialize MQTT. | |
void | customCheckState () |
void | setup () |
Setup - perform initialization of all hardware subsystems, create queues, create queue handles initialize system check table. | |
void | loop () |
Main loop. | |
Variables | |
uint8_t | operation_mode = 0 |
uint8_t | current_state = ARMED_FLIGHT_STATE::PRE_FLIGHT_GROUND |
uint8_t | STATE_BIT_MASK = 0 |
TinyGPSPlus | gps |
SystemLogger | SYSTEM_LOGGER |
const char * | system_log_file = "/event_log.txt" |
LOG_LEVEL | level = INFO |
const char * | rocket_ID = "FC1" |
uint8_t | is_flight_mode = 0 |
char | subsystems_state_buffer [10] |
uint8_t | SUBSYSTEM_INIT_MASK = 0b00000000 |
uint8_t | DAQ_MODE = 0 |
uint8_t | TEST_MODE = 0 |
uint8_t | SOH_recvd_flag = 0 |
unsigned long | last_NAK_time = 0 |
unsigned long | current_NAK_time = 0 |
char | SOH_CHR [6] = "SOH" |
char | serial_buffer [MAX_CMD_LENGTH] |
int16_t | serial_index = 0 |
char | test_data_buffer [MAX_CSV_LENGTH] |
char | data_buffer_formatted [MAX_CSV_LENGTH] |
int16_t | test_data_serial_index = 0 |
uint8_t | recv_data_led = 2 |
uint8_t | red_led = 15 |
uint8_t | green_led = 4 |
uint8_t | buzzer = 33 |
uint8_t | SET_DAQ_MODE_PIN = 14 |
uint8_t | SET_TEST_MODE_PIN = 13 |
uint8_t | SD_CS_PIN = 26 |
uint8_t | current_DAQ_state = DAQ_STATES::HANDSHAKE |
uint8_t | sub_check_state |
uint8_t | current_test_state = TEST_STATES::DATA_CONSUME |
const char * | f_name = "/altitude_log.csv" |
File | test_file |
const char * | test_data_file = "/data.csv" |
const char * | run_state_file = "/state.txt" |
char | current_test_state_buffer [50] = "" |
char | subsystem_state_buffer [50] |
unsigned long | last_buzz = 0 |
unsigned long | current_buzz = 0 |
unsigned long | buzz_interval = 200 |
uint8_t | buzzer_state = LOW |
unsigned long | last_blink = 0 |
unsigned long | current_blink = 0 |
unsigned long | blink_interval = 200 |
uint8_t | led_state = LOW |
int | value = 0 |
Parse the received serial command if it is a string. | |
WiFiClient | wifi_client |
WIFIConfig | wifi_config |
uint8_t | drogue_pyro = 25 |
uint8_t | main_pyro = 12 |
uint8_t | flash_cs_pin = 5 |
uint8_t | remote_switch = 27 |
uint8_t | flash_led_pin = 32 |
char | filename [] = "flight.txt" |
uint32_t | FILE_SIZE_512K = 524288L |
uint32_t | FILE_SIZE_1M = 1048576L |
uint32_t | FILE_SIZE_4M = 4194304L |
SerialFlashFile | file |
unsigned long long | previous_log_time = 0 |
unsigned long long | current_log_time = 0 |
uint16_t | log_sample_interval = 10 |
DataLogger | data_logger (flash_cs_pin, flash_led_pin, filename, file, FILE_SIZE_4M) |
long long | current_time = 0 |
long long | previous_time = 0 |
char | telemetry_packet_buffer [256] |
ring_buffer | altitude_ring_buffer |
float | curr_val |
float | oldest_val |
uint8_t | apogee_flag =0 |
uint8_t | main_eject_flag = 0 |
TaskHandle_t | readAccelerationTaskHandle |
TaskHandle_t | readAltimeterTaskHandle |
TaskHandle_t | readGPSTaskHandle |
TaskHandle_t | clearTelemetryQueueTaskHandle |
TaskHandle_t | checkFlightStateTaskHandle |
TaskHandle_t | flightStateCallbackTaskHandle |
TaskHandle_t | MQTT_TransmitTelemetryTaskHandle |
TaskHandle_t | kalmanFilterTaskHandle |
TaskHandle_t | debugToTerminalTaskHandle |
TaskHandle_t | logToMemoryTaskHandle |
accel_type_t | acc_data |
gyro_type_t | gyro_data |
gps_type_t | gps_data |
altimeter_type_t | altimeter_data |
telemetry_type_t | telemetry_packet |
MPU6050 | imu (0x68, 16, 1000) |
SFE_BMP180 | altimeter |
char | status |
double | T |
double | PRESSURE |
double | p0 |
double | a |
QueueHandle_t | telemetry_data_queue_handle |
QueueHandle_t | log_to_mem_queue_handle |
QueueHandle_t | check_state_queue_handle |
QueueHandle_t | debug_to_term_queue_handle |
QueueHandle_t | kalman_filter_queue_handle |
This contains the main driver code for the flight computer.
0x5765206D6179206D616B65206F757220706C616E73202C 0x62757420476F642068617320746865206C61737420776F7264
#define ACK 0x06 |
positive acknowledgement
#define CAN 0x18 |
cancel
#define EOT 0x04 |
end of transmission
#define MAX_CMD_LENGTH 10 |
Maximum length of the XMODEM command string that can be received
#define MAX_CSV_LENGTH 256 |
Maximum length of the csv string that can be received
#define NAK 0x15 |
negative acknowledgement
#define NAK_INTERVAL 4000 |
Interval in which to send the NAK command to the transmitter
#define SOH 0x01 |
start of header
enum DAQ_STATES |
enum OPERATION_MODE |
flight states these states are to be used for flight
enum TEST_STATES |
Holds the states used when consuming the test data in testing mode
void blink_200ms | ( | uint8_t | led_pin | ) |
implements non-blocking blink
uint8_t BMPInit | ( | ) |
Initialize BMP180 barometric sensor.
void buzz | ( | ) |
Buzz the buzzer for a given buzz_interval This function is non-blocking.
void checkFlightState | ( | void * | pvParameters | ) |
void checkRunTestToggle | ( | ) |
Sample the RUN/TEST toggle pins to check whether the flight computer is in test-DAQ mode, TEST mode or FLIGHT mode. If in DAQ mode, set the DAQ flag If in TEST mode, define the TEST flag FLIGHT mode is activated by completely removing the jumper.
TEST_MODE Pin and RUN_MODE pin are both pulled HIGH. When you set the jumper, you pull that pin to LOW.
void debugToTerminalTask | ( | void * | pvParameters | ) |
debug flight/test data to terminal, this task is called if the DEBUG_TO_TERMINAL is set to 1 (see defs.h)
pvParameter | - A value that is passed as the parameter to the created task. If pvParameter is set to the address of a variable then the variable must still exist when the created task executes - so it is not valid to pass the address of a stack variable. |
record number operation_mode state ax ay az pitch roll gx gy gz latitude longitude gps_altitude pressure temperature altitude_agl velocity
void drogueChuteDeploy | ( | ) |
fires the pyro-charge to deploy the drogue chute Turn on the drogue chute ejection circuit by running the GPIO HIGH for a preset No. of seconds.
Default no. of seconds to remain HIGH is 5
char feedRowParser | ( | ) |
void flightStateCallback | ( | void * | pvParameters | ) |
performs flight actions based on the current flight state
If the flight state requires an action, we perform it here For example if the flight state is apogee, we perform MAIN_CHUTE ejection
uint8_t GPSInit | ( | ) |
Initialize the GPS connected on Serial2.
FIXME: Proper GPS init check! Look into if the GPS has acquired a LOCK on satelites Only if it has a lock then can we return a 1
GPS is low priority at the time of writing this but make it work!
void handshakeSerialEvent | ( | ) |
Receive serial message during handshake.
uint8_t initTestGPIO | ( | ) |
Inititialize the GPIOs.
void InitXMODEM | ( | ) |
Initiate XMODEM protocol by sending a NAK command every 4 seconds until the transmitter returns an ACK signal.
XMODEM serial function definition
none |
void kalmanFilterTask | ( | void * | pvParameters | ) |
Filter data using the Kalman Filter.
void listDir | ( | fs::FS & | fs, |
const char * | dirname, | ||
uint8_t | levels ) |
XMODEM serial function prototypes
void logToMemory | ( | void * | pvParameter | ) |
log the data to the external flash memory
pvParameter | - A value that is passed as the paramater to the created task. If pvParameter is set to the address of a variable then the variable must still exist when the created task executes - so it is not valid to pass the address of a stack variable. |
void loop | ( | ) |
Main loop.
Here is where we consume the test data stored in the data.txt file
void mainChuteDeploy | ( | ) |
fires the pyro-charge to deploy the main chute Turn on the main chute ejection circuit by running the GPIO HIGH for a preset No. of seconds Default no. of seconds to remain HIGH is 5
void MQTT_TransmitTelemetry | ( | void * | pvParameters | ) |
send flight data to ground
pvParameter | - A value that is passed as the paramater to the created task. If pvParameter is set to the address of a variable then the variable must still exist when the created task executes - so it is not valid to pass the address of a stack variable. |
PACKAGE TELEMETRY PACKET
record number operation_mode state ax ay az pitch roll gx gy gz latitude longitude gps_altitude gps_time pressure temperature altitude_agl velocity pyro1_state // not used pyro2_state // not used battery_voltage // not used
void MQTTInit | ( | const char * | broker_IP, |
int | broker_port ) |
Initialize MQTT.
void ParseSerialNumeric | ( | int | value | ) |
Parse the received serial command if it is a digit We are only interested in numeric values being sent by the transmitter to us, the receiver.
void readAccelerationTask | ( | void * | pvParameter | ) |
Read acceleration data from the accelerometer.
pvParameters | - A value that is passed as the paramater to the created task. If pvParameters is set to the address of a variable then the variable must still exist when the created task executes - so it is not valid to pass the address of a stack variable. |
void readAltimeterTask | ( | void * | pvParameters | ) |
Read atm pressure data from the barometric sensor onboard.
void readGPSTask | ( | void * | pvParameters | ) |
Read the GPS location data and altitude and append to telemetry packet for transmission.
pvParameters | - A value that is passed as the paramater to the created task. If pvParameters is set to the address of a variable then the variable must still exist when the created task executes - so it is not valid to pass the address of a stack variable. |
void receiveTestDataSerialEvent | ( | ) |
Receive serial message during RECEIVE_TEST_DATA state Data received in this state is the actual test data. It is saved into the test flash memory.
bool rowParserFinished | ( | ) |
void setup | ( | ) |
Setup - perform initialization of all hardware subsystems, create queues, create queue handles initialize system check table.
We need to read the TEST state from a file in the SD card This file stores the state we are in permanently, so that next time we reset while in run mode, we have a reference state to use
This file will be updated in the loop once we are done consuming the test data
check what state we are in while in the test state. If we are in the data consume state, set the current state to DATA_CONSUME The state is got from the SD card state.txt file
void SwitchLEDs | ( | uint8_t | red_state, |
uint8_t | green_state ) |
Switch the LEDS states.
accel_type_t acc_data |
///////////////////////// DATA TYPES /////////////////////////
uint8_t current_DAQ_state = DAQ_STATES::HANDSHAKE |
Define current data consume state the flight computer is in
unsigned long long current_log_time = 0 |
What is the processor time right now?
uint8_t current_state = ARMED_FLIGHT_STATE::PRE_FLIGHT_GROUND |
The starting state - we start at PRE_FLIGHT_GROUND state
SerialFlashFile file |
object representing file object for flash memory
uint32_t FILE_SIZE_1M = 1048576L |
1MB
uint32_t FILE_SIZE_4M = 4194304L |
4MB
uint32_t FILE_SIZE_512K = 524288L |
512KB
char filename[] = "flight.txt" |
data log filename - Filename must be less than 20 chars, including the file extension
uint8_t flash_cs_pin = 5 |
External flash memory chip select pin
uint8_t flash_led_pin = 32 |
LED pin connected to indicate flash memory formatting
uint8_t green_led = 4 |
Green LED pin
MPU6050 imu(0x68, 16, 1000) | ( | 0x68 | , |
16 | , | ||
1000 | ) |
///////////////////////// END OF DATA VARIABLES ///////////////////////// create an MPU6050 object 0x68 is the address of the MPU set gyro to max deg to 1000 deg/sec set accel fs reading to 16g
uint16_t log_sample_interval = 10 |
After how long should we sample and log data to flash memory?
uint8_t operation_mode = 0 |
Tells whether software is in safe or flight mode - FLIGHT_MODE=1, SAFE_MODE=0
unsigned long long previous_log_time = 0 |
The last time we logged data to memory
TaskHandle_t readAccelerationTaskHandle |
Task creation handles
uint8_t recv_data_led = 2 |
External flash memory chip select pin
uint8_t red_led = 15 |
Red LED pin
const char* rocket_ID = "FC1" |
Unique ID of the rocket. Change to the needed rocket name before uploading
uint8_t SD_CS_PIN = 26 |
Chip select pin for SD card
uint8_t SET_DAQ_MODE_PIN = 14 |
Pin to set the flight computer to DAQ mode
uint8_t SET_TEST_MODE_PIN = 13 |
Pin to set the flight computer to TEST mode
uint8_t SOH_recvd_flag = 0 |
Transmitter acknowledged?
uint8_t SUBSYSTEM_INIT_MASK = 0b00000000 |
Holds the status of the subsystems. 1 if Init OK, 0 if init failed
char subsystems_state_buffer[10] |
Holds the status of the subsystems. 1 if Init OK, 0 if init failed
QueueHandle_t telemetry_data_queue_handle |
///////////////////////// END OF PERIPHERALS INIT /////////////////////////
int value = 0 |
Parse the received serial command if it is a string.
WiFiClient wifi_client |
MQTT helper instances, if using MQTT to transmit telemetry