diff --git a/firmware/drivers/pid_controller/.pid_controller.cpp.swp b/firmware/drivers/pid_controller/.pid_controller.cpp.swp
new file mode 100644
index 0000000000000000000000000000000000000000..23cc8998492688172b9c42322ffacccc4822b9fe
Binary files /dev/null and b/firmware/drivers/pid_controller/.pid_controller.cpp.swp differ
diff --git a/firmware/drivers/pid_controller/pid_controller.cpp b/firmware/drivers/pid_controller/pid_controller.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3ed79ba8f2fb578b6c8e1ee0b9752bd6ae35a805
--- /dev/null
+++ b/firmware/drivers/pid_controller/pid_controller.cpp
@@ -0,0 +1,83 @@
+#include <pid_controller.hpp>
+#include <algorithm>
+#include <ltc6992.hpp>
+
+//define statics
+double Pid_controller::setpoint_=0.; //target temperature in °C
+double Pid_controller::output_=0.05; //output to LTC6992
+std::vector<double> Pid_controller::pid_vec_ = {0.,0.,0.}; //current values of P I D
+std::vector<double> Pid_controller::kpid_vec_ = {0., 0., 0.}; //coefficients Kp Ki Kd
+double Pid_controller::I_reset_ = 0.; //reset value of I
+double Pid_controller::I_reset_errsq_ = 0.; //value of error*error above which the I-term is held in reset
+
+
+Pid_controller::
+
+
+void Pid_controller::init(double setpoint, std::vector<double> kpid, double I_reset, double I_reset_errsq){
+    setpoint_ = setpoint;
+    kpid_ = kpid;
+    I_reset_ = I_reset;
+    I_reset_errsq_ = I_reset_errsq;
+}
+
+void Pid_controller::update_pid(double temperature){
+    //calculate error from setpoint
+    double error = setpoint_ - temperature;
+    //update P,I,D
+    pid_vec_[2] = error - pid_vec_[0];
+    (error*error < I_reset_errsq_) ? pid_vec_[1] += error : pid_vec_[1] = I_reset_;
+    pid_vec_[0] = error;
+    //calculate output
+    output_ = kpid_vec_[0]*pid_vec_[0] + kpid_vec_[1]*pid_vec_[1] + kpid_vec_[2]*pid_vec_[2];
+    //clamp output to rails
+    output_ = std::max(output_, 0.1);
+    output_ = std::min(output_, 0.9);
+    //send value to controller
+    Ltc6992::set_level(output_);
+}
+
+void Pid_controller::set_Kp(double Kp){
+    kpid_vec_[0] = Kp;
+}
+
+void Pid_controller::set_Ki(double Ki){
+    kpid_vec_[1] = Ki;
+}
+
+void Pid_controller::set_Kd(double Kd){
+    kpid_vec_[2] = Kd;
+}
+
+void Pid_controller::set_I_reset(double I_reset){
+    I_reset_ = I_reset;
+    pid_vec_[1] = I_reset;
+}
+
+void Pid_controller::set_I_reset_errsq(double I_reset_errsq){
+    I_reset_errsq_ = I_reset_errsq;
+}
+
+void Pid_controller::set_setpoint(double temperature){
+    setpoint_ = temperature;
+}
+
+std::vector<double> Pid_controller::get_kpid() const{
+    return kpid_vec_;
+}
+
+std::vector<double> Pid_controller::get_pid() const{
+    return pid_vec_;
+}
+
+double Pid_controller::get_output() const{
+    return output_;
+}
+
+double Pid_controller::get_I_reset() const{
+    return I_reset_;
+}
+
+double Pid_controller::get_setpoint() const{
+    return setpoint_;
+}
diff --git a/firmware/drivers/pid_controller/pid_controller.hpp b/firmware/drivers/pid_controller/pid_controller.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..95a89c5845e2b9455744dd26abf16b4a0a02482d
--- /dev/null
+++ b/firmware/drivers/pid_controller/pid_controller.hpp
@@ -0,0 +1,33 @@
+#ifndef PID_CONTROLLER_HPP_INCLUDED
+#define PID_CONTROLLER_HPP_INCLUDED
+#include <ltc6992.hpp>
+#include <vector>
+
+class Pid_controller{
+public:
+    static void init(double setpoint, std::vector<double> kpid, double I_reset, double I_reset_errsq);
+    static void update_pid(double temperature);
+
+    static void set_Kp(double Kp);
+    static void set_Ki(double Ki);
+    static void set_Kd(double Kd);
+    static void set_I_reset(double I_reset);
+    static void set_I_reset_errsq(double I_reset_errsq);
+    static void set_setpoint(double temperature);
+
+    static std::vector<double> get_kpid() const;
+    static std::vector<double> get_pid() const;
+    static double get_output() const;
+    static double get_I_reset() const;
+    static double get_setpoint() const;
+
+private:
+    static double setpoint_; //target temperature in °C
+    static double output_; //output to LTC6992
+    static std::vector<double> pid_vec_; //current values of P I D
+    static std::vector<double> kpid_vec_; //coefficients Kp Ki Kd
+    static double I_reset_; //reset value of I
+    static double I_reset_errsq_; //value of error*error above which the I-term is held in reset
+};
+
+#endif