VOC Optimation
[owSlave2.git] / DS2438_DHT22 / DS2438_DHT22 - Kopie.c
1 // Copyright (c) 2015, Tobias Mueller tm(at)tm3d.de\r
2 // All rights reserved.\r
3 //\r
4 // Redistribution and use in source and binary forms, with or without\r
5 // modification, are permitted provided that the following conditions are\r
6 // met:\r
7 //\r
8 //  * Redistributions of source code must retain the above copyright\r
9 //    notice, this list of conditions and the following disclaimer.\r
10 //  * Redistributions in binary form must reproduce the above copyright\r
11 //    notice, this list of conditions and the following disclaimer in the\r
12 //    documentation and/or other materials provided with the\r
13 //    distribution.\r
14 //  * All advertising materials mentioning features or use of this\r
15 //    software must display the following acknowledgement: This product\r
16 //    includes software developed by tm3d.de and its contributors.\r
17 //  * Neither the name of tm3d.de nor the names of its contributors may\r
18 //    be used to endorse or promote products derived from this software\r
19 //    without specific prior written permission.\r
20 //\r
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\r
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
32 \r
33 \r
34 #define F_CPU 8000000UL\r
35 #define FP_CALC\r
36 #include <avr/io.h>\r
37 #include <avr/interrupt.h>\r
38 #include <util/delay.h>\r
39 #include <avr/wdt.h>\r
40 #include <avr/sleep.h>\r
41 \r
42 extern void OWINIT();\r
43 \r
44 \r
45 uint8_t owid[8]={0x26, 0xA2, 0xD9, 0x84, 0xDD, 0xDD, 0x05, 0xCE};/**/\r
46 uint8_t config_info[16]={0x01,0x06, 0x05,0x08, 0x04,0x07, 0x00,0x00, 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00};\r
47         \r
48 \r
49 extern uint8_t mode;\r
50 extern uint8_t gcontrol;\r
51 extern uint8_t reset_indicator;\r
52 extern uint8_t alarmflag;\r
53 \r
54 volatile uint8_t wdcounter;\r
55 \r
56 \r
57 typedef union {\r
58 #if  defined(__AVR_ATtiny25__)\r
59         volatile uint8_t bytes[16];\r
60 #else\r
61         volatile uint8_t bytes[64];\r
62 #endif\r
63         struct {\r
64                 uint8_t status;  //1\r
65                 int16_t temp;  //2\r
66                 uint16_t voltage;  //4\r
67                 uint16_t current;  //6\r
68                 uint8_t threshold; //8\r
69                 \r
70                 uint8_t page1[8]; //9\r
71 #if  defined(__AVR_ATtiny25__)\r
72 #else\r
73                 uint8_t page2[8]; //17\r
74                 uint8_t page3[8]; //25\r
75                 uint8_t page4[8];  //33\r
76                 uint8_t page5[8];  //41\r
77                 uint8_t page6[8];  //49\r
78                 uint8_t page7[8];  //57\r
79                 //uint8_t crc;  //65\r
80 #endif\r
81         };\r
82 } pack_t;\r
83 volatile pack_t pack;\r
84 \r
85 #if  defined(__AVR_ATtiny25__)||defined(__AVR_ATtiny45__)  || defined(__AVR_ATtiny85__)\r
86 \r
87 #define DDR_SENSOR   DDRB \r
88 #define PORT_SENSOR  PORTB\r
89 #define PIN_SENSOR   PINB\r
90 #define SENSOR       PB4\r
91 #endif\r
92 \r
93 #if  defined(__AVR_ATtiny24__)||defined(__AVR_ATtiny44__)  || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny24A__)||defined(__AVR_ATtiny44A__)  || defined(__AVR_ATtiny84A__)\r
94 #define DDR_SENSOR   DDRA\r
95 #define PORT_SENSOR  PORTA\r
96 #define PIN_SENSOR   PINA\r
97 #define SENSOR       PINA2\r
98 #endif\r
99 \r
100 \r
101 \r
102 #define SENSOR_sda_out          DDR_SENSOR |= (1 << SENSOR)\r
103 #define SENSOR_sda_in                   DDR_SENSOR &= ~(1 << SENSOR);PORT_SENSOR |= (1 << SENSOR) // release sda => hi in consequence of pullup\r
104 #define SENSOR_sda_low    PORT_SENSOR &= ~(1 << SENSOR)\r
105 #define SENSOR_is_hi                    PIN_SENSOR & (1 << SENSOR)\r
106 #define SENSOR_is_low           !(PIN_SENSOR & (1 << SENSOR))\r
107 \r
108 volatile int16_t am2302_temp;\r
109 volatile uint16_t am2302_hum;\r
110 \r
111 \r
112 uint8_t am_wait(uint8_t _time,uint8_t _signal){\r
113         TCNT1=0;\r
114         while(TCNT1==0);\r
115         if (_signal) \r
116                 while((SENSOR_is_hi)&&(TCNT1<_time)) {}\r
117         else\r
118                 while((SENSOR_is_low)&&(TCNT1<_time)) {}\r
119          \r
120                 if (TCNT1>=_time) {return 1;}\r
121         return 0;\r
122 }\r
123 \r
124 volatile uint8_t am2302_mode=0; \r
125 volatile uint8_t timeout=0;\r
126 \r
127 \r
128 \r
129 #if  defined(__AVR_ATtiny24__)||defined(__AVR_ATtiny44__)  || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny24A__)||defined(__AVR_ATtiny44A__)  || defined(__AVR_ATtiny84A__)\r
130 ISR(WATCHDOG_vect) {\r
131 #else\r
132 ISR(WDT_vect) {\r
133 #endif \r
134         sleep_disable();          // Disable Sleep on Wakeup\r
135         am2302_mode++;\r
136         if (reset_indicator==1) reset_indicator++;\r
137         else if (reset_indicator==2) mode=0;\r
138 /*      if (timeout==2) {\r
139                 DIS_TIMER;\r
140                 EN_OWINT;\r
141                 mode=OWM_SLEEP;\r
142         }\r
143         timeout++;*/\r
144         sleep_enable();           // Enable Sleep Mode\r
145 \r
146 }\r
147 \r
148 int testSW() {\r
149         uint8_t r;\r
150         DDRB&=~(1<<PORTB0);  //Eingang\r
151         __asm__ __volatile__ ("nop");\r
152         PORTB|=(1<<PORTB0); //Pullup\r
153         __asm__ __volatile__ ("nop");\r
154         __asm__ __volatile__ ("nop");\r
155         __asm__ __volatile__ ("nop");\r
156         __asm__ __volatile__ ("nop");\r
157         __asm__ __volatile__ ("nop");\r
158         r=PINB&(1<<PORTB0);\r
159         __asm__ __volatile__ ("nop");\r
160         PORTB&=~(1<<PORTB0);\r
161         __asm__ __volatile__ ("nop");\r
162         DDRB|=(1<<PORTB0);  //Eingang\r
163         return (r==0);\r
164         \r
165         \r
166 }       \r
167         \r
168 uint8_t am2302_1() {\r
169         int16_t lam2302_temp;\r
170         uint16_t lam2302_hum;\r
171         uint8_t rSREG;\r
172         uint8_t sensor_data[5];\r
173 #if  defined(__AVR_ATtiny25__)||defined(__AVR_ATtiny45__)  || defined(__AVR_ATtiny85__)\r
174         TCCR1=(1<<CS12); //Clock/8 1µs\r
175 #endif\r
176 \r
177 #if  defined(__AVR_ATtiny24__)||defined(__AVR_ATtiny44__)  || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny24A__)||defined(__AVR_ATtiny44A__)  || defined(__AVR_ATtiny84A__)\r
178         TCCR1B=(1<<CS11); //Clock/8 1µs\r
179 #endif\r
180         SENSOR_sda_out;\r
181         SENSOR_sda_low; // MCU start signal\r
182         TCNT1=0;while(TCNT1==0);while(TCNT1<250) {}// start signal (pull sda down for min 0.8ms and maximum 20ms)\r
183         TCNT1=0;while(TCNT1==0);while(TCNT1<250) {}// start signal (pull sda down for min 0.8ms and maximum 20ms)\r
184         SENSOR_sda_in;\r
185         if (am_wait(200,1)) return 2;\r
186 \r
187         // AM2302 response signal min: 75us typ:80us max:85us\r
188         if (am_wait(100,0)) return 3;\r
189         if (am_wait(100,1)) return 4;\r
190         \r
191         for(uint8_t i = 0; i < 5; i++)  {\r
192                 uint8_t sensor_byte = 0;\r
193                 for(uint8_t j = 1; j <= 8; j++) {// get 8 bits from sensor\r
194                         if (am_wait(88,0)) return 5;\r
195                         \r
196                         TCNT1=0;while(TCNT1==0);;while(TCNT1<35)                ;\r
197                         sensor_byte <<= 1; // add new lower byte\r
198                         if (SENSOR_is_hi) {// if sda high after 30us => bit=1 else bit=0\r
199                                 sensor_byte |= 1;\r
200                                 if (am_wait(45,1)) return 6;// 30us - 75us = 45us\r
201                         }\r
202                 }\r
203                 sensor_data[i] = sensor_byte;\r
204         }\r
205 \r
206         // checksum\r
207         if ( ((sensor_data[0]+sensor_data[1]+sensor_data[2]+sensor_data[3]) & 0xff ) != sensor_data[4])\r
208         {\r
209                 // debug output\r
210                 //printf("%b %b %b %b %b %b" CR, sensor_data[0], sensor_data[1], sensor_data[2], sensor_data[3], sensor_data[4], ((sensor_data[0]+sensor_data[1]+sensor_data[2]+sensor_data[3]) & 0xff ));\r
211                 PORTB&=~(1<<PINB0);\r
212                 return 7;\r
213         }\r
214         if (!testSW()) {\r
215 #ifdef FP_CALC\r
216         double htemp;\r
217         if (sensor_data[2]&0x80) { //min\r
218                 sensor_data[2]&=~(0x80);\r
219                 htemp=-((sensor_data[2]<<8) + sensor_data[3]);\r
220         } else\r
221                 htemp=((sensor_data[2]<<8) + sensor_data[3]);\r
222         double hhum=(1.0546-0.000216*htemp)*((sensor_data[0]<<8) + sensor_data[1]);\r
223         \r
224         lam2302_hum=0.318*hhum +76;\r
225         lam2302_temp=htemp*25.6;\r
226 #else\r
227 \r
228         if (sensor_data[2]&0x80) { //minus\r
229                 sensor_data[2]&=~(0x80);\r
230                 lam2302_temp=-((sensor_data[2]<<8) + sensor_data[3]);\r
231         } else\r
232                 lam2302_temp=((sensor_data[2]<<8) + sensor_data[3]);\r
233         \r
234         lam2302_hum=((sensor_data[0]<<8) + sensor_data[1]);\r
235         volatile uint32_t h1=lam2302_temp*lam2302_hum*3/44803;\r
236         lam2302_hum=lam2302_hum*16/49-h1+80;\r
237         //lam2302_temp=lam2302_temp*128/5;\r
238 \r
239         int16_t h2=lam2302_temp%5;\r
240         lam2302_temp=lam2302_temp/5;\r
241         lam2302_temp*=128;\r
242         lam2302_temp+=h2*128/5;\r
243 #endif    \r
244         config_info[5]=7;\r
245         }\r
246         else {\r
247                 if (sensor_data[2]&0x80) { //minus\r
248                         sensor_data[2]&=~(0x80);\r
249                         lam2302_temp=-((sensor_data[2]<<8) + sensor_data[3]);\r
250                 } else\r
251                 lam2302_temp=((sensor_data[2]<<8) + sensor_data[3])*25.6;;\r
252                 \r
253                 lam2302_hum=((sensor_data[0]<<8) + sensor_data[1]);\r
254                 config_info[5]=12;\r
255         }\r
256         rSREG=SREG;\r
257         cli();\r
258         am2302_hum=lam2302_hum;\r
259         am2302_temp=lam2302_temp;\r
260         SREG=rSREG;\r
261         return 0;\r
262 }\r
263 \r
264 \r
265 uint8_t am2302_2() { //4mhz\r
266         int16_t lam2302_temp;\r
267         uint16_t lam2302_hum;\r
268         uint8_t rSREG;\r
269         uint8_t sensor_data[5];\r
270         #if  defined(__AVR_ATtiny25__)||defined(__AVR_ATtiny45__)  || defined(__AVR_ATtiny85__)\r
271         TCCR1=(1<<CS11)|(1<<CS10); //Clock/8 1µs\r
272         #endif\r
273 \r
274         #if  defined(__AVR_ATtiny24__)||defined(__AVR_ATtiny44__)  || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny24A__)||defined(__AVR_ATtiny44A__)  || defined(__AVR_ATtiny84A__)\r
275         TCCR1B=(1<<CS11); //Clock/8 1µs\r
276         #endif\r
277         SENSOR_sda_out;\r
278         SENSOR_sda_low; // MCU start signal\r
279         TCNT1=0;while(TCNT1==0);while(TCNT1<250) {}// start signal (pull sda down for min 0.8ms and maximum 20ms)\r
280         TCNT1=0;while(TCNT1==0);while(TCNT1<250) {}// start signal (pull sda down for min 0.8ms and maximum 20ms)\r
281         SENSOR_sda_in;\r
282         if (am_wait(200,1)) return 2;\r
283 \r
284         // AM2302 response signal min: 75us typ:80us max:85us\r
285         if (am_wait(100,0)) return 3;\r
286         if (am_wait(100,1)) return 4;\r
287         \r
288         for(uint8_t i = 0; i < 5; i++)  {\r
289                 uint8_t sensor_byte = 0;\r
290                 for(uint8_t j = 1; j <= 8; j++) {// get 8 bits from sensor\r
291                         if (am_wait(88,0)) return 5;\r
292                         \r
293                         TCNT1=0;while(TCNT1==0);;while(TCNT1<35)                ;\r
294                         sensor_byte <<= 1; // add new lower byte\r
295                         if (SENSOR_is_hi) {// if sda high after 30us => bit=1 else bit=0\r
296                                 sensor_byte |= 1;\r
297                                 if (am_wait(45,1)) return 6;// 30us - 75us = 45us\r
298                         }\r
299                 }\r
300                 sensor_data[i] = sensor_byte;\r
301         }\r
302 \r
303         // checksum\r
304         if ( ((sensor_data[0]+sensor_data[1]+sensor_data[2]+sensor_data[3]) & 0xff ) != sensor_data[4])\r
305         {\r
306                 // debug output\r
307                 //printf("%b %b %b %b %b %b" CR, sensor_data[0], sensor_data[1], sensor_data[2], sensor_data[3], sensor_data[4], ((sensor_data[0]+sensor_data[1]+sensor_data[2]+sensor_data[3]) & 0xff ));\r
308                 PORTB&=~(1<<PINB0);\r
309                 return 7;\r
310         }\r
311 #ifdef FP_CALC\r
312         lam2302_hum=0.318* ((sensor_data[0]<<8) + sensor_data[1])+76;\r
313         if (sensor_data[2]&0x80) { //minus\r
314                 sensor_data[2]&=~(0x80);\r
315                 lam2302_temp=-((sensor_data[2]<<8) + sensor_data[3])*25.6;\r
316         } else\r
317                 lam2302_temp=((sensor_data[2]<<8) + sensor_data[3])*25.6;\r
318 #else\r
319 \r
320 \r
321         if (sensor_data[2]&0x80) { //minus\r
322                 sensor_data[2]&=~(0x80);\r
323                 lam2302_temp=-((sensor_data[2]<<8) + sensor_data[3]);\r
324         } else\r
325         lam2302_temp=((sensor_data[2]<<8) + sensor_data[3]);\r
326         \r
327         lam2302_hum=((sensor_data[0]<<8) + sensor_data[1]);\r
328         volatile uint32_t h1=lam2302_temp*lam2302_hum*3/44803;\r
329         lam2302_hum=lam2302_hum*16/49-h1+80;\r
330         //lam2302_temp=lam2302_temp*128/5;\r
331 \r
332         int16_t h2=lam2302_temp%5;\r
333         lam2302_temp=lam2302_temp/5;\r
334         lam2302_temp*=128;\r
335         lam2302_temp+=h2*128/5;\r
336 #endif  \r
337         \r
338         \r
339         rSREG=SREG;\r
340         cli();\r
341         am2302_hum=lam2302_hum;\r
342         am2302_temp=lam2302_temp;\r
343         SREG=rSREG;\r
344         return 0;\r
345 }\r
346 \r
347 \r
348 \r
349 int main(void){\r
350     PRR|=(1<<PRUSI)|(1<<PRADC);  //Switch off usi and adc for save Power\r
351 #if  defined(__AVR_ATtiny24__)||defined(__AVR_ATtiny44__)  || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny24A__)||defined(__AVR_ATtiny44A__)  || defined(__AVR_ATtiny84A__)\r
352         PORTA=0xFF;\r
353         PORTB=0xFF-(1<<PORTB0); //Schalter kann gegen Masse sein und zieht dann immer Strom\r
354         DDRB|=(1<<PORTB0); //Als Ausgang und 0\r
355 #endif\r
356         OWINIT();\r
357 \r
358         ACSR|=(1<<ACD);  //Disable Comparator\r
359         ADCSRB|=(1<<ACME); //Disable Analog multiplexer\r
360         MCUCR &=~(1<<PUD); //All Pins Pullup...\r
361         MCUCR |=(1<<BODS);\r
362         MCUCR &=~(1<<PUD);\r
363         \r
364 #if  defined(__AVR_ATtiny25__)||defined(__AVR_ATtiny45__)  || defined(__AVR_ATtiny85__)\r
365 \r
366         PORTB|=(1<<PINB0)|(1<<PINB1)|(1<<PINB3)|(1<<PINB4)|(1<<PINB5);\r
367         DDRB|=(1<<PINB1); //DBLINE\r
368 #define SENSON PORTB|=(1<<PINB0);\r
369 #define SENSOFF PORTB&=~(1<<PINB0);\r
370         DDRB|=(1<<PINB0); //stromversorgung\r
371         \r
372         // Set up Watch Dog Timer for Inactivity\r
373         WDTCR |= ((1<<WDCE) | (1<<WDE));   // Enable the WD Change Bit\r
374         WDTCR =   (1<<WDIE) |              // Enable WDT Interrupt\r
375         (1<<WDP2) | (1<<WDP1);   // Set Timeout to ~2 seconds\r
376 #endif\r
377 \r
378 #if  defined(__AVR_ATtiny24__)||defined(__AVR_ATtiny44__)  || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny24A__)||defined(__AVR_ATtiny44A__)  || defined(__AVR_ATtiny84A__)\r
379 \r
380 \r
381         DDRA|=(1<<PINA1); //stromversorgung\r
382 #define SENSON PORTA|=(1<<PINA1);\r
383 #define SENSOFF PORTA&=~(1<<PINA1);\r
384 \r
385         // Set up Watch Dog Timer for Inactivity\r
386         WDTCSR |= (1<<WDCE) ;   // Enable the WD Change Bit\r
387         WDTCSR =   (1<<WDIE) |              // Enable WDT Interrupt\r
388         (1<<WDP2) | (1<<WDP1);   // Set Timeout to ~2 seconds\r
389 #endif\r
390 \r
391         \r
392     uint8_t i;\r
393         uint8_t err;\r
394 #if  defined(__AVR_ATtiny25__)\r
395     for(i=0;i<16;i++) pack.bytes[i]=0;\r
396 #else\r
397         uint8_t pn=1;\r
398     for(i=0;i<64;i++) pack.bytes[i]=0;\r
399 #endif\r
400         //pack.bytes[0]=1;\r
401         //pack.bytes[1]=2;\r
402         SENSON\r
403         _delay_ms(4000);\r
404         err =am2302_1();\r
405         sei();\r
406     while(1)   {\r
407                 alarmflag=1;\r
408                 if (am2302_mode==2) {\r
409                         err=am2302_1();\r
410                         if (err!=0) {\r
411 #if  defined(__AVR_ATtiny25__)\r
412 #else\r
413                                 pack.page3[pn]=err;\r
414                                 pn=pn+1;if (pn>31) pn=1;\r
415 #endif\r
416                         }\r
417                         SENSOFF\r
418                         am2302_mode=3;\r
419                 }\r
420                 if (am2302_mode>=8) {\r
421                         am2302_mode=0;\r
422                         SENSON\r
423                 }\r
424 #if  defined(__AVR_ATtiny25__)||defined(__AVR_ATtiny45__)  || defined(__AVR_ATtiny85__)\r
425                         if (((TIMSK & (1<<TOIE0))==0)&& (mode==0))\r
426 #endif                  \r
427 #if  defined(__AVR_ATtiny24__)||defined(__AVR_ATtiny44__)  || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny24A__)||defined(__AVR_ATtiny44A__)  || defined(__AVR_ATtiny84A__)\r
428                         if (((TIMSK0 & (1<<TOIE0))==0)&& (mode==0))\r
429 #endif\r
430                           {\r
431 //                      CLKPR=(1<<CLKPCE);\r
432         //              CLKPR=(1<<CLKPS2); /*0.5Mhz*/\r
433                         //PORTB&=~(1<<PINB1);\r
434                         MCUCR|=(1<<SE)|(1<<SM1);\r
435                         MCUCR&=~(1<<ISC01);\r
436                 } else {\r
437                         MCUCR|=(1<<SE);\r
438                         MCUCR&=~(1<<SM1);\r
439                 }\r
440                 asm("SLEEP");\r
441    }\r
442 \r
443 \r
444 }