Skip to content

Commit c8af05d

Browse files
committed
Add runtime updates of debug config
Listen to the same serial port used for debug output to switch Debug Level and other config. Use VERBOSE, DEBUG, INFO, WARNING, ERROR, NONE or V,D,I,W,E,N. to change debug level, or LABEL, TIMESTAMP, NEWLINE or L,T,N to toggle config settings. Terminate command with a Line feed ('\n) or CRLF ('\r\n')
1 parent 21b5ccd commit c8af05d

File tree

5 files changed

+129
-37
lines changed

5 files changed

+129
-37
lines changed

README.md

+87-8
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Arduino_DebugUtils
22
==================
33

4-
[![Check Arduino status](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/check-arduino.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/check-arduino.yml)
5-
[![Compile Examples status](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/compile-examples.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/compile-examples.yml)
6-
[![Spell Check status](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/spell-check.yml/badge.svg)](https://github.com/arduino-libraries/Arduino_DebugUtils/actions/workflows/spell-check.yml)
4+
[![Check Arduino status](https://github.com/robroypt/Arduino_DebugUtils/actions/workflows/check-arduino.yml/badge.svg)](https://github.com/robroypt/Arduino_DebugUtils/actions/workflows/check-arduino.yml)
5+
[![Compile Examples status](https://github.com/robroypt/Arduino_DebugUtils/actions/workflows/compile-examples.yml/badge.svg)](https://github.com/robroypt/Arduino_DebugUtils/actions/workflows/compile-examples.yml)
6+
[![Spell Check status](https://github.com/robroypt/Arduino_DebugUtils/actions/workflows/spell-check.yml/badge.svg)](https://github.com/robroypt/Arduino_DebugUtils/actions/workflows/spell-check.yml)
77

88
This class provides functionality useful for debugging sketches via `printf`-style statements.
99

@@ -16,7 +16,7 @@ Arduino_DebugUtils has 6 different debug levels (described descending from highe
1616
* `DBG_DEBUG` - more information
1717
* `DBG_VERBOSE` - most information
1818

19-
The desired debug level can be set via `setDebugLevel(DBG_WARNING)`.
19+
The desired debug level can be set in code via `setDebugLevel(DBG_WARNING)` or while the code is running using the Serial Monitor.
2020

2121
Debug messages are written via `print` which supports `printf`-style formatted output.
2222

@@ -34,8 +34,35 @@ If desired, timestamps can be prefixed to the debug message. Timestamp output ca
3434
Normally all debug output is redirected to the primary serial output of each board (`Serial`). In case you want to redirect the output to another output stream you can make use of `setDebugOutputStream(&Serial2)`.
3535
3636
# Documentation
37-
### Debug :
38-
Arduino_DebugUtils Object that will be used for calling member functions.
37+
## Code setup
38+
39+
### Include the Library
40+
41+
Include the Arduino_DebugUtils library by adding
42+
```C++
43+
#include "Arduino_DebugUtils.h"
44+
```
45+
at the top of your code.
46+
47+
### Setup the Serial Port
48+
49+
By default, the Output Stream and input port for printing debug messages and receiving config commands is `Serial`.
50+
51+
For minimal setup, just create the Serial object with a specified baud rate.
52+
```C++
53+
Serial.begin(9600); // Set baud rate here. Make sure you match the same baud rate in your terminal or monitor
54+
```
55+
In advanced cases you can use other serial ports (if available), or a Software Serial object. You can also (optionally) set a different Debug Level, turn on timestamps and debug labels.
56+
57+
```C++
58+
mySerial.begin(9600); // Set baud rate here. Make sure you match the same baud rate in your terminal or monitor
59+
Debug.setDebugOutputStream(&mySerial);
60+
Debug.setDebugLevel(DBG_VERBOSE);
61+
Debug.timestampOn();
62+
```
63+
64+
### Debug: object
65+
Arduino_DebugUtils Object that will be used for calling member functions is automatically instantiated when you include the library.
3966

4067
### Debug.setDebugLevel(int const debug_level) :
4168
Parameter debug_level in order of lowest to highest priority are : `DBG_NONE`, `DBG_ERROR`, `DBG_WARNING`, `DBG_INFO` (default), `DBG_DEBUG`, and `DBG_VERBOSE`.
@@ -79,6 +106,28 @@ Debug.timestampOff();
79106
DEBUG_VERBOSE("i = %d", i); //Output looks like : i = 21
80107
```
81108
109+
### Debug.debugLabelOn() :
110+
Calling this function switches on the Debug Label in the `Debug.print()` function call;
111+
By default, printing the debug label is off, unless turned on using this function call.
112+
113+
Return type: void.
114+
115+
Example:
116+
```C++
117+
Debug.debugLabelOn();
118+
```
119+
120+
### Debug.debugLabelOff() :
121+
Calling this function switches off the Debug Label in the `Debug.print()` function call;
122+
By default, printing the debug label is off, unless turned on using this function call.
123+
124+
Return type: void.
125+
126+
Example:
127+
```C++
128+
Debug.debugLabelOff();
129+
```
130+
82131
### Debug.newlineOn() :
83132
Calling this function ensures that a newline will be sent at the end of the `Debug.print()` function call;
84133
By default, a newline is sent
@@ -96,10 +145,9 @@ Return type: void.
96145

97146
Example:
98147
```C++
99-
Debug.timestampOff();
148+
Debug.newlineOff();
100149
```
101150

102-
103151
### Debug.print(int const debug_level, const char * fmt, ...);
104152
This function prints the message if parameter `debug_level` in the `Debug.print(debug_level, ...)` function call belongs to the range: DBG_ERROR <= debug_level <= (<DBG_LEVEL> that has been set using `setDebugLevel()` function).
105153

@@ -111,3 +159,34 @@ Debug.setDebugLevel(DBG_VERBOSE);
111159
int i = 0;
112160
DEBUG_VERBOSE("DBG_VERBOSE i = %d", i);
113161
```
162+
## Set Debug Settings at Runtime
163+
164+
While your code is running you can
165+
- set the current debug level
166+
- toggle the display of the prefixed Timestamp at the beginning of the `Debug.print()` function call
167+
- toggle the display of the debug label at the beginning of the `Debug.print()` function call
168+
- toggle the sending of a newline at the end of the `Debug.print()` function call
169+
170+
### Setup
171+
172+
Modify your `loop()` function to call `Debug.processDebugConfigCommand()` each time.
173+
174+
Example:
175+
```C++
176+
int i = 0;
177+
178+
void loop() {
179+
DEBUG_VERBOSE("i = %d", i);
180+
i++;
181+
Debug.processDebugConfigCommand();
182+
delay(1000); // See note on timing below
183+
}
184+
```
185+
186+
### Timing
187+
- If you have a delay in your `loop()` (as is the case with the example code) this will also delay action on any entered commands, so for faster response call `processDebugConfigCommand()` more often.
188+
189+
### Trouble-shooting
190+
Check your monitor or terminal is configured:
191+
- to send a LF or CRLF Line Ending at the end of a message sent via the serial port.
192+
- to use the same baud rate specified when setting up the Serial object (9600 in the examples)

examples/Arduino_Debug_Advance/Arduino_Debug_Advance.ino

+1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ int i = 0;
2626
void loop() {
2727
DEBUG_VERBOSE("i = %d", i);
2828
i++;
29+
Debug.processDebugConfigCommand();
2930
delay(1000);
3031
}

examples/Arduino_Debug_Basic/Arduino_Debug_Basic.ino

+1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ int i = 0;
1010
void loop() {
1111
DEBUG_INFO("i = %d", i);
1212
i++;
13+
Debug.processDebugConfigCommand();
1314
delay(1000);
1415
}

src/Arduino_DebugUtils.cpp

+39-28
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
INPUT BUFFER
2626
******************************************************************************/
2727

28-
#define COMMAND_BUFFER_SIZE 50 // Define a reasonable size for the input buffer
28+
#define COMMAND_BUFFER_SIZE 30 // Define a reasonable size for the input buffer
2929
char commandBuffer[COMMAND_BUFFER_SIZE];
3030

3131
/******************************************************************************
@@ -96,8 +96,7 @@ void Arduino_DebugUtils::timestampOff() {
9696
_timestamp_on = false;
9797
}
9898

99-
void Arduino_DebugUtils::print(int const debug_level, const char * fmt, ...)
100-
{
99+
void Arduino_DebugUtils::print(int const debug_level, const char * fmt, ...){
101100
if (!shouldPrint(debug_level))
102101
return;
103102

@@ -113,8 +112,7 @@ void Arduino_DebugUtils::print(int const debug_level, const char * fmt, ...)
113112
va_end(args);
114113
}
115114

116-
void Arduino_DebugUtils::print(int const debug_level, const __FlashStringHelper * fmt, ...)
117-
{
115+
void Arduino_DebugUtils::print(int const debug_level, const __FlashStringHelper * fmt, ...){
118116
if (!shouldPrint(debug_level))
119117
return;
120118

@@ -132,8 +130,7 @@ void Arduino_DebugUtils::print(int const debug_level, const __FlashStringHelper
132130
va_end(args);
133131
}
134132

135-
void Arduino_DebugUtils::processDebugUpdateLevelCommand()
136-
{
133+
void Arduino_DebugUtils::processDebugConfigCommand(){
137134
static size_t bufferIndex = 0; // Index to track buffer position
138135

139136
// Check if the stream is available and has data
@@ -146,42 +143,56 @@ void Arduino_DebugUtils::processDebugUpdateLevelCommand()
146143
commandBuffer[bufferIndex] = '\0'; // Null-terminate the string
147144

148145
// Compare C-strings for each command
149-
if (strcmp(commandBuffer, "V") == 0 || strcmp(commandBuffer, "VERBOSE") == 0)
150-
{
146+
if (strcmp(commandBuffer, "V") == 0 || strcmp(commandBuffer, "VERBOSE") == 0) {
151147
setDebugLevel(DBG_VERBOSE);
152148
_debug_io_stream->println("Debug level set to VERBOSE.");
153-
}
154-
else if (strcmp(commandBuffer, "D") == 0 || strcmp(commandBuffer, "DEBUG") == 0)
155-
{
149+
} else if (strcmp(commandBuffer, "D") == 0 || strcmp(commandBuffer, "DEBUG") == 0) {
156150
setDebugLevel(DBG_INFO);
157151
_debug_io_stream->println("Debug level set to DEBUG.");
158-
}
159-
else if (strcmp(commandBuffer, "I") == 0 || strcmp(commandBuffer, "INFO") == 0)
160-
{
152+
} else if (strcmp(commandBuffer, "I") == 0 || strcmp(commandBuffer, "INFO") == 0) {
161153
setDebugLevel(DBG_INFO);
162154
_debug_io_stream->println("Debug level set to INFO.");
163-
}
164-
else if (strcmp(commandBuffer, "W") == 0 || strcmp(commandBuffer, "WARNING") == 0)
165-
{
155+
} else if (strcmp(commandBuffer, "W") == 0 || strcmp(commandBuffer, "WARNING") == 0) {
166156
setDebugLevel(DBG_WARNING);
167157
_debug_io_stream->println("Debug level set to WARNING.");
168-
}
169-
else if (strcmp(commandBuffer, "E") == 0 || strcmp(commandBuffer, "ERROR") == 0)
170-
{
158+
} else if (strcmp(commandBuffer, "E") == 0 || strcmp(commandBuffer, "ERROR") == 0) {
171159
setDebugLevel(DBG_ERROR);
172160
_debug_io_stream->println("Debug level set to ERROR.");
173-
}
174-
else
175-
{
176-
_debug_io_stream->println("Invalid command. Use V,D,I,W,E or VERBOSE, DEBUG, INFO, WARNING, or ERROR.");
161+
} else if (strcmp(commandBuffer, "N") == 0 || strcmp(commandBuffer, "NONE") == 0) {
162+
setDebugLevel(DBG_NONE);
163+
_debug_io_stream->println("Debug level set to NONE.");
164+
} else if (strcmp(commandBuffer, "T") == 0 || strcmp(commandBuffer, "TIMESTAMP") == 0) {
165+
if (_timestamp_on) {
166+
timestampOff();
167+
_debug_io_stream->println("TIMESTAMPS set to OFF.");
168+
} else {
169+
timestampOn();
170+
_debug_io_stream->println("TIMESTAMPS set to ON.");
171+
}
172+
} else if (strcmp(commandBuffer, "N") == 0 || strcmp(commandBuffer, "NEWLINE") == 0) {
173+
if (_newline_on) {
174+
newlineOff();
175+
_debug_io_stream->println("NEWLINE set to OFF.");
176+
} else {
177+
newlineOn();
178+
_debug_io_stream->println("NEWLINE set to ON.");
179+
}
180+
} else if (strcmp(commandBuffer, "L") == 0 || strcmp(commandBuffer, "LABEL") == 0) {
181+
if (_print_debug_label) {
182+
debugLabelOff();
183+
_debug_io_stream->println("DEBUG LABEL set to OFF.");
184+
} else {
185+
debugLabelOn();
186+
_debug_io_stream->println("DEBUG LABEL set to ON.");
187+
}
188+
} else {
189+
_debug_io_stream->println("Invalid command. Use VERBOSE, DEBUG, INFO, WARNING, ERROR, NONE or V,D,I,W,E,N. LABEL, TIMESTAMP, NEWLINE or L,T,N.");
177190
}
178191

179192
// Clear the buffer for the next command
180193
bufferIndex = 0;
181194
commandBuffer[0] = '\0';
182-
}
183-
else if (incomingChar != '\r')
184-
{
195+
} else if (incomingChar != '\r') {
185196
// Add the character to the buffer if it's not a carriage return
186197
if (bufferIndex < COMMAND_BUFFER_SIZE - 1)
187198
{

src/Arduino_DebugUtils.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class Arduino_DebugUtils {
7070
void print(int const debug_level, const char * fmt, ...);
7171
void print(int const debug_level, const __FlashStringHelper * fmt, ...);
7272

73-
void processDebugUpdateLevelCommand();
73+
void processDebugConfigCommand();
7474

7575
private:
7676

0 commit comments

Comments
 (0)