diff --git a/sbs.conf b/sbs.conf index d9de8cc62ce658c79e188ede53902876566de4f7..c9b528c935d9cd0bd1caa1bc46751c213a61d5c6 100644 --- a/sbs.conf +++ b/sbs.conf @@ -154,7 +154,6 @@ Files: src/tests/catch/ada/test-ada-data.cpp [hermes-tests] Type: srcfiles Files: src/tests/catch/fsm/test-ada.cpp - src/tests/catch/fsm/test-deployment.cpp [ram-test] Type: srcfiles @@ -270,7 +269,7 @@ Main: drivers/test-motor Type: test BoardId: stm32f429zi_skyward_death_stack BinName: test-servo -Include: %shared +Include: %shared %servo %pwm Defines: Main: drivers/test-servo @@ -346,8 +345,8 @@ Main: test-sensormanager Type: test BoardId: stm32f429zi_skyward_death_stack BinName: test-dpl -Include: %deployment %shared %pwm %logger %logger-hermes %logservice %evt-functions %servo -Defines: -DDEBUG +Include: %shared %deathstack %logger %pwm %xbee %piksi %servo %test-utils +Defines: -DDEBUG -DTRACE_EVENTS Main: test-dpl [test-fmm] diff --git a/scripts/event_header_generator/EventFunctions.cpp.template b/scripts/event_header_generator/EventStrings.cpp.template similarity index 100% rename from scripts/event_header_generator/EventFunctions.cpp.template rename to scripts/event_header_generator/EventStrings.cpp.template diff --git a/scripts/event_header_generator/Events.h.template b/scripts/event_header_generator/Events.h.template index fc2119939a1b9b96321b1730ecd5f4b92ef4cc4f..456d25118ec7bae544e4f460c5905c0cf601607a 100644 --- a/scripts/event_header_generator/Events.h.template +++ b/scripts/event_header_generator/Events.h.template @@ -29,8 +29,7 @@ // Generated from: {sheet_link} // Autogen date: {date} -#ifndef SRC_SHARED_BOARDS_HOMEONE_EVENTS_H -#define SRC_SHARED_BOARDS_HOMEONE_EVENTS_H +#pragma once #include <cstdint> #include <string> @@ -38,7 +37,7 @@ #include "events/Event.h" #include "events/EventBroker.h" -#include "EventClasses.h" +#include "EventStrings.h" #include "Topics.h" using std::string; @@ -65,5 +64,3 @@ const std::vector<uint8_t> EVENT_LIST {{{event_list}}}; string getEventString(uint8_t event); }} - -#endif /* SRC_SHARED_BOARDS_HOMEONE_EVENTS_H */ diff --git a/scripts/event_header_generator/Topics.h.template b/scripts/event_header_generator/Topics.h.template index 697a99760719deedc35ac3d8d6fa58c9407405b8..87986edbad2dfd6f72a2377389d43da214e85816 100644 --- a/scripts/event_header_generator/Topics.h.template +++ b/scripts/event_header_generator/Topics.h.template @@ -29,8 +29,7 @@ // Generated from: {sheet_link} // Autogen date: {date} -#ifndef SRC_SHARED_BOARDS_HOMEONE_TOPICS_H -#define SRC_SHARED_BOARDS_HOMEONE_TOPICS_H +#pragma once #include <stdint.h> #include <string> @@ -60,4 +59,3 @@ string getTopicString(uint8_t topic); }} // namespace DeathStackBoard -#endif /* SRC_SHARED_BOARDS_HOMEONE_TOPICS_H_ */ diff --git a/scripts/event_header_generator/event_generator.py b/scripts/event_header_generator/event_generator.py index 29f350aae72566b225434a5acf88f7f74370b71e..048a2ba7f8fe2725e46533b6877e974bf75e8cfc 100644 --- a/scripts/event_header_generator/event_generator.py +++ b/scripts/event_header_generator/event_generator.py @@ -39,10 +39,10 @@ service = None # Spreadsheet file used to generate the events. The can be found in the link # to the spreadsheet, for example: -# https://docs.google.com/spreadsheets/d/1msICDqJtSseSP_JAoAPoKIzpKlI6bI2n8lwws1X2hz4/ +# https://docs.google.com/spreadsheets/d/184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0/ # --> -# 1msICDqJtSseSP_JAoAPoKIzpKlI6bI2n8lwws1X2hz4 -SPREADSHEET_ID = '1msICDqJtSseSP_JAoAPoKIzpKlI6bI2n8lwws1X2hz4' +# 184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0 +SPREADSHEET_ID = '184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0' EVENTS_RANGE_NAME = 'EventList!A2:A' TOPICS_RANGE_NAME = 'Topics!B3:B' @@ -108,7 +108,7 @@ def has_duplicates(lst): -print("Homeone on-board software event header generator v0.2") +print("Skyward on-board software event header generator v0.2") print("Google sheets API auth in progress...") if auth(): @@ -120,7 +120,7 @@ else: if not os.path.exists(OUTPUT_FOLDER): os.mkdir(OUTPUT_FOLDER) -print("Reading from: https://docs.google.com/spreadsheets/d/12TecOmDd7Uot-MvXkCbhDJRU48-XO6s5ChKDlr4AOvI") +print("Reading from: https://docs.google.com/spreadsheets/d/" + SPREADSHEET_ID) events = load_events() topics = load_topics() @@ -193,17 +193,17 @@ template = template.format(sheet_link=link, date=date, with open(join(OUTPUT_FOLDER, 'Topics.h'), 'w') as header_file: header_file.write(template) -with open('EventFunctions.cpp.template', 'r') as cpp_template_file: +with open('EventStrings.cpp.template', 'r') as cpp_template_file: cpp = cpp_template_file.read() cpp = cpp.format(sheet_link=link, date=date, event_map_data=event_map_str, topic_map_data=topic_map_str) -with open(join(OUTPUT_FOLDER, 'EventFunctions.cpp'), 'w') as cpp_file: +with open(join(OUTPUT_FOLDER, 'EventStrings.cpp'), 'w') as cpp_file: cpp_file.write(cpp) print("Topics.h successfully generated.") print() -print("All files successfully generated. Please move Events.h, Topics.h, EventFunction.cpp into your project sources.") +print("All files successfully generated. Please move Events.h, Topics.h, EventStrings.cpp into your project sources.") print(".... Done.") diff --git a/skyward-boardcore b/skyward-boardcore index b19d6c451f27b10a9459515dcf93fa8da4ef345e..16e09b5ff9c47fcaf95cab1910b5a456582a08f2 160000 --- a/skyward-boardcore +++ b/skyward-boardcore @@ -1 +1 @@ -Subproject commit b19d6c451f27b10a9459515dcf93fa8da4ef345e +Subproject commit 16e09b5ff9c47fcaf95cab1910b5a456582a08f2 diff --git a/src/boards/DeathStack/DeathStack.h b/src/boards/DeathStack/DeathStack.h index 0d5ee68d071cd2ae984a8f4e1a1722831a448337..7489412d05bdf8f99f5e646e29d6cc1cd9c19e17 100644 --- a/src/boards/DeathStack/DeathStack.h +++ b/src/boards/DeathStack/DeathStack.h @@ -31,8 +31,8 @@ #include <events/EventBroker.h> #include <utils/EventSniffer.h> -#include "DeathStack/events/Events.h" #include "DeathStack/LoggerService/TmRepository.h" +#include "DeathStack/events/Events.h" #include "DeathStack/events/Topics.h" #include "DeathStackStatus.h" @@ -43,8 +43,8 @@ #include "DeathStack/FlightModeManager/FlightModeManager.h" #include "DeathStack/PinHandler/PinHandler.h" #include "DeathStack/SensorManager/SensorManager.h" -#include "DeathStack/events/EventData.h" #include "DeathStack/TMTCManager/TMTCManager.h" +#include "DeathStack/events/EventData.h" using std::bind; @@ -74,6 +74,9 @@ public: SensorManager* sensor_manager; TMTCManager* tmtc; FlightModeManager* fmm; + + Cutter* cutter; + Servo* servo; DeploymentController* dpl; private: @@ -101,7 +104,10 @@ private: sensor_manager = new SensorManager(ada); tmtc = new TMTCManager(); fmm = new FlightModeManager(); - dpl = new DeploymentController(); + cutter = new Cutter(CUTTER_PWM_FREQUENCY, CUTTER_PWM_DUTY_CYCLE, + CUTTER_TEST_PWM_DUTY_CYCLE); + servo = new Servo(DeploymentConfigs::SERVO_TIMER); + dpl = new DeploymentController(*cutter, *servo); // Start threads try diff --git a/src/boards/DeathStack/DeploymentController/DeploymentController.cpp b/src/boards/DeathStack/DeploymentController/DeploymentController.cpp index 8afda6e4f6ea95aae7d97c49da117d73bb22b69d..274e4d6dac0dcc2d06ce3bd5ae6deb19f9ea2cf0 100644 --- a/src/boards/DeathStack/DeploymentController/DeploymentController.cpp +++ b/src/boards/DeathStack/DeploymentController/DeploymentController.cpp @@ -23,8 +23,8 @@ #include <stdexcept> -#include "DeathStack/events/Events.h" #include "DeathStack/configs/DeploymentConfig.h" +#include "DeathStack/events/Events.h" #include "DeploymentController.h" #include "Motor/MotorDriver.h" @@ -33,13 +33,13 @@ namespace DeathStackBoard { -DeploymentController::DeploymentController() - : HSM(&DeploymentController::state_initialization, 4096, 2), motor(), - servo_rk(TIM4_DATA), servo_l(TIM8_DATA) -{ - // No conflicts on TIM4, enable PWM immediately - configureTIM4Servos(); +using namespace DeploymentConfigs; +DeploymentController::DeploymentController(Cutter& cutter, + Servo& ejection_servo) + : HSM(&DeploymentController::state_initialization, 4096, 2), + cutters(cutter), ejection_servo(ejection_servo) +{ memset(&status, 0, sizeof(DeploymentStatus)); sEventBroker->subscribe(this, TOPIC_DEPLOYMENT); @@ -67,6 +67,8 @@ State DeploymentController::state_idle(const Event& ev) { case EV_ENTRY: { + initServo(); + logStatus(DeploymentCTRLState::DPL_IDLE); // Process deferred events try @@ -96,30 +98,23 @@ State DeploymentController::state_idle(const Event& ev) } case EV_NC_OPEN: { - retState = transition(&DeploymentController::state_openingNosecone); - break; - } - case EV_CUT_MAIN: - { - retState = transition(&DeploymentController::state_cuttingMain); + retState = + transition(&DeploymentController::state_ejectingNosecone); break; } case EV_CUT_DROGUE: { - retState = transition(&DeploymentController::state_cuttingDrogue); + retState = transition(&DeploymentController::state_cuttingPrimary); break; } - case EV_DPL_ALTITUDE: + case EV_TEST_CUTTER_PRIMARY: { - // TIM8 Pins are conflicting with the motor driver pins, don't - // configure them until necessary - configureTIM8Servos(); + retState = transition(&DeploymentController::state_testingPrimary); break; } - case EV_START_ROGALLO_CONTROL: + case EV_TEST_CUTTER_BACKUP: { - TRACE("Controlling rogallo\n"); - controlRogallo(); + retState = transition(&DeploymentController::state_testingBackup); break; } default: @@ -131,56 +126,42 @@ State DeploymentController::state_idle(const Event& ev) return retState; } -State DeploymentController::state_openingNosecone(const Event& ev) +State DeploymentController::state_ejectingNosecone(const Event& ev) { State retState = HANDLED; switch (ev.sig) { case EV_ENTRY: { - // Start the motor to open the nosecone - motor.start(MOTOR_OPEN_DIR); - logStatus(DeploymentCTRLState::OPENING_NC); - - ev_open_timeout_id = sEventBroker->postDelayed<NC_OPEN_TIMEOUT>( - Event{EV_TIMEOUT_MOT_OPEN}, TOPIC_DEPLOYMENT); + logStatus(DeploymentCTRLState::EJECTING_NC); - TRACE("[DPL_CTRL] state_openingNosecone ENTRY\n"); + TRACE("[DPL_CTRL] state_ejectingNosecone ENTRY\n"); break; } case EV_INIT: { - TRACE("[DPL_CTRL] state_openingNosecone INIT\n"); + TRACE("[DPL_CTRL] state_ejectingNosecone INIT\n"); - retState = transition(&DeploymentController::state_spinning); + retState = transition(&DeploymentController::state_movingServo); break; } case EV_EXIT: { - // Stop the motor - motor.stop(); - - sEventBroker->removeDelayed(ev_min_open_time_id); - sEventBroker->removeDelayed(ev_open_timeout_id); + disableServo(); TRACE("[DPL_CTRL] state_openingNosecone EXIT\n"); break; } - case EV_TIMEOUT_MOT_OPEN: - { - retState = transition(&DeploymentController::state_idle); - break; - } case EV_CUT_DROGUE: { deferred_events.put(ev); break; } - case EV_CUT_MAIN: + case EV_NC_DETACHED: { - deferred_events.put(ev); + retState = transition(&DeploymentController::state_idle); break; } default: @@ -192,19 +173,20 @@ State DeploymentController::state_openingNosecone(const Event& ev) return retState; } -State DeploymentController::state_spinning(const Event& ev) +State DeploymentController::state_movingServo(const Event& ev) { State retState = HANDLED; switch (ev.sig) { case EV_ENTRY: { - ev_min_open_time_id = - sEventBroker->postDelayed<NC_MINIMUM_OPENING_TIME>( - Event{EV_MOT_MIN_OPEN_TIME}, TOPIC_DEPLOYMENT); + ejectNosecone(); - TRACE("[DPL_CTRL] state_spinning ENTRY\n"); - logStatus(DeploymentCTRLState::SPINNING); + ev_open_timeout_id = sEventBroker->postDelayed<NC_OPEN_TIMEOUT>( + Event{EV_TIMEOUT_NC_OPEN}, TOPIC_DEPLOYMENT); + + TRACE("[DPL_CTRL] state_movingServo ENTRY\n"); + logStatus(DeploymentCTRLState::MOVING_SERVO); break; } case EV_INIT: @@ -213,40 +195,101 @@ State DeploymentController::state_spinning(const Event& ev) } case EV_EXIT: { - TRACE("[DPL_CTRL] state_spinning EXIT\n"); + sEventBroker->removeDelayed(ev_open_timeout_id); + + TRACE("[DPL_CTRL] state_movingServo EXIT\n"); break; } - case EV_NC_DETACHED: + case EV_TIMEOUT_NC_OPEN: { - retState = - transition(&DeploymentController::state_awaitingOpenTime); + // Increment retry counter + ++ejection_retry_count; + + if (ejection_retry_count == MAX_EJECTION_ATTEMPTS) + { + // We've tried enough, the nosecone cannot be ejected, RIP + retState = transition(&DeploymentController::state_idle); + } + else + { + // Reset the servo and try again + retState = + transition(&DeploymentController::state_resettingServo); + } + break; } - case EV_MOT_MIN_OPEN_TIME: + default: { retState = - transition(&DeploymentController::state_awaitingDetachment); + tran_super(&DeploymentController::state_ejectingNosecone); + break; + } + } + return retState; +} + +State DeploymentController::state_resettingServo(const Event& ev) +{ + State retState = HANDLED; + switch (ev.sig) + { + case EV_ENTRY: + { + resetServo(); + + ev_reset_timeout_id = + sEventBroker->postDelayed<SERVO_RESET_TIMEOUT>( + Event{EV_TIMEOUT_SERVO_RESET}, TOPIC_DEPLOYMENT); + + TRACE("[DPL_CTRL] state_resettingServo ENTRY\n"); + logStatus(DeploymentCTRLState::RESETTING_SERVO); + break; + } + case EV_INIT: + { + break; + } + case EV_EXIT: + { + sEventBroker->removeDelayed(ev_reset_timeout_id); + + TRACE("[DPL_CTRL] state_resettingServo EXIT\n"); + break; + } + case EV_TIMEOUT_SERVO_RESET: + { + retState = transition(&DeploymentController::state_movingServo); break; } default: { - retState = tran_super(&DeploymentController::state_openingNosecone); + retState = + tran_super(&DeploymentController::state_ejectingNosecone); break; } } return retState; } -State DeploymentController::state_awaitingOpenTime(const Event& ev) +State DeploymentController::state_cuttingPrimary(const Event& ev) { State retState = HANDLED; switch (ev.sig) { case EV_ENTRY: { - TRACE("[DPL_CTRL] state_awaitingOpenTime ENTRY\n"); - logStatus(DeploymentCTRLState::AWAITING_MINOPENTIME); + // Cutting drogue + cutters.enablePrimaryCutter(); + + logStatus(DeploymentCTRLState::CUTTING_PRIMARY); + + ev_cut_timeout_id = + sEventBroker->postDelayed<CUT_DURATION>( + {EV_TIMEOUT_CUTTING}, TOPIC_DEPLOYMENT); + + TRACE("[DPL_CTRL] state_cuttingPrimary ENTRY\n"); break; } case EV_INIT: @@ -255,33 +298,44 @@ State DeploymentController::state_awaitingOpenTime(const Event& ev) } case EV_EXIT: { - TRACE("[DPL_CTRL] state_awaitingOpenTime EXIT\n"); + cutters.disablePrimaryCutter(); + + sEventBroker->removeDelayed(ev_cut_timeout_id); + TRACE("[DPL_CTRL] state_cuttingPrimary EXIT\n"); break; } - case EV_MOT_MIN_OPEN_TIME: + case EV_TIMEOUT_CUTTING: { - retState = transition(&DeploymentController::state_idle); + retState = transition(&DeploymentController::state_cuttingBackup); break; } default: { - retState = tran_super(&DeploymentController::state_openingNosecone); + retState = tran_super(&DeploymentController::Hsm_top); break; } } return retState; } -State DeploymentController::state_awaitingDetachment(const Event& ev) +State DeploymentController::state_cuttingBackup(const Event& ev) { State retState = HANDLED; switch (ev.sig) { case EV_ENTRY: { - TRACE("[DPL_CTRL] state_awaitingDetachment ENTRY\n"); - logStatus(DeploymentCTRLState::AWAITING_DETACHMENT); + // Cutting rogallina + cutters.enableBackupCutter(); + + logStatus(DeploymentCTRLState::CUTTING_BACKUP); + + ev_cut_timeout_id = + sEventBroker->postDelayed<CUT_DURATION>( + {EV_TIMEOUT_CUTTING}, TOPIC_DEPLOYMENT); + + TRACE("[DPL_CTRL] state_cuttingBackup ENTRY\n"); break; } case EV_INIT: @@ -290,40 +344,45 @@ State DeploymentController::state_awaitingDetachment(const Event& ev) } case EV_EXIT: { - TRACE("[DPL_CTRL] state_awaitingOpenTime EXIT\n"); + cutters.disableBackupCutter(); + + sEventBroker->removeDelayed(ev_cut_timeout_id); + + TRACE("[DPL_CTRL] state_cuttingBackup EXIT\n"); break; } - case EV_NC_DETACHED: + case EV_TIMEOUT_CUTTING: { retState = transition(&DeploymentController::state_idle); break; } default: { - retState = tran_super(&DeploymentController::state_openingNosecone); + retState = tran_super(&DeploymentController::Hsm_top); break; } } return retState; } -State DeploymentController::state_cuttingDrogue(const Event& ev) +State DeploymentController::state_testingPrimary(const Event& ev) { State retState = HANDLED; switch (ev.sig) { case EV_ENTRY: { - // Cutting drogue - cutter.startCutDrogue(); - logStatus(DeploymentCTRLState::CUTTING_DROGUE); + // Cutting rogallina + cutters.enableTestPrimaryCutter(); + + logStatus(DeploymentCTRLState::TESTING_PRIMARY); ev_cut_timeout_id = - sEventBroker->postDelayed<MAXIMUM_CUTTING_DURATION>( + sEventBroker->postDelayed<CUT_DURATION>( {EV_TIMEOUT_CUTTING}, TOPIC_DEPLOYMENT); - TRACE("[DPL_CTRL] state_cuttingDrogue ENTRY\n"); + TRACE("[DPL_CTRL] state_testingPrimary ENTRY\n"); break; } case EV_INIT: @@ -332,10 +391,11 @@ State DeploymentController::state_cuttingDrogue(const Event& ev) } case EV_EXIT: { - cutter.stopCutDrogue(); + cutters.disablePrimaryCutter(); sEventBroker->removeDelayed(ev_cut_timeout_id); - TRACE("[DPL_CTRL] state_cuttingDrogue EXIT\n"); + + TRACE("[DPL_CTRL] state_testingPrimary EXIT\n"); break; } @@ -344,11 +404,6 @@ State DeploymentController::state_cuttingDrogue(const Event& ev) retState = transition(&DeploymentController::state_idle); break; } - case EV_CUT_MAIN: - { - deferred_events.put(ev); - break; - } default: { retState = tran_super(&DeploymentController::Hsm_top); @@ -358,7 +413,7 @@ State DeploymentController::state_cuttingDrogue(const Event& ev) return retState; } -State DeploymentController::state_cuttingMain(const Event& ev) +State DeploymentController::state_testingBackup(const Event& ev) { State retState = HANDLED; switch (ev.sig) @@ -366,14 +421,15 @@ State DeploymentController::state_cuttingMain(const Event& ev) case EV_ENTRY: { // Cutting rogallina - cutter.startCutMainChute(); - logStatus(DeploymentCTRLState::CUTTING_MAIN); + cutters.enableTestBackupCutter(); + + logStatus(DeploymentCTRLState::TESTING_BACKUP); ev_cut_timeout_id = - sEventBroker->postDelayed<MAXIMUM_CUTTING_DURATION>( + sEventBroker->postDelayed<CUT_DURATION>( {EV_TIMEOUT_CUTTING}, TOPIC_DEPLOYMENT); - TRACE("[DPL_CTRL] state_cuttingMain ENTRY\n"); + TRACE("[DPL_CTRL] state_testingBackup ENTRY\n"); break; } case EV_INIT: @@ -382,19 +438,14 @@ State DeploymentController::state_cuttingMain(const Event& ev) } case EV_EXIT: { - cutter.stopCutMainChute(); + cutters.disableBackupCutter(); sEventBroker->removeDelayed(ev_cut_timeout_id); - TRACE("[DPL_CTRL] state_cuttingMain EXIT\n"); + TRACE("[DPL_CTRL] state_testingBackup EXIT\n"); break; } - case EV_CUT_DROGUE: - { - deferred_events.put(ev); - break; - } case EV_TIMEOUT_CUTTING: { retState = transition(&DeploymentController::state_idle); @@ -409,68 +460,31 @@ State DeploymentController::state_cuttingMain(const Event& ev) return retState; } -void DeploymentController::configureTIM4Servos() +void DeploymentController::initServo() { - { - miosix::FastInterruptDisableLock dLock; - miosix::nosecone::rogP1::mode(miosix::Mode::ALTERNATE); - miosix::nosecone::rogP2::mode(miosix::Mode::ALTERNATE); + ejection_servo.enable(SERVO_CHANNEL); - miosix::nosecone::rogP1::alternateFunction(2); - miosix::nosecone::rogP2::alternateFunction(2); - } - servo_rk.enable(SERVO_RIGHT_CH); - servo_rk.enable(SERVO_KEEL_CH); + ejection_servo.setPosition(SERVO_CHANNEL, SERVO_RESET_POS); - servo_rk.setPosition(SERVO_RIGHT_CH, SERVO_R_RESET_POS); - servo_rk.setPosition(SERVO_KEEL_CH, SERVO_K_RESET_POS); - - servo_rk.start(); + ejection_servo.start(); } -// The pins connected to TIM8 are shared with the nosecone driver. Don't -// enable the timer until we have to drive the servos -void DeploymentController::configureTIM8Servos() +void DeploymentController::resetServo() { - { - miosix::FastInterruptDisableLock dLock; - miosix::nosecone::motP1::mode(miosix::Mode::ALTERNATE); - miosix::nosecone::motP1::alternateFunction(3); - } - servo_l.enable(SERVO_LEFT_CH); - servo_l.setPosition(SERVO_LEFT_CH, SERVO_L_RESET_POS); + ejection_servo.setPosition(SERVO_CHANNEL, SERVO_RESET_POS); +} - servo_l.start(); +void DeploymentController::ejectNosecone() +{ + ejection_servo.setPosition(SERVO_CHANNEL, SERVO_EJECT_POS); } -void DeploymentController::controlRogallo() +void DeploymentController::disableServo() { - // Ensure TIM8 is correctly configured - configureTIM8Servos(); - - // Wait for TIM8 servo to go to position - Thread::sleep(2000); - - // Drive the left servo - servo_l.setPosition(SERVO_LEFT_CH, SERVO_L_CONTROL_POS); - // Wait then reset position - Thread::sleep(4000); - servo_l.setPosition(SERVO_LEFT_CH, SERVO_L_RESET_POS); - Thread::sleep(4000); - - // Drive the keel servo - servo_rk.setPosition(SERVO_KEEL_CH, SERVO_K_CONTROL_POS); - // Wait then reset position - Thread::sleep(4000); - servo_rk.setPosition(SERVO_KEEL_CH, SERVO_K_RESET_POS); - Thread::sleep(4000); - - // Drive the keel servo - servo_rk.setPosition(SERVO_RIGHT_CH, SERVO_R_CONTROL_POS); - // Wait then reset position - Thread::sleep(4000); - servo_rk.setPosition(SERVO_RIGHT_CH, SERVO_R_RESET_POS); - Thread::sleep(4000); + // Do not reset the position to 0 + + ejection_servo.stop(); + ejection_servo.disable(SERVO_CHANNEL); } } // namespace DeathStackBoard diff --git a/src/boards/DeathStack/DeploymentController/DeploymentController.h b/src/boards/DeathStack/DeploymentController/DeploymentController.h index 7d7d3515ab6aa6611ad8e55de6cc52699a695bc2..6afab21de6ab0361c5afd0f05377eea7fb5bd37d 100644 --- a/src/boards/DeathStack/DeploymentController/DeploymentController.h +++ b/src/boards/DeathStack/DeploymentController/DeploymentController.h @@ -38,25 +38,28 @@ class PinObserver; namespace DeathStackBoard { +/** + * @brief Deployment Controller State Machine + */ class DeploymentController : public HSM<DeploymentController> { public: - DeploymentController(); + DeploymentController(Cutter &cutter, Servo &ejection_servo); ~DeploymentController(); State state_initialization(const Event &ev); State state_idle(const Event &ev); - State state_cuttingDrogue(const Event &ev); - State state_cuttingMain(const Event &ev); + State state_cuttingPrimary(const Event &ev); + State state_cuttingBackup(const Event &ev); - State state_openingNosecone(const Event &ev); - State state_spinning(const Event &ev); - State state_awaitingDetachment(const Event &ev); - State state_awaitingOpenTime(const Event &ev); + State state_testingPrimary(const Event &ev); + State state_testingBackup(const Event &ev); - State state_controlRogallo(const Event &ev); + State state_ejectingNosecone(const Event &ev); + State state_movingServo(const Event &ev); + State state_resettingServo(const Event &ev); private: /** @@ -76,17 +79,18 @@ private: void logStatus() { status.timestamp = miosix::getTick(); - status.cutter_status = cutter.getStatus(); - status.motor_status = motor.getStatus(); + status.cutter_status = cutters.getStatus(); + status.servo_position = + ejection_servo.getPosition(DeploymentConfigs::SERVO_CHANNEL); logger.log(status); StackLogger::getInstance()->updateStack(THID_DPL_FSM); } - void configureTIM4Servos(); - void configureTIM8Servos(); - - void controlRogallo(); + void initServo(); + void resetServo(); + void ejectNosecone(); + void disableServo(); /** * Defer an event to be processed when the state machine goes back to @@ -96,20 +100,20 @@ private: */ void deferEvent(const Event &ev); - Cutter cutter{}; + Cutter &cutters; + Servo &ejection_servo; + DeploymentStatus status; - MotorDriver motor; LoggerService &logger = *(LoggerService::getInstance()); CircularBuffer<Event, DEFERRED_EVENTS_QUEUE_SIZE> deferred_events; - uint16_t ev_min_open_time_id = 0; + uint8_t ejection_retry_count = 0; + uint16_t ev_open_timeout_id = 0; + uint16_t ev_reset_timeout_id = 0; uint16_t ev_cut_timeout_id = 0; - - Servo servo_rk; - Servo servo_l; }; } // namespace DeathStackBoard \ No newline at end of file diff --git a/src/boards/DeathStack/DeploymentController/DeploymentData.h b/src/boards/DeathStack/DeploymentController/DeploymentData.h index 1d785889a9254f793595a57975f73b850a105307..8ed9e6c8d2a2e71f9857f19e65ffa9eb53277bd3 100644 --- a/src/boards/DeathStack/DeploymentController/DeploymentData.h +++ b/src/boards/DeathStack/DeploymentController/DeploymentData.h @@ -32,33 +32,31 @@ namespace DeathStackBoard enum DeploymentCTRLState : uint8_t { DPL_IDLE = 0, - CUTTING_DROGUE, - CUTTING_MAIN, - OPENING_NC, - SPINNING, - AWAITING_DETACHMENT, - AWAITING_MINOPENTIME + CUTTING_PRIMARY, + CUTTING_BACKUP, + EJECTING_NC, + MOVING_SERVO, + RESETTING_SERVO, + TESTING_PRIMARY, + TESTING_BACKUP }; struct DeploymentStatus { long long timestamp; DeploymentCTRLState state; - MotorStatus motor_status; CutterStatus cutter_status; + float servo_position; static std::string header() { - return "timestamp,state,motor_active,motor_last_direction,cutter_" - "state\n"; + return "timestamp,state,cutter_state,servo_position\n"; } void print(std::ostream& os) const { - os << timestamp << "," << (int)state << "," - << (int)motor_status.motor_active << "," - << (int)motor_status.motor_last_direction << "," - << (int)cutter_status.state << "\n"; + os << timestamp << "," << (int)state << "," << (int)cutter_status.state + << "," << servo_position << "\n"; } }; diff --git a/src/boards/DeathStack/DeploymentController/ThermalCutter/Cutter.h b/src/boards/DeathStack/DeploymentController/ThermalCutter/Cutter.h index 164aa1cfe489450582f74922fc618640741cfecc..43c2678b6fc27d81bad3719c0b11c8c8d4718b8b 100644 --- a/src/boards/DeathStack/DeploymentController/ThermalCutter/Cutter.h +++ b/src/boards/DeathStack/DeploymentController/ThermalCutter/Cutter.h @@ -35,82 +35,129 @@ using miosix::Thread; namespace DeathStackBoard { +/** + * @brief Interface class to operate the thermal cutters on the Hermev V1 + * rocket. + * + * Provides the ability to enable a cutter using the "nominal" duty cycle or + * using a "test" duty cycle (lower duty cycle that does not cut the parachute + * but is used to check if current is flowing) + */ class Cutter { public: - Cutter(unsigned int frequency = CUTTER_PWM_FREQUENCY, - float duty_cycle = DROGUE_CUTTER_PWM_DUTY_CYCLE) + /** + * @brief Create a new Cutter + * + * @param frequency Frequency of the PWM driving the cutters + * @param duty_cycle Duty cycle of the PWM driving the cutters + * @param test_duty_cycle Duty cycle to be used when testing the + * cutters for continuity + */ + Cutter(unsigned int frequency, float duty_cycle, float test_duty_cycle) : pwm(CUTTER_TIM, frequency), - pin_enable_drogue(DrogueCutterEna::getPin()), - pin_enable_main_chute(MainChuteCutterEna::getPin()), - duty_cycle(duty_cycle) + pin_enable_primary(PrimaryCutterEna::getPin()), + pin_enable_backup(BackupCutterEna::getPin()), + cut_duty_cycle(duty_cycle), test_duty_cycle(test_duty_cycle) { - pin_enable_drogue.low(); - pin_enable_main_chute.low(); + pin_enable_primary.low(); + pin_enable_backup.low(); // Start PWM with 0 duty cycle to keep IN pins low - pwm.enableChannel(CUTTER_CHANNEL_DROGUE, 0.0f); - pwm.enableChannel(CUTTER_CHANNEL_MAIN_CHUTE, 0.0f); + pwm.enableChannel(CUTTER_CHANNEL_PRIMARY, 0.0f); + pwm.enableChannel(CUTTER_CHANNEL_BACKUP, 0.0f); pwm.start(); - - TRACE("PWM Instantiated. Freq: %d, duty: %f\n", frequency, duty_cycle); } ~Cutter() { - stopCutDrogue(); - stopCutMainChute(); + disablePrimaryCutter(); + disableBackupCutter(); + pwm.stop(); } - void startCutDrogue() + /** + * @brief Activates the primary cutter. + */ + void enablePrimaryCutter() { - if (status.state == CutterState::IDLE) - { - enableCutter(CUTTER_CHANNEL_DROGUE, pin_enable_drogue); - status.state = CutterState::CUTTING_DROGUE; - } + enableCutter(CUTTER_CHANNEL_PRIMARY, pin_enable_primary, + cut_duty_cycle); + status.state = CutterState::CUTTING_PRIMARY; } - void stopCutDrogue() + /** + * @brief Deactivates the primary cutter + */ + void disablePrimaryCutter() { - if (status.state == CutterState::CUTTING_DROGUE) + if (status.state == CutterState::CUTTING_PRIMARY) { - disableCutter(CUTTER_CHANNEL_DROGUE, pin_enable_drogue); + disableCutter(CUTTER_CHANNEL_PRIMARY, pin_enable_primary); status.state = CutterState::IDLE; } } - void startCutMainChute() + /** + * @brief Activates the backup cutter. + */ + void enableBackupCutter() { - if (status.state == CutterState::IDLE) - { - enableCutter(CUTTER_CHANNEL_MAIN_CHUTE, pin_enable_main_chute); - status.state = CutterState::CUTTING_MAIN; - } + enableCutter(CUTTER_CHANNEL_BACKUP, pin_enable_backup, cut_duty_cycle); + status.state = CutterState::CUTTING_BACKUP; } - void stopCutMainChute() + /** + * @brief Deactivates the pbackup cutter + */ + void disableBackupCutter() { - if (status.state == CutterState::CUTTING_MAIN) + if (status.state == CutterState::CUTTING_BACKUP) { - disableCutter(CUTTER_CHANNEL_MAIN_CHUTE, pin_enable_main_chute); + disableCutter(CUTTER_CHANNEL_BACKUP, pin_enable_backup); status.state = CutterState::IDLE; } } + /** + * @brief Enables the primary cutter using the "test" duty cycle + * + * call disablePrimaryCutter() to disable + */ + void enableTestPrimaryCutter() + { + enableCutter(CUTTER_CHANNEL_BACKUP, pin_enable_backup, test_duty_cycle); + status.state = CutterState::TESTING_PRIMARY; + } + + /** + * @brief Enables the backup cutter using the "test" duty cycle + * + * call disableBackupCutter() to disable + */ + void enableTestBackupCutter() + { + enableCutter(CUTTER_CHANNEL_BACKUP, pin_enable_backup, test_duty_cycle); + status.state = CutterState::TESTING_PRIMARY; + } + CutterStatus getStatus() { return status; } private: - void enableCutter(PWMChannel channel, miosix::GpioPin& ena_pin) + void enableCutter(PWMChannel channel, miosix::GpioPin& ena_pin, + float duty_cycle) { - // Enable PWM Generation - - pwm.setDutyCycle(channel, duty_cycle); + // Only enable if the cutter is currently idle + if (status.state == CutterState::IDLE) + { + // Enable PWM Generation + pwm.setDutyCycle(channel, duty_cycle); - // enable hbridge - ena_pin.high(); + // enable + ena_pin.high(); + } } void disableCutter(PWMChannel channel, miosix::GpioPin& ena_pin) @@ -123,11 +170,14 @@ private: ena_pin.low(); // Disable hbridge } + Cutter(const Cutter& c) = delete; + PWM pwm; - GpioPin pin_enable_drogue; - GpioPin pin_enable_main_chute; + GpioPin pin_enable_primary; + GpioPin pin_enable_backup; - float duty_cycle; + float cut_duty_cycle; + float test_duty_cycle; CutterStatus status; }; diff --git a/src/boards/DeathStack/DeploymentController/ThermalCutter/CutterData.h b/src/boards/DeathStack/DeploymentController/ThermalCutter/CutterData.h index 869247cfe37550b4fee7e0e9495c1f287e8caf16..39f6d04990cc912dead538e894931a53fa8c66ee 100644 --- a/src/boards/DeathStack/DeploymentController/ThermalCutter/CutterData.h +++ b/src/boards/DeathStack/DeploymentController/ThermalCutter/CutterData.h @@ -32,8 +32,10 @@ namespace DeathStackBoard enum class CutterState : uint8_t { IDLE, - CUTTING_DROGUE, - CUTTING_MAIN + CUTTING_PRIMARY, + CUTTING_BACKUP, + TESTING_PRIMARY, + TESTING_BACKUP }; struct CutterStatus diff --git a/src/boards/DeathStack/FlightModeManager/FlightModeManager.cpp b/src/boards/DeathStack/FlightModeManager/FlightModeManager.cpp index 4f95b265492fdbe5bc2b77112ab7f5ceb1d4702a..5d6d5091edd7227f1fb76a99c6ec5436acf60514 100644 --- a/src/boards/DeathStack/FlightModeManager/FlightModeManager.cpp +++ b/src/boards/DeathStack/FlightModeManager/FlightModeManager.cpp @@ -23,10 +23,10 @@ #include <DeathStack/FlightModeManager/FlightModeManager.h> #include <events/EventBroker.h> -#include "DeathStack/events/Events.h" #include "DeathStack/System/StackLogger.h" -#include "DeathStack/events/Topics.h" #include "DeathStack/configs/FMMConfig.h" +#include "DeathStack/events/Events.h" +#include "DeathStack/events/Topics.h" #include "Debug.h" @@ -381,27 +381,11 @@ State FlightModeManager::state_testing(const Event& ev) sEventBroker->post(Event{EV_NC_OPEN}, TOPIC_DEPLOYMENT); break; } - case EV_TC_NC_CLOSE: - { - sEventBroker->post(Event{EV_NC_CLOSE}, TOPIC_DEPLOYMENT); - break; - } - case EV_TC_CUT_FIRST_DROGUE: + case EV_TC_CUT_DROGUE: { sEventBroker->post(Event{EV_CUT_DROGUE}, TOPIC_DEPLOYMENT); break; } - case EV_TC_CUT_MAIN: - { - sEventBroker->post(Event{EV_CUT_MAIN}, TOPIC_DEPLOYMENT); - break; - } - case EV_TC_START_ROGALLO_CONTROL: - { - sEventBroker->post(Event{EV_START_ROGALLO_CONTROL}, - TOPIC_DEPLOYMENT); - break; - } case EV_TC_CLOSE_LOG: { logger.stop(); @@ -534,16 +518,8 @@ State FlightModeManager::state_drogueDescent(const Event& ev) break; } - case EV_TC_MANUAL_MODE: // Manual mode = we don't trust ADA for - // deployment - case EV_TC_ABORT_ROGALLO: // Abort rogallo = don't deploy, or cut if - // deployed - { - retState = transition(&FlightModeManager::state_manualDescent); - break; - } case EV_ADA_DPL_ALT_DETECTED: - case EV_TC_CUT_FIRST_DROGUE: + case EV_TC_CUT_DROGUE: { retState = transition(&FlightModeManager::state_rogalloDescent); break; @@ -577,23 +553,11 @@ State FlightModeManager::state_terminalDescent(const Event& ev) { break; } - case EV_TC_CUT_FIRST_DROGUE: // if you want to repeat cutting + case EV_TC_CUT_DROGUE: // if you want to repeat cutting { sEventBroker->post(Event{EV_CUT_DROGUE}, TOPIC_DEPLOYMENT); break; } - case EV_TC_CUT_MAIN: // remove rogallo - { - sEventBroker->post(Event{EV_CUT_MAIN}, TOPIC_DEPLOYMENT); - break; - } - case EV_TC_START_ROGALLO_CONTROL: - { - sEventBroker->post(Event{EV_START_ROGALLO_CONTROL}, - TOPIC_DEPLOYMENT); - - break; - } default: /* If an event is not handled here, try with super-state */ { retState = tran_super(&FlightModeManager::state_flying); @@ -626,10 +590,6 @@ State FlightModeManager::state_rogalloDescent(const Event& ev) { break; } - case EV_TC_ABORT_ROGALLO: // GS doesn't trust rogallo - { - sEventBroker->post(Event{EV_CUT_MAIN}, TOPIC_DEPLOYMENT); - } default: /* If an event is not handled here, try with super-state */ { retState = tran_super(&FlightModeManager::state_terminalDescent); diff --git a/src/boards/DeathStack/LoggerService/LoggerService.cpp b/src/boards/DeathStack/LoggerService/LoggerService.cpp index 15793f52c51fdd5d0ea5821da7ac0a2f735088c0..a2e102a251c77c6000b939b25eb757a7d2775bd3 100644 --- a/src/boards/DeathStack/LoggerService/LoggerService.cpp +++ b/src/boards/DeathStack/LoggerService/LoggerService.cpp @@ -246,9 +246,6 @@ LogResult LoggerService::log<DeploymentStatus>(const DeploymentStatus& t) miosix::PauseKernelLock kLock; tm_repository.dpl_tm.fsm_state = (uint8_t)t.state; - tm_repository.dpl_tm.motor_active = t.motor_status.motor_active; - tm_repository.dpl_tm.motor_last_direction = - (uint8_t)t.motor_status.motor_last_direction; tm_repository.dpl_tm.cutter_state = (uint8_t)t.cutter_status.state; // HR TM diff --git a/src/boards/DeathStack/SensorManager/Sensors/ADCWrapper.h b/src/boards/DeathStack/SensorManager/Sensors/ADCWrapper.h index 5b28c5613fb8bc91b19479a8d43c414a2160b6a6..4e4df6f57edd0e128752758888f865457d916ef2 100644 --- a/src/boards/DeathStack/SensorManager/Sensors/ADCWrapper.h +++ b/src/boards/DeathStack/SensorManager/Sensors/ADCWrapper.h @@ -76,7 +76,7 @@ public: CurrentSenseData* getCurrentDataPtr() { return ¤t_data; } private: - float adcToCurrent(uint16_t adc_in) { return (adc_in - 107) / 32.4f; } + float adcToCurrent(uint16_t adc_in) { return (adc_in - 107) / 23.8f; } const adc_t::Channel CS_1_CHANNEL = static_cast<adc_t::Channel>(ADC_CURRENT_SENSE_1_CHANNEL); diff --git a/src/boards/DeathStack/TMTCManager/TCHandler.h b/src/boards/DeathStack/TMTCManager/TCHandler.h index 902ba983f9a9616951f9e864e75b0641dbce6da8..d6c6e1d7d1dc8e582550f32459af40862aa2de0b 100644 --- a/src/boards/DeathStack/TMTCManager/TCHandler.h +++ b/src/boards/DeathStack/TMTCManager/TCHandler.h @@ -50,13 +50,10 @@ static const std::map<uint8_t, uint8_t> noargCmdToEvt = { MAV_CMD_DISARM, EV_TC_DISARM }, { MAV_CMD_CALIBRATE_ADA, EV_TC_CALIBRATE_ADA}, // { MAV_CMD_ABORT_LAUNCH, EV_TC_ABORT_LAUNCH}, - { MAV_CMD_ABORT_ROGALLO, EV_TC_ABORT_ROGALLO}, { MAV_CMD_FORCE_INIT, EV_TC_FORCE_INIT}, { MAV_CMD_FORCE_LAUNCH, EV_TC_LAUNCH}, { MAV_CMD_NOSECONE_OPEN, EV_TC_NC_OPEN }, { MAV_CMD_NOSECONE_CLOSE, EV_TC_NC_CLOSE }, - { MAV_CMD_CUT_MAIN, EV_TC_CUT_MAIN }, - { MAV_CMD_CUT_DROGUE, EV_TC_CUT_FIRST_DROGUE }, { MAV_CMD_START_ROGALLO_CONTROL, EV_TC_START_ROGALLO_CONTROL}, { MAV_CMD_START_LOGGING, EV_TC_START_SENSOR_LOGGING }, @@ -65,7 +62,6 @@ static const std::map<uint8_t, uint8_t> noargCmdToEvt = { MAV_CMD_TEST_MODE, EV_TC_TEST_MODE }, { MAV_CMD_BOARD_RESET, EV_TC_BOARD_RESET }, - { MAV_CMD_MANUAL_MODE, EV_TC_MANUAL_MODE }, { MAV_CMD_END_MISSION, EV_TC_END_MISSION } }; diff --git a/src/boards/DeathStack/configs/CutterConfig.h b/src/boards/DeathStack/configs/CutterConfig.h index 46ee3e141bee943bd5e76c65572d84fb099bc38e..f4c7e85907d341d64c34294fcabe6a74abc8dee3 100644 --- a/src/boards/DeathStack/configs/CutterConfig.h +++ b/src/boards/DeathStack/configs/CutterConfig.h @@ -27,7 +27,6 @@ #include "drivers/pwm/pwm.h" #include "interfaces-impl/hwmapping.h" - namespace DeathStackBoard { // clang-format off @@ -42,26 +41,26 @@ static const PWM::Timer CUTTER_TIM{ // clang-format on -// DROGUE --> THCUT1 on theboard -static const PWMChannel CUTTER_CHANNEL_DROGUE = PWMChannel::CH2; -typedef miosix::actuators::thCut1::ena DrogueCutterEna; +static constexpr int CUT_DURATION = 5 * 1000; + +// PRIMARY --> THCUT1 on theboard +static const PWMChannel CUTTER_CHANNEL_PRIMARY = PWMChannel::CH2; +typedef miosix::actuators::thCut1::ena PrimaryCutterEna; -// MAIN CHUTE --> THCUT2 on theboard -static const PWMChannel CUTTER_CHANNEL_MAIN_CHUTE = PWMChannel::CH2; -typedef miosix::actuators::thCut2::ena MainChuteCutterEna; +// BACKUP --> THCUT2 on theboard +static const PWMChannel CUTTER_CHANNEL_BACKUP = PWMChannel::CH2; +typedef miosix::actuators::thCut2::ena BackupCutterEna; // PWM Frequency & duty-cycle -static const unsigned int CUTTER_PWM_FREQUENCY = 1500; -// FREQ: 15k -// 0.3: 2.2 s cut -> ni-cr wire broken -// 0.15: 8.5 s cut, too slow -static const float DROGUE_CUTTER_PWM_DUTY_CYCLE = 0.065f; -static const float ROG_CUTTER_PWM_DUTY_CYCLE = 0.2f; +static const unsigned int CUTTER_PWM_FREQUENCY = 15000; // Hz +// Duty cycle to be used during flight to cut the chord +static constexpr float CUTTER_PWM_DUTY_CYCLE = 0.30f; +// Duty cycle to be used during integration, to perform a a non-destructive +// continuity check +static constexpr float CUTTER_TEST_PWM_DUTY_CYCLE = 0.05f; // Period of time where the IN must be kept low before bringing ENA/INH low static const int CUTTER_DISABLE_DELAY_MS = 50; - -} // DeathStackBoard - +} // namespace DeathStackBoard diff --git a/src/boards/DeathStack/configs/DeploymentConfig.h b/src/boards/DeathStack/configs/DeploymentConfig.h index 032520b31374d773f33e220a708c140131524c49..4f3ea9d808bcbdcb3671a575e5baadbb77fbe198 100644 --- a/src/boards/DeathStack/configs/DeploymentConfig.h +++ b/src/boards/DeathStack/configs/DeploymentConfig.h @@ -33,41 +33,25 @@ namespace DeathStackBoard { -// TODO: Update with correct values -static constexpr int MAXIMUM_CUTTING_DURATION = 15 * 1000; +namespace DeploymentConfigs +{ -static constexpr int NC_MINIMUM_OPENING_TIME = 5000; -static constexpr int NC_OPEN_TIMEOUT = 15000; -static constexpr int NC_CLOSE_TIMEOUT = 15000; +static constexpr uint8_t MAX_EJECTION_ATTEMPTS = 1; -static const MotorDirection MOTOR_OPEN_DIR = MotorDirection::NORMAL; -static const MotorDirection MOTOR_CLOSE_DIR = MotorDirection::REVERSE; +static constexpr int NC_OPEN_TIMEOUT = 10000; +static constexpr int SERVO_RESET_TIMEOUT = 1000; -static const PWM::Timer TIM4_DATA{ +static const PWM::Timer SERVO_TIMER{ TIM4, &(RCC->APB1ENR), RCC_APB1ENR_TIM4EN, TimerUtils::getPrescalerInputFrequency(TimerUtils::InputClock::APB1)}; -static const PWM::Timer TIM8_DATA{ - TIM8, &(RCC->APB2ENR), RCC_APB2ENR_TIM8EN, - TimerUtils::getPrescalerInputFrequency(TimerUtils::InputClock::APB2)}; - -static constexpr PWMChannel SERVO_LEFT_CH = PWMChannel::CH2; -static constexpr PWMChannel SERVO_RIGHT_CH = PWMChannel::CH2; -static constexpr PWMChannel SERVO_KEEL_CH = PWMChannel::CH1; - -// Right servo reset position -static constexpr float SERVO_R_RESET_POS = 0.875f; -// Right servo control position -static constexpr float SERVO_R_CONTROL_POS = 0.80f; +static constexpr PWMChannel SERVO_CHANNEL = PWMChannel::CH1; -// Keel servo reset position -static constexpr float SERVO_K_RESET_POS = 0.875f; -// Keel servo control position -static constexpr float SERVO_K_CONTROL_POS = 0.80f; +// Servo rest position +static constexpr float SERVO_RESET_POS = 1.0f; +// Servo position when ejecting the nosecone +static constexpr float SERVO_EJECT_POS = 0.30f; -// Left servo reset position -static constexpr float SERVO_L_RESET_POS = 0.125f; -// Left servo control position -static constexpr float SERVO_L_CONTROL_POS = 0.20f; +} // namespace DeploymentConfigs } // namespace DeathStackBoard diff --git a/src/boards/DeathStack/events/EventStrings.cpp b/src/boards/DeathStack/events/EventStrings.cpp index 33d1070b5eba51aa966a8f6615d4a97ccacc7af0..758880dc4ded6b63b1e8173516d73665528c86ab 100644 --- a/src/boards/DeathStack/events/EventStrings.cpp +++ b/src/boards/DeathStack/events/EventStrings.cpp @@ -26,16 +26,15 @@ ****************************************************************************** */ -// Generated from: https://docs.google.com/spreadsheets/d/1msICDqJtSseSP_JAoAPoKIzpKlI6bI2n8lwws1X2hz4 -// Autogen date: 2019-05-20 17:09:34.002542 -#include <map> -#include <cstring> +// Generated from: https://docs.google.com/spreadsheets/d/184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0 +// Autogen date: 2019-10-10 19:39:23.107904 + #include "Events.h" #include "Topics.h" +#include <map> using std::map; -using std::string; namespace DeathStackBoard { @@ -53,57 +52,45 @@ string getEventString(uint8_t event) { EV_BUTTON_UP, "EV_BUTTON_UP" }, { EV_BUTTON_VERY_LONG_PRESS, "EV_BUTTON_VERY_LONG_PRESS" }, { EV_CALIBRATE_ADA, "EV_CALIBRATE_ADA" }, - { EV_CUT_ALL, "EV_CUT_ALL" }, { EV_CUT_DROGUE, "EV_CUT_DROGUE" }, - { EV_CUT_MAIN, "EV_CUT_MAIN" }, { EV_DPL_ALTITUDE, "EV_DPL_ALTITUDE" }, { EV_FLIGHTSTATS_TIMEOUT, "EV_FLIGHTSTATS_TIMEOUT" }, { EV_INIT_ERROR, "EV_INIT_ERROR" }, { EV_INIT_OK, "EV_INIT_OK" }, { EV_LANDED, "EV_LANDED" }, { EV_LIFTOFF, "EV_LIFTOFF" }, - { EV_MOT_CLOSE_LIMIT, "EV_MOT_CLOSE_LIMIT" }, - { EV_MOT_MIN_OPEN_TIME, "EV_MOT_MIN_OPEN_TIME" }, - { EV_MOT_OPEN_LIMIT, "EV_MOT_OPEN_LIMIT" }, - { EV_NC_CLOSE, "EV_NC_CLOSE" }, { EV_NC_DETACHED, "EV_NC_DETACHED" }, { EV_NC_OPEN, "EV_NC_OPEN" }, - { EV_NC_STOP, "EV_NC_STOP" }, { EV_SEND_HR_TM, "EV_SEND_HR_TM" }, { EV_SEND_LR_TM, "EV_SEND_LR_TM" }, { EV_SEND_TEST_TM, "EV_SEND_TEST_TM" }, - { EV_START_ROGALLO_CONTROL, "EV_START_ROGALLO_CONTROL" }, - { EV_TC_ABORT_ROGALLO, "EV_TC_ABORT_ROGALLO" }, { EV_TC_ARM, "EV_TC_ARM" }, { EV_TC_BOARD_RESET, "EV_TC_BOARD_RESET" }, { EV_TC_CALIBRATE_ADA, "EV_TC_CALIBRATE_ADA" }, { EV_TC_CLOSE_LOG, "EV_TC_CLOSE_LOG" }, - { EV_TC_CUT_ALL, "EV_TC_CUT_ALL" }, - { EV_TC_CUT_FIRST_DROGUE, "EV_TC_CUT_FIRST_DROGUE" }, - { EV_TC_CUT_MAIN, "EV_TC_CUT_MAIN" }, + { EV_TC_CUT_DROGUE, "EV_TC_CUT_DROGUE" }, { EV_TC_DISARM, "EV_TC_DISARM" }, { EV_TC_END_MISSION, "EV_TC_END_MISSION" }, { EV_TC_FORCE_INIT, "EV_TC_FORCE_INIT" }, { EV_TC_LAUNCH, "EV_TC_LAUNCH" }, - { EV_TC_MANUAL_MODE, "EV_TC_MANUAL_MODE" }, { EV_TC_NC_CLOSE, "EV_TC_NC_CLOSE" }, { EV_TC_NC_OPEN, "EV_TC_NC_OPEN" }, - { EV_TC_NC_STOP, "EV_TC_NC_STOP" }, { EV_TC_SET_DPL_ALTITUDE, "EV_TC_SET_DPL_ALTITUDE" }, { EV_TC_SET_REFERENCE_ALTITUDE, "EV_TC_SET_REFERENCE_ALTITUDE" }, { EV_TC_SET_REFERENCE_TEMP, "EV_TC_SET_REFERENCE_TEMP" }, { EV_TC_START_ROGALLO_CONTROL, "EV_TC_START_ROGALLO_CONTROL" }, { EV_TC_START_SENSOR_LOGGING, "EV_TC_START_SENSOR_LOGGING" }, { EV_TC_STOP_SENSOR_LOGGING, "EV_TC_STOP_SENSOR_LOGGING" }, + { EV_TC_TEST_CUTTER_BACKUP, "EV_TC_TEST_CUTTER_BACKUP" }, + { EV_TC_TEST_CUTTER_PRIMARY, "EV_TC_TEST_CUTTER_PRIMARY" }, { EV_TC_TEST_MODE, "EV_TC_TEST_MODE" }, - { EV_TC_TEST_SERVO, "EV_TC_TEST_SERVO" }, + { EV_TEST_CUTTER_BACKUP, "EV_TEST_CUTTER_BACKUP" }, + { EV_TEST_CUTTER_PRIMARY, "EV_TEST_CUTTER_PRIMARY" }, { EV_TEST_MODE, "EV_TEST_MODE" }, - { EV_TIMEOUT_APOGEE, "EV_TIMEOUT_APOGEE" }, - { EV_TIMEOUT_ARM, "EV_TIMEOUT_ARM" }, { EV_TIMEOUT_CUTTING, "EV_TIMEOUT_CUTTING" }, { EV_TIMEOUT_END_MISSION, "EV_TIMEOUT_END_MISSION" }, - { EV_TIMEOUT_MOT_CLOSE, "EV_TIMEOUT_MOT_CLOSE" }, - { EV_TIMEOUT_MOT_OPEN, "EV_TIMEOUT_MOT_OPEN" }, + { EV_TIMEOUT_NC_OPEN, "EV_TIMEOUT_NC_OPEN" }, + { EV_TIMEOUT_SERVO_RESET, "EV_TIMEOUT_SERVO_RESET" }, { EV_TIMEOUT_SHADOW_MODE, "EV_TIMEOUT_SHADOW_MODE" }, { EV_UMBILICAL_DETACHED, "EV_UMBILICAL_DETACHED" } }; diff --git a/src/boards/DeathStack/events/Events.h b/src/boards/DeathStack/events/Events.h index 398510fc2be70de4de1ec6eff2f532e3bec008e4..93011ce854c34d8e2fff9945f72d3030d7996f58 100644 --- a/src/boards/DeathStack/events/Events.h +++ b/src/boards/DeathStack/events/Events.h @@ -26,11 +26,10 @@ ****************************************************************************** */ -// Generated from: https://docs.google.com/spreadsheets/d/1msICDqJtSseSP_JAoAPoKIzpKlI6bI2n8lwws1X2hz4 -// Autogen date: 2019-05-20 17:09:34.002542 +// Generated from: https://docs.google.com/spreadsheets/d/184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0 +// Autogen date: 2019-10-10 19:39:23.107904 -#ifndef SRC_SHARED_BOARDS_HOMEONE_EVENTS_H -#define SRC_SHARED_BOARDS_HOMEONE_EVENTS_H +#pragma once #include <cstdint> #include <string> @@ -40,10 +39,13 @@ #include "events/EventBroker.h" #include "Topics.h" +using std::string; + namespace DeathStackBoard { /** * Definition of all events in the Homeone Board software + * Refer to section 5.1.1 of the Software Design Document. */ enum Events : uint8_t { @@ -57,62 +59,50 @@ enum Events : uint8_t EV_BUTTON_UP, EV_BUTTON_VERY_LONG_PRESS, EV_CALIBRATE_ADA, - EV_CUT_ALL, EV_CUT_DROGUE, - EV_CUT_MAIN, EV_DPL_ALTITUDE, EV_FLIGHTSTATS_TIMEOUT, EV_INIT_ERROR, EV_INIT_OK, EV_LANDED, EV_LIFTOFF, - EV_MOT_CLOSE_LIMIT, - EV_MOT_MIN_OPEN_TIME, - EV_MOT_OPEN_LIMIT, - EV_NC_CLOSE, EV_NC_DETACHED, EV_NC_OPEN, - EV_NC_STOP, EV_SEND_HR_TM, EV_SEND_LR_TM, EV_SEND_TEST_TM, - EV_START_ROGALLO_CONTROL, - EV_TC_ABORT_ROGALLO, EV_TC_ARM, EV_TC_BOARD_RESET, EV_TC_CALIBRATE_ADA, EV_TC_CLOSE_LOG, - EV_TC_CUT_ALL, - EV_TC_CUT_FIRST_DROGUE, - EV_TC_CUT_MAIN, + EV_TC_CUT_DROGUE, EV_TC_DISARM, EV_TC_END_MISSION, EV_TC_FORCE_INIT, EV_TC_LAUNCH, - EV_TC_MANUAL_MODE, EV_TC_NC_CLOSE, EV_TC_NC_OPEN, - EV_TC_NC_STOP, EV_TC_SET_DPL_ALTITUDE, EV_TC_SET_REFERENCE_ALTITUDE, EV_TC_SET_REFERENCE_TEMP, EV_TC_START_ROGALLO_CONTROL, EV_TC_START_SENSOR_LOGGING, EV_TC_STOP_SENSOR_LOGGING, + EV_TC_TEST_CUTTER_BACKUP, + EV_TC_TEST_CUTTER_PRIMARY, EV_TC_TEST_MODE, - EV_TC_TEST_SERVO, + EV_TEST_CUTTER_BACKUP, + EV_TEST_CUTTER_PRIMARY, EV_TEST_MODE, - EV_TIMEOUT_APOGEE, - EV_TIMEOUT_ARM, EV_TIMEOUT_CUTTING, EV_TIMEOUT_END_MISSION, - EV_TIMEOUT_MOT_CLOSE, - EV_TIMEOUT_MOT_OPEN, + EV_TIMEOUT_NC_OPEN, + EV_TIMEOUT_SERVO_RESET, EV_TIMEOUT_SHADOW_MODE, EV_UMBILICAL_DETACHED }; -const std::vector<uint8_t> EVENT_LIST {EV_ADA_APOGEE_DETECTED, EV_ADA_DPL_ALT_DETECTED, EV_ADA_READY, EV_APOGEE, EV_BUTTON_DOWN, EV_BUTTON_LONG_PRESS, EV_BUTTON_SHORT_PRESS, EV_BUTTON_UP, EV_BUTTON_VERY_LONG_PRESS, EV_CALIBRATE_ADA, EV_CUT_ALL, EV_CUT_DROGUE, EV_CUT_MAIN, EV_DPL_ALTITUDE, EV_FLIGHTSTATS_TIMEOUT, EV_INIT_ERROR, EV_INIT_OK, EV_LANDED, EV_LIFTOFF, EV_MOT_CLOSE_LIMIT, EV_MOT_MIN_OPEN_TIME, EV_MOT_OPEN_LIMIT, EV_NC_CLOSE, EV_NC_DETACHED, EV_NC_OPEN, EV_NC_STOP, EV_SEND_HR_TM, EV_SEND_LR_TM, EV_SEND_TEST_TM, EV_START_ROGALLO_CONTROL, EV_TC_ABORT_ROGALLO, EV_TC_ARM, EV_TC_BOARD_RESET, EV_TC_CALIBRATE_ADA, EV_TC_CLOSE_LOG, EV_TC_CUT_ALL, EV_TC_CUT_FIRST_DROGUE, EV_TC_CUT_MAIN, EV_TC_DISARM, EV_TC_END_MISSION, EV_TC_FORCE_INIT, EV_TC_LAUNCH, EV_TC_MANUAL_MODE, EV_TC_NC_CLOSE, EV_TC_NC_OPEN, EV_TC_NC_STOP, EV_TC_SET_DPL_ALTITUDE, EV_TC_SET_REFERENCE_ALTITUDE, EV_TC_SET_REFERENCE_TEMP, EV_TC_START_ROGALLO_CONTROL, EV_TC_START_SENSOR_LOGGING, EV_TC_STOP_SENSOR_LOGGING, EV_TC_TEST_MODE, EV_TC_TEST_SERVO, EV_TEST_MODE, EV_TIMEOUT_APOGEE, EV_TIMEOUT_ARM, EV_TIMEOUT_CUTTING, EV_TIMEOUT_END_MISSION, EV_TIMEOUT_MOT_CLOSE, EV_TIMEOUT_MOT_OPEN, EV_TIMEOUT_SHADOW_MODE, EV_UMBILICAL_DETACHED}; +const std::vector<uint8_t> EVENT_LIST {EV_ADA_APOGEE_DETECTED, EV_ADA_DPL_ALT_DETECTED, EV_ADA_READY, EV_APOGEE, EV_BUTTON_DOWN, EV_BUTTON_LONG_PRESS, EV_BUTTON_SHORT_PRESS, EV_BUTTON_UP, EV_BUTTON_VERY_LONG_PRESS, EV_CALIBRATE_ADA, EV_CUT_DROGUE, EV_DPL_ALTITUDE, EV_FLIGHTSTATS_TIMEOUT, EV_INIT_ERROR, EV_INIT_OK, EV_LANDED, EV_LIFTOFF, EV_NC_DETACHED, EV_NC_OPEN, EV_SEND_HR_TM, EV_SEND_LR_TM, EV_SEND_TEST_TM, EV_TC_ARM, EV_TC_BOARD_RESET, EV_TC_CALIBRATE_ADA, EV_TC_CLOSE_LOG, EV_TC_CUT_DROGUE, EV_TC_DISARM, EV_TC_END_MISSION, EV_TC_FORCE_INIT, EV_TC_LAUNCH, EV_TC_NC_CLOSE, EV_TC_NC_OPEN, EV_TC_SET_DPL_ALTITUDE, EV_TC_SET_REFERENCE_ALTITUDE, EV_TC_SET_REFERENCE_TEMP, EV_TC_START_ROGALLO_CONTROL, EV_TC_START_SENSOR_LOGGING, EV_TC_STOP_SENSOR_LOGGING, EV_TC_TEST_CUTTER_BACKUP, EV_TC_TEST_CUTTER_PRIMARY, EV_TC_TEST_MODE, EV_TEST_CUTTER_BACKUP, EV_TEST_CUTTER_PRIMARY, EV_TEST_MODE, EV_TIMEOUT_CUTTING, EV_TIMEOUT_END_MISSION, EV_TIMEOUT_NC_OPEN, EV_TIMEOUT_SERVO_RESET, EV_TIMEOUT_SHADOW_MODE, EV_UMBILICAL_DETACHED}; /** * @brief Returns the name of the provided event @@ -120,7 +110,6 @@ const std::vector<uint8_t> EVENT_LIST {EV_ADA_APOGEE_DETECTED, EV_ADA_DPL_ALT_DE * @param event * @return string */ -std::string getEventString(uint8_t event); -} +string getEventString(uint8_t event); -#endif /* SRC_SHARED_BOARDS_HOMEONE_EVENTS_H */ +} diff --git a/src/boards/DeathStack/events/Topics.h b/src/boards/DeathStack/events/Topics.h index 71ba0272a7b6638c064c49911493991921330d02..0bdb3bf9340ebc5e5a42edefabdbd526b87d7a39 100644 --- a/src/boards/DeathStack/events/Topics.h +++ b/src/boards/DeathStack/events/Topics.h @@ -26,16 +26,17 @@ ****************************************************************************** */ -// Generated from: https://docs.google.com/spreadsheets/d/1msICDqJtSseSP_JAoAPoKIzpKlI6bI2n8lwws1X2hz4 -// Autogen date: 2019-05-20 17:09:34.002542 +// Generated from: https://docs.google.com/spreadsheets/d/184kR2OAD7yWV0fYJdiGUDmHmy5_prY3nr-XgNA0Uge0 +// Autogen date: 2019-10-10 19:39:23.107904 -#ifndef SRC_SHARED_BOARDS_HOMEONE_TOPICS_H -#define SRC_SHARED_BOARDS_HOMEONE_TOPICS_H +#pragma once #include <stdint.h> #include <string> #include <vector> +using std::string; + namespace DeathStackBoard { /** @@ -62,8 +63,7 @@ const std::vector<uint8_t> TOPIC_LIST {TOPIC_ADA, TOPIC_CAN, TOPIC_DEPLOYMENT, T * @param event * @return string */ -std::string getTopicString(uint8_t topic); +string getTopicString(uint8_t topic); } // namespace DeathStackBoard -#endif /* SRC_SHARED_BOARDS_HOMEONE_TOPICS_H_ */ diff --git a/src/tests/drivers/test-cutter.cpp b/src/tests/drivers/test-cutter.cpp index f4485d9ffe542fae62c9fa555f56652f07db1e89..71bbdfa0ce34d92e21d0385fb941972db13c6f8f 100644 --- a/src/tests/drivers/test-cutter.cpp +++ b/src/tests/drivers/test-cutter.cpp @@ -33,7 +33,7 @@ using namespace std; using namespace miosix; using namespace DeathStackBoard; -static constexpr int CUT_TIME = 10000; +static constexpr int CUT_TIME = 60 * 1000; long long measured_cut_time = 0; void wait() @@ -53,8 +53,6 @@ void wait() bool print = false; -float vToI(uint16_t adc) { return ((float)(adc - 109)) * 19500 / 510.0f; } - void csense(void*) { ADCWrapper adc; @@ -91,12 +89,17 @@ int main() printf( "Info: To stop cutting (and to stop the cut timer) press the OPEN " "button\n"); - printf("What do you want to cut? (1 / 2)\n"); + printf("What do you want to cut? (1 - primary / 2 - backup)\n"); unsigned int c, freq = 0; float duty = 0; string temp; getline(cin, temp); stringstream(temp) >> c; + if (c != 1 && c != 2) + { + printf("Choose 1 or 2\n"); + continue; + } cout << "Insert frequency (Hz): \n"; getline(cin, temp); stringstream(temp) >> freq; @@ -107,29 +110,36 @@ int main() printf("Cutting %d, freq: %d, duty: %f\n", c, freq, duty); - if (!(freq > 1 && freq < 20000 && duty > 0.0f && duty <= 100.0f)) + if (!(freq > 1 && freq <= 30000 && duty >= 0.0f && duty <= 100.0f)) { printf("Wrong inputs!\n"); continue; } - print = true; - - Cutter cutter{freq, duty / 100}; - - if (c == 1) + do { - cutter.startCutDrogue(); - wait(); - cutter.stopCutDrogue(); - } - else if (c == 2) + cout << "READY!\nWrite 'yeet' to begin:\n"; + getline(cin, temp); + } while (temp != "yeet"); + { - cutter.startCutMainChute(); - wait(); - cutter.stopCutMainChute(); + print = true; + + Cutter cutter{freq, duty / 100, CUTTER_TEST_PWM_DUTY_CYCLE}; + + if (c == 1) + { + cutter.enablePrimaryCutter(); + wait(); + cutter.disablePrimaryCutter(); + } + else if (c == 2) + { + cutter.enableBackupCutter(); + wait(); + cutter.disableBackupCutter(); + } } - Thread::sleep(2000); print = false; Thread::sleep(500); diff --git a/src/tests/drivers/test-servo.cpp b/src/tests/drivers/test-servo.cpp index 087ff7e89b80fc3ebf7739986579c441445c50c3..915841cb7201d304aa164ed3988b8a8fb243963a 100644 --- a/src/tests/drivers/test-servo.cpp +++ b/src/tests/drivers/test-servo.cpp @@ -24,37 +24,48 @@ #include <arch/common/drivers/servo_stm32.h> #include <miosix.h> #include <cstdio> +#include <iostream> +#include <sstream> +#include <string> +#include "drivers/servo/servo.h" +#include "DeathStack/configs/DeploymentConfig.h" using namespace miosix; +using namespace std; +using namespace DeathStackBoard; -typedef Gpio<GPIOB_BASE, 8> ServoPin; +static const PWMChannel CHANNEL = PWMChannel::CH1; -static const int CHANNEL = 2; int main() { - { - FastInterruptDisableLock l; - ServoPin::mode(Mode::ALTERNATE); - ServoPin::alternateFunction(2); - } - - SynchronizedServo& s = SynchronizedServo::instance(); + Servo s{DeploymentConfigs::SERVO_TIMER}; + s.setMinPulseWidth(800); + s.setMaxPulseWidth(2200); + s.setPosition(CHANNEL, 0.77f); s.enable(CHANNEL); - s.setPosition(CHANNEL, 0); + s.start(); - Thread::sleep(5000); + // Thread::sleep(5000); + string temp; printf("Ready.\n"); + int pos; for (;;) { - printf("Set position:\n"); - float p; - if (scanf("%f", &p) > 0) + temp = ""; + printf("Insert position: \n"); + getline(cin, temp); + + stringstream(temp) >> pos; + + if (pos >= 0 && pos <= 100) { - s.setPosition(CHANNEL, p/100.0f); + printf("Position set to %d\n", pos); + s.setPosition(CHANNEL, pos / 100.0f); } else { printf("You dumb fuck.\n"); } + Thread::sleep(100); } } \ No newline at end of file diff --git a/src/tests/test-dpl.cpp b/src/tests/test-dpl.cpp index 02c812a29185e71254992121918821e90e7724cc..a92926e6857f7cbbd957824fbcea6c7427c563fb 100644 --- a/src/tests/test-dpl.cpp +++ b/src/tests/test-dpl.cpp @@ -1,60 +1,325 @@ -#include <miosix.h> -#include <utils/catch.hpp> +/** + * Copyright (c) 2019 Skyward Experimental Rocketry + * Authors: Luca Erbetta + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <logger/Logger.h> +#include <cstdio> +#include <iostream> +#include <sstream> +#include <string> -#include <skyward-boardcore/src/shared/utils/EventSniffer.h> #include "DeathStack/DeploymentController/DeploymentController.h" +#include "DeathStack/DeploymentController/ThermalCutter/Cutter.h" +#include "DeathStack/SensorManager/Sensors/ADCWrapper.h" +#include "DeathStack/configs/CutterConfig.h" +#include "DeathStack/events/EventInjector.h" #include "DeathStack/events/Events.h" -#include "DeathStack/events/Topics.h" -#include "PinObserver.h" +#include "utils/testutils/TestHelper.h" -using miosix::Thread; using namespace DeathStackBoard; -void onEventReceived(uint8_t event, uint8_t topic) -{ - TRACE("[%.3f] %s on %s\n", (miosix::getTick() / 1000.0f), - getEventString(event).c_str(), getTopicString(topic).c_str()); -} +using namespace std; + +void cuttingSequence(); +void cutterContinuity(); +void noseconeEjection(); +void manualEvent(); + +float adcToCurrent(uint16_t adc_in) { return (adc_in - 107) / 32.4f; } int main() { - DeploymentController* dpl = new DeploymentController(); - dpl->start(); sEventBroker->start(); - EventSniffer* sniffer = - new EventSniffer(*sEventBroker, TOPIC_LIST, onEventReceived); - - Thread::sleep(1000); - - printf("\n Init ok\n\n"); - while (true) + string temp; + for (;;) { - printf("o - nc open\n"); - printf("d - cut drogue\n"); - printf("m - cut main\n"); - printf("x - detach\n"); + int choice; + cout << "\n\nWhat do you want to do?: \n"; + cout << "1. Test cutting sequence\n"; + cout << "2. Non-destructive cutter test\n"; + cout << "3. Nosecone ejection\n"; + cout << "4. Manual event input\n"; - char c = getchar(); + getline(cin, temp); + stringstream(temp) >> choice; - switch (c) + switch (choice) { - case ('o'): - sEventBroker->post({EV_NC_OPEN}, TOPIC_DEPLOYMENT); + case 1: + cuttingSequence(); break; - case ('d'): - sEventBroker->post({EV_CUT_MAIN}, TOPIC_DEPLOYMENT); + case 2: + cutterContinuity(); break; - case ('m'): - sEventBroker->post({EV_CUT_DROGUE}, TOPIC_DEPLOYMENT); + case 3: + noseconeEjection(); break; - case ('x'): - sEventBroker->post({EV_NC_DETACHED}, TOPIC_DEPLOYMENT); + case 4: + manualEvent(); break; default: break; } } +} + +bool print = false; + +void csense(void*) +{ + ADCWrapper adc; + adc.getCurrentSensorPtr()->init(); + + for (;;) + { + adc.getCurrentSensorPtr()->onSimpleUpdate(); + uint16_t raw1 = + adc.getCurrentSensorPtr()->getCurrentDataPtr()->raw_value_1; + uint16_t raw2 = + adc.getCurrentSensorPtr()->getCurrentDataPtr()->raw_value_2; + + float current1 = + adc.getCurrentSensorPtr()->getCurrentDataPtr()->current_1; + float current2 = + adc.getCurrentSensorPtr()->getCurrentDataPtr()->current_2; + if (print) + { + printf("%d,%d,%d,%f,%f\n", (int)miosix::getTick(), (int)raw1, + (int)raw2, current1, current2); + } + Thread::sleep(100); + } +} + +void cuttingSequence() +{ + string temp; + char yn; + + cout << "\n\n** CUTTER SEQUENCE TEST **\n\n"; + cout << "Use predefined cutter parameters? (y/n)\n"; + getline(cin, temp); + stringstream(temp) >> yn; + unsigned int freq = CUTTER_PWM_FREQUENCY; + float duty = CUTTER_PWM_DUTY_CYCLE * 100; + + if (yn == 'n') + { + do + { + cout << "Insert frequency (Hz): \n"; + getline(cin, temp); + stringstream(temp) >> freq; + + cout << "Insert duty cycle(%): \n"; + getline(cin, temp); + stringstream(temp) >> duty; + } while (freq < 100 || freq > 30000 || duty < 0 || duty > 100); + + printf("Using custom parameters: Freq: %d, Duty: %.2f\n", freq, duty); + } + else + { + printf("Using default parameters: Freq: %d, Duty: %.2f\n", freq, duty); + } + + do + { + cout << "Write 'start' to begin:\n"; + getline(cin, temp); + } while (temp != "start"); + + { + Cutter c{freq, duty / 100.0f, CUTTER_TEST_PWM_DUTY_CYCLE}; + Servo s{DeploymentConfigs::SERVO_TIMER}; + + DeploymentController dpl{c, s}; + dpl.start(); + print = true; + Thread::sleep(1000); + cout << "Activating primary cutter...\n"; + sEventBroker->post({EV_CUT_DROGUE}, TOPIC_DEPLOYMENT); + + waitForEvent(EV_TIMEOUT_CUTTING, TOPIC_DEPLOYMENT); + cout << "Primary cutter is done.\n"; + cout << "Activating secondary cutter\n"; + + waitForEvent(EV_TIMEOUT_CUTTING, TOPIC_DEPLOYMENT); + cout << "Backup cutter is done.\n"; + cout << "\n Test finished!\n\n"; + Thread::sleep(1000); + print = false; + } +} + +void cutterContinuity() +{ + string temp; + int cutter; + cout << "\n\n** NON-DESTRUCTIVE CUTTER TEST **\n\n"; + do + { + cout << "Which cutter to test? (1-primary / 2-backup)\n"; + + string temp; + getline(cin, temp); + stringstream(temp) >> cutter; + } while (cutter != 1 && cutter != 2); + + cout << "Use predefined cutter parameters? (y/n)\n"; + + char yn; + getline(cin, temp); + stringstream(temp) >> yn; + unsigned int freq = CUTTER_PWM_FREQUENCY; + float duty = CUTTER_TEST_PWM_DUTY_CYCLE * 100; + + if (yn == 'n') + { + do + { + cout << "Insert frequency (Hz): \n"; + getline(cin, temp); + stringstream(temp) >> freq; - // EV_NC_OPEN EV_CUT_DROGUE EV_CUT_MAIN EV_NC_DETACHED -} \ No newline at end of file + cout << "Insert test duty cycle(%): \n"; + getline(cin, temp); + stringstream(temp) >> duty; + } while (freq < 100 || freq > 30000 || duty < 0 || duty > 100); + + printf("Using custom parameters: Freq: %d, Test Duty: %.2f\n", freq, + duty); + } + else + { + printf("Using default parameters: Freq: %d, Test Duty: %.2f\n", freq, + duty); + } + + do + { + cout << "Write 'start' to begin:\n"; + getline(cin, temp); + } while (temp != "start"); + + { + Cutter c{freq, CUTTER_PWM_DUTY_CYCLE, duty}; + Servo s{DeploymentConfigs::SERVO_TIMER}; + + DeploymentController dpl{c, s}; + dpl.start(); + Thread::sleep(1000); + print = true; + if (cutter == 1) + { + cout << "Activating primary cutter...\n"; + sEventBroker->post({EV_TEST_CUTTER_PRIMARY}, TOPIC_DEPLOYMENT); + } + else + { + cout << "Activating backup cutter...\n"; + sEventBroker->post({EV_TEST_CUTTER_BACKUP}, TOPIC_DEPLOYMENT); + } + + waitForEvent(EV_TIMEOUT_CUTTING, TOPIC_DEPLOYMENT); + + cout << "Cutter test is done.\n"; + cout << "\n Test finished!\n\n"; + + Thread::sleep(1000); + print = false; + + dpl.stop(); + } +} + +void noseconeEjection() +{ + Servo s{DeploymentConfigs::SERVO_TIMER}; + s.setMinPulseWidth(800); + s.setMaxPulseWidth(2200); + s.enable(DeploymentConfigs::SERVO_CHANNEL); + + s.setPosition(DeploymentConfigs::SERVO_CHANNEL, + DeploymentConfigs::SERVO_RESET_POS); + + s.start(); + + cout << "\n\n** NOSECONE EJECTION TEST **\n\n"; + string temp; + do + { + cout << "Write 'yeet' to yeet out the nosecone:\n"; + getline(cin, temp); + } while (temp != "yeet"); + + { + EventCounter counter{*sEventBroker}; + + Cutter c{CUTTER_PWM_FREQUENCY, CUTTER_PWM_DUTY_CYCLE, + CUTTER_TEST_PWM_DUTY_CYCLE}; + + DeploymentController dpl{c, s}; + dpl.start(); + counter.subscribe(TOPIC_DEPLOYMENT); + counter.start(); + + cout << "Activating primary cutter...\n"; + sEventBroker->post({EV_NC_OPEN}, TOPIC_DEPLOYMENT); + + for (;;) + { + if (counter.getCount(EV_TIMEOUT_NC_OPEN) == + DeploymentConfigs::MAX_EJECTION_ATTEMPTS) + break; + if (counter.getCount(EV_NC_DETACHED) >= 1) + break; + Thread::sleep(10); + } + + cout << "Cutter test is done.\n"; + cout << "\n Test finished!\n\n"; + + dpl.stop(); + counter.stop(); + } +} + +void manualEvent() +{ + cout << "\n\n** MANUAL MODE **\n\n"; + cout << "Hope you know what you are doing\n"; + + Cutter c{CUTTER_PWM_FREQUENCY, CUTTER_PWM_DUTY_CYCLE, + CUTTER_TEST_PWM_DUTY_CYCLE}; + + Servo s{DeploymentConfigs::SERVO_TIMER}; + s.setMinPulseWidth(800); + s.setMaxPulseWidth(2200); + + DeploymentController dpl{c, s}; + EventInjector ei; + + ei.start(); + dpl.start(); +}