Many changes from 2018
[owSlave2.git] / DS2438_DHT11 / DS2438_DHT22.c
1 // Copyright (c) 2017, 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[26]={0x01,0x06, 0x05,0x08, 0x04,0x07, 0x00,0x00, 0x02,0x09,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,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_sda_hi    PORT_SENSOR |= (1 << SENSOR)\r
91 #define SENSOR_is_hi                    PIN_SENSOR & (1 << SENSOR)\r
92 #define SENSOR_is_low           !(PIN_SENSOR & (1 << SENSOR))\r
93 \r
94 volatile int16_t am2302_temp;\r
95 volatile uint16_t am2302_hum;\r
96 \r
97 \r
98 uint8_t am_wait(uint8_t _time,uint8_t _signal){\r
99         TCNT1=0;\r
100         while(TCNT1==0);\r
101         if (_signal)\r
102         while((SENSOR_is_hi)&&(TCNT1<_time)) {}\r
103         else\r
104         while((SENSOR_is_low)&&(TCNT1<_time)) {}\r
105         \r
106         if (TCNT1>=_time) {return 1;}\r
107         return 0;\r
108 }\r
109 \r
110 volatile uint8_t am2302_mode=0;\r
111 volatile uint8_t timeout=0;\r
112 \r
113 \r
114 \r
115 \r
116 \r
117 \r
118 uint8_t userRegister[1];\r
119 int16_t sRH,sT;\r
120 volatile double temperatureC,humidityRH;\r
121 volatile double l;\r
122 \r
123 #if  defined(__AVR_ATtiny24__)||defined(__AVR_ATtiny44__)  || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny24A__)||defined(__AVR_ATtiny44A__)  || defined(__AVR_ATtiny84A__)\r
124 ISR(WATCHDOG_vect) {\r
125         #else\r
126 ISR(WDT_vect) {\r
127         #endif\r
128         wdcounter++;\r
129         if (reset_indicator==1) reset_indicator++;\r
130         else if (reset_indicator==2) mode=0;\r
131 }\r
132         \r
133 int testSW(void) {\r
134         uint8_t r;\r
135         DDRB&=~(1<<PORTB0);  //Eingang\r
136         __asm__ __volatile__ ("nop");\r
137         PORTB|=(1<<PORTB0); //Pullup\r
138         __asm__ __volatile__ ("nop");\r
139         __asm__ __volatile__ ("nop");\r
140         __asm__ __volatile__ ("nop");\r
141         __asm__ __volatile__ ("nop");\r
142         __asm__ __volatile__ ("nop");\r
143         r=PINB&(1<<PORTB0);\r
144         __asm__ __volatile__ ("nop");\r
145         PORTB&=~(1<<PORTB0);\r
146         __asm__ __volatile__ ("nop");\r
147         DDRB|=(1<<PORTB0);  //Eingang\r
148         return (r==0);\r
149 }\r
150 \r
151 uint8_t am2302() {\r
152         int16_t lam2302_temp;\r
153         uint16_t lam2302_hum;\r
154         uint8_t rSREG;\r
155         uint8_t sensor_data[5];\r
156 \r
157         TCCR1B=(1<<CS11); //Clock/8 1µs\r
158 \r
159         \r
160         SENSOR_sda_out;\r
161         SENSOR_sda_low; \r
162         _delay_ms(20);\r
163         SENSOR_sda_hi;  \r
164         SENSOR_sda_in;\r
165 //      _delay_ms(40);\r
166         //SENSOR_sda_low;\r
167         //_delay_us(40);\r
168 \r
169         //SENSOR_sda_in;\r
170         /*uint16_t loopCnt;\r
171         loopCnt=10000;\r
172         while((SENSOR_is_low)) {\r
173                 if (loopCnt-- == 0) return  11;\r
174         }\r
175         loopCnt=10000;\r
176         while((SENSOR_is_hi)) {\r
177                 if (loopCnt-- == 0) return  12;\r
178         }*/\r
179         if (am_wait(200,1)) return 2;\r
180         if (am_wait(100,0)) return 3;\r
181         if (am_wait(100,1)) return 4;\r
182         \r
183         for(uint8_t i = 0; i < 5; i++)  {\r
184                 uint8_t sensor_byte = 0;\r
185                 for(uint8_t j = 1; j <= 8; j++) {// get 8 bits from sensor\r
186                         if (am_wait(88,0)) return 5;\r
187                         \r
188                         TCNT1=0;while(TCNT1==0);;while(TCNT1<35)                ;\r
189                         sensor_byte <<= 1; // add new lower byte\r
190                         if (SENSOR_is_hi) {// if sda high after 30us => bit=1 else bit=0\r
191                                 sensor_byte |= 1;\r
192                                 if (am_wait(45,1)) return 6;// 30us - 75us = 45us\r
193                         }\r
194                 }\r
195                 sensor_data[i] = sensor_byte;\r
196         }\r
197 \r
198         // checksum\r
199         if ( ((sensor_data[0]+sensor_data[1]+sensor_data[2]+sensor_data[3]) & 0xff ) != sensor_data[4])\r
200         {\r
201                 PORTB&=~(1<<PINB0);\r
202                 return 7;\r
203         }\r
204         if (sensor_data[2]&0x80) { //minus\r
205                 sensor_data[2]&=~(0x80);\r
206                 lam2302_temp=-( sensor_data[2]*10);\r
207         } else\r
208                 lam2302_temp=(sensor_data[2]*10);\r
209         if (!testSW()) {\r
210                 double htemp=lam2302_temp;\r
211         double hhum=(1.0546-0.000216*htemp)*(sensor_data[0]*10);\r
212                 //htemp=Temperauter * 10 \r
213                 //lam2302_hum=0.318*hhum +76;\r
214                 lam2302_hum=0.31*hhum +80; //hhum = Hum*10 -> 5V also all *5\r
215                 config_info[5]=7;\r
216         }\r
217         else {\r
218                 \r
219                 lam2302_hum=(sensor_data[0]*10);\r
220                 config_info[5]=12;\r
221         }\r
222         lam2302_temp=lam2302_temp*25.6;\r
223         rSREG=SREG;\r
224         cli();\r
225         am2302_hum=lam2302_hum;\r
226         am2302_temp=lam2302_temp;\r
227         SREG=rSREG;\r
228         return 0;\r
229 }\r
230 \r
231 \r
232 \r
233 \r
234 \r
235 \r
236 \r
237 \r
238         int main(void){\r
239                 PRR|=(1<<PRUSI)|(1<<PRADC);   // adc and usi for save Power\r
240                 PORTA=0xFF;\r
241                 PORTB=0xFF-(1<<PORTB0); //Schalter kann gegen Masse sein und zieht dann immer Strom\r
242                 DDRB|=(1<<PORTB0); //Als Ausgang und 0\r
243                 \r
244                 \r
245                 OWINIT();\r
246 \r
247                 ACSR|=(1<<ACD);  //Disable Comparator\r
248                 ADCSRB|=(1<<ACME); //Disable Analog multiplexer\r
249                 MCUCR &=~(1<<PUD); //All Pins Pullup...\r
250                 MCUCR |=(1<<BODS);\r
251 \r
252                 \r
253                 DDRA|=(1<<PINA1); //stromversorgung\r
254 #define SENSON PORTA|=(1<<PINA1);\r
255 #define SENSOFF PORTA&=~(1<<PINA1);\r
256 \r
257                 // Set up Watch Dog Timer for Inactivity\r
258                 WDTCSR |= (1<<WDCE) ;   // Enable the WD Change Bit\r
259                 WDTCSR =   (1<<WDIE) |              // Enable WDT Interrupt\r
260                         (1<<WDP2) | (1<<WDP1);   // Set Timeout to ~2 seconds           \r
261                 \r
262                 if (testSW()) {\r
263                         config_info[5]=12;  //hum *10\r
264                         }else{\r
265                         config_info[5]=7; //HIH4031\r
266                 }\r
267                 \r
268                 uint8_t i;\r
269                 for(i=0;i<64;i++) pack.bytes[i]=0;\r
270                 pack.page3[0]=0xF1; //Wiregate Code\r
271                 MCUSR=0;\r
272                 \r
273                 uint8_t err;\r
274                 uint8_t pn=1;\r
275                 SENSON\r
276                 _delay_ms(4000);\r
277                 err =am2302();\r
278                 am2302_temp=err*256;\r
279                 sei();\r
280                 \r
281                 while(1)   {\r
282                         if (gcontrol) {\r
283                                 if (wdcounter>2) {\r
284                                         wdcounter=0;\r
285                                         SENSON\r
286                                 }\r
287                                 gcontrol=0;\r
288                         }\r
289                         if (wdcounter==2) {\r
290                                 err=am2302();\r
291                                 if (err!=0) {\r
292                                         pack.page3[pn]=err;\r
293                                         pn=pn+1;if (pn>31) pn=1;\r
294                                 }\r
295                                 //SENSOFF\r
296                                 wdcounter=3;\r
297                         }\r
298                         if (wdcounter>=16) {\r
299                                 wdcounter=0;\r
300                                 SENSON\r
301                         }\r
302                         \r
303                         \r
304 \r
305                         if (((TIMSK0 & (1<<TOIE0))==0)&& (mode==0))       {\r
306                                 MCUCR|=(1<<SE)|(1<<SM1);\r
307                                 MCUCR&=~(1<<ISC01);\r
308                                 } else {\r
309                                 MCUCR|=(1<<SE);\r
310                                 MCUCR&=~(1<<SM1);\r
311                         }\r
312                         asm("SLEEP");\r
313                 }\r
314 \r
315 \r
316         }