Avionics
Core avionics package for CURE flight computers
Loading...
Searching...
No Matches
Serial_Sim.h
Go to the documentation of this file.
1#ifndef SERIAL_SIM_H
2#define SERIAL_SIM_H
3
4#include "Adafruit_Sensor.h"
5#include "ArduinoHAL.h"
8
9#define LSM6DS_ACCEL_RANGE_16_G 0x03
10#define LSM6DS_GYRO_RANGE_2000_DPS 0x03
11#define LSM6DS_RATE_104_HZ 0x04
12// LIS3MDL (Magnetometer 1.3) Define
13#define LIS3MDL_DATARATE_155_HZ 0x06
14#define LIS3MDL_RANGE_4_GAUSS 0x01
15#define LIS3MDL_CONTINUOUSMODE 0x00
16#define LIS3MDL_MEDIUMMODE 0x01
17// LIS2MDL (Magnetometer 1.4) Define
18#define LIS2MDL_RATE_100_HZ 0x06
19// BMP3 (Barometric Pressure Sensor) Define
20#define BMP3_OVERSAMPLING_8X 0x03
21#define BMP3_OVERSAMPLING_4X 0x02
22#define BMP3_IIR_FILTER_COEFF_3 0x03
23#define BMP3_ODR_100_HZ 0x05
24
30class SerialSim {
31public:
32 static SerialSim& getInstance() {
33 static SerialSim instance; // Singleton
34 return instance;
35 }
36
37 void begin(Stream *inStream, BaseStateMachine *stateMachine) {
38 serial = inStream;
39 this->stateMachine = stateMachine;
40
41 // Handshake: send "START\n" until we get ACK (0x06)
42 uint8_t ack = 0;
43 while (ack != 0x06) {
44 serial->write("START\n");
45 delay(100);
46 if (serial->available() > 0) {
47 ack = serial->read();
48 }
49 }
50 }
51
52 // Non‐blocking update:
53 // 1) Read as many characters as available
54 // 2) If we detect a newline, parse that line
55 void update() {
56 int availableBytes = serial->available();
57
58 while (serial->available() > 0) {
59 char c = static_cast<char>(serial->read());
60
61 // If we get a newline, parse the line
62 if (c == '\n') {
63 // We have a full line in _partialLine
64 handleIncomingLine(_partialLine);
65 _partialLine = ""; // Clear for the next line
66 }
67 else {
68 _partialLine += c;
69 }
70 }
71 }
72
73 bool serialAvailable(void){
74 return serial->available() > 0;
75 }
76
77 // These next update functions provide the sensor data to calling code
78 void updateTimeStamp(float &timestamp) {
79 timestamp = _timestamp;
80 }
81
82 void updateAcl(sensors_event_t *accel) {
83 accel->acceleration.x = accel_x;
84 accel->acceleration.y = accel_y;
85 accel->acceleration.z = accel_z;
86 }
87
88 void updateGyro(sensors_event_t *gyro) {
89 gyro->gyro.x = gyro_x;
90 gyro->gyro.y = gyro_y;
91 gyro->gyro.z = gyro_z;
92 }
93
94 void updateMag(sensors_event_t *mag) {
95 mag->magnetic.x = magnetic_x;
96 mag->magnetic.y = magnetic_y;
97 mag->magnetic.z = magnetic_z;
98 }
99
100 void updateAlt(float &alt){
101 alt = _alt;
102 }
103
104 void updatePres(float &pres){
105 pres = _pres;
106 }
107
108 void updateTemp(sensors_event_t &temp){
109 temp.temperature = _temp;
110 }
111
112private:
113 SerialSim() {} // Private constructor for singleton
114 SerialSim(const SerialSim&) = delete;
115 SerialSim& operator=(const SerialSim&) = delete;
116
117 // Called once a full line of data is received
118 void handleIncomingLine(String &line) {
119 Serial.println("Handling line: " + line);
120 if (line.length() < 5) {
121 Serial.println("Line too short");
122 return; // not enough data to parse anything meaningful
123 }
124
125 // We'll parse each comma‐separated float in the line
126 _timestamp = parseNextFloat(line);
127 accel_x = parseNextFloat(line);
128 accel_y = parseNextFloat(line);
129 accel_z = parseNextFloat(line);
130 _alt = parseNextFloat(line);
131 // gyro_x = parseNextFloat(line);
132 // gyro_y = parseNextFloat(line);
133 // gyro_z = parseNextFloat(line);
134 // magnetic_x = parseNextFloat(line);
135 // magnetic_y = parseNextFloat(line);
136 // magnetic_z = parseNextFloat(line);
137
138 // _pres = parseNextFloat(line);
139 // _temp = line.toFloat(); // The remaining chunk is the last float
140
141 Serial.println("Parsed Data!");
142
143 // After parsing the line, send an ACK
144 ack();
145 }
146
147 float parseNextFloat(String &data) {
148 int commaIndex = data.indexOf(',');
149 if (commaIndex == -1) {
150 // If there's no comma, parse as much as we can
151 float val = data.toFloat();
152 data = "";
153 return val;
154 }
155
156 // Parse substring up to the comma
157 float value = data.substring(0, commaIndex).toFloat();
158 // Remove parsed portion (including the comma)
159 data = data.substring(commaIndex + 1);
160 return value;
161 }
162
163 // Send ACK (0x06) alongside the current state to the serial port
164 void ack(){
165 serial->write(stateMachine->getState());
166 serial->write(0x06);
167 }
168
169private:
170 Stream* serial = nullptr;
171 BaseStateMachine* stateMachine = nullptr;
172 String _partialLine; // used to accumulate characters until newline
173
174 // Parsed sensor data
175 float _timestamp = 0;
176 float accel_x = 0, accel_y = 0, accel_z = 0;
177 float gyro_x = 0, gyro_y = 0, gyro_z = 0;
178 float magnetic_x = 0, magnetic_y = 0, magnetic_z = 0;
179 float _alt = 0;
180 float _pres = 0;
181 float _temp = 0;
182};
183
184#endif // SERIAL_SIM_H
Abstract interface for flight state machines driven by IMU/altimeter data.
void println(const T &message)
Definition serial_mock.h:32
Serial-based sensor/flight simulation singleton for hardware-in-the-loop.
Definition Serial_Sim.h:30
void updateTemp(sensors_event_t &temp)
Definition Serial_Sim.h:108
void updateMag(sensors_event_t *mag)
Definition Serial_Sim.h:94
void updateAlt(float &alt)
Definition Serial_Sim.h:100
void update()
Definition Serial_Sim.h:55
void updatePres(float &pres)
Definition Serial_Sim.h:104
void updateTimeStamp(float &timestamp)
Definition Serial_Sim.h:78
void begin(Stream *inStream, BaseStateMachine *stateMachine)
Definition Serial_Sim.h:37
bool serialAvailable(void)
Definition Serial_Sim.h:73
void updateGyro(sensors_event_t *gyro)
Definition Serial_Sim.h:88
void updateAcl(sensors_event_t *accel)
Definition Serial_Sim.h:82
static SerialSim & getInstance()
Definition Serial_Sim.h:32
MockSerial Serial