#include "temperature.hpp" #include 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)) { _restore_pin(); return TemperatureSensorStatus::LOW_RESPONSE_SIGNAL_TIMEOUT; } // The sensor sends a HIGH signal and keeps it for 80us if (!_wait_read(HIGH, TemperatureSensorTiming::RESPONSE_SIGNAL_TIME_MICROS)) { _restore_pin(); return TemperatureSensorStatus::HIGH_RESPONSE_SIGNAL_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 )) { _restore_pin(); return TemperatureSensorStatus::START_TO_TRANSMIT_SIGNAL_TIMEOUT; } const auto start_time = micros(); if (!_wait_read(HIGH, TemperatureSensorTiming::DATA_TRANSMIT_TIMEOUT_MICROS)) { _restore_pin(); return TemperatureSensorStatus::DATA_TRANSMIT_TIMEOUT; } // A voltage length greater than 40 means the bit is a 1 if ((micros() - start_time) > 40U) { data_bytes[byte_index] |= static_cast(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(); _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; } void TemperatureSensor::_restore_pin() noexcept { pinMode(_pin, OUTPUT); digitalWrite(_pin, HIGH); }