supla-device
Loading...
Searching...
No Matches
DS18B20.h
1/*
2 Copyright (C) AC SOFTWARE SP. Z O.O.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17*/
18
19#ifndef SRC_SUPLA_SENSOR_DS18B20_H_
20#define SRC_SUPLA_SENSOR_DS18B20_H_
21
22#include <Arduino.h>
23#include <DallasTemperature.h>
24#include <OneWire.h>
25
26#include <supla/log_wrapper.h>
27
28#include "supla/sensor/thermometer.h"
29
30namespace Supla {
31namespace Sensor {
32
33class OneWireBus {
34 public:
35 explicit OneWireBus(uint8_t pinNumber)
36 : pin(pinNumber), nextBus(nullptr), lastReadTime(0), oneWire(pinNumber) {
37 SUPLA_LOG_DEBUG("Initializing OneWire bus at pin %d", pinNumber);
38 sensors.setOneWire(&oneWire);
39 sensors.begin();
40 if (sensors.isParasitePowerMode()) {
41 SUPLA_LOG_DEBUG("OneWire(pin %d) Parasite power is ON", pinNumber);
42 } else {
43 SUPLA_LOG_DEBUG("OneWire(pin %d) Parasite power is OFF", pinNumber);
44 }
45
46 SUPLA_LOG_DEBUG(
47 "OneWire(pin %d) Found %d devices:",
48 pinNumber,
49 sensors.getDeviceCount());
50
51 // report parasite power requirements
52
53 DeviceAddress address;
54 char strAddr[64];
55 for (int i = 0; i < sensors.getDeviceCount(); i++) {
56 if (!sensors.getAddress(address, i)) {
57 SUPLA_LOG_DEBUG("Unable to find address for Device %d", i);
58 } else {
59 snprintf(
60 strAddr, sizeof(strAddr),
61 "{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}",
62 address[0],
63 address[1],
64 address[2],
65 address[3],
66 address[4],
67 address[5],
68 address[6],
69 address[7]);
70 SUPLA_LOG_DEBUG("Index %d - address %s", i, strAddr);
71 sensors.setResolution(address, 12);
72 }
73 delay(0);
74 }
75 sensors.setWaitForConversion(true);
76 sensors.requestTemperatures();
77 sensors.setWaitForConversion(false);
78 }
79
80 int8_t getIndex(uint8_t *deviceAddress) {
81 DeviceAddress address;
82 for (int i = 0; i < sensors.getDeviceCount(); i++) {
83 if (sensors.getAddress(address, i)) {
84 bool found = true;
85 for (int j = 0; j < 8; j++) {
86 if (deviceAddress[j] != address[j]) {
87 found = false;
88 }
89 }
90 if (found) {
91 return i;
92 }
93 }
94 }
95 return -1;
96 }
97
98 uint8_t pin;
99 OneWireBus *nextBus;
100 uint32_t lastReadTime;
101 DallasTemperature sensors;
102
103 protected:
104 OneWire oneWire;
105};
106
107class DS18B20 : public Thermometer {
108 public:
109 explicit DS18B20(uint8_t pin, uint8_t *deviceAddress = nullptr) {
110 OneWireBus *bus = oneWireBus;
111 OneWireBus *prevBus = nullptr;
112 address[0] = 0;
113 lastValidValue = TEMPERATURE_NOT_AVAILABLE;
114 retryCounter = 0;
115
116 if (bus) {
117 while (bus) {
118 if (bus->pin == pin) {
119 myBus = bus;
120 break;
121 }
122 prevBus = bus;
123 bus = bus->nextBus;
124 }
125 }
126
127 // There is no OneWire bus created yet for this pin
128 if (!bus) {
129 SUPLA_LOG_DEBUG("Creating OneWire bus for pin: %d", pin);
130 myBus = new OneWireBus(pin);
131 if (prevBus) {
132 prevBus->nextBus = myBus;
133 } else {
134 oneWireBus = myBus;
135 }
136 }
137 if (deviceAddress == nullptr) {
138 SUPLA_LOG_DEBUG(
139 "Device address not provided. Using device from index 0");
140 } else {
141 memcpy(address, deviceAddress, 8);
142 }
143 }
144
146 if (millis() - myBus->lastReadTime > 10000) {
147 myBus->sensors.requestTemperatures();
148 myBus->lastReadTime = millis();
149 }
150 if (millis() - myBus->lastReadTime > 5000 &&
151 (lastReadTime != myBus->lastReadTime)) {
152 channel.setNewValue(getValue());
153 lastReadTime = myBus->lastReadTime;
154 }
155 }
156
157 double getValue() {
158 double value = TEMPERATURE_NOT_AVAILABLE;
159 if (address[0] == 0) {
160 value = myBus->sensors.getTempCByIndex(0);
161 } else {
162 value = myBus->sensors.getTempC(address);
163 }
164
165 if (value == DEVICE_DISCONNECTED_C || value == 85.0) {
166 value = TEMPERATURE_NOT_AVAILABLE;
167 }
168
169 if (value == TEMPERATURE_NOT_AVAILABLE) {
170 retryCounter++;
171 if (retryCounter > 3) {
172 retryCounter = 0;
173 } else {
174 value = lastValidValue;
175 }
176 } else {
177 retryCounter = 0;
178 }
179 lastValidValue = value;
180
181 return value;
182 }
183
184 DallasTemperature &getHwSensors() {
185 return myBus->sensors;
186 }
187
188 protected:
189 static OneWireBus *oneWireBus;
190 OneWireBus *myBus;
191 DeviceAddress address;
192 int8_t retryCounter;
193 double lastValidValue;
194};
195
196OneWireBus *DS18B20::oneWireBus = nullptr;
197
198}; // namespace Sensor
199}; // namespace Supla
200
201#endif // SRC_SUPLA_SENSOR_DS18B20_H_
void iterateAlways()
Method called on each SuplaDevice iteration.
Definition DS18B20.h:145
Definition DS18B20.h:33