Browse Source

working, tested original DS1820

Ondřej Hruška 2 years ago
parent
commit
56320f7f26
Signed by: Ondřej Hruška <ondra@ondrovo.com> GPG key ID: 2C5FD5035250423D
5 changed files with 372 additions and 8 deletions
  1. 2 0
      CMakeLists.txt
  2. 1 0
      Makefile
  3. 63 8
      main.c
  4. 248 0
      onewire.c
  5. 58 0
      onewire.h

+ 2 - 0
CMakeLists.txt View File

@@ -19,6 +19,8 @@ set(SOURCE_FILES
19 19
         lib/usart.h
20 20
         lcd.c
21 21
         lcd.h
22
+        onewire.c
23
+        onewire.h
22 24
         )
23 25
 
24 26
 include_directories(lib

+ 1 - 0
Makefile View File

@@ -31,6 +31,7 @@ OBJS += lib/iopins.o
31 31
 OBJS += lib/spi.o
32 32
 OBJS += lib/adc.o
33 33
 OBJS += lcd.o
34
+OBJS += onewire.o
34 35
 
35 36
 # Dirs with header files
36 37
 INCL_DIRS = . lib/

+ 63 - 8
main.c View File

@@ -6,19 +6,24 @@
6 6
 #include <stdint.h>          // C header for int types like uint8_t
7 7
 #include <stdbool.h>         // C header for the bool type
8 8
 #include <stdlib.h>
9
+#include <stdio.h>
9 10
 
10 11
 // Include stuff from the library
11 12
 #include "lib/iopins.h"
12 13
 #include "lib/usart.h"
13 14
 #include "lcd.h"
15
+#include "onewire.h"
14 16
 
15 17
 
16 18
 // Pins
17 19
 #define LED 13
18 20
 
21
+#define OW_PIN D9
22
+
19 23
 void _lcd_wait_bf();
20 24
 void _lcd_write_byte(uint8_t bb);
21 25
 
26
+#if 0
22 27
 // UART receive handler
23 28
 ISR(USART_RX_vect)
24 29
 {
@@ -26,31 +31,81 @@ ISR(USART_RX_vect)
26 31
 	uint8_t b = usart_rx();
27 32
 	usart_tx(b); // send back
28 33
 }
29
-
34
+#endif
30 35
 
31 36
 void main()
32 37
 {
38
+#if 0
33 39
 	usart_init(BAUD_115200);
34 40
 	usart_isr_rx_enable(true); // enable RX interrupt handler
41
+#endif
35 42
 
36 43
 	// configure pins
37 44
 	as_output(LED);
38 45
 
39 46
 	lcd_init();
40 47
 
48
+    lcd_clear();
49
+    lcd_puts("");
50
+
41 51
 	// globally enable interrupts (for the USART_RX handler)
42 52
 	sei();
43
-	uint8_t cnt = 0;
53
+
54
+	uint8_t addr[8];
55
+	char charbuf[21];
56
+
57
+	int dots = 0;
44 58
 	while (1) {
45
-		lcd_clear();
59
+        bool signal = ow_reset(OW_PIN);
60
+        if (!signal) {
61
+            lcd_clear();
62
+            lcd_puts("No 1-Wire detected...");
63
+            dots = 0;
64
+        } else {
65
+            ow_write(OW_PIN, 0x33);
66
+            ow_read_arr(OW_PIN, addr, 8);
46 67
 
47
-		lcd_xy(cnt, 0);
48
-		lcd_putc('A'+cnt);
68
+            lcd_clear();
49 69
 
50
-		cnt = (cnt+1)%20;
70
+            char *p = charbuf;
71
+            for(uint8_t i = 0; i < 4; i++) {
72
+                p += sprintf(p, "%02X", addr[i]);
73
+                if (i < 3) *p++ = ':';
74
+            }
75
+            lcd_puts(charbuf);
76
+            lcd_xy(0, 1);
51 77
 
52
-		pin_toggle(13); // blink the LED
78
+            p = charbuf;
79
+            for(uint8_t i = 0; i < 4; i++) {
80
+                p += sprintf(p, "%02X", addr[4+i]);
81
+                if (i < 3) *p++ = ':';
82
+            }
83
+            lcd_puts(charbuf);
84
+
85
+            ds1820_single_measure(OW_PIN);
86
+            uint16_t cels = ds1820_read_temp_c(OW_PIN);
87
+
88
+            if (cels == 850) {
89
+                lcd_xy(12, 0);
90
+                for(uint8_t i = 0; i <= dots; i++) {
91
+                    lcd_putc('.');
92
+                }
93
+                dots = (dots+1)%3;
94
+            } else {
95
+                p = charbuf;
96
+                p += sprintf(p, "%d", cels/10);
97
+                *p++ = '.';
98
+                p += sprintf(p, "%d", cels%10);
99
+                *p++ = 0xDF;
100
+                *p++ = 'C';
101
+                *p++ = 0;
53 102
 
54
-		_delay_ms(100);
103
+                lcd_xy(12, 0);
104
+                lcd_puts(charbuf);
105
+            }
106
+        }
107
+
108
+		pin_toggle(13); // blink the LED
109
+        _delay_ms(100);
55 110
 	}
56 111
 }

+ 248 - 0
onewire.c View File

@@ -0,0 +1,248 @@
1
+#include <avr/io.h>
2
+#include <util/delay.h>
3
+#include <stdint.h>
4
+#include <stdbool.h>
5
+
6
+#include "iopins.h"
7
+#include "onewire.h"
8
+
9
+
10
+/** Perform bus reset. Returns true if any device is connected */
11
+bool ow_reset(const uint8_t pin)
12
+{
13
+	as_output_n(pin);
14
+	pin_down_n(pin);
15
+	_delay_us(480);
16
+
17
+	as_input_pu_n(pin);
18
+	_delay_us(70);
19
+
20
+	const bool a = ! pin_read_n(pin);
21
+
22
+	_delay_us(410);
23
+
24
+	return a;
25
+}
26
+
27
+
28
+/** Send a single bit */
29
+void _ow_tx_bit(const uint8_t pin, const bool bit)
30
+{
31
+	as_output_n(pin);
32
+	pin_down_n(pin);
33
+
34
+	if (bit)
35
+	{
36
+		_delay_us(6);
37
+		as_input_pu_n(pin);
38
+		_delay_us(64);
39
+	}
40
+	else
41
+	{
42
+		_delay_us(60);
43
+		as_input_pu_n(pin);
44
+		_delay_us(10);
45
+	}
46
+}
47
+
48
+
49
+/** Send a single byte */
50
+void ow_write(const uint8_t pin, const uint8_t byte)
51
+{
52
+	for (uint8_t i = 0; i < 8; i++)
53
+	{
54
+		_ow_tx_bit(pin, (byte >> i) & 0x01);
55
+	}
56
+}
57
+
58
+
59
+/** Read a single bit */
60
+bool _ow_rx_bit(const uint8_t pin)
61
+{
62
+	as_output_n(pin);
63
+	pin_down_n(pin);
64
+	_delay_us(6);
65
+
66
+	as_input_pu_n(pin);
67
+	_delay_us(9);
68
+
69
+	const bool a = pin_read_n(pin);
70
+
71
+	_delay_us(55);
72
+
73
+	return a;
74
+}
75
+
76
+
77
+/** Read a single byte */
78
+uint8_t ow_read(const uint8_t pin)
79
+{
80
+	uint8_t byte = 0;
81
+
82
+	for (uint8_t i = 0; i < 8; i++)
83
+	{
84
+		byte = (byte >> 1) | (_ow_rx_bit(pin) << 7);
85
+	}
86
+
87
+	return byte;
88
+}
89
+
90
+
91
+/** Wait until the device is ready. Returns false on timeout */
92
+bool ow_wait_ready(const uint8_t pin)
93
+{
94
+	uint16_t timeout = 700;
95
+	as_input_pu_n(pin);
96
+
97
+	while (--timeout > 0)
98
+	{
99
+		if (pin_is_high_n(pin)) return true;
100
+		_delay_ms(1);
101
+	}
102
+
103
+	return false;
104
+}
105
+
106
+
107
+/** Read bytes into an array */
108
+void ow_read_arr(const uint8_t pin, uint8_t* array, const uint8_t count)
109
+{
110
+	for (uint8_t i = 0; i < count; i++)
111
+	{
112
+		array[i] = ow_read(pin);
113
+	}
114
+}
115
+
116
+
117
+
118
+// ---------- CRC utils ----------
119
+
120
+/*
121
+ Dallas 1-wire CRC routines for Arduino with examples of usage.
122
+ The 16-bit routine is new.
123
+ The 8-bit routine is from http://github.com/paeaetech/paeae/tree/master/Libraries/ds2482/
124
+
125
+ Copyright (C) 2010 Kairama Inc
126
+
127
+ This program is free software: you can redistribute it and/or modify
128
+ it under the terms of the GNU General Public License as published by
129
+ the Free Software Foundation, either version 3 of the License, or
130
+ (at your option) any later version.
131
+
132
+ This program is distributed in the hope that it will be useful,
133
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
134
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
135
+ GNU General Public License for more details.
136
+
137
+ You should have received a copy of the GNU General Public License
138
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
139
+*/
140
+// Dallas 1-wire 16-bit CRC calculation. Developed from Maxim Application Note 27.
141
+
142
+/** Compute a CRC16 checksum */
143
+uint16_t crc16(uint8_t *data, uint8_t len)
144
+{
145
+	uint16_t crc = 0;
146
+
147
+	for (uint8_t i = 0; i < len; i++)
148
+	{
149
+		uint8_t inbyte = data[i];
150
+		for (uint8_t j = 0; j < 8; j++)
151
+		{
152
+			uint8_t mix = (crc ^ inbyte) & 0x01;
153
+			crc = crc >> 1;
154
+			if (mix)
155
+				crc = crc ^ 0xA001;
156
+
157
+			inbyte = inbyte >> 1;
158
+		}
159
+	}
160
+	return crc;
161
+}
162
+
163
+
164
+// The 1-Wire CRC scheme is described in Maxim Application Note 27:
165
+// "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products"
166
+
167
+/** Compute a CRC8 checksum */
168
+uint8_t crc8(uint8_t *addr, uint8_t len)
169
+{
170
+	uint8_t crc = 0;
171
+
172
+	for (uint8_t i = 0; i < len; i++)
173
+	{
174
+		uint8_t inbyte = addr[i];
175
+		for (uint8_t j = 0; j < 8; j++)
176
+		{
177
+			uint8_t mix = (crc ^ inbyte) & 0x01;
178
+			crc >>= 1;
179
+			if (mix)
180
+				crc ^= 0x8C;
181
+
182
+			inbyte >>= 1;
183
+		}
184
+	}
185
+
186
+	return crc;
187
+}
188
+
189
+
190
+// --- utils for DS1820 ---
191
+
192
+
193
+/** Read temperature in 0.0625°C, or TEMP_ERROR on error */
194
+int16_t ds1820_read_temp(uint8_t pin)
195
+{
196
+	ow_write(pin, READ_SCRATCHPAD);
197
+	uint8_t bytes[9];
198
+	ow_read_arr(pin, bytes, 9);
199
+
200
+	uint8_t crc = crc8(bytes, 8);
201
+	if (crc != bytes[8])
202
+	{
203
+		return TEMP_ERROR;
204
+	}
205
+	else
206
+	{
207
+		int16_t a = ((bytes[1] << 8) | bytes[0]) >> 1;
208
+		a = a << 4;
209
+		a += (16 - bytes[6]) & 0x0F;
210
+		a -= 0x04;
211
+
212
+		return a;
213
+	}
214
+}
215
+
216
+/** Read temperature in 0.1°C, or TEMP_ERROR on error */
217
+int16_t ds1820_read_temp_c(uint8_t pin)
218
+{
219
+	int32_t temp = ds1820_read_temp(pin);
220
+
221
+	if (temp == TEMP_ERROR)
222
+		return TEMP_ERROR;
223
+
224
+	temp *= 625;
225
+	uint16_t rem = temp % 1000;
226
+	temp /= 1000;
227
+	if (rem >= 500) temp++;
228
+
229
+	return (int16_t) temp;
230
+}
231
+
232
+
233
+bool ds1820_single_measure(uint8_t pin)
234
+{
235
+	ow_reset(pin);
236
+	ow_write(pin, SKIP_ROM);
237
+	ow_write(pin, CONVERT_T);
238
+
239
+	if (!ow_wait_ready(pin))
240
+	{
241
+		return false;
242
+	}
243
+
244
+	ow_reset(pin);
245
+	ow_write(pin, SKIP_ROM);
246
+
247
+	return true;
248
+}

+ 58 - 0
onewire.h View File

@@ -0,0 +1,58 @@
1
+#pragma once
2
+
3
+//
4
+// Utils for Dallas OneWire bus (DS1820 etc)
5
+//
6
+
7
+#include <stdint.h>
8
+#include <stdbool.h>
9
+
10
+#define SKIP_ROM  0xCC
11
+#define CONVERT_T 0x44
12
+#define READ_SCRATCHPAD 0xBE
13
+
14
+/** Perform bus reset. Returns true if any device is connected */
15
+bool ow_reset(uint8_t pin);
16
+
17
+/** Send a single byte */
18
+void ow_write(const uint8_t pin, const uint8_t byte);
19
+
20
+/** Read a single byte */
21
+uint8_t ow_read(uint8_t pin);
22
+
23
+/** Wait until the device is ready. Returns false on timeout */
24
+bool ow_wait_ready(uint8_t pin);
25
+
26
+/** Read bytes into an array */
27
+void ow_read_arr(uint8_t pin, uint8_t* array, uint8_t count);
28
+
29
+/** Compute a CRC16 checksum */
30
+uint16_t crc16(uint8_t *data, uint8_t len);
31
+
32
+/** Compute a CRC8 checksum */
33
+uint8_t crc8(uint8_t *addr, uint8_t len);
34
+
35
+// --- utils for DS1820 ---
36
+
37
+#define TEMP_ERROR (-32768)
38
+
39
+/**
40
+ * Read temperature in 0.0625°C, or TEMP_ERROR on error
41
+ * Use this where you'd normally use READ_SCRATCHPAD
42
+ */
43
+int16_t ds1820_read_temp(uint8_t pin);
44
+
45
+
46
+/**
47
+ * Read temperature in 0.1°C, or TEMP_ERROR on error
48
+ * Use this where you'd normally use READ_SCRATCHPAD
49
+ */
50
+int16_t ds1820_read_temp_c(uint8_t pin);
51
+
52
+/**
53
+ * Perform a temperature measurement with single DS1820 device on the line
54
+ * Can be followed by a call to read temperature (READ_SCRATCHPAD).
55
+ *
56
+ * Returns false on failure (device not connected)
57
+ */
58
+bool ds1820_single_measure(uint8_t pin);