STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1#include <Adafruit_LIS3DH.h>
2#include <Adafruit_Sensor.h>
3#include <Arduino.h>
4#include <SPI.h>
5#include <SPIMemory.h>
6#include <STAR_ISM330DH.h>
7#include <STAR_MCP3201.h>
8#include <SparkFun_LPS28DFW_Arduino_Library.h>
9#include <Wire.h>
10#include <math.h>
11
12#include "apogee.h"
13#include "config.h"
14#include "flight_log.h"
15#include "flight_state.h"
16#include "pins.h"
17
18static SPIFlash g_flash(PIN_MX25_CS);
22static LPS28DFW g_baro;
23
26
27static volatile bool g_launchFlag = false;
28static volatile bool g_imuWakeFlag = false;
29
30void IRAM_ATTR onAccelInt() {
31 g_launchFlag = true;
32}
33
34void IRAM_ATTR onImuInt() {
35 g_imuWakeFlag = true;
36}
37
38static float pressureToAltitudeM(float pressureHpa, float seaLevelHpa) {
39 if (pressureHpa <= 0.f || seaLevelHpa <= 0.f)
40 return NAN;
41 return 44330.0f * (1.0f - powf(pressureHpa / seaLevelHpa, 0.190284f));
42}
43
44static uint32_t s_lastLpsMs = 0;
45static uint32_t s_lastMcpMs = 0;
46
47void setup() {
48 Serial.begin(115200);
49 while (!Serial)
50 delay(10);
51 delay(50);
52
55
56 SPI.begin(PIN_SCLK, PIN_MISO, PIN_MOSI, static_cast<int8_t>(-1));
59
60 if (!g_flash.begin()) {
61 Serial.println("ERROR: MX25 flash begin failed");
62 while (true)
63 delay(1000);
64 }
65 const uint32_t cap = g_flash.getCapacity();
66 Serial.printf("Flash capacity: %lu bytes\r\n",
67 static_cast<unsigned long>(cap));
68 if (!flightLogInit(g_flash, cap))
69 Serial.println("WARN: flightLogInit failed");
70
72
73 if (!g_lis.begin()) {
74 Serial.println("ERROR: LIS3DH not found");
75 while (true)
76 delay(1000);
77 }
78 g_lis.setDataRate(ACCEL_ODR);
79 g_lis.setRange(ACCEL_RANGE);
80 g_lis.configureHighGInterrupt(INT1_THS_VALUE, INT1_DUR_VALUE);
81
82 if (!g_imu.begin(SPI, SPISettings(4000000, MSBFIRST, SPI_MODE3),
83 PIN_IMU_CS)) {
84 Serial.println("ERROR: ISM330 SPI begin failed");
85 while (true)
86 delay(1000);
87 }
88 g_imu.deviceReset();
89 while (!g_imu.getDeviceReset())
90 delay(1);
91 delay(100);
92 g_imu.setDeviceConfig(true);
93 g_imu.setBlockDataUpdate(true);
94 g_imu.setAccelDataRate(ISM_XL_ODR_104Hz);
95 g_imu.setAccelFullScale(ISM330_ACCEL_FS);
96 g_imu.setGyroDataRate(ISM_GY_ODR_104Hz);
97 g_imu.setGyroFullScale(ISM_500dps);
98 g_imu.setAccelFilterLP2(true);
99 g_imu.setAccelSlopeFilter(ISM_LP_ODR_DIV_100);
100 g_imu.setGyroFilterLP1(true);
101 g_imu.setGyroLP1Bandwidth(ISM_MEDIUM);
102 if (!g_imu.configureWakeUpOnInt1(ISM330_WKUP_THS, ISM330_WAKEUP_DUR,
104 Serial.println("ERROR: ISM330 configureWakeUpOnInt1 failed");
105 while (true)
106 delay(1000);
107 }
108 g_imu.setPinMode(false);
109
110 Wire.begin(PIN_SDA, PIN_SCL);
111 while (g_baro.begin(LPS28DFW_I2C_ADDR, Wire) != LPS28DFW_OK) {
112 Serial.println("ERROR: LPS28DFW not found");
113 delay(1000);
114 }
115 lps28dfw_md_t modeConfig = {
116 .fs = LPS28DFW_1260hPa,
117 .odr = LPS28DFW_50Hz,
118 .avg = LPS28DFW_4_AVG,
119 .lpf = LPS28DFW_LPF_ODR_DIV_4,
120 };
121 if (g_baro.setModeConfig(&modeConfig) != LPS28DFW_OK) {
122 Serial.println("ERROR: LPS28DFW setModeConfig failed");
123 while (true)
124 delay(1000);
125 }
126
128 attachInterrupt(digitalPinToInterrupt(PIN_ACCEL_INT1), onAccelInt, RISING);
130 attachInterrupt(digitalPinToInterrupt(PIN_IMU_INT1), onImuInt, RISING);
131
132 apogeeReset();
133
134 Serial.println("DAN-E Avionics ready");
135}
136
137void loop() {
138 const uint32_t now = millis();
139
140 if (g_launchFlag) {
141 g_launchFlag = false;
142 (void)g_lis.readAndClearInterrupt();
144 }
145 if (g_imuWakeFlag) {
146 g_imuWakeFlag = false;
148 (void)g_imu.serviceWakeUpInterrupt(&wu);
149 }
150
151 if (now - s_lastLpsMs >= 20U) {
152 s_lastLpsMs = now;
153 if (g_baro.getSensorData() == LPS28DFW_OK) {
154 const float hpa = g_baro.data.pressure.hpa;
155 const float tempC = g_baro.data.heat.deg_c;
156 const float altM = pressureToAltitudeM(hpa, LPS28DFW_SEA_LEVEL_HPA);
157
159 apogeePushAltitude(altM);
162 }
163
164 if (sensorsShouldLog())
165 logLps28dfw(hpa, tempC, altM, now);
166 }
167 }
168
169 if (now - s_lastMcpMs >= 10U) {
170 s_lastMcpMs = now;
171 const uint16_t raw = g_adc.read();
172 const float psi =
173 (static_cast<float>(raw) / ADC_COUNTS) * PT_FULL_SCALE_PSI;
174 if (sensorsShouldLog())
175 logMcp3201(raw, psi, now);
176 }
177
178 g_lis.read();
179 sensors_event_t ev{};
180 g_lis.getEvent(&ev);
181 if (sensorsShouldLog()) {
182 const float ax = ev.acceleration.x / 9.80665f;
183 const float ay = ev.acceleration.y / 9.80665f;
184 const float az = ev.acceleration.z / 9.80665f;
185 logLis3dh(ax, ay, az, now);
186 }
187
188 if (g_imu.checkStatus()) {
189 if (g_imu.getAccel(&g_accel) && g_imu.getGyro(&g_gyro)) {
190 if (sensorsShouldLog()) {
191 logIsm330(g_accel.xData / 1000.0f, g_accel.yData / 1000.0f,
192 g_accel.zData / 1000.0f, g_gyro.xData / 1000.0f,
193 g_gyro.yData / 1000.0f, g_gyro.zData / 1000.0f, now);
194 }
195 }
196 }
197
200
201#if DEBUG_TELEMETRY
202 static uint32_t s_dbgMs = 0;
203 if (now - s_dbgMs >= 200U) {
204 s_dbgMs = now;
205 Serial.printf(
206 "state=%u baro_ok\r\n",
207 static_cast<unsigned>(static_cast<uint8_t>(flightStateGet())));
208 }
209#endif
210
211 delay(1);
212}
This is a library for the Adafruit LIS3DH Accel breakout board.
static SerialStub Serial
Definition Arduino.h:128
#define INPUT
Definition Arduino.h:21
#define HIGH
Definition Arduino.h:19
void pinMode(int, int)
Definition Arduino.h:46
#define OUTPUT
Definition Arduino.h:22
unsigned long millis()
Definition Arduino.h:29
void digitalWrite(int, int)
Definition Arduino.h:48
#define PIN_ADC_CS
Definition pins.h:12
#define PIN_MX25_CS
Definition pins.h:11
#define PIN_MISO
Definition pins.h:8
#define PIN_SDA
Definition pins.h:17
#define PIN_IMU_INT1
Definition pins.h:32
#define PIN_MX25_RESET
Definition pins.h:21
#define PIN_IMU_CS
Definition pins.h:14
#define PIN_SCLK
Definition pins.h:6
#define PIN_SCL
Definition pins.h:18
#define PIN_MOSI
Definition pins.h:7
#define PIN_ACCEL_CS
Definition pins.h:13
#define PIN_ACCEL_INT1
Definition pins.h:34
#define ISM330_WAKEUP_DUR
Definition main.h:28
#define ISM330_ROUTE_DRDY_TO_INT1
Definition main.h:31
#define ISM330_ACCEL_FS
Definition main.h:21
#define ACCEL_RANGE
Definition main.h:11
#define ACCEL_ODR
Definition main.h:21
#define LPS28DFW_I2C_ADDR
Definition main.h:9
#define LPS28DFW_SEA_LEVEL_HPA
Definition main.h:13
#define ADC_COUNTS
Definition main.h:17
void delay(int ms)
void apogeeReset()
Definition apogee.cpp:14
bool apogeeShouldConfirm()
Definition apogee.cpp:43
void apogeePushAltitude(float alt_m)
Definition apogee.cpp:20
Class that stores state and functions for interacting with Adafruit_LIS3DH.
SPI driver for ISM330DHCX.
static constexpr uint8_t INT1_THS_VALUE
Definition config.h:48
static constexpr uint8_t ISM330_WKUP_THS
Definition config.h:68
static constexpr float PT_FULL_SCALE_PSI
Definition config.h:12
static constexpr uint8_t INT1_DUR_VALUE
Definition config.h:55
void setup()
Definition main.cpp:142
void loop()
Definition main.cpp:201
static volatile bool g_imuWakeFlag
Definition main.cpp:28
static LPS28DFW g_baro
Definition main.cpp:22
static volatile bool g_launchFlag
Definition main.cpp:27
static ISM330DH_SPI g_imu
Definition main.cpp:21
static SPIFlash g_flash(PIN_MX25_CS)
void IRAM_ATTR onImuInt()
Definition main.cpp:34
static sfe_ism_data_t g_accel
Definition main.cpp:24
static Adafruit_LIS3DH g_lis(PIN_ACCEL_CS, &SPI)
static uint32_t s_lastMcpMs
Definition main.cpp:45
static sfe_ism_data_t g_gyro
Definition main.cpp:25
static uint32_t s_lastLpsMs
Definition main.cpp:44
static STAR_MCP3201 g_adc(PIN_ADC_CS, &SPI)
static float pressureToAltitudeM(float pressureHpa, float seaLevelHpa)
Definition main.cpp:38
void IRAM_ATTR onAccelInt()
Definition main.cpp:30
void logLis3dh(float ax_g, float ay_g, float az_g, uint32_t t_ms)
bool flightLogInit(SPIFlash &flash, uint32_t capacityBytes)
bool sensorsShouldLog()
void logMcp3201(uint16_t raw, float psi, uint32_t t_ms)
void logIsm330(float ax, float ay, float az, float gx, float gy, float gz, uint32_t t_ms)
void logLps28dfw(float hpa, float temp_c, float alt_m, uint32_t t_ms)
FlightState flightStateGet()
void flightStateInit()
void flightStateOnLaunchDetect()
Idle → Launch (call from main when LIS3 launch ISR fires).
void flightStateOnApogee()
Launch → Active when apogee algorithm confirms (only valid from Launch).
void applyActuatorOutputs()
void flightStateTick()
#define ISM_GY_ODR_104Hz
#define ISM_MEDIUM
#define ISM_LP_ODR_DIV_100
#define ISM_500dps
#define ISM_XL_ODR_104Hz
Filled by serviceWakeUpInterrupt() when INT1 was a wake-up (high-accel) event.