1 | //LED Treiber mit Attiny13; PWM Ausgang für LED Steuerung PB1; Akkuüberwachung über ADC PB2; Taster auf PB3
|
2 |
|
3 | //########################################################################################### MODE/PWM SETUP
|
4 |
|
5 | #define outpin 1 // PWM Ausgang PB1
|
6 | #define PWM OCR0B //PWM-value
|
7 |
|
8 | #define adcpin 2 //ADC PIN ! PB2
|
9 | #define adcchn 1 //ADC Kanal ! ADC1
|
10 |
|
11 | #define tasterpin 3 //PCINT3
|
12 |
|
13 | #define portinit() do{ DDRB=(1<<outpin); PORTB=0xff-(1<<outpin)-(1<<adcpin)-(1<<tasterpin); }while(0)//Port deklarieren
|
14 |
|
15 |
|
16 | #define F_CPU 4800000 //CPU: 4.8MHz PWM: 9.4kHz ####### use low fuse: 0x75 #######
|
17 | //#define BATTMON 125//enable battery monitoring with this threshold
|
18 |
|
19 |
|
20 | //###########################################################################################
|
21 |
|
22 | #include <avr/io.h>
|
23 | #include <util/delay.h>
|
24 | #include <avr/interrupt.h>
|
25 | #include <avr/sleep.h>
|
26 | #include <avr/eeprom.h>
|
27 | #include <avr/pgmspace.h>
|
28 | #include <avr/wdt.h>
|
29 |
|
30 | #define byte uint8_t
|
31 | #define word uint16_t
|
32 |
|
33 | #define WDTIME 0b01000011 //125ms
|
34 |
|
35 | #define sleepinit() do{ WDTCR=WDTIME; sei(); MCUCR=(MCUCR &~0b00111000)|0b00110000; }while(0) //WDT-int and Power Down-Sleep
|
36 |
|
37 | #define SLEEP asm volatile ("SLEEP")
|
38 |
|
39 | #define pwminit() do{ TCCR0A=0b00100001; TCCR0B=0b00000001; }while(0) //chan A, phasePWM, clk/1 ->2.35kHz@1.2MHz
|
40 |
|
41 | #define adcinit() do{ ADMUX =0b01100000|adcchn; ADCSRA=0b11000100; }while(0) //ref1.1V, left-adjust, ADC1/PB2; enable, start, clk/16
|
42 | #define adcread() do{ ADCSRA|=64; while (ADCSRA&64); }while(0)
|
43 | #define adcresult ADCH
|
44 |
|
45 |
|
46 | #define ADCoff ADCSRA&=~(1<<7) //ADC off (enable=0);
|
47 | #define ADCon ADCSRA|=(1<<7) //ADC on
|
48 | #define ACoff ACSR|=(1<<7) //AC off (disable=1)
|
49 | #define ACon ACSR&=~(1<<7) //AC on (disable=0)
|
50 |
|
51 |
|
52 | //______________________Taster entprellen_______________________________________________________________________________________________
|
53 | /************************************************************************/
|
54 | /* */
|
55 | /* Not so powerful Debouncing Example */
|
56 | /* No Interrupt needed */
|
57 | /* */
|
58 | /* Author: Peter Dannegger */
|
59 | /* */
|
60 | /************************************************************************/
|
61 | // Target: ATtiny13
|
62 | //http://www.mikrocontroller.net/attachment/highlight/67964
|
63 |
|
64 | #define debounce( port, pin ) \
|
65 | ({ \
|
66 | static uint8_t flag = 0; /* new variable on every macro usage */ \
|
67 | uint8_t i = 0; \
|
68 | \
|
69 | if( flag ){ /* check for key release: */ \
|
70 | for(;;){ /* loop ... */ \
|
71 | if( !(port & 1<<pin) ){ /* ... until key pressed or ... */ \
|
72 | i = 0; /* 0 = bounce */ \
|
73 | break; \
|
74 | } \
|
75 | _delay_us( 98 ); /* * 256 = 25ms */ \
|
76 | if( --i == 0 ){ /* ... until key >25ms released */ \
|
77 | flag = 0; /* clear press flag */ \
|
78 | i = 0; /* 0 = key release debounced */ \
|
79 | break; \
|
80 | } \
|
81 | } \
|
82 | }else{ /* else check for key press: */ \
|
83 | for(;;){ /* loop ... */ \
|
84 | if( (port & 1<<pin) ){ /* ... until key released or ... */ \
|
85 | i = 0; /* 0 = bounce */ \
|
86 | break; \
|
87 | } \
|
88 | _delay_us( 98 ); /* * 256 = 25ms */ \
|
89 | if( --i == 0 ){ /* ... until key >25ms pressed */ \
|
90 | flag = 1; /* set press flag */ \
|
91 | i = 1; /* 1 = key press debounced */ \
|
92 | break; \
|
93 | } \
|
94 | } \
|
95 | } \
|
96 | i; /* return value of Macro */ \
|
97 | })
|
98 |
|
99 |
|
100 | //_____________________________________________________________________________________________________________________
|
101 |
|
102 | byte mypwm=0;
|
103 | byte pmode=1; //Start Mode
|
104 | byte interrupt_flag=1;
|
105 |
|
106 | #ifdef BATTMON
|
107 | byte lowbattcounter=0;
|
108 | #endif
|
109 |
|
110 |
|
111 |
|
112 | ISR(WDT_vect) { //WatchDogTimer interrupt / Akkuüberwachung
|
113 |
|
114 | #ifdef BATTMON //code to check voltage and ramp down
|
115 | adcread();
|
116 | if (adcresult<BATTMON) { if (++lowbattcounter>8) {mypwm=(mypwm>>1)+3;lowbattcounter=0;} } //Halbiert PWM
|
117 | else lowbattcounter=0;
|
118 | #endif
|
119 | }
|
120 |
|
121 |
|
122 |
|
123 | ISR(PCINT0_vect) { //pin change interrupt
|
124 | //PWM=30; //test
|
125 |
|
126 | if( debounce( PINB, tasterpin )){ //Taster entprellt
|
127 | interrupt_flag=0; //aktuellen Modus verlassen
|
128 | pmode++; //nächster Modus
|
129 | }}
|
130 |
|
131 | int main(void) {
|
132 |
|
133 | portinit(); //Ports
|
134 | sleepinit(); //Sleep
|
135 | ACoff;
|
136 | #ifdef BATTMON
|
137 | adcinit();
|
138 | #else
|
139 | ADCoff;
|
140 | #endif
|
141 | pwminit(); //PWM
|
142 |
|
143 | PCMSK = (1 << tasterpin); // Externer Reset auf tasterpin definieren
|
144 | GIMSK = (1 << PCIE); // Pin Change Interrupt freigeben
|
145 |
|
146 |
|
147 | while(1){
|
148 | interrupt_flag=1; //Dauerschleife aktivieren
|
149 |
|
150 | switch(pmode){
|
151 |
|
152 | case 1: mypwm=255; while(interrupt_flag){PWM=mypwm;} break; //100%
|
153 |
|
154 | case 2: mypwm=120; while(interrupt_flag){PWM=mypwm;} break; //50%
|
155 |
|
156 |
|
157 | case 3: mypwm=0; //Ausgang auf 0%
|
158 | sleep_cpu(); //power down
|
159 |
|
160 |
|
161 | //--nach power down--
|
162 |
|
163 | pmode=1; //mit 1 Mode starten
|
164 | break;
|
165 |
|
166 |
|
167 |
|
168 | default: mypwm=5; while(interrupt_flag){PWM=mypwm;} pmode=1; break; //all other
|
169 |
|
170 | }//switch
|
171 |
|
172 | }
|
173 |
|
174 |
|
175 |
|
176 |
|
177 | return 0;
|
178 | }//main
|