www.mikrocontroller.net

Forum: Compiler & IDEs LED dimmen per PWM mit ADC (ATMega88)


Autor: C-Neuling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Programm soll eine Spannung die durch eine Led gemessen wird und per 
AD Wandler umgewandelt wird per PWM eine andere LED dimmen, je nach 
Größe der Spannung.
Die optische Led hängt an PC5.
Die Led welche gedimmt werden soll an PB2.
Kann jemand sagen welche Teile in diesem Programm nicht stimmen? Denn 
leider funtioniert es nicht... :-(

#include <stdlib.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdbool.h>

void ad_init(void);
void wandeln(void);
void timer0(void);
void initialisierung(void);
void PWM(void);

#define TEILER1 5000  //??????????????
#define TEILER2 5000  //??????????????

unsigned int softwareteiler1, softwareteiler2;
unsigned int wert;

bool Takt1 =0;
bool Takt2 =0;


int main(void)
{
  initialisierung();  // ruft alle Initialisierungen auf

  while (1)          // Endlosschleife
  {
      if (Takt1)
      {
      Takt1=0;
      wandeln();
      }

    if (Takt2)
      {
      Takt2 = 0;
      PWM();

      }
  }

}



// Timer0 initialisieren


void timer0(void)
{
  sei();
  TCCR0B |= (1<<CS01);      //Prescaler  / 8
  TIMSK0 |= (1<<TOIE0);
}



// Initialiserung AD-Wandler


void ad_init(void)
{


PRR = 0x00;

MCUCR = 0x10;

ADCSRA |= (1<<ADEN); // A/D-Wandler Enable


ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);  // Prescaler auf 128 
stellen


ADMUX |= (1<<REFS0) | (1<<MUX2) | (1<<MUX0); //  (AVCC als AREF + 
external C) (ADC5 = input)


ADCSRB = 0x00;  // Free runing mode


DIDR0 = 0x3f;  // Digital Input Disable Register



}


// Interrupt Routine Timer0 Overflow


ISR (TIMER0_OVF_vect)
{
  softwareteiler1--;
  if (softwareteiler1 == 0)
    {
    softwareteiler1 = TEILER1;
    Takt1 = 1;                // Takt1 Flag = True
    softwareteiler2--;
    if (softwareteiler2 == 0)
      {
      softwareteiler2 = TEILER2;
      Takt2=1;              // Takt2 Flag = True
      }
    }

}


// WANDELN

void wandeln (void)
{


  ADCSRA |= (1<<ADEN);  // A/D Wandler einschalten

  // Dummy-Messung (eine Messung wird durchgeführt und dann verworfen)

  ADCSRA |= (1<<ADSC);                // eine ADC-Wandlung
    while ( ADCSRA & (1<<ADSC) );    // Auf Abschluss der Wandlung 
warten

  wert = ADCW;    // Dummy Messung
  wert = 0;

  ADCSRA |= (1<<ADEN);    //Free Running Modus wir eingeschaltet
  ADCSRB |= 0x00;
  wert=ADCW;              //Register wird ausgelesen und wert wird 
übergeben
}




//PWM

void PWM(void)
{
   DDRB = (1 << PB2 );
   TCCR2A = (1<<COM2A1) | (1<<WGM21)| (1<<WGM20);
   TCCR2B = (1<<WGM22) | (1<<CS00);
   ICR1 = 0x00FF;
   OCR2A = wert;

}


//Initialisierung in main


void initialisierung(void)
{


  softwareteiler1 = TEILER1; //Variablen konstanten Wert zuweisen
  softwareteiler2 = TEILER2;

  DDRB |= (1<<PB2);    // Port B2 als Ausgang (gelbe LED)
  DDRC &= ~(1<<PC5);  // Pin 5 an Port C als Eingang definieren (weise 
LED)

  timer0();  // Initialisierung Timer0
  ad_init();  // Initialisierung AD-Wandler


}

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
- Takt1, Takt2 müssen 'volatile' werden - softwareteiler1 und 
softwareteiler2 wahrscheinlich auch.
 - Sind die TEILERx Macros geraten?
5000 * 5000 * 256 * 8
TEILER1
       TEILER2
              8-Bit -Timer
                     Prescaler
...sind eine Menge Takte zwischen zwei Wandlungen
 - Musst du den ADC immer ab- und wieder anschalten? Es reicht doch 
(wenn's nicht ultra-mobil werden soll) wenn der ADC bei der 
Initialisierung angeschaltet (ADEN-Bit) wird
 - bei "wandlung()" passen Bits und Kommentare nicht zusammen ("ADCSRA 
|= (1 << ADEN);  //Free Running Modus wir eingeschaltet")
 - Warum gibt "wandlung()" nicht einfach den gemessenen Wert zurück?

hth. Jörg

Autor: C-Neuling (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Jörg danke das du dir die Mühe gemacht hast das Programm durch zu 
schauen.
Was meinst du mit Makros das verstehe ich nicht? Die 5000 hab ich 
einfach mal so reingetippt das was da steht ich weis noch nicht wie ich 
auf richtige Werte komme.
Ja es müsste okay sein wenn ich den ADC in der Initialisierung 
einschalte
das müsste ja dann so aussehen?

void initialisierung(void)
{


  softwareteiler1 = TEILER1; //Variablen konstanten Wert zuweisen
  softwareteiler2 = TEILER2;

  DDRB |= (1<<PB2);    // Port B2 als Ausgang (gelbe LED)
  DDRC &= ~(1<<PC5);  // Pin 5 an Port C als Eingang definieren (weise
LED)

  timer0();  // Initialisierung Timer0
  ad_init();  // Initialisierung AD-Wandler

   ADCSRA |= (1<<ADEN);  //ADC wird eingeschaltet
}

und diese Zeile dann überall rauslöschen?!

Wie kann ich bei wandlung()  nur den gemessen Wert zurück geben? Das hab 
ich noch nicht verstanden.


Sorry für so viele Fragen aber ist halt echt Neuland

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... Weiter im text:
 - Der PWM-ausgang, den du im Programm einschaltest (OC2A) liegt auf 
PB*3*, nicht PB2. Du musst also die LED anders anschließen oder OC*1B* 
benutzen.
 - Verrate doch bitte, wie die LED zu messung angeschlossen ist -- wenn 
die LED einfach so angeschlossen ist (direkt am ADC-pin), wirst du da 
nicht so wahnsinnig viel messen können.
 - wenn du 8-Bit-PWM benutzt, musst du den Wert anpassen (wert>>2, 
wert/4, ADLAR setzen und nur das ADCH-Register benutzen, etc.)
 - Es reicht auch den Timer am anfang einzustellen, und im laufenden 
Programm NUR noch das OCnx-Register zu verstellen.

hth. Jörg
ps.: sry wegen der 'Meckerei' ;)

Autor: Jörg X. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab dein Programm mal nach meinem Geschmack umstrukturiert, es 
kompiliert (mit WinAVR-20071221), ist aber ungetestet.

Poste unbedingt deine Schaltung (auch wenn ich dir damit 
wahrscheinlich nicht wirklich helfen kann)

hth. Jörg
ps.: besorg dir ein C-Buch!
pps.: als Notlösung gibt's im Web ein Openbook über C, ich finde das 
aber ein bisschen unübersichtlich

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.