AskSin++
Ds18b20.h
1 //- -----------------------------------------------------------------------------------------------------------------------
2 // AskSin++
3 // 2018-04-03 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
4 //- -----------------------------------------------------------------------------------------------------------------------
5 
6 #ifndef __SENSORS_DS18B20_h__
7 #define __SENSORS_DS18B20_h__
8 
9 #include <Sensors.h>
10 #if defined(ARDUINO_ARCH_STM32F1)
11 #include <OneWireSTM.h>
12 #else
13 #include <OneWire.h>
14 #endif
15 
16 // https://www.tweaking4all.com/hardware/arduino/arduino-ds18b20-temperature-sensor/
17 
18 namespace as {
19 
20 class Ds18b20 : public Temperature {
21 
22 public:
26  static uint8_t init (OneWire& ow,Ds18b20* devs,uint8_t max) {
27  uint8_t a[8], num=0;
28  while( ow.search(a) == 1 && num < max) {
29  if( OneWire::crc8(a,7) == a[7] ) {
30  if( Ds18b20::valid(a) == true ) {
31  devs->init(ow,a);
32  ++num;
33  ++devs;
34  }
35  }
36  }
37  return num;
38  }
42  static void measure (Ds18b20* devs,uint8_t count) {
43  if (count > 0) {
44  devs->convert(true); // this will trigger all DS18b20 on the bus
45  devs->wait(); // this will also wait for all to be finish
46  for( uint8_t num=0; num < count; ++num, ++devs ) {
47  devs->read(); // read value for every device
48  }
49  }
50  }
54  static bool valid(uint8_t* addr) {
55  return *addr == 0x10 || *addr == 0x28 || *addr == 0x22;
56  }
57 
58 private:
59  uint8_t _addr[8];
60  OneWire* _wire;
61 
62 public:
63  Ds18b20 () : _wire(0) {}
64 
65  void init (OneWire& ow,uint8_t* addr) {
66  _wire = &ow;
67  for( uint8_t i=0; i<8; ++i )
68  _addr[i]=addr[i];
69  _present = true;
70  }
71 
72  void convert(__attribute__((unused)) bool kick=false) {
73  _wire->reset();
74  if( kick == true ) {
75  _wire->skip();
76  }
77  else {
78  _wire->select(_addr);
79  }
80  _wire->write(0x44); // start conversion, use ds.write(0x44,1) with parasite power on at the end
81  }
82 
83  void wait () {
84  //delay(750);
85  while (_wire->read() == 0) ;
86  }
87 
88  void read () {
89  _wire->reset();
90  _wire->select(_addr);
91  _wire->write(0xBE); // Read Scratchpad
92 
93  uint8_t data[9];
94  for (uint8_t i = 0; i < 9; i++) { // we need 9 bytes
95  data[i] = _wire->read();
96  }
97 
98  if (OneWire::crc8(data, 8) == data[8]) {
99  int16_t raw = (data[1] << 8) | data[0];
100  if (_addr[0] == 0x10) {
101  raw = raw << 3; // 9 bit resolution default
102  if (data[7] == 0x10) {
103  // "count remain" gives full 12 bit resolution
104  raw = (raw & 0xFFF0) + 12 - data[6];
105  }
106  } else {
107  byte cfg = (data[4] & 0x60);
108  // at lower res, the low bits are undefined, so let's zero them
109  if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
110  else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
111  else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
113  }
114  _temperature = (raw*10)/16;
115  }
116  }
117 
118  void measure (__attribute__((unused)) bool async=false) {
119  if( _present == true ) {
120  convert();
121  wait();
122  read();
123  }
124  }
125 
126 };
127 
128 }
129 
130 #endif
as::Ds18b20::init
static uint8_t init(OneWire &ow, Ds18b20 *devs, uint8_t max)
Definition: Ds18b20.h:26
as::Ds18b20::valid
static bool valid(uint8_t *addr)
Definition: Ds18b20.h:54
as::Ds18b20::measure
static void measure(Ds18b20 *devs, uint8_t count)
Definition: Ds18b20.h:42
as::Temperature
Definition: Sensors.h:30
as::Ds18b20
Definition: Ds18b20.h:20