From 4794e6adafa15013e95c7bbebfb8d78eeb50a7ad Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Sat, 1 Jun 2024 13:47:06 +0200 Subject: [PATCH] 0.3.0 PCR --- libraries/PCR/CHANGELOG.md | 15 ++- libraries/PCR/PCR.h | 91 ++++++------------- libraries/PCR/README.md | 68 +++++++++----- .../PCR_demo_DS18B20/PCR_demo_DS18B20.ino | 14 +-- .../PCR_demo_MAX31855/PCR_demo_MAX31855.ino | 12 +-- .../PCR_demo_aquarium/PCR_demo_aquarium.ino | 54 +++++++++++ .../PCR_demo_array/PCR_demo_array.ino | 30 +++--- .../PCR_demo_basic/PCR_demo_basic.ino | 6 +- .../PCR_demo_extended/PCR_demo_extended.ino | 12 +-- .../PCR_runtime_change/PCR_runtime_change.ino | 22 ++--- libraries/PCR/library.json | 2 +- libraries/PCR/library.properties | 2 +- libraries/PCR/test/unit_test_001.cpp | 78 +++++++++++++++- 13 files changed, 266 insertions(+), 140 deletions(-) create mode 100644 libraries/PCR/examples/PCR_demo_aquarium/PCR_demo_aquarium.ino diff --git a/libraries/PCR/CHANGELOG.md b/libraries/PCR/CHANGELOG.md index 5c351720..0553c333 100644 --- a/libraries/PCR/CHANGELOG.md +++ b/libraries/PCR/CHANGELOG.md @@ -6,6 +6,19 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.3.0] - 2024-06-01 +- breaking change + - duration in configuration function to **float seconds** as this is more convenient. + - update examples to use seconds. +- fix **getHoldTemp()** bug. +- fix signature of functions in 0.2.1 +- clean up code (remove commented sections). +- add **PCR_demo_aquarium.ino** example (for fun). +- update readme.md +- update unit tests + +---- + ## [0.2.1] - 2024-05-31 - add **setHeatPulseLength(uint16_t len)** to modify the pulse length of the heater / cooler. - add example **PCR_demo_DS18B20.ino** DS18B20 for PCR. @@ -16,11 +29,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - update readme.md - minor edits - ## [0.2.0] - 2024-05-30 - initial class version (published) ---- + ## [0.1.3] - 2024-05-30 - initial class version (not published) diff --git a/libraries/PCR/PCR.h b/libraries/PCR/PCR.h index 32b0dbc5..8d80f93a 100644 --- a/libraries/PCR/PCR.h +++ b/libraries/PCR/PCR.h @@ -3,7 +3,7 @@ // FILE: PCR.h // AUTHOR: Rob Tillaart // DATE: 2015-06-10 -// VERSION: 0.2.1 +// VERSION: 0.3.0 // PURPOSE: Arduino library for PCR process control. // URL: https://github.com/RobTillaart/PCR // https://forum.arduino.cc/t/problem-with-arduino-pcr-amplifies-of-dna/314808 @@ -12,7 +12,7 @@ #include "Arduino.h" -#define PCR_LIB_VERSION (F("0.2.1")) +#define PCR_LIB_VERSION (F("0.3.0")) enum PCRSTATE { PCR_STATE_IDLE = 0, @@ -40,52 +40,52 @@ public: // PARAMETERS - void setInitial(float Celsius, uint32_t ms) + void setInitial(float Celsius, float seconds) { _initialTemp = Celsius; - _initialTime = ms; + _initialTime = seconds * 1000; } float getInitialTemp() { return _initialTemp; } - uint32_t getInitialTime() { return _initialTime; } + float getInitialTime() { return _initialTime * 0.001; } - void setDenature(float Celsius, uint32_t ms) + void setDenature(float Celsius, float seconds) { _denatureTemp = Celsius; - _denatureTime = ms; + _denatureTime = seconds * 1000; } float getDenatureTemp() { return _denatureTemp; } - uint32_t getDenatureTime() { return _denatureTime; } + float getDenatureTime() { return _denatureTime * 0.001; } - void setAnnealing(float Celsius, uint32_t ms) + void setAnnealing(float Celsius, float seconds) { _annealingTemp = Celsius; - _annealingTime = ms; + _annealingTime = seconds * 1000; } float getAnnealingTemp() { return _annealingTemp; } - uint32_t getAnnealingTime() { return _annealingTime; } + float getAnnealingTime() { return _annealingTime * 0.001; } - void setExtension(float Celsius, uint32_t ms) + void setExtension(float Celsius, float seconds) { _extensionTemp = Celsius; - _extensionTime = ms; + _extensionTime = seconds * 1000; } float getExtensionTemp() { return _extensionTemp; } - float getExtensionTime() { return _extensionTime; } + float getExtensionTime() { return _extensionTime * 0.001; } - void setElongation(float Celsius, uint32_t ms) + void setElongation(float Celsius, float seconds) { _elongationTemp = Celsius; - _elongationTime = ms; + _elongationTime = seconds * 1000; } float getElongationTemp() { return _elongationTemp; } - float getElongationTime() { return _elongationTime; } + float getElongationTime() { return _elongationTime * 0.001; } void setHold(float Celsius) { _holdTemp = Celsius; } - float getHoldTemp() { return _extensionTemp; } + float getHoldTemp() { return _holdTemp; } // PROCESS CONTROL - void reset(int iterations) + void reset(uint16_t iterations) { _startTime = millis(); _cycles = iterations; @@ -94,7 +94,7 @@ public: debug(); } - int iterationsLeft() + uint16_t iterationsLeft() { return _cycles; } @@ -104,11 +104,6 @@ public: uint8_t process(float temperature) { _temperature = temperature; - /* 0.3.0 - if (_temperature < temp[_state]) heat(); - else if (_temperature > temp[_state]) cool(); - else off(); - */ switch(_state) { case PCR_STATE_IDLE: @@ -190,18 +185,19 @@ public: // HEATER / COOLER CONTROL + // ms = timing in milliseconds void setHeatPulseLength(uint16_t ms = 10) { if (ms > 1000) ms = 1000; _heatPulseLength = ms; } + // returns milliseconds. uint16_t getHeatPulseLength() { return _heatPulseLength; } - void heat() { digitalWrite(_heatPin, HIGH); @@ -222,26 +218,9 @@ public: digitalWrite(_coolPin, LOW); } - - // blocking version of single step. - // to be tested what to do with it - // could be a separate class / stand alone version. - /* - void keepTempTime(float temperature, uint32_t ms, float (*getTemp)()) - { - _startTime = millis(); - _temperature = temperature; - while (millis() - _startTime < ms) - { - if (getTemp() < _temperature ) heat(); - else if (getTemp() > _temperature) cool(); - else off(); - } - } - */ - // estimator timeLeft, assumes process is not stopped. - uint32_t timeLeft() + // returns value in seconds + float timeLeft() { uint32_t sum = 0; if (_state < PCR_STATE_DENATURE) sum += _initialTime; @@ -249,7 +228,7 @@ public: sum += _annealingTime * _cycles; sum += _extensionTime * _cycles; if (_state <= PCR_STATE_ELONGATION) sum += _elongationTime; - return sum; + return sum * 0.001; } @@ -257,12 +236,6 @@ protected: // development. void debug() { - // log for plotting temperature - // - // Serial.print(_cycles); - // Serial.print("\t"); - // Serial.println(_temperature); - // log for seeing state transitions. Serial.print(_startTime); Serial.print("\t"); @@ -278,16 +251,8 @@ protected: else if (_state == PCR_STATE_HOLD) Serial.println("\tHold"); } - -/* - // simplify the code. 0.3.0 - // maybe temperature only? - float _temp[6] = { 94, 94, 54, 76, 76, 14 }; - float _time[6] = { 0, 1, 1, 1, 1, -1 }; -*/ - - float _initialTemp = 94; - uint32_t _initialTime = 0; + float _initialTemp = 94; // °Celsius + uint32_t _initialTime = 0; // milliseconds float _denatureTemp = 94; uint32_t _denatureTime = 1000; float _annealingTemp = 54; @@ -303,7 +268,7 @@ protected: int _heatPin = 0; int _coolPin = 0; PCRSTATE _state = PCR_STATE_IDLE; - int _cycles = 0; + uint16_t _cycles = 0; uint32_t _startTime = 0; uint16_t _heatPulseLength = 10; // milliseconds. }; diff --git a/libraries/PCR/README.md b/libraries/PCR/README.md index 651a58b9..fe4497c3 100644 --- a/libraries/PCR/README.md +++ b/libraries/PCR/README.md @@ -19,7 +19,7 @@ Arduino library for PCR process control. **Experimental** -From wikipedia: +From Wikipedia: _The polymerase chain reaction (PCR) is a method widely used to make millions to billions of copies of a specific DNA sample rapidly, allowing scientists to amplify @@ -103,10 +103,21 @@ Some examples: - control an ice making machine. +#### Breaking change 0.3.0 + +Since 0.3.0 the timing of the 6 steps is done in seconds instead of milliseconds. +As the steps take up to 15 minutes of more, defining the time in seconds is a more +natural order of magnitude than milliseconds. +Note however that the internal math still is done in milliseconds so one can define +a step as taking 15.75 seconds = 15750 milliseconds. + +Pre 0.3.0 versions are now obsolete. + #### Related - https://en.wikipedia.org/wiki/Polymerase_chain_reaction - https://github.com/RobTillaart/PCR +- https://github.com/RobTillaart/Temperature scale conversions. - https://forum.arduino.cc/t/problem-with-arduino-pcr-amplifies-of-dna/314808 - https://www.scientificamerican.com/article/the-unusual-origin-of-the-polymeras/ (paid site) @@ -121,15 +132,17 @@ Some examples: - **PCR(uint8_t heatPin, uint8_t coolPin)** constructor defines the hardware pins to which the heater and cooler are connected. -- **void reset(int iterations)** full stop of the process, also stops heating and cooling, +- **void reset(uint16_t iterations)** full stop of the process, also stops heating and cooling, resets the state to IDLE and defines the number of iterations for the next run. +The parameter iterations must be >= 0 so it changed to unsigned int in 0.3.0. - **uint8_t process(float temperature)** The worker core. This function runs the main process and iterates over the DENATURE, ANNEALING and EXTENSION phase. Returns the current state. The user **MUST** provide the actual temperature of the sample so process can heat and cool the sample on a need to basis. The user **MUST** call this function as often as possible in a tight loop. - **int iterationsLeft()** returns the number of iterations left. -- **uint32_t timeLeft()** estimator of the time left to reach the HOLD state. +- **float timeLeft()** estimator of the time left to reach the HOLD state. +Since 0.3.0 returns its value in seconds. This function assumes that the duration per phase does not change runtime, however it will adapt its estimate. Returns the value in milliseconds. @@ -137,29 +150,36 @@ Returns the value in milliseconds. #### About phases -Temperatures are in °Celsius, timing is in milliseconds (for 0.2.x version). +Temperatures are in **°Celsius**, timing is in **seconds** (since 0.3.0 version). + The timing is the time that the process will be in this state, so it includes the time to heat / cool to reach the temperature defined. +The timing parameter is a float so you can use e.g. 10.5 seconds, or even use +scientific notation like 1.2e2. +In theory the maximum time is 4294967 seconds which is 49.7 days, +In practice the phases are much shorter. +- 1 hour = 3600 seconds, 1 day = 86400 seconds + Note that the parameters of the phases can change while the process is running, e.g. one can increase the duration of the extension phase per cycle to give -that part of the PCR process more time. +that part of the PCR process more time (adjust to concentration?). #### 1 Initial phase This step used in **hot-start PCR** (Wikipedia) to bring the system to starting temperature. -- **void setInitial(float Celsius, uint32_t ms)** Sets temperature and duration. +- **void setInitial(float Celsius, float seconds)** Sets temperature and duration. - **float getInitialTemp()** returns set value. -- **uint32_t getInitialTime()** returns set value. +- **float getInitialTime()** returns set value. #### 2 Denature phase This step breaks the double DNA helix into two single strands. -- **void setDenature(float Celsius, uint32_t ms)** Sets temperature and duration. +- **void setDenature(float Celsius, float seconds)** Sets temperature and duration. - **float getDenatureTemp()** returns set value. -- **uint32_t getDenatureTime()** returns set value. +- **float getDenatureTime()** returns set value. #### 3 Annealing phase @@ -167,16 +187,16 @@ This step let **primers** (Wikipedia) connect to the single strands. The primers create a starting point for the replication. The temperature and duration depends on many factors, so very specific for the reaction. -- **void setAnnealing(float Celsius, uint32_t ms)** Sets temperature and duration. +- **void setAnnealing(float Celsius, float seconds)** Sets temperature and duration. - **float getAnnealingTemp()** returns set value. -- **uint32_t getAnnealingTime()** returns set value. +- **float getAnnealingTime()** returns set value. #### 4 Extension phase This step extends the primers with **dNTP's** nucleotides (Wikipedia) to complete the duplication process. -- **void setExtension(float Celsius, uint32_t ms)** Sets temperature and duration. +- **void setExtension(float Celsius, float seconds)** Sets temperature and duration. - **float getExtensionTemp()** returns set value. - **float getExtensionTime()** returns set value. @@ -185,7 +205,7 @@ the duplication process. This step is used to finalize the remaining DNA strands that are not fully extended in step 4 Extension phase. -- **void setElongation(float Celsius, uint32_t ms)** Sets temperature and duration. +- **void setElongation(float Celsius, float seconds)** Sets temperature and duration. - **float getElongationTemp()** returns set value. - **float getElongationTime()** returns set value. @@ -204,8 +224,9 @@ from their own code. In 0.2.x version the heater / cooler are switched on/off for a short period. This prevent excessive heating or cooling due to not switching of the heater / cooler in time. -This pulsed heating cooling makes the process safer and a bit slower to heat up / cool down. -The length of the period can be adjusted between 0 and 1000 milliseconds to increase +This pulsed heating / cooling makes the process safer as after the call it is switched off. +Drawback is that the pulsed behaviour makes the process a bit slower to heat up / cool down. +Therefore the length of the period can be adjusted between 0 and 1000 milliseconds to increase the efficiency of the process. Be aware that the heat() and cool() will block longer. - **void heat()** Switches off cooler first, and then switches the heater for (default) @@ -213,9 +234,10 @@ the efficiency of the process. Be aware that the heat() and cool() will block lo - **void cool()** switch on the cooler for (default) 10 milliseconds. Switches off heater first. - **void off()** switch off both heater and cooler. - **void setHeatPulseLength(uint16_t ms = 10)** adjust the timing for heat() and cool(). - - The maximum value is 1000 milliseconds == 1 second. + - The maximum value is 1000 milliseconds == 1 second (this limit is to prevent overheating). - The minimum value is 0 milliseconds but it would slow down the heating / cooling. - - warning the heat() and cool() will block for the set period. + - Assumption: optimal time == time to increase 0.1°C. This depends on the specific heat. + - Warning: the heat() and cool() will block for the set period. - **uint16_t getHeatPulseLength()** returns set value. @@ -235,8 +257,6 @@ Users can patch this function when needed, or make it empty. #### Should -- time of phases should be in seconds ==> breaking change - - **void setAnnealing(float Celsius, float seconds)** Sets temperature and duration. - investigate the blocking version - void keepTempTime(temp, time, getTemperature()); @@ -244,17 +264,17 @@ Users can patch this function when needed, or make it empty. - PCR scripting language, simple example? - add examples -- optimize code - - have an array of times and temperatures to go through. -- add continuous heating (unsafe mode) versus the current pulsed heating(safe mode). - add stir pin, to control the stirring of the PCR device. - add signalling pin to indicate ready by a buzzer. -- add unit tests #### Wont - add callback function when ready (user can check state) - +- Fahrenheit interface (C = (F-32) x 5/9.0; F = C x 9/5.0 + 32; +- Kelvin or other temperature scale. +- optimize code + - have an array of times and temperatures to go through. +- add continuous heating (unsafe mode) versus the current pulsed heating(safe mode). ## Support diff --git a/libraries/PCR/examples/PCR_demo_DS18B20/PCR_demo_DS18B20.ino b/libraries/PCR/examples/PCR_demo_DS18B20/PCR_demo_DS18B20.ino index d34e893c..09198046 100644 --- a/libraries/PCR/examples/PCR_demo_DS18B20/PCR_demo_DS18B20.ino +++ b/libraries/PCR/examples/PCR_demo_DS18B20/PCR_demo_DS18B20.ino @@ -51,17 +51,17 @@ void setup() sensor.begin(); sensor.setResolution(10); // 10 bit ==> 0.25 degrees precision sensor.requestTemperatures(); - delay(1000); // wait a second to get a first reading. + delay(1000); // wait a second to get a first measurement. // configure PCR process // adjust timing and temperature to your needs. - pcr.setInitial(98, 10000); // temp, ms - pcr.setDenature(94.5, 5000); // temp, ms - pcr.setAnnealing(54.2, 2000); // temp, ms - pcr.setExtension(75.0, 3000); // temp, ms - pcr.setElongation(75.0, 3000); // temp, ms - pcr.setHold(8.0); // temp only + pcr.setInitial(98, 10); // temp, seconds + pcr.setDenature(94.5, 5); // temp, seconds + pcr.setAnnealing(54.2, 2); // temp, seconds + pcr.setExtension(75.0, 3); // temp, seconds + pcr.setElongation(75.0, 5); // temp, seconds + pcr.setHold(8.0); // temp only pcr.reset(15); // iterations. Serial.print("Estimated time (ms): "); diff --git a/libraries/PCR/examples/PCR_demo_MAX31855/PCR_demo_MAX31855.ino b/libraries/PCR/examples/PCR_demo_MAX31855/PCR_demo_MAX31855.ino index ae166d61..60f0408d 100644 --- a/libraries/PCR/examples/PCR_demo_MAX31855/PCR_demo_MAX31855.ino +++ b/libraries/PCR/examples/PCR_demo_MAX31855/PCR_demo_MAX31855.ino @@ -46,12 +46,12 @@ void setup() // configure PCR process // adjust timing and temperature to your needs. - pcr.setInitial(98, 10000); // temp, ms - pcr.setDenature(94.5, 5000); // temp, ms - pcr.setAnnealing(54.2, 2000); // temp, ms - pcr.setExtension(75.0, 3000); // temp, ms - pcr.setElongation(75.0, 3000); // temp, ms - pcr.setHold(8.0); // temp only + pcr.setInitial(98, 10); // temp, seconds + pcr.setDenature(94.5, 5); // temp, seconds + pcr.setAnnealing(54.2, 2); // temp, seconds + pcr.setExtension(75.0, 3); // temp, seconds + pcr.setElongation(75.0, 3); // temp, seconds + pcr.setHold(8.0); // temp only pcr.reset(15); // iterations. Serial.print("Estimated time (ms): "); diff --git a/libraries/PCR/examples/PCR_demo_aquarium/PCR_demo_aquarium.ino b/libraries/PCR/examples/PCR_demo_aquarium/PCR_demo_aquarium.ino new file mode 100644 index 00000000..e56cb199 --- /dev/null +++ b/libraries/PCR/examples/PCR_demo_aquarium/PCR_demo_aquarium.ino @@ -0,0 +1,54 @@ +// +// FILE: PCR_demo_aquarium.ino +// AUTHOR: Rob Tillaart +// PURPOSE: using PCR class to control temperature in a tropic aquarium +// URL: https://github.com/RobTillaart/PCR +// +// Warning: example takes a day to do one cycle. Adjust timing to see effect. + + +#include "PCR.h" + + +PCR pcr(8, 9); // heatPin, coolPin + + +float getTemperature() +{ + return 30; // dummy, to be elaborated. +} + +void setup() +{ + Serial.begin(115200); + Serial.println(); + Serial.println(__FILE__); + Serial.print("PCR_LIB_VERSION: "); + Serial.println(PCR_LIB_VERSION); + Serial.println(); + + // split 86400 seconds over three temperature levels + pcr.setDenature(32, 23200); // temp, seconds + pcr.setAnnealing(29, 43200); // temp, seconds + pcr.setExtension(27, 20000); // temp, seconds + + // just one cycle a day. + pcr.reset(1); +} + + +void loop() +{ + while (true) + { + float temp = getTemperature(); + pcr.process(temp); + // break after a full cycle / day. + if (pcr.iterationsLeft() == 0) break; + } + // do next cycle / day. + pcr.reset(1); +} + + +// -- END OF FILE -- diff --git a/libraries/PCR/examples/PCR_demo_array/PCR_demo_array.ino b/libraries/PCR/examples/PCR_demo_array/PCR_demo_array.ino index eab8096b..98914822 100644 --- a/libraries/PCR/examples/PCR_demo_array/PCR_demo_array.ino +++ b/libraries/PCR/examples/PCR_demo_array/PCR_demo_array.ino @@ -28,25 +28,25 @@ void setup() Serial.println(); // configure all phases - pcr[0].setInitial(98, 10000); // temp, ms - pcr[0].setDenature(94.5, 5000); // temp, ms - pcr[0].setAnnealing(54.2, 2000); // temp, ms - pcr[0].setExtension(75.0, 3000); // temp, ms - pcr[0].setElongation(75.0, 3000); // temp, ms + pcr[0].setInitial(98, 10); // temp, seconds + pcr[0].setDenature(94.5, 5); // temp, seconds + pcr[0].setAnnealing(54.2, 2); // temp, seconds + pcr[0].setExtension(75.0, 3); // temp, seconds + pcr[0].setElongation(75.0, 3); // temp, seconds pcr[0].setHold(8.0); // temp only - pcr[1].setInitial(97, 8000); - pcr[1].setDenature(94, 4000); - pcr[1].setAnnealing(54, 2000); - pcr[1].setExtension(70.0, 2000); - pcr[1].setElongation(70.0, 2000); + pcr[1].setInitial(97, 8); + pcr[1].setDenature(94, 4); + pcr[1].setAnnealing(54, 2); + pcr[1].setExtension(70.0, 2); + pcr[1].setElongation(70.0, 2); pcr[1].setHold(8.0); - pcr[2].setInitial(96, 15000); - pcr[2].setDenature(93, 8000); - pcr[2].setAnnealing(53, 4000); - pcr[2].setExtension(75.0, 4000); - pcr[2].setElongation(75.0, 4000); + pcr[2].setInitial(96, 15); + pcr[2].setDenature(93, 8); + pcr[2].setAnnealing(53, 4); + pcr[2].setExtension(75.0, 4); + pcr[2].setElongation(75.0, 4); pcr[2].setHold(8.0); pcr[0].reset(15); // iterations. diff --git a/libraries/PCR/examples/PCR_demo_basic/PCR_demo_basic.ino b/libraries/PCR/examples/PCR_demo_basic/PCR_demo_basic.ino index 63a6b7ab..ff3f1308 100644 --- a/libraries/PCR/examples/PCR_demo_basic/PCR_demo_basic.ino +++ b/libraries/PCR/examples/PCR_demo_basic/PCR_demo_basic.ino @@ -25,9 +25,9 @@ void setup() Serial.println(PCR_LIB_VERSION); Serial.println(); - pcr.setDenature(94.5, 1000); // temp, ms - pcr.setAnnealing(54.2, 1000); // temp, ms - pcr.setExtension(75.0, 1000); // temp, ms + pcr.setDenature(94.5, 1); // temp, seconds + pcr.setAnnealing(54.2, 2); // temp, seconds + pcr.setExtension(75.0, 3); // temp, seconds pcr.reset(5); // iterations. diff --git a/libraries/PCR/examples/PCR_demo_extended/PCR_demo_extended.ino b/libraries/PCR/examples/PCR_demo_extended/PCR_demo_extended.ino index d23de652..99ef0a0b 100644 --- a/libraries/PCR/examples/PCR_demo_extended/PCR_demo_extended.ino +++ b/libraries/PCR/examples/PCR_demo_extended/PCR_demo_extended.ino @@ -27,12 +27,12 @@ void setup() Serial.println(); // configure all phases - pcr.setInitial(98, 10000); // temp, ms - pcr.setDenature(94.5, 5000); // temp, ms - pcr.setAnnealing(54.2, 2000); // temp, ms - pcr.setExtension(75.0, 3000); // temp, ms - pcr.setElongation(75.0, 3000); // temp, ms - pcr.setHold(8.0); // temp only + pcr.setInitial(98, 10); // temp, seconds + pcr.setDenature(94.5, 5); // temp, seconds + pcr.setAnnealing(54.2, 2); // temp, seconds + pcr.setExtension(75.0, 3); // temp, seconds + pcr.setElongation(75.0, 5); // temp, seconds + pcr.setHold(8.0); // temp only pcr.reset(15); // iterations. Serial.print("Estimated time (ms): "); diff --git a/libraries/PCR/examples/PCR_runtime_change/PCR_runtime_change.ino b/libraries/PCR/examples/PCR_runtime_change/PCR_runtime_change.ino index d1f5ed20..7261268b 100644 --- a/libraries/PCR/examples/PCR_runtime_change/PCR_runtime_change.ino +++ b/libraries/PCR/examples/PCR_runtime_change/PCR_runtime_change.ino @@ -27,15 +27,15 @@ void setup() Serial.println(); // configure all phases - pcr.setInitial(98, 10000); // temp, ms - pcr.setDenature(94.5, 5000); // temp, ms - pcr.setAnnealing(54.2, 2000); // temp, ms - pcr.setExtension(75.0, 3000); // temp, ms - pcr.setElongation(75.0, 3000); // temp, ms - pcr.setHold(8.0); // temp only + pcr.setInitial(98, 10); // temp, seconds + pcr.setDenature(94.5, 5); // temp, seconds + pcr.setAnnealing(54.2, 2); // temp, seconds + pcr.setExtension(75.0, 3); // temp, seconds + pcr.setElongation(75.0, 3); // temp, seconds + pcr.setHold(8.0); // temp only pcr.reset(10); // iterations. - Serial.print("Estimated time (ms): "); + Serial.print("Estimated time (seconds): "); Serial.println(pcr.timeLeft()); bool flagFive = false; @@ -48,10 +48,10 @@ void setup() if ((pcr.iterationsLeft() == 5) && (flagFive == false)) { flagFive = true; - pcr.setDenature(94.5, 7500); // temp, ms - pcr.setAnnealing(54.2, 4000); // temp, ms - pcr.setExtension(75.0, 5000); // temp, ms - Serial.print("Estimated time (ms): "); + pcr.setDenature(94.5, 7.5); // temp, seconds + pcr.setAnnealing(54.2, 4.25); // temp, seconds + pcr.setExtension(75.0, 5.75); // temp, seconds + Serial.print("Estimated time (seconds): "); Serial.println(pcr.timeLeft()); } } diff --git a/libraries/PCR/library.json b/libraries/PCR/library.json index 656869a1..85904c43 100644 --- a/libraries/PCR/library.json +++ b/libraries/PCR/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/PCR.git" }, - "version": "0.2.1", + "version": "0.3.0", "license": "MIT", "frameworks": "*", "platforms": "*", diff --git a/libraries/PCR/library.properties b/libraries/PCR/library.properties index 08a31335..77699de2 100644 --- a/libraries/PCR/library.properties +++ b/libraries/PCR/library.properties @@ -1,5 +1,5 @@ name=PCR -version=0.2.1 +version=0.3.0 author=Rob Tillaart maintainer=Rob Tillaart sentence=Arduino library for PCR process control. diff --git a/libraries/PCR/test/unit_test_001.cpp b/libraries/PCR/test/unit_test_001.cpp index b0c01e49..8baca5a7 100644 --- a/libraries/PCR/test/unit_test_001.cpp +++ b/libraries/PCR/test/unit_test_001.cpp @@ -54,8 +54,82 @@ unittest(test_constructor_parameters) { PCR pcr(8,9); - assertEqual(1, 1); - // to elaborate configuration. + pcr.setInitial(94, 50); + assertEqualFloat(94, pcr.getInitialTemp(), 0.01); + assertEqualFloat(50, pcr.getInitialTime(), 0.01); + + pcr.setDenature(93, 30); + assertEqualFloat(93, pcr.getDenatureTemp(), 0.01); + assertEqualFloat(30, pcr.getDenatureTime(), 0.01); + + pcr.setAnnealing(54, 40); + assertEqualFloat(54, pcr.getAnnealingTemp(), 0.01); + assertEqualFloat(40, pcr.getAnnealingTime(), 0.01); + + pcr.setExtension(75, 60); + assertEqualFloat(75, pcr.getExtensionTemp(), 0.01); + assertEqualFloat(60, pcr.getExtensionTime(), 0.01); + + pcr.setElongation(74, 90); + assertEqualFloat(74, pcr.getElongationTemp(), 0.01); + assertEqualFloat(90, pcr.getElongationTime(), 0.01); + + pcr.setHold(17); + assertEqualFloat(17, pcr.getHoldTemp(), 0.01); +} + + +unittest(test_constructor_iterations) +{ + PCR pcr(8,9); + + assertEqual(0, pcr.iterationsLeft()); + for (int i = 1; i < 10; i++) + { + pcr.reset(i); + assertEqual(i, pcr.iterationsLeft()); + } +} + + +unittest(test_constructor_heat_pulse_length) +{ + PCR pcr(8,9); + + assertEqual(10, pcr.getHeatPulseLength()); + for (int i = 10; i <= 100; i+= 10) + { + pcr.setHeatPulseLength(i); + assertEqual(i, pcr.getHeatPulseLength()); + } + // test constrain + pcr.setHeatPulseLength(5000); + assertEqual(1000, pcr.getHeatPulseLength()); + + pcr.setHeatPulseLength(); + assertEqual(10, pcr.getHeatPulseLength()); + +} + + +unittest(test_constructor_timeLeft) +{ + PCR pcr(8,9); + + assertEqualFloat(1, pcr.timeLeft(), 0.01); + + pcr.setInitial(94, 50); + pcr.setDenature(93, 30); + pcr.setAnnealing(54, 40); + pcr.setExtension(75, 60); + pcr.setElongation(74, 90); + pcr.setHold(17); + + // note: zero cycles + assertEqualFloat(140, pcr.timeLeft(), 0.1); + + pcr.reset(10); + assertEqualFloat(1440, pcr.timeLeft(), 0.1); }