From e4cabdd5e3aa1d339118351efc1271de999ddf83 Mon Sep 17 00:00:00 2001 From: David Crocker Date: Tue, 14 Dec 2021 21:43:10 +0000 Subject: Handle driver warnings and errors via the event handling system Also removed delay to reporting driver OTPW when a fan has just been turned on Also bug fixes to event handling system --- src/CAN/CanInterface.cpp | 4 +- src/CAN/CommandProcessor.cpp | 5 ++ src/Fans/LocalFan.cpp | 28 +------ src/Platform/Event.cpp | 13 +++ src/Platform/Event.h | 6 ++ src/Platform/Platform.cpp | 194 ++++++++++++++++--------------------------- src/Platform/Platform.h | 9 +- src/Version.h | 2 +- 8 files changed, 104 insertions(+), 157 deletions(-) diff --git a/src/CAN/CanInterface.cpp b/src/CAN/CanInterface.cpp index 9249dfc5..20c36877 100644 --- a/src/CAN/CanInterface.cpp +++ b/src/CAN/CanInterface.cpp @@ -350,8 +350,8 @@ void CanInterface::SendAnnounce(CanMessageBuffer *buf) noexcept void CanInterface::RaiseEvent(EventType type, uint16_t param, uint8_t device, const char *format, va_list vargs) noexcept { CanMessageBuffer buf(nullptr); - auto msg = buf.SetupStatusMessage(CanInterface::GetCanAddress(), CanId::MasterAddress); - msg->eventType = EventType::heater_fault; + auto msg = buf.SetupStatusMessage(GetCanAddress(), GetCurrentMasterAddress()); + msg->eventType = type.ToBaseType();; msg->deviceNumber = device; msg->eventParam = param; msg->zero = 0; diff --git a/src/CAN/CommandProcessor.cpp b/src/CAN/CommandProcessor.cpp index 43d99b58..b74c4750 100644 --- a/src/CAN/CommandProcessor.cpp +++ b/src/CAN/CommandProcessor.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "ExpansionManager.h" # include @@ -655,6 +656,10 @@ void CommandProcessor::ProcessReceivedMessage(CanMessageBuffer *buf) noexcept ClosedLoop::ProcessReceivedData(buf->id.Src(), buf->msg.closedLoopData, buf->dataLength); break; + case CanMessageType::event: + Event::Add(buf->msg.event, buf->id.Src(), buf->dataLength); + break; + #if SUPPORT_ACCELEROMETERS case CanMessageType::accelerometerData: Accelerometers::ProcessReceivedData(buf->id.Src(), buf->msg.accelerometerData, buf->dataLength); diff --git a/src/Fans/LocalFan.cpp b/src/Fans/LocalFan.cpp index 3acfce43..5e404258 100644 --- a/src/Fans/LocalFan.cpp +++ b/src/Fans/LocalFan.cpp @@ -70,9 +70,6 @@ void LocalFan::SetHardwarePwm(float pwmVal) noexcept void LocalFan::InternalRefresh(bool checkSensors) noexcept { float reqVal; -#if HAS_SMART_DRIVERS - DriverChannelsBitmap driverChannelsMonitored; -#endif if (sensorsMonitored.IsEmpty()) { @@ -87,11 +84,7 @@ void LocalFan::InternalRefresh(bool checkSensors) noexcept reqVal = 0.0; const bool bangBangMode = (triggerTemperatures[1] <= triggerTemperatures[0]); sensorsMonitored.Iterate - ([&reqVal, bangBangMode, this -#if HAS_SMART_DRIVERS - , &driverChannelsMonitored -#endif - ](unsigned int sensorNum, unsigned int) noexcept + ([&reqVal, bangBangMode, this](unsigned int sensorNum, unsigned int) noexcept { const auto sensor = reprap.GetHeat().FindSensor(sensorNum); if (sensor.IsNotNull()) @@ -120,13 +113,6 @@ void LocalFan::InternalRefresh(bool checkSensors) noexcept reqVal = newVal; } } -#if HAS_SMART_DRIVERS - const int channel = sensor->GetSmartDriversChannel(); - if (channel >= 0) - { - driverChannelsMonitored.SetBit((unsigned int)channel); - } -#endif } } ); @@ -137,12 +123,6 @@ void LocalFan::InternalRefresh(bool checkSensors) noexcept if (lastVal <= 0.0) { // We are turning this fan on -#if HAS_SMART_DRIVERS - if (driverChannelsMonitored.IsNonEmpty()) - { - reprap.GetPlatform().DriverCoolingFansOnOff(driverChannelsMonitored, true); // tell Platform that we have started a fan that cools drivers - } -#endif if (reqVal < 1.0 && blipTime != 0) { // Starting the fan from standstill, so blip the fan @@ -158,12 +138,6 @@ void LocalFan::InternalRefresh(bool checkSensors) noexcept else { blipping = false; -#if HAS_SMART_DRIVERS - if (driverChannelsMonitored.IsNonEmpty() && lastVal > 0.0) - { - reprap.GetPlatform().DriverCoolingFansOnOff(driverChannelsMonitored, false); // tell Platform that we have stopped a fan that cools drivers - } -#endif } lastVal = reqVal; diff --git a/src/Platform/Event.cpp b/src/Platform/Event.cpp index e6cc33b5..022836db 100644 --- a/src/Platform/Event.cpp +++ b/src/Platform/Event.cpp @@ -60,6 +60,19 @@ inline Event::Event(Event *_ecv_null p_next, EventType et, uint16_t p_param, uin return true; } +#if SUPPORT_CAN_EXPANSION + +// Queue an event received via CAN +/*static*/ void Event::Add(const CanMessageEvent& msg, CanAddress src, size_t msgLen) noexcept +{ + // We need to make sure that the text is null terminated + String msgText; + msgText.copy(msg.text, msg.GetMaxTextLength(msgLen)); + (void)AddEvent((EventType)msg.eventType, msg.eventParam, src, msg.deviceNumber, "%s", msgText.c_str()); +} + +#endif + // Get the highest priority event and mark it as being serviced /*static*/ bool Event::StartProcessing() noexcept { diff --git a/src/Platform/Event.h b/src/Platform/Event.h index 81fb2a60..7e120095 100644 --- a/src/Platform/Event.h +++ b/src/Platform/Event.h @@ -32,6 +32,7 @@ #include class VariableSet; +class CanMessageEvent; class Event { @@ -48,6 +49,11 @@ public: // Queue an event, or release it if we have a similar event pending already. Returns true if the event was added, false if it was released. static bool AddEventV(EventType et, uint16_t p_param, CanAddress p_ba, uint8_t devNum, const char *_ecv_array format, va_list vargs) noexcept; +#if SUPPORT_CAN_EXPANSION + // Queue an event received via CAN + static void Add(const CanMessageEvent& msg, CanAddress src, size_t msgLen) noexcept; +#endif + // Get the highest priority event if there is one start processing it static bool StartProcessing() noexcept; diff --git a/src/Platform/Platform.cpp b/src/Platform/Platform.cpp index 58dc2a2a..7c8b9a8b 100644 --- a/src/Platform/Platform.cpp +++ b/src/Platform/Platform.cpp @@ -725,14 +725,9 @@ void Platform::Init() noexcept temperatureShutdownDrivers.Clear(); temperatureWarningDrivers.Clear(); shortToGroundDrivers.Clear(); - openLoadADrivers.Clear(); - openLoadBDrivers.Clear(); - notOpenLoadADrivers.Clear(); - notOpenLoadBDrivers.Clear(); #endif #if HAS_STALL_DETECT - stalledDrivers.Clear(); logOnStallDrivers.Clear(); eventOnStallDrivers.Clear(); #endif @@ -1088,16 +1083,25 @@ void Platform::Spin() noexcept // Check one TMC2660 or TMC2224 for temperature warning or temperature shutdown if (enableValues[nextDriveToPoll] >= 0) // don't poll driver if it is flagged "no poll" { - const StandardDriverStatus stat = SmartDrivers::GetStatus(nextDriveToPoll, true, true); + StandardDriverStatus stat = SmartDrivers::GetStatus(nextDriveToPoll, true, true); const DriversBitmap mask = DriversBitmap::MakeFromBits(nextDriveToPoll); if (stat.ot) { temperatureShutdownDrivers |= mask; } - else if (stat.otpw) + else { - temperatureWarningDrivers |= mask; + temperatureShutdownDrivers &= ~mask; + if (stat.otpw) + { + temperatureWarningDrivers |= mask; + } + else + { + temperatureWarningDrivers &= ~mask; + } } + if (stat.s2ga || stat.s2gb || stat.s2vsa || stat.s2vsb) { shortToGroundDrivers |= mask; @@ -1107,73 +1111,80 @@ void Platform::Spin() noexcept shortToGroundDrivers &= ~mask; } + // Deal with the open load bits // The driver often produces a transient open-load error, especially in stealthchop mode, so we require the condition to persist before we report it. - // Also, false open load indications persist when in standstill, if the phase has zero current in that position - if (stat.ola) + // So clear them unless they have been active for the minimum time. + MillisTimer& timer = openLoadTimers[nextDriveToPoll]; + if (stat.IsAnyOpenLoadBitSet()) { - if (!openLoadATimer.IsRunning()) + if (timer.IsRunning()) { - openLoadATimer.Start(); - openLoadADrivers.Clear(); - notOpenLoadADrivers.Clear(); + if (!timer.Check(OpenLoadTimeout)) + { + stat.ClearOpenLoadBits(); + } } - openLoadADrivers |= mask; - } - else if (openLoadATimer.IsRunning()) - { - notOpenLoadADrivers |= mask; - if (openLoadADrivers.Disjoint(~notOpenLoadADrivers)) + else { - openLoadATimer.Stop(); + timer.Start(); + stat.ClearOpenLoadBits(); } } + else + { + timer.Stop(); + } - if (stat.olb) + const StandardDriverStatus oldStatus = lastEventStatus[nextDriveToPoll]; + lastEventStatus[nextDriveToPoll] = stat; + if (stat.HasNewErrorSince(oldStatus)) { - if (!openLoadBTimer.IsRunning()) + // It's a new error +# if SUPPORT_REMOTE_COMMANDS + if (CanInterface::InExpansionMode()) { - openLoadBTimer.Start(); - openLoadBDrivers.Clear(); - notOpenLoadBDrivers.Clear(); + CanInterface::RaiseEvent(EventType::driver_error, stat.AsU16(), nextDriveToPoll, "", va_list()); + } + else +#endif + { + Event::AddEvent(EventType::driver_error, stat.AsU16(), CanInterface::GetCanAddress(), nextDriveToPoll, ""); } - openLoadBDrivers |= mask; } - else if (openLoadBTimer.IsRunning()) + else if (stat.HasNewWarningSince(oldStatus)) { - notOpenLoadBDrivers |= mask; - if (openLoadBDrivers.Disjoint(~notOpenLoadBDrivers)) + // It's a new warning +# if SUPPORT_REMOTE_COMMANDS + if (CanInterface::InExpansionMode()) { - openLoadBTimer.Stop(); + CanInterface::RaiseEvent(EventType::driver_warning, stat.AsU16(), nextDriveToPoll, "", va_list()); + } + else +#endif + { + Event::AddEvent(EventType::driver_warning, stat.AsU16(), CanInterface::GetCanAddress(), nextDriveToPoll, ""); } } # if HAS_STALL_DETECT - if (stat.stall) + if (stat.HasNewStallSince(oldStatus) && reprap.GetGCodes().IsReallyPrinting()) { - if (stalledDrivers.Disjoint(mask) && reprap.GetGCodes().IsReallyPrinting()) - { - // This stall is new so check whether we need to perform some action in response to the stall + // This stall is new so check whether we need to perform some action in response to the stall # if SUPPORT_REMOTE_COMMANDS - if (CanInterface::InExpansionMode()) - { - CanInterface::RaiseEvent(EventType::driver_stall, 0, nextDriveToPoll, "", va_list()); - } - else + if (CanInterface::InExpansionMode()) + { + CanInterface::RaiseEvent(EventType::driver_stall, 0, nextDriveToPoll, "", va_list()); + } + else # endif - if (eventOnStallDrivers.Intersects(mask)) - { - Event::AddEvent(EventType::driver_stall, 0, CanInterface::GetCanAddress(), nextDriveToPoll, ""); - } - else if (logOnStallDrivers.Intersects(mask)) - { - MessageF(WarningMessage, "Driver %u stalled at Z height %.2f", nextDriveToPoll, (double)reprap.GetMove().LiveCoordinate(Z_AXIS, reprap.GetCurrentTool())); - } + if (eventOnStallDrivers.Intersects(mask)) + { + Event::AddEvent(EventType::driver_stall, 0, CanInterface::GetCanAddress(), nextDriveToPoll, ""); + } + else if (logOnStallDrivers.Intersects(mask)) + { + MessageF(WarningMessage, "Driver %u stalled at Z height %.2f", nextDriveToPoll, (double)reprap.GetMove().LiveCoordinate(Z_AXIS, reprap.GetCurrentTool())); } - stalledDrivers |= mask; - } - else - { - stalledDrivers &= ~mask; } # endif } @@ -1207,15 +1218,13 @@ void Platform::Spin() noexcept { driversPowered = true; #if HAS_SMART_DRIVERS - openLoadATimer.Stop(); - openLoadBTimer.Stop(); + for (size_t i= 0; i < MaxSmartDrivers; ++i) + { + openLoadTimers[i].Stop(); + } temperatureShutdownDrivers.Clear(); temperatureWarningDrivers.Clear(); shortToGroundDrivers.Clear(); - openLoadADrivers.Clear(); - openLoadBDrivers.Clear(); - notOpenLoadADrivers.Clear(); - notOpenLoadBDrivers.Clear(); #endif } @@ -1249,43 +1258,6 @@ void Platform::Spin() noexcept if (now - lastDriverPollMillis > MinimumWarningInterval) { bool reported = false; -#if HAS_SMART_DRIVERS - ReportDrivers(ErrorMessage, shortToGroundDrivers, "short-to-ground", reported); - ReportDrivers(ErrorMessage, temperatureShutdownDrivers, "over temperature shutdown", reported); - if (openLoadATimer.CheckAndStop(OpenLoadTimeout)) - { - ReportDrivers(WarningMessage, openLoadADrivers, "motor phase A may be disconnected", reported); - } - if (openLoadBTimer.CheckAndStop(OpenLoadTimeout)) - { - ReportDrivers(WarningMessage, openLoadBDrivers, "motor phase B may be disconnected", reported); - } - - // Don't warn about a hot driver if we recently turned on a fan to cool it - if (temperatureWarningDrivers.IsNonEmpty()) - { - const DriversBitmap driversMonitored[NumTmcDriversSenseChannels] = -# ifdef DUET_NG - { DriversBitmap::MakeLowestNBits(5), DriversBitmap::MakeLowestNBits(5).ShiftUp(5) }; // first channel is Duet, second is DueX5 -# elif defined(DUET_M) - { DriversBitmap::MakeLowestNBits(5), DriversBitmap::MakeLowestNBits(2).ShiftUp(5) }; // first channel is Duet, second is daughter board -# else - { DriversBitmap::MakeLowestNBits(NumDirectDrivers) }; -# endif - for (unsigned int i = 0; i < NumTmcDriversSenseChannels; ++i) - { - if (driversFanTimers[i].IsRunning()) - { - const bool timedOut = driversFanTimers[i].CheckAndStop(DriverCoolingTimeout); - if (!timedOut) - { - temperatureWarningDrivers &= ~driversMonitored[i]; - } - } - } - ReportDrivers(WarningMessage, temperatureWarningDrivers, "high temperature", reported); - } -#endif #if HAS_VOLTAGE_MONITOR if (numVinOverVoltageEvents != previousVinOverVoltageEvents) @@ -2374,28 +2346,6 @@ GCodeResult Platform::DiagnosticTest(GCodeBuffer& gb, const StringRef& reply, Ou return GCodeResult::ok; } -#if HAS_SMART_DRIVERS - -// This is called when a fan that monitors driver temperatures is turned on when it was off -void Platform::DriverCoolingFansOnOff(DriverChannelsBitmap driverChannelsMonitored, bool on) noexcept -{ - driverChannelsMonitored.Iterate - ([this, on](unsigned int i, unsigned int) noexcept - { - if (on) - { - this->driversFanTimers[i].Start(); - } - else - { - this->driversFanTimers[i].Stop(); - } - } - ); -} - -#endif - // Get the index of the averaging filter for an analog port. // Note, the Thermistor code assumes that this is also the thermistor input number int Platform::GetAveragingFilterIndex(const IoPort& port) const noexcept @@ -3005,8 +2955,10 @@ void Platform::SetEnableValue(size_t driver, int8_t eVal) noexcept temperatureShutdownDrivers &= mask; temperatureWarningDrivers &= mask; shortToGroundDrivers &= mask; - openLoadADrivers &= mask; - openLoadBDrivers &= mask; + if (driver < MaxSmartDrivers) + { + openLoadTimers[driver].Stop(); + } } #endif } @@ -5044,7 +4996,7 @@ void Platform::SendDriversStatus(CanMessageBuffer& buf) noexcept msg->SetStandardFields(MaxSmartDrivers); for (size_t driver = 0; driver < MaxSmartDrivers; ++driver) { - msg->data[driver] = SmartDrivers::GetStatus(driver); + msg->data[driver] = SmartDrivers::GetStatus(driver).AsU32(); } # else msg->SetStandardFields(NumDrivers); diff --git a/src/Platform/Platform.h b/src/Platform/Platform.h index 2ccf6acc..fca11c6a 100644 --- a/src/Platform/Platform.h +++ b/src/Platform/Platform.h @@ -583,7 +583,6 @@ public: #if HAS_SMART_DRIVERS float GetTmcDriversTemperature(unsigned int boardNumber) const noexcept; - void DriverCoolingFansOnOff(DriverChannelsBitmap driverChannelsMonitored, bool on) noexcept; unsigned int GetNumSmartDrivers() const noexcept { return numSmartDrivers; } #endif @@ -758,11 +757,10 @@ private: float minimumMovementSpeed; // minimum allowed movement speed in mm per step clock #if HAS_SMART_DRIVERS - size_t numSmartDrivers; // the number of TMC drivers we have, the remaining are simple enable/step/dir drivers + size_t numSmartDrivers; // the number of TMC drivers we have, the remaining are simple enable/step/dir drivers DriversBitmap temperatureShutdownDrivers, temperatureWarningDrivers, shortToGroundDrivers; - DriversBitmap openLoadADrivers, openLoadBDrivers, notOpenLoadADrivers, notOpenLoadBDrivers; - MillisTimer openLoadATimer, openLoadBTimer; - MillisTimer driversFanTimers[NumTmcDriversSenseChannels]; // driver cooling fan timers + MillisTimer openLoadTimers[MaxSmartDrivers]; + StandardDriverStatus lastEventStatus[MaxSmartDrivers]; uint8_t nextDriveToPoll; #endif @@ -774,7 +772,6 @@ private: #if HAS_STALL_DETECT DriversBitmap logOnStallDrivers, eventOnStallDrivers; - DriversBitmap stalledDrivers; #endif #if defined(__LPC17xx__) diff --git a/src/Version.h b/src/Version.h index fa5b9479..df884df1 100644 --- a/src/Version.h +++ b/src/Version.h @@ -10,7 +10,7 @@ #ifndef VERSION // Note: the complete VERSION string must be in standard version number format and must not contain spaces! This is so that DWC can parse it. -# define MAIN_VERSION "3.4.0beta6+3" +# define MAIN_VERSION "3.4.0beta7" # ifdef USE_CAN0 # define VERSION_SUFFIX "(CAN0)" # else -- cgit v1.2.3