Description
Hi guys,
I lost several hours to solve this strange bug. The board I am using is Arduino Nano BLE Sense 33.
In short, I use sprintf to format sensor readings before Serial.print() in loop(). At the start, the program works perfectly. However, after many iterations of loop() the system hangs.
After I checked the program carefully, I found It's pressure sensor reading function causing the crash.
pressure = BARO.readPressure();
If I comment out this function, or simply replace this line with:
pressure = 5;
The program will not crash anymore.
Why I found the pressure sensor cause the froze:
I changed the code like this:
Serial.println("test1");
pressure = BARO.readPressure();
Serial.println(pressure);
Serial.println("test2");
After several loops, the program freezes after the serial port outputs "test1". No output and No error printed in serial port afterward.
What weird is that, if I comment out all the other sensor reading functions except the pressure sensor, the program can run further. (At least for 20 minutes. I don't know if it will crash after a longer period)
Well the code crashes here in the library:
Lines 60 to 63 in d3d6bac
Here is my sketch: simply read some sensor value, format them and print to the serial port.
Serial.println("test1");
// pressure = BARO.readPressure();
pressure = 5;
Serial.println("test2");#include <Arduino_APDS9960.h>
#include <Arduino_LSM9DS1.h>
#include <Arduino_LPS22HB.h>
#include <Arduino_HTS221.h>
#include <PDM.h>
// Parameters for Microphone
#define MICROPHONE_BUFFER_SIZE_IN_WORDS (256U)
#define MICROPHONE_BUFFER_SIZE_IN_BYTES (MICROPHONE_BUFFER_SIZE_IN_WORDS * sizeof(int16_t))
/* MP34DT05 Microphone data buffer with a bit depth of 16. Also a variable for the RMS value */
int16_t microphoneBuffer[MICROPHONE_BUFFER_SIZE_IN_WORDS];
int16_t microphoneRMSValue;
// /* Used as a simple flag to know when microphone buffer is full and RMS value
// * can be computed. */
bool microphoneBufferReadyFlag = false;
void Microphone_availablePDMDataCallback()
{
// query the number of bytes available
int bytesAvailable = PDM.available();
if(bytesAvailable == MICROPHONE_BUFFER_SIZE_IN_BYTES)
{
PDM.read(microphoneBuffer, bytesAvailable);
microphoneBufferReadyFlag = true;
}
}
float Micophone_computeRMSValue()
{
float rms = 0;
// Square difference between each set of elements
for (int i = 0; i < MICROPHONE_BUFFER_SIZE_IN_WORDS; i++) {
rms += microphoneBuffer[i] * microphoneBuffer[i];
}
return sqrt((float)rms/MICROPHONE_BUFFER_SIZE_IN_WORDS);
}
void setup() {
Serial.begin(9600);
while (!Serial); // Wait for serial monitor to open
if (!APDS.begin()) {
Serial.println("Error initializing APDS9960 sensor.");
while (true); // Stop forever
}
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
while (1);
}
if (!BARO.begin()) {
Serial.println("Failed to initialize pressure sensor!");
while (1);
}
if (!HTS.begin()) {
Serial.println("Failed to initialize humidity temperature sensor!");
while (1);
}
/* PDM setup for MP34DT05 microphone */
/* configure the data receive callback to transfer data to local buffer */
PDM.onReceive(Microphone_availablePDMDataCallback);
/* Initialise single PDM channel with a 16KHz sample rate (only 16kHz or 44.1kHz available */
if (!PDM.begin(1, 16000))
{
Serial.println("Failed to start PDM!");
/* Hacky way of stopping program executation in event of failure. */
while(1);
}
else
{
/* Gain values can be from 0 to 80 (around 38db). Check out nrf_pdm.h
* from the nRF528x-mbedos core to confirm this. */
/* This has to be done after PDM.begin() is called as begin() always
* sets the gain as the default PDM.h value (20).
*/
PDM.setGain(50);
}
}
int proximity = 0;
int r = 0, g = 0, b = 0;
unsigned long lastUpdate = 0;
float x1, y, z1, x2, y2, z2, x3, y3, z3, pressure, temperature, humidity, sound;
const int size = 50;
char event[size];
void loop() {
// check if a gesture reading is available
if (APDS.gestureAvailable()) {
int gesture = APDS.readGesture();
lastUpdate = millis();
switch (gesture) {
case GESTURE_UP:
snprintf_P(event, size, PSTR("UP[%013lu,%013lu](%i)$"), lastUpdate, lastUpdate, 1);
Serial.println(event);
break;
case GESTURE_DOWN:
snprintf_P(event, size, PSTR("DOWN[%013lu,%013lu](%i)$"), lastUpdate, lastUpdate, 1);
Serial.println(event);
break;
case GESTURE_LEFT:
snprintf_P(event, size, PSTR("LEFT[%013lu,%013lu](%i)$"), lastUpdate, lastUpdate, 1);
Serial.println(event);
break;
case GESTURE_RIGHT:
snprintf_P(event, size, PSTR("RIGHT[%013lu,%013lu](%i)$"), lastUpdate, lastUpdate, 1);
Serial.println(event);
break;
default:
// ignore
break;
}
delay(1000);
}
// Check if a proximity reading is available.
if (APDS.proximityAvailable()) {
proximity = APDS.readProximity();
}
// check if a color reading is available
if (APDS.colorAvailable()) {
APDS.readColor(r, g, b);
}
if(IMU.accelerationAvailable()){
IMU.readAcceleration(x1, y, z1);
}
if (IMU.gyroscopeAvailable()) {
IMU.readGyroscope(x2, y2, z2);
}
if (IMU.magneticFieldAvailable()) {
IMU.readMagneticField(x3, y3, z3);
}
if(microphoneBufferReadyFlag)
{
sound = Micophone_computeRMSValue();
microphoneBufferReadyFlag = false;
}
pressure = BARO.readPressure();
temperature = HTS.readTemperature();
humidity = HTS.readHumidity();
// Print updates every 200ms
if (millis() - lastUpdate > 200) {
lastUpdate = millis();
snprintf_P(event, size, PSTR("proximity[%013lu,%013lu](%i)$"), lastUpdate, lastUpdate, proximity);
Serial.println(event);
snprintf_P(event, size, PSTR("pressure[%013lu,%013lu](%i)$"), lastUpdate, lastUpdate, (int)pressure);
Serial.println(event);
snprintf_P(event, size, PSTR("temperature[%013lu,%013lu](%i)$"), lastUpdate, lastUpdate, (int)temperature);
Serial.println(event);
snprintf_P(event, size, PSTR("humidity[%013lu,%013lu](%i)$"), lastUpdate, lastUpdate, (int)humidity);
Serial.println(event);
snprintf_P(event, size, PSTR("RMS_Sound[%013lu,%013lu](%i)$"), lastUpdate, lastUpdate, (int)sound);
Serial.println(event);
Serial.println();
Serial.print("rgb=");
Serial.print(r);
Serial.print(",");
Serial.print(g);
Serial.print(",");
Serial.println(b);
Serial.print("Vibration=");
Serial.print(x1);
Serial.print(",");
Serial.print(y);
Serial.print(",");
Serial.println(z1);
Serial.print("Gyroscope=");
Serial.print(x2);
Serial.print(",");
Serial.print(y2);
Serial.print(",");
Serial.println(z2);
Serial.print("MagneticField=");
Serial.print(x3);
Serial.print(",");
Serial.print(y3);
Serial.print(",");
Serial.println(z3);
Serial.println();
Serial.println();
}
}