add more checks
This commit is contained in:
parent
778e28aafa
commit
4acafea1b0
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 17.0.0, 2025-06-20T07:57:23. -->
|
<!-- Written by QtCreator 17.0.0, 2025-07-25T08:23:37. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
@ -109,15 +109,15 @@
|
|||||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Ninja
|
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||||
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
||||||
-DCMAKE_BUILD_TYPE:STRING=Build
|
-DQT_MAINTENANCE_TOOL:FILEPATH=/opt/Qt/MaintenanceTool
|
||||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
||||||
-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
|
||||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
|
||||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
||||||
-DQT_MAINTENANCE_TOOL:FILEPATH=/opt/Qt/MaintenanceTool</value>
|
-DCMAKE_BUILD_TYPE:STRING=Build
|
||||||
|
-DCMAKE_GENERATOR:STRING=Ninja
|
||||||
|
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}</value>
|
||||||
<value type="QString" key="CMake.Source.Directory">/home/bartoszek/zephyrproject/zephyr/rims_app</value>
|
<value type="QString" key="CMake.Source.Directory">/home/bartoszek/zephyrproject/zephyr/rims_app</value>
|
||||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/bartoszek/zephyrproject/zephyr/rims_app/build</value>
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/bartoszek/zephyrproject/zephyr/rims_app/build</value>
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
@ -221,14 +221,36 @@
|
|||||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">zephyr_final</value>
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">zephyr_final</value>
|
||||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/bartoszek/zephyrproject/zephyr/rims_app/build/zephyr</value>
|
||||||
</valuemap>
|
</valuemap>
|
||||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">zephyr_pre0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">zephyr_pre0</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/bartoszek/zephyrproject/zephyr/rims_app/build/zephyr</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
|
||||||
</valuemap>
|
</valuemap>
|
||||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||||
@ -289,14 +311,36 @@
|
|||||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">zephyr_final</value>
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">zephyr_final</value>
|
||||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/bartoszek/zephyrproject/zephyr/rims_app/build/zephyr</value>
|
||||||
</valuemap>
|
</valuemap>
|
||||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1">
|
||||||
|
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="QList<int>" key="Analyzer.Valgrind.VisibleErrorKinds"></value>
|
||||||
|
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||||
|
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">zephyr_pre0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">zephyr_pre0</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/bartoszek/zephyrproject/zephyr/rims_app/build/zephyr</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">2</value>
|
||||||
</valuemap>
|
</valuemap>
|
||||||
</data>
|
</data>
|
||||||
<data>
|
<data>
|
||||||
|
|||||||
@ -26,7 +26,7 @@ struct CommunicationCallback {
|
|||||||
/*
|
/*
|
||||||
* Sends bytes back. Bytes represents top level Egress message from each
|
* Sends bytes back. Bytes represents top level Egress message from each
|
||||||
*/
|
*/
|
||||||
virtual std::expected<uint32_t, Error> send(std::span<std::byte> submessage) const = 0;
|
NDIS virtual std::expected<uint32_t, Error> send(std::span<std::byte> submessage) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UartCallback : public CommunicationCallback {
|
struct UartCallback : public CommunicationCallback {
|
||||||
@ -36,7 +36,7 @@ struct UartCallback : public CommunicationCallback {
|
|||||||
const pb_msgdesc_t *_fields; // fields of egress message
|
const pb_msgdesc_t *_fields; // fields of egress message
|
||||||
WireFormatID _sender;
|
WireFormatID _sender;
|
||||||
|
|
||||||
std::expected<uint32_t, Error> send(std::span<std::byte> subsystemMessage) const override;
|
NDIS std::expected<uint32_t, Error> send(std::span<std::byte> subsystemMessage) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IPCCallback : public CommunicationCallback {
|
struct IPCCallback : public CommunicationCallback {
|
||||||
@ -45,14 +45,14 @@ struct IPCCallback : public CommunicationCallback {
|
|||||||
function<void(std::span<std::byte> subsystemMessage)> _copy;
|
function<void(std::span<std::byte> subsystemMessage)> _copy;
|
||||||
std::reference_wrapper<zephyr::semaphore::sem> _sem;
|
std::reference_wrapper<zephyr::semaphore::sem> _sem;
|
||||||
|
|
||||||
std::expected<uint32_t, Error> send(std::span<std::byte> subsystemMessage) const override;
|
NDIS std::expected<uint32_t, Error> send(std::span<std::byte> subsystemMessage) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NoCallback : public CommunicationCallback {
|
struct NoCallback : public CommunicationCallback {
|
||||||
|
|
||||||
// CommunicationCallback interface
|
// CommunicationCallback interface
|
||||||
public:
|
public:
|
||||||
std::expected<uint32_t, Error> send(std::span<std::byte> submessage) const override {
|
NDIS std::expected<uint32_t, Error> send(std::span<std::byte> submessage) const override {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -147,7 +147,7 @@ class MessageDispatcher {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<RequestData, 8> _activeRequests;
|
std::array<RequestData, 8> _activeRequests;
|
||||||
zephyr::mutex::ZepryrSpinlock _lock;
|
zephyr::mutex::ZepryrSpinlock _lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -195,6 +195,5 @@ class MessengerThread : public ZephyrThread {
|
|||||||
std::array<k_poll_event, 8> _events;
|
std::array<k_poll_event, 8> _events;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
};
|
};
|
||||||
} // namespace rims
|
} // namespace rims
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
#include "operation.hpp"
|
#include "operation.hpp"
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
|
#include "ctrl.hpp"
|
||||||
#include "error.hpp"
|
#include "error.hpp"
|
||||||
#include "inplace_vector.hpp"
|
#include "inplace_vector.hpp"
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
#include "messenger.hpp"
|
#include "messenger.hpp"
|
||||||
#include "pid.hpp"
|
#include "pid.hpp"
|
||||||
#include "zephyr.hpp"
|
#include "zephyr.hpp"
|
||||||
#include "ctrl.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@ -73,26 +73,28 @@ void OperationOrchestrator::event_tick() {
|
|||||||
zephyr::semaphore::k_sem_take_now(_tickSem);
|
zephyr::semaphore::k_sem_take_now(_tickSem);
|
||||||
ULOG_INFO("PID update thread");
|
ULOG_INFO("PID update thread");
|
||||||
for (auto &channel : _channels) {
|
for (auto &channel : _channels) {
|
||||||
channel.update();
|
if (auto r = channel.update(); not r){
|
||||||
|
ULOG_WARNING("Operation Orchestrator failed to 'make a tick' for channel %d with err %d/%d", channel.id(), r.error().endpoint, r.error().code);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OperationOrchestrator::event_operationMessageArrived() {
|
void OperationOrchestrator::event_operationMessageArrived() {
|
||||||
static op_IngressMessage req;
|
static op_IngressMessage req;
|
||||||
static op_EgressMessage resp;
|
static op_EgressMessage resp;
|
||||||
constexpr auto service = "operation";
|
constexpr auto service = "operation";
|
||||||
|
|
||||||
ULOG_INFO("%s consume ingress", service);
|
ULOG_INFO("%s consume ingress", service);
|
||||||
operationIngressQueue.try_consume([&](const auto &_req) {
|
operationIngressQueue.try_consume([&](const auto &_req) {
|
||||||
req = _req;
|
req = _req;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
ULOG_INFO("%s execute handler", service);
|
ULOG_INFO("%s execute handler", service);
|
||||||
for (const auto &handler : op_handlers) {
|
for (const auto &handler : op_handlers) {
|
||||||
if (handler.execute(this, req, resp)) break;
|
if (handler.execute(this, req, resp)) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULOG_INFO("%s produce egress", service);
|
ULOG_INFO("%s produce egress", service);
|
||||||
operationEgressQueue.try_produce(resp);
|
operationEgressQueue.try_produce(resp);
|
||||||
}
|
}
|
||||||
@ -116,6 +118,7 @@ std::expected<void, op::error> OperationOrchestrator::handle_initializeChannelRe
|
|||||||
const auto ch = req.ctrl_channels[i];
|
const auto ch = req.ctrl_channels[i];
|
||||||
for (const auto &opchannel : _channels) {
|
for (const auto &opchannel : _channels) {
|
||||||
if (opchannel.usesControlChannel(ch)) {
|
if (opchannel.usesControlChannel(ch)) {
|
||||||
|
ULOG_WARNING("opchannel %d alreadu uses channel %d", opchannel.id(), ch);
|
||||||
return std::unexpected{op::channel_used_multiple_times{}};
|
return std::unexpected{op::channel_used_multiple_times{}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,13 +134,16 @@ std::expected<void, op::error> OperationOrchestrator::handle_initializeChannelRe
|
|||||||
bool used = std::any_of(_channels.begin(), _channels.end(), [id](const OperationChannel &ch) { return ch.id() == id; });
|
bool used = std::any_of(_channels.begin(), _channels.end(), [id](const OperationChannel &ch) { return ch.id() == id; });
|
||||||
if (!used) return id;
|
if (!used) return id;
|
||||||
}
|
}
|
||||||
|
ULOG_WARNING("There are no more valid channel IDs");
|
||||||
return std::unexpected{op::max_number_of_channels{}};
|
return std::unexpected{op::max_number_of_channels{}};
|
||||||
};
|
};
|
||||||
|
|
||||||
// create OperationChannel for channels and id
|
// create OperationChannel for channels and id
|
||||||
auto activatedChannels = TRY(OperationChannel::check_channels(std::span{channels}));
|
auto activatedChannels = TRY(OperationChannel::check_channels(std::span{channels}));
|
||||||
auto id = TRY(find_id());
|
ULOG_DEBUG("all ctrl channels seams to be active");
|
||||||
const auto &newChannel = _channels.emplace_back(activatedChannels, id);
|
auto id = TRY(find_id());
|
||||||
|
const auto &newChannel = _channels.emplace_back(activatedChannels, id);
|
||||||
|
ULOG_INFO("created channel %d", newChannel.id());
|
||||||
|
|
||||||
resp.has_data = true;
|
resp.has_data = true;
|
||||||
resp.data.channel = newChannel.id();
|
resp.data.channel = newChannel.id();
|
||||||
@ -169,10 +175,11 @@ std::expected<void, op::error> OperationOrchestrator::handle_modeRequest(const M
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
TemperatureSlopeMode::TemperatureSlopeMode(PowerControl &pc, PIDController &pid, const op_TemperatureSlopeConfig &config) : _powerControl{pc}, _pid{pid}, _tempChannel{static_cast<uint8_t>(config.temperature_channel_id)}, _slope{config.slope} {
|
TemperatureSlopeMode::TemperatureSlopeMode(PowerControl &pc, PIDController &pid, const op_TemperatureSlopeConfig &config) //
|
||||||
|
: _powerControl{pc}, _pid{pid}, _tempChannel{static_cast<uint8_t>(config.temperature_channel_id)}, _slope{config.slope} {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TemperatureSlopeMode::update() {
|
std::expected<void, op::error> TemperatureSlopeMode::update() {
|
||||||
float currentTemperature = temp(_tempChannel).temperature_c;
|
float currentTemperature = temp(_tempChannel).temperature_c;
|
||||||
|
|
||||||
// Use simple hysteresis to reduce mode-switch jitter
|
// Use simple hysteresis to reduce mode-switch jitter
|
||||||
@ -185,7 +192,7 @@ void TemperatureSlopeMode::update() {
|
|||||||
_heating = false;
|
_heating = false;
|
||||||
}
|
}
|
||||||
const float outputPower = _pid.get().update(targetTemperature().temperature_c, currentTemperature);
|
const float outputPower = _pid.get().update(targetTemperature().temperature_c, currentTemperature);
|
||||||
_powerControl.get().setPower(outputPower);
|
return _powerControl.get().setPower(outputPower);
|
||||||
};
|
};
|
||||||
|
|
||||||
auto useConstantSlope = [&]() {
|
auto useConstantSlope = [&]() {
|
||||||
@ -199,13 +206,13 @@ void TemperatureSlopeMode::update() {
|
|||||||
const float measuredSlope = (dT / dt) * 60.0f; // °C/min
|
const float measuredSlope = (dT / dt) * 60.0f; // °C/min
|
||||||
|
|
||||||
const float outputPower = _pid.get().update(_slope, measuredSlope);
|
const float outputPower = _pid.get().update(_slope, measuredSlope);
|
||||||
_powerControl.get().setPower(outputPower);
|
return _powerControl.get().setPower(outputPower);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (closeToSetpoint) {
|
if (closeToSetpoint) {
|
||||||
useConstantTemperatureAlg();
|
return useConstantTemperatureAlg();
|
||||||
} else {
|
} else {
|
||||||
useConstantSlope();
|
return useConstantSlope();
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastTemperature = currentTemperature;
|
_lastTemperature = currentTemperature;
|
||||||
@ -227,10 +234,11 @@ ConstantTemperatureMode::ConstantTemperatureMode(PowerControl &pc, PIDController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantTemperatureMode::update() {
|
std::expected<void, op::error> ConstantTemperatureMode::update() {
|
||||||
auto currentTemperature = temp(_tempChannel).temperature_c;
|
auto currentTemperature = temp(_tempChannel).temperature_c;
|
||||||
float outputPower = _pid.get().update(targetTemperature().temperature_c, currentTemperature);
|
float outputPower = _pid.get().update(targetTemperature().temperature_c, currentTemperature);
|
||||||
_powerControl.get().setPower(outputPower);
|
CHECK(_powerControl.get().setPower(outputPower));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::expected<void, op::error> OperationOrchestrator::handle_targetTemperatureRequest(const TargetTemperatureRequest &req, TargetTemperatureResponse &resp) {
|
std::expected<void, op::error> OperationOrchestrator::handle_targetTemperatureRequest(const TargetTemperatureRequest &req, TargetTemperatureResponse &resp) {
|
||||||
@ -349,7 +357,7 @@ PowerControl::PowerControl(std::span<uint8_t> channels) : _control_channels{chan
|
|||||||
ULOG_DEBUG("PowerControl start");
|
ULOG_DEBUG("PowerControl start");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PowerControl::setPower(float percent) {
|
std::expected<void, op::error> PowerControl::setPower(float percent) {
|
||||||
ULOG_INFO("Set power %f", (double)percent);
|
ULOG_INFO("Set power %f", (double)percent);
|
||||||
|
|
||||||
for (const auto ch : _control_channels) {
|
for (const auto ch : _control_channels) {
|
||||||
@ -360,6 +368,8 @@ void PowerControl::setPower(float percent) {
|
|||||||
|
|
||||||
MessengerThread::ipc_request(plr);
|
MessengerThread::ipc_request(plr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace rims
|
} // namespace rims
|
||||||
|
|||||||
@ -87,7 +87,7 @@ class PowerControl {
|
|||||||
static std::expected<void, op::error> check_channels(std::span<uint8_t> channels);
|
static std::expected<void, op::error> check_channels(std::span<uint8_t> channels);
|
||||||
PowerControl(std::span<uint8_t> channels);
|
PowerControl(std::span<uint8_t> channels);
|
||||||
|
|
||||||
void setPower(float percent);
|
NDIS std::expected<void, op::error> setPower(float percent);
|
||||||
|
|
||||||
bool usesChannel(uint8_t ch) const {
|
bool usesChannel(uint8_t ch) const {
|
||||||
return std::find(_control_channels.begin(), _control_channels.end(), ch) != _control_channels.end();
|
return std::find(_control_channels.begin(), _control_channels.end(), ch) != _control_channels.end();
|
||||||
@ -108,7 +108,8 @@ class DisabledMode : public ModeStrategy {
|
|||||||
public:
|
public:
|
||||||
DisabledMode() {
|
DisabledMode() {
|
||||||
}
|
}
|
||||||
void update() {
|
NDIS std::expected<void, op::error> update() {
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
float targetTemperature() const = delete;
|
float targetTemperature() const = delete;
|
||||||
void setTargetTemperature(float temp) = delete;
|
void setTargetTemperature(float temp) = delete;
|
||||||
@ -125,7 +126,7 @@ class ConstantTemperatureMode : public ModeStrategy {
|
|||||||
ConstantTemperatureMode(ConstantTemperatureMode &&) = default;
|
ConstantTemperatureMode(ConstantTemperatureMode &&) = default;
|
||||||
ConstantTemperatureMode &operator=(ConstantTemperatureMode &&) = default;
|
ConstantTemperatureMode &operator=(ConstantTemperatureMode &&) = default;
|
||||||
|
|
||||||
void update();
|
NDIS std::expected<void, op::error> update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// reference wrapper allows this class to be movable
|
/// reference wrapper allows this class to be movable
|
||||||
@ -145,7 +146,7 @@ class TemperatureSlopeMode : public ModeStrategy {
|
|||||||
TemperatureSlopeMode(TemperatureSlopeMode &&) = default;
|
TemperatureSlopeMode(TemperatureSlopeMode &&) = default;
|
||||||
TemperatureSlopeMode &operator=(TemperatureSlopeMode &&) = default;
|
TemperatureSlopeMode &operator=(TemperatureSlopeMode &&) = default;
|
||||||
|
|
||||||
void update();
|
NDIS std::expected<void, op::error> update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// reference wrapper allows this class to be movable
|
/// reference wrapper allows this class to be movable
|
||||||
@ -209,8 +210,8 @@ class OperationChannel {
|
|||||||
return _ownId;
|
return _ownId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void update() {
|
NDIS std::expected<void, op::error> update() {
|
||||||
std::visit([](auto &mode) { mode.update(); }, _mode);
|
return std::visit([](auto &mode) { return mode.update(); }, _mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
NDIS std::expected<void, op::error> handle_targetTemperatureRequest(const TargetTemperatureRequest &request, TargetTemperatureResponse &resp);
|
NDIS std::expected<void, op::error> handle_targetTemperatureRequest(const TargetTemperatureRequest &request, TargetTemperatureResponse &resp);
|
||||||
@ -247,7 +248,10 @@ class OperationOrchestrator {
|
|||||||
|
|
||||||
NDIS std::expected<void, op::error> channelValid(uint8_t ch) const {
|
NDIS std::expected<void, op::error> channelValid(uint8_t ch) const {
|
||||||
auto found = std::find_if(_channels.begin(), _channels.end(), [&](const OperationChannel &opch) { return opch.id() == ch; });
|
auto found = std::find_if(_channels.begin(), _channels.end(), [&](const OperationChannel &opch) { return opch.id() == ch; });
|
||||||
if (found != _channels.end()) return std::unexpected{op::channel_not_found{}};
|
if (found == _channels.end()) {
|
||||||
|
ULOG_WARNING("channel %d not found", ch);
|
||||||
|
return std::unexpected{op::channel_not_found{}};
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -260,6 +264,7 @@ class OperationOrchestrator {
|
|||||||
auto found = std::find_if(_channels.begin(), _channels.end(), [&](const OperationChannel &opch) { return opch.id() == ch; });
|
auto found = std::find_if(_channels.begin(), _channels.end(), [&](const OperationChannel &opch) { return opch.id() == ch; });
|
||||||
|
|
||||||
if (found == _channels.end()) {
|
if (found == _channels.end()) {
|
||||||
|
ULOG_WARNING("channel %d not found", ch);
|
||||||
return std::unexpected{op::channel_not_found{}};
|
return std::unexpected{op::channel_not_found{}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,6 +275,7 @@ class OperationOrchestrator {
|
|||||||
auto found = std::find_if(_channels.begin(), _channels.end(), [&](const OperationChannel &opch) { return opch.id() == ch; });
|
auto found = std::find_if(_channels.begin(), _channels.end(), [&](const OperationChannel &opch) { return opch.id() == ch; });
|
||||||
|
|
||||||
if (found == _channels.end()) {
|
if (found == _channels.end()) {
|
||||||
|
ULOG_WARNING("channel %d not found", ch);
|
||||||
return std::unexpected{op::channel_not_found{}};
|
return std::unexpected{op::channel_not_found{}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -92,7 +93,9 @@ TemperatureSampler::TemperatureSampler(uint8_t channel) : _temperature{0.05}, _c
|
|||||||
k_work_init(&_sampleWork, TemperatureSampler::sample_work_handler);
|
k_work_init(&_sampleWork, TemperatureSampler::sample_work_handler);
|
||||||
|
|
||||||
select_channel(_channel);
|
select_channel(_channel);
|
||||||
calibration();
|
if (not calibration()) {
|
||||||
|
ULOG_WARNING("Temperature sampler channel %d calibration failed", _channel);
|
||||||
|
}
|
||||||
|
|
||||||
_broadcastTimer.start();
|
_broadcastTimer.start();
|
||||||
_samplerTimer.start();
|
_samplerTimer.start();
|
||||||
@ -227,6 +230,8 @@ float TemperatureSampler::adc2CelciusWeight() const {
|
|||||||
const auto adcMax = this->_referenceAdcMax.filtered();
|
const auto adcMax = this->_referenceAdcMax.filtered();
|
||||||
const auto adcMin = this->_referenceAdcMin.filtered();
|
const auto adcMin = this->_referenceAdcMin.filtered();
|
||||||
|
|
||||||
|
assert(adcMin != adcMax);
|
||||||
|
|
||||||
return (tempMax - tempMin) / static_cast<float>(adcMin - adcMax);
|
return (tempMax - tempMin) / static_cast<float>(adcMin - adcMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,15 +308,25 @@ std::expected<adc_sample, temperature::error> TemperatureSampler::adc() {
|
|||||||
constexpr auto ADC_RESOLUTION = 12;
|
constexpr auto ADC_RESOLUTION = 12;
|
||||||
const adc_dt_spec adc_spec = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 0);
|
const adc_dt_spec adc_spec = ADC_DT_SPEC_GET_BY_IDX(DT_PATH(zephyr_user), 0);
|
||||||
const auto nsamples = oversampling();
|
const auto nsamples = oversampling();
|
||||||
const adc_sequence_options options = {
|
|
||||||
.interval_us = 100,
|
const adc_sequence_options options = {
|
||||||
.callback = nullptr,
|
.interval_us = 100,
|
||||||
.user_data = nullptr,
|
.callback = nullptr,
|
||||||
.extra_samplings = static_cast<uint16_t>(nsamples - 1),
|
.user_data = nullptr,
|
||||||
|
.extra_samplings = static_cast<uint16_t>(nsamples - 1),
|
||||||
};
|
};
|
||||||
samples.resize(nsamples, 0);
|
samples.resize(nsamples, 0);
|
||||||
|
|
||||||
adc_sequence sequence = {.options = &options, .channels = BIT(15), .buffer = samples.data(), .buffer_size = samples.size() * sizeof(adc_sample), .resolution = ADC_RESOLUTION, .oversampling = 0, .calibrate = false};
|
const adc_sequence sequence = {//
|
||||||
|
.options = &options,
|
||||||
|
.channels = BIT(15),
|
||||||
|
.buffer = samples.data(),
|
||||||
|
.buffer_size = samples.size() * sizeof(adc_sample),
|
||||||
|
.resolution = ADC_RESOLUTION,
|
||||||
|
.oversampling = 0,
|
||||||
|
.calibrate = false
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @retval -EINVAL If a parameter with an invalid value has been provided.
|
* @retval -EINVAL If a parameter with an invalid value has been provided.
|
||||||
* @retval -ENOMEM If the provided buffer is to small to hold the results
|
* @retval -ENOMEM If the provided buffer is to small to hold the results
|
||||||
@ -324,7 +339,6 @@ std::expected<adc_sample, temperature::error> TemperatureSampler::adc() {
|
|||||||
* in the buffer, but at least some of them were taken with
|
* in the buffer, but at least some of them were taken with
|
||||||
* an extra delay compared to what was scheduled.
|
* an extra delay compared to what was scheduled.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
auto ret = adc_read_dt(&adc_spec, &sequence);
|
auto ret = adc_read_dt(&adc_spec, &sequence);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
if (not _faultTP) {
|
if (not _faultTP) {
|
||||||
|
|||||||
@ -111,7 +111,7 @@ class TemperatureSampler {
|
|||||||
TemperatureSampler &operator=(TemperatureSampler &&) = delete;
|
TemperatureSampler &operator=(TemperatureSampler &&) = delete;
|
||||||
|
|
||||||
void tick() ;
|
void tick() ;
|
||||||
std::expected<void, temperature::error> calibration() ;
|
NDIS std::expected<void, temperature::error> calibration() ;
|
||||||
|
|
||||||
bool pending() const {
|
bool pending() const {
|
||||||
return _samplePending;
|
return _samplePending;
|
||||||
@ -134,8 +134,8 @@ class TemperatureSampler {
|
|||||||
float adc2CelciusWeight() const;
|
float adc2CelciusWeight() const;
|
||||||
Temperature_c adcToTemperature(uint32_t adc_value) const;
|
Temperature_c adcToTemperature(uint32_t adc_value) const;
|
||||||
|
|
||||||
std::expected<adc_sample, temperature::error> adcWithCalibration();
|
NDIS std::expected<adc_sample, temperature::error> adcWithCalibration();
|
||||||
std::expected<adc_sample, temperature::error> adc();
|
NDIS std::expected<adc_sample, temperature::error> adc();
|
||||||
|
|
||||||
void do_sample() ;
|
void do_sample() ;
|
||||||
struct k_work _sampleWork{};
|
struct k_work _sampleWork{};
|
||||||
@ -191,14 +191,13 @@ class TemperatureSamplerOrchestrator {
|
|||||||
TemperatureSamplerOrchestrator();
|
TemperatureSamplerOrchestrator();
|
||||||
void loop();
|
void loop();
|
||||||
|
|
||||||
[[nodiscard]] std::expected<void, temperature::error> handle_getTemperatureRequest(const GetTemperatureRequest &req, GetTemperatureResponse &resp) const;
|
NDIS std::expected<void, temperature::error> handle_getTemperatureRequest(const GetTemperatureRequest &req, GetTemperatureResponse &resp) const;
|
||||||
[[nodiscard]] std::expected<void, temperature::error> handle_activeChannelsRequest(const GetActiveChannelsRequest &req, GetActiveChannelsResponse &resp) const;
|
NDIS std::expected<void, temperature::error> handle_activeChannelsRequest(const GetActiveChannelsRequest &req, GetActiveChannelsResponse &resp) const;
|
||||||
[[nodiscard]] std::expected<void, temperature::error> handle_samplerConfigRequest(const SamplerConfigRequest &req, SamplerConfigResponse &resp);
|
NDIS std::expected<void, temperature::error> handle_samplerConfigRequest(const SamplerConfigRequest &req, SamplerConfigResponse &resp);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// events handled in main loop
|
// events handled in main loop
|
||||||
void event_messageArrived();
|
void event_messageArrived();
|
||||||
|
|
||||||
void action_samplersTick();
|
void action_samplersTick();
|
||||||
|
|
||||||
std::array<TemperatureSampler, temperatureChannelsNr> _temperatureSamplerChannels;
|
std::array<TemperatureSampler, temperatureChannelsNr> _temperatureSamplerChannels;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user