www.mikrocontroller.net

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


Autor: Sacx (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
Software:    Entwicklungsumgebung: AVR Studio 4.14 build 589
        C-Compiler:WinAVR-20080610

Tastenfunktion:  Taster 1  : Reset des Sensormoduls 

Jumperstellung:  keine Auswirkung

Fuses im uC:  CKDIV8: Aus    (keine generelle Vorteilung des Takts)


=============================================================================*/ 


// Deklarationen ==============================================================

// Festlegung der Quarzfrequenz

#ifndef F_CPU          // optional definieren
#define F_CPU 18432000UL      // 18,432 MHz Quarz  
#endif                


// Include von Header-Dateien

#include <avr/io.h>        // I/O-Konfiguration (intern weitere Dateien)
#include <stdbool.h>       // Bibliothek fuer Bit-Variable
#include <avr/interrupt.h>    // Definition von Interrupts
#include <util/delay.h>      // Definition von Delays (Wartezeiten)
#include <avr/sleep.h>

#define  SET_BIT(PORT, BIT)  ((PORT) |=  (1 << (BIT))) // Port-Bit Setzen
#define CLR_BIT(PORT, BIT)  ((PORT) &= ~(1 << (BIT))) // Port-Bit Loeschen
#define TGL_BIT(PORT, BIT)   ((PORT) ^=  (1 << (BIT))) // Port-Bit Toggeln

int i;
int x;

void initLDR0(void);
void initLDR1(void);
void initLDR2(void);
void initLDR3(void);
void init_Timer2(void);
void Schlafmodus(void);
void Leuchtstaerke(void);
void Auswertung(void);
void Motorsteuerung(void);

int lux0;
int lux1;
int lux2;
int lux3;

unsigned char modus = 0;

/*volatile int LDR0;
volatile int LDR1;
volatile int LDR2;
volatile int LDR3;

volatile int LDR02;
volatile int LDR20;
volatile int LDR13;
volatile int LDR31;*/

int LDR0;
int LDR1;
int LDR2;
int LDR3;

int LDR02;
int LDR20;
int LDR13;
int LDR31;

bool Motor_oben = 0;
bool Motor_unten = 0;
bool Motor_rechts = 0;
bool Motor_links = 0;


//========================================================================

// Hauptprogramm==========================================================


int main(void)

{
  init_Timer2();

  while(1)
  {
    Schlafmodus();
    
    switch(modus)
    {
      case 0:
        Schlafmodus();
        break;
    
      case 1:
        cli();
        Leuchtstaerke();
        Auswertung();
        break;

      case 2:
        Motorsteuerung();
        break;
    
    }
    
    }
}
 




//========================================================================
//============================ Interrupt Routine==========================

// Interrupt Timer 2 (8bit)
//18432000/256/1024=0,0124s

ISR (TIMER2_OVF_vect)      // Interrupt Service Rountine Timer Overflow 2

{
  i++;
  
  if(i==166)
  {
    i=0;
    modus=1;
  }
}  



  
//=========================================================================
//============================== Initialisierung Timer2====================

void init_Timer2()          // Timer 2 initaliseren
{
    ASSR  |= (1<< AS2);           // Timer2 asynchron takten
   // _delay_ms(100);               // Einschwingzeit des 32kHz Quarzes
  TCCR2A = 0;            // Timer 2 auf "Normal Mode" schalten
  TCCR2B |= 0x7    ;      // mit Prescaler /1024 betreiben -> OVF 8s  XXXXXXXXXXXX 0x7
  
  while((ASSR & (1<< TCR2AUB))&&(ASSR & (1<< TCR2BUB)));   // Warte auf das Ende des Zugriffs

    TIFR2  |= (1<<TOV2);             // Interrupts löschen (*)
    TIMSK2 |= (1<<TOIE2);            // Timer overflow Interrupt freischalten
}
  


//=========================================================================
//=================Unterprogramm für Schlafmodus===========================

void Schlafmodus()

{
  sei();
  
  ACSR |= (1<<ACD);        // A/D deaktivieren
  ADCSRA &= ~(1<<ADEN);      // A/D ausschalten
  PRR |= (1<<PRADC);        // A/D shutdown
  
  OCR2A |= 0x0;                       // Dummyzugriff
    while((ASSR & (1<< TCR2AUB))&&(ASSR & (1<< TCR2BUB)));   // Warte auf das Ende des Zugriffs
 
    set_sleep_mode(SLEEP_MODE_PWR_SAVE);
    sleep_mode();                   // in den Schlafmodus wechseln  
}

  

//=========================================================================
//=================Unterprogramm für Leuchstaerkenbestimmung===============


void Leuchtstaerke()

//======================== 1. WANDLUNG ====================================

{
  initLDR0();

  PRR &= ~(1<<PRADC);            // A/D boot
  ACSR &= ~(1<<ACD);            // A/D aktivieren
  ADCSRA |= (1<<ADEN);          // AD aktivieren
  ADCSRA |= (1<<ADSC);          // Konvertierung starten

  while (ADCSRA & (1<<ADSC))        // Wenn Konvertierung gestartet ist
    {
      ;  
    }

  lux0 = ADCL;
  lux0 += (ADCH<<8);

  lux0=0;

  for (i=0; i<4; i++)
    {
      ADCSRA |= (1<<ADSC);

      while (ADCSRA & (1<<ADSC))      // Wenn Conversion gestartet ist
        {
          ;  
        }

      lux0 = ADCL;
      lux0 += (ADCH<<8);
    }
    
  ADCSRA &= ~(1<<ADEN);
    
  lux0 /=4;                // durch 4 teilen
  LDR0 = lux0;

  i=0;
    
  _delay_us(50);
    
    
//======================== 2. WANDLUNG ====================================

  initLDR1();

  ADCSRA |= (1<<ADEN);          // AD aktivieren
  ADCSRA |= (1<<ADSC);          // Konvertierung starten

  while (ADCSRA & (1<<ADSC))        // Wenn Konvertierung gestartet ist
    {
      ;  
    }

  lux1 = ADCL;
  lux1 += (ADCH<<8);
  
  lux1=0;

  for (i=0; i<4; i++)
    {
      ADCSRA |= (1<<ADSC);

      while (ADCSRA & (1<<ADSC))      // Wenn Conversion gestartet ist
        {
          ;  
        }

      lux1 = ADCL;
      lux1 += (ADCH<<8);
    }
    
  ADCSRA &= ~(1<<ADEN);
  
  lux1 /=4;                // durch 4 teilen
  LDR1 = lux1;

  i=0;

  _delay_us(50);


//======================== 3. WANDLUNG ====================================

  initLDR2();

  ADCSRA |= (1<<ADEN);          // AD aktivieren
  ADCSRA |= (1<<ADSC);          // Konvertierung starten

  while (ADCSRA & (1<<ADSC))        // Wenn Konvertierung gestartet ist
    {
      ;  
    }

  lux2 = ADCL;
  lux2 += (ADCH<<8);
  
  lux2=0;

  for (i=0; i<4; i++)
    {
      ADCSRA |= (1<<ADSC);

      while (ADCSRA & (1<<ADSC))      // Wenn Conversion gestartet ist
        {
          ;  
        }

      lux2 = ADCL;
      lux2 += (ADCH<<8);
    }
    
  ADCSRA &= ~(1<<ADEN);
    
  lux2 /=4;                // durch 4 teilen
  LDR2 = lux2;

  i=0;

  _delay_us(50);

//======================== 4. WANDLUNG ====================================

  initLDR3();

  ADCSRA |= (1<<ADEN);          // AD aktivieren
  ADCSRA |= (1<<ADSC);          // Konvertierung starten

  while (ADCSRA & (1<<ADSC))        // Wenn Konvertierung gestartet ist
    {
      ;  
    }

  lux3 = ADCL;
  lux3 += (ADCH<<8);
  
  lux3=0;

  for (i=0; i<4; i++)
    {
      ADCSRA |= (1<<ADSC);

      while (ADCSRA & (1<<ADSC))      // Wenn Conversion gestartet ist
        {
          ;  
        }

      lux3 = ADCL;
      lux3 += (ADCH<<8);
    }
    
  ADCSRA &= ~(1<<ADEN);
    
  lux3 /=4;                // durch 4 teilen
  LDR3 = lux3;

  i=0;
    
  _delay_us(50);
}  




//=========================================================================
//=================Unterprogramm zur LDR-Initialisierung===================

void initLDR0()

{
  ADMUX |= 0xC0;    // (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (0<<MUX2) | (0<<MUX0) | (0<<MUX1)

            // 1.1V mit Externen Kondensator (REFS) + ADC0 Eingang LDR (MUX)

  ADCSRA |= 0x87;    // (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)

            // ADC aktivieren + Vorteiler 128 (Prescaler Selection Bits)
}  

void initLDR1()

{
  ADMUX |= 0xC1;    // (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (0<<MUX2) | (0<<MUX0) | (1<<MUX1)

            // 1.1V mit Externen Kondensator (REFS) + ADC1 Eingang LDR (MUX)

  ADCSRA |= 0x87;    
}  

void initLDR2()

{
  ADMUX |= 0xC2;    // (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (0<<MUX2) | (1<<MUX0) | (0<<MUX1)

            // 1.1V mit Externen Kondensator (REFS) + ADC2 Eingang LDR (MUX)

  ADCSRA |= 0x87;    
}  

void initLDR3()

{
  ADMUX |= 0xC3;    // (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (0<<MUX2) | (1<<MUX0) | (1<<MUX1)

            // 1.1V mit Externen Kondensator (REFS) + ADC3 Eingang LDR (MUX)

  ADCSRA |= 0x87;    
}  



//=========================================================================
//=================Unterprogramm zur LDR-Auswertung========================

void Auswertung()

{
  if(LDR0>LDR2)
  {
    LDR02 = LDR0-LDR2;

    if(LDR02>100)
    {
      Motor_links=1;
      LDR02=0;
      modus=2;
    }
    
    else
    {
      LDR02=0;
      modus=0;
    }
  }    

  else
  {
    LDR20 = LDR2-LDR0;
  
    if(LDR20>100)
    {
      Motor_rechts=1;
      LDR20=0;
      modus=2;
    }
    
    else
    {
      LDR20=0;
      modus=0;
    }
  }
  
  if(LDR1>LDR3)
  {
    LDR13 = LDR1-LDR3;

    if(LDR13>100)
    {
      Motor_oben=1;
      LDR13=0;
      modus=2;
    }
    
    else
    {
      LDR13=0;
      modus=0;
    }
  }
  
  else
  {
    LDR31 = LDR3-LDR1;

    if(LDR31>100)
    {
      Motor_unten=1;
      LDR31=0;
      modus=2;
    }
    
    else
    {
      LDR31=0;
      modus=0;
    }
  }
}    



//=========================================================================
//=================Unterprogramm zur Motorsteuerung========================

void Motorsteuerung()

{
  if(Motor_links==1)          //LDR0>LDR2
    {
      SET_BIT(DDRB, DDB0);
      CLR_BIT(PORTB, PB0);    // LED einschalten;
      Motor_links=0;
      modus=1;
    }
  
  else
    {  
      SET_BIT(DDRB, DDB0);
      SET_BIT(PORTB, PB0);    // LED ausschalten, falls an
      modus=1;
    }

  if(Motor_rechts==1)          //LDR0<LDR2
    {
      SET_BIT(DDRB, DDB2);
      CLR_BIT(PORTB, PB2);    // LED einschalten;
      Motor_rechts=0;
      modus=1;
    }
  
  else
    {  
      SET_BIT(DDRB, DDB2);
      SET_BIT(PORTB, PB2);    // LED ausschalten, falls an
      modus=1;
    }

  if(Motor_oben==1)          //LDR1>LDR3
    {
      SET_BIT(DDRB, DDB1);
      CLR_BIT(PORTB, PB1);    // LED einschalten;
      Motor_oben=0;
      modus=1;
    }
  
  else
    {  
      SET_BIT(DDRB, DDB1);
      SET_BIT(PORTB, PB1);    // LED ausschalten, falls an
      modus=1;
    }

  if(Motor_unten==1)          //LDR1<LDR3
    {
      SET_BIT(DDRB, DDB3);
      CLR_BIT(PORTB, PB3);    // LED einschalten;
      Motor_unten=0;
      modus=1;
    }
  
  else
    {  
      SET_BIT(DDRB, DDB3);
      SET_BIT(PORTB, PB3);    // LED ausschalten, falls anmodus=1;
      modus=1;
    }
}      


Danke schonmal im VOraus :)

Autor: Sacx (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.