µracoli Manual  Version foo
ds18b20.h
1 /* Copyright (c) 2014 Daniel Thiele, Axel Wachtler
2  All rights reserved.
3 
4  Redistribution and use in source and binary forms, with or without
5  modification, are permitted provided that the following conditions
6  are met:
7 
8  * Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13  * Neither the name of the authors nor the names of its contributors
14  may be used to endorse or promote products derived from this software
15  without specific prior written permission.
16 
17  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  POSSIBILITY OF SUCH DAMAGE. */
28 
29 #ifndef DS18B20_H
30 #define DS18B20_H
31 
45 /* === includes ============================================================ */
46 #include <util/crc16.h>
47 #include <string.h>
48 #include "ow.h"
49 #include "sensor_defs.h"
50 
51 /* === macros ============================================================== */
75 #if !defined(DS18B20_NB)
76 # define DS18B20_NB (1)
77 # define DS18B20_ADDR {0}
78 #endif
79 
80 
81 /* undefine if DS18B20 is self-powered */
82 #define DS18B20_PARASITE_POWER (1)
83 
84 #define DS18B20_DEBUG (0)
85 #if DS18B20_DEBUG == 1
86 # include "hif.h"
87 # define DBG(...) PRINTF(__VA_ARGS__)
88 # define DBGP(x) PRINT(x)
89 #else
90 # define DBG(...)
91 # define DBGP(x)
92 #endif
93 
94 
95 /* depends on selected resolution */
96 #define DS18B20_CONV_TIME_MS (188) /* 10-bit resolution, 187.5ms */
97 #define DS18B20_COPYSCRATCH_TIME_MS (20) /* at least 10ms, acc. to datasheet */
98 #define DS18B20_SIZE_SCRATCHPAD (9)
99 
100 #define DS18B20_FUNCCMD_CONVT (0x44)
101 #define DS18B20_FUNCCMD_READSCRATCH (0xBE)
102 #define DS18B20_FUNCCMD_WRITESCRATCH (0x4E)
103 #define DS18B20_FUNCCMD_COPYSCRATCH (0x48)
104 #define DS18B20_FUNCCMD_RECALLEE (0xB8)
105 #define DS18B20_FUNCCMD_READPOWER (0xB4)
106 
107 /* === types =============================================================== */
109 typedef struct
110 {
111  sensor_driver_t g;
112  ow_serial_t addr[DS18B20_NB];
113 } ds18b20_ctx_t;
114 
115 /* === prototypes ========================================================== */
116 #ifdef __cplusplus
117 extern "C" {
118 #endif
119 
120 /* === low level functions ================================================== */
128 static inline uint8_t ds18b20_command(uint8_t command, uint8_t *buf)
129 {
130  uint8_t i;
131  uint8_t crc = 0;
132  uint8_t rv = SENSOR_ERR_OK;
133 
134  switch(command)
135  {
136  case DS18B20_FUNCCMD_CONVT :
137  break;
138  case DS18B20_FUNCCMD_READSCRATCH:
139  ow_byte_write(DS18B20_FUNCCMD_READSCRATCH);
140  DBGP("read scratch:");
141  for(i=0; i<9; i++)
142  {
143  *buf = ow_byte_read();
144  DBG("0x%02x ", *buf);
145  crc = _crc_ibutton_update(crc, *buf++);
146  }
147  DBG("crc = 0x%x\n", crc);
148  if (crc != 0)
149  {
150  rv = SENSOR_ERR_CRC;
151  }
152  break;
153  case DS18B20_FUNCCMD_WRITESCRATCH:
154  break;
155  case DS18B20_FUNCCMD_COPYSCRATCH:
156 #if defined(DS18B20_PARASITE_POWER)
157  PINHI(DQ);
158  PINOUTP(DQ);
159 #endif
160  break;
161  case DS18B20_FUNCCMD_RECALLEE:
162  break;
163  case DS18B20_FUNCCMD_READPOWER:
164  break;
165  default:
166  /* unknown */
167  break;
168  }
169 
170  return rv;
171 }
180 static inline uint8_t ds18b20_read_temperature(ow_serial_t ser, int16_t *temp)
181 {
182  uint8_t buf[DS18B20_SIZE_SCRATCHPAD];
183  uint8_t rv = SENSOR_ERR_OK;
184  /* send convert to all */
185  ow_reset();
186  ow_byte_write(OW_ROMCMD_SKIP);
187  ow_byte_write(DS18B20_FUNCCMD_CONVT);
188  _delay_ms(DS18B20_CONV_TIME_MS);
189 
190  if (ser != 0)
191  {
192  ow_master_matchrom(ser);
193  DBGP("match rom");
194 
195  }
196  else
197  {
198  ow_reset();
199  ow_byte_write(OW_ROMCMD_SKIP);
200  DBGP("skip rom");
201  }
202 
203 
204 #if defined(DS18B20_PARASITE_POWER)
205  PINHI(DQ);
206  PINOUTP(DQ);
207 #endif
208 
209 
210 #if defined(DS18B20_PARASITE_POWER)
211  PININP(DQ);
212  PINLO(DQ);
213 #endif
214 
215  rv = ds18b20_command(DS18B20_FUNCCMD_READSCRATCH, buf);
216  if (rv == SENSOR_ERR_OK)
217  {
218  *temp = ( ((int16_t)buf[1] << 8)| ((int16_t)buf[0] << 0) )/16;
219  }
220  /* TODO: evaluate CRC */
221  return rv;
222 }
223 
224 /* === high level sensor functions ========================================= */
226 static inline void ds18b20_trigger(void *pctx, bool one_shot)
227 {
228 }
229 
231 static inline uint8_t ds18b20_get_val(void *pctx, uint8_t *pdata)
232 {
233  uint8_t rv, err, i;
234  int16_t temp;
235  ds18b20_ctx_t *p = (ds18b20_ctx_t*) pctx;
236 
237  rv = sizeof(sensor_temperature_t)*DS18B20_NB;
238  if (pdata != NULL)
239  {
240  rv = 0;
241  for (i = 0; i < DS18B20_NB; i++)
242  {
243  err = ds18b20_read_temperature(p->addr[i], &temp);
244  if (temp == 85 && err == SENSOR_ERR_OK)
245  {
246  /* TODO: add some quirks or heuristics,
247  If temp is const 85°C we will have a problem here.
248  What a silly chip design - to signal PWRON with a value
249  just from the middle of the valid data range!
250  */
251  err = SENSOR_ERR_PWRON;
252  }
253  if (err == SENSOR_ERR_OK)
254  {
255  ((sensor_temperature_t*)pdata)->type = SENSOR_DATA_TEMPERATURE;
256  ((sensor_temperature_t*)pdata)->sensor = SENSOR_DS18B20;
257  ((sensor_temperature_t*)pdata)->temp = (float)temp;
258  rv += sizeof(sensor_temperature_t);
259  pdata += sizeof(sensor_temperature_t);
260  }
261  else
262  {
263  *pdata++ = 0x80;
264  *pdata++ = err;
265  rv += 2;
266  }
267  ((ds18b20_ctx_t*)pctx)->g.last_error = err;
268  DBG("ds18b20_get_val: temp=%d, rv=%d, err=%d\n\r", temp, rv, err);
269  }
270  }
271 
272  return rv;
273 }
274 
275 static inline uint8_t ds18b20_get_raw(void *pctx, uint8_t *pdata)
276 {
277  return 0;
278 }
279 
280 static inline void ds18b20_sleep(void *pctx)
281 {
282 }
283 
290 static inline uint8_t sensor_create_ds18b20(void *pdata, bool raw)
291 {
292  uint8_t rv = sizeof(ds18b20_ctx_t);
293  ds18b20_ctx_t *pcfg;
294  ow_serial_t tmp_addr[DS18B20_NB] = DS18B20_ADDR;
295  if (pdata != NULL)
296  {
297  /* init generic sensor data */
298  pcfg = (ds18b20_ctx_t *)pdata;
299  pcfg->g.id = SENSOR_DS18B20;
300  pcfg->g.f_trigger = NULL;
301  pcfg->g.f_get_val = raw ? ds18b20_get_raw : ds18b20_get_val;
302  pcfg->g.f_sleep = NULL;
303  // ... more functions to setup
304 
305  /* init private sensor data */
306  memcpy(pcfg->addr, tmp_addr, sizeof(tmp_addr));
307  /* TODO: scan bus for DS18B20 devices and store addresses sorted */
308 
309  /* initialize sensor hardware */
310  }
311  return rv;
312 }
313 
314 #ifdef __cplusplus
315 } /* extern "C" */
316 #endif
317 
318 #endif /* DS18B20_H */
static uint8_t sensor_create_ds18b20(void *pdata, bool raw)
Definition: ds18b20.h:290
#define DS18B20_NB
Definition: ds18b20.h:76
static uint8_t ds18b20_get_val(void *pctx, uint8_t *pdata)
Definition: ds18b20.h:231
uint8_t ow_reset(void)
void ow_master_matchrom(ow_serial_t ser)
static uint8_t ds18b20_command(uint8_t command, uint8_t *buf)
Definition: ds18b20.h:128
static void ds18b20_trigger(void *pctx, bool one_shot)
Definition: ds18b20.h:226
uint8_t ow_byte_read(void)
void ow_byte_write(uint8_t byte)
static uint8_t ds18b20_read_temperature(ow_serial_t ser, int16_t *temp)
Definition: ds18b20.h:180