diff --git a/libraries/PCR/.arduino-ci.yml b/libraries/PCR/.arduino-ci.yml new file mode 100644 index 00000000..d9b3a2aa --- /dev/null +++ b/libraries/PCR/.arduino-ci.yml @@ -0,0 +1,30 @@ +platforms: + rpipico: + board: rp2040:rp2040:rpipico + package: rp2040:rp2040 + gcc: + features: + defines: + - ARDUINO_ARCH_RP2040 + warnings: + flags: + +packages: + rp2040:rp2040: + url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + +compile: + # Choosing to run compilation tests on 2 different Arduino platforms + platforms: + - uno + # - due + # - zero + # - leonardo + - m4 + - esp32 + - esp8266 + # - mega2560 + - rpipico + + libraries: + - "printHelpers" diff --git a/libraries/PCR/.github/FUNDING.yml b/libraries/PCR/.github/FUNDING.yml new file mode 100644 index 00000000..554358c3 --- /dev/null +++ b/libraries/PCR/.github/FUNDING.yml @@ -0,0 +1,4 @@ +# These are supported funding model platforms + +github: RobTillaart +custom: "https://www.paypal.me/robtillaart" diff --git a/libraries/PCR/.github/workflows/arduino-lint.yml b/libraries/PCR/.github/workflows/arduino-lint.yml new file mode 100644 index 00000000..7f8f4ef4 --- /dev/null +++ b/libraries/PCR/.github/workflows/arduino-lint.yml @@ -0,0 +1,13 @@ +name: Arduino-lint + +on: [push, pull_request] +jobs: + lint: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - uses: arduino/arduino-lint-action@v1 + with: + library-manager: update + compliance: strict \ No newline at end of file diff --git a/libraries/PCR/.github/workflows/arduino_test_runner.yml b/libraries/PCR/.github/workflows/arduino_test_runner.yml new file mode 100644 index 00000000..dbd0ce79 --- /dev/null +++ b/libraries/PCR/.github/workflows/arduino_test_runner.yml @@ -0,0 +1,17 @@ +name: Arduino CI + +on: [push, pull_request] + +jobs: + runTest: + runs-on: ubuntu-latest + timeout-minutes: 20 + + steps: + - uses: actions/checkout@v4 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 + - run: | + gem install arduino_ci + arduino_ci.rb diff --git a/libraries/PCR/.github/workflows/jsoncheck.yml b/libraries/PCR/.github/workflows/jsoncheck.yml new file mode 100644 index 00000000..1cbb5e2c --- /dev/null +++ b/libraries/PCR/.github/workflows/jsoncheck.yml @@ -0,0 +1,18 @@ +name: JSON check + +on: + push: + paths: + - '**.json' + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + - name: json-syntax-check + uses: limitusus/json-syntax-check@v2 + with: + pattern: "\\.json$" \ No newline at end of file diff --git a/libraries/PCR/CHANGELOG.md b/libraries/PCR/CHANGELOG.md new file mode 100644 index 00000000..7944d7c2 --- /dev/null +++ b/libraries/PCR/CHANGELOG.md @@ -0,0 +1,28 @@ +# Change Log PCR + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + + +## [0.2.0] - 2024-05-30 +- initial class version (published) + +---- +## [0.1.3] - 2024-05-30 +- initial class version (not published) + +## [0.1.02] - 10-jun-2015 +- refactored version +- https://forum.arduino.cc/t/problem-with-arduino-pcr-amplifies-of-dna/314808/9 + +## [0.1.01] - 10-jun-2015 +- not published. + +## [0.1.00] - 10-jun-2015 +- initial example sketch +- 10-jun-2015 + + + diff --git a/libraries/PCR/LICENSE b/libraries/PCR/LICENSE new file mode 100644 index 00000000..3b61d73d --- /dev/null +++ b/libraries/PCR/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2015-2024 Rob Tillaart + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/libraries/PCR/PCR.h b/libraries/PCR/PCR.h new file mode 100644 index 00000000..dc1549a3 --- /dev/null +++ b/libraries/PCR/PCR.h @@ -0,0 +1,285 @@ +#pragma once +// +// FILE: PCR.h +// AUTHOR: Rob Tillaart +// DATE: 2015-06-10 +// VERSION: 0.2.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 + + + +#include "Arduino.h" + +#define PCR_LIB_VERSION (F("0.2.0")) + +enum PCRSTATE { + PCR_STATE_IDLE = 0, + PCR_STATE_INITIAL, + PCR_STATE_DENATURE, + PCR_STATE_ANNEALING, + PCR_STATE_EXTENSION, + PCR_STATE_ELONGATION, + PCR_STATE_HOLD +}; + + +class PCR +{ +public: + PCR(uint8_t heatPin, uint8_t coolPin) + { + _state = PCR_STATE_IDLE; + _heatPin = heatPin; + _coolPin = coolPin; + pinMode(_heatPin, OUTPUT); + pinMode(_coolPin, OUTPUT); + off(); + } + + + // PARAMETERS + void setInitial(float temp, uint32_t ms) + { + _initialTemp = temp; + _initialTime = ms; + } + float getInitialTemp() { return _initialTemp; } + uint32_t getInitialTime() { return _initialTime; } + + void setDenature(float temp, uint32_t ms) + { + _denatureTemp = temp; + _denatureTime = ms; + } + float getDenatureTemp() { return _denatureTemp; } + uint32_t getDenatureTime() { return _denatureTime; } + + void setAnnealing(float temp, uint32_t ms) + { + _annealingTemp = temp; + _annealingTime = ms; + } + float getAnnealingTemp() { return _annealingTemp; } + uint32_t getAnnealingTime() { return _annealingTime; } + + void setExtension(float temp, uint32_t ms) + { + _extensionTemp = temp; + _extensionTime = ms; + } + float getExtensionTemp() { return _extensionTemp; } + float getExtensionTime() { return _extensionTime; } + + void setElongation(float temp, uint32_t ms) + { + _elongationTemp = temp; + _elongationTime = ms; + } + float getElongationTemp() { return _elongationTemp; } + float getElongationTime() { return _elongationTime; } + + void setHold(float temp) { _holdTemp = temp; } + float getHoldTemp() { return _extensionTemp; } + + + // PROCESS CONTROL + void reset(int iterations) + { + _startTime = millis(); + _cycles = iterations; + _state = PCR_STATE_IDLE; + off(); + debug(); + } + + int iterationsLeft() { return _cycles; }; + + // returns PCR_STATE_HOLD when ready; + uint8_t process(float temperature) + { + _temperature = temperature; + switch(_state) + { + case PCR_STATE_IDLE: + _state = PCR_STATE_INITIAL; + _startTime = millis(); + debug(); + break; + + case PCR_STATE_INITIAL: + if (_temperature < _initialTemp) heat(); + else if (_temperature > _initialTemp) cool(); + else off(); + if (millis() - _startTime >= _initialTime) + { + _state = PCR_STATE_DENATURE; + _startTime = millis(); + debug(); + } + break; + + case PCR_STATE_DENATURE: + if (_temperature < _denatureTemp) heat(); + else if (_temperature > _denatureTemp) cool(); + else off(); + if (millis() - _startTime >= _denatureTime) + { + _state = PCR_STATE_ANNEALING; + _startTime = millis(); + debug(); + } + break; + + case PCR_STATE_ANNEALING: + if (_temperature < _annealingTemp) heat(); + else if (_temperature > _annealingTemp) cool(); + else off(); + if (millis() - _startTime >= _annealingTime) + { + _state = PCR_STATE_EXTENSION; + _startTime = millis(); + debug(); + } + break; + + case PCR_STATE_EXTENSION: + if (_temperature < _extensionTemp) heat(); + else if (_temperature > _extensionTemp) cool(); + else off(); + if (millis() - _startTime >= _extensionTime) + { + _cycles--; + if (_cycles > 0) _state = PCR_STATE_DENATURE; + else _state = PCR_STATE_ELONGATION; + _startTime = millis(); + debug(); + } + break; + + case PCR_STATE_ELONGATION: + if (_temperature < _elongationTemp) heat(); + else if (_temperature > _elongationTemp) cool(); + else off(); + if (millis() - _startTime >= _elongationTime) + { + _state = PCR_STATE_HOLD; + _startTime = millis(); + debug(); + } + break; + + case PCR_STATE_HOLD: + if (_temperature < _holdTemp) heat(); + else if (_temperature > _holdTemp) cool(); + else off(); + break; + } + return _state; + } + + + // HEATER / COOLER CONTROL + void heat() + { + digitalWrite(_heatPin, HIGH); + delay(10); + digitalWrite(_coolPin, LOW); + } + + void cool() + { + digitalWrite(_coolPin, HIGH); + delay(10); + digitalWrite(_coolPin, LOW); + } + + void off() + { + digitalWrite(_heatPin, LOW); + digitalWrite(_coolPin, LOW); + } + + + // blocking version of single step. + // to be tested what to do with it + // could be a separate class. + /* + 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() + { + uint32_t sum = 0; + if (_state < PCR_STATE_DENATURE) sum += _initialTime; + sum += _denatureTime * _cycles; + sum += _annealingTime * _cycles; + sum += _extensionTime * _cycles; + if (_state <= PCR_STATE_ELONGATION) sum += _elongationTime; + return sum; + } + +private: + // 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"); + Serial.print(_cycles); + if (_state == PCR_STATE_IDLE) Serial.println("\tIdle"); + if (_state == PCR_STATE_INITIAL) Serial.println("\tInitialization"); + if (_state == PCR_STATE_DENATURE) Serial.println("\tDenature"); + if (_state == PCR_STATE_ANNEALING) Serial.println("\tAnnealing"); + if (_state == PCR_STATE_EXTENSION) Serial.println("\tExtension"); + if (_state == PCR_STATE_ELONGATION) Serial.println("\tElongation"); + if (_state == PCR_STATE_HOLD) Serial.println("\tHOLD"); + } + + + float _initialTemp = 94; + uint32_t _initialTime = 0; + float _denatureTemp = 94; + uint32_t _denatureTime = 1000; + float _annealingTemp = 54; + uint32_t _annealingTime = 1000; + float _extensionTemp = 76; + uint32_t _extensionTime = 1000; + float _elongationTemp = 76; + uint32_t _elongationTime = 1000; + float _holdTemp = 14; + + float _temperature = 0; + + int _heatPin = 0; + int _coolPin = 0; + PCRSTATE _state = PCR_STATE_IDLE; + int _cycles = 0; + uint32_t _startTime = 0; +}; + + +// -- END OF FILE -- + + + + + diff --git a/libraries/PCR/README.md b/libraries/PCR/README.md new file mode 100644 index 00000000..d8c1de38 --- /dev/null +++ b/libraries/PCR/README.md @@ -0,0 +1,231 @@ + +[![Arduino CI](https://github.com/RobTillaart/PCR/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci) +[![Arduino-lint](https://github.com/RobTillaart/PCR/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/PCR/actions/workflows/arduino-lint.yml) +[![JSON check](https://github.com/RobTillaart/PCR/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/PCR/actions/workflows/jsoncheck.yml) +[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/PCR.svg)](https://github.com/RobTillaart/PCR/issues) + +[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/PCR/blob/master/LICENSE) +[![GitHub release](https://img.shields.io/github/release/RobTillaart/PCR.svg?maxAge=3600)](https://github.com/RobTillaart/PCR/releases) +[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/PCR.svg)](https://registry.platformio.org/libraries/robtillaart/PCR) + + +# PCR + +Arduino library for PCR process control. + + +## Description + + +**Experimental** + +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 +a very small sample of DNA (or a part of it) sufficiently to enable detailed study. +PCR was invented in 1983 by American biochemist Kary Mullis at Cetus Corporation._ + +This library implements a PCR class that helps to control time and temperatures of the +main PCR cycles. + +In short a PCR cycle is a process of controlled heating and cooling to let DNA "reproduce" +to get large quantities. Roughly the amount doubles in every cycle (of step 2,3,4). + +This process exists of repeated cycles of the three main steps. (times and temp from wikipedia) + +| step | name | temperature range | time range | +|:----:|:----------------|:----------------------|:------------:| +| 1 | Initialization | 94–98°C = 201–208°F | 00–10 min. | +| 2 | Denaturation | 94–98°C = 201–208°F | 20–30 sec. | +| 3 | Annealing | 50–65°C = 122–149°F | 20–40 sec. | +| 4 | Extension | 70–80°C = 158–176°F | ? | +| 5 | Elongation | 70–80°C = 158–176°F | 05–15 min. | +| 6 | Final Hold | 4–15°C = 39–59°F | indefinitely | + +The PCR function **process()** takes care of the repeating of step 2,3 and 4. + + +Typical core code looks like: + +```cpp + // configure all phases + pcr.setInitial(98, 10000); // temp, ms + pcr.setDenature(94.5, 5000); + pcr.setAnnealing(54.2, 2000); + pcr.setExtension(75.0, 3000); + pcr.setElongation(75.0, 3000); + pcr.setHold(8.0); + + pcr.reset(15); // iterations. + // execute the process. + while (pcr.iterationsLeft() > 0) + { + float temp = getTemperature(); + pcr.process(temp); + } +``` + + +**Note:** this library is meant for educational purposes and is not meant to replace professional equipment. + + +#### Hardware notes + +The hardware setup needs a device that can be cooled or heated depending on the phase of the cycle. +Furthermore the hardware setup needs to provide an actual temperature to guide the process. +This latter can be an DS18B20 especially the waterproof version. + +``` + Processor PCR DEVICE + +---------------+ +---------------+ + | | | | + | | | | + | heatPin o|------------------->|o HEATER | + | coolPin o|------------------->|o COOLER | + | | | | + | getTemp() O|<-------------------|o temperature | + | | | sensor | + | | | | + | | | | + | | | | + +---------------+ +---------------+ +``` + + +#### Other applications + +The PCR class can be used to manage other temperature control processes. +Some examples: +- control an oven with a thermocouple, (e.g. glass melting) +- control the temperature of a tropic aquarium to simulate day and night. +- control an ice making machine. + + +#### Related + +- https://en.wikipedia.org/wiki/Polymerase_chain_reaction +- https://github.com/RobTillaart/PCR +- 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) + + +## Interface + +```cpp +#include "PCR.h" +``` + +#### Constructor + +- **PCR(uint8_t heatPin, uint8_t coolPin)** constructor defines the haredware pins to which +the heater and cooler are connected. +- **void reset(int 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. +- **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. +Returns the current state. +- **int iterationsLeft()** returns the number of iterations left. +- **uint32_t timeLeft()** estimator of the time left to reach the HOLD state. +This function assumes that the duration per phase does not change runtime, +however it will adapt its estimate. +Returns the value in milliseconds. + + +#### Initial phase + +Temperatures are in °Celsius, timing is in milliseconds. +Note that these parameters can change while the process is running. + +- **void setInitial(float Celsius, uint32_t ms)** Sets temperature and duration. +- **float getInitialTemp()** returns set value. +- **uint32_t getInitialTime()** returns set value. + +#### Denature phase + +- **void setDenature(float Celsius, uint32_t ms)** Sets temperature and duration. +- **float getDenatureTemp()** returns set value. +- **uint32_t getDenatureTime()** returns set value. + +#### Annealing phase + +- **void setAnnealing(float Celsius, uint32_t ms)** Sets temperature and duration. +- **float getAnnealingTemp()** returns set value. +- **uint32_t getAnnealingTime()** returns set value. + +#### Extension phase + +- **void setExtension(float Celsius, uint32_t ms)** Sets temperature and duration. +- **float getExtensionTemp()** returns set value. +- **float getExtensionTime()** returns set value. + +#### Elongation phase + +- **void setElongation(float Celsius, uint32_t ms)** Sets temperature and duration. +- **float getElongationTemp()** returns set value. +- **float getElongationTime()** returns set value. + +#### Hold phase + +The Hold phase goes on forever ans is meant to store the result on a cool temperature +for final storage. + +- **void setHold(float Celsius)** Sets temperature for final phase. +- **float getHoldTemp()** returns set value. + +#### Heater, cooler control + +These are public functions so the user can control these also from their own code. + +- **void heat()** switch on the heater for 10 milliseconds. +- **void cool()** switch on the cooler for 10 milliseconds. +- **void off()** switch off all. + +#### Debug + +- **void debug()** is a function used to output some state to Serial. +Users can patch this function when needed, or make it empty. + + +## Future + +#### Must + +- improve documentation + - description of the phases. +- build setup to test + + +#### Should + +- investigate the blocking version + - void keepTempTime(temp, time, getTemperature()); +- make the 10 milliseconds control pulses configurable (e.g. 10..100 ms) +- investigate continuous heating (unsafe mode)versus the current pulsed heating(safe mode). + +#### Could + +- PCR scripting language? +- add examples +- optimize code + - have an array of times and temperatures to go through. +- stir pin, to control the stirring of the PCR device. +- add unit tests + + +#### Wont +- add callback function when ready (user can check state) + + +## Support + +If you appreciate my libraries, you can support the development and maintenance. +Improve the quality of the libraries by providing issues and Pull Requests, or +donate through PayPal or GitHub sponsors. + +Thank you, + + diff --git a/libraries/PCR/examples/PCR_demo_basic/PCR_demo_basic.ino b/libraries/PCR/examples/PCR_demo_basic/PCR_demo_basic.ino new file mode 100644 index 00000000..0180b498 --- /dev/null +++ b/libraries/PCR/examples/PCR_demo_basic/PCR_demo_basic.ino @@ -0,0 +1,56 @@ +// +// FILE: PCR_demo_basic.ino +// AUTHOR: Rob Tillaart +// PURPOSE: basic PCR demo +// URL: https://github.com/RobTillaart/ACD10 + + +#include "PCR.h" + + +PCR pcr(8, 9); // heatPin, coolPin + + +float getTemperature() +{ + return 65; +} + +void setup() +{ + Serial.begin(115200); + Serial.println(); + Serial.println(__FILE__); + Serial.print("PCR_LIB_VERSION: "); + 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.reset(5); // iterations. + + // endless loop + while (true) + { + float temp = getTemperature(); + pcr.process(temp); + + if (pcr.iterationsLeft() == 0) + { + // optional break out of loop or stay in HOLD state; + // display end state reached, ring a bell etc. + // break; + } + } +} + + +void loop() +{ +} + + + +// -- END OF FILE -- diff --git a/libraries/PCR/examples/PCR_demo_extended/PCR_demo_extended.ino b/libraries/PCR/examples/PCR_demo_extended/PCR_demo_extended.ino new file mode 100644 index 00000000..6a99824b --- /dev/null +++ b/libraries/PCR/examples/PCR_demo_extended/PCR_demo_extended.ino @@ -0,0 +1,57 @@ +// +// FILE: PCR_demo_extended.ino +// AUTHOR: Rob Tillaart +// PURPOSE: extended PCR demo, adds initialization, elongation and final hold +// URL: https://github.com/RobTillaart/ACD10 +// +// adjust timing and temperature. + +#include "PCR.h" + + +PCR pcr(8, 9); // heatPin, coolPin + + +float getTemperature() +{ + return 65; +} + +void setup() +{ + Serial.begin(115200); + Serial.println(); + Serial.println(__FILE__); + Serial.print("PCR_LIB_VERSION: "); + Serial.println(PCR_LIB_VERSION); + 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.reset(15); // iterations. + Serial.print("Estimated time (ms): "); + Serial.println(pcr.timeLeft()); + + while (pcr.iterationsLeft() > 0) + { + float temp = getTemperature(); + pcr.process(temp); + } + + Serial.println("done"); +} + + +void loop() +{ +} + + + +// -- END OF FILE -- diff --git a/libraries/PCR/examples/PCR_runtime_change/PCR_runtime_change.ino b/libraries/PCR/examples/PCR_runtime_change/PCR_runtime_change.ino new file mode 100644 index 00000000..9be1ccfe --- /dev/null +++ b/libraries/PCR/examples/PCR_runtime_change/PCR_runtime_change.ino @@ -0,0 +1,69 @@ +// +// FILE: PCR_demo_extended.ino +// AUTHOR: Rob Tillaart +// PURPOSE: extended PCR demo, adds initialization, elongation and final hold +// URL: https://github.com/RobTillaart/ACD10 +// +// adjust timing and temperature. + +#include "PCR.h" + + +PCR pcr(8, 9); // heatPin, coolPin + + +float getTemperature() +{ + return 65; +} + +void setup() +{ + Serial.begin(115200); + Serial.println(); + Serial.println(__FILE__); + Serial.print("PCR_LIB_VERSION: "); + Serial.println(PCR_LIB_VERSION); + 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.reset(10); // iterations. + Serial.print("Estimated time (ms): "); + Serial.println(pcr.timeLeft()); + + bool flagFive = false; + while (pcr.iterationsLeft() > 0) + { + float temp = getTemperature(); + pcr.process(temp); + + // increase time for last 5 iterations. + 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): "); + Serial.println(pcr.timeLeft()); + } + } + + Serial.println("done"); +} + + +void loop() +{ +} + + + +// -- END OF FILE -- diff --git a/libraries/PCR/keywords.txt b/libraries/PCR/keywords.txt new file mode 100644 index 00000000..4caf6165 --- /dev/null +++ b/libraries/PCR/keywords.txt @@ -0,0 +1,52 @@ +# Syntax Colouring Map For PCR + +# Data types (KEYWORD1) +PCR KEYWORD1 + + +# Methods and Functions (KEYWORD2) + +setInitial KEYWORD2 +getInitialTemp KEYWORD2 +getInitialTime KEYWORD2 + +setDenature KEYWORD2 +getDenatureTemp KEYWORD2 +getDenatureTime KEYWORD2 + +setAnnealing KEYWORD2 +getAnnealingTemp KEYWORD2 +getAnnealingTime KEYWORD2 + +setExtension KEYWORD2 +getExtensionTemp KEYWORD2 +getExtensionTime KEYWORD2 + +setElongation KEYWORD2 +getElongationTemp KEYWORD2 +getElongationTime KEYWORD2 + +setHold KEYWORD2 +getHoldTemp KEYWORD2 + +reset KEYWORD2 +iterationsLeft KEYWORD2 +process KEYWORD2 + +heat KEYWORD2 +cool KEYWORD2 +off KEYWORD2 + +timeLeft KEYWORD2 + + +# Constants (LITERAL1) +PCR_LIB_VERSION LITERAL1 + +PCR_STATE_IDLE LITERAL1 +PCR_STATE_INITIAL LITERAL1 +PCR_STATE_DENATURE LITERAL1 +PCR_STATE_ANNEALING LITERAL1 +PCR_STATE_EXTENSION LITERAL1 +PCR_STATE_ELONGATION LITERAL1 +PCR_STATE_HOLD LITERAL1 diff --git a/libraries/PCR/library.json b/libraries/PCR/library.json new file mode 100644 index 00000000..6c7bbc42 --- /dev/null +++ b/libraries/PCR/library.json @@ -0,0 +1,23 @@ +{ + "name": "PCR", + "keywords": "polymerase, chain, reaction, denature, annealing, extension", + "description": "Arduino library for PCR process control.", + "authors": + [ + { + "name": "Rob Tillaart", + "email": "Rob.Tillaart@gmail.com", + "maintainer": true + } + ], + "repository": + { + "type": "git", + "url": "https://github.com/RobTillaart/PCR.git" + }, + "version": "0.2.0", + "license": "MIT", + "frameworks": "*", + "platforms": "*", + "headers": "PCR.h" +} diff --git a/libraries/PCR/library.properties b/libraries/PCR/library.properties new file mode 100644 index 00000000..1be22529 --- /dev/null +++ b/libraries/PCR/library.properties @@ -0,0 +1,11 @@ +name=PCR +version=0.2.0 +author=Rob Tillaart +maintainer=Rob Tillaart +sentence=Arduino library for PCR process control. +paragraph=polymerase, chain, reaction, denature, annealing, extension. +category=data processing +url=https://github.com/RobTillaart/PCR +architectures=* +includes=PCR.h +depends= diff --git a/libraries/PCR/test/unit_test_001.cpp b/libraries/PCR/test/unit_test_001.cpp new file mode 100644 index 00000000..b0c01e49 --- /dev/null +++ b/libraries/PCR/test/unit_test_001.cpp @@ -0,0 +1,66 @@ +// +// FILE: unit_test_001.cpp +// AUTHOR: Rob Tillaart +// DATE: 2024-05-30 +// PURPOSE: unit tests for the PCR library +// URL: https://github.com/RobTillaart/PCR +// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md +// + +// supported assertions +// https://github.com/Arduino-CI/arduino_ci/blob/master/cpp/unittest/Assertion.h#L33-L42 +// ---------------------------- +// assertEqual(expected, actual) +// assertNotEqual(expected, actual) +// assertLess(expected, actual) +// assertMore(expected, actual) +// assertLessOrEqual(expected, actual) +// assertMoreOrEqual(expected, actual) +// assertTrue(actual) +// assertFalse(actual) +// assertNull(actual) +// assertNotNull(actual) + +#include + + +#include "PCR.h" + + +unittest_setup() +{ + fprintf(stderr, "PCR_LIB_VERSION: %s\n", (char *) PCR_LIB_VERSION); +} + + +unittest_teardown() +{ +} + + +unittest(test_constants) +{ + assertEqual(PCR_STATE_IDLE , 0); + assertEqual(PCR_STATE_INITIAL , 1); + assertEqual(PCR_STATE_DENATURE , 2); + assertEqual(PCR_STATE_ANNEALING , 3); + assertEqual(PCR_STATE_EXTENSION , 4); + assertEqual(PCR_STATE_ELONGATION, 5); + assertEqual(PCR_STATE_HOLD , 6); +} + + +unittest(test_constructor_parameters) +{ + PCR pcr(8,9); + + assertEqual(1, 1); + // to elaborate configuration. +} + + +unittest_main() + + +// -- END OF FILE -- +