diff options
Diffstat (limited to 'minion/src/temperature.cpp')
-rw-r--r-- | minion/src/temperature.cpp | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/minion/src/temperature.cpp b/minion/src/temperature.cpp new file mode 100644 index 0000000..1231e24 --- /dev/null +++ b/minion/src/temperature.cpp @@ -0,0 +1,117 @@ +#include "temperature.hpp" + +#include <Arduino.h> + +TemperatureSensor::TemperatureSensor(uint8_t pin) noexcept : _pin(pin) +{ + pinMode(_pin, OUTPUT); +} + +auto TemperatureSensor::read_temperature() noexcept -> TemperatureSensorStatus +{ + // Send start signal and wait + digitalWrite(_pin, LOW); + delay(TemperatureSensorTiming::START_SIGNAL_TIME_MILLIS); + + // Pull up and wait for response + digitalWrite(_pin, HIGH); + delayMicroseconds(TemperatureSensorTiming::RESPONSE_SIGNAL_WAIT_TIME_MICROS); + + pinMode(_pin, INPUT); + + // The sensor sends a LOW signal and keeps it for 80us + if (!_wait_read(LOW, TemperatureSensorTiming::RESPONSE_SIGNAL_TIME_MICROS)) + { + return TemperatureSensorStatus::TIMEOUT; + } + + // The sensor sends a HIGH signal and keeps it for 80us + if (!_wait_read(HIGH, TemperatureSensorTiming::RESPONSE_SIGNAL_TIME_MICROS)) + { + return TemperatureSensorStatus::TIMEOUT; + } + + uint8_t data_bytes[TEMPERATURE_SENSOR_RESPONSE_DATA_BYTE_CNT] = { 0U, + 0U, + 0U, + 0U, + 0U }; + + uint8_t bit_index = BITS_IN_BYTE - 1U; + uint8_t byte_index = 0U; + + for (uint16_t index = 0U; + index < (BITS_IN_BYTE * TEMPERATURE_SENSOR_RESPONSE_DATA_BYTE_CNT); + index++) + { + // Wait for the start to transmit signal + if (!_wait_read( + LOW, + TemperatureSensorTiming::START_TO_TRANSMIT_SIGNAL_TIME_MICROS + 5U + )) + { + return TemperatureSensorStatus::TIMEOUT; + } + + const auto start_time = micros(); + + if (!_wait_read(HIGH, TemperatureSensorTiming::DATA_TRANSMIT_TIMEOUT_MICROS)) + { + return TemperatureSensorStatus::TIMEOUT; + } + + // A voltage length greater than 40 means the bit is a 1 + if ((micros() - start_time) > 40U) + { + data_bytes[byte_index] |= static_cast<uint8_t>(1U << bit_index); + } + + // Continue to the next byte if it's the last bit + if (bit_index == 0U) + { + // Restart at the MSB + bit_index = BITS_IN_BYTE - 1U; + + byte_index++; + continue; + } + + bit_index--; + } + + // Restore pin to initial state + pinMode(_pin, OUTPUT); + digitalWrite(_pin, HIGH); + + _temperature = data_bytes[2]; + + auto sum = data_bytes[0] + data_bytes[2]; + + if (data_bytes[4] != sum) + { + return TemperatureSensorStatus::CHECKSUM_ERROR; + } + + return TemperatureSensorStatus::OK; +} + +auto TemperatureSensor::temperature() const noexcept -> uint8_t +{ + return _temperature; +} + +// NOLINTNEXTLINE(bugprone-easily-swappable-parameters) +auto TemperatureSensor::_wait_read(uint8_t level, size_t timeout_micros) noexcept -> bool +{ + const auto start_time = micros(); + + while (digitalRead(_pin) == level) + { + if ((start_time + timeout_micros) < micros()) + { + return false; + } + } + + return true; +} |