comparison simple_ds18b20.c @ 0:8705acff2494

lots of stuff
author Matt Johnston <matt@ucc.asn.au>
date Sat, 01 Jun 2013 01:38:42 +0800
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:8705acff2494
1 // Matt Johnston 2012
2 // Based on ds18x20.c by Martin Thomas, in turn based on code by
3 // Peter // Dannegger and others.
4 //
5 #include <stdio.h>
6 #include <avr/pgmspace.h>
7
8 #include "ds18x20.h"
9 #include "onewire.h"
10 #include "crc8.h"
11
12 #include "simple_ds18b20.h"
13
14 uint8_t
15 simple_ds18b20_start_meas(uint8_t id[])
16 {
17 uint8_t ret;
18
19 ow_reset();
20 if( ow_input_pin_state() ) { // only send if bus is "idle" = high
21 ow_command_with_parasite_enable(DS18X20_CONVERT_T, id);
22 ret = DS18X20_OK;
23 }
24 else {
25 ret = DS18X20_START_FAIL;
26 }
27
28 return ret;
29 }
30
31 static uint8_t
32 read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n )
33 {
34 uint8_t i;
35 uint8_t ret;
36
37 ow_command( DS18X20_READ, id );
38 for ( i = 0; i < n; i++ ) {
39 sp[i] = ow_byte_rd();
40 }
41 if ( crc8( &sp[0], DS18X20_SP_SIZE ) ) {
42 ret = DS18X20_ERROR_CRC;
43 } else {
44 ret = DS18X20_OK;
45 }
46
47 return ret;
48 }
49
50 int16_t
51 ds18b20_raw16_to_decicelsius(uint16_t measure)
52 {
53 uint8_t negative;
54 int16_t decicelsius;
55 uint16_t fract;
56
57 // check for negative
58 if ( measure & 0x8000 ) {
59 negative = 1; // mark negative
60 measure ^= 0xffff; // convert to positive => (twos complement)++
61 measure++;
62 }
63 else {
64 negative = 0;
65 }
66
67 decicelsius = (measure >> 4);
68 decicelsius *= 10;
69
70 // decicelsius += ((measure & 0x000F) * 640 + 512) / 1024;
71 // 625/1000 = 640/1024
72 fract = ( measure & 0x000F ) * 640;
73 if ( !negative ) {
74 fract += 512;
75 }
76 fract /= 1024;
77 decicelsius += fract;
78
79 if ( negative ) {
80 decicelsius = -decicelsius;
81 }
82
83 if ( decicelsius == 850 || decicelsius < -550 || decicelsius > 1250 ) {
84 return DS18X20_INVALID_DECICELSIUS;
85 } else {
86 return decicelsius;
87 }
88 }
89
90 uint8_t
91 simple_ds18b20_read_decicelsius( uint8_t id[], int16_t *decicelsius )
92 {
93 uint16_t reading;
94 uint8_t ret;
95
96 ret = simple_ds18b20_read_raw(id, &reading);
97 if (ret == DS18X20_OK)
98 {
99 *decicelsius = ds18b20_raw16_to_decicelsius(reading);
100 }
101 return ret;
102 }
103
104 uint8_t
105 simple_ds18b20_read_raw( uint8_t id[], uint16_t *reading )
106 {
107 uint8_t sp[DS18X20_SP_SIZE];
108 uint8_t ret;
109
110 if (id)
111 {
112 ow_reset();
113 }
114 ret = read_scratchpad( id, sp, DS18X20_SP_SIZE );
115 if ( ret == DS18X20_OK ) {
116 *reading = sp[0] | (sp[1] << 8);
117 }
118 return ret;
119 }
120
121 static void
122 printhex_nibble(const unsigned char b, FILE *stream)
123 {
124 unsigned char c = b & 0x0f;
125 if ( c > 9 ) {
126 c += 'A'-10;
127 }
128 else {
129 c += '0';
130 }
131 fputc(c, stream);
132 }
133
134 void
135 printhex_byte(const unsigned char b, FILE *stream)
136 {
137 printhex_nibble( b >> 4, stream);
138 printhex_nibble( b, stream);
139 }
140
141 void
142 printhex(uint8_t *id, uint8_t n, FILE *stream)
143 {
144 for (uint8_t i = 0; i < n; i++)
145 {
146 if (i > 0)
147 {
148 fputc(' ', stream);
149 }
150 printhex_byte(id[i], stream);
151 }
152 }
153
154
155 uint8_t
156 simple_ds18b20_read_all()
157 {
158 uint8_t id[OW_ROMCODE_SIZE];
159 for( uint8_t diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE; )
160 {
161 diff = ow_rom_search( diff, &id[0] );
162
163 if( diff == OW_PRESENCE_ERR ) {
164 printf_P( PSTR("No Sensor found\r") );
165 return OW_PRESENCE_ERR; // <--- early exit!
166 }
167
168 if( diff == OW_DATA_ERR ) {
169 printf_P( PSTR("Bus Error\r") );
170 return OW_DATA_ERR; // <--- early exit!
171 }
172
173 int16_t decicelsius;
174 uint8_t ret = simple_ds18b20_read_decicelsius(NULL, &decicelsius);
175 if (ret != DS18X20_OK)
176 {
177 printf_P(PSTR("Failed reading\r"));
178 return OW_DATA_ERR;
179 }
180
181 printf_P(PSTR("DS18B20 %d: "), diff);
182 if (crc8(id, OW_ROMCODE_SIZE))
183 {
184 printf_P(PSTR("CRC fail"));
185 }
186 printhex(id, OW_ROMCODE_SIZE, stdout);
187 printf_P(PSTR(" %d.%d ÂșC\n"), decicelsius/10, decicelsius % 10);
188 }
189 printf_P(PSTR("Done sensors\n"));
190 return DS18X20_OK;
191 }
192