When people refer to debugging as the general process of removing and fixing potential errors, that can be found in the digital layer (software) or even on the physical layer (hardware). These errors are called “bugs“, and this practice prevents future malfunctions or defects in the final product. It's common to happen when there are multiple modules coupled for a certain objective, a weak connection or a defective piece of hardware.
For all these reasons, we are going to talk about how to make debugging on the Arduino IDE and WisBlock.
Product listStep by stepHardware Debugging
Let's start with the hardware debugging. The first thing to do is to check connections. The right assembly and secured with the proper screws are vital for the correct working of the WisBlock.
Here are some examples of the module not properly connected to the WisBlock base:
Now, this is how it must be properly secured and connected to the WisBlock Base:
Another important item to check is the USB cable. The first thing is the proper connection between the module and the computer. You must check if in the connection are USB hubs, the cable is broken or is not very well used. In the next photos you will see the difference.
Next, and one of the most delicate are the antennas. The LoRa® antenna and the BLE antenna must be assembled with care and with a firm hand.
These are the regular problems that can occur with the WisBlock, but only with the assembly, antennas and USB cable. There are more things that you need to be aware of when debugging the hardware.
In the hardware debugging process it is important to even test the device with a simple code, such as blinking the built-in LED. The example in the Arduino IDE also works on the WisBlock 4631 core, you can find it in “File>Examples>01.Basics>Blink“.
Or here is the same code:
/*
Blink
Turns an LED on for one second, then off for one second, repeatedly.
Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your Arduino
model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products
modified 8 May 2014
by Scott Fitzgerald
modified 2 Sep 2016
by Arturo Guadalupi
modified 8 Sep 2016
by Colby Newman
This example code is in the public domain.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/Blink
*/
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
If you are using batteries or the solar panel with the WisBlock, make sure that the connector you’re using is adequate. The battery connector is the JST PHR with a pitch of 2.2 mm, and the one for the solar panel is JST ZHR with a pitch of 1.5 mm. Find them both in the RAKwireless store:
Electrical isolation is also very important for any electronic device
After finishing the P&D stage you can use a indoor or outdoor enclosure for your objective, in RAKwireless we got you covered with many options such as:
There is an important aspect to keep in mind when working with the WisBlock 4631 core, and that is the mapping for the ports. If you are using Arduino IDE, the number of the ports aren't the same as in the Arduino Uno or Arduino Mega, for example. That is why there is this table for mapping the I/O from the RAK4631 GPIO mapping to nRF52840 (and Arduino equivalent) GPIO ports:
Now let's dig deeper into the software debugging, starting with the Tracking Technique for debugging in Arduino IDE.
Usually, we use a print function as the common method to know where the code stops working, and if a condition or a function is correctly executing.
#include<bluefruit.h>
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
Serial.println("LED TURN ON"); // Track 1
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
Serial.println("LED TURN OFF"); //Track 2
}
As you can see in the images above, the code works if the LED is turned on sending the message, and if the LED is turned off also sends the message, this example works as intended.
Let's use another way to track a function and the general behavior of the code:
In the first line, we define the macro that we are going to use along all the code, TRACKING() will be the macro that we’ll use later.
The second line tells you the directory of the file that you are currently tracking.
The third line is a space.
The fourth line tells you the line where the current tracker is executed.
In the fifth line another space.
The sixth contains the name of the function, the return type and the type of each parameter.
#define TRACKING() \
Serial.print(__FILE__); \
Serial.print(':'); \
Serial.print(__LINE__); \
Serial.print(": "); \
Serial.println(__PRETTY_FUNCTION__); \
Serial.flush();
The way to use this technique is the next:
#define TRACKING() \
Serial.print(__FILE__); \
Serial.print(':'); \
Serial.print(__LINE__); \
Serial.print(": "); \
Serial.println(__PRETTY_FUNCTION__); \
Serial.flush();
#include<bluefruit.h>
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
TRACKING();
Serial.println("LED TURN ON");
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
TRACKING();
delay(1000); // wait for a second
Serial.println("LED TURN OFF");
}
As you can see the serial port prints the line where is the file to track, the line where “TRACKING()” is, and the function that is executing.
C:\Users\Harold Duarte\Documents\Arduino\Debugging_example\Debugging_example.ino:20: void loop()
The same goes for the other “TRACKING()”, but in line 23:
C:\Users\Harold Duarte\Documents\Arduino\Debugging_example\Debugging_example.ino:23: void loop()
Now let's use it in a more long a complicated code. For example, the reading and printing of the RAK1906 environmental sensor:
/**
@file RAK1906_Environment_BEM680.ino
@author rakwireless.com
@brief Setup and read values from bme680 sensor
@version 0.1
@date 2020-12-28
@copyright Copyright (c) 2020
**/
#define TRACKING() \
Serial.print(__FILE__); \
Serial.print(':'); \
Serial.print(__LINE__); \
Serial.print(": "); \
Serial.println(__PRETTY_FUNCTION__); \
Serial.flush();
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME680.h> // Click to install library: http://librarymanager/All#Adafruit_BME680
Adafruit_BME680 bme;
// Might need adjustments
#define SEALEVELPRESSURE_HPA (1010.0)
void bme680_init()
{
Wire.begin();
TRACKING();
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME680 sensor, check wiring!");
return;
}
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C for 150 ms
}
void bme680_get()
{
TRACKING();
Serial.print("Temperature = ");
Serial.print(bme.temperature);
Serial.println(" *C");
Serial.print("Pressure = ");
Serial.print(bme.pressure / 100.0);
Serial.println(" hPa");
Serial.print("Humidity = ");
Serial.print(bme.humidity);
Serial.println(" %");
Serial.print("Gas = ");
Serial.print(bme.gas_resistance / 1000.0);
Serial.println(" KOhms");
Serial.println();
}
void setup()
{TRACKING();
// Initialize the built in LED
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// Initialize Serial for debug output
Serial.begin(115200);
time_t serial_timeout = millis();
// On nRF52840 the USB serial is not available immediately
while (!Serial)
{
if ((millis() - serial_timeout) < 5000)
{
delay(100);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
else
{
break;
}
}
bme680_init();
}
void loop()
{TRACKING();
if (! bme.performReading()) {
Serial.println("Failed to perform reading :(");
return;
}
bme680_get();
delay(5000);
}
This is the output in the serial monitor., As you can see there is a change for the first reading and the rest, let's dig a bit more into it.
Line 1 shows that for the first time the sensor calls the function void bme680_init()
just once.
C:\Users\HAROLD~1\AppData\Local\Temp\arduino_modified_sketch_856054\RAK1906_Environment_BME680.ino:29: void bme680_init()
C:\Users\HAROLD~1\AppData\Local\Temp\arduino_modified_sketch_856054\RAK1906_Environment_BME680.ino:93: void loop()
C:\Users\HAROLD~1\AppData\Local\Temp\arduino_modified_sketch_856054\RAK1906_Environment_BME680.ino:45: void bme680_get()
Temperature = 30.20 *C
Pressure = 873.11 hPa
Humidity = 65.07 %
Gas = 6.56 KOhms
And for the rest of the iterations in the reading of the sensor, there are no more callings for this function because is used on the void Setup, and this function only runs once.
C:\Users\HAROLD~1\AppData\Local\Temp\arduino_modified_sketch_856054\RAK1906_Environment_BME680.ino:93: void loop()
C:\Users\HAROLD~1\AppData\Local\Temp\arduino_modified_sketch_856054\RAK1906_Environment_BME680.ino:45: void bme680_get()
Temperature = 29.83 *C
Pressure = 873.12 hPa
Humidity = 63.94 %
Gas = 5.71 KOhms
Other common problems in software are the BSP not working properly and the Bootloader not being updated. You can check the bootloader tutorials that we published on Hackster:
- First steps with WisBlock: Update the Bootloader (via BLE)
- First steps with WisBlock: Update the Bootloader (via USB)
And for the BSP on Arduino Install and VS code. We got you covered on Hackster too.
After this tutorial, you will understand the basics of hardware and software debugging, with the tracking technique. If you want to continue this journey, check the next tutorial: Debugging - VS Code.
Also, follow us on our Hackster profile and be part of our community, to keep updated with more projects and news.
Please share with us your comments, and doubts don’t forget to interact with us in the comment section.
Comments