diff --git a/examples/Arduino_Debug_Levels/Arduino_Debug_Levels.ino b/examples/Arduino_Debug_Levels/Arduino_Debug_Levels.ino
new file mode 100644
index 0000000..ece8327
--- /dev/null
+++ b/examples/Arduino_Debug_Levels/Arduino_Debug_Levels.ino
@@ -0,0 +1,23 @@
+#define DEBUG_LEVEL DEBUG_LEVEL_INFO
+#include <Arduino_DebugUtils.h>
+
+void setup() {
+  Serial.begin(9600);
+  Debug.timestampOn();
+  Debug.debugLabelOn();
+  Debug.setDebugLevel(DBG_ALL);
+}
+
+int i = 0;
+
+void loop() {
+  DEBUG_ERROR("i = %d", i);
+  DEBUG_WARNING("i = %d", i);
+  DEBUG_INFO("i = %d", i);
+  DEBUG_DEBUG("i = %d", i);
+  DEBUG_VERBOSE("i = %d", i);
+
+  Serial.println();
+  i++;
+  delay(1000);
+}
diff --git a/src/Arduino_DebugUtils.cpp b/src/Arduino_DebugUtils.cpp
index 270927b..0d9ee4b 100644
--- a/src/Arduino_DebugUtils.cpp
+++ b/src/Arduino_DebugUtils.cpp
@@ -25,8 +25,8 @@
    CONSTANTS
  ******************************************************************************/
 
-static int const DEFAULT_DEBUG_LEVEL   = DBG_INFO;
-static Stream *  DEFAULT_OUTPUT_STREAM = &Serial;
+static Arduino_DebugUtils::Level const DEFAULT_DEBUG_LEVEL  = DBG_INFO;
+static Stream *  DEFAULT_OUTPUT_STREAM                      = &Serial;
 
 /******************************************************************************
    CTOR/DTOR
@@ -45,11 +45,11 @@ Arduino_DebugUtils::Arduino_DebugUtils() {
    PUBLIC MEMBER FUNCTIONS
  ******************************************************************************/
 
