1 | #define F_CPU 8000000UL // main clock
|
2 |
|
3 | #include <avr/io.h>
|
4 | #include <avr/interrupt.h>
|
5 | #include <avr/pgmspace.h>
|
6 | #include <util/delay.h>
|
7 | #include <avr/eeprom.h>
|
8 | #include <stdlib.h>
|
9 |
|
10 | #include <avr/wdt.h>
|
11 | #include <avr/sleep.h>
|
12 |
|
13 | #include "typedefinition.h"
|
14 |
|
15 |
|
16 | #define Taster PD2
|
17 | #define LS PD3
|
18 | #define LED_red PD6
|
19 | #define LED_green PD7
|
20 |
|
21 | // Motordrive defines
|
22 | #define IN1 PC5
|
23 | #define IN2 PC4
|
24 | #define EN PB1
|
25 | #define SENSE PC0
|
26 | #define ON (1)
|
27 | #define OFF (0)
|
28 | #define CW (0)
|
29 | #define CCW (1)
|
30 |
|
31 |
|
32 | const unsigned int TRESHOLD = 250;
|
33 | volatile unsigned int INT_TASTER = 0;
|
34 | const unsigned int DriveTime = 3950;
|
35 | volatile unsigned int aktDrivetime = 0;
|
36 | volatile unsigned int CALIB=1;
|
37 | volatile unsigned int FIRST=1;
|
38 | unsigned int moveTimeMotor=0;
|
39 | unsigned int moveTimeMotor2=0;
|
40 | volatile unsigned short Adc_value;
|
41 | volatile unsigned int timediff = 0;
|
42 | volatile unsigned int wert=0;
|
43 |
|
44 |
|
45 | u16 ReadChannel(u8 mux);
|
46 | void drive_Motor(u8 Dir, u8 Enable);
|
47 | inline static void motor_break(u8 Dir)
|
48 | {
|
49 | if(Dir==CCW){
|
50 | _delay_ms (65);
|
51 | drive_Motor(CCW,ON);
|
52 | _delay_ms (50);
|
53 | drive_Motor(CW,ON);
|
54 | _delay_ms (5);
|
55 | drive_Motor(CCW,OFF);
|
56 | }
|
57 | else
|
58 | {
|
59 | _delay_ms (65);
|
60 | drive_Motor(CW,ON);
|
61 | _delay_ms (50);
|
62 | drive_Motor(CCW,ON);
|
63 | _delay_ms (5);
|
64 | drive_Motor(CW,OFF);
|
65 | }
|
66 | };
|
67 |
|
68 | //*****************Routinen****************
|
69 | void ExtInt_init(void)
|
70 | {
|
71 |
|
72 | MCUCR |= (10<<ISC00)|(11<<ISC10); //Int1&2 genertates INt. at fall and rising edge
|
73 | // Taster is int 0___falling edge, Ls is int 1 rising edge
|
74 | //GICR |= (1<<INT0); // enable ext.Int 1&2 on PD2&3
|
75 |
|
76 | }
|
77 |
|
78 |
|
79 | //*********************util-routines********************++++++
|
80 |
|
81 | u16 ReadChannel(u8 mux)
|
82 | {
|
83 | u8 i;
|
84 | u16 result;
|
85 |
|
86 | ADMUX = mux; // Kanal waehlen
|
87 | ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
|
88 |
|
89 | ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
|
90 | // setzen auf 8 (1) und ADC aktivieren (1)
|
91 |
|
92 | /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
|
93 | also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
|
94 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
|
95 | while ( ADCSRA & (1<<ADSC) ) {
|
96 | ; // auf Abschluss der Konvertierung warten
|
97 | }
|
98 | result = ADCW; // ADCW muss einmal gelesen werden,
|
99 | // sonst wird Ergebnis der nächsten Wandlung
|
100 | // nicht übernommen.
|
101 |
|
102 | /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
|
103 | result = 0;
|
104 | for( i=0; i<4; i++ )
|
105 | {
|
106 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
|
107 | while ( ADCSRA & (1<<ADSC) ) {
|
108 | ; // auf Abschluss der Konvertierung warten
|
109 | }
|
110 | result += ADCW; // Wandlungsergebnisse aufaddieren
|
111 | }
|
112 | ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
|
113 |
|
114 | result /= 4; // Summe durch vier teilen = arithm. Mittelwert
|
115 |
|
116 | return result;
|
117 | }
|
118 | void drive_Motor(u8 Dir, u8 Enable){
|
119 |
|
120 | PORTC &=~((1<<IN1)|(1<<IN2)); // Fast motor stop
|
121 | PORTB &=~(1<<EN); // Stop Motor
|
122 | switch (Enable)
|
123 | {
|
124 | case ON:
|
125 |
|
126 | if(Dir){
|
127 |
|
128 | PORTC &=~(1<<IN1);
|
129 | PORTC |=(1<<IN2);
|
130 | //transmit_str_USART("jump1 \n ");
|
131 | //for(;;){;}
|
132 |
|
133 | }
|
134 | else{
|
135 | //transmit_str_USART("jump2 \n ");
|
136 | //for(;;){;}
|
137 | PORTC &=~(1<<IN2);
|
138 | PORTC |=(1<<IN1);
|
139 | }
|
140 | PORTB |=(1<<EN);
|
141 |
|
142 | break;
|
143 | case OFF: //transmit_str_USART("jump3 \n ");
|
144 | //for(;;){;}
|
145 | PORTC &=~((1<<IN1)|(1<<IN2));
|
146 | break;
|
147 | default:
|
148 | break;
|
149 | }
|
150 | //transmit_str_USART("jump4 \n ");
|
151 | // for(;;){;}
|
152 |
|
153 | }
|
154 |
|
155 |
|
156 |
|
157 | int main(void){
|
158 |
|
159 |
|
160 | /* set port direction's */
|
161 |
|
162 | DDRD = 0xF3; // PD2&3 are Inputs
|
163 | DDRC = 0xFF;
|
164 | DDRB |= (1<<EN);
|
165 | PORTB &=~(1<<EN);
|
166 | PORTC &=~((1<<IN1)|(1<<IN2));
|
167 | PORTD |= _BV(LED_red)|_BV(LED_green);
|
168 |
|
169 | /* init routinen*/
|
170 |
|
171 | ExtInt_init();
|
172 |
|
173 | sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed
|
174 |
|
175 |
|
176 | /**************** test if motor is in Reset positon**********/
|
177 |
|
178 | drive_Motor(CCW,ON);
|
179 | _delay_ms (500);
|
180 |
|
181 | while(1) // drive reverse till on reset position
|
182 | {
|
183 | Adc_value = ReadChannel(SENSE);
|
184 | _delay_ms (10);
|
185 | if(Adc_value>=TRESHOLD)
|
186 | {
|
187 | // overcurrent detect
|
188 | drive_Motor(CCW,OFF);
|
189 | goto rst_position;
|
190 | }
|
191 | }
|
192 | rst_position:
|
193 | GIFR |= (1<<INT0);
|
194 | GICR |= (1<<INT0); // enable Taster
|
195 |
|
196 |
|
197 |
|
198 |
|
199 | while(1)
|
200 | {
|
201 | timediff=DriveTime-aktDrivetime;
|
202 | if(INT_TASTER&&CALIB) // calibrierung durch tasterdruck
|
203 | {
|
204 |
|
205 | GIFR |= (1<<INT0);
|
206 | GICR |= (1<<INT0); // enable Taster
|
207 | INT_TASTER=0;
|
208 | _delay_ms (100);
|
209 | drive_Motor(CW,ON); // starte motor
|
210 | while(!INT_TASTER)
|
211 | {
|
212 | _delay_ms (10);
|
213 | moveTimeMotor++;
|
214 | }
|
215 | drive_Motor(CCW,OFF);
|
216 | _delay_ms (100);
|
217 |
|
218 | GIFR |= (1<<INT0);
|
219 | GICR |= (1<<INT0);
|
220 | INT_TASTER=0;
|
221 | while(1){
|
222 | if(INT_TASTER==1)
|
223 | break;
|
224 | _delay_ms (1);
|
225 | }; // warte auf neuen tastendruck
|
226 |
|
227 | GIFR |= (1<<INT0);
|
228 | GICR |= (1<<INT0);
|
229 | INT_TASTER=0;
|
230 | drive_Motor(CW,ON); // starte motor
|
231 | while(!INT_TASTER)
|
232 | {
|
233 | _delay_ms (10);
|
234 | moveTimeMotor2++;
|
235 | }
|
236 | wert=(unsigned int)moveTimeMotor2*0.25;
|
237 | drive_Motor(CCW,OFF);
|
238 | //motor_break(CW);
|
239 | // remove to Reset Position
|
240 | _delay_ms (200);
|
241 | PORTD &= ~(LED_green);
|
242 | drive_Motor(CCW,ON);
|
243 | _delay_ms (500);
|
244 |
|
245 | while(1) // drive reverse till on reset position
|
246 | {
|
247 | Adc_value = ReadChannel(SENSE);
|
248 | _delay_ms (10);
|
249 | if(Adc_value>=TRESHOLD)
|
250 | {
|
251 | // overcurrent detect
|
252 | drive_Motor(CCW,OFF);
|
253 | goto rst_position2;
|
254 | }
|
255 | }
|
256 | rst_position2:
|
257 |
|
258 | CALIB=0;
|
259 | GIFR |= (1<<INT0);
|
260 | GICR |= (1<<INT0);
|
261 | INT_TASTER=0;
|
262 |
|
263 | }
|
264 | if(INT_TASTER&&FIRST) // First mode
|
265 | {
|
266 | drive_Motor(CW,ON);
|
267 | _delay_ms (500);
|
268 | for(u16 i=0;i<moveTimeMotor-50;i++)
|
269 | {
|
270 |
|
271 | Adc_value = ReadChannel(SENSE);
|
272 | _delay_ms (10);
|
273 | if(Adc_value>=TRESHOLD)
|
274 | {
|
275 | drive_Motor(CCW,OFF);
|
276 | _delay_ms (100);
|
277 | drive_Motor(CCW,ON);
|
278 | _delay_ms (500);
|
279 | // overcurrent detect
|
280 | while(1) // drive reverse till on reset position
|
281 | {
|
282 | Adc_value = ReadChannel(SENSE);
|
283 | _delay_ms (10);
|
284 | if(Adc_value>=TRESHOLD)
|
285 | {
|
286 | // overcurrent detect
|
287 | drive_Motor(CCW,OFF);
|
288 | FIRST=1;
|
289 | goto finish;
|
290 | }
|
291 | }
|
292 |
|
293 | }
|
294 | }
|
295 | aktDrivetime+=moveTimeMotor;
|
296 | drive_Motor(CCW,OFF);
|
297 | FIRST=0;
|
298 | finish: GIFR |= (1<<INT0);
|
299 | GICR |= (1<<INT0);
|
300 | _delay_ms (100);
|
301 | INT_TASTER=0;
|
302 | }
|
303 | if(INT_TASTER) // normal mode
|
304 | {
|
305 | drive_Motor(CW,ON);
|
306 | _delay_ms (500);
|
307 | for(u16 i=0;i<moveTimeMotor2-50;i++)
|
308 | {
|
309 |
|
310 | Adc_value = ReadChannel(SENSE);
|
311 | _delay_ms (10);
|
312 | if(Adc_value>=TRESHOLD)
|
313 | {
|
314 | drive_Motor(CCW,OFF);
|
315 | _delay_ms (100);
|
316 | drive_Motor(CCW,ON);
|
317 | _delay_ms (500);
|
318 | // overcurrent detect
|
319 | while(1) // drive reverse till on reset position
|
320 | {
|
321 | Adc_value = ReadChannel(SENSE);
|
322 | _delay_ms (10);
|
323 | if(Adc_value>=TRESHOLD)
|
324 | {
|
325 | // overcurrent detect
|
326 | drive_Motor(CCW,OFF);
|
327 | FIRST=1;
|
328 | goto finish2;
|
329 | }
|
330 | }
|
331 |
|
332 | }
|
333 | }
|
334 | drive_Motor(CCW,OFF);
|
335 | aktDrivetime+=moveTimeMotor2;
|
336 | finish2: GIFR |= (1<<INT0);
|
337 | GICR |= (1<<INT0);
|
338 | _delay_ms (100);
|
339 | INT_TASTER=0;
|
340 | }
|
341 | if((timediff<wert)&&(FIRST==0))
|
342 | {
|
343 | FIRST=1;
|
344 | GICR &= ~(1<<INT0);
|
345 | aktDrivetime=0;
|
346 | drive_Motor(CCW,ON);
|
347 | _delay_ms (500);
|
348 | PORTD ^= _BV(LED_red);
|
349 | // overcurrent detect
|
350 | while(1) // drive reverse till on reset position
|
351 | {
|
352 | Adc_value = ReadChannel(SENSE);
|
353 | _delay_ms (10);
|
354 | if(Adc_value>=TRESHOLD)
|
355 | {
|
356 | // overcurrent detect
|
357 | drive_Motor(CCW,OFF);
|
358 | goto next;
|
359 | }
|
360 | }
|
361 | next:
|
362 | GIFR |= (1<<INT0);
|
363 | GICR |= (1<<INT0);
|
364 | _delay_ms (100);
|
365 | INT_TASTER=0;
|
366 | }
|
367 | _delay_ms (10);
|
368 | }
|
369 | return 1;
|
370 |
|
371 | }// end main
|
372 |
|
373 |
|
374 | ISR (INT0_vect){
|
375 | unsigned char sreg = SREG;
|
376 | //transmit_str_USART("Int0 \n ");
|
377 | INT_TASTER=1; // setze Flag
|
378 | GICR &= ~(1<<INT0);// disable Int0
|
379 | _delay_ms (100);
|
380 | SREG=sreg;
|
381 | }
|