From 8cae1ab4fa09af995aa28b2f391b36b4cecfdefb Mon Sep 17 00:00:00 2001 From: Oseias Ferreira Date: Sat, 2 Feb 2019 18:31:32 -0200 Subject: [PATCH 1/2] Added new methods to implement optional buffer to store analog port timed readings, instead of delay interruptions. public: Update isReading setUseDelay startRead private: initBuffer readBuffer Added variables bool useDelay; double *analogBuffer; unsigned int bufferId; long lastRead; bool enableRead; Added constructor to set delay or buffer option. Added example to use this library without delay() interruptions. Updated keywords.txt. Removed unused volatile variables (it does not use interrupts). --- examples/WithoutDelay/WithoutDelay.ino | 138 +++++++++++++++++++++ keywords.txt | 8 +- src/NTC_Thermistor.cpp | 165 ++++++++++++++++++++++--- src/NTC_Thermistor.h | 74 ++++++++++- 4 files changed, 359 insertions(+), 26 deletions(-) create mode 100644 examples/WithoutDelay/WithoutDelay.ino 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..b15d0d2 100644 --- a/src/NTC_Thermistor.cpp +++ b/src/NTC_Thermistor.cpp @@ -11,11 +11,11 @@ #include "NTC_Thermistor.h" NTC_Thermistor::NTC_Thermistor( - const int pin, - const double referenceResistance, - const double nominalResistance, - const double nominalTemperatureCelsius, - const double bValue + const int pin, + const double referenceResistance, + const double nominalResistance, + const double nominalTemperatureCelsius, + const double bValue ) : NTC_Thermistor( pin, referenceResistance, nominalResistance, @@ -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 ) { - this->pin = pin; - this->referenceResistance = referenceResistance; - this->nominalResistance = nominalResistance; - this->nominalTemperature = celsiusToKelvins(nominalTemperatureCelsius); - this->bValue = bValue; - setReadingsNumber(readingsNumber); - setDelayTime(delayTime); - init(); } -inline void NTC_Thermistor::init() { - pinMode(this->pin, INPUT_PULLUP); +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; + this->enableRead = false; + this->analogBuffer = NULL; + setUseDelay(useDelay); + setDelayTime(delayTime); + setReadingsNumber(readingsNumber); +} + +/** + 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(); - } - return (analogSum / this->readingsNumber); + + //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; + } + + 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..96d3690 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) From 0c4d1f592e096552dae13d07b0c39bf486489e9c Mon Sep 17 00:00:00 2001 From: Oseias Ferreira Date: Sat, 2 Feb 2019 19:41:42 -0200 Subject: [PATCH 2/2] Fix indentation issues. --- src/NTC_Thermistor.cpp | 202 ++++++++++++++++++++--------------------- src/NTC_Thermistor.h | 62 ++++++------- 2 files changed, 132 insertions(+), 132 deletions(-) diff --git a/src/NTC_Thermistor.cpp b/src/NTC_Thermistor.cpp index b15d0d2..571c5ce 100644 --- a/src/NTC_Thermistor.cpp +++ b/src/NTC_Thermistor.cpp @@ -11,11 +11,11 @@ #include "NTC_Thermistor.h" NTC_Thermistor::NTC_Thermistor( - const int pin, - const double referenceResistance, - const double nominalResistance, - const double nominalTemperatureCelsius, - const double bValue + const int pin, + const double referenceResistance, + const double nominalResistance, + const double nominalTemperatureCelsius, + const double bValue ) : NTC_Thermistor( pin, referenceResistance, nominalResistance, @@ -35,49 +35,49 @@ NTC_Thermistor::NTC_Thermistor( const int readingsNumber, const long delayTime ) : NTC_Thermistor( - pin, referenceResistance, - nominalResistance, - nominalTemperatureCelsius, - bValue, - readingsNumber, - delayTime, - NTC_DEFAULT_ENABLE_DELAY + 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 + 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; - this->enableRead = false; - this->analogBuffer = NULL; - setUseDelay(useDelay); - setDelayTime(delayTime); - setReadingsNumber(readingsNumber); + this->pin = pin; + pinMode(this->pin, INPUT_PULLUP); + this->referenceResistance = referenceResistance; + this->nominalResistance = nominalResistance; + this->nominalTemperature = celsiusToKelvins(nominalTemperatureCelsius); + this->bValue = bValue; + this->enableRead = false; + this->analogBuffer = NULL; + setUseDelay(useDelay); + setDelayTime(delayTime); + setReadingsNumber(readingsNumber); } /** - Allocate or reallocate buffer memory - when delay is disabled. + 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); - } + if (this->analogBuffer == NULL){ + this->analogBuffer = (double*)malloc(sizeof(double) * this->readingsNumber); + }else { + this->analogBuffer = (double*)realloc(this->analogBuffer, sizeof(double) * this->readingsNumber); + } } /** @@ -141,37 +141,37 @@ inline double NTC_Thermistor::readResistance() { inline double NTC_Thermistor::readVoltage() { double analogSum = 0; - //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(); + //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. + 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; - } - - if (this->isReading()) // return only buffered - return analogSum / this->bufferId + 1; - else - return analogSum / this->readingsNumber; + 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; + } + + if (this->isReading()) // return only buffered + return analogSum / this->bufferId + 1; + else + return analogSum / this->readingsNumber; } inline void NTC_Thermistor::sleep() { @@ -181,10 +181,10 @@ 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(); - } + // delay disabled - set buffer + if (!this->useDelay){ + initBuffer(); + } } void NTC_Thermistor::setDelayTime(const long newDelayTime) { @@ -193,62 +193,62 @@ void NTC_Thermistor::setDelayTime(const long newDelayTime) { /** - Enabled/Disable delay interrupts. - true: enable delay interrupts to readings. - false: disable delay and enable time based buffer to readings. + 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; + this->useDelay = delayEnable; - // delay disabled - set buffer - if (!this->useDelay){ - initBuffer(); - } + // delay disabled - set buffer + if (!this->useDelay){ + initBuffer(); + } } /** - Alias to Update(long now) + Alias to Update(long now) */ bool NTC_Thermistor::Update(){ - return Update(millis()); + 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) + 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 + bool result = false; //default return false - if (isReading() && !this->useDelay && now - this->lastRead > this->delayTime){ + if (isReading() && !this->useDelay && now - this->lastRead > this->delayTime){ - this->analogBuffer[this->bufferId] = analogRead(this->pin); - this->lastRead = now; - this->bufferId++; + 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; + 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 + 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(); + this->bufferId = 0; + this->enableRead = true; + this->lastRead = millis(); } /**{} diff --git a/src/NTC_Thermistor.h b/src/NTC_Thermistor.h index 96d3690..5bfd109 100644 --- a/src/NTC_Thermistor.h +++ b/src/NTC_Thermistor.h @@ -76,11 +76,11 @@ class NTC_Thermistor final { double bValue; unsigned int readingsNumber; long delayTime; - bool useDelay; - double *analogBuffer; - unsigned int bufferId; - long lastRead; - bool enableRead; + bool useDelay; + double *analogBuffer; + unsigned int bufferId; + long lastRead; + bool enableRead; public: @@ -137,7 +137,7 @@ class NTC_Thermistor final { @param delayTime - delay time between a temperature readings (ms). @param enableDelay - enable delay interruption - or disabled to use timed buffer without interruption - Update() function + or disabled to use timed buffer without interruption - Update() function must be called in loop cycle. */ @@ -149,7 +149,7 @@ class NTC_Thermistor final { double bValue, int readingsNumber, long delayTime, - bool enableDelay + bool enableDelay ); /** @@ -185,34 +185,34 @@ 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); + /* + 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); + /* + Populate buffer to avoid delay() in rotines. + */ + bool Update(); + bool Update(long now); - /* - To check if read is finish. - */ - bool isReading(){return enableRead;}; + /* + To check if read is finish. + */ + bool isReading(){return enableRead;}; - /* - Start read and buffer population - */ - void startRead(); + /* + Start read and buffer population + */ + void startRead(); private: /** - Buffer memory allocation + Buffer memory allocation */ inline void initBuffer(); @@ -226,10 +226,10 @@ class NTC_Thermistor final { */ inline double readVoltage(); - /** - Reads a voltage from the thermistor buffer. - */ - inline double readBuffer(); + /** + Reads a voltage from the thermistor buffer. + */ + inline double readBuffer(); /** Resistance to Kelvin conversion: