1 | /*
|
2 | Atmega verbunden mit einem DS18S20 Temperatursensor
|
3 | 8 LED's geben die gemessene Temperatur aus
|
4 | Die LED's sind an PORTB
|
5 | Beinchen | Wert in °C
|
6 | ---------------------
|
7 | B0 1
|
8 | B1 2
|
9 | B2 4
|
10 | B3 8
|
11 | B4 10
|
12 | B5 20
|
13 | B6 40
|
14 | B7 80
|
15 |
|
16 | die Leuchtenden LED's werden einfach addiert und somit kann die Gesammttemperatur abgelesen werden
|
17 |
|
18 | Am PORT D sind 8 Schalter angeschlossen deren Werte denen der LED's entsprechen, damit lässt sich die Solltemperatur
|
19 | einstellen. Ist diese Erreicht bzw stimmt diese mit der am DS18S20 gemessenen Temperatur überein so wird ein Relais ausgeschaltet
|
20 |
|
21 | Relais ist an C0
|
22 | */
|
23 | #include <avr/io.h>
|
24 | #include <avr/interrupt.h>
|
25 | #define F_CPU 2000000
|
26 | #include <util/delay.h>
|
27 | #include <inttypes.h>
|
28 | #include <stdint.h>
|
29 |
|
30 | #define TRUE 1
|
31 | #define FALSE 0
|
32 |
|
33 | // Anchlussbelegung: An welchen Pins h?ngt der DS1820
|
34 | #define W1_PIN PC0 //PB0 Pin soll der W1_PIN sein - in diesem Fall ist es der DataPin vom DS1820
|
35 | #define W1_IN PINC //Pin abfragen
|
36 | #define W1_OUT PORTC //Ausg?nge ansteuern
|
37 | #define W1_DDR DDRC //Datenrichtung jeweils festlegen - je nach dem ob daten zum DS gesedent, oder vom DS empfangen werden sollen
|
38 | #define LED_OUT PORTB
|
39 | #define LED_DDR DDRB
|
40 | #define RELAIS_C PC1 //Relais an C1
|
41 |
|
42 | // Kommandos an den DS1820
|
43 | #define MATCH_ROM 0x55 //64 Bit code wird vom Master an ale DS gesendet - nur der DS mit dem Passenden 64Bit "namen" antwortet
|
44 | #define SKIP_ROM 0xCC //Master spricht alle DS simultan an - gefollgt von einem Convert_t beginnen alle mit der Temp. Konvertierung
|
45 | #define SEARCH_ROM 0xF0 //identifizieren aller 64Bit adressen der angeschlosenen DS
|
46 | #define CONVERT_T 0x44 //startet eine Temperaturkonvertierung und legt die daten im scratchpad (2byte gro?er Speicher im DS) ab
|
47 | #define READ 0xBE //scratchpad auslesen (Read Befehl an DS schicken)
|
48 | #define WRITE 0x4E //master beschreibt scratchpad (Write Befehl an den DS schicken)
|
49 | #define EE_WRITE 0x48 //scratchpad daten in den EEPROM kopieren
|
50 | #define EE_RECALL 0xB8 //
|
51 |
|
52 | //Reset bei DS1820 ausl?sen (d.h. Master sendet min. 480?s low, dann high,
|
53 | //nach 60...240?s sendet der DS1820 ein low zur?ck)
|
54 | uint8_t w1_reset( void )
|
55 | {
|
56 | uint8_t err;
|
57 |
|
58 | W1_OUT &= ~(1<<W1_PIN); //C0 = W1-PIN als Ausgang mit einem low ansteuern
|
59 | W1_DDR |= 1<<W1_PIN; //W1_PIN als Ausgang alle anderen bleiben unangetastet
|
60 | _delay_us( 480 ); //mindestens 480?s warten
|
61 | cli(); //das Global Interrupt Enable Bit im Status Register wird gel?scht
|
62 | W1_DDR &= ~(1<<W1_PIN); //W1_PIN als Eingang
|
63 | _delay_us( 66 ); //66?s warten
|
64 | err = W1_IN & (1<<W1_PIN); //in err den Zustand von W1_IN speichern (im besten Fall ein low vom DS1820)
|
65 | sei(); //das Global Interrupt Enable Bit im Status Register wird gesetzt
|
66 | _delay_us( 480 - 66 ); //warten
|
67 | if( (W1_IN & (1<<W1_PIN)) == 0 ) // Vergleich -> ist er genau 0 dann err=1
|
68 | err = 1;
|
69 | return err; //d.h. ist nun in err eine 1 so hat der DS1820 geantwortet
|
70 | }
|
71 | //schreibt ein Bit in den IC, gleichzeitig wird ein Bit vom DS empfangen
|
72 | uint8_t w1_bit_io( uint8_t b )
|
73 |
|
74 | {
|
75 | cli(); //das Global Interrupt Enable Bit im Status Register wird gel?scht
|
76 | W1_DDR |= 1<<W1_PIN; //W1_PIN als Ausgang
|
77 | _delay_us( 1 ); //warten
|
78 | if( b )
|
79 | W1_DDR &= ~(1<<W1_PIN); //falls W1_PIN als Eingang geschaltet
|
80 | _delay_us( 15 - 1 ); //warten
|
81 | if( (W1_IN & (1<<W1_PIN)) == 0 ) //falls das logische & von ==0 ergibt
|
82 | b = 0; //b=0
|
83 | _delay_us( 60 - 15 ); //warten
|
84 | W1_DDR &= ~(1<<W1_PIN); //W1_PIN als Eingang
|
85 | sei(); //das Global Interrupt Enable Bit im Status Register wird gesetzt
|
86 | return b;
|
87 | }
|
88 |
|
89 |
|
90 | //benutzt w1_bit_io um nacheinander 8 Bit zum IC zu schicken bzw. umgekehrt gleichzeitig 8 Bit vom IC zu holen
|
91 | uint8_t w1_byte_wr( uint8_t b )
|
92 | {
|
93 | uint8_t i = 8, j; //8Bit lang
|
94 |
|
95 | do {
|
96 | j = w1_bit_io( b & 1 ); //das Ergebniss aus w1_bit_io
|
97 | b >>= 1;
|
98 | if( j )
|
99 | b |= 0x80; //b oder= 0b10000000
|
100 | } while( --i );
|
101 | return b;
|
102 | }
|
103 | //liest ein Byte vom DS1820
|
104 | uint8_t w1_byte_rd( void )
|
105 | {
|
106 | return w1_byte_wr( 0xFF );
|
107 | }
|
108 | //?bertrag?t ein Kommando zu IC
|
109 | void w1_command( uint8_t command )
|
110 | {
|
111 | w1_reset(); //zuerst die restet prozedur
|
112 | w1_byte_wr( SKIP_ROM ); //dann alle DS1820 simultan ansprechen
|
113 | w1_byte_wr( command ); //dann das Kommando
|
114 | }
|
115 | //Messung starten
|
116 | uint8_t start_meas( void )
|
117 | {
|
118 | if( W1_IN & ( 1 << W1_PIN ) ) { //kleine Fehlererkennung - pr?ft ob der Pegel high ist (Ist der Pin daher auf Eingang geschaltet, dann muss es n?glich sein, beiinaktivem Bus einen HighPegel auszulesen) wird ein high gelesen ist alles True sonst False
|
119 | w1_command( CONVERT_T ); //(then)fals high ausgelesen wurde zum Konvertierungsschritt ?bergehen
|
120 | W1_OUT |= 1 << W1_PIN; //(else) ein high zum ausgang senden
|
121 | return TRUE;
|
122 | }
|
123 | return FALSE;
|
124 | }
|
125 |
|
126 | //Temperatur vom DS abholen
|
127 | int16_t read_meas_fast( void )
|
128 | {
|
129 | uint16_t temp;
|
130 | w1_command( READ ); // read command
|
131 | temp = w1_byte_rd(); // low byte wird nach temp gespeichert
|
132 | temp |= (uint16_t)w1_byte_rd() << 8; // high byte wird nach temp gespeichert
|
133 | // if( id[0] == 0x10 ) // 9 -> 12 bit
|
134 | temp <<= 3;
|
135 | return temp;
|
136 | }
|
137 |
|
138 |
|
139 | int main(void)
|
140 | {
|
141 | uint8_t t_soll = 0; //Variable zum speichern der Zustände von D
|
142 | uint8_t t_ist =0;
|
143 | int8_t xx;
|
144 | const uint16_t pause = 200;
|
145 | const uint16_t pause_2 =80;
|
146 |
|
147 | int8_t p;
|
148 | int8_t tC;
|
149 | int16_t t;
|
150 | int16_t u;
|
151 | int8_t aa = 0b00010001;
|
152 | int8_t bb = 0b00110011;
|
153 | int8_t cc = 0b01110111;
|
154 | int8_t dd = 0b11111111;
|
155 | int8_t ee = 0b11101110;
|
156 | int8_t ff = 0b11001100;
|
157 | int8_t gg = 0b10001000;
|
158 | int8_t hh = 0b10000001;
|
159 | int8_t ii = 0b11000011;
|
160 | int8_t jj = 0b11100111;
|
161 | int8_t kk = 0b11111111;
|
162 | int8_t ll = 0b01111110;
|
163 | int8_t mm = 0b00111100;
|
164 | int8_t nn = 0b00011000;
|
165 | int8_t oo = 0b10001000;
|
166 | int8_t pp = 0b10000001;
|
167 | int8_t qq = 0b11000011;
|
168 | int8_t rr = 0b11100111;
|
169 | int8_t ss = 0b11111111;
|
170 | int8_t tt = 0b01111110;
|
171 | int8_t uu = 0b00111100;
|
172 | int8_t vv = 0b00011000;
|
173 |
|
174 | DDRD = 0x00; //D als Input
|
175 | DDRC = 0xff; //C als Output
|
176 | PORTC = 0x00; //fangen alle bei 0V an
|
177 | DDRB = 0xff; //alle B Port Pins sind Output
|
178 | PORTB = 0x00; //fangen alle bei 0V an
|
179 | // Initialisierung als Lauflicht
|
180 | for(int a=0; a<2; a++)
|
181 | {
|
182 | PORTB = ~aa;
|
183 | _delay_ms(pause);
|
184 | PORTB = ~bb;
|
185 | _delay_ms(pause);
|
186 | PORTB = ~cc;
|
187 | _delay_ms(pause);
|
188 | PORTB = ~dd;
|
189 | _delay_ms(pause);
|
190 | PORTB = ~ee;
|
191 | _delay_ms(pause);
|
192 | PORTB = ~ff;
|
193 | _delay_ms(pause);
|
194 | PORTB = ~gg;
|
195 | _delay_ms(pause);
|
196 | PORTB = ~ff;
|
197 | _delay_ms(pause);
|
198 | PORTB = ~ee;
|
199 | _delay_ms(pause);
|
200 | PORTB = ~dd;
|
201 | _delay_ms(pause);
|
202 | PORTB = ~cc;
|
203 | _delay_ms(pause);
|
204 | PORTB = ~bb;
|
205 | _delay_ms(pause);
|
206 | PORTB = ~aa;
|
207 | }
|
208 |
|
209 | for(int a=0; a<2; a++){
|
210 | PORTB = ~hh;
|
211 | _delay_ms(pause);
|
212 | PORTB = ~ii;
|
213 | _delay_ms(pause);
|
214 | PORTB = ~jj;
|
215 | _delay_ms(pause);
|
216 | PORTB = ~kk;
|
217 | _delay_ms(pause);
|
218 | PORTB = ~ll;
|
219 | _delay_ms(pause);
|
220 | PORTB = ~mm;
|
221 | _delay_ms(pause);
|
222 | PORTB = ~nn;
|
223 | _delay_ms(pause);
|
224 | PORTB = ~mm;
|
225 | _delay_ms(pause);
|
226 | PORTB = ~ll;
|
227 | _delay_ms(pause);
|
228 | PORTB = ~kk;
|
229 | _delay_ms(pause);
|
230 | PORTB = ~jj;
|
231 | _delay_ms(pause);
|
232 | PORTB = ~ii;
|
233 | _delay_ms(pause);
|
234 | PORTB = ~hh;
|
235 | _delay_ms(pause);
|
236 | }
|
237 |
|
238 | for(int a=0; a<10; a++){
|
239 | PORTB = ~oo;
|
240 | _delay_ms(pause_2);
|
241 | PORTB = ~pp;
|
242 | _delay_ms(pause_2);
|
243 | PORTB = ~qq;
|
244 | _delay_ms(pause_2);
|
245 | PORTB = ~rr;
|
246 | _delay_ms(pause_2);
|
247 | PORTB = ~ss;
|
248 | _delay_ms(pause_2);
|
249 | PORTB = ~tt;
|
250 | _delay_ms(pause_2);
|
251 | PORTB = ~uu;
|
252 | _delay_ms(pause_2);
|
253 | PORTB = ~vv;
|
254 | _delay_ms(pause_2);
|
255 | }
|
256 |
|
257 |
|
258 |
|
259 | // Port x, alle Pins als Ausgang schalten (Grundeinstellung)
|
260 | W1_DDR = 0xFF;
|
261 | // Port x, Pins initialisieren (low)
|
262 | W1_OUT = 0x00;
|
263 | // Sensor initialisieren
|
264 | // >>Notiz>> Wir gehen einfach von einem Erfolg aus <<
|
265 | w1_reset();
|
266 | // Hauptschleife
|
267 | do
|
268 | {
|
269 |
|
270 | // Kommando an den Sensor (Messung starten)
|
271 | // >>Notiz>> Wir gehen einfach von einem Erfolg aus <<
|
272 | start_meas();
|
273 |
|
274 | // Temperatur vom Sensor holen
|
275 | t = read_meas_fast();
|
276 | t = t/8;
|
277 | u = t;
|
278 |
|
279 | // Temperatur in Grad Celsius:
|
280 | tC = (t >> 1) | (t & 0xFF00);
|
281 |
|
282 | if(tC < 0) tC = -tC; //Vorzeichen entfernen
|
283 |
|
284 |
|
285 | //reset (alle LEDs aus)
|
286 | p = 0x00;
|
287 |
|
288 | //Konfiguration der Pins für LEDs setzen
|
289 | // (0 = LED an, 1 = LED aus)
|
290 | if(tC >= 80) { p |=(1<<7); tC -= 80; } //Pin7 f?r 80?C an
|
291 | if(tC >= 40) { p |=(1<<6); tC -= 40; } //Pin6 f?r 40?C an
|
292 | if(tC >= 20) { p |=(1<<5); tC -= 20; } //Pin5 f?r 20?C an
|
293 | if(tC >= 10) { p |=(1<<4); tC -= 10; } //Pin4 f?r 10?C an
|
294 | if(tC >= 8) { p |=(1<<3); tC -= 8; } //Pin3 f?r 8?C an
|
295 | if(tC >= 4) { p |=(1<<2); tC -= 4; } //Pin2 f?r 4?C an
|
296 | if(tC >= 2) { p |=(1<<1); tC -= 2; } //Pin1 f?r 2?C an
|
297 | if(tC >= 1) { p |=(1<<0); tC -= 1; } //Pin0 f?r 1?C an
|
298 |
|
299 | t_ist = p;
|
300 | //Solltemp. in der Schleife abholen ermöglicht Solltemp nachzuregeln
|
301 | t_soll = PIND; //Status von D in SchalterD speichern
|
302 |
|
303 |
|
304 | p = ~p; //LED Signal invertieren weil LED falsch angelötet
|
305 | //p = p-0,5; //Eichung des Thermometers
|
306 | LED_OUT = p;
|
307 |
|
308 |
|
309 |
|
310 | ///Hysterese...Relais
|
311 | ///t_ist/ kommt vom Temp. - sensor
|
312 | ///t_soll/ kommt von PIND
|
313 |
|
314 | if((t_ist <= t_soll - 1)) //&& !(PORTC & (1<<RELAIS_C)))
|
315 | {
|
316 | //Heizung //an //(Relais HIGH)
|
317 | PORTC |= (1<<RELAIS_C);
|
318 | }
|
319 | else if((t_ist >= t_soll + 1))// && (PORTC & (1<<RELAIS_C)))
|
320 | {
|
321 | //Heizung////aus //(Relais LOW)//
|
322 | PORTC &= ~ (1<<RELAIS_C);
|
323 | }
|
324 |
|
325 |
|
326 | // ein wenig warten verhindert,
|
327 | // dass der Sensor durch Selbsterw?rmung
|
328 | // falsche Ergebnisse liefert
|
329 | _delay_ms(1000);
|
330 |
|
331 |
|
332 |
|
333 |
|
334 |
|
335 | }while(1);
|
336 |
|
337 | }
|