Forum: Mikrocontroller und Digitale Elektronik Timer0 gesteuerter AD-Wandler


von Digi H. (digihunter)


Angehängte Dateien:

Lesenswert?

Hallo zusammen!

Es geht um nen digitalen Regler(Zeitdiskreten Regler) da werden ständig 
die Werte in festen Absänden abtastet, Berechnet und Ausgegeben.

Da bei 16MHz keine Abtastraten die niedriger als 125kHz gibt, nehme ich 
mir einen Timer0 und lasse damit bei Overflow den AD-Wandler ein mal 
Wandeln.
Also 16Mhz : Teiler 8 : 256 = 7812,5 Hz => 128us Periode in der 
AD-Wandler sich ein Wert schnapt mit dem später gerechent wird.

Das Problem ist, dass ich mit Timer und ISR noch nicht gearbeitet habe 
und auch keine Ahnung habe welche Zeile in welche routinen gehören.

z.B. eigentlich würd ich AD-Wandlung und Berechnung in ISR stecken, wie 
ich verstanden habe da geht mein Timer in meinem Fall jede 128us ein mal 
rein.

Und es wäre vielleicht besser wenn ich ADC mit ADTS2 (Timer0 Überlauf) 
Trigern lasse ? aber freilaufenden Betrib brauche ich eigentlich nicht.

Ich warne erfahrene C Programmierer vor meinem schlechten Code(den ich 
aber ziemlich gut auskommentiert habe) und hoffe ihr könnt mir helfen es 
bisschen aufzuräumen.

Danke !

von Peter D. (peda)


Lesenswert?

int x=0; // 8-bit Variable

Versuch mal, richtig zu kommentieren.

8 Bit ist "char", bzw. wenn positiv ausreicht, besser "unsigned char".


Und ins main gehört immer ne Endlosschleife (darf nie verlassen werden).

Du hast aufm MC kein BS, wohin Du zurück kannst.


Peter

von Digi H. (digihunter)


Angehängte Dateien:

Lesenswert?

Peter Dannegger wrote:
> int x=0; // 8-bit Variable
>
> Versuch mal, richtig zu kommentieren.
> 8 Bit ist "char", bzw. wenn positiv ausreicht, besser "unsigned char".

das stimmt 8-bit, deklariert als int weil es wird dann mit int 
gerechnet, hier e = 230 - x; e ist int und so weit ich weiss ein 
gemischtes rechnen darf man nicht machen.

> Und ins main gehört immer ne Endlosschleife (darf nie verlassen werden).
>
> Du hast aufm MC kein BS, wohin Du zurück kannst.

nun ich habe alles aus main nach ISR kopiert und da ne schleife mit 
while(1) eingebaut. War das gemeint ?

meiner Meinung nach sehen da

    uint8_t buffer; // buffer für gewandelten 8-bit Wert

    // A/D - Wandler initialisieren
    adc_init();

nicht gut aus :(


von Peter D. (peda)


Lesenswert?

Digi Hunter wrote:

> das stimmt 8-bit, deklariert als int weil es wird dann mit int
> gerechnet, hier e = 230 - x; e ist int und so weit ich weiss ein
> gemischtes rechnen darf man nicht machen.

Wer sagt denn sowas ?
char nach int geht problemlos.


> nun ich habe alles aus main nach ISR kopiert und da ne schleife mit
> while(1) eingebaut. War das gemeint ?

Es war genau so gemeint, wie ich es gesagt habe.

> // Berechnung Ende

ist keine C-Anweisung.

Und danach bist Du im Nirwana.


Peter

von Dieter (Gast)


Lesenswert?

Initialisierung von timer und ad wandler gehören ins main.

aber vielleicht solltest du erst mal mit etwas leichtem anfangen,

z.b. einen Ausgang zu setzen wenn eine Taste gedrückt wird,
wenn das läuft

versuchen Interrupts zu verstehen usw ...

von Dirk (Gast)


Angehängte Dateien:

Lesenswert?

Hallo, setz einfach ein Flag und polle in der Main Routine dieses Flag 
Bit.

Ein kleines Beispiel befindet sich im Anhang.

von Digi H. (digihunter)


Angehängte Dateien:

Lesenswert?

Danke Dirk !!!
Sieht schon viiiiiiel besser aus, dieses Flag(status_byte |= 
(1<<do_adc);) war u.a. mein Problem.

Nun habe ich in help.c Funktionen
int get_adc(void)
void rechnung(void)
gefüllt und regelung3.c genannt.

was muss ich noch mit Variablen temp und x anstellen damit 
AD-gewandelter Wert heil in void rechnung(void) ankommt ?
Also in diesem Absnitt hier:


________________________________________________________

// adc wandlung
int get_adc(void)
{
    // Wandlung starten (1<<ADSC) Einzel.Wandl. und (0<<ADATE) warschnl. 
nicht nötig da sowieso "0"
    ADCSRA |= (1<<ADSC)|(0<<ADATE);

    // Warten bis die AD-Wandlung abgeschloßen ist
    while ( !(ADCSRA & (1<<ADIF)) );

    // AD-Wert auslesen  ADCH da nur 8-bit ausreichen.
    x = ADCH;
}

// berechnung
void rechnung(void)
{
    // Berechnung Anfang
    e = 230 - x;
    esum = esum + e;
    edif = e - ealt;
    PORTC = ( 62 * e + 44 * esum + 274 * edif ) / 1000; 
//Reglergleichung
    ealt = e;
    // Berechnung Ende
}

int main(void) {
  unsigned int temp=0;
  timer0_init();
  adc_init();
  sei();
  for(;;){  //Endlosschleife starten
    if(status_byte & (1<<do_adc)){  // wenn do_adc 1 ist
      status_byte &= ~(1<<do_adc);  //do_adc löschen
      temp = get_adc(); // AD wandeln
      rechnung(); // Rechnen
    }
  }

}
________________________________________________________

von Digi H. (digihunter)


Angehängte Dateien:

Lesenswert?

Hallo nochmal !
Wieso antwortet mir denn keiner ? stelle ich solche dumme Fragen ? :)

Nun habe ich regelung3.c wieder aufgeräumt und lade die gleich mit hoch.

Hab natürlich noch paar Fragen:

1. "status_byte" ist das irgendwo definiert oder nur ne Fantasie von 
Dirk ?
   das habe ich als char definiert (reicht doch ?) weil der Compiler 
gemeckert
   hat.

2. ADIF Bit in Register ADCSR wird doch automatisch(von uC) zurück auf 
"0"
   gesetz nachdem ich nur ADCH (s. regelung3.c) ausgelesen habe ?


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.