Hi, I'm facing an extremely strange problem with a product I'm developing.
I've been getting significant idle current measurements (around 7 mA), and I couldn't for the love of me figure out what was causing it. I stripped the application code down and added parts in one by one, watching the idle current. The current while advertising is about 1 mA, which seems reasonable. I narrowed it down to a single C++ class instance. This is the class:
.h file:
#ifndef ERROR_MODEL_GYRO_LEARNING_H
#define ERROR_MODEL_GYRO_LEARNING_H
#include "error_model.h"
/**
* @brief An error model for gyroscopes, using an accelerometer to learn bias values.
*/
class ErrorModelGyroLearning: public ErrorModel {
private:
Vector3 m_lastAccel;
Vector3 m_bias;
float m_sampleRate;
float m_alpha;
uint32_t m_sampleCount = 0;
public:
/**
* @brief Constructs the error model instance.
*
* @param[in] sampleRate The rate at which the data is sampled
*/
ErrorModelGyroLearning(float sampleRate);
void processSample(SensorData& data) override;
};
#endif // ERROR_MODEL_GYRO_LEARNING_H
.cpp file:
#include "error_model_gyro_learning.h"
// Gyroscope noise level
#define FUZZY_GYRO_ZERO 0.20 * RAD_TO_DEG
#define FUZZY_GYRO_ZERO_SQUARED (FUZZY_GYRO_ZERO * FUZZY_GYRO_ZERO)
// Accelerometer noise level
#define FUZZY_ACCEL_ZERO 0.05
#define FUZZY_ACCEL_ZERO_SQUARED (FUZZY_ACCEL_ZERO * FUZZY_ACCEL_ZERO)
ErrorModelGyroLearning::ErrorModelGyroLearning(float sampleRate):
ErrorModel(SensorType::Gyroscope),
m_sampleRate(sampleRate),
m_alpha(2.0 / sampleRate) {}
// m_alpha(2.0 / 100.0) {}
void ErrorModelGyroLearning::processSample(SensorData& data) {
if(m_enabled) {
if(!m_valid) {
Vector3 delta_accel = m_lastAccel - data.accel;
m_lastAccel = data.accel;
if(delta_accel.squareLength() < FUZZY_ACCEL_ZERO_SQUARED &&
data.gyro.squareLength() < FUZZY_GYRO_ZERO_SQUARED)
{
// What we are seeing on the gyros should be bias only so learn from this
m_bias.setX((1.0 - m_alpha) * m_bias.x() + m_alpha * data.gyro.x());
m_bias.setY((1.0 - m_alpha) * m_bias.y() + m_alpha * data.gyro.y());
m_bias.setZ((1.0 - m_alpha) * m_bias.z() + m_alpha * data.gyro.z());
if(m_sampleCount < (5 * m_sampleRate)) {
m_sampleCount++;
if(m_sampleCount == (5 * m_sampleRate)) {
m_valid = true;
}
}
}
}
data.gyro -= m_bias;
}
}
In fact, I've narrowed it down to this line in the initializer list: m_alpha(2.0 / sampleRate) {}
. I'm passing in a sampleRate
value of 100. When the m_alpha
value is initialized using the sampleRate
value, the idle/advertising current draw is over 7 mA. When I initialize m_alpha
by hardcoding the sampleRate
value, I measure a current of 1 mA.
I'm simply stumped why a single line can cause this much current draw. Could it be a bug in the FPU?
In fact, just putting these three lines at the top of my main.cpp file causes the same behaviour (7 mA idle):
uint32_t interval = 10;
float sampleRate = 1000 / interval;
float m_alpha = 2.0 / sampleRate;
Commenting out the last line results in a current draw of around 1 mA.
Hoping to find the cause of this, because it's driving me insane! I'm using nRF52832 QFAA variant, SoftDevice 132 v3.0.0 and compiling using GCC/G++. My CFLAGS include -mfloat-abi=hard -mfpu=fpv4-sp-d16