diff --git a/NodeManager.cpp b/NodeManager.cpp
index 0e0eca1631262c4562027bb2a85e0f67e0c6b18e..bcee7dba9955c185105416e4434117ff70972403 100755
--- a/NodeManager.cpp
+++ b/NodeManager.cpp
@@ -2542,6 +2542,10 @@ void SensorMHZ19::onProcess(Request & request) {
   _send(_msg_service.set(function));
 }
 
+// what to do when receiving an interrupt
+void SensorMHZ19::onInterrupt() {
+}
+
 #endif
 
 /*
@@ -2620,6 +2624,10 @@ void SensorAM2320::onReceive(const MyMessage & message) {
 // what to do when receiving a remote message
 void SensorAM2320::onProcess(Request & request) {
 }
+
+// what to do when receiving an interrupt
+void SensorAM2320::onInterrupt() {
+}
 #endif
 
 /*
@@ -2750,6 +2758,10 @@ void SensorTSL2561::onProcess(Request & request) {
   }
   _send(_msg_service.set(function));
 }
+
+// what to do when receiving an interrupt
+void SensorTSL2561::onInterrupt() {
+}
 #endif
 
 /*
@@ -2764,7 +2776,7 @@ SensorPT100::SensorPT100(NodeManager* node_manager, int child_id, int pin): Sens
   setValueType(TYPE_FLOAT);
 }
 
-//// setter/getter
+// setter/getter
 void SensorPT100::setVoltageRef(float value) {
    _voltageRef = value;
 }
@@ -2784,7 +2796,6 @@ void SensorPT100::onSetup() {
 void SensorPT100::onLoop() {
   // read the PT100 sensor
   int temperature = _PT100->readTemperature(_pin);  
-  
   #if DEBUG == 1
     Serial.print(F("PT100 I="));
     Serial.print(_child_id);
@@ -2809,6 +2820,112 @@ void SensorPT100::onProcess(Request & request) {
   }
   _send(_msg_service.set(function));
 }
+
+// what to do when receiving an interrupt
+void SensorPT100::onInterrupt() {
+}
+#endif
+
+/*
+   SensorDimmer
+*/
+
+#if MODULE_DIMMER == 1
+// contructor
+SensorDimmer::SensorDimmer(NodeManager* node_manager, int child_id, int pin): Sensor(node_manager, child_id, pin) {
+  // set presentation, type and value type
+  setPresentation(S_DIMMER);
+  setType(V_PERCENTAGE);
+}
+
+// setter/getter
+void SensorDimmer::setEasing(int value) {
+  _easing = value;
+}
+void SensorDimmer::setDuration(int value) {
+  _duration = value*1000;
+}
+void SensorDimmer::setStepDuration(int value) {
+  _duration = value;
+}
+
+// what to do during before
+void SensorDimmer::onBefore() {
+  pinMode(_pin, OUTPUT);
+}
+
+// what to do during setup
+void SensorDimmer::onSetup() {
+}
+
+// what to do during loop
+void SensorDimmer::onLoop() {
+}
+
+// what to do as the main task when receiving a message
+void SensorDimmer::onReceive(const MyMessage & message) {
+  if (message.getCommand() == C_SET) {
+    int percentage = message.getInt();
+    // normalize the provided percentage
+    if (percentage < 0) percentage = 0;
+    if (percentage > 100) percentage = 100;
+    fadeTo(percentage);
+    _value_int = percentage;
+  }
+  if (message.getCommand() == C_REQ) {
+    // return the current status
+    _value_int = _percentage;
+  }
+}
+
+// what to do when receiving a remote message
+void SensorDimmer::onProcess(Request & request) {
+   int function = request.getFunction();
+  switch(function) {
+    case 101: setEasing(request.getValueInt()); break;
+    case 102: setDuration(request.getValueInt()); break;
+    case 103: setStepDuration(request.getValueInt()); break;
+    default: return;
+  }
+  _send(_msg_service.set(function));
+}
+
+// what to do when receiving an interrupt
+void SensorDimmer::onInterrupt() {
+}
+
+// fade to the provided value
+void SensorDimmer::fadeTo(int target_percentage) {
+  #if DEBUG == 1
+    Serial.print(F("DIM I="));
+    Serial.print(_child_id);
+    Serial.print(F(" V="));
+    Serial.println(target_percentage);
+  #endif
+  // count how many steps we need to do
+  int steps = _duration / _step_duration;
+  // for each step
+  for (int current_step = 1; current_step <= steps; current_step++) {
+    // calculate the delta between the target value and the current
+    int delta = target_percentage - _percentage;
+    // calculate the smooth transition and adjust it in the 0-255 range
+    int value_to_write = (int)(_getEasing(current_step,_percentage,delta,steps) / 100. * 255);
+    // write to the PWM output
+    analogWrite(_pin,value_to_write);
+    // wait at the end of this step
+    wait(_step_duration);
+  }
+  _percentage = target_percentage;
+}
+
+// for smooth transitions. t: current time, b: beginning value, c: change in value, d: duration
+float SensorDimmer::_getEasing(float t, float b, float c, float d) {
+  if (_easing == EASE_INSINE) return -c * cos(t/d * (M_PI/2)) + c + b;
+  else if (_easing == EASE_OUTSINE) return c * sin(t/d * (M_PI/2)) + b;
+  else if (_easing == EASE_INOUTSINE) return -c/2 * (cos(M_PI*t/d) - 1) + b;
+  else return c*t/d + b;
+}
+
 #endif
 
 /*******************************************
@@ -3149,6 +3266,12 @@ int NodeManager::registerSensor(int sensor_type, int pin, int child_id) {
       // register temperature sensor
       return registerSensor(new SensorPT100(this,child_id,pin));
     }
+  #endif
+   #if MODULE_DIMMER == 1 
+    else if (sensor_type == SENSOR_DIMMER) {
+      // register the dimmer sensor
+      return registerSensor(new SensorDimmer(this,child_id,pin));
+    }
   #endif
   else {
     #if DEBUG == 1
diff --git a/NodeManager.h b/NodeManager.h
index 883b32095deef30606e20d33d5f12d5fc7fe8a63..a0f94b8282fb4904dc013b972f99cf9bc84bf45e 100755
--- a/NodeManager.h
+++ b/NodeManager.h
@@ -190,6 +190,10 @@
 #ifndef MODULE_BMP280
   #define MODULE_BMP280 0
 #endif
+// Enable this module to use one of the following sensors: SENSOR_DIMMER
+#ifndef MODULE_DIMMER
+  #define MODULE_DIMMER 0
+#endif
 
 /***********************************
    Supported Sensors
@@ -299,6 +303,10 @@ enum supported_sensors {
     // BMP280 sensor, return temperature and pressure
     SENSOR_BMP280,
   #endif
+  #if MODULE_DIMMER == 1
+    // Generic dimmer sensor used to drive a pwm output
+    SENSOR_DIMMER,
+  #endif
 };
  
 /***********************************
@@ -376,6 +384,9 @@ enum supported_sensors {
   #include <Adafruit_Sensor.h>
   #include <Adafruit_BMP280.h>
 #endif
+#if MODULE_DIMMER == 1
+  #include <math.h>
+#endif
 
 /*******************************************************************
    Classes
@@ -1222,13 +1233,14 @@ class SensorMHZ19: public Sensor {
     SensorMHZ19(NodeManager* node_manager, int child_id, int pin);
     // set the pins for RX and TX of the SoftwareSerial (default: Rx=6, Tx=7)
     void setRxTx(int rxpin, int txpin);
+    int readCO2();
     // define what to do at each stage of the sketch
     void onBefore();
     void onSetup();
     void onLoop();
     void onReceive(const MyMessage & message);
     void onProcess(Request & request);
-    int readCO2();
+    void onInterrupt();
   protected:
     SoftwareSerial* _ser;
     int _tx_pin = 6;
@@ -1249,6 +1261,7 @@ class SensorAM2320: public Sensor {
     void onLoop();
     void onReceive(const MyMessage & message);
     void onProcess(Request & request);
+    void onInterrupt();
     // constants
     const static int TEMPERATURE = 0;
     const static int HUMIDITY = 1;
@@ -1279,6 +1292,7 @@ class SensorTSL2561: public Sensor {
     void onLoop();
     void onReceive(const MyMessage & message);
     void onProcess(Request & request);
+    void onInterrupt();
     // constants
     const static int ADDR_FLOAT = 0;
     const static int ADDR_LOW = 1;
@@ -1316,12 +1330,50 @@ class SensorPT100: public Sensor {
     void onLoop();
     void onReceive(const MyMessage & message);
     void onProcess(Request & request);
+    void onInterrupt();
   protected:
     DFRobotHighTemperature* _PT100;
     float _voltageRef = 3.3;
 };
 #endif
 
+/*
+    SensorPT100
+*/
+#if MODULE_DIMMER == 1
+class SensorDimmer: public Sensor {
+  public:
+    SensorDimmer(NodeManager* node_manager, int child_id, int pin);
+    // [101] set the effect to use for a smooth transition, can be one of SensorDimmer::EASE_LINEAR, SensorDimmer::EASE_INSINE, SensorDimmer::EASE_OUTSINE, SensorDimmer::EASE_INOUTSINE (default: EASE_LINEAR)
+    void setEasing(int value);
+    // [102] the duration of entire the transition in seconds (default: 1)
+    void setDuration(int value);
+    // [103] the duration of a single step of the transition in milliseconds (default: 100)
+    void setStepDuration(int value);
+    // fade the output from the current value to the target provided in the range 0-100
+    void fadeTo(int value);
+    enum easing {
+      EASE_LINEAR,
+      EASE_INSINE,
+      EASE_OUTSINE,
+      EASE_INOUTSINE,
+    };
+    // define what to do at each stage of the sketch
+    void onBefore();
+    void onSetup();
+    void onLoop();
+    void onReceive(const MyMessage & message);
+    void onProcess(Request & request);
+    void onInterrupt();
+  protected:
+    int _percentage = 0;
+    int _easing = EASE_LINEAR;
+    int _duration = 1000;
+    int _step_duration = 100;
+    float _getEasing(float t, float b, float c, float d);
+};
+#endif
+
 /***************************************
    NodeManager: manages all the aspects of the node
 */
diff --git a/NodeManager.ino b/NodeManager.ino
index 3df7d4749d1c34e584a3d9ea91d0d291d4504046..e42bf43569716623021feac9af3f81754a5cce06 100755
--- a/NodeManager.ino
+++ b/NodeManager.ino
@@ -1,3 +1,4 @@
+
 /*
 NodeManager is intended to take care on your behalf of all those common tasks a MySensors node has to accomplish, speeding up the development cycle of your projects.
 NodeManager includes the following main components:
diff --git a/README.md b/README.md
index 122990f4da49d48b098060466e294ade1276c8f8..e5cb7f1695ea070b45b0219010c1a71026fe993f 100755
--- a/README.md
+++ b/README.md
@@ -209,7 +209,8 @@ The next step is to enable NodeManager's additional functionalities and the modu
 #define MODULE_PT100 0
 // Enable this module to use one of the following sensors: SENSOR_BMP280
 #define MODULE_BMP280 0
-
+// Enable this module to use one of the following sensors: SENSOR_DIMMER
+#define MODULE_DIMMER 0
 ~~~
 
 ### Installing the dependencies
@@ -412,6 +413,7 @@ SENSOR_TSL2561 | TSL2561 sensor, return light in lux
 SENSOR_AM2320 | AM2320 sensors, return temperature/humidity based on the attached AM2320 sensor
 SENSOR_PT100 | High temperature sensor associated with DFRobot Driver, return the temperature in C° from the attached PT100 sensor
 SENSOR_BMP280 | BMP280 sensor, return temperature/pressure based on the attached BMP280 sensor
+SENSOR_DIMMER | Generic dimmer sensor used to drive a pwm output
 
 To register a sensor simply call the NodeManager instance with the sensory type and the pin the sensor is conncted to and optionally a child id. For example:
 ~~~c
@@ -688,6 +690,18 @@ Each sensor class can expose additional methods.
     void setAddress(int value);
 ~~~
 
+* SensorDimmer
+~~~c
+    // [101] set the effect to use for a smooth transition, can be one of SensorDimmer::EASE_LINEAR, SensorDimmer::EASE_INSINE, SensorDimmer::EASE_OUTSINE, SensorDimmer::EASE_INOUTSINE (default: EASE_LINEAR)
+    void setEasing(int value);
+    // [102] the duration of entire the transition in seconds (default: 1)
+    void setDuration(int value);
+    // [103] the duration of a single step of the transition in milliseconds (default: 100)
+    void setStepDuration(int value);
+    // fade the output from the current value to the target provided in the range 0-100
+    void fadeTo(int value);
+~~~
+
 ### Upload your sketch
 
 Upload your sketch to your arduino board as you are used to.
@@ -1350,6 +1364,7 @@ v1.6:
 * Added support for PT100 high temperature sensor
 * Added support for MH-Z19 CO2 sensor
 * Added buil-in rain and soil moisture analog sensors
+* Added support for generic dimmer sensor (PWM output)
 * SensorRainGauge now supports sleep mode
 * SensorSwitch now supports awake mode
 * SensorLatchingRealy now handles automatically both on and off commands
diff --git a/config.h b/config.h
index 0259c24df78b96b7b837544422a15027410d8794..c367a80a6cee31989108e5aa9ae9d187f0a6597f 100755
--- a/config.h
+++ b/config.h
@@ -163,6 +163,8 @@
 #define MODULE_PT100 0
 // Enable this module to use one of the following sensors: SENSOR_BMP280
 #define MODULE_BMP280 0
+// Enable this module to use one of the following sensors: SENSOR_DIMMER
+#define MODULE_DIMMER 0
 
 #endif