feat: main loop now listens to state
This commit is contained in:
+35
-24
@@ -75,33 +75,44 @@ void MainLoop::update() noexcept
|
|||||||
UartHandler& uart = UartHandler::getInstance();
|
UartHandler& uart = UartHandler::getInstance();
|
||||||
uart.poll();
|
uart.poll();
|
||||||
|
|
||||||
while(uart.getNumAvailablePackets()) {
|
switch (StateMachine::getInstance().getState()) {
|
||||||
uint8_t packet[16];
|
case StateMachine::STATE::IDLING:
|
||||||
uart.getNextPacket(packet);
|
case StateMachine::STATE::MOVING:
|
||||||
CommandParser::Command command = CommandParser::getInstance().parsePacket(packet);
|
while(uart.getNumAvailablePackets()) {
|
||||||
|
uint8_t packet[16];
|
||||||
|
uart.getNextPacket(packet);
|
||||||
|
CommandParser::Command command = CommandParser::getInstance().parsePacket(packet);
|
||||||
|
|
||||||
switch (command.instruction) {
|
switch (command.instruction) {
|
||||||
// Scoping to keep variables local
|
// Scoping to keep variables local
|
||||||
case CommandParser::Command::TYPE::MOVE_ABSOLUTE: {
|
case CommandParser::Command::TYPE::MOVE_ABSOLUTE: {
|
||||||
AdafruitServoMotor& motor = motors[command.args[0]];
|
AdafruitServoMotor& motor = motors[command.args[0]];
|
||||||
const float moveTarget = (float)command.args[1] / 10.0f;
|
const float moveTarget = (float)command.args[1] / 10.0f;
|
||||||
motor.moveTo(moveTarget);
|
motor.moveTo(moveTarget);
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CommandParser::Command::TYPE::MOVE_RELATIVE: {
|
|
||||||
AdafruitServoMotor& motor = motors[command.args[0]];
|
|
||||||
const float moveDelta = (float)command.args[1] / 10.0f;
|
|
||||||
motor.moveTo(motor.getPosition() + moveDelta);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CommandParser::Command::TYPE::RESET_POSITIONS: {
|
|
||||||
for (uint8_t i = 0; i < 3; i++) {
|
|
||||||
motors[i].moveTo(0);
|
|
||||||
motors[i].commitMoveImmediately();
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case CommandParser::Command::TYPE::MOVE_RELATIVE: {
|
||||||
|
AdafruitServoMotor& motor = motors[command.args[0]];
|
||||||
|
const float moveDelta = (float)command.args[1] / 10.0f;
|
||||||
|
motor.moveTo(motor.getPosition() + moveDelta);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CommandParser::Command::TYPE::RESET_POSITIONS: {
|
||||||
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
|
motors[i].moveTo(0);
|
||||||
|
motors[i].commitMoveImmediately();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case StateMachine::STATE::ERROR:
|
||||||
|
default:
|
||||||
|
// Freeze in place until error clears or device reset
|
||||||
|
yield();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-14
@@ -14,7 +14,7 @@ StateMachine& StateMachine::getInstance() noexcept
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StateMachine::setState(const State newState) noexcept
|
bool StateMachine::setState(const STATE newState) noexcept
|
||||||
{
|
{
|
||||||
if (canSwitchToState(newState)) {
|
if (canSwitchToState(newState)) {
|
||||||
state = newState;
|
state = newState;
|
||||||
@@ -24,15 +24,15 @@ bool StateMachine::setState(const State newState) noexcept
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StateMachine::canSwitchToState(const State newState) const noexcept
|
bool StateMachine::canSwitchToState(const STATE newState) const noexcept
|
||||||
{
|
{
|
||||||
// Error state is final
|
// Error state is final
|
||||||
if (state == State::ERROR) {
|
if (state == STATE::ERROR) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error state only settable via raiseError()
|
// Error state only settable via raiseError()
|
||||||
if (newState == State::ERROR) {
|
if (newState == STATE::ERROR) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,39 +42,39 @@ bool StateMachine::canSwitchToState(const State newState) const noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case StateMachine::State::INITIALIZING:
|
case StateMachine::STATE::INITIALIZING:
|
||||||
switch (newState) {
|
switch (newState) {
|
||||||
// Can go to idle
|
// Can go to idle
|
||||||
case State::IDLING:
|
case STATE::IDLING:
|
||||||
return true;
|
return true;
|
||||||
// Can't go straight to moving
|
// Can't go straight to moving
|
||||||
case State::MOVING:
|
case STATE::MOVING:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case StateMachine::State::IDLING:
|
case StateMachine::STATE::IDLING:
|
||||||
switch (newState) {
|
switch (newState) {
|
||||||
// Can't initialize again
|
// Can't initialize again
|
||||||
case State::INITIALIZING:
|
case STATE::INITIALIZING:
|
||||||
return false;
|
return false;
|
||||||
// Can enter move state
|
// Can enter move state
|
||||||
case State::MOVING:
|
case STATE::MOVING:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case StateMachine::State::MOVING:
|
case StateMachine::STATE::MOVING:
|
||||||
switch (newState) {
|
switch (newState) {
|
||||||
// Can't initialize again
|
// Can't initialize again
|
||||||
case State::INITIALIZING:
|
case STATE::INITIALIZING:
|
||||||
return false;
|
return false;
|
||||||
// Can go into idling
|
// Can go into idling
|
||||||
case State::IDLING:
|
case STATE::IDLING:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -87,7 +87,7 @@ bool StateMachine::canSwitchToState(const State newState) const noexcept
|
|||||||
|
|
||||||
bool StateMachine::raiseError(const String &reason) noexcept
|
bool StateMachine::raiseError(const String &reason) noexcept
|
||||||
{
|
{
|
||||||
state = State::ERROR;
|
state = STATE::ERROR;
|
||||||
lastError = reason;
|
lastError = reason;
|
||||||
digitalWrite(ERROR_INDICATOR_LED_PIN, HIGH);
|
digitalWrite(ERROR_INDICATOR_LED_PIN, HIGH);
|
||||||
if (Serial) {
|
if (Serial) {
|
||||||
|
|||||||
+7
-7
@@ -4,28 +4,28 @@
|
|||||||
// Singleton-instance
|
// Singleton-instance
|
||||||
class StateMachine
|
class StateMachine
|
||||||
{
|
{
|
||||||
enum class State {
|
public:
|
||||||
|
enum class STATE {
|
||||||
INITIALIZING,
|
INITIALIZING,
|
||||||
IDLING,
|
IDLING,
|
||||||
MOVING,
|
MOVING,
|
||||||
ERROR
|
ERROR
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
|
||||||
StateMachine(const StateMachine&) = delete;
|
StateMachine(const StateMachine&) = delete;
|
||||||
StateMachine(StateMachine&&) = delete;
|
StateMachine(StateMachine&&) = delete;
|
||||||
static StateMachine& getInstance() noexcept;
|
static StateMachine& getInstance() noexcept;
|
||||||
|
|
||||||
State getState() const noexcept { return state; };
|
STATE getState() const noexcept { return state; };
|
||||||
String getLastError() const noexcept { return lastError; };
|
String getLastError() const noexcept { return lastError; };
|
||||||
// May fail if a state transition from state a to b is not valid
|
// May fail if a state transition from state a to b is not valid
|
||||||
bool setState(const State newState) noexcept;
|
bool setState(const STATE newState) noexcept;
|
||||||
bool raiseError(const String& reason) noexcept;
|
bool raiseError(const String& reason) noexcept;
|
||||||
bool canSwitchToState(const State newState) const noexcept;
|
bool canSwitchToState(const STATE newState) const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StateMachine() noexcept;
|
StateMachine() noexcept;
|
||||||
|
|
||||||
State state = State::INITIALIZING;
|
STATE state = STATE::INITIALIZING;
|
||||||
String lastError = "";
|
String lastError = "";
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user