From 5c428f2e6f2f8705ef322bf04d23448c37e70ac2 Mon Sep 17 00:00:00 2001 From: Carl Philipp Klemm <philipp@uvos.xyz> Date: Mon, 11 Dec 2023 16:27:16 +0100 Subject: [PATCH] Random sample mesurement points Add watchdog thread that allows system to restart when system makes no progress --- CMakeLists.txt | 3 ++- expirament.cpp | 50 ++++++++++++++++++++++++++++++++++++++------ expirament.h | 2 ++ expiramentimpl.h | 12 ++++++----- main.cpp | 5 +++++ randomgen.cpp | 25 ++++++++++++++++++++++ randomgen.h | 10 +++++++++ watchdog.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ watchdog.h | 10 +++++++++ 9 files changed, 159 insertions(+), 12 deletions(-) create mode 100644 randomgen.cpp create mode 100644 randomgen.h create mode 100644 watchdog.cpp create mode 100644 watchdog.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e852151..1eff89b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,8 @@ set(SRC_FILES coincell.cpp biocontrol.cpp tokenize.cpp - expirament.cpp) + expirament.cpp + randomgen.cpp) add_executable(${PROJECT_NAME} ${SRC_FILES}) target_link_libraries(${PROJECT_NAME} ${MULTIPLEXER_LIBRARIES} ${SERIALPORT_LIBRARIES} diff --git a/expirament.cpp b/expirament.cpp index f59fbc9..a30def7 100644 --- a/expirament.cpp +++ b/expirament.cpp @@ -4,6 +4,8 @@ #include "expiramentimpl.h" #include "vcpps.h" #include "panic.h" +#include "randomgen.h" +#include "watchdog.h" #include <chrono> #include <filesystem> @@ -66,6 +68,7 @@ bool Expirament::run(size_t startstep, size_t substep) for(globalstep = startstep; globalstep < MAX_LOOP*STEP_COUNT && !stop; ++globalstep) { Log(Log::INFO)<<"System starting globalstep "<<globalstep; + watchdog::reset(); bool ret = step(substep); substep = 0; if(!ret) @@ -140,28 +143,62 @@ bool Expirament::heatMeasureSeq(float fraction) return true; } +std::vector<double> Expirament::createStepSequence(size_t upSteps, size_t downSteps, double low, double high) +{ + std::vector<double> out; + + double closeToLow = low+(high-low)*0.05; + double closeToHigh = low+(high-low)*0.95; + + double last = low; + for(size_t i = 0; i < upSteps - 1; ++i) + { + double step = rd::rand(closeToHigh, last); + out.push_back(step); + last = step; + } + + out.push_back(high); + + last = high; + for(size_t i = 0; i < downSteps - 1; ++i) + { + double step = rd::rand(last, closeToLow); + out.push_back(step); + last = step; + } + + out.push_back(low); + + assert(out.size() == upSteps+downSteps); + + return out; +} + bool Expirament::thermalCycle(size_t count, size_t start) { bool ret = true; + for(size_t i = 0; i < count; ++i) { Log(Log::INFO)<<"Cycle "<<i<<" for globalsetp "<<globalstep; saveStep(i); - if(i % 2 == 0) + if(i == 0) { - ret = heatMeasureSeq(0.5); + std::vector<double> steps = createStepSequence(2, 3, 0, 1); + ret = heatMeasureSeq(steps[0]); if(!ret) return false; - ret = heatMeasureSeq(1); + ret = heatMeasureSeq(steps[1]); if(!ret) return false; - ret = heatMeasureSeq(0.66); + ret = heatMeasureSeq(steps[2]); if(!ret) return false; - ret = heatMeasureSeq(0.33); + ret = heatMeasureSeq(steps[3]); if(!ret) return false; - ret = heatMeasureSeq(0); + ret = heatMeasureSeq(steps[4]); if(!ret) return false; } @@ -221,6 +258,7 @@ bool Expirament::charge(float fraction, bool all) if(current > 0.9) current = 0.9; Log(Log::INFO)<<"Doing charge sequence to "<<fraction<<" at "<<current<<'A'; + watchdog::reset(); for(size_t i = 0; i < coinCells->size(); ++i) { if(all) diff --git a/expirament.h b/expirament.h index 370efd3..86c5af0 100644 --- a/expirament.h +++ b/expirament.h @@ -45,6 +45,8 @@ private: std::filesystem::path createCsvPath(const std::filesystem::path& filename); + static std::vector<double> createStepSequence(size_t upSteps, size_t downSteps, double low = 0, double high = 1); + public: Expirament(std::vector<std::unique_ptr<CoinCell>>* coinCells, Vcpps* psu, float voltage, float current, diff --git a/expiramentimpl.h b/expiramentimpl.h index 9fe7ba4..780c9d4 100644 --- a/expiramentimpl.h +++ b/expiramentimpl.h @@ -10,6 +10,8 @@ bool Expirament::step(size_t startsubstep) saveStep(startsubstep); + std::vector<double> steps = createStepSequence(3, 2, 0, 1); + bool ret = true; switch(globalstep % STEP_COUNT) { @@ -17,35 +19,35 @@ bool Expirament::step(size_t startsubstep) ret = thermalCycle(CYCLES_PER_STEP, startsubstep); break; case 1: - ret = charge(0.0); + ret = charge(steps[0]); ret &= takeMesurements(); break; case 2: ret = thermalCycle(CYCLES_PER_STEP, startsubstep); break; case 3: - ret = charge(0.33); + ret = charge(steps[1]); ret &= takeMesurements(); break; case 4: ret = thermalCycle(CYCLES_PER_STEP, startsubstep); break; case 5: - ret = charge(0.66); + ret = charge(steps[2]); ret &= takeMesurements(); break; case 6: ret = thermalCycle(CYCLES_PER_STEP); break; case 7: - ret = charge(1); + ret = charge(steps[3]); ret &= takeMesurements(); break; case 8: ret = thermalCycle(CYCLES_PER_STEP, startsubstep); break; case 9: - ret = charge(0.5); + ret = charge(steps[4]); ret &= takeMesurements(); break; case 10: diff --git a/main.cpp b/main.cpp index c5c0784..022fda6 100644 --- a/main.cpp +++ b/main.cpp @@ -16,11 +16,13 @@ #include "log.h" #include "heaters.h" #include "multiplexers.h" +#include "randomgen.h" #include "vcpps.h" #include "startupfailure.h" #include "panic.h" #include "options.h" #include "expirament.h" +#include "watchdog.h" void devicefailed(Vcpps& psu, int device, uint16_t serial, int code) { @@ -185,6 +187,9 @@ int main(int argc, char** argv) Log::level = Log::INFO; Log::sendmailLevel = Log::WARN; + rd::init(); + watchdog::init(10*60*60); + Config config; argp_parse(&argp, argc, argv, 0, 0, &config); diff --git a/randomgen.cpp b/randomgen.cpp new file mode 100644 index 0000000..eac93df --- /dev/null +++ b/randomgen.cpp @@ -0,0 +1,25 @@ +#include "randomgen.h" +#include <assert.h> +#include <cstddef> +#include <cstdint> +#include <random> + +static std::default_random_engine randomEngine; + +double rd::rand(double max, double min) +{ + std::uniform_real_distribution<double> dist(min, max); + return dist(randomEngine); +} + +size_t rd::uid() +{ + static std::uniform_int_distribution<size_t> distSt(0, SIZE_MAX); + return distSt(randomEngine); +} + +void rd::init() +{ + std::random_device randomDevice; + randomEngine.seed(randomDevice()); +} diff --git a/randomgen.h b/randomgen.h new file mode 100644 index 0000000..1d81450 --- /dev/null +++ b/randomgen.h @@ -0,0 +1,10 @@ +#pragma once + +#include <cstddef> +namespace rd +{ + double rand(double max = 1, double min = 0); + void init(); + size_t uid(); + +} diff --git a/watchdog.cpp b/watchdog.cpp new file mode 100644 index 0000000..2e1adcc --- /dev/null +++ b/watchdog.cpp @@ -0,0 +1,54 @@ +#include "watchdog.h" + +#include <thread> +#include <atomic> +#include <cstdio> + +#include "log.h" + +namespace watchdog +{ + +static std::atomic<long> timer = 0; +static std::atomic<bool> join = false; +static std::thread* thread = nullptr; +static unsigned long timeout; + +static void threadFn() +{ + Log(Log::INFO)<<"Watchdog started with timeout "<<timeout; + while(!join) + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + if(timer-- < 0) + { + Log(Log::ERROR)<<"Watchdog timeout, exiting"; + std::exit(2); + } + } + Log(Log::INFO)<<"Watchdog shutdown"; +} + +void reset() +{ + timer = timeout; +} + +void init(unsigned long timeoutIn = 600) +{ + exit(); + timeout = timeoutIn; + timer = timeout; + join = false; + thread = new std::thread(&watchdog::threadFn); +} + +void exit() +{ + join = true; + if(thread) + thread->join(); + thread = nullptr; +} + +} diff --git a/watchdog.h b/watchdog.h new file mode 100644 index 0000000..aeacc4c --- /dev/null +++ b/watchdog.h @@ -0,0 +1,10 @@ +#pragma once + +namespace watchdog +{ + +void init(unsigned long timeout); +void reset(); +void exit(); + +} -- GitLab