Change M0/M1 into a command

That implies changing motor's mode from SpreadCycle into StealtMode (or vice versa)
requires a stand still MMU with no other command (i.e. motor moves) being performed.
This elegantly solves the synchronization problem of TMC2130 mode change, as it results
in severe jerking while a motor is moving.

The change in protocol is minimal - M0/M1 first return `M0 A` (accepted) and another `Q0` then
returns `M0 F` (finished). The MK4 counterpart may ignore the additional report if necessary
as the mode change is done immediately (shortly after responding with `M0 A`)
pull/119/head
D.R.racer 2021-09-07 08:04:50 +02:00 committed by DRracer
parent 641b91f0cb
commit 3646b8b1c0
4 changed files with 62 additions and 22 deletions

View File

@ -1,13 +1,13 @@
target_sources(
firmware
PRIVATE
command_base.cpp
PRIVATE command_base.cpp
cut_filament.cpp
eject_filament.cpp
feed_to_bondtech.cpp
feed_to_finda.cpp
load_filament.cpp
no_command.cpp
set_mode.cpp
tool_change.cpp
unload_filament.cpp
unload_to_finda.cpp

17
src/logic/set_mode.cpp Normal file
View File

@ -0,0 +1,17 @@
#include "set_mode.h"
#include "../modules/globals.h"
#include "../modules/motion.h"
namespace logic {
SetMode setMode;
void SetMode::Reset(uint8_t param) {
mg::globals.SetMotorsMode(param != 0); // remember the last mode set
// distribute the mode to all motors immediately
mm::motion.SetMode((param == 0) ? mm::Normal : mm::Stealth);
state = ProgressCode::OK;
error = ErrorCode::OK;
}
} // namespace logic

29
src/logic/set_mode.h Normal file
View File

@ -0,0 +1,29 @@
#pragma once
#include <stdint.h>
#include "command_base.h"
namespace logic {
/// @brief Sets the mode of TMC2130 for all motors at once.
/// In the original proposal, the M0/M1 message was declared as a query, since it can be processed immediately.
/// The reality is a bit different - the TMC2130 driver cannot change from SpreadCycle into StealthMode while moving the motor,
/// at least not without serious jerking in most cases.
/// Therefore the M0/M1 messages were reconsidered into a command, because only one command at a time can be performed
/// (regardless of how long it takes it to finish) - that implies no motor moves are being performed while M0/M1 is being applied.
class SetMode : public CommandBase {
public:
inline SetMode()
: CommandBase() {}
/// Restart the automaton
void Reset(uint8_t param) override;
/// @returns true if the state machine finished its job, false otherwise
/// Since we perform the TMC2130 mode change in the Reset directly, the return is always true here (command finished ok)
bool StepInner() override { return true; }
};
/// The one and only instance of NoCommand state machine in the FW
extern SetMode setMode;
} // namespace logic

View File

@ -26,6 +26,7 @@
#include "logic/eject_filament.h"
#include "logic/load_filament.h"
#include "logic/no_command.h"
#include "logic/set_mode.h"
#include "logic/tool_change.h"
#include "logic/unload_filament.h"
@ -259,6 +260,9 @@ void PlanCommand(const mp::RequestMsg &rq) {
case mp::RequestMsgCodes::Unload:
currentCommand = &logic::unloadFilament;
break;
case mp::RequestMsgCodes::Mode:
currentCommand = &logic::setMode;
break;
default:
currentCommand = &logic::noCommand;
break;
@ -271,12 +275,6 @@ void PlanCommand(const mp::RequestMsg &rq) {
}
}
void SetMode(uint8_t m) {
mg::globals.SetMotorsMode(m != 0); // remember the last mode set
// distribute the mode to all motors immediately
mm::motion.SetMode((m == 0) ? mm::Normal : mm::Stealth);
}
void ProcessRequestMsg(const mp::RequestMsg &rq) {
switch (rq.code) {
case mp::RequestMsgCodes::Button:
@ -287,10 +285,6 @@ void ProcessRequestMsg(const mp::RequestMsg &rq) {
// immediately report FINDA status
ReportFINDA(rq);
break;
case mp::RequestMsgCodes::Mode:
// immediately switch to normal/stealth as requested
SetMode(rq.value);
break;
case mp::RequestMsgCodes::Query:
// immediately report progress of currently running command
ReportRunningCommand();