1 | //Steuerung mit Encode, Impuls, Eingabe (ein Motor) v1.doc
|
2 |
|
3 | // TIMER0 ENCODER 8 BIT, 1ms TOV, Bremsrampe für Motoren,
|
4 | // OCR1A wird per countup und countdown in switch geladen
|
5 | // TIMER1 PWM 10 Bit, WARTESCHLEIFE 16 BIT, kein Teiler, 8,8ms TOV
|
6 | // TIMER2 PWM 8 BIT ENTPRELLEN, 8,8 ms TOV
|
7 |
|
8 | // März 2009 o.k.
|
9 |
|
10 | // Der Motor läuft langsam bis Maximum, danach bremst er mit derselben Bremstabelle wieder auf Minimum (Fast PWM)
|
11 |
|
12 | #include <avr/io.h>
|
13 | #include <avr/interrupt.h>
|
14 | #include <inttypes.h>
|
15 |
|
16 | #define F_CPU 7372800
|
17 | #include <util/delay.h>
|
18 | #include <avr/pgmspace.h>
|
19 |
|
20 | uint16_t pwmtable[25] PROGMEM = { 80,80,85,90,90,100,115,190, 295, 385, 425, 465,4 85, 495, 505,535, 585,685, 785, 815, 865, 895, 950, 1000,1023 };
|
21 |
|
22 | //############################## Globale Variablen ###############################
|
23 |
|
24 | volatile uint8_t up1=2, countTimer1 =240; // ISR TIMER1
|
25 | volatile uint8_t c; // INTERRUPT 0 und INTERRUPT 1
|
26 | volatile char countbrems0, tmp=0, brems0, a=0; // für Warteschleifen der Motoren und switch pwm in ISR TIMER0-COMP
|
27 |
|
28 | int32_t val = 0; // Encoder
|
29 | volatile int8_t enc_delta; // Encoder
|
30 | static int8_t last; // Encoder
|
31 |
|
32 | #define waitpind PIND
|
33 | #define waitportbit2 PD2 // INT0
|
34 | #define waitportbit3 PD3 // INT1
|
35 |
|
36 | #define PHASE_A (PIND & 1<<PD0)
|
37 | #define PHASE_B (PIND & 1<<PD1)
|
38 |
|
39 | //############################## DEFINE PWM ###################################
|
40 |
|
41 | #define OC1A_PIN PD5 // OC1A pin
|
42 | #define OC1A_DDR DDRD // OC1A DDR
|
43 |
|
44 | #define IN1A PA0
|
45 | #define IN1B PA1
|
46 |
|
47 | // ####################### DEFINE Tastatur-Entprellen ########################################
|
48 |
|
49 | // 2 Tasten ----- PD6, PD7 kurz / lang gedrückt LED an PORTCx wird ein- und ausgeschaltet
|
50 |
|
51 | #define KEY_PIN PIND
|
52 | #define KEY7 7
|
53 | #define KEY6 6
|
54 |
|
55 | #define LED7 7
|
56 | #define LED6 6
|
57 | #define LED5 5
|
58 | #define LED4 4
|
59 | #define LED3 3
|
60 | #define LED2 2
|
61 | #define LED1 1
|
62 | #define LED0 0
|
63 |
|
64 |
|
65 | typedef unsigned char u8;
|
66 | typedef signed short s16;
|
67 |
|
68 | volatile u8 key_state;
|
69 | volatile u8 key_press;
|
70 |
|
71 | //############################# EXTERNER INT0 #######################################
|
72 | ISR(INT0_vect)
|
73 | {
|
74 | PORTC=~c;
|
75 | if(waitpind & (1<<waitportbit2));
|
76 |
|
77 | c++;
|
78 | }
|
79 | //############################# EXTERNER INT1 #######################################
|
80 |
|
81 | ISR(INT1_vect)
|
82 | {
|
83 | PORTC=~c;
|
84 | if(waitpind & (1<<waitportbit3));
|
85 |
|
86 | c--;
|
87 | }
|
88 |
|
89 | //###################### TIMER0_OVF ENCODER #####################################
|
90 |
|
91 | ISR(TIMER0_OVF_vect) // 350us, da Timer0 bei Match auf Null gesetzt wird
|
92 | // OCR0 hat den Ladewert 40,
|
93 | //somit wird nach 8,6us x 40 Takten ca. 350us MATCH ausgelöst gesetzt
|
94 |
|
95 | {
|
96 | PORTA ^= (1<<PA7); // gemessen nix, da er durch Match von OCR0 kein TOP erreicht
|
97 | }
|
98 |
|
99 | //###################### TIMER 1 PWM 16 Bit Timer #######################################
|
100 |
|
101 | ISR(TIMER1_OVF_vect) // kein Teiler, alle 8,8ms TOV
|
102 |
|
103 | {
|
104 | PORTA ^= (1<<PA6); // gemessen 8,5ms
|
105 |
|
106 | countTimer1++;
|
107 |
|
108 | if(countTimer1==200)
|
109 | {
|
110 | up1++;
|
111 | }
|
112 | }
|
113 |
|
114 | //###################### TIMER2 ENTPRELLEN, WARTEN #####################################
|
115 |
|
116 | ISR(TIMER2_OVF_vect)
|
117 |
|
118 | {
|
119 | PORTA ^= (1<<PA5); // gemessen 2,2ms
|
120 |
|
121 | static u8 ct0, ct1;
|
122 | u8 i;
|
123 | i = key_state ^ ~KEY_PIN;
|
124 | ct0 = ~( ct0 & i );
|
125 | ct1 = ct0 ^ (ct1 & i);
|
126 | i &= ct0 & ct1;
|
127 | key_state ^= i;
|
128 | key_press |= key_state & i;
|
129 | }
|
130 | //###################### TIMER0 COMPARE Interrupt ENCODER #######################################
|
131 |
|
132 | ISR( TIMER0_COMP_vect )
|
133 | {
|
134 | PORTA ^= (1<<PA4); // gemessen 350us
|
135 |
|
136 | switch(a)
|
137 | {
|
138 | case 0:
|
139 | PORTB=0xff;
|
140 | {
|
141 | countbrems0++; //a=0
|
142 |
|
143 | if(countbrems0==255)
|
144 | {
|
145 | {
|
146 | brems0++; // 2,2ms x 255 = 561 ms ,countbrems0=155
|
147 | }
|
148 |
|
149 | if(brems0==15)
|
150 | {
|
151 | countbrems0=0; // 561ms x 10= 5,61 Sekunden,brems0=2
|
152 | brems0=0;
|
153 | tmp++;
|
154 | PORTC=~tmp;
|
155 | if(tmp==24)
|
156 | {
|
157 | a=1;
|
158 | }
|
159 | } // Ende if innen
|
160 | } //Ende if außen
|
161 | } break; // Ende case 0
|
162 |
|
163 | case 1:
|
164 |
|
165 | PORTB=0xff;
|
166 | { //a=1
|
167 | countbrems0++;
|
168 |
|
169 | if(countbrems0==255)
|
170 | {
|
171 | { // 2,2ms x 255 = 561 ms ,countbrems0=155
|
172 | brems0++;
|
173 | }
|
174 |
|
175 | if(brems0==15)
|
176 | {
|
177 | countbrems0=0; // 561ms x 10= 5,61 Sekunden,brems0=2
|
178 | brems0=0;
|
179 | tmp--;
|
180 | PORTC=~tmp;
|
181 | if(tmp==0)
|
182 | {
|
183 | a=0;
|
184 | }
|
185 | } // Ende if innen
|
186 | } //Ende if außen
|
187 | }break; // Ende case 1
|
188 | } // Ende switch
|
189 |
|
190 |
|
191 | OCR0 = 40;
|
192 |
|
193 | int8_t new, diff;
|
194 | new = 0;
|
195 |
|
196 | if( PHASE_A )
|
197 | new = 3;
|
198 | if( PHASE_B )
|
199 | new ^= 1;
|
200 | diff = last - new;
|
201 | if( diff & 1 )
|
202 | {
|
203 | last = new;
|
204 | enc_delta += (diff & 2) - 1; // bit 1 = direction (+/-)
|
205 | }
|
206 | }
|
207 |
|
208 | // ############################## TASTEN ENTPRELLEN ####################################
|
209 |
|
210 | u8 get_key_press( u8 key_mask )
|
211 | {
|
212 | cli();
|
213 | key_mask &= key_press;
|
214 | key_press ^= key_mask;
|
215 | sei();
|
216 | return key_mask;
|
217 | }
|
218 |
|
219 | u8 get_key_short( u8 key_mask )
|
220 | {
|
221 | cli();
|
222 | return get_key_press( ~key_state & key_mask );
|
223 | }
|
224 |
|
225 | //###################### ENCODER Übergabe Zustand der Bits #######################################
|
226 |
|
227 | int8_t encode_read1( void ) // read single step encoders
|
228 | {
|
229 | int8_t val;
|
230 |
|
231 | cli();
|
232 | val = enc_delta;
|
233 | enc_delta = 0;
|
234 | sei();
|
235 | return val; // counts since last call
|
236 | }
|
237 |
|
238 |
|
239 | // ############################ TIMER initialisieren ##########################################
|
240 |
|
241 | //------------------------------------- TIMER0 ---------------------------------------------------
|
242 |
|
243 | void init(void)
|
244 | {
|
245 | TIMSK = (1<<TOIE0)|(1<<TOIE1) |(1<<TOIE2) | 1<<OCIE0 ;
|
246 | // TIMER0(ENCODER),TIMER1(WARTEN),
|
247 | // TIMER2(ENTPRELLEN)
|
248 | // und OCR0-Register für ENCODER Interrupt
|
249 |
|
250 | TCCR0 = (1<<WGM01)| (1<<CS01)|(1<<CS00);
|
251 | // 1/64 Prescale Encoder
|
252 | // 1ms TOV, da T/64 2,2 ms pro TOV und 8,6us pro Takt
|
253 | // 8,6us x 116 = 1ms
|
254 | //---------------------------------------------------- TIMER1 PWM ------------------------------------------------------------------------
|
255 |
|
256 | TCCR1A = _BV(COM1A1) | _BV(WGM11) | _BV(WGM10); // non-inverted PWM on OC1A, 10 Bit Fast PWM
|
257 |
|
258 | TCCR1B = _BV(CS10) | _BV(CS11) | _BV(WGM12); // precaler 64 -> ~122 Hz PWM frequency
|
259 |
|
260 | //------------------------------------------- TIMER2 ENTPRELLEN ------------------------------------------
|
261 |
|
262 |
|
263 | TCCR2 = 1<<CS22; // CTC, Takt / 64, ENTPRELLEN
|
264 |
|
265 | //---------------------------------------- EXTERNER INTERUPT INITIALISIERUNG -----------------------------------------------------
|
266 |
|
267 | GICR = (1<<INT0) | (1<<INT1);
|
268 | MCUCR =(1<<ISC01) | (1<<ISC11);
|
269 |
|
270 | sei();
|
271 |
|
272 | DDRD &=~((1<<PD7) | (1<<PD6) | (1<<PD4) | (1<<PD3) | (1<<PD2) | (1<<PD1) ); // Eingänge, ausser PD5 OC1A PWM
|
273 |
|
274 | DDRD |= (1<<PD5); //LED uses OC1A
|
275 | PORTD = 0xff; // PORTD ist Eingang,ausser PD5
|
276 | }
|
277 | //################### Encoder initialisieren und Timer 0 und Timer 2 starten ####################
|
278 |
|
279 | void encode_init( void )
|
280 | {
|
281 | int8_t new;
|
282 | new = 0;
|
283 | if( PHASE_A )
|
284 | new = 3;
|
285 | if( PHASE_B )
|
286 | new ^= 1;
|
287 | last = new;
|
288 | enc_delta = 0;
|
289 | }
|
290 |
|
291 | int main(void)
|
292 | {
|
293 |
|
294 | init();
|
295 |
|
296 | DDRA=0xff;
|
297 | PORTA = 0xfe;
|
298 |
|
299 | DDRB=0xff;
|
300 | PORTB = 0xff;
|
301 |
|
302 | DDRC=0xff;
|
303 | PORTC = 0xff;
|
304 |
|
305 |
|
306 |
|
307 | while(1)
|
308 | {
|
309 | OCR1A = pgm_read_word(pwmtable+tmp);
|
310 |
|
311 | if( get_key_press( 1<<KEY7 ))
|
312 | PORTC ^= (1<<LED7);
|
313 |
|
314 | if( get_key_press( 1<<KEY6 ))
|
315 | PORTC ^= (1<<LED6);
|
316 |
|
317 | val += encode_read1();
|
318 |
|
319 | PORTB = ~val;
|
320 |
|
321 | } // Ende while
|
322 | return 0;
|
323 | } // Ende main
|