-void Arduino_DebugUtils::setDebugLevel(int const debug_level) {
+void Arduino_DebugUtils::setDebugLevel(Arduino_DebugUtils::Level const debug_level) {
   _debug_level = debug_level;
 }
 
-int Arduino_DebugUtils::getDebugLevel() const {
+Arduino_DebugUtils::Level Arduino_DebugUtils::getDebugLevel() const {
   return _debug_level;
 }
 
@@ -89,7 +89,7 @@ void Arduino_DebugUtils::timestampOff() {
   _timestamp_on = false;
 }
 
-void Arduino_DebugUtils::print(int const debug_level, const char * fmt, ...)
+void Arduino_DebugUtils::print(Arduino_DebugUtils::Level const debug_level, const char * fmt, ...)
 {
   if (!shouldPrint(debug_level))
     return;
@@ -106,7 +106,7 @@ void Arduino_DebugUtils::print(int const debug_level, const char * fmt, ...)
   va_end(args);
 }
 
-void Arduino_DebugUtils::print(int const debug_level, const __FlashStringHelper * fmt, ...)
+void Arduino_DebugUtils::print(Arduino_DebugUtils::Level const debug_level, const __FlashStringHelper * fmt, ...)
 {
   if (!shouldPrint(debug_level))
     return;
@@ -130,10 +130,10 @@ void Arduino_DebugUtils::print(int const debug_level, const __FlashStringHelper
  ******************************************************************************/
 
 void Arduino_DebugUtils::vPrint(char const * fmt, va_list args) {
-  
+
   va_list args_copy;
   va_copy(args_copy, args);
-  
+
   // calculate required buffer length
   int msg_buf_size = vsnprintf(nullptr, 0, fmt, args) + 1; // add one for null terminator
 #if __STDC_NO_VLA__ == 1
@@ -196,7 +196,7 @@ void Arduino_DebugUtils::printTimestamp()
   _debug_output_stream->print(timestamp);
 }
 
-void Arduino_DebugUtils::printDebugLabel(int const debug_level)
+void Arduino_DebugUtils::printDebugLabel(Arduino_DebugUtils::Level const debug_level)
 {
   static char const * DEBUG_MODE_STRING[5] =
   {
@@ -207,16 +207,40 @@ void Arduino_DebugUtils::printDebugLabel(int const debug_level)
     "[DBG_VERBOSE] ",
   };
 
-  bool is_valid_debug_level = (debug_level >= DBG_ERROR) && (debug_level <= DBG_VERBOSE);
-  if (!is_valid_debug_level)
-    return;
+  const char* level_str = nullptr;
+  switch(debug_level) {
+  case Arduino_DebugUtils::Level::Error:
+    level_str = DEBUG_MODE_STRING[0];
+    break;
+  case Arduino_DebugUtils::Level::Warning:
+    level_str = DEBUG_MODE_STRING[1];
+    break;
+  case Arduino_DebugUtils::Level::Info:
+    level_str = DEBUG_MODE_STRING[2];
+    break;
+  case Arduino_DebugUtils::Level::Debug:
+    level_str = DEBUG_MODE_STRING[3];
+    break;
+  case Arduino_DebugUtils::Level::Verbose:
+    level_str = DEBUG_MODE_STRING[4];
+    break;
+  case Arduino_DebugUtils::Level::None:
+  case Arduino_DebugUtils::Level::All:
+  default:
+    break;
+  }
 
-  _debug_output_stream->print(DEBUG_MODE_STRING[debug_level]);
+  if(level_str != nullptr) {
+    _debug_output_stream->print(level_str);
+  }
 }
 
-bool Arduino_DebugUtils::shouldPrint(int const debug_level) const
+bool Arduino_DebugUtils::shouldPrint(Arduino_DebugUtils::Level const debug_level) const
 {
-  return ((debug_level >= DBG_ERROR) && (debug_level <= DBG_VERBOSE) && (debug_level <= _debug_level));
+  uint_fast16_t dl = static_cast<uint_fast16_t>(debug_level);
+  uint_fast16_t _dl = static_cast<uint_fast16_t>(_debug_level);
+
+  return _dl & dl == dl;
 }
 
 /******************************************************************************
@@ -225,10 +249,10 @@ bool Arduino_DebugUtils::shouldPrint(int const debug_level) const
 
 Arduino_DebugUtils Debug;
 
-void setDebugMessageLevel(int const debug_level) {
+void setDebugMessageLevel(Arduino_DebugUtils::Level const debug_level) {
   Debug.setDebugLevel(debug_level);
 }
 
-int getDebugMessageLevel() {
+Arduino_DebugUtils::Level getDebugMessageLevel() {
   return Debug.getDebugLevel();
 }
diff --git a/src/Arduino_DebugUtils.h b/src/Arduino_DebugUtils.h
index 73e6287..cb1e633 100644
--- a/src/Arduino_DebugUtils.h
+++ b/src/Arduino_DebugUtils.h
@@ -26,19 +26,13 @@
 
 #include <stdarg.h>
 
-/******************************************************************************
-   CONSTANTS
- ******************************************************************************/
-
-static int const DBG_NONE    = -1;
-static int const DBG_ERROR   =  0;
-static int const DBG_WARNING =  1;
-static int const DBG_INFO    =  2;
-static int const DBG_DEBUG   =  3;
-static int const DBG_VERBOSE =  4;
-
-void setDebugMessageLevel(int const debug_level);
-int  getDebugMessageLevel();
+#define DEBUG_LEVEL_NONE                   0x0000
+#define DEBUG_LEVEL_ERROR                  0x0001
+#define DEBUG_LEVEL_WARNING                0x0003
+#define DEBUG_LEVEL_INFO                   0x0007
+#define DEBUG_LEVEL_DEBUG                  0x000F
+#define DEBUG_LEVEL_VERBOSE                0x001F
+#define DEBUG_LEVEL_ALL                    0xFFFF
 
 /******************************************************************************
    CLASS DECLARATION
@@ -47,11 +41,20 @@ int  getDebugMessageLevel();
 class Arduino_DebugUtils {
 
   public:
+    enum class Level: uint_fast16_t {
+      None                    = DEBUG_LEVEL_NONE,
+      Error                   = DEBUG_LEVEL_ERROR,
+      Warning                 = DEBUG_LEVEL_WARNING,
+      Info                    = DEBUG_LEVEL_INFO,
+      Verbose                 = DEBUG_LEVEL_VERBOSE,
+      Debug                   = DEBUG_LEVEL_DEBUG,
+      All                     = DEBUG_LEVEL_ALL,
+    };
 
     Arduino_DebugUtils();
 
-    void setDebugLevel(int const debug_level);
-    int  getDebugLevel() const;
+    void setDebugLevel(Level const debug_level);
+    Arduino_DebugUtils::Level getDebugLevel() const;
 
     void setDebugOutputStream(Stream * stream);
 
@@ -67,8 +70,8 @@ class Arduino_DebugUtils {
     void formatTimestampOn();
     void formatTimestampOff();
 
-    void print(int const debug_level, const char * fmt, ...);
-    void print(int const debug_level, const __FlashStringHelper * fmt, ...);
+    void print(Level const debug_level, const char * fmt, ...);
+    void print(Level const debug_level, const __FlashStringHelper * fmt, ...);
 
 
   private:
@@ -77,16 +80,31 @@ class Arduino_DebugUtils {
     bool      _newline_on;
     bool      _print_debug_label;
     bool      _format_timestamp_on;
-    int       _debug_level;
+    Level     _debug_level;
     Stream *  _debug_output_stream;
 
     void vPrint(char const * fmt, va_list args);
     void printTimestamp();
-    void printDebugLabel(int const debug_level);
-    bool shouldPrint(int const debug_level) const;
+    void printDebugLabel(Arduino_DebugUtils::Level const debug_level);
+    inline bool shouldPrint(Level const debug_level) const;
 
 };
 
+void setDebugMessageLevel(Arduino_DebugUtils::Level const debug_level);
+Arduino_DebugUtils::Level  getDebugMessageLevel();
+
+/******************************************************************************
+   CONSTANTS
+ ******************************************************************************/
+
+static constexpr Arduino_DebugUtils::Level DBG_NONE    = Arduino_DebugUtils::Level::None;
+static constexpr Arduino_DebugUtils::Level DBG_ERROR   = Arduino_DebugUtils::Level::Error;
+static constexpr Arduino_DebugUtils::Level DBG_WARNING = Arduino_DebugUtils::Level::Warning;
+static constexpr Arduino_DebugUtils::Level DBG_INFO    = Arduino_DebugUtils::Level::Info;
+static constexpr Arduino_DebugUtils::Level DBG_DEBUG   = Arduino_DebugUtils::Level::Debug;
+static constexpr Arduino_DebugUtils::Level DBG_VERBOSE = Arduino_DebugUtils::Level::Verbose;
+static constexpr Arduino_DebugUtils::Level DBG_ALL     = Arduino_DebugUtils::Level::All;
+
 /******************************************************************************
    EXTERN
  ******************************************************************************/
@@ -97,24 +115,39 @@ extern Arduino_DebugUtils Debug;
  * DEFINE
  **************************************************************************************/
 
-#ifndef DEBUG_ERROR
-#  define DEBUG_ERROR(fmt, ...) Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__)
+
+#ifndef DEBUG_LEVEL
+#  define DEBUG_LEVEL DEBUG_LEVEL_ALL
+#endif
+
+#if !defined(DEBUG_ERROR) && ((DEBUG_LEVEL & DEBUG_LEVEL_ERROR) == DEBUG_LEVEL_ERROR)
+#  define DEBUG_ERROR(fmt, ...)       Debug.print(DBG_ERROR, fmt, ## __VA_ARGS__)
+#else
+#  define DEBUG_ERROR(fmt, ...)       (void) 0
 #endif
 
-#ifndef DEBUG_WARNING
-#  define DEBUG_WARNING(fmt, ...) Debug.print(DBG_WARNING, fmt, ## __VA_ARGS__)
+#if !defined(DEBUG_WARNING) && ((DEBUG_LEVEL & DEBUG_LEVEL_WARNING) == DEBUG_LEVEL_WARNING)
+#  define DEBUG_WARNING(fmt, ...)     Debug.print(DBG_WARNING, fmt, ## __VA_ARGS__)
+#else
+#  define DEBUG_WARNING(fmt, ...)     (void) 0
 #endif
 
-#ifndef DEBUG_INFO
-#  define DEBUG_INFO(fmt, ...) Debug.print(DBG_INFO, fmt, ## __VA_ARGS__)
+#if !defined(DEBUG_INFO) && ((DEBUG_LEVEL & DEBUG_LEVEL_INFO) == DEBUG_LEVEL_INFO)
+#  define DEBUG_INFO(fmt, ...)        Debug.print(DBG_INFO, fmt, ## __VA_ARGS__)
+#else
+#  define DEBUG_INFO(fmt, ...)        (void) 0
 #endif
 
-#ifndef DEBUG_DEBUG
-#  define DEBUG_DEBUG(fmt, ...) Debug.print(DBG_DEBUG, fmt, ## __VA_ARGS__)
+#if !defined(DEBUG_DEBUG) && ((DEBUG_LEVEL & DEBUG_LEVEL_DEBUG) == DEBUG_LEVEL_DEBUG)
+#  define DEBUG_DEBUG(fmt, ...)       Debug.print(DBG_DEBUG, fmt, ## __VA_ARGS__)
+#else
+#  define DEBUG_DEBUG(fmt, ...)       (void) 0
 #endif
 
-#ifndef DEBUG_VERBOSE
-#  define DEBUG_VERBOSE(fmt, ...) Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__)
+#if !defined(DEBUG_VERBOSE) && ((DEBUG_LEVEL & DEBUG_LEVEL_VERBOSE) == DEBUG_LEVEL_VERBOSE)
+#  define DEBUG_VERBOSE(fmt, ...)     Debug.print(DBG_VERBOSE, fmt, ## __VA_ARGS__)
+#else
+#  define DEBUG_VERBOSE(fmt, ...)     (void) 0
 #endif
 
 #endif /* ARDUINO_DEBUG_UTILS_H_ */