diff --git a/CMakeLists.txt b/CMakeLists.txt
index e8521515240a52a85eec3605a256414d22755392..1eff89b1d29b8af692c38ef11a4966972c82a2c8 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 f59fbc95b47369ba5c282ec3fdd8f610b840f632..a30def72b6dbec580add0e2ebdf99fe9cdfbe031 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 370efd37fb74563aff08ab56e2f94799027cd37e..86c5af0225725e587a9aefb7a4ea693df7ef74e1 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 9fe7ba4fab0176567320369aa116e90ccca2e4d9..780c9d451106f19d8d6cafa89536e598aab86885 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 c5c078415c152e169523559457aaf56d8dea200a..022fda6de0f389be14d4bb254975a0fda4b910eb 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 0000000000000000000000000000000000000000..eac93dfc1e6ea0b0fa4673d78976278677fe0a66
--- /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 0000000000000000000000000000000000000000..1d81450a4db9613e1bb87912c2c503e86077a0a7
--- /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 0000000000000000000000000000000000000000..2e1adcc9d213c25aa9baa0498fd3d1ee6c78424a
--- /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 0000000000000000000000000000000000000000..aeacc4c1d4a514468fc8cc504bcb1d213e32b7f2
--- /dev/null
+++ b/watchdog.h
@@ -0,0 +1,10 @@
+#pragma once
+
+namespace watchdog
+{
+
+void init(unsigned long timeout);
+void reset();
+void exit();
+
+}