diff --git a/examples/WithoutDelay/WithoutDelay.ino b/examples/WithoutDelay/WithoutDelay.ino new file mode 100644 index 0000000..06440f7 --- /dev/null +++ b/examples/WithoutDelay/WithoutDelay.ino @@ -0,0 +1,138 @@ +#include + +/* + Thermistor. + + Reads a temperature from the NTC 3950 thermistor and displays + it in the default Serial. + + https://github.com/YuriiSalimov/NTC_Thermistor + + Created by Oséias Ferreira, January, 2019 + based on code written by Yuri Shalimov, April, 2018. + Released into the public domain. +*/ +#include + +#define SENSOR_PIN A1 +#define REFERENCE_RESISTANCE 8000 +#define NOMINAL_RESISTANCE 100000 +#define NOMINAL_TEMPERATURE 25 +#define B_VALUE 3950 + +/** + How many readings are taken to determine a mean temperature. + The more values, the longer a calibration is performed, + but the readings will be more accurate. +*/ +#define READINGS_NUMBER 10 + +/** + Delay time between a temperature readings + from the temperature sensor (ms). +*/ +#define DELAY_TIME 20 + +#define DELAY_ENABLE false + +const int printInterval = 2000; //sec +long lastPrint = 0; + +uint8_t numRead = 10; + +NTC_Thermistor* thermistor = NULL; + +void setup() { + Serial.begin(9600); + Serial.println("NTC_Thermistor Disable Delay example."); + thermistor = new NTC_Thermistor( + SENSOR_PIN, + REFERENCE_RESISTANCE, + NOMINAL_RESISTANCE, + NOMINAL_TEMPERATURE, + B_VALUE, + READINGS_NUMBER, + DELAY_TIME, + DELAY_ENABLE + ); + /* or + thermistor = new NTC_Thermistor( + SENSOR_PIN, + REFERENCE_RESISTANCE, + NOMINAL_RESISTANCE, + NOMINAL_TEMPERATURE, + B_VALUE + ); + thermistor->setReadingsNumber(READINGS_NUMBER); + thermistor->setDelayTime(DELAY_TIME); + thermistor->setUseDelay(DELAY_ENABLE); + */ + + // start first read + thermistor->startRead(); +} + +void loop() { + unsigned long now = millis(); // to control Serial.print + unsigned long now_us = 0; // to measure spent time + + if (thermistor->isReading()){ + now_us = micros(); + if (thermistor->Update(now)) { + unsigned long updateTime = micros() - now_us; + Serial.print("updateTime: "); + Serial.println(String(updateTime) + " us"); + } + } + else{ //read is finished + if (now - lastPrint > printInterval){ // print only after wait printInterval + + now_us = micros(); // reset + + double celsius = thermistor->readCelsius(); + double kelvin = thermistor->readKelvin(); + double fahrenheit = thermistor->readFahrenheit(); + + unsigned long readTime = micros() - now_us; + + Serial.print("NoDelay\t"); + Serial.print("Temperature: "); + Serial.print(String(celsius) + " C, "); + Serial.print(String(kelvin) + " K, "); + Serial.print(String(fahrenheit) + " F "); + Serial.print("readTime: "); + Serial.println(String(readTime) + " us "); + + //enable delay + thermistor->setUseDelay(true); + + now_us = micros(); // reset + + celsius = thermistor->readCelsius(); + kelvin = thermistor->readKelvin(); + fahrenheit = thermistor->readFahrenheit(); + + readTime = micros() - now_us; + + Serial.print("Delay\t"); + Serial.print("Temperature: "); + Serial.print(String(celsius) + " C, "); + Serial.print(String(kelvin) + " K, "); + Serial.print(String(fahrenheit) + " F "); + Serial.print("ReadTime: "); + Serial.println(String(readTime) + " us "); + + //disable delay + thermistor->setUseDelay(false); + numRead++; + thermistor->setReadingsNumber(numRead); + if (numRead == 20) numRead=5; + + + lastPrint = now; + + // read again + thermistor->startRead(); + } + } +} diff --git a/keywords.txt b/keywords.txt index 56e8e58..2dd5d41 100644 --- a/keywords.txt +++ b/keywords.txt @@ -12,9 +12,13 @@ NTC_Thermistor KEYWORD1 # Methods and Functions (KEYWORD2) # ########################################## +Update KEYWORD2 +isReading KEYWORD2 readCelsius KEYWORD2 -readKelvin KEYWORD2 readFahrenheit KEYWORD2 readFarenheit KEYWORD2 -setReadingsNumber KEYWORD2 +readKelvin KEYWORD2 setDelayTime KEYWORD2 +setReadingsNumber KEYWORD2 +setUseDelay KEYWORD2 +startRead KEYWORD2 diff --git a/src/NTC_Thermistor.cpp b/src/NTC_Thermistor.cpp index 97a7595..571c5ce 100644 --- a/src/NTC_Thermistor.cpp +++ b/src/NTC_Thermistor.cpp @@ -34,19 +34,50 @@ NTC_Thermistor::NTC_Thermistor( const double bValue, const int readingsNumber, const long delayTime +) : NTC_Thermistor( + pin, referenceResistance, + nominalResistance, + nominalTemperatureCelsius, + bValue, + readingsNumber, + delayTime, + NTC_DEFAULT_ENABLE_DELAY +) { +} + +NTC_Thermistor::NTC_Thermistor( + const int pin, + const double referenceResistance, + const double nominalResistance, + const double nominalTemperatureCelsius, + const double bValue, + const int readingsNumber, + const long delayTime, + const bool useDelay ) { this->pin = pin; + pinMode(this->pin, INPUT_PULLUP); this->referenceResistance = referenceResistance; this->nominalResistance = nominalResistance; this->nominalTemperature = celsiusToKelvins(nominalTemperatureCelsius); this->bValue = bValue; - setReadingsNumber(readingsNumber); + this->enableRead = false; + this->analogBuffer = NULL; + setUseDelay(useDelay); setDelayTime(delayTime); - init(); + setReadingsNumber(readingsNumber); } -inline void NTC_Thermistor::init() { - pinMode(this->pin, INPUT_PULLUP); +/** + Allocate or reallocate buffer memory + when delay is disabled. +*/ +inline void NTC_Thermistor::initBuffer(){ + if (this->analogBuffer == NULL){ + this->analogBuffer = (double*)malloc(sizeof(double) * this->readingsNumber); + }else { + this->analogBuffer = (double*)realloc(this->analogBuffer, sizeof(double) * this->readingsNumber); + } } /** @@ -105,13 +136,42 @@ inline double NTC_Thermistor::readResistance() { with a slight delay. @return average thermistor voltage. */ + + inline double NTC_Thermistor::readVoltage() { double analogSum = 0; - for (int i = 0; i < this->readingsNumber; i++) { - analogSum += analogRead(this->pin); - sleep(); + + //delay enabled + if (this->useDelay){ + for (unsigned int i = 0; i < this->readingsNumber; i++){ + analogSum += analogRead(this->pin); + sleep(); + } + return (analogSum / this->readingsNumber); + } + // buffer enabled + else return this->readBuffer(); +} + +/** + Reads voltage readings stored in the buffer. + @return average thermistor voltage. +*/ + +inline double NTC_Thermistor::readBuffer() { + double analogSum = 0; + for (unsigned int i = 0; i < this->readingsNumber; i++){ + analogSum += this->analogBuffer[i]; + + // abort loop if buffer is incomplete + if (this->isReading() && i == this->bufferId) + break; } - return (analogSum / this->readingsNumber); + + if (this->isReading()) // return only buffered + return analogSum / this->bufferId + 1; + else + return analogSum / this->readingsNumber; } inline void NTC_Thermistor::sleep() { @@ -120,13 +180,78 @@ inline void NTC_Thermistor::sleep() { void NTC_Thermistor::setReadingsNumber(const int newReadingsNumber) { this->readingsNumber = validate(newReadingsNumber, NTC_DEFAULT_READINGS_NUMBER); + + // delay disabled - set buffer + if (!this->useDelay){ + initBuffer(); + } } void NTC_Thermistor::setDelayTime(const long newDelayTime) { this->delayTime = validate(newDelayTime, NTC_DEFAULT_DELAY_TIME); } + +/** + Enabled/Disable delay interrupts. + true: enable delay interrupts to readings. + false: disable delay and enable time based buffer to readings. +*/ +void NTC_Thermistor::setUseDelay(bool delayEnable){ + this->useDelay = delayEnable; + + // delay disabled - set buffer + if (!this->useDelay){ + initBuffer(); + } +} + + +/** + Alias to Update(long now) +*/ +bool NTC_Thermistor::Update(){ + return Update(millis()); +} + /** + Populate buffer with timed voltage read from the thermistor analog port. + this->delayTime value is used as interval to read analog port. + @return + true: if analog ports is read: + (enableRead=true and useDelay=false and (now - lastRead) > this->delayTime) + false: if nothing is executed + (enableRead=false or useDelay=true or (now - lastRead) < this->delayTime) +*/ +bool NTC_Thermistor::Update(long now){ + bool result = false; //default return false + + if (isReading() && !this->useDelay && now - this->lastRead > this->delayTime){ + + this->analogBuffer[this->bufferId] = analogRead(this->pin); + this->lastRead = now; + this->bufferId++; + + if (this->bufferId >= this->readingsNumber){ //finish read + this->bufferId = 0; //reset buffer index + this->enableRead = false; //stop read + } + result = true; + } + return result; +} + +/** + Start timed based readings when delay is disabled. + must needs call it before +*/ +void NTC_Thermistor::startRead(){ + this->bufferId = 0; + this->enableRead = true; + this->lastRead = millis(); +} + +/**{} Returns the data if it is positive, otherwise returns alternative data. */ diff --git a/src/NTC_Thermistor.h b/src/NTC_Thermistor.h index 9ef97d3..5bfd109 100644 --- a/src/NTC_Thermistor.h +++ b/src/NTC_Thermistor.h @@ -64,6 +64,7 @@ #define NTC_DEFAULT_READINGS_NUMBER 5 #define NTC_DEFAULT_DELAY_TIME 10 +#define NTC_DEFAULT_ENABLE_DELAY 1 class NTC_Thermistor final { @@ -73,8 +74,14 @@ class NTC_Thermistor final { double nominalResistance; double nominalTemperature; // in Celsius. double bValue; - volatile int readingsNumber; - volatile long delayTime; + unsigned int readingsNumber; + long delayTime; + bool useDelay; + double *analogBuffer; + unsigned int bufferId; + long lastRead; + bool enableRead; + public: /** @@ -117,6 +124,34 @@ class NTC_Thermistor final { long delayTime ); + /** + Constructor. + @param pin - an analog port number to be attached + to the thermistor. + @param referenceResistance - reference resistance. + @param nominalResistance - nominal resistance. + @param nominalTemperature - nominal temperature in Celsius. + @param bValue - b-value of a thermistor. + @param readingsNumber - how many readings are + taken to determine a mean temperature. + @param delayTime - delay time between + a temperature readings (ms). + @param enableDelay - enable delay interruption + or disabled to use timed buffer without interruption - Update() function + must be called in loop cycle. + + */ + NTC_Thermistor( + int pin, + double referenceResistance, + double nominalResistance, + double nominalTemperatureCelsius, + double bValue, + int readingsNumber, + long delayTime, + bool enableDelay + ); + /** Reads and returns a temperature in Celsius from the thermocouple. @@ -149,11 +184,37 @@ class NTC_Thermistor final { */ void setDelayTime(long newDelayTime); + + /* + Set enable/disable delay interruption to thermistor readings. + false: enable buffer and timer without interruption + true: enable delay interruption - default + */ + void setUseDelay(bool delayEnable); + + + /* + Populate buffer to avoid delay() in rotines. + */ + bool Update(); + bool Update(long now); + + /* + To check if read is finish. + */ + bool isReading(){return enableRead;}; + + /* + Start read and buffer population + */ + void startRead(); + + private: /** - Initialization of module. + Buffer memory allocation */ - inline void init(); + inline void initBuffer(); /** Calculates a resistance of the thermistor: @@ -165,6 +226,11 @@ class NTC_Thermistor final { */ inline double readVoltage(); + /** + Reads a voltage from the thermistor buffer. + */ + inline double readBuffer(); + /** Resistance to Kelvin conversion: 1/K = 1/K0 + 1/B * ln(R/R0)