Mal wieder ADC Mittelwert

OP #3210609
Lesenswert?

Hallo liebe Leute.
Ich weiß dieses Thema gibts hier schon oft. Aber ich stehe irgendwie 
gerade voll auf'm Schlauch.
Der Betreff sagt's ja schon. Und die ADCResult auf dem LCD funktioniert 
auch von 0-1023 wie sie soll. Doch sobald ich die Mittelwertberechnung 
mache geht die Zahl nur noch von 0-255 und das dann eben 4 mal 
nacheinander.
Bin mir auch nicht sicher ob das vom Timing her überhaupt passt. Denn 
die Mittelwertberechnung zieht sich ja unabhängig vom ADC den ADCResult 
wert. Aber ich komm da auch nich drauf wie man das am Besten koppeln 
könnte...

Habt ihr vielleicht ne fuchsige Idee?
1
#define F_CPU 8000000UL            // 8 MHz-Takt
2

3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <stdlib.h>
6
#include <avr/delay.h>
7
#include "lcd-routines.h"
8

9
int i;
10
uint16_t ADCMittel=0;
11
char ADCString[4];
12
uint16_t ADCResult;
13

14
int main ()
15
{  
16
lcd_init();                    // Initialisierung des LCD    
17
lcd_string("ADC Result:");
18
                  
19
//////ADC Einstellen
20
ADMUX  = 0b01000000;              //Interne Referenz = AVCC - Rechtsbündig - Pin ist PC0
21
ADCSRA = 0b10001110;              //ADEN, ADIE, Geschwidigkeit des ADC festlegen 125kHz, Vorteiler 64 - Interrupt - ADC einschalten
22
  
23
sei();                      //Set interrupt enable
24
  
25
ADCSRA |= 1<<ADSC;                //Starte Messung
26
  
27
  while(1)
28
  {
29
  //////ADC MITTELWERT
30
    
31
    for (i=0;i<256;i++)
32
    {      
33
    ADCMittel=ADCMittel+ADCResult;      //Aufsummieren
34
    }
35
          
36
    if (i=256)
37
    {
38
    ADCMittel=ADCMittel/256;        //Mittelwert bilden
39
    
40
    //ADCmittel = ADCmittel;        //Umrechnung für PT100
41

42
    itoa(ADCMittel, ADCString, 10 );    //Umwandlung
43
    lcd_setcursor(12,1);          //Ausgabe
44
    lcd_string(ADCString);
45
    lcd_string("    ");
46
    _delay_ms(100);
47
    }    
48
  }    
49
  
50
}
51
ISR (ADC_vect)                  //Interrupt routine: ADC
52
{                
53

54
uint8_t lowADC = ADCL;              //Lese unteres Byte ADC
55
ADCResult = ADCH<<8 | lowADC;          //Schiebe oberes ADC-Byte 8 nach links und füge unteres Byte hinzu
56

57
ADCSRA |= 1<<ADSC;                //Starte eine Messung
58
}
Gast #3210646
Lesenswert?

Hi

>    for (i=0;i<256;i++)
>    {
>    ADCMittel=ADCMittel+ADCResult;      //Aufsummieren
>    }

Woher weiß dein Controller daß ein neuer Wert vorliegt? In der Zeit, in 
der die Schleife abgearbeitet wird dürften max. 1 bis zwei Messungen 
ablaufen.

MfG spess
#3210661
Lesenswert?

Spess53 schrieb:
> Hi
>
>>    for (i=0;i<256;i++)
>>    {
>>    ADCMittel=ADCMittel+ADCResult;      //Aufsummieren
>>    }
>
> Woher weiß dein Controller daß ein neuer Wert vorliegt? In der Zeit, in
> der die Schleife abgearbeitet wird dürften max. 1 bis zwei Messungen
> ablaufen.

Jep.

@Sebastian
In einer Anwendung wie dieser bringt der ganze Interrupt-Quatsch nichts.
Machs klassisch konventionell und gut ists. Wandlung starten, Warten bis 
sie fertig ist, auslesen. Und das in einer Schleife 64 mal. Und am 
besten gleich ab in eine eigene Funktion damit.(*)

Mit deinem Interrupt Ansatz handelst du dir mehr Probleme ein, als dir 
lieb ist. Zb. dass man eine ISR-main gesharte Variable volatile machen 
muss und wenn es sich um was größeres als einen uint8_t handelt, dann 
musst du auch noch für atomares Auslesen sorgen.

(*) womit wir genau bei den im AVR-GCC-Tutorial beschriebenen Funktionen 
wären.
#3210671
Lesenswert?

Karl Heinz Buchegger schrieb:
> Sebastian Schubert schrieb:
>> Hunt Worker schrieb:
>>> Warum "if (i=256)..." in deiner while(1)?
>>
>> Um die Mittelwertberechnung erst dann zu starten wenn dementsprechend
>> viele Werte gespeichert wurden.
>
> SChön.
> Dazu brauchst du aber einen Vergleich.
> Du hast aber keinen Vergleich geschrieben, sondern eine Zuweisung.
> (Und die Compilerwarnung ignoriert)

Im übrigen ist das Quatsch.
Welchen Wert soll denn i nach diesem Konstrukt
1
int i;
2

3
...
4
    for (i=0;i<256;i++)
5
    {      
6
    ADCMittel=ADCMittel+ADCResult;      //Aufsummieren
7
    }
8
          
9
    if (i=256)

sonst haben, ausser 256?
Die for-Schleife wurde beendet, WEIL i bei der Zählerei den Wert 256 
erreicht hat! Das muss man nicht testen.
Gast #3210723
Lesenswert?

Karl Heinz Buchegger schrieb:
> Welchen Wert soll denn i nach diesem Konstrukt
> ...
> sonst haben, ausser 256?
> Die for-Schleife wurde beendet, WEIL i bei der Zählerei den Wert 256
> erreicht hat! Das muss man nicht testen.

Sebastian Schubert schrieb:
> Ach mist stimmt da muss eigentlich ein == hin... Kein Wunder...
> Danke für die Erleuchtung!

Sorry, aber da musste ich schon ein wenig schmunzeln.

Mal abgesehen davon, dass du "=" und "==" vertauscht hast(passiert jedem 
mal) hat "i" nach dieser for-Schleife immer den Wert 256.
Wahrscheinlich ist der Compiler so intelligent, und optimiert den 
Vergleich mit raus.
Der Code wäre zu jetzigem äquivalent auch ohne if-Abfrage...
OP #3211172
Lesenswert?

Ok also ich werde das Programm jetzt mit der ADC_Read_Avg() nochma neu 
bauen. Das is wirklich das Einfachste und wenn man diesen Ablauf in ein 
ADC.c oderso schreibt kann man den Readout ja auch in zwei Zeilen 
abhaken. Danke Karl Heinz Buchegger =)

Muss auch dazu sagen, dass das mein erstes richtiges Projekt is. Bin 
gerade mit den Gundsachen wie Taster, LED und LCD durch und wollte jetzt 
eben mal was umsetzen.

Also nochma danke an alle Helfer und nen schönen nichtmehr ganz so 
extrem heißen Tag! =)

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