Where to start... I have code that has enabled all 3 timers on the arduino (0, 1, and 2) for Fast 8-bit PWM mode. As of right now, the Output Compare Registers are set to a static value (max 255) with the pre-scaler set as the clock speed. The interrupt routines run fine in my testing and perform read values from pins A0-A5, which will be stored into global variables (declared as volatile) which will be accessed later in the program.
Globals.h
extern volatile unsigned int PIN_A0_READ;
extern volatile unsigned int PIN_A1_READ;
extern volatile unsigned int PIN_A2_READ;
extern volatile unsigned int PIN_A3_READ;
extern volatile unsigned int PIN_A4_READ;
extern volatile unsigned int PIN_A5_READ;
Thermistor.h (Constructor, notice how the read value is passed by reference to the instantiated object. Thermistor class methods only perform reads and DO NOT WRITE!!!)
Thermistor(unsigned int *analogRead, int pinAddress, long int nominalResistance, float R2, float lineVoltage,
int beta = 3950, int nominalTemperature = 25) :
adcValue(analogRead), logicalPinAddress(pinAddress), nominalResistance(nominalResistance),
lineVoltage(lineVoltage), r2(R2), beta(beta), nominalTemperature(nominalTemperature){};
All seems well at first; I can print the global values without a problem in the main loop and I see that they are being read and written correctly over the Serial monitor. However, when I try printing more statistics over the Serial which are longer in size, it appears to stop reading the values from the ADC and completely hang the program toward the end of the buffer.
I've done some research on this topic and it seems as though the print() and println() functions from the Serial are supposed to block Interrupts by temporarily disabling them. This may explain why the ADC is not updating it's values.. perhaps the print statements occur first and the ISR does not have a chance to read the sensor value beforehand. If this were the case, it would not take very long to print a series of strings when the interrupts are disabled. And yet-- it takes a good 10 seconds or so to print out all of my statistics with a max baud rate (115200). If I disable all ISR's manually by commenting out their definitions, then print the same information, it prints things to the console almost instantaneously, which is indicating that the ISR's are in fact-- being re-enabled and triggered intermediately between the various Serial print calls. What's interesting is that the print behavior seems to work fine up until the very last few lines which is where the main loop stalls. Additionally, why are the global variables no longer being updated if functioning correctly?
The Arduino API should automatically flush the output buffer when it gets filled. But Strings are large in size, and I actually encountered some memory fragmentation issues prior when printing very large strings all at once. To avoid this as much as possible, I have a small check implemented in my printConfig() method which forces the buffer to flush() if the Arduino does not have less than 32 bytes available on the heap. This implies that I am only really trying to print 32 bytes or less to the Serial port at a time in this function, and performing a mem-check and flushing in between only when it is necessary. This seems to work fairly reliably and it does not stall the program when only trying to print and call a single getter method from the class.
I do not really know the cause of this weird behavior. It only stalls when trying to iterate between multiple Thermistor class objects and invoking the printConfig() method. The stuff that does print out, does not have an updated read value from the ADC.
What is going on here?
Thermistor.cpp (Note: the ArduinoSTL is a library ports over the std namespace. Changing this to the print() println() methods from the Arduino.h API makes no difference at all in the buggy behavior)
void Thermistor::printConfig()
{
for (int j = 0; j < 10; ++j)
{
// Check to see if SRAM memory available is less than 32 bytes to load string.
if (freeMemory() < 12 + 20) // Largest value size is 12 (long double). Prompt size is < 20 bytes.
{
// If it is, flush to the Serial buffer to free up space.
std::cout.flush();
}
else
{
switch(j)
{
case 0:
std::cout << "Logical Pin Address: " << getLogicalPinAddress() << " ";
break;
case 1:
std::cout << "Analog Read: " << getAdcValue() << " ";
break;
case 2:
std::cout << "Nominal Resistance: " << getNominalResistance() << " ";
break;
case 3:
std::cout << "Beta Value: " << getBeta() << " ";
break;
case 4:
std::cout << "Supply Voltage: " << getLineVoltage() << " ";
break;
case 5:
std::cout << "Voltage Output: " << getVo() << " ";
break;
case 6:
std::cout << "R1: " << getR1() << " ";
break;
case 7:
std::cout << "R2: " << getR2() << " ";
break;
case 8:
std::cout << "Temperature (C): " << getTemperatureCelsius() << " ";
break;
case 9:
std::cout << "Temperature (F): " << getTemperatureFahrenheit() << " ";
break;
}
}
std::cout << '\n';
}
std::cout.flush();
}
main.cpp
// Iterate through vector of Thermistors
for (int i = 0; i < sensors.size(), ++i;){
Thermistor * T;
T = &sensors.at(i); // get reference to object inside.
T->printConfig(); // print out the Thermistor Statistics.
std::cout << std::endl; // newline betweeen each probe for readability.
}
Serial Monitor results
Logical Pin Address: 15
Analog Read: 0
Nominal Resistance: 20000
Beta Value: 3950
Supply Voltage: 5.00
Voltage Output: 0.00
R1: inf
R2: 20000.00
Temperature (C): inf
Temperature (F): 0.00
Logical Pin Address: 16
Analog Read: 0
Nominal Resistance: 20000
Beta Value: 3950
Supply Voltage: 5.00
Voltage Output: 0.00
R1: inf
R2: 20000.00
Temperature (C): inf
Temperature (F): ovf
Logical Pin Address: 17
Analog Read: 0
Nominal Resistance: 20000
Beta Value: 3950
Supply Voltage: 5.00
Voltage Output: 0.00
R1: inf
R2: 20000.00
Temperature (C): inf
Temperature (F): ovf
Logical Pin Address: 18
Analog Read: 0
Nominal Resistance: 20000
Beta Value: 3950
Supply Voltage: 5.00
Voltage Output: 0.00
R1: inf
R2: 20000.00
Temperature (C): inf
Temperature (F): ovf
Logical Pin Address: 19
Analog Read: 0
Nominal Resistance: 20000
Beta Value: 3950
Supply Voltage: 5.00
Voltage Output: 0.00
R1: inf
R2: 20000.00
Temperature (C): inf
Temperature (F): 0.00