Forum: Mikrocontroller und Digitale Elektronik CodevisionAVR AD-Wandler und Interrupt


von dr_v (Gast)


Lesenswert?

Hallo,

ich baue hier eine kleine digitale Regelung mit Atmega16 auf und brauche 
eure Hilfe.

uC:      Atmega16 16Mhz Takt
Eingang: ADC 8bit 125kHz, Signal an pin0 gegen Masse (Bereich 0-5V)
Ausgang: PortC binär (8-bit) und dann auf ne R/2R Brücke.
Compiler: CodevisionAVR 1.25.1 Standart
Datei mit C-Quelle ist eingefügt

Funktion: Der uC sollte Spannung dass an Pin0 anliegt wandeln, umrechnen 
mit der Formel, und Ergebnis an PortC einstellen und halten, und dann 
wieder Wert wandeln, berechnen und halten bis der nächste wert berechnet 
wird.

1.Problem: AD-Wandler und Interrupt ich bin mir nicht sicher ob 
AD-Wandlung unterbrochen wird wärend die Berechnung mit der Formel 
läuft. Da muss noch bestimmt am Anfang und am Ende der Berechnung was 
mit Interrupt passieren :) In pdf-Anleitung von cvavr steht nur bisi was 
über externe isr's und Timer.

2. Ich habe umgerechnet 128 Takte fürs AD-Wandeln und Berechnen, wird 
das ausreichen ?, denn ich muss warscheinlich mit float-DatenTyp rechnen 
weil die konstanten in der Formel Nachkommastellen haben und dazu muss 
ich noch 3 mal multiplizieren.

... und wenn jemend welche Vorschläge hat um Code schneller und 
schlanker zu machen wäre ich sehr dankbar.

Danke !

von dr_v (Gast)


Angehängte Dateien:

Lesenswert?

Sorry hier ist die Quelle ;)

von fieser, klugscheissender Rahul (Gast)


Lesenswert?

>um Code schneller

Schmeiss floating-point-arithmetik raus. Benutze lieber 
Fixpunkt-Arithmetik.
Dazu musst du die Konstanten erweitern.

von Karl heinz B. (kbucheg)


Lesenswert?

> denn ich muss warscheinlich mit float-DatenTyp rechnen
> weil die konstanten in der Formel Nachkommastellen haben
> und dazu muss ich noch 3 mal multiplizieren.

Das ist kein Grund

 a = 0.234 * b

kann auch gerechnet werden als

 a = 234 * b / 100;

wenn a und b integer sind, macht das keinen Unterschied.
Ausser dem, dass die 2-te Variante um etliches schneller
ist.

In deinem Fall:
anstatt
  PORTC=(0,062*e+0,044*esum+0,274*edif);  //Reglergleichung
kommt
  PORTC = ( 62 * e + 44 * esum + 274 * edif ) / 1000;

und schon brauchst du kein floating point mehr.

Es gibt auch keinen Grund, warum e, ealt, esum und edif
float sein muessen.


> ... und wenn jemend welche Vorschläge hat um Code schneller
> und schlanker zu machen wäre ich sehr dankbar.

Dein Code ist hauptsächlich deshalb so aufgebläht, wewil
du einen Wizard benutzt hast, der dir auf dem Chip alles
mögliche initialisierst. Unabhängig davon, ob du das brauchst
oder nicht.
Schmeiss das ganze Wizard Zeugs raus, lass nur das drinn was
du brauchst und dein Code passt locker auf eine Bildschirmseite.



von dr_v (Gast)


Lesenswert?

Danke für Vorschlag mit Fixpunkt-Arithmetik !

Ich habe jetzt alle Variablen als int deklariert ist doch richtig so ?

was ist eigentlich mit Interrupt und ADC ? stimmt der code ?

von Axel R. (Gast)


Lesenswert?

nach der vorschau ist der anhang weg

von dr_v (Gast)


Angehängte Dateien:

Lesenswert?

Morgen !

habe gestern noch versuch zu ermitteln wie lange dauert die 
berechnung(natürlich mit Fixpunkt-Arithmetik),
dazu habe ich vor der berechnung PortD auf 0 und nach der berechnung auf 
FF gesetzt und dann am Oszi den Dauer ermittelt und das sind 
25uSekunden.
Naja :( Perioden dauer zwischen Abtastwerten bei 125kHz ist 8us.
Also es haut nicht hin es sei denn die Berechnung wird mehr als 3 mal 
schneller.

Die 2 Fragen von vorhin interessiren mich immer noch:

Alle Variablen als "int" deklariert ist doch richtig so ?

Was ist eigentlich mit Interrupt für die berechnung und ADC ? stimmt der 
code ?

von Karl heinz B. (kbucheg)


Lesenswert?

> Also es haut nicht hin es sei denn die Berechnung wird mehr als 3 mal
> schneller.

Schneller wirds nicht mehr.
Ein Problem könnte ich mir noch vorstellen. Dein µC wird
wahrscheinlich eine Menge Zeit in der ADC_ISR verbringen.
Eine Wandlung dauert ein paar Taktzyklen. Ist die
Wandlung fertig, so wird die ISR abgearbeitet und sofort
die nächste Wandlung gestartet.
D.h. Dein µC arbeitet hauptsächlich in der ISR. Mit der dann
noch verbleibenden Rechenzeitzeit werden nebenbei noch
deine Berechnungen in der Hauptschleife ausgeführt.
Eventuell (müsste man probieren) wäre hier ein Verzicht
auf eine ISR und eine klassische Hauptschleife

   ADC starten
   while( 1 ) {
     ADC holen
     ADC starten
     umrechnen
     Ausgeben
   }

die bessere Alternative. Zumindest verteilt sich dann
die Rechenzeit besser auf die 2 Tasks. Während der ADC
wandelt, rechnet der µC den Wert um und gibt ihn aus
sodass beim nächsten Schleifendurchlauf das nächste
ADC Ergebnis schon wieder fertig zum Abholen ist.

> Alle Variablen als "int" deklariert ist doch richtig so ?
Denk nach.
Was sollen sie sonst sein?

> Was ist eigentlich mit Interrupt für die berechnung und ADC ?
> stimmt der code ?
Ich frag moch schon die ganze Zeit was du in dieser ISR
eigentlich machst. Anscheinend werden da nacheinander
verschiedene ADC Kanäle durchgeschaltet. Ausgewertet wird
aber immer nur ein einziger.
Sieht für mich nicht so aus als ob das stimmen könnte.



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.