Skip to content

Commit bc18cc5

Browse files
committed
Update tutorial content
1 parent b804efc commit bc18cc5

File tree

1 file changed

+48
-42
lines changed

1 file changed

+48
-42
lines changed

content/learn/02.microcontrollers/04.debugging/debugging.md

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ The Arduino® Zero board features an on-board debugger, the Atmel® Embedded Deb
156156

157157
Arduino® boards with a SAMD microcontroller feature native on-chip debug capabilities; these debugging capabilities can be used with an external ICD tool over JTAG or SWD interfaces. CMSIS-DAP compliant debug probes can be used with the Arduino IDE 2.0 out of the box without any configuration file; non-standard debug probes require a special configuration. Check out these tutorials to learn how to use an external ICD tool with SAMD based Arduino boards and the Arduino IDE 2.0:
158158

159-
* [Debugging with the Segger J-Link](https://docs.arduino.cc/tutorials/mkr-wifi-1010/mkr-jlink-setup).
159+
* [Debugging with the SEGGER J-Link](https://docs.arduino.cc/tutorials/mkr-wifi-1010/mkr-jlink-setup).
160160
* [Debugging with the Atmel-ICE](https://docs.arduino.cc/tutorials/mkr-wifi-1010/atmel-ice).
161161

162162
### Hardware Tools
@@ -224,7 +224,7 @@ Shown visual representation of the signal via SDR software can now be used to ve
224224

225225
## Debugging Techniques Example
226226

227-
A simple example will be used to demonstrate implementation of different debugging techniques and how they can be very useful for the development process. We are going to use [Arduino Nano 33 BLE](https://docs.arduino.cc/hardware/nano-33-ble) and use the LSM9DS1 inertial measurement unit's features to show the importance and ease of debugging process. The example code will be based on using [accelerometer](https://docs.arduino.cc/tutorials/nano-33-ble/imu_accelerometer), [gyroscope](https://docs.arduino.cc/tutorials/nano-33-ble/imu_gyroscope), and [magnetometer](https://docs.arduino.cc/tutorials/nano-33-ble/imu_magnetometer) at the same time, having the tasks to be executed in order to be able to obtain every value of the module.
227+
A simple example will demonstrate the implementation of different debugging techniques and how they can be handy for the development process of a program in the Arduino® ecosystem. We will use the Arduino® Nano 33 BLE Sense board, and its onboard inertial measurement unit (IMU) features to show the debugging process's importance. The example code uses accelerometer, gyroscope, and magnetometer data simultaneously, having the tasks be executed to obtain every value:
228228

229229
```arduino
230230
/*
@@ -243,11 +243,10 @@ A simple example will be used to demonstrate implementation of different debuggi
243243
244244
#include <Arduino_LSM9DS1.h>
245245
246-
// For debugging purposes
247246
#define DUMP_BUFFER_SIZE 32
248247
unsigned char GoodBuffer[DUMP_BUFFER_SIZE];
249248
unsigned char BadBuffer[DUMP_BUFFER_SIZE];
250-
unsigned long Count = 0;
249+
unsigned long count = 0;
251250
uint8_t good, bad = 0;
252251
253252
float x, y, z, ledvalue;
@@ -257,15 +256,14 @@ int plusThreshold = 30, minusThreshold = -30;
257256
void setup() {
258257
Serial.begin(9600);
259258
while (!Serial);
260-
Serial.println("Started");
259+
Serial.println("- Started");
261260
262261
if (!IMU.begin()) {
263-
Serial.println("Failed to initialize IMU!");
262+
Serial.println("- Failed to initialize IMU!");
264263
265264
bad++;
266-
Save_Debug_Buffer();
267-
Disp_Debug_Buffer();
268-
265+
save_bebug_buffer();
266+
disp_debug_buffer();
269267
debug_stop();
270268
}
271269
@@ -281,104 +279,112 @@ void loop() {
281279
magnetometer_task();
282280
}
283281
284-
Save_Debug_Buffer();
282+
save_debug_buffer();
285283
debug_stop();
286284
}
287285
286+
// Accelerometer setup
288287
void accelermeter_setup() {
289288
Serial.print(F("- Accelerometer sample rate: "));
290289
Serial.print(IMU.accelerationSampleRate());
291290
Serial.println(F(" Hz"));
292291
}
293292
293+
// Read accelerometer data in all three directions task
294294
void accelerometer_task() {
295295
if (IMU.accelerationAvailable()) {
296-
Serial.println(F("Accelerometer Data Ready "));
296+
Serial.println(F("- Accelerometer data ready"));
297297
IMU.readAcceleration(x, y, z);
298298
good++;
299299
} else {
300-
Serial.println(F("Accelerometer Data Not Ready "));
300+
Serial.println(F("Accelerometer data not ready"));
301301
bad++;
302302
}
303303
304304
if (x > 0.1) {
305305
x = 100 * x;
306306
degreesX = map(x, 0, 97, 0, 90);
307-
Serial.print(F("Tilting up "));
307+
Serial.print(F("- Tilting up "));
308308
Serial.print(degreesX);
309309
Serial.println(F(" degrees"));
310310
}
311+
311312
if (x < -0.1) {
312313
x = 100 * x;
313314
degreesX = map(x, 0, -100, 0, 90);
314-
Serial.print(F("Tilting down "));
315+
Serial.print(F("- Tilting down "));
315316
Serial.print(degreesX);
316317
Serial.println(F(" degrees"));
317318
}
319+
318320
if (y > 0.1) {
319321
y = 100 * y;
320322
degreesY = map(y, 0, 97, 0, 90);
321-
Serial.print(F("Tilting left "));
323+
Serial.print(F("- Tilting left "));
322324
Serial.print(degreesY);
323325
Serial.println(F(" degrees"));
324326
}
327+
325328
if (y < -0.1) {
326329
y = 100 * y;
327330
degreesY = map(y, 0, -100, 0, 90);
328-
Serial.print(F("Tilting right "));
331+
Serial.print(F("- Tilting right "));
329332
Serial.print(degreesY);
330333
Serial.println(F(" degrees"));
331334
}
335+
332336
delay(1000);
333337
}
334338
339+
// Gyroscope setup
335340
void gyroscope_setup(){
336-
Serial.print(F("Gyroscope sample rate = "));
341+
Serial.print(F("- Gyroscope sample rate = "));
337342
Serial.print(IMU.gyroscopeSampleRate());
338343
Serial.println(F(" Hz"));
339344
Serial.println();
340-
Serial.println(F("Gyroscope in degrees/second"));
345+
Serial.println(F("- Gyroscope in degrees/second"));
341346
}
342347
348+
// Read gyroscope data in all three directions task
343349
void gyroscope_task(){
344350
if (IMU.gyroscopeAvailable()) {
345351
IMU.readGyroscope(x, y, z);
346-
Serial.println(F("GyroScope Data Ready "));
352+
Serial.println(F("- Gyroscope data ready"));
347353
good++;
348354
} else {
349-
Serial.println(F("GyroScope Data Not Ready "));
355+
Serial.println(F("- Gyroscope data not ready"));
350356
bad++;
351357
}
352358
353359
if(y > plusThreshold){
354-
Serial.println(F("Collision front"));
360+
Serial.println(F("- Collision front"));
355361
delay(500);
356362
}
357363
358364
if(y < minusThreshold){
359-
Serial.println(F("Collision back"));
365+
Serial.println(F("- Collision back"));
360366
delay(500);
361367
}
362368
363369
if(x < minusThreshold){
364-
Serial.println(F("Collision right"));
370+
Serial.println(F("- Collision right"));
365371
delay(500);
366372
}
367373
368374
if(x > plusThreshold){
369-
Serial.println(F("Collision left"));
375+
Serial.println(F("- Collision left"));
370376
delay(500);
371377
}
372378
}
373379
380+
// Read magnetometer data in all three directions task
374381
void magnetometer_task(){
375-
// read magnetic field in all three directions
376382
IMU.readMagneticField(x, y, z);
377383
378-
if(x < 0){
384+
if(x < 0) {
379385
ledvalue = -(x);
380386
}
381-
else{
387+
else {
382388
ledvalue = x;
383389
}
384390
@@ -387,23 +393,23 @@ void magnetometer_task(){
387393
}
388394
389395
// For debugging purposes
390-
void Save_Debug_Buffer(void) {
391-
if (Count < DUMP_BUFFER_SIZE) {
392-
GoodBuffer[Count] = good;
393-
BadBuffer[Count] = bad;
396+
void save_debug_buffer(void) {
397+
if (count < DUMP_BUFFER_SIZE) {
398+
GoodBuffer[count] = good;
399+
BadBuffer[count] = bad;
394400
Disp_Debug_Buffer();
395-
Count++;
401+
count++;
396402
}
397403
}
398404
399-
void Disp_Debug_Buffer(){
405+
void disp_debug_buffer(){
400406
// Simple log of Good or Bad Pass Marks during runtime
401407
Serial.println(F("\n Strategic Array Dump Result >>"));
402408
Serial.print(F("Good Marks: "));
403-
Serial.println(GoodBuffer[Count]);
409+
Serial.println(GoodBuffer[count]);
404410
405411
Serial.print(F("Bad Marks: "));
406-
Serial.println(BadBuffer[Count]);
412+
Serial.println(BadBuffer[count]);
407413
}
408414
409415
void debug_stop(){
@@ -412,19 +418,19 @@ void debug_stop(){
412418
}
413419
```
414420

415-
The complete code as shown unifies accelerometer, gyroscope, and magnetometer into a single code structure. As it involves tasks from different modules, it is separated into different functions and executed in a more identifiable manner. It includes the **Strategic Array Dump** to understand exactly how the code operates. The `good` and `bad` marks are located at the points of interest, and will dump into assigned arrays to be able to display at the end of the code.
421+
As shown, the complete code unifies the accelerometer, gyroscope, and magnetometer into a single code structure. As it involves tasks from different modules, it is separated into different functions and executed in a more identifiable manner. The code includes a **trace code** technique for debugging (dump into an array) to understand precisely how the code operates. The `good` and `bad` marks are located at the points of interest in the code and will dump into assigned arrays to be able to display at the end of the code.
416422

417-
It is crucial to know when to stop the code to be able to debug the code. While the code above is capable of debugging at runtime, it is much easier to debug knowing when to or how to stop the code operation. For instance, stopping within first run, will give you following result.
423+
It is crucial to know when to stop the code from debugging. While the code shown above can be debugged at runtime, it is much easier to know when to stop or how to stop the code operation. For instance, stopping within the first run gives the following result:
418424

419425
![Strategic Array Dump - Only One Runtime Instance](assets/debug_dump_print.png)
420426

421-
In the serial monitor we can observe that it has 1 good mark and 1 bad mark. The good mark came from the gyroscope having ready the data for the use, while the bad mark comes from the accelerometer as the data was not ready. So it is possible to see the accelerometer does not have enough time to get the data ready before it gets to the measurement task. We can try by running certain amount of instances before it gets to array dump sector, and the result can be seen as follows.
427+
In the Arduino Serial Monitor, we can observe that it has a `1` good mark and a `1` bad mark. The good mark came from the gyroscope having ready the data for use, while the bad mark came from the accelerometer as the data was not ready. So it is possible to see that the accelerometer does not have enough time to get the data ready before it gets to the measurement task. We can try by running a certain number of instances before it gets to the array dump sector, and the result can be seen as follows:
422428

423429
![Strategic Array Dump - 5 Runtime Instance](assets/debug_dump_print_iter.png)
424430

425-
The accelerometer was able to perform its task without any issue with the exception of the first runtime instance, resulting in 9 good marks but 1 bad mark due to this behaviour. By this, it is possible to know the code structure does not misbehave, but for the first time when the device is starting, the accelerometer requires more time to be able to get the data ready in the first instance. The `Serial.println(F())` of module setups, and task runtimes also show us if the code was able to get past the operations without any issue.
431+
The accelerometer performed its task without any issue except the first runtime instance, resulting in `9` good marks but `1` bad mark due to this behavior. The `Serial.println(F())` instruction of module setups and task runtimes also shows us if the code could get past the operations without any issue. By this, it is possible to know the code structure does not misbehave, but for the first time when the device is starting, the accelerometer requires more time to get the data ready in the first instance.
426432

427-
Additionally, it is possible to modify the loop code by adding simply GPIO 13 to drive High and Low to measure the time it takes to complete 3 module tasks. It will be also helpful to understand the power consumption it draws from this runtime instance.
433+
Additionally, it is possible to modify the loop code by simply adding a `digitalWrite(LED_BUILTIN, HIGH)` instruction and a `digitalWrite(LED_BUILTIN, LOW)` instruction to measure the time it takes to complete the three module tasks. It will also be helpful to understand the power consumption it draws from this runtime instance:
428434

429435
```arduino
430436
void loop() {
@@ -451,9 +457,9 @@ Debugging is a necessary step for developing robust and reliable embedded system
451457
* **Localization**: this phase involves narrowing the range of possibilities until the bug can be isolated to a specific code segment in the embedded software.
452458
* **Correction**: this phase involves eradicating the bug from the software.
453459

454-
Knowing the potential causes of bugs allows us to adopt strategies that minimize their occurrence. To aid this process, lots of different debugging technniques and external devices are present. Maybe some software designs does not require the usage of external debuggers for example, but when the software involves different levels of requirements and specially when it requires scalability, things change drastically for the development process. The debugging techniques and the external debuggers will support this development process, thus granting refined software. You will know how the device will behave in most cases with the software, its computational performance, and even achieve non-power hungry devices due to clean memory management.
460+
Knowing the potential causes of bugs allows us to adopt strategies that minimize their occurrence. Many different debugging techniques and external devices are present to aid this process. Maybe some software designs do not require the usage of external debuggers, for example. However, when the software involves different requirements, especially scalability, things change drastically for the development process. The debugging techniques and the external debuggers will support this development process, thus granting sophisticated software. In most cases, we will know how the device will behave with the software, its computational performance, and even achieve non-power hungry devices due to clean memory management.
455461

456-
The debugging may be an overlooked aspect of the development, but it is the most serious yet crucial tool that exists for the development. If you desire to develop a genuine device, the debugging process should always be implemented, to achieve its genuine performance.
462+
Debugging may be an overlooked aspect of development, but it is the most serious yet crucial tool for development. If we desire to develop a robust and reliable device, the debugging process should consistently be implemented to achieve this goals.
457463

458464
## Further Reading and Resources
459465

0 commit comments

Comments
 (0)