SauHandyWD2.c


1
/*
2
 * Sauhandy.c
3
 *
4
 * Created: 22.08.2013 20:02:46
5
 *  Author: Gerald
6
 */ 
7
#include <avr/io.h>
8
#define F_CPU 128000UL //CKSEL Fuses to “0100” --> slow ISP down
9
10
#include <util/delay.h>
11
#include <avr/sleep.h>
12
#include <avr/interrupt.h>
13
 #include <avr/wdt.h>
14
15
#define ADCPort PB5          //                    _____________ 
16
#define ADCReg DDB5          //      (PCINT5/RESET/ADC0/dW) PB5  -      - VCC  
17
#define Bleeder PB3          //                    |      |  
18
#define BleederReg DDB3        //  (PCINT3/XTAL1/CLKI/OC1B/ADC3) PB3  -      - PB2 (SCK/USCK/SCL/ADC1/T0/INT0/PCINT2)
19
#define PowerSwitch PB0        //                    |      |
20
#define PowerSwitchReg DDB0      //  (PCINT4/XTAL2/CLKO/OC1B/ADC2) PB4  -      - PB1 (MISO/DO/AIN1/OC0B/OC1A/PCINT1)
21
#define CallSwitch PB1        //                    |      |
22
#define CallSwitchReg DDB1      //                  GND  -      - PB0 (MOSI/DI/SDA/AIN0/OC0A/OC1A/AREF/PCINT0)
23
#define HangupSwitch PB2      //                    _____________
24
#define HangupSwitchReg DDB2
25
#define Sensor PB4
26
#define SensorReg DDB4
27
#define SensorPin PINB4
28
#define Port PORTB
29
#define PortReg DDRB
30
#define PIN PINB
31
32
33
34
35
36
37
38
void initADC(void){
39
  uint16_t erase;
40
  ADMUX = (1<<REFS1) ; //interne 1,1Volt
41
  //ADCSRA = //(1<<ADPS1) | (1<<ADPS2);//prescaler zw. 50 und 200 kHz, hier also 2
42
  ADCSRA |= (1<<ADEN); //ADC ENable  
43
  ADCSRA |= (1<<ADSC); //ADc Single Conversion
44
  while (ADCSRA & (1<<ADSC) ) //warte bis fertig
45
  {
46
  }
47
  erase = ADCW; //auslesen (löscht auch)
48
}
49
50
void enablewatchdog(void){
51
  MCUSR = 0x00; // clear watchdog
52
  WDTCR |= (1<<WDCE) | (1<<WDE)  ;   // Enable watchdog
53
  WDTCR |= (1<<WDIE) | (1<<WDP1);    // Watchdog interrupt instead of reset with 60ms timeout;
54
  WDTCR &= ~(1<<WDE);          // halte WDIE geespeichert
55
  
56
}
57
58
void disablewatchdog(void){
59
  MCUSR = 0x00; // clear watchdog
60
  WDTCR |= (1<<WDCE) | (1<<WDE); // bereitmachen zum löschen
61
  WDTCR = 0x00;    //löschen
62
}
63
64
void watchdogreset(void){
65
  MCUSR = 0x00; // clear watchdog
66
}
67
68
69
void wait(uint16_t timein60ms){ //in 60ms schritten
70
  for (uint16_t i = 0; i<timein60ms; i++ ){
71
    disablewatchdog();
72
    watchdogreset();
73
    enablewatchdog();
74
    sei();
75
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
76
    sleep_mode();
77
    cli();
78
    disablewatchdog();
79
  }
80
}  
81
82
void waitlong(uint16_t timein2s){ //in 2s schritten
83
  for (uint16_t i = 0; i<timein2s; i++ ){
84
    disablewatchdog();
85
    MCUSR = 0x00; // clear watchdog
86
    WDTCR = (1<<WDCE) | (1<<WDE)  ;   // Enable watchdog
87
    WDTCR |= (1<<WDIE) | (1<<WDP0) | (1<<WDP1) | (1<<WDP2);    // Watchdog interrupt instead of reset with 8s timeout;
88
    WDTCR &= ~(1<<WDE);          // halte WDIE geespeichert
89
    sei();
90
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
91
    sleep_mode();
92
    cli();
93
    disablewatchdog();
94
  }
95
}
96
97
void domagic(void){
98
  PortReg |= (PowerSwitchReg); //lege als Ausgang fest
99
  Port &= ~(1<<PowerSwitch); //Hold PowerSwitch for 2 Sec
100
  waitlong(1);
101
  PortReg &= ~(1<<PowerSwitchReg); //Als Eingang
102
  Port |= (1<<PowerSwitch); //Pullup
103
  waitlong(5); //let it boot
104
  Port |= (1<<CallSwitch);
105
  wait(1); //push Call Button for 60ms
106
  Port &= ~(1<<CallSwitch);
107
  
108
  wait(1);
109
  
110
  Port |= (1<<CallSwitch);
111
  wait(1); //push Call Button for 60ms
112
  Port &= ~(1<<CallSwitch);
113
  
114
  waitlong(3); //ring 6 seconds
115
  
116
  Port |= (1<<HangupSwitch);
117
  wait(1); //push Hangup Button for 60ms
118
  Port &= ~(1<<HangupSwitch);
119
  
120
  wait(20);
121
  PortReg |= (PowerSwitchReg); //lege als Ausgang fest
122
  Port &= ~(1<<PowerSwitch); //Hold PowerSwitch for 2 Sec
123
  waitlong(1);
124
  PortReg &= ~(1<<PowerSwitchReg); //Als Eingang
125
  Port |= (1<<PowerSwitch); //Pullup
126
  
127
}
128
129
void lowbattery(void){
130
  PortReg |= (PowerSwitchReg); //lege als Ausgang fest
131
  Port &= ~(1<<PowerSwitch); //Hold PowerSwitch for 2 Sec
132
  waitlong(1);
133
  PortReg &= ~(1<<PowerSwitchReg); //Als Eingang
134
  Port |= (1<<PowerSwitch); //Pullup
135
  waitlong(2); //let it boot
136
  Port |= (1<<CallSwitch);
137
  wait(1); //push Call Button for 60ms
138
  Port &= ~(1<<CallSwitch);
139
  
140
  wait(5);
141
  
142
  Port |= (1<<CallSwitch);
143
  wait(1); //push Call Button for 60ms
144
  Port &= ~(1<<CallSwitch);
145
  
146
  waitlong(2); //ring 4 seconds
147
  
148
  Port |= (1<<HangupSwitch);
149
  wait(1); //push Hangup Button for 60ms
150
  Port &= ~(1<<HangupSwitch);
151
  
152
  waitlong(1); // kurze Pause zwischen Anrufen
153
  Port |= (1<<CallSwitch);
154
  wait(1); //push Call Button for 60ms
155
  Port &= ~(1<<CallSwitch);
156
  
157
  wait(5);
158
  Port |= (1<<CallSwitch);
159
  wait(1); //push Call Button for 50ms
160
  Port &= ~(1<<CallSwitch);
161
  
162
  waitlong(2); //ring 4 seconds
163
  
164
  Port |= (1<<HangupSwitch);
165
  wait(1); //push Hangup Button for 60ms
166
  Port &= ~(1<<HangupSwitch);
167
  
168
  wait(20);
169
  PortReg |= (PowerSwitchReg); //lege als Ausgang fest
170
  Port &= ~(1<<PowerSwitch); //Hold PowerSwitch for 2 Sec
171
  waitlong(1);
172
  PortReg &= ~(1<<PowerSwitchReg); //Als Eingang
173
  Port |= (1<<PowerSwitch); //Pullup
174
}
175
176
177
uint16_t ReadADC(void){
178
  initADC();
179
  //ADMUX |= (1<<MUX0) | (1<<MUX2); //Nehme PIN adc0
180
  ADCSRA |= (1<<ADSC); //ADc Single Conversion
181
  while (ADCSRA & (1<<ADSC) ) {
182
  }
183
  ADCSRA &= ~(1<<ADEN); //disable adc
184
  return ADCW;
185
}
186
187
188
189
int main(void)
190
{  
191
  PortReg |= (1<<CallSwitchReg) | (1<<HangupSwitchReg) | (1<<BleederReg) | (1<<ADCReg) | (1<<SensorReg) ; //output
192
  Port |= (1<<ADC) | (1<<Bleeder) | (1<<PowerSwitch); // auf High setzen
193
  uint16_t Spannungswert=1023*1.1*2.9/(13.3/3.3); //1024 bit * 1,1V Gap * 2.9V BatterieSpannung / Spannungsteiler
194
  uint32_t messungcounter=1;
195
  GIMSK = (1<<PCIE);    //Enable PCINT as InterruptReg
196
  PCMSK = (1<<PCINT0);  //Maske auf PCINT0
197
  sei();
198
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
199
  sleep_mode();      //erkenne handy einschalten
200
  cli();
201
  //Port |= (1<<HangupSwitch); for debugging
202
  PCMSK &= ~(1<<PCINT0);    //keine interrupts mehr
203
  waitlong(4);
204
  PCMSK = (1<<PCINT0);  //Maske auf PCINT0
205
  //Port &= ~(1<<HangupSwitch); for debugging
206
  sei();
207
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
208
  sleep_mode();      //erkenne handy ausschalten
209
  cli();
210
  //Port |= (1<<HangupSwitch); for debugging
211
  PCMSK &= ~(1<<PCINT0);    //keine interrupts mehr
212
  waitlong(4);
213
  //Port &= ~(1<<HangupSwitch); for debugging
214
  GIMSK &= ~(1<<PCIE);
215
  PCMSK &= ~(1<<PCINT0);    //keine interrupts mehr
216
  waitlong(8); //warte 16 Sekunden bis zur scharfschaltung
217
  watchdogreset();
218
  enablewatchdog();
219
  sei();
220
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
221
  sleep_mode();
222
  //uint8_t test =0; for debugging
223
  
224
  while(1){
225
    cli();
226
    disablewatchdog();
227
    /*test++;
228
    if (test==50){
229
      Port ^= (1<<CallSwitch);
230
      test=0;
231
    } // for debugging */
232
    
233
  
234
    PortReg &= ~(1<<SensorReg); //Eingang
235
    Port |= (1<<Sensor); // Pullup
236
    //Port ^= (1<<HangupSwitch); for debugging
237
    if (PINB & (1<<SensorPin)){
238
      Port &= ~(1<<Sensor);
239
      PortReg |= (1<<SensorReg); //Wieder als Ausgang
240
      domagic();
241
      watchdogreset();
242
      
243
      waitlong(450); //warte 15mins bis wieder scharf
244
      
245
      }
246
    Port &= ~(1<<Sensor);
247
    PortReg |= (1<<SensorReg); //Wieder als Ausgang (wenn nicht shcon passert)
248
      
249
      
250
    if (messungcounter==6000000){ // ca. alle 4 Tage messen
251
      watchdogreset();
252
      disablewatchdog();
253
      messungcounter=0;
254
      PortReg &= ~(1<<ADCReg); //Lege ADC als Eingang fest;
255
      Port &= ~(1<<Bleeder) ; // aktiviere Spanungsteiler
256
      Port &= ~(1<<ADC); //Pullup runter
257
      uint16_t ADCresult=ReadADC();
258
      PortReg |= (1<<ADCReg); //Lege ADC als Ausgang fest;
259
      Port |= (1<<ADC) | (1<<Bleeder) ; // auf High setzen
260
      if (ADCresult <= Spannungswert){
261
        lowbattery();
262
      }
263
    }
264
    messungcounter++;
265
    sei();
266
    enablewatchdog();
267
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
268
    sleep_mode();  
269
  
270
    }
271
}
272
273
ISR(PCINT0_vect){
274
}
275
276
ISR(WDT_vect){
277
  }