Forum: Compiler & IDEs Sensormodul für Motoransteuerung mit Power Save


von Sacx (Gast)


Lesenswert?

Hallo zusammen

Ich habe mir nun schon einige Infos hier aus dem Forum geholt und nun 
endlich mein Programm fertig geschrieben.
Das Ganze habe ich dann auf einem breadb board aufgebaut und wollte es 
testen... nur, wie halt meistens so ist, funktioniert es nicht wirklich 
:)

So zur Funktionsbeschreibung...

Im Grunde habe ich 4 Licht-Sensoren die im Kreuz angeordnet sind. Dabei 
sollen die gegenüberliegenden miteinander verglichen werden und wenn 
sich die Werte um einen bestimmten Betrag unterscheiden, soll jeweils 
ein Motor verfahren.

Einen Power Save Mode hab ich eingebaut, damit er nur alle 4s die 
Sensoren ansteuert.

Ich habe den Power Save Mode testweise so geschrieben, das er direkt 
eine LED ansteuert und das ganze hat auch funktioniert. Ich denke also 
das dieser Modus schon funktionieren sollte.

Allerdings schalte ich in meinem richtigen Programm jedes Mal, bevor ich 
in den Power Save Mode gehe, den AD - Wandler aus und ich könnte mir 
vorstellen, das dort vllt der Fehler ist ^^

Übrigens verwende ich BWPs die bei derzeitigem Wetter, bei Raumlicht, in 
etwa 0,4V liefern. Zudem setze ich einen 18Mhz Quarz testweise ein, den 
ich später allerdings durch einen Uhrenquarz 32khz ersetzen möchte um 
Wakeup-Zeiten im Sekundenbereich zu bekommen.

Nun, langer Rede kurzer Sinn... hier mein Programm
1
Software:    Entwicklungsumgebung: AVR Studio 4.14 build 589
2
        C-Compiler:WinAVR-20080610
3
4
Tastenfunktion:  Taster 1  : Reset des Sensormoduls 
5
6
Jumperstellung:  keine Auswirkung
7
8
Fuses im uC:  CKDIV8: Aus    (keine generelle Vorteilung des Takts)
9
10
11
=============================================================================*/ 
12
13
14
// Deklarationen ==============================================================
15
16
// Festlegung der Quarzfrequenz
17
18
#ifndef F_CPU          // optional definieren
19
#define F_CPU 18432000UL      // 18,432 MHz Quarz  
20
#endif                
21
22
23
// Include von Header-Dateien
24
25
#include <avr/io.h>        // I/O-Konfiguration (intern weitere Dateien)
26
#include <stdbool.h>       // Bibliothek fuer Bit-Variable
27
#include <avr/interrupt.h>    // Definition von Interrupts
28
#include <util/delay.h>      // Definition von Delays (Wartezeiten)
29
#include <avr/sleep.h>
30
31
#define  SET_BIT(PORT, BIT)  ((PORT) |=  (1 << (BIT))) // Port-Bit Setzen
32
#define CLR_BIT(PORT, BIT)  ((PORT) &= ~(1 << (BIT))) // Port-Bit Loeschen
33
#define TGL_BIT(PORT, BIT)   ((PORT) ^=  (1 << (BIT))) // Port-Bit Toggeln
34
35
int i;
36
int x;
37
38
void initLDR0(void);
39
void initLDR1(void);
40
void initLDR2(void);
41
void initLDR3(void);
42
void init_Timer2(void);
43
void Schlafmodus(void);
44
void Leuchtstaerke(void);
45
void Auswertung(void);
46
void Motorsteuerung(void);
47
48
int lux0;
49
int lux1;
50
int lux2;
51
int lux3;
52
53
unsigned char modus = 0;
54
55
/*volatile int LDR0;
56
volatile int LDR1;
57
volatile int LDR2;
58
volatile int LDR3;
59
60
volatile int LDR02;
61
volatile int LDR20;
62
volatile int LDR13;
63
volatile int LDR31;*/
64
65
int LDR0;
66
int LDR1;
67
int LDR2;
68
int LDR3;
69
70
int LDR02;
71
int LDR20;
72
int LDR13;
73
int LDR31;
74
75
bool Motor_oben = 0;
76
bool Motor_unten = 0;
77
bool Motor_rechts = 0;
78
bool Motor_links = 0;
79
80
81
//========================================================================
82
83
// Hauptprogramm==========================================================
84
85
86
int main(void)
87
88
{
89
  init_Timer2();
90
91
  while(1)
92
  {
93
    Schlafmodus();
94
    
95
    switch(modus)
96
    {
97
      case 0:
98
        Schlafmodus();
99
        break;
100
    
101
      case 1:
102
        cli();
103
        Leuchtstaerke();
104
        Auswertung();
105
        break;
106
107
      case 2:
108
        Motorsteuerung();
109
        break;
110
    
111
    }
112
    
113
    }
114
}
115
 
116
117
118
119
120
//========================================================================
121
//============================ Interrupt Routine==========================
122
123
// Interrupt Timer 2 (8bit)
124
//18432000/256/1024=0,0124s
125
126
ISR (TIMER2_OVF_vect)      // Interrupt Service Rountine Timer Overflow 2
127
128
{
129
  i++;
130
  
131
  if(i==166)
132
  {
133
    i=0;
134
    modus=1;
135
  }
136
}  
137
138
139
140
  
141
//=========================================================================
142
//============================== Initialisierung Timer2====================
143
144
void init_Timer2()          // Timer 2 initaliseren
145
{
146
    ASSR  |= (1<< AS2);           // Timer2 asynchron takten
147
   // _delay_ms(100);               // Einschwingzeit des 32kHz Quarzes
148
  TCCR2A = 0;            // Timer 2 auf "Normal Mode" schalten
149
  TCCR2B |= 0x7    ;      // mit Prescaler /1024 betreiben -> OVF 8s  XXXXXXXXXXXX 0x7
150
  
151
  while((ASSR & (1<< TCR2AUB))&&(ASSR & (1<< TCR2BUB)));   // Warte auf das Ende des Zugriffs
152
153
    TIFR2  |= (1<<TOV2);             // Interrupts löschen (*)
154
    TIMSK2 |= (1<<TOIE2);            // Timer overflow Interrupt freischalten
155
}
156
  
157
158
159
//=========================================================================
160
//=================Unterprogramm für Schlafmodus===========================
161
162
void Schlafmodus()
163
164
{
165
  sei();
166
  
167
  ACSR |= (1<<ACD);        // A/D deaktivieren
168
  ADCSRA &= ~(1<<ADEN);      // A/D ausschalten
169
  PRR |= (1<<PRADC);        // A/D shutdown
170
  
171
  OCR2A |= 0x0;                       // Dummyzugriff
172
    while((ASSR & (1<< TCR2AUB))&&(ASSR & (1<< TCR2BUB)));   // Warte auf das Ende des Zugriffs
173
 
174
    set_sleep_mode(SLEEP_MODE_PWR_SAVE);
175
    sleep_mode();                   // in den Schlafmodus wechseln  
176
}
177
178
  
179
180
//=========================================================================
181
//=================Unterprogramm für Leuchstaerkenbestimmung===============
182
183
184
void Leuchtstaerke()
185
186
//======================== 1. WANDLUNG ====================================
187
188
{
189
  initLDR0();
190
191
  PRR &= ~(1<<PRADC);            // A/D boot
192
  ACSR &= ~(1<<ACD);            // A/D aktivieren
193
  ADCSRA |= (1<<ADEN);          // AD aktivieren
194
  ADCSRA |= (1<<ADSC);          // Konvertierung starten
195
196
  while (ADCSRA & (1<<ADSC))        // Wenn Konvertierung gestartet ist
197
    {
198
      ;  
199
    }
200
201
  lux0 = ADCL;
202
  lux0 += (ADCH<<8);
203
204
  lux0=0;
205
206
  for (i=0; i<4; i++)
207
    {
208
      ADCSRA |= (1<<ADSC);
209
210
      while (ADCSRA & (1<<ADSC))      // Wenn Conversion gestartet ist
211
        {
212
          ;  
213
        }
214
215
      lux0 = ADCL;
216
      lux0 += (ADCH<<8);
217
    }
218
    
219
  ADCSRA &= ~(1<<ADEN);
220
    
221
  lux0 /=4;                // durch 4 teilen
222
  LDR0 = lux0;
223
224
  i=0;
225
    
226
  _delay_us(50);
227
    
228
    
229
//======================== 2. WANDLUNG ====================================
230
231
  initLDR1();
232
233
  ADCSRA |= (1<<ADEN);          // AD aktivieren
234
  ADCSRA |= (1<<ADSC);          // Konvertierung starten
235
236
  while (ADCSRA & (1<<ADSC))        // Wenn Konvertierung gestartet ist
237
    {
238
      ;  
239
    }
240
241
  lux1 = ADCL;
242
  lux1 += (ADCH<<8);
243
  
244
  lux1=0;
245
246
  for (i=0; i<4; i++)
247
    {
248
      ADCSRA |= (1<<ADSC);
249
250
      while (ADCSRA & (1<<ADSC))      // Wenn Conversion gestartet ist
251
        {
252
          ;  
253
        }
254
255
      lux1 = ADCL;
256
      lux1 += (ADCH<<8);
257
    }
258
    
259
  ADCSRA &= ~(1<<ADEN);
260
  
261
  lux1 /=4;                // durch 4 teilen
262
  LDR1 = lux1;
263
264
  i=0;
265
266
  _delay_us(50);
267
268
269
//======================== 3. WANDLUNG ====================================
270
271
  initLDR2();
272
273
  ADCSRA |= (1<<ADEN);          // AD aktivieren
274
  ADCSRA |= (1<<ADSC);          // Konvertierung starten
275
276
  while (ADCSRA & (1<<ADSC))        // Wenn Konvertierung gestartet ist
277
    {
278
      ;  
279
    }
280
281
  lux2 = ADCL;
282
  lux2 += (ADCH<<8);
283
  
284
  lux2=0;
285
286
  for (i=0; i<4; i++)
287
    {
288
      ADCSRA |= (1<<ADSC);
289
290
      while (ADCSRA & (1<<ADSC))      // Wenn Conversion gestartet ist
291
        {
292
          ;  
293
        }
294
295
      lux2 = ADCL;
296
      lux2 += (ADCH<<8);
297
    }
298
    
299
  ADCSRA &= ~(1<<ADEN);
300
    
301
  lux2 /=4;                // durch 4 teilen
302
  LDR2 = lux2;
303
304
  i=0;
305
306
  _delay_us(50);
307
308
//======================== 4. WANDLUNG ====================================
309
310
  initLDR3();
311
312
  ADCSRA |= (1<<ADEN);          // AD aktivieren
313
  ADCSRA |= (1<<ADSC);          // Konvertierung starten
314
315
  while (ADCSRA & (1<<ADSC))        // Wenn Konvertierung gestartet ist
316
    {
317
      ;  
318
    }
319
320
  lux3 = ADCL;
321
  lux3 += (ADCH<<8);
322
  
323
  lux3=0;
324
325
  for (i=0; i<4; i++)
326
    {
327
      ADCSRA |= (1<<ADSC);
328
329
      while (ADCSRA & (1<<ADSC))      // Wenn Conversion gestartet ist
330
        {
331
          ;  
332
        }
333
334
      lux3 = ADCL;
335
      lux3 += (ADCH<<8);
336
    }
337
    
338
  ADCSRA &= ~(1<<ADEN);
339
    
340
  lux3 /=4;                // durch 4 teilen
341
  LDR3 = lux3;
342
343
  i=0;
344
    
345
  _delay_us(50);
346
}  
347
348
349
350
351
//=========================================================================
352
//=================Unterprogramm zur LDR-Initialisierung===================
353
354
void initLDR0()
355
356
{
357
  ADMUX |= 0xC0;    // (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (0<<MUX2) | (0<<MUX0) | (0<<MUX1)
358
359
            // 1.1V mit Externen Kondensator (REFS) + ADC0 Eingang LDR (MUX)
360
361
  ADCSRA |= 0x87;    // (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
362
363
            // ADC aktivieren + Vorteiler 128 (Prescaler Selection Bits)
364
}  
365
366
void initLDR1()
367
368
{
369
  ADMUX |= 0xC1;    // (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (0<<MUX2) | (0<<MUX0) | (1<<MUX1)
370
371
            // 1.1V mit Externen Kondensator (REFS) + ADC1 Eingang LDR (MUX)
372
373
  ADCSRA |= 0x87;    
374
}  
375
376
void initLDR2()
377
378
{
379
  ADMUX |= 0xC2;    // (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (0<<MUX2) | (1<<MUX0) | (0<<MUX1)
380
381
            // 1.1V mit Externen Kondensator (REFS) + ADC2 Eingang LDR (MUX)
382
383
  ADCSRA |= 0x87;    
384
}  
385
386
void initLDR3()
387
388
{
389
  ADMUX |= 0xC3;    // (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (0<<MUX2) | (1<<MUX0) | (1<<MUX1)
390
391
            // 1.1V mit Externen Kondensator (REFS) + ADC3 Eingang LDR (MUX)
392
393
  ADCSRA |= 0x87;    
394
}  
395
396
397
398
//=========================================================================
399
//=================Unterprogramm zur LDR-Auswertung========================
400
401
void Auswertung()
402
403
{
404
  if(LDR0>LDR2)
405
  {
406
    LDR02 = LDR0-LDR2;
407
408
    if(LDR02>100)
409
    {
410
      Motor_links=1;
411
      LDR02=0;
412
      modus=2;
413
    }
414
    
415
    else
416
    {
417
      LDR02=0;
418
      modus=0;
419
    }
420
  }    
421
422
  else
423
  {
424
    LDR20 = LDR2-LDR0;
425
  
426
    if(LDR20>100)
427
    {
428
      Motor_rechts=1;
429
      LDR20=0;
430
      modus=2;
431
    }
432
    
433
    else
434
    {
435
      LDR20=0;
436
      modus=0;
437
    }
438
  }
439
  
440
  if(LDR1>LDR3)
441
  {
442
    LDR13 = LDR1-LDR3;
443
444
    if(LDR13>100)
445
    {
446
      Motor_oben=1;
447
      LDR13=0;
448
      modus=2;
449
    }
450
    
451
    else
452
    {
453
      LDR13=0;
454
      modus=0;
455
    }
456
  }
457
  
458
  else
459
  {
460
    LDR31 = LDR3-LDR1;
461
462
    if(LDR31>100)
463
    {
464
      Motor_unten=1;
465
      LDR31=0;
466
      modus=2;
467
    }
468
    
469
    else
470
    {
471
      LDR31=0;
472
      modus=0;
473
    }
474
  }
475
}    
476
477
478
479
//=========================================================================
480
//=================Unterprogramm zur Motorsteuerung========================
481
482
void Motorsteuerung()
483
484
{
485
  if(Motor_links==1)          //LDR0>LDR2
486
    {
487
      SET_BIT(DDRB, DDB0);
488
      CLR_BIT(PORTB, PB0);    // LED einschalten;
489
      Motor_links=0;
490
      modus=1;
491
    }
492
  
493
  else
494
    {  
495
      SET_BIT(DDRB, DDB0);
496
      SET_BIT(PORTB, PB0);    // LED ausschalten, falls an
497
      modus=1;
498
    }
499
500
  if(Motor_rechts==1)          //LDR0<LDR2
501
    {
502
      SET_BIT(DDRB, DDB2);
503
      CLR_BIT(PORTB, PB2);    // LED einschalten;
504
      Motor_rechts=0;
505
      modus=1;
506
    }
507
  
508
  else
509
    {  
510
      SET_BIT(DDRB, DDB2);
511
      SET_BIT(PORTB, PB2);    // LED ausschalten, falls an
512
      modus=1;
513
    }
514
515
  if(Motor_oben==1)          //LDR1>LDR3
516
    {
517
      SET_BIT(DDRB, DDB1);
518
      CLR_BIT(PORTB, PB1);    // LED einschalten;
519
      Motor_oben=0;
520
      modus=1;
521
    }
522
  
523
  else
524
    {  
525
      SET_BIT(DDRB, DDB1);
526
      SET_BIT(PORTB, PB1);    // LED ausschalten, falls an
527
      modus=1;
528
    }
529
530
  if(Motor_unten==1)          //LDR1<LDR3
531
    {
532
      SET_BIT(DDRB, DDB3);
533
      CLR_BIT(PORTB, PB3);    // LED einschalten;
534
      Motor_unten=0;
535
      modus=1;
536
    }
537
  
538
  else
539
    {  
540
      SET_BIT(DDRB, DDB3);
541
      SET_BIT(PORTB, PB3);    // LED ausschalten, falls anmodus=1;
542
      modus=1;
543
    }
544
}

Danke schonmal im VOraus :)

von Sacx (Gast)


Lesenswert?

Die Funktion Schlafmodus(); gleich nach der while-Schleife gehört da 
nicht hin ^^ habs schon verbessert.

Mein Problem bei dieser Funktion ist eigentlich das Ein- bzw. 
Ausschalten des A/D-Wandlers. Ich weiß nicht ob ich das so richtig 
gemacht habe.

Außerdem hab ich grad einige Test gemacht und hab in den Interrupt eine 
Funktion geschrieben zum Toggeln einer LED... dies hat ohne Probleme 
funktioniert.

Nun habe ich dieses Toggeln in case1 gesetz und die Funktionen 
Leuchtstaerke, Auswertung sowie case2 komplett auskommentiert.

Nun müsste der uc eigentlich ja im interrupt den modus 1 setzen und das 
programm müsste in der while-schleife in case1 springen, oder hab ich da 
schon was vermurkst?

bitte um Anregungen :)

Gruß sacx

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.