summaryrefslogtreecommitdiff
path: root/minion/src/temperature.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'minion/src/temperature.cpp')
-rw-r--r--minion/src/temperature.cpp117
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;
+}