Link top level error reporting to TMC2130 error flags
parent
7029b1b03d
commit
ef96d998a3
|
|
@ -4,14 +4,7 @@
|
||||||
namespace hal {
|
namespace hal {
|
||||||
namespace tmc2130 {
|
namespace tmc2130 {
|
||||||
|
|
||||||
TMC2130::TMC2130(const MotorParams ¶ms, const MotorCurrents ¤ts, MotorMode mode)
|
bool TMC2130::Init(const MotorParams ¶ms, const MotorCurrents ¤ts, MotorMode mode) {
|
||||||
: mode(mode)
|
|
||||||
, currents(currents)
|
|
||||||
, sg_counter(0) {
|
|
||||||
Init(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TMC2130::Init(const MotorParams ¶ms) {
|
|
||||||
gpio::Init(params.csPin, gpio::GPIO_InitTypeDef(gpio::Mode::output, gpio::Level::high));
|
gpio::Init(params.csPin, gpio::GPIO_InitTypeDef(gpio::Mode::output, gpio::Level::high));
|
||||||
gpio::Init(params.sgPin, gpio::GPIO_InitTypeDef(gpio::Mode::input, gpio::Pull::up));
|
gpio::Init(params.sgPin, gpio::GPIO_InitTypeDef(gpio::Mode::input, gpio::Pull::up));
|
||||||
gpio::Init(params.stepPin, gpio::GPIO_InitTypeDef(gpio::Mode::output, gpio::Level::low));
|
gpio::Init(params.stepPin, gpio::GPIO_InitTypeDef(gpio::Mode::output, gpio::Level::low));
|
||||||
|
|
@ -69,15 +62,11 @@ bool TMC2130::Init(const MotorParams ¶ms) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TMC2130::SetMode(const MotorParams ¶ms, MotorMode mode) {
|
void TMC2130::SetMode(const MotorParams ¶ms, MotorMode mode) {
|
||||||
this->mode = mode;
|
|
||||||
|
|
||||||
///0xFFF00 is used as a "Normal" mode threshold since stealthchop will be used at standstill.
|
///0xFFF00 is used as a "Normal" mode threshold since stealthchop will be used at standstill.
|
||||||
WriteRegister(params, Registers::TPWMTHRS, (mode == Stealth) ? 70 : 0xFFF00); // @todo should be configurable
|
WriteRegister(params, Registers::TPWMTHRS, (mode == Stealth) ? 70 : 0xFFF00); // @todo should be configurable
|
||||||
}
|
}
|
||||||
|
|
||||||
void TMC2130::SetCurrents(const MotorParams ¶ms, const MotorCurrents ¤ts) {
|
void TMC2130::SetCurrents(const MotorParams ¶ms, const MotorCurrents ¤ts) {
|
||||||
this->currents = currents;
|
|
||||||
|
|
||||||
uint32_t ihold_irun = (uint32_t)(currents.iHold & 0x1F) << 0 //ihold
|
uint32_t ihold_irun = (uint32_t)(currents.iHold & 0x1F) << 0 //ihold
|
||||||
| (uint32_t)(currents.iRun & 0x1F) << 8 //irun
|
| (uint32_t)(currents.iRun & 0x1F) << 8 //irun
|
||||||
| (uint32_t)(15 & 0x0F) << 16; //IHOLDDELAY
|
| (uint32_t)(15 & 0x0F) << 16; //IHOLDDELAY
|
||||||
|
|
|
||||||
|
|
@ -32,27 +32,24 @@ struct MotorCurrents {
|
||||||
uint8_t iHold; ///< Holding current
|
uint8_t iHold; ///< Holding current
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct __attribute__((packed)) ErrorFlags {
|
||||||
|
uint8_t reset_flag : 1; ///< driver restarted
|
||||||
|
uint8_t uv_cp : 1; ///< undervoltage on charge pump
|
||||||
|
uint8_t s2g : 1; ///< short to ground
|
||||||
|
uint8_t otpw : 1; ///< over temperature pre-warning
|
||||||
|
uint8_t ot : 1; ///< over temperature hard
|
||||||
|
inline ErrorFlags()
|
||||||
|
: reset_flag(0)
|
||||||
|
, uv_cp(0)
|
||||||
|
, s2g(0)
|
||||||
|
, otpw(0)
|
||||||
|
, ot(0) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// TMC2130 interface - instances of this class are hidden in modules::motion::Motion::AxisData
|
||||||
class TMC2130 {
|
class TMC2130 {
|
||||||
MotorMode mode;
|
|
||||||
MotorCurrents currents;
|
|
||||||
struct __attribute__((packed)) ErrorFlags {
|
|
||||||
uint8_t reset_flag : 1;
|
|
||||||
uint8_t uv_cp : 1;
|
|
||||||
uint8_t s2g : 1;
|
|
||||||
uint8_t otpw : 1;
|
|
||||||
uint8_t ot : 1;
|
|
||||||
inline ErrorFlags()
|
|
||||||
: reset_flag(0)
|
|
||||||
, uv_cp(0)
|
|
||||||
, s2g(0)
|
|
||||||
, otpw(0)
|
|
||||||
, ot(0) {}
|
|
||||||
|
|
||||||
} errorFlags;
|
|
||||||
bool enabled = false;
|
|
||||||
uint8_t sg_counter;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// TMC2130 register addresses
|
||||||
enum class Registers : uint8_t {
|
enum class Registers : uint8_t {
|
||||||
/// General Configuration Registers
|
/// General Configuration Registers
|
||||||
GCONF = 0x00,
|
GCONF = 0x00,
|
||||||
|
|
@ -76,28 +73,18 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
TMC2130(const MotorParams ¶ms,
|
TMC2130() = default;
|
||||||
const MotorCurrents ¤ts,
|
|
||||||
MotorMode mode);
|
|
||||||
|
|
||||||
/// (re)initialization of the chip - please note this is necessary due to some HW flaws in the original MMU boards.
|
/// (re)initialization of the chip - please note this is necessary due to some HW flaws in the original MMU boards.
|
||||||
/// And yes, the TMC may not get correctly initialized.
|
/// And yes, the TMC may not get correctly initialized.
|
||||||
/// @returns true if the TMC2130 was inited correctly
|
/// @returns true if the TMC2130 was inited correctly
|
||||||
bool Init(const MotorParams ¶ms);
|
bool Init(const MotorParams ¶ms,
|
||||||
|
const MotorCurrents ¤ts,
|
||||||
/// Get the current motor mode
|
MotorMode mode);
|
||||||
MotorMode Mode() const {
|
|
||||||
return mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the current motor mode
|
/// Set the current motor mode
|
||||||
void SetMode(const MotorParams ¶ms, MotorMode mode);
|
void SetMode(const MotorParams ¶ms, MotorMode mode);
|
||||||
|
|
||||||
/// Get the current motor currents
|
|
||||||
const MotorCurrents &Currents() const {
|
|
||||||
return currents;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the current motor currents
|
/// Set the current motor currents
|
||||||
void SetCurrents(const MotorParams ¶ms, const MotorCurrents ¤ts);
|
void SetCurrents(const MotorParams ¶ms, const MotorCurrents ¤ts);
|
||||||
|
|
||||||
|
|
@ -149,6 +136,10 @@ public:
|
||||||
private:
|
private:
|
||||||
void _spi_tx_rx(const MotorParams ¶ms, uint8_t (&pData)[5]);
|
void _spi_tx_rx(const MotorParams ¶ms, uint8_t (&pData)[5]);
|
||||||
void _handle_spi_status(const MotorParams ¶ms, uint8_t status);
|
void _handle_spi_status(const MotorParams ¶ms, uint8_t status);
|
||||||
|
|
||||||
|
ErrorFlags errorFlags;
|
||||||
|
bool enabled = false;
|
||||||
|
uint8_t sg_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tmc2130
|
} // namespace tmc2130
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,80 @@
|
||||||
#include "command_base.h"
|
#include "command_base.h"
|
||||||
#include "../modules/idler.h"
|
#include "../modules/idler.h"
|
||||||
#include "../modules/selector.h"
|
#include "../modules/selector.h"
|
||||||
|
#include "../modules/motion.h"
|
||||||
|
|
||||||
namespace mi = modules::idler;
|
namespace mi = modules::idler;
|
||||||
namespace ms = modules::selector;
|
namespace ms = modules::selector;
|
||||||
|
namespace mm = modules::motion;
|
||||||
|
|
||||||
namespace logic {
|
namespace logic {
|
||||||
|
|
||||||
|
inline ErrorCode &operator|=(ErrorCode &a, ErrorCode b) {
|
||||||
|
return a = (ErrorCode)((uint16_t)a | (uint16_t)b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ErrorCode TMC2130ToErrorCode(const hal::tmc2130::TMC2130 &tmc, uint8_t tmcIndex) {
|
||||||
|
ErrorCode e = ErrorCode::OK;
|
||||||
|
|
||||||
|
if (tmc.GetErrorFlags().reset_flag) {
|
||||||
|
e |= ErrorCode::TMC_RESET;
|
||||||
|
}
|
||||||
|
if (tmc.GetErrorFlags().uv_cp) {
|
||||||
|
e |= ErrorCode::TMC_UNDERVOLTAGE_ON_CHARGE_PUMP;
|
||||||
|
}
|
||||||
|
if (tmc.GetErrorFlags().s2g) {
|
||||||
|
e |= ErrorCode::TMC_SHORT_TO_GROUND;
|
||||||
|
}
|
||||||
|
if (tmc.GetErrorFlags().otpw) {
|
||||||
|
e |= ErrorCode::TMC_OVER_TEMPERATURE_WARN;
|
||||||
|
}
|
||||||
|
if (tmc.GetErrorFlags().ot) {
|
||||||
|
e |= ErrorCode::TMC_OVER_TEMPERATURE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e != ErrorCode::OK) {
|
||||||
|
switch (tmcIndex) {
|
||||||
|
case config::Axis::Pulley:
|
||||||
|
e |= ErrorCode::TMC_PULLEY_BIT;
|
||||||
|
break;
|
||||||
|
case config::Axis::Selector:
|
||||||
|
e |= ErrorCode::TMC_SELECTOR_BIT;
|
||||||
|
break;
|
||||||
|
case config::Axis::Idler:
|
||||||
|
e |= ErrorCode::TMC_IDLER_BIT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
bool CommandBase::Step() {
|
bool CommandBase::Step() {
|
||||||
|
ErrorCode tmcErr = ErrorCode::OK;
|
||||||
// check the global HW errors - may be we should avoid the modules layer and check for the HAL layer errors directly
|
// check the global HW errors - may be we should avoid the modules layer and check for the HAL layer errors directly
|
||||||
if (mi::idler.State() == mi::Idler::Failed) {
|
if (mi::idler.State() == mi::Idler::Failed) {
|
||||||
state = ProgressCode::ERRTMCFailed;
|
state = ProgressCode::ERRTMCFailed;
|
||||||
error = ErrorCode::TMC_IOIN_MISMATCH;
|
tmcErr |= TMC2130ToErrorCode(mm::motion.DriverForAxis(mm::Axis::Idler), mm::Axis::Idler);
|
||||||
return true; // the HW error prevents us from continuing with the with the state machine - the MMU must be restarted/fixed before continuing
|
}
|
||||||
} else if (ms::selector.State() == ms::Selector::Failed) {
|
if (ms::selector.State() == ms::Selector::Failed) {
|
||||||
state = ProgressCode::ERRTMCFailed;
|
state = ProgressCode::ERRTMCFailed;
|
||||||
error = ErrorCode::TMC_IOIN_MISMATCH;
|
tmcErr |= TMC2130ToErrorCode(mm::motion.DriverForAxis(mm::Axis::Selector), mm::Axis::Selector);
|
||||||
return true; // the HW error prevents us from continuing with the with the state machine - the MMU must be restarted/fixed before continuing
|
}
|
||||||
|
// may be we should model the Pulley as well...
|
||||||
|
// if (ms::selector.State() == ms::Selector::Failed) {
|
||||||
|
// state = ProgressCode::ERRTMCFailed;
|
||||||
|
// error |= TMC2130ToErrorCode(mm::motion.DriverForAxis(mm::Axis::Selector), mm::Axis::Selector);
|
||||||
|
// return true; // the HW error prevents us from continuing with the with the state machine - the MMU must be restarted/fixed before continuing
|
||||||
|
// }
|
||||||
|
|
||||||
|
// @@TODO not sure how to prevent losing the previously accumulated error ... or do I really need to do it?
|
||||||
|
// May be the TMC error word just gets updated with new flags as the motion proceeds
|
||||||
|
// And how about the logical errors like FINDA_DIDNT_SWITCH_ON?
|
||||||
|
if (tmcErr != ErrorCode::OK) {
|
||||||
|
error |= tmcErr;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return StepInner();
|
return StepInner();
|
||||||
|
|
|
||||||
|
|
@ -56,5 +56,5 @@ enum class ErrorCode : uint_fast16_t {
|
||||||
/// TMC driver over temperature error - we really shouldn't ever reach this error.
|
/// TMC driver over temperature error - we really shouldn't ever reach this error.
|
||||||
/// It can still be recovered if the driver cools down below 120C.
|
/// It can still be recovered if the driver cools down below 120C.
|
||||||
/// The driver needs to be disabled and enabled again for operation to resume after this error is cleared.
|
/// The driver needs to be disabled and enabled again for operation to resume after this error is cleared.
|
||||||
TMC_OVER_TEMPERATURE_ERROR = 0xC000,
|
TMC_OVER_TEMPERATURE_ERROR = 0xC000
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -73,5 +73,10 @@ bool Idler::Step() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//hal::tmc2130::MotorParams Idler::TMCDriverParams() const {
|
||||||
|
// return
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
} // namespace idler
|
} // namespace idler
|
||||||
} // namespace modules
|
} // namespace modules
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ public:
|
||||||
/// @returns the index of idle position of the idler, usually 5 in case of 0-4 valid indices of filament slots
|
/// @returns the index of idle position of the idler, usually 5 in case of 0-4 valid indices of filament slots
|
||||||
inline static constexpr uint8_t IdleSlotIndex() { return config::toolCount; }
|
inline static constexpr uint8_t IdleSlotIndex() { return config::toolCount; }
|
||||||
|
|
||||||
|
// hal::tmc2130::MotorParams TMCDriverParams()const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void PrepareMoveToPlannedSlot() override;
|
virtual void PrepareMoveToPlannedSlot() override;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ bool Motion::InitAxis(Axis axis) {
|
||||||
// disable the axis and re-init the driver: this will clear the internal
|
// disable the axis and re-init the driver: this will clear the internal
|
||||||
// StallGuard data as a result without special handling
|
// StallGuard data as a result without special handling
|
||||||
Disable(axis);
|
Disable(axis);
|
||||||
return axisData[axis].drv.Init(axisParams[axis].params);
|
return axisData[axis].drv.Init(axisParams[axis].params, axisParams[axis].currents, axisParams[axis].mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Motion::SetEnabled(Axis axis, bool enabled) {
|
void Motion::SetEnabled(Axis axis, bool enabled) {
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
namespace modules {
|
namespace modules {
|
||||||
|
|
||||||
/// @@TODO
|
|
||||||
/// Logic of motor handling
|
/// Logic of motor handling
|
||||||
/// Ideally enable stepping of motors under ISR (all timers have higher priority than serial)
|
/// Ideally enable stepping of motors under ISR (all timers have higher priority than serial)
|
||||||
namespace motion {
|
namespace motion {
|
||||||
|
|
@ -38,7 +37,7 @@ static constexpr MotorMode DefaultMotorMode(const config::AxisConfig &axis) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Static axis configuration
|
/// Static axis configuration
|
||||||
static constexpr AxisParams axisParams[NUM_AXIS] = {
|
static AxisParams axisParams[NUM_AXIS] = {
|
||||||
// Pulley
|
// Pulley
|
||||||
{
|
{
|
||||||
.name = 'P',
|
.name = 'P',
|
||||||
|
|
@ -215,6 +214,11 @@ public:
|
||||||
/// stop whatever moves are being done
|
/// stop whatever moves are being done
|
||||||
void AbortPlannedMoves();
|
void AbortPlannedMoves();
|
||||||
|
|
||||||
|
/// @returns the TMC213 driver associated with the particular axis
|
||||||
|
inline const hal::tmc2130::TMC2130 &DriverForAxis(Axis axis) const {
|
||||||
|
return axisData[axis].drv;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct AxisData {
|
struct AxisData {
|
||||||
TMC2130 drv; ///< Motor driver
|
TMC2130 drv; ///< Motor driver
|
||||||
|
|
@ -226,11 +230,7 @@ private:
|
||||||
/// Helper to initialize AxisData members
|
/// Helper to initialize AxisData members
|
||||||
static AxisData DataForAxis(Axis axis) {
|
static AxisData DataForAxis(Axis axis) {
|
||||||
return {
|
return {
|
||||||
.drv = {
|
.drv = {},
|
||||||
axisParams[axis].params,
|
|
||||||
axisParams[axis].currents,
|
|
||||||
axisParams[axis].mode,
|
|
||||||
},
|
|
||||||
.ctrl = {
|
.ctrl = {
|
||||||
axisParams[axis].jerk,
|
axisParams[axis].jerk,
|
||||||
axisParams[axis].accel,
|
axisParams[axis].accel,
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,13 @@
|
||||||
namespace hal {
|
namespace hal {
|
||||||
namespace tmc2130 {
|
namespace tmc2130 {
|
||||||
|
|
||||||
TMC2130::TMC2130(const MotorParams ¶ms,
|
|
||||||
const MotorCurrents ¤ts,
|
|
||||||
MotorMode mode) {
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
void TMC2130::SetMode(const MotorParams ¶ms, MotorMode mode) {
|
void TMC2130::SetMode(const MotorParams ¶ms, MotorMode mode) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TMC2130::Init(const MotorParams & /*params*/) {
|
bool TMC2130::Init(const MotorParams ¶ms,
|
||||||
|
const MotorCurrents ¤ts,
|
||||||
|
MotorMode mode) {
|
||||||
// TODO
|
// TODO
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue