1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#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))
{
_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<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();
_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);
}
|