I am running out of ideas of what may be causing this problem, and I would appreciate some help identifying anything I am overlooking.
Quick Problem Summary
A variable gets set to 32767 quite often and I am unsure why. I tried checking if it was a types problem, if there was somewhere in my code it could overflow, any division by 0, initialising all variables in all sections of the code, and have now tried to cast all relevant variables to int
. What else could I try?
This is how this variable gets set in a C++ function:
readValue = readAverage(A0);
targetValue = 2000; // Some constant number set beforehand
myVariable = targetValue - static_cast<int>(round(readValue));
// After some operations that only check if myVariable is within a range
// There are several states in which LOG_myVariable can get set in case there is an error where data wants to get logged
LOG_myVariable = myVariable
All of the variables above are public and get initialised to 0. See in the context section to see how the readAverage
function works.
This code block above gets repeated thousands of times in a loop and exits when I send an interrupt. LOG_myVariable
only gets set in the method above. Sometimes it gives me normal values that I would expect, but it is returning 32767 very often. Is this some C++ syntax or function I am overlooking?
Some context:
An Arduino Due is using the MATLAB 2019 - Arduino Support Package Add-on. The variables described above are stored in memory and are dynamically overwritten during every logging function. I send them back to MATLAB via the C++ commandHandler
as:
byte dataOut[2] = {
highByte(LOG_myVariable),
lowByte(LOG_myVariable)
};
sendResponseMsg(commandID, dataOut, 2);
In MATLAB, I convert it within a method after requesting the dataOut
via sendCommand
:
[dataOut] = sendCommand(arduinoObj, arduinoObj.LibraryName, commandID, dataIn);
% Converts the two High and Low bytes from [dataOut] into a single integer.
myVariableMATLAB = 256 * dataOut(1) + dataOut(2);
readAverage
works like this:
/*
Reads the raw ADC sampled value of a pin an averagePoints amount of times.
All the values get averaged and the function returns `outputAverage`.
Note
*/
int myClass::readAverage(const uint8_t pin) {
int i = 1, outputAverage = 0; // Iteration value, OutputAverage
double sum = 0, runningAverage = 0;
// Array Initialization
int readings[70] = { 0 };
for (i = 0; i <= 70; i++) {
if ((runningAverage >= 0) && (runningAverage <= 4096)) {
// First 10% readings to setup a runningAverage value
if (i < 70 * 0.1) {
readings[i] = static_cast<int>(analogRead(pin));
sum += readings[i];
runningAverage = static_cast<int>(sum/(i+1));
} else if (i >= 70 * 0.1) {
// Normal Operation
readings[i] = static_cast<int>(analogRead(pin));
// Filtering Outliers
// If xReading is within [LOWER_PERCENTAGE, HIGHER_PERCENTAGE] * runningAverage range.
if ((readings[i] >= LOWER_PERCENTAGE * runningAverage)
&& (readings[i] < HIGHER_PERCENTAGE * runningAverage)) {
sum += readings[i];
runningAverage = static_cast<int>(sum/(i+1));
} else {
// Enter Error/ Out of Bounds Log Mode, how?
// Meant to filter out
}
}
} else {
/* Enter Unknown Error Mode
Note it defaults to a single measurement, but no signal is sent to mention this.
*/
runningAverage = static_cast<int>(analogRead(pin));
}
}
outputAverage = static_cast<int>(round(runningAverage));
return outputAverage;
}
Any tips on improving the code/logic are always appreciated too!