diff --git a/esphome/components/pid/climate.py b/esphome/components/pid/climate.py
index 97a98efc20..446c614f14 100644
--- a/esphome/components/pid/climate.py
+++ b/esphome/components/pid/climate.py
@@ -8,6 +8,7 @@ pid_ns = cg.esphome_ns.namespace('pid')
 PIDClimate = pid_ns.class_('PIDClimate', climate.Climate, cg.Component)
 PIDAutotuneAction = pid_ns.class_('PIDAutotuneAction', automation.Action)
 PIDResetIntegralTermAction = pid_ns.class_('PIDResetIntegralTermAction', automation.Action)
+PIDSetControlParametersAction = pid_ns.class_('PIDSetControlParametersAction', automation.Action)
 
 CONF_DEFAULT_TARGET_TEMPERATURE = 'default_target_temperature'
 
@@ -90,3 +91,28 @@ def esp8266_set_frequency_to_code(config, action_id, template_arg, args):
     cg.add(var.set_positive_output(config[CONF_POSITIVE_OUTPUT]))
     cg.add(var.set_negative_output(config[CONF_NEGATIVE_OUTPUT]))
     yield var
+
+
+@automation.register_action(
+    'climate.pid.set_control_parameters',
+    PIDSetControlParametersAction,
+    automation.maybe_simple_id({
+        cv.Required(CONF_ID): cv.use_id(PIDClimate),
+        cv.Required(CONF_KP): cv.templatable(cv.float_),
+        cv.Optional(CONF_KI, default=0.0): cv.templatable(cv.float_),
+        cv.Optional(CONF_KD, default=0.0): cv.templatable(cv.float_),
+    })
+)
+def set_control_parameters(config, action_id, template_arg, args):
+    paren = yield cg.get_variable(config[CONF_ID])
+    var = cg.new_Pvariable(action_id, template_arg, paren)
+
+    kp_template_ = yield cg.templatable(config[CONF_KP], args, float)
+    cg.add(var.set_kp(kp_template_))
+
+    ki_template_ = yield cg.templatable(config[CONF_KI], args, float)
+    cg.add(var.set_ki(ki_template_))
+
+    kd_template_ = yield cg.templatable(config[CONF_KD], args, float)
+    cg.add(var.set_kd(kd_template_))
+    yield var
diff --git a/esphome/components/pid/pid_climate.h b/esphome/components/pid/pid_climate.h
index 12436e225c..f11d768867 100644
--- a/esphome/components/pid/pid_climate.h
+++ b/esphome/components/pid/pid_climate.h
@@ -29,6 +29,9 @@ class PIDClimate : public climate::Climate, public Component {
 
   float get_output_value() const { return output_value_; }
   float get_error_value() const { return controller_.error; }
+  float get_kp() { return controller_.kp; }
+  float get_ki() { return controller_.ki; }
+  float get_kd() { return controller_.kd; }
   float get_proportional_term() const { return controller_.proportional_term; }
   float get_integral_term() const { return controller_.integral_term; }
   float get_derivative_term() const { return controller_.derivative_term; }
@@ -101,5 +104,27 @@ template<typename... Ts> class PIDResetIntegralTermAction : public Action<Ts...>
   PIDClimate *parent_;
 };
 
+template<typename... Ts> class PIDSetControlParametersAction : public Action<Ts...> {
+ public:
+  PIDSetControlParametersAction(PIDClimate *parent) : parent_(parent) {}
+
+  void play(Ts... x) {
+    auto kp = this->kp_.value(x...);
+    auto ki = this->ki_.value(x...);
+    auto kd = this->kd_.value(x...);
+
+    this->parent_->set_kp(kp);
+    this->parent_->set_ki(ki);
+    this->parent_->set_kd(kd);
+  }
+
+ protected:
+  TEMPLATABLE_VALUE(float, kp)
+  TEMPLATABLE_VALUE(float, ki)
+  TEMPLATABLE_VALUE(float, kd)
+
+  PIDClimate *parent_;
+};
+
 }  // namespace pid
 }  // namespace esphome
diff --git a/esphome/components/pid/sensor/__init__.py b/esphome/components/pid/sensor/__init__.py
index cfab23d204..ff8cf15eb5 100644
--- a/esphome/components/pid/sensor/__init__.py
+++ b/esphome/components/pid/sensor/__init__.py
@@ -15,6 +15,9 @@ PID_CLIMATE_SENSOR_TYPES = {
     'DERIVATIVE': PIDClimateSensorType.PID_SENSOR_TYPE_DERIVATIVE,
     'HEAT': PIDClimateSensorType.PID_SENSOR_TYPE_HEAT,
     'COOL': PIDClimateSensorType.PID_SENSOR_TYPE_COOL,
+    'KP': PIDClimateSensorType.PID_SENSOR_TYPE_KP,
+    'KI': PIDClimateSensorType.PID_SENSOR_TYPE_KI,
+    'KD': PIDClimateSensorType.PID_SENSOR_TYPE_KD,
 }
 
 CONF_CLIMATE_ID = 'climate_id'
diff --git a/esphome/components/pid/sensor/pid_climate_sensor.cpp b/esphome/components/pid/sensor/pid_climate_sensor.cpp
index 6241a139f6..f60627b6ac 100644
--- a/esphome/components/pid/sensor/pid_climate_sensor.cpp
+++ b/esphome/components/pid/sensor/pid_climate_sensor.cpp
@@ -35,6 +35,18 @@ void PIDClimateSensor::update_from_parent_() {
     case PID_SENSOR_TYPE_COOL:
       value = clamp(-this->parent_->get_output_value(), 0.0f, 1.0f);
       break;
+    case PID_SENSOR_TYPE_KP:
+      value = this->parent_->get_kp();
+      this->publish_state(value);
+      return;
+    case PID_SENSOR_TYPE_KI:
+      value = this->parent_->get_ki();
+      this->publish_state(value);
+      return;
+    case PID_SENSOR_TYPE_KD:
+      value = this->parent_->get_kd();
+      this->publish_state(value);
+      return;
     default:
       value = NAN;
       break;
diff --git a/esphome/components/pid/sensor/pid_climate_sensor.h b/esphome/components/pid/sensor/pid_climate_sensor.h
index 85759f1eaf..f3774610f8 100644
--- a/esphome/components/pid/sensor/pid_climate_sensor.h
+++ b/esphome/components/pid/sensor/pid_climate_sensor.h
@@ -14,6 +14,9 @@ enum PIDClimateSensorType {
   PID_SENSOR_TYPE_DERIVATIVE,
   PID_SENSOR_TYPE_HEAT,
   PID_SENSOR_TYPE_COOL,
+  PID_SENSOR_TYPE_KP,
+  PID_SENSOR_TYPE_KI,
+  PID_SENSOR_TYPE_KD,
 };
 
 class PIDClimateSensor : public sensor::Sensor, public Component {
diff --git a/tests/test3.yaml b/tests/test3.yaml
index ef464fd5b7..3854a528f4 100644
--- a/tests/test3.yaml
+++ b/tests/test3.yaml
@@ -169,6 +169,13 @@ api:
       then:
         - tm1651.turn_off:
             id: tm1651_battery
+    - service: pid_set_control_parameters
+      then:
+        - climate.pid.set_control_parameters:
+            id: pid_climate
+            kp: 1.0
+            kd: 1.0
+            ki: 1.0
 
 wifi:
   ssid: 'MySSID'
@@ -681,6 +688,17 @@ climate:
     away_config:
       default_target_temperature_low: 16°C
       default_target_temperature_high: 20°C
+  - platform: pid
+    id: pid_climate
+    name: "PID Climate Controller"
+    sensor: ha_hello_world
+    default_target_temperature: 21°C
+    heat_output: my_slow_pwm
+    control_parameters:
+      kp: 0.0
+      ki: 0.0
+      kd: 0.0
+    
 
 cover:
   - platform: endstop
@@ -761,6 +779,11 @@ output:
     id: dimmer1
     gate_pin: GPIO5
     zero_cross_pin: GPIO12
+  - platform: slow_pwm
+    pin: GPIO5
+    id: my_slow_pwm
+    period: 15s
+
 
 mcp23017:
   id: mcp23017_hub