diff --git a/NodeManager.cpp b/NodeManager.cpp
index 32a122568428e5840e5c9a835b426bf9054a6206..bca261447b9720e8f09a725db13ade1e17929c6c 100644
--- a/NodeManager.cpp
+++ b/NodeManager.cpp
@@ -4,6 +4,30 @@
 
 #include "NodeManager.h"
 
+/***************************************
+   Global functions
+*/
+
+// return vcc in V
+float getVcc() {
+  // Measure Vcc against 1.1V Vref
+  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+    ADMUX = (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
+  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
+    ADMUX = (_BV(MUX5) | _BV(MUX0));
+  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
+    ADMUX = (_BV(MUX3) | _BV(MUX2));
+  #else
+    ADMUX = (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
+  #endif
+  // Vref settle
+  delay(70);
+  // Do conversion
+  ADCSRA |= _BV(ADSC);
+  while (bit_is_set(ADCSRA, ADSC)) {};
+  // return Vcc in mV
+  return (float)((1125300UL) / ADC) / 1000;
+}
 
 /***************************************
    PowerManager
@@ -58,6 +82,7 @@ void PowerManager::powerOff() {
   digitalWrite(_vcc_pin, LOW);
 }
 
+
 /******************************************
     Sensors
 */
@@ -429,6 +454,205 @@ void SensorThermistor::onReceive(const MyMessage & message) {
   onLoop();
 }
 
+
+/*
+   SensorML8511
+*/
+
+// contructor
+SensorML8511::SensorML8511(int child_id, int pin): Sensor(child_id, pin) {
+  // set presentation, type and value type
+  setPresentation(S_UV);
+  setType(V_UV);
+  setValueType(TYPE_FLOAT);
+}
+
+// what do to during before
+void SensorML8511::onBefore() {
+  // set the pin as input
+  pinMode(_pin, INPUT);
+}
+
+// what do to during setup
+void SensorML8511::onSetup() {
+  onLoop();
+}
+
+// what do to during loop
+void SensorML8511::onLoop() {
+  // read the voltage 
+  int uvLevel = analogRead(_pin);
+  int refLevel = getVcc()*1024/3.3;
+  //Use the 3.3V power pin as a reference to get a very accurate output value from sensor
+  float outputVoltage = 3.3 / refLevel * uvLevel;
+  //Convert the voltage to a UV intensity level
+  float uvIntensity = _mapfloat(outputVoltage, 0.99, 2.8, 0.0, 15.0); 
+  #if DEBUG == 1
+    Serial.print(F("UV I="));
+    Serial.print(_child_id);
+    Serial.print(F(" V="));
+    Serial.print(outputVoltage);
+    Serial.print(F(" I="));
+    Serial.println(uvIntensity);
+  #endif
+  // store the value
+  _value_float = uvIntensity;
+}
+
+// what do to as the main task when receiving a message
+void SensorML8511::onReceive(const MyMessage & message) {
+  onLoop();
+}
+
+// The Arduino Map function but for floats
+float SensorML8511::_mapfloat(float x, float in_min, float in_max, float out_min, float out_max) {
+  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
+}
+
+/*
+ * SensorMQ
+ */
+SensorMQ::SensorMQ(int child_id, int pin): Sensor(child_id,pin) {
+  setPresentation(S_AIR_QUALITY);
+  setType(V_LEVEL);
+}
+
+//setter/getter
+void SensorMQ::setRlValue(float value) {
+  _rl_value = value;
+}
+void SensorMQ::setRoValue(float value) {
+  _ro = value;
+}
+void SensorMQ::setCleanAirFactor(float value) {
+  _ro_clean_air_factor = value;
+}
+void SensorMQ::setCalibrationSampleTimes(int value) {
+  _calibration_sample_times = value;
+}
+void SensorMQ::setCalibrationSampleInterval(int value){
+  _calibration_sample_interval = value;
+}
+void SensorMQ::setReadSampleTimes(int value) {
+  _read_sample_times = value;
+}
+void SensorMQ::setReadSampleInterval(int value) {
+  _read_sample_interval = value;
+}
+void SensorMQ::setLPGCurve(float *value) {
+  _LPGCurve[0] = value[0];
+  _LPGCurve[2] = value[1];
+  _LPGCurve[2] = value[2];
+}
+void SensorMQ::setCOCurve(float *value) {
+  _COCurve[0] = value[0];
+  _COCurve[2] = value[1];
+  _COCurve[2] = value[2];
+}
+void SensorMQ::setSmokeCurve(float *value) {
+  _SmokeCurve[0] = value[0];
+  _SmokeCurve[2] = value[1];
+  _SmokeCurve[2] = value[2];
+}
+
+// what do to during before
+void SensorMQ::onBefore() {
+  // prepare the pin for input
+  pinMode(_pin, INPUT);
+}
+
+// what do to during setup
+void SensorMQ::onSetup() {
+  _ro = _MQCalibration();
+}
+
+// what do to during loop
+void SensorMQ::onLoop() {
+  if (_pin == -1) return;
+  // calculate rs/ro
+  float mq = _MQRead()/_ro;
+  // calculate the ppm
+  float lpg = _MQGetGasPercentage(mq,_gas_lpg);
+  float co = _MQGetGasPercentage(mq,_gas_co);
+  float smoke = _MQGetGasPercentage(mq,_gas_smoke);
+  // assign to the value the requested gas
+  uint16_t value;
+  if (_target_gas == _gas_lpg) value = lpg;
+  if (_target_gas == _gas_co) value = co;
+  if (_target_gas == _gas_smoke) value = smoke;
+  #if DEBUG == 1
+    Serial.print(F("MQ I="));
+    Serial.print(_child_id);
+    Serial.print(F(" V="));
+    Serial.print(value);
+    Serial.print(F(" LPG="));
+    Serial.print(lpg);
+    Serial.print(F(" CO="));
+    Serial.print(co);
+    Serial.print(F(" SMOKE="));
+    Serial.println(smoke);
+  #endif
+  // store the value
+  _value_int = (int16_t)ceil(value);
+}
+
+// what do to as the main task when receiving a message
+void SensorMQ::onReceive(const MyMessage & message) {
+  onLoop();
+}
+
+// returns the calculated sensor resistance
+float SensorMQ::_MQResistanceCalculation(int raw_adc) {
+  return ( ((float)_rl_value*(1023-raw_adc)/raw_adc));
+}
+
+//  This function assumes that the sensor is in clean air
+float SensorMQ::_MQCalibration() {
+  int i;
+  float val=0;
+  //take multiple samples
+  for (i=0; i< _calibration_sample_times; i++) {  
+    val += _MQResistanceCalculation(analogRead(_pin));
+    delay(_calibration_sample_interval);
+  }
+  //calculate the average value
+  val = val/_calibration_sample_times;                   
+  //divided by RO_CLEAN_AIR_FACTOR yields the Ro
+  val = val/_ro_clean_air_factor;
+  //according to the chart in the datasheet
+  return val;
+}
+
+// This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
+float SensorMQ::_MQRead() {
+  int i;
+  float rs=0;
+  for (i=0; i<_read_sample_times; i++) {
+    rs += _MQResistanceCalculation(analogRead(_pin));
+    delay(_read_sample_interval);
+  }
+  rs = rs/_read_sample_times;
+  return rs;
+}
+
+// This function passes different curves to the MQGetPercentage function which calculates the ppm (parts per million) of the target gas.
+int SensorMQ::_MQGetGasPercentage(float rs_ro_ratio, int gas_id) {
+  if ( gas_id == _gas_lpg ) {
+    return _MQGetPercentage(rs_ro_ratio,_LPGCurve);
+  } else if ( gas_id == _gas_co) {
+    return _MQGetPercentage(rs_ro_ratio,_COCurve);
+  } else if ( gas_id == _gas_smoke) {
+    return _MQGetPercentage(rs_ro_ratio,_SmokeCurve);
+  }
+  return 0;
+}
+
+// returns ppm of the target gas
+int SensorMQ::_MQGetPercentage(float rs_ro_ratio, float *pcurve) {
+  return (pow(10,( ((log10(rs_ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
+}
+
+
 /*
    SensorDigitalInput
 */
@@ -1015,150 +1239,6 @@ void SensorBME280::onReceive(const MyMessage & message) {
 }
 #endif
 
-/*
- * SensorMQ
- */
-SensorMQ::SensorMQ(int child_id, int pin): Sensor(child_id,pin) {
-  setPresentation(S_AIR_QUALITY);
-  setType(V_LEVEL);
-}
-
-//setter/getter
-void SensorMQ::setRlValue(float value) {
-  _rl_value = value;
-}
-void SensorMQ::setRoValue(float value) {
-  _ro = value;
-}
-void SensorMQ::setCleanAirFactor(float value) {
-  _ro_clean_air_factor = value;
-}
-void SensorMQ::setCalibrationSampleTimes(int value) {
-  _calibration_sample_times = value;
-}
-void SensorMQ::setCalibrationSampleInterval(int value){
-  _calibration_sample_interval = value;
-}
-void SensorMQ::setReadSampleTimes(int value) {
-  _read_sample_times = value;
-}
-void SensorMQ::setReadSampleInterval(int value) {
-  _read_sample_interval = value;
-}
-void SensorMQ::setLPGCurve(float *value) {
-  _LPGCurve[0] = value[0];
-  _LPGCurve[2] = value[1];
-  _LPGCurve[2] = value[2];
-}
-void SensorMQ::setCOCurve(float *value) {
-  _COCurve[0] = value[0];
-  _COCurve[2] = value[1];
-  _COCurve[2] = value[2];
-}
-void SensorMQ::setSmokeCurve(float *value) {
-  _SmokeCurve[0] = value[0];
-  _SmokeCurve[2] = value[1];
-  _SmokeCurve[2] = value[2];
-}
-
-// what do to during before
-void SensorMQ::onBefore() {
-  // prepare the pin for input
-  pinMode(_pin, INPUT);
-}
-
-// what do to during setup
-void SensorMQ::onSetup() {
-  _ro = _MQCalibration();
-  onLoop();
-}
-
-// what do to during loop
-void SensorMQ::onLoop() {
-  if (_pin == -1) return;
-  // calculate rs/ro
-  float mq = _MQRead()/_ro;
-  // calculate the ppm
-  float lpg = _MQGetGasPercentage(mq,_gas_lpg);
-  float co = _MQGetGasPercentage(mq,_gas_co);
-  float smoke = _MQGetGasPercentage(mq,_gas_smoke);
-  // assign to the value the requested gas
-  uint16_t value;
-  if (_target_gas == _gas_lpg) value = lpg;
-  if (_target_gas == _gas_co) value = co;
-  if (_target_gas == _gas_smoke) value = smoke;
-  #if DEBUG == 1
-    Serial.print(F("MQ I="));
-    Serial.print(_child_id);
-    Serial.print(F(" V="));
-    Serial.print(value);
-    Serial.print(F(" LPG="));
-    Serial.print(lpg);
-    Serial.print(F(" CO="));
-    Serial.print(co);
-    Serial.print(F(" SMOKE="));
-    Serial.println(smoke);
-  #endif
-  // store the value
-  _value_int = (int16_t)ceil(value);
-}
-
-// what do to as the main task when receiving a message
-void SensorMQ::onReceive(const MyMessage & message) {
-  onLoop();
-}
-
-// returns the calculated sensor resistance
-float SensorMQ::_MQResistanceCalculation(int raw_adc) {
-  return ( ((float)_rl_value*(1023-raw_adc)/raw_adc));
-}
-
-//  This function assumes that the sensor is in clean air
-float SensorMQ::_MQCalibration() {
-  int i;
-  float val=0;
-  //take multiple samples
-  for (i=0; i< _calibration_sample_times; i++) {  
-    val += _MQResistanceCalculation(analogRead(_pin));
-    delay(_calibration_sample_interval);
-  }
-  //calculate the average value
-  val = val/_calibration_sample_times;                   
-  //divided by RO_CLEAN_AIR_FACTOR yields the Ro
-  val = val/_ro_clean_air_factor;
-  //according to the chart in the datasheet
-  return val;
-}
-
-// This function use MQResistanceCalculation to caculate the sensor resistenc (Rs).
-float SensorMQ::_MQRead() {
-  int i;
-  float rs=0;
-  for (i=0; i<_read_sample_times; i++) {
-    rs += _MQResistanceCalculation(analogRead(_pin));
-    delay(_read_sample_interval);
-  }
-  rs = rs/_read_sample_times;
-  return rs;
-}
-
-
-// This function passes different curves to the MQGetPercentage function which calculates the ppm (parts per million) of the target gas.
-int SensorMQ::_MQGetGasPercentage(float rs_ro_ratio, int gas_id) {
-  if ( gas_id == _gas_lpg ) {
-    return _MQGetPercentage(rs_ro_ratio,_LPGCurve);
-  } else if ( gas_id == _gas_co) {
-    return _MQGetPercentage(rs_ro_ratio,_COCurve);
-  } else if ( gas_id == _gas_smoke) {
-    return _MQGetPercentage(rs_ro_ratio,_SmokeCurve);
-  }
-  return 0;
-}
-
-// returns ppm of the target gas
-int SensorMQ::_MQGetPercentage(float rs_ro_ratio, float *pcurve) {
-  return (pow(10,( ((log10(rs_ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
-}
 
 
 /*******************************************
@@ -1256,6 +1336,7 @@ int NodeManager::registerSensor(int sensor_type, int pin, int child_id) {
     else if (sensor_type == SENSOR_LDR) return registerSensor(new SensorLDR(child_id, pin));
     else if (sensor_type == SENSOR_THERMISTOR) return registerSensor(new SensorThermistor(child_id, pin));
     else if (sensor_type == SENSOR_MQ) return registerSensor(new SensorMQ(child_id, pin));
+    else if (sensor_type == SENSOR_ML8511) return registerSensor(new SensorML8511(child_id, pin));
   #endif
   #if MODULE_DIGITAL_INPUT == 1
     else if (sensor_type == SENSOR_DIGITAL_INPUT) return registerSensor(new SensorDigitalInput(child_id, pin));
@@ -1607,7 +1688,7 @@ void NodeManager::_process(const char * message) {
     else if (strcmp(message, "BATTERY") == 0) {
       // measure the board vcc
       float volt = 0;
-      if (_battery_internal_vcc || _battery_pin == -1) volt = _getVcc();
+      if (_battery_internal_vcc || _battery_pin == -1) volt = getVcc();
       else volt = analogRead(_battery_pin) * _battery_volts_per_bit;
       // calculate the percentage
       int percentage = ((volt - _battery_min) / (_battery_max - _battery_min)) * 100;
@@ -1834,29 +1915,6 @@ int NodeManager::_getAvailableChildId() {
   }
 }
 
-#if BATTERY_MANAGER == 1
-// return vcc in V
-float NodeManager::_getVcc() {
-  // Measure Vcc against 1.1V Vref
-  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
-    ADMUX = (_BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
-  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
-    ADMUX = (_BV(MUX5) | _BV(MUX0));
-  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
-    ADMUX = (_BV(MUX3) | _BV(MUX2));
-  #else
-    ADMUX = (_BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1));
-  #endif
-  // Vref settle
-  delay(70);
-  // Do conversion
-  ADCSRA |= _BV(ADSC);
-  while (bit_is_set(ADCSRA, ADSC)) {};
-  // return Vcc in mV
-  return (float)((1125300UL) / ADC) / 1000;
-}
-#endif
-
 // guess the initial value of a digital output based on the configured interrupt mode
 int NodeManager::_getInterruptInitialValue(int mode) {
   if (mode == RISING) return LOW; 
@@ -1864,3 +1922,4 @@ int NodeManager::_getInterruptInitialValue(int mode) {
   return -1;
 }
 
+
diff --git a/NodeManager.h b/NodeManager.h
index fff34de7560abd8600228e5e57310d38589556f9..299fd8f2d7d730ba5cccb67048110cb0db441cb4 100644
--- a/NodeManager.h
+++ b/NodeManager.h
@@ -149,6 +149,8 @@
   #define SENSOR_THERMISTOR 3
   // MQ2 air quality sensor
   #define SENSOR_MQ 19
+  // ML8511 UV sensor
+  #define SENSOR_ML8511 20
 #endif
 #if MODULE_DIGITAL_INPUT == 1
   // Generic digital sensor, return a pin's digital value
@@ -196,7 +198,7 @@
   // MLX90614 sensor, contactless temperature sensor
   #define SENSOR_BME280 18
 #endif
-// last Id: 19
+// last Id: 20
 /***********************************
   Libraries
 */
@@ -248,6 +250,7 @@ class PowerManager {
     void setPowerPins(int ground_pin, int vcc_pin, long wait = 50);
     void powerOn();
     void powerOff();
+    float getVcc();
   private:
     int _vcc_pin = -1;
     int _ground_pin = -1;
@@ -407,6 +410,78 @@ class SensorThermistor: public Sensor {
     float _offset = 0;
 };
 
+/*
+    SensorMQ
+ */
+class SensorMQ: public Sensor {
+  public:
+    SensorMQ(int child_id, int pin);
+    // define the target gas whose ppm has to be returned. 0: LPG, 1: CO, 2: Smoke (default: 1);
+    void setTargetGas(int value);
+    // define the load resistance on the board, in kilo ohms (default: 1);
+    void setRlValue(float value);
+    // define the Ro resistance on the board (default: 10000);
+    void setRoValue(float value);
+    // Sensor resistance in clean air (default: 9.83);
+    void setCleanAirFactor(float value);
+    // define how many samples you are going to take in the calibration phase (default: 50);
+    void setCalibrationSampleTimes(int value);
+    // define the time interal(in milisecond) between each samples in the cablibration phase (default: 500);
+    void setCalibrationSampleInterval(int value);
+    // define how many samples you are going to take in normal operation (default: 50);
+    void setReadSampleTimes(int value);
+    // define the time interal(in milisecond) between each samples in the normal operations (default: 5);
+    void setReadSampleInterval(int value);
+    // set the LPGCurve array (default: {2.3,0.21,-0.47})
+    void setLPGCurve(float *value);
+    // set the COCurve array (default: {2.3,0.72,-0.34})
+    void setCOCurve(float *value);
+    // set the SmokeCurve array (default: {2.3,0.53,-0.44})
+    void setSmokeCurve(float *value);
+    // define what to do at each stage of the sketch
+    void onBefore();
+    void onSetup();
+    void onLoop();
+    void onReceive(const MyMessage & message);
+  protected:
+    float _rl_value = 1.0;
+    float _ro_clean_air_factor = 9.83;
+    int _calibration_sample_times = 50;
+    int _calibration_sample_interval = 500;
+    int _read_sample_interval = 50;
+    int _read_sample_times = 5;
+    float _ro = 10000.0;
+    float _LPGCurve[3] = {2.3,0.21,-0.47};
+    float _COCurve[3] = {2.3,0.72,-0.34};
+    float _SmokeCurve[3] = {2.3,0.53,-0.44};
+    float _MQResistanceCalculation(int raw_adc);
+    float _MQCalibration();
+    float _MQRead();
+    int _MQGetGasPercentage(float rs_ro_ratio, int gas_id);
+    int  _MQGetPercentage(float rs_ro_ratio, float *pcurve);
+    int _gas_lpg = 0;
+    int _gas_co = 1;
+    int _gas_smoke = 2;
+    int _target_gas = _gas_co;
+};
+
+/*
+    SensorML8511
+ */
+
+class SensorML8511: public Sensor {
+  public:
+    SensorML8511(int child_id, int pin);
+    // define what to do at each stage of the sketch
+    void onBefore();
+    void onSetup();
+    void onLoop();
+    void onReceive(const MyMessage & message);
+  protected:
+    float _mapfloat(float x, float in_min, float in_max, float out_min, float out_max);
+};
+  
+
 /*
    SensorDigitalInput: read the digital input of the configured pin
 */
@@ -622,60 +697,7 @@ class SensorBME280: public Sensor {
 };
 #endif
 
-/*
-    SensorMQ
- */
-class SensorMQ: public Sensor {
-  public:
-    SensorMQ(int child_id, int pin);
-    // define the target gas whose ppm has to be returned. 0: LPG, 1: CO, 2: Smoke (default: 1);
-    void setTargetGas(int value);
-    // define the load resistance on the board, in kilo ohms (default: 1);
-    void setRlValue(float value);
-    // define the Ro resistance on the board (default: 10000);
-    void setRoValue(float value);
-    // Sensor resistance in clean air (default: 9.83);
-    void setCleanAirFactor(float value);
-    // define how many samples you are going to take in the calibration phase (default: 50);
-    void setCalibrationSampleTimes(int value);
-    // define the time interal(in milisecond) between each samples in the cablibration phase (default: 500);
-    void setCalibrationSampleInterval(int value);
-    // define how many samples you are going to take in normal operation (default: 50);
-    void setReadSampleTimes(int value);
-    // define the time interal(in milisecond) between each samples in the normal operations (default: 5);
-    void setReadSampleInterval(int value);
-    // set the LPGCurve array (default: {2.3,0.21,-0.47})
-    void setLPGCurve(float *value);
-    // set the COCurve array (default: {2.3,0.72,-0.34})
-    void setCOCurve(float *value);
-    // set the SmokeCurve array (default: {2.3,0.53,-0.44})
-    void setSmokeCurve(float *value);
-    // define what to do at each stage of the sketch
-    void onBefore();
-    void onSetup();
-    void onLoop();
-    void onReceive(const MyMessage & message);
-  protected:
-    float _rl_value = 1.0;
-    float _ro_clean_air_factor = 9.83;
-    int _calibration_sample_times = 50;
-    int _calibration_sample_interval = 500;
-    int _read_sample_interval = 50;
-    int _read_sample_times = 5;
-    float _ro = 10000.0;
-    float _LPGCurve[3] = {2.3,0.21,-0.47};
-    float _COCurve[3] = {2.3,0.72,-0.34};
-    float _SmokeCurve[3] = {2.3,0.53,-0.44};
-    float _MQResistanceCalculation(int raw_adc);
-    float _MQCalibration();
-    float _MQRead();
-    int _MQGetGasPercentage(float rs_ro_ratio, int gas_id);
-    int  _MQGetPercentage(float rs_ro_ratio, float *pcurve);
-    int _gas_lpg = 0;
-    int _gas_co = 1;
-    int _gas_smoke = 2;
-    int _target_gas = _gas_co;
-};
+
 
 /***************************************
    NodeManager: manages all the aspects of the node
diff --git a/NodeManager.ino b/NodeManager.ino
index 4d224b48946c225e090401b2776f503ea6d0ac6a..1fc03880e43569479185a4ed964bfe0a9e0e063c 100644
--- a/NodeManager.ino
+++ b/NodeManager.ino
@@ -29,7 +29,7 @@ void before() {
   /*
    * Register below your sensors
   */
-  nodeManager.registerSensor(SENSOR_MQ,A1);
+  nodeManager.registerSensor(SENSOR_ML8511,A1);
 
   /*
    * Register above your sensors
diff --git a/README.md b/README.md
index 0a92d2ece4d58bf0b764b7d6f5aa52157fb2e25a..0d952b0ae5ca5f16690bb01b8d6a86c7ba82a4d3 100644
--- a/README.md
+++ b/README.md
@@ -38,8 +38,9 @@ NodeManager configuration includes compile-time configuration directives (which
 ## Setup MySensors
 Since NodeManager has to communicate with the MySensors gateway on your behalf, it has to know how to do it. Place on top of the `config.h` file all the MySensors typical directives you are used to set on top of your sketch so both your sketch AND NodeManager will be able to share the same configuration. For example:
 ~~~c
+#define MY_BAUD_RATE 9600
 //#define MY_DEBUG
-#define MY_NODE_ID 100
+//#define MY_NODE_ID 100
 
 #define MY_RADIO_NRF24
 //#define MY_RF24_ENABLE_ENCRYPTION
@@ -76,7 +77,7 @@ Those NodeManager's directives in the `config.h` file control which module/libra
 // if enabled, a battery sensor will be created at BATTERY_CHILD_ID and will report vcc voltage together with the battery level percentage
 #define BATTERY_SENSOR 1
 
-// Enable this module to use one of the following sensors: SENSOR_ANALOG_INPUT, SENSOR_LDR, SENSOR_THERMISTOR, SENSOR_MQ
+// Enable this module to use one of the following sensors: SENSOR_ANALOG_INPUT, SENSOR_LDR, SENSOR_THERMISTOR, SENSOR_MQ, SENSOR_ML8511
 #define MODULE_ANALOG_INPUT 1
 // Enable this module to use one of the following sensors: SENSOR_DIGITAL_INPUT
 #define MODULE_DIGITAL_INPUT 1
@@ -197,6 +198,7 @@ SENSOR_BH1750 | BH1750 sensor, return light level in lux
 SENSOR_MLX90614 | MLX90614 contactless temperature sensor, return ambient and object temperature
 SENSOR_BME280 | BME280 sensor, return temperature/humidity/pressure based on the attached BME280 sensor
 SENSOR_MQ | MQ sensor, return ppm of the target gas
+SENSOR_ML8511 | ML8511 sensor, return UV intensity
 
 To register a sensor simply call the NodeManager instance with the sensory type and the pin the sensor is conncted to. For example:
 ~~~c
@@ -427,6 +429,13 @@ A NodeManager object must be created and called from within your sketch during `
 ### Sensor::before()
 * Call sensor-specific implementation of before by invoking `onBefore()` to initialize the sensor
 
+## NodeManager::setup()
+* Send a custom message with a STARTED payload to the controller
+* Call `setup()` of each registered sensor
+
+### Sensor::setup()
+* Call sensor-specific implementation of setup by invoking `onSetup()` to initialize the sensor
+
 ## NodeManager::loop()
 * If all the sensors are powered by an arduino pin, this is set to HIGH
 * Call `loop()` of each registered sensor
diff --git a/config.h b/config.h
index 70ce7ad20277d70881bec0a7e33ac6e0bec5d9cc..c5f1c09b519afd58467adfd73b541a6d1584590c 100644
--- a/config.h
+++ b/config.h
@@ -48,7 +48,7 @@
 // if enabled, a battery sensor will be created at BATTERY_CHILD_ID and will report vcc voltage together with the battery level percentage
 #define BATTERY_SENSOR 1
 
-// Enable this module to use one of the following sensors: SENSOR_ANALOG_INPUT, SENSOR_LDR, SENSOR_THERMISTOR, SENSOR_MQ
+// Enable this module to use one of the following sensors: SENSOR_ANALOG_INPUT, SENSOR_LDR, SENSOR_THERMISTOR, SENSOR_MQ, SENSOR_ML8511
 #define MODULE_ANALOG_INPUT 1
 // Enable this module to use one of the following sensors: SENSOR_DIGITAL_INPUT
 #define MODULE_DIGITAL_INPUT 1