Sensormodul für Motoransteuerung mit Power Save

Gast #1956747
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 :)
Gast #1957122
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren