diff --git a/static_test_driver/autosequence.ino b/static_test_driver/autosequence.ino index 0534922..feb888c 100644 --- a/static_test_driver/autosequence.ino +++ b/static_test_driver/autosequence.ino @@ -40,7 +40,8 @@ typedef enum { MAINSTAGE, OXYGEN_SHUTDOWN, SHUTDOWN, - COOL_DOWN + COOL_DOWN, + STATIC_TEST_COMPLETE } state_t; // Convenience @@ -48,7 +49,7 @@ typedef enum { state = STATE; \ write_state(#STATE); \ } - + long start_time = 0; long shutdown_time = 0; @@ -82,7 +83,7 @@ void start_countdown() { if (valve_status[FUEL_PRE] || valve_status[FUEL_MAIN] || valve_status[OX_PRE] || - valve_status[OX_MAIN]) { + valve_status[OX_MAIN] ||) { Serial.println(F("Countdown aborted due to unexpected initial state")); SET_STATE(STAND_BY) // Set state to signal countdown was aborted } @@ -105,18 +106,21 @@ void abort_autosequence() { case PRESTAGE_READY: set_valve(FUEL_PRE, 0); set_valve(OX_PRE, 0); + set_valve(N2_CHOKE. 0); SET_STATE(STAND_BY) break; case PRESTAGE: + set_valve(N2_CHOKE, 0); set_valve(OX_PRE, 0); set_valve(FUEL_PRE, 0); reset_igniter(); SET_STATE(COOL_DOWN) shutdown_time = millis(); break; - + case MAINSTAGE: + set_valve(N2_CHOKE, 0); set_valve(OX_PRE, 0); set_valve(FUEL_PRE, 0); SET_STATE(SHUTDOWN) @@ -156,6 +160,7 @@ void run_control() { #endif if (run_time >= PRESTAGE_PREP_TIME) { SET_STATE(PRESTAGE_READY) + set_valve(N2_CHOKE, 1); set_valve(FUEL_PRE, 1); set_valve(OX_PRE, 1); } @@ -214,6 +219,7 @@ void run_control() { case SHUTDOWN: // Both prestage valves are closed, others may still be open if (millis() >= shutdown_time + PRE_LEADTIME) { + set_valve(N2_CHOKE, 0); set_valve(OX_MAIN, 0); set_valve(FUEL_MAIN, 0); SET_STATE(COOL_DOWN) @@ -228,5 +234,37 @@ void run_control() { start_time = 0; } break; + + case STATIC_TEST_COMPLETE: + // State that requires manual input to open Kero valve once static test is completed for the day + char state; + for (int i=1; i<10; i++){ + cout << "Are you done test firing for the day? [Y/N]"; + cin >> state; + if (state=='Y'){ + cout << "Are you sure you're done? [Y/N]"; + cin >> state; + if (state=='Y'){ + cout << "Draining Kerosene valve...vwooosh"; + set_valve(KERO_DRAIN, 1); + return; + } + else if (state=='N'){ + cout << "Let the firing resume!"; + return; + } + else{ + break; + } + } + else if (state=='N'){ + cout << "Let the firing resume!"; + return; + } + else{ + break; + } + } + break; } } diff --git a/static_test_driver/sensors.ino b/static_test_driver/sensors.ino index dbd2e84..e6e4eeb 100644 --- a/static_test_driver/sensors.ino +++ b/static_test_driver/sensors.ino @@ -1,147 +1,238 @@ - -#define SENSOR_ERROR_LIMIT 5 // Max number of errors in a row before deciding a sensor is faulty - -#define PRESSURE_CALIBRATION_FACTOR 246.58 -#define PRESSURE_OFFSET 118.33 -#define PRESSURE_MIN_VALID -100 -#define PRESSURE_MAX_VALID 1000 - -#define TEMP_MIN_VALID -10 -#define TEMP_MAX_VALID 120 - -#define FORCE_MIN_VALID -50 -#define FORCE_MAX_VALID 500 - -#if CONFIGURATION == MK_2 -#define LOAD_CELL_CALIBRATION_FACTOR 20400.0 //This value is obtained using the SparkFun_HX711_Calibration sketch -#else -#define LOAD_CELL_CALIBRATION_FACTOR 20400 -#endif - -#define LOAD_CELL_RETRY_INTERVAL 10 -#define LOAD_CELL_MAX_RETRIES 20 - -String sensor_errors = ""; - -float mean(const float *data, unsigned int size) { - float result = 0; - for (int i = 0; i < size; i++) - result += data[i]; - return result / size; -} - -void update_sensor_errors() { - set_lcd_errors(sensor_errors); - sensor_errors = ""; -} - -void error_check(int &error, bool working, const String &sensor_type, const String &sensor_name="", const String &sensor_short_name="") { - if (working) { - error = 0; - } else { - if (sensor_errors.length()) { - sensor_errors += ','; - } - sensor_errors += sensor_type.substring(0, min(sensor_type.length(), 2)) + sensor_short_name; - if (!error) { - Serial.print(sensor_name); - if (sensor_name.length()) { - Serial.print(' '); - } - Serial.print(sensor_type); - Serial.println(F(" sensor error")); - } - error++; - if (error > SENSOR_ERROR_LIMIT) { - sensor_status = false; - } - } -} - -float read_temp(int sensor, int &error, const String &sensor_name, const String &sensor_short_name) { - float result = analogRead(sensor) * 5.0 * 100 / 1024; - error_check(error, result > TEMP_MIN_VALID && result < TEMP_MAX_VALID, "temp", sensor_name, sensor_short_name); - return result; -} - -float read_pressure(int sensor, int &error, const String &sensor_name, const String &sensor_short_name) { - float result = (analogRead(sensor) * 5 / 1024.0) * PRESSURE_CALIBRATION_FACTOR - PRESSURE_OFFSET; - error_check(error, result > PRESSURE_MIN_VALID && result < PRESSURE_MAX_VALID, sensor_name, "pressure"); - return result; -} - -void init_accelerometer(Adafruit_MMA8451 &mma) { - bool working = false; - if (mma.begin()) { - mma.setRange(MMA8451_RANGE_2_G); // set acc range (2 4 8) - Serial.print(F("Accelerometer range ")); - Serial.print(2 << mma.getRange()); - Serial.println("G"); - working = true; - } - int error = 0; - error_check(error, working, "accelerometer"); - delay(100); -} - -sensors_vec_t read_accelerometer(Adafruit_MMA8451 &mma, int &error) { - sensors_event_t event; - mma.getEvent(&event); - sensors_vec_t accel = event.acceleration; - error_check(error, !(mma.x == -1 && mma.y == -1 && mma.z == -1), "accelerometer"); - return accel; -} - -void init_force(HX711 &scale) { - scale.begin(LOAD_CELL_DOUT, LOAD_CELL_CLK); - - // Calibrate load cell - scale.set_scale(LOAD_CELL_CALIBRATION_FACTOR); // This value is obtained by using the SparkFun_HX711_Calibration sketch - scale.tare(); // Load Cell, Assuming there is no weight on the scale, reset to 0 - - // Try reading a value from the load cell - int error = 0; - read_force(scale, error); - - if (!error) { - Serial.println(F("Load cell amp connected")); - } - delay(100); -} - -float read_force(HX711 &scale, int &error) { - // Wait for load cell data to become ready - bool is_ready = false; - for (unsigned i = 0; i < LOAD_CELL_MAX_RETRIES; i++) { - if (scale.is_ready()) { - is_ready = true; - break; - } - delay(LOAD_CELL_RETRY_INTERVAL); - } - - // Read a value from the load cell - float result = 0; - if (is_ready) { - result = scale.get_units(); - } - error_check(error, is_ready && !isnan(result) && result > FORCE_MIN_VALID && result < FORCE_MAX_VALID, "Force"); - return result; -} - -void init_thermocouple(Adafruit_MAX31855 &thermocouple, const String &sensor_name, const String &sensor_short_name) { - int error = 0; - thermocouple.begin(); - read_thermocouple(thermocouple, error, sensor_name, sensor_short_name); - if (!error) { - Serial.print(sensor_name); - Serial.println(F(" theromocouple connected")); - } - delay(100); -} - -float read_thermocouple(Adafruit_MAX31855 &thermocouple, int &error, const String &sensor_name, const String &sensor_short_name) { - float result = thermocouple.readCelsius(); - error_check(error, !isnan(result) && result > 0, "thermocouple", sensor_name, sensor_short_name); - return result; -} + +#define SENSOR_ERROR_LIMIT 5 // Max number of errors in a row before deciding a sensor is faulty + +#define PRESSURE_CALIBRATION_FACTOR 246.58 +#define PRESSURE_OFFSET 118.33 +#define PRESSURE_MIN_VALID -100 +#define PRESSURE_MAX_VALID 1000 + +#define TEMP_MIN_VALID -10 +#define TEMP_MAX_VALID 120 + +#define FORCE_MIN_VALID -50 +#define FORCE_MAX_VALID 500 + +#if CONFIGURATION == MK_2 +#define LOAD_CELL_CALIBRATION_FACTOR 20400.0 //This value is obtained using the SparkFun_HX711_Calibration sketch +#else +#define LOAD_CELL_CALIBRATION_FACTOR 20400 +#endif + +#define LOAD_CELL_RETRY_INTERVAL 10 +#define LOAD_CELL_MAX_RETRIES 20 + + + +String sensor_errors = ""; + +//Number of Sensors +//Load Cells - 4 +//Pressure Transducers - 4 +//Thermocouples - n/a (not a priority) +//Accelerometer - probably 1 so no need to work on that too much. + +//------------------------------------------------------------------------------------------- +//Utility Functions +//------------------------------------------------------------------------------------------- + +float mean(const float *data, unsigned int size) { + float result = 0; + for (int i = 0; i < size; i++) + result += data[i]; + return result / size; +} + +void update_sensor_errors() { + set_lcd_errors(sensor_errors); + sensor_errors = ""; +} + +void error_check(int &error, bool working, const String &sensor_type, const String &sensor_name="", const String &sensor_short_name="") { + if (working) { + error = 0; + } else { + if (sensor_errors.length()) { + sensor_errors += ','; + } + sensor_errors += sensor_type.substring(0, min(sensor_type.length(), 2)) + sensor_short_name; + if (!error) { + Serial.print(sensor_name); + if (sensor_name.length()) { + Serial.print(' '); + } + Serial.print(sensor_type); + Serial.println(F(" sensor error")); + } + error++; + if (error > SENSOR_ERROR_LIMIT) { + sensor_status = false; //static_test_driver + } + + + } +} + + +//------------------------------------------------------------------------------------------- +//LoadCell +//------------------------------------------------------------------------------------------- + +//SENSOR DEVICE 1 + +class LoadCell +{ + private: + HX711 m_scale; + + public: + uint8_t m_dout; //Digital out pin + uint8_t m_clk; //Clock pin + double m_calibrationFactor; + + int m_error; + + LoadCell(){} + LoadCell(uint8_t dout, uint8_t clk) : m_calibrationFactor{LOAD_CELL_CALIBRATION_FACTOR} , m_dout {dout} , m_clk {clk}, m_error{0} {} + + float read_force(); + void init_force(); +}; + +void LoadCell::init_force() { + m_scale.begin(m_dout, m_clk); + + // Calibrate load cell + m_scale.set_scale(m_calibrationFactor); // This value is obtained by using the SparkFun_HX711_Calibration sketch + //Calibration is just the slope of the data function we get from the cell, we use it to find force at the values we get. + m_scale.tare(); // Load Cell, Assuming there is no weight on the scale, reset to 0 mark intial valeue of cell as 0 + + // Try reading a value from the load cell + read_force(); + + if (!m_error) { + Serial.println(F("Load cell amp connected")); + } + delay(100); +} + +float LoadCell::read_force() { + // Wait for load cell data to become ready + bool is_ready = false; + for (unsigned int i = 0; i < LOAD_CELL_MAX_RETRIES; i++) { + if (m_scale.is_ready()) { + is_ready = true; + break; + } + delay(LOAD_CELL_RETRY_INTERVAL); + } + + // Read a value from the load cell + float result = 0; + if (is_ready) { + result = m_scale.get_units(); + } + error_check(m_error, is_ready && !isnan(result) && result > FORCE_MIN_VALID && result < FORCE_MAX_VALID, "Force"); + return result; +} + + +//------------------------------------------------------------------------------------------- +//Thermocouple +//------------------------------------------------------------------------------------------- + +//SENSOR DEVICE 2 + + +class Thermocouple +{ + private: + Adafruit_MAX31855 m_thermocouple; + public: + int m_thermocouplepin; + int m_error; + const String m_sensor_name; + const String m_sensor_short_name; + + Thermocouple(int8_t pin, const String& name, const String& shortname) : m_thermocouplepin {pin}, m_sensor_name { name } , m_sensor_short_name { shortname }, m_error{0} , m_thermocouple{pin} {} + + void init_thermocouple(); + float read_thermocouple(); + float read_temp(); + +}; + +float Thermocouple::read_temp() { + float result = analogRead(m_thermocouplepin) * 5.0 * 100 / 1024; + error_check(m_error, result > TEMP_MIN_VALID && result < TEMP_MAX_VALID, "temp", m_sensor_name, m_sensor_short_name); + return result; +} + +void Thermocouple::init_thermocouple() { + int error = 0; + m_thermocouple.begin(); + read_thermocouple(); + if (!m_error) { + Serial.print(m_sensor_name); + Serial.println(F(" theromocouple connected")); + } + delay(100); +} + +float Thermocouple::read_thermocouple() { + float result = m_thermocouple.readCelsius(); + error_check(m_error, !isnan(result) && result > 0, "thermocouple", m_sensor_name, m_sensor_short_name); + return result; +} + + + +//------------------------------------------------------------------------------------------- +//Pressure Transducers +//------------------------------------------------------------------------------------------- + +//Sensor Device 3 + +class PressureTransducer +{ + public: + int m_pressurepin; + int m_error; + const String m_sensor_name; + const String m_sensor_short_name; + PressureTransducer(int pin, const String& name, const String& shortname) : m_pressurepin{pin}, m_sensor_name{name}, m_sensor_short_name{shortname} , m_error{0} {} + + float read_pressure(int sensor); + +}; + +float PressureTransducer::read_pressure(int sensor) { + float result = (analogRead(sensor) * 5 / 1024.0) * PRESSURE_CALIBRATION_FACTOR - PRESSURE_OFFSET; + error_check(m_error, result > PRESSURE_MIN_VALID && result < PRESSURE_MAX_VALID, m_sensor_name, "pressure"); + return result; +}; + +//------------------------------------------------------------------------------------------- +//Accelerometer +//------------------------------------------------------------------------------------------- + +void init_accelerometer(Adafruit_MMA8451 &mma) { + bool working = false; + if (mma.begin()) { + mma.setRange(MMA8451_RANGE_2_G); // set acc range (2 4 8) + Serial.print(F("Accelerometer range ")); + Serial.print(2 << mma.getRange()); + Serial.println("G"); + working = true; + } + int error = 0; + error_check(error, working, "accelerometer"); + delay(100); +} + +sensors_vec_t read_accelerometer(Adafruit_MMA8451 &mma, int &error) { + sensors_event_t event; + mma.getEvent(&event); + sensors_vec_t accel = event.acceleration; + error_check(error, !(mma.x == -1 && mma.y == -1 && mma.z == -1), "accelerometer"); + return accel; +} diff --git a/static_test_driver/valves.ino b/static_test_driver/valves.ino index cbc5d33..07a4b1a 100644 --- a/static_test_driver/valves.ino +++ b/static_test_driver/valves.ino @@ -1,21 +1,26 @@ +class Valve +{ +public: + uint8_t m_valvepin; + String m_valvename; + String m_telemetry_id; -const uint8_t valve_pins[] = {34, 33, 32, 31}; + Valve(uint8_t pin, String& name; String& telemetry) : m_valvepin{pin}, m_valvename{name}, m_telemetry_id{telemetry}{} -const char *valve_names[] = {"Fuel prestage", "Fuel mainstage", "Oxygen prestage", "Oxygen mainstage"}; -const char *valve_telemetry_ids[] = {"fuel_pre_setting", "fuel_main_setting", "ox_pre_setting", "ox_main_setting"}; + void init_valve; + void set_valve; +}; -void init_engine() { - for (uint8_t i = 0; i < sizeof(valve_pins); i++) { - pinMode(valve_pins[i], OUTPUT); - } - pinMode(IGNITER_PIN, OUTPUT); +// valve initializer function +void Valve::init_valve(uint8_t pin) { + pinMode(pin, OUTPUT); } -void set_valve(int valve, bool setting) { - Serial.print(valve_names[valve]); +// valve setting function +void Valve::set_valve(bool setting) { + Serial.print(m_valvename); Serial.print(F(" to ")); Serial.println(setting? F("open") : F("closed")); - SEND_NAME(valve_telemetry_ids[valve], setting); - valve_status[valve] = setting; - digitalWrite(valve_pins[valve], setting); + SEND_NAME(m_telemetry_id, setting); + digitalWrite(m_valvepin, setting); }