#include <array>
#include <utility>
#include <cstddef>
#include <math.h>
// Our lookup table function. No more implementation needed!
// https://joelfilho.com/blog/2020/compile_time_lookup_tables_in_cpp/
template<std::size_t Length, typename Generator>
constexpr auto lut(Generator&& f){
using content_type = decltype(f(std::size_t{0}));
std::array<content_type, Length> arr {};
for(std::size_t i = 0; i < Length; i++){
arr[i] = f(i);
}
return arr;
}
//------------------------------------------------
// Usage, with inline variable templates requires C++17
//------------------------------------------------
template<signed minTemp,std::size_t Length>
inline constexpr auto thermistor_lut = lut<Length>([](std::size_t n){
const unsigned beta = 3435;
const unsigned R_at25C = 10000;
const unsigned R_Pullup = 22000;
const unsigned adcValAtPullupVoltage = 57600;
unsigned NtcResVal = R_at25C * exp(beta*((1/(273.15+n+minTemp)) - (1/298.15)));
unsigned AdcValAtnTempC = (NtcResVal*adcValAtPullupVoltage)/(NtcResVal+R_Pullup);
return AdcValAtnTempC;
});
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
void loop() {
delay(10); // this speeds up the simulation
const signed minTemp = -20;
auto my_lut = thermistor_lut<minTemp, 120>;
int32_t baseTemp, fineTemp = 0;
double floatTemp = minTemp;
static uint64_t rawAdcCount = 30000;
rawAdcCount++;
auto it = std::lower_bound(my_lut.begin(), my_lut.end(), rawAdcCount, std::greater_equal());
if(it != my_lut.begin())
{
baseTemp = std::distance(my_lut.begin(), (it-1)) + minTemp;
fineTemp = (100*(*(it-1)-rawAdcCount))/(*(it-1) - *it);
floatTemp = baseTemp + (fineTemp/100.0);
}
Serial.printf("Temperature is: %.2f for ADC value: %d \n", floatTemp, rawAdcCount);
}
//See compiler output at https://godbolt.org/z/eacf9MPeY