main.c


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
  }