diff --git a/MultiMAX6675.cpp b/MultiMAX6675.cpp new file mode 100644 index 0000000..1c74fa0 --- /dev/null +++ b/MultiMAX6675.cpp @@ -0,0 +1,50 @@ +#include "MultiMAX6675.h" + +void MultiMAX6675::begin(SPIClass * spi) { + current_millis = millis(); + this->spi = spi; +} + +void MultiMAX6675::loop() { + current_millis = millis(); + std::size_t queue_size = read_queue.size(); + if(queue_size == 0) return; + for(uint16_t i = read_queue_free_on_beginning; i < queue_size; i++) { + QueueItem item = read_queue[i]; + if(current_millis >= item.read_on) { + digitalWrite(item.pin, LOW); + spi->beginTransaction(SPISettings(4300000, SPI_MSBFIRST, SPI_MODE0)); + // [bit, description] - [0, dummy sign bit][1-12, the data we want, a 12-bit unsigned number(0-4096)][13, thermocouple input][14, device id][15, state] + // I have no idea what the last 3 bits are for, so just shift them. lol + float temperature = (spi->transfer16(0) >> 3) / 4.0; + spi->endTransaction(); + digitalWrite(item.pin, HIGH); + *item.var = item.unit == Unit::CELCIUS ? temperature : ((1.8 * temperature) + 32); + if(queue_size - 1 == i) { + read_queue.pop_back(); + } else { + read_queue_free_on_beginning = i; + } + } + } +} + +unsigned int MultiMAX6675::add(uint8_t CS_PIN) { + pinMode(CS_PIN, OUTPUT); + digitalWrite(CS_PIN, HIGH); + cs_pins.push_back(CS_PIN); + return cs_pins.size() - 1; +} + +void MultiMAX6675::read(Unit unit, uint8_t pin_index, float * var) { + digitalWrite(cs_pins[pin_index], LOW); + digitalWrite(cs_pins[pin_index], HIGH); + // delay(220); + QueueItem item = QueueItem { .read_on = current_millis + 220, .pin = cs_pins[pin_index], .var = var, .unit = unit}; + if(read_queue_free_on_beginning == 0) { + read_queue.push_back(item); + } else { + read_queue[read_queue_free_on_beginning] = item; + read_queue_free_on_beginning--; + } +} diff --git a/MultiMAX6675.h b/MultiMAX6675.h new file mode 100644 index 0000000..2ca144d --- /dev/null +++ b/MultiMAX6675.h @@ -0,0 +1,36 @@ +#ifndef MULTIMAX6675_H +#define MULTIMAX6675_H + +#include +#include +#include +#include + +enum Unit { + CELCIUS, + FAHRENHEIT +}; + +struct QueueItem { + unsigned long read_on; + uint8_t pin; + float * var; + Unit unit; +}; + +class MultiMAX6675 { + public: + void begin(SPIClass * spi); + uint32_t add(uint8_t cs); + void read(Unit unit, uint8_t pin_index, float * var); + void loop(); + private: + SPIClass * spi; + std::vector cs_pins; + std::vector read_queue; + uint16_t read_queue_free_on_beginning = 0; + unsigned long current_millis; + bool start_read = false; +}; + +#endif \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..77e457a --- /dev/null +++ b/README.md @@ -0,0 +1,57 @@ +# MultiMAX6675 +--- +### A simple Arduino library that allows you to **non-blocking(ly)** read MAX6675 K-Type Thermocouple Sensor. + +## **Library is still in-progress, if you get any bugs, please open an issue.** + +## Todo +### - add errors when thermocouple is not connected. +### - optimizations + +## Example Usage +```c++ +#include +#include +#include + +// Pins, modify accordingly. + +#define SPI_SCLK 27 +#define SPI_MISO 25 +#define TC1_CS 26 +#define TC2_CS 14 + +MultiMAX6675 thermocouples; + +uint8_t thermocouple2_index; +uint8_t thermocouple1_index; + +void setup() { + Serial.begin(9600); + // Initialize SPI, or create your own SPIClass. + // It is assumed that they all share the same SPI Bus. + SPI.begin(SPI_SCLK, SPI_MISO); + thermocouples.begin(&SPI); // Takes a pointer to an SPIClass + + thermocouple1_index = thermocouples.add(TC1_CS); // Takes a CS(Chip Select) pin of the thermocouple, returns an index. Either save the index to a variable, or you don't have to if you already know the order. + thermocouple2_index = thermocouples.add(TC2_CS); +} + +float thermocouple1_temperature; +float thermocouple2_temperature; + +unsigned long prev = 0; + +void loop() { + // [Unit::CELCIUS, Unit::FAHRENHEIT][Thermocouple Index, look above][Pointer to a float, where you want to save the temperature.] + // You can ONLY read every 250ms(preferably a bit more), in order to not run out of memory(?), due to sensor limitation, resulting in a crash. Use millis() to do so, otherwise, what's point of this library. xD + if(millis() >= (prev + 300)) { + prev = millis(); + thermocouples.read(Unit::CELCIUS, thermocouple1_index, &thermocouple1_temperature); + thermocouples.read(Unit::CELCIUS, thermocouple2_index, &thermocouple2_temperature); + Serial.println(thermocouple1_temperature); + Serial.println(thermocouple2_temperature); + } + thermocouples.loop(); // Call this as often as possible. +} +``` \ No newline at end of file diff --git a/examples/Read/Read.ino b/examples/Read/Read.ino new file mode 100644 index 0000000..6872a60 --- /dev/null +++ b/examples/Read/Read.ino @@ -0,0 +1,44 @@ +#include +#include +#include + +// Pins, modify accordingly. + +#define SPI_SCLK 27 +#define SPI_MISO 25 +#define TC1_CS 26 +#define TC2_CS 14 + +MultiMAX6675 thermocouples; + +uint8_t thermocouple2_index; +uint8_t thermocouple1_index; + +void setup() { + Serial.begin(9600); + // Initialize SPI, or create your own SPIClass. + // It is assumed that they all share the same SPI Bus. + SPI.begin(SPI_SCLK, SPI_MISO); + thermocouples.begin(&SPI); // Takes a pointer to an SPIClass + + thermocouple1_index = thermocouples.add(TC1_CS); // Takes a CS(Chip Select) pin of the thermocouple, returns an index. Either save the index to a variable, or you don't have to if you already know the order. + thermocouple2_index = thermocouples.add(TC2_CS); +} + +float thermocouple1_temperature; +float thermocouple2_temperature; + +unsigned long prev = 0; + +void loop() { + // [Unit::CELCIUS, Unit::FAHRENHEIT][Thermocouple Index, look above][Pointer to a float, where you want to save the temperature.] + // You can ONLY read every 250ms(preferably a bit more), in order to not run out of memory(?), due to sensor limitation, resulting in a crash. Use millis() to do so, otherwise, what's point of this library. xD + if(millis() >= (prev + 300)) { + prev = millis(); + thermocouples.read(Unit::CELCIUS, thermocouple1_index, &thermocouple1_temperature); + thermocouples.read(Unit::FAHRENHEIT, thermocouple2_index, &thermocouple2_temperature); + Serial.println(thermocouple1_temperature); + Serial.println(thermocouple2_temperature); + } + thermocouples.loop(); // Call this as often as possible. +} \ No newline at end of file diff --git a/keywords.txt b/keywords.txt new file mode 100644 index 0000000..e17688f --- /dev/null +++ b/keywords.txt @@ -0,0 +1,4 @@ +MultiMAX6675 KEYWORD1 +begin KEYWORD2 +add KEYWORD2 +read KEYWORD2 \ No newline at end of file diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..c0da3bc --- /dev/null +++ b/library.properties @@ -0,0 +1,11 @@ +name=MultiMAX6675 +version=0.0.1 +author=Shuncey +maintainer=Shuncey +sentence=Read multiple MAX6675 sensor non-blocking(ly) +paragraph=A simple Arduino library that allows you to non-blocking(ly) read MAX6675 K-Type Thermocouple Sensor. +category=Sensors +url=https://github.com/shunceyb/MultiMAX6675 +architectures=* +includes=MultiMAX6675.h +depends= \ No newline at end of file