VOC Optimation
[owSlave2.git] / DS2438_DHT22 / DS2438_DHT22.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 #include <avr/io.h>\r
36 #include <avr/interrupt.h>\r
37 #include <util/delay.h>\r
38 #include <avr/wdt.h>\r
39 #include <avr/sleep.h>\r
40 #include <avr/pgmspace.h>\r
41 \r
42 \r
43 extern void OWINIT();\r
44 extern void EXTERN_SLEEP();\r
45 \r
46 uint8_t owid[8]={0x26, 0xA2, 0xD9, 0x84, 0xDD, 0xDD, 0x05, 0xCE};/**/\r
47 uint8_t config_info[16]={0x01,0x06, 0x05,0x08, 0x04,0x07, 0x00,0x00, 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00};\r
48 \r
49 \r
50 \r
51 extern uint8_t mode;\r
52 extern uint8_t gcontrol;\r
53 extern uint8_t reset_indicator;\r
54 extern uint8_t alarmflag;\r
55 \r
56 volatile uint8_t wdcounter;\r
57 \r
58 \r
59 typedef union {\r
60 \r
61         volatile uint8_t bytes[64];\r
62         struct {\r
63                 uint8_t status;  //1\r
64                 int16_t temp;  //2\r
65                 uint16_t voltage;  //4\r
66                 uint16_t current;  //6\r
67                 uint8_t threshold; //8\r
68                 \r
69                 uint8_t page1[8]; //9\r
70                 uint8_t page2[8]; //17\r
71                 uint8_t page3[8]; //25\r
72                 uint8_t page4[8];  //33\r
73                 uint8_t page5[8];  //41\r
74                 uint8_t page6[8];  //49\r
75                 uint8_t page7[8];  //57\r
76                 //uint8_t crc;  //65\r
77         };\r
78 } pack_t;\r
79 volatile pack_t pack;\r
80 \r
81 \r
82 #define DDR_SENSOR   DDRA\r
83 #define PORT_SENSOR  PORTA\r
84 #define PIN_SENSOR   PINA\r
85 #define SENSOR       PINA2\r
86 \r
87 #define SENSOR_sda_out          DDR_SENSOR |= (1 << SENSOR)\r
88 #define SENSOR_sda_in                   DDR_SENSOR &= ~(1 << SENSOR);PORT_SENSOR |= (1 << SENSOR) // release sda => hi in consequence of pullup\r
89 #define SENSOR_sda_low    PORT_SENSOR &= ~(1 << SENSOR)\r
90 #define SENSOR_is_hi                    PIN_SENSOR & (1 << SENSOR)\r
91 #define SENSOR_is_low           !(PIN_SENSOR & (1 << SENSOR))\r
92 \r
93 volatile int16_t am2302_temp;\r
94 volatile uint16_t am2302_hum;\r
95 \r
96 \r
97 uint8_t am_wait(uint8_t _time,uint8_t _signal){\r
98         TCNT1=0;\r
99         while(TCNT1==0);\r
100         if (_signal)\r
101         while((SENSOR_is_hi)&&(TCNT1<_time)) {}\r
102         else\r
103         while((SENSOR_is_low)&&(TCNT1<_time)) {}\r
104         \r
105         if (TCNT1>=_time) {return 1;}\r
106         return 0;\r
107 }\r
108 \r
109 volatile uint8_t am2302_mode=0;\r
110 volatile uint8_t timeout=0;\r
111 \r
112 \r
113 \r
114 \r
115 \r
116 \r
117 uint8_t userRegister[1];\r
118 int16_t sRH,sT;\r
119 volatile double temperatureC,humidityRH;\r
120 volatile double l;\r
121 \r
122 #if  defined(__AVR_ATtiny24__)||defined(__AVR_ATtiny44__)  || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny24A__)||defined(__AVR_ATtiny44A__)  || defined(__AVR_ATtiny84A__)\r
123 ISR(WATCHDOG_vect) {\r
124         #else\r
125 ISR(WDT_vect) {\r
126         #endif\r
127         wdcounter++;\r
128         if (reset_indicator==1) reset_indicator++;\r
129         else if (reset_indicator==2) mode=0;\r
130 }\r
131         \r
132 int testSW(void) {\r
133         uint8_t r;\r
134         DDRB&=~(1<<PORTB0);  //Eingang\r
135         __asm__ __volatile__ ("nop");\r
136         PORTB|=(1<<PORTB0); //Pullup\r
137         __asm__ __volatile__ ("nop");\r
138         __asm__ __volatile__ ("nop");\r
139         __asm__ __volatile__ ("nop");\r
140         __asm__ __volatile__ ("nop");\r
141         __asm__ __volatile__ ("nop");\r
142         r=PINB&(1<<PORTB0);\r
143         __asm__ __volatile__ ("nop");\r
144         PORTB&=~(1<<PORTB0);\r
145         __asm__ __volatile__ ("nop");\r
146         DDRB|=(1<<PORTB0);  //Eingang\r
147         return (r==0);\r
148 }\r
149 \r
150 uint8_t am2302() {\r
151         int16_t lam2302_temp;\r
152         uint16_t lam2302_hum;\r
153         uint8_t rSREG;\r
154         uint8_t sensor_data[5];\r
155 \r
156         TCCR1B=(1<<CS11); //Clock/8 1µs\r
157 \r
158         SENSOR_sda_out;\r
159         SENSOR_sda_low; // MCU start signal\r
160         TCNT1=0;while(TCNT1==0);while(TCNT1<250) {}// start signal (pull sda down for min 0.8ms and maximum 20ms)\r
161         TCNT1=0;while(TCNT1==0);while(TCNT1<250) {}// start signal (pull sda down for min 0.8ms and maximum 20ms)\r
162         SENSOR_sda_in;\r
163         if (am_wait(200,1)) return 2;\r
164 \r
165         // AM2302 response signal min: 75us typ:80us max:85us or 500us different types\r
166         if (am_wait(100,0)) return 3;\r
167         if (am_wait(100,1)) return 4;\r
168         \r
169         for(uint8_t i = 0; i < 5; i++)  {\r
170                 uint8_t sensor_byte = 0;\r
171                 for(uint8_t j = 1; j <= 8; j++) {// get 8 bits from sensor\r
172                         if (am_wait(88,0)) return 5;\r
173                         \r
174                         TCNT1=0;while(TCNT1==0);;while(TCNT1<35)                ;\r
175                         sensor_byte <<= 1; // add new lower byte\r
176                         if (SENSOR_is_hi) {// if sda high after 30us => bit=1 else bit=0\r
177                                 sensor_byte |= 1;\r
178                                 if (am_wait(45,1)) return 6;// 30us - 75us = 45us\r
179                         }\r
180                 }\r
181                 sensor_data[i] = sensor_byte;\r
182         }\r
183 \r
184         // checksum\r
185         if ( ((sensor_data[0]+sensor_data[1]+sensor_data[2]+sensor_data[3]) & 0xff ) != sensor_data[4])\r
186         {\r
187                 PORTB&=~(1<<PINB0);\r
188                 return 7;\r
189         }\r
190         if (sensor_data[2]&0x80) { //minus\r
191                 sensor_data[2]&=~(0x80);\r
192                 lam2302_temp=-((sensor_data[2]<<8) + sensor_data[3]);\r
193         } else\r
194                 lam2302_temp=((sensor_data[2]<<8) + sensor_data[3]);\r
195         if (!testSW()) {\r
196                 double htemp=lam2302_temp;\r
197         double hhum=(1.0546-0.000216*htemp)*((sensor_data[0]<<8) + sensor_data[1]);\r
198                 //htemp=Temperauter * 10 \r
199                 //lam2302_hum=0.318*hhum +76;\r
200                 lam2302_hum=0.31*hhum +80; //hhum = Hum*10 -> 5V also all *5\r
201                 config_info[5]=7;\r
202         }\r
203         else {\r
204                 \r
205                 lam2302_hum=((sensor_data[0]<<8) + sensor_data[1]);\r
206                 config_info[5]=12;\r
207         }\r
208         lam2302_temp=lam2302_temp*25.6;\r
209         rSREG=SREG;\r
210         cli();\r
211         am2302_hum=lam2302_hum;\r
212         am2302_temp=lam2302_temp;\r
213         SREG=rSREG;\r
214         return 0;\r
215 }\r
216 \r
217 \r
218 \r
219 \r
220 \r
221 \r
222 \r
223 \r
224         int main(void){\r
225                 PRR|=(1<<PRUSI)|(1<<PRADC);   // adc and usi for save Power\r
226                 PORTA=0xFF;\r
227                 PORTB=0xFF-(1<<PORTB0); //Schalter kann gegen Masse sein und zieht dann immer Strom\r
228                 DDRB|=(1<<PORTB0); //Als Ausgang und 0\r
229                 \r
230                 \r
231                 OWINIT();\r
232 \r
233                 ACSR|=(1<<ACD);  //Disable Comparator\r
234                 ADCSRB|=(1<<ACME); //Disable Analog multiplexer\r
235                 MCUCR &=~(1<<PUD); //All Pins Pullup...\r
236                 MCUCR |=(1<<BODS);\r
237 \r
238                 \r
239                 DDRA|=(1<<PINA1); //stromversorgung\r
240 #define SENSON PORTA|=(1<<PINA1);\r
241 #define SENSOFF PORTA&=~(1<<PINA1);\r
242 \r
243                 // Set up Watch Dog Timer for Inactivity\r
244                 WDTCSR |= (1<<WDCE) ;   // Enable the WD Change Bit\r
245                 WDTCSR =   (1<<WDIE) |              // Enable WDT Interrupt\r
246                         (1<<WDP2) | (1<<WDP1);   // Set Timeout to ~2 seconds           \r
247                 \r
248                 if (testSW()) {\r
249                         config_info[5]=12;  //hum *10\r
250                         }else{\r
251                         config_info[5]=7; //HIH4031\r
252                 }\r
253                 \r
254                 uint8_t i;\r
255                 for(i=0;i<64;i++) pack.bytes[i]=0;\r
256                 MCUSR=0;\r
257                 \r
258                 uint8_t err;\r
259                 uint8_t pn=1;\r
260                 SENSON\r
261                 _delay_ms(4000);\r
262                 err =am2302();\r
263                 \r
264                 sei();\r
265                 \r
266                 while(1)   {\r
267                         if (gcontrol) {\r
268                                 if (wdcounter>2) {\r
269                                         wdcounter=0;\r
270                                         SENSON\r
271                                 }\r
272                                 gcontrol=0;\r
273                         }\r
274                         if (wdcounter==2) {\r
275                                 err=am2302();\r
276                                 if (err!=0) {\r
277                                         pack.page3[pn]=err;\r
278                                         pn=pn+1;if (pn>31) pn=1;\r
279                                 }\r
280                                 SENSOFF\r
281                                 wdcounter=3;\r
282                         }\r
283                         if (wdcounter>=16) {\r
284                                 wdcounter=0;\r
285                                 SENSON\r
286                         }\r
287                         \r
288                         \r
289 \r
290                         if (((TIMSK0 & (1<<TOIE0))==0)&& (mode==0))       {\r
291                                 MCUCR|=(1<<SE)|(1<<SM1);\r
292                                 MCUCR&=~(1<<ISC01);\r
293                                 } else {\r
294                                 MCUCR|=(1<<SE);\r
295                                 MCUCR&=~(1<<SM1);\r
296                         }\r
297                         asm("SLEEP");\r
298                 }\r
299 \r
300 \r
301         }