Forum: Mikrocontroller und Digitale Elektronik ADC Mittelwert bilden in C


von el p. (elpistolero84)


Lesenswert?

Hallo Leute,

ich programmiere einen pic18 für die auswertung einer kapazitiven 
tastenfeldes.

um einen genauen ergebnis des adc wertes zu haben wollte ich den 
mittelwert z.b einer 16 messungen bilden. um anschließend mit dem wert 
weiter arbeiten. jedoch habe ich nicht wirklich einen plan wie ich es 
mit C bilden kann.

hier nochmal das programm (dies ist mein zweites programm mit einem µc)

ich würde mich für weitere fragen freuen..

danke und gruss
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <p18lf45k22.h>
4
5
/* Konfiguration */
6
#pragma config FOSC = INTIO67          // Interne Oszillator
7
#pragma config PWRTEN = ON             // Power Up Timer
8
#pragma config BOREN = OFF             // Brown of Reset
9
#pragma config WDTEN = OFF             // Watchdog Timer
10
#pragma config LVP = OFF               // Low Voltage ICSP
11
#pragma config MCLRE = EXTMCLR         // externer MCLR
12
#pragma code
13
14
#define Taste1_Abfrage 0b01000101     // ADCON für AN17 der Taste 1 definiert - 0x45
15
16
#define LED1_Taste1 LATDbits.LATD2    // Ausgang RD2 wird auf LED1_Taste1 übergeben
17
18
#define GODONE ADCON0bits.GO_DONE       
19
20
unsigned int Ergebnis;
21
22
void main(void)
23
{
24
25
  TRISCbits.TRISC5 = 1;   // Taste1 Eingang
26
27
  TRISDbits.TRISD2 = 0;   // LED1 Ausgang
28
29
  ANSELCbits.ANSC5 = 1;   // Analogeingang AN17 für Taste1
30
31
  ADCON1 = 0x80;          // VDD(+3.3V) und VSS(0V) als  
32
33
  ADCON2 = 0xB1;          // Rechtsbündig; 8Tad; FOSC/8 = 500kHz 
34
35
  OSCCON = 0x54;          // Register für die Interne Oszillator
36
37
    
38
    ADCON0 = Taste1_Abfrage;
39
    GODONE = 1;
40
    while(GODONE == 1);
41
42
    Ergebnis = ADRESH;
43
    Ergebnis = Ergebnis <<8;
44
    Ergebnis = Ergebnis + ADRESL; <----hier "Ergebnis" mittelwert bilden
45
46
    if(Ergebnis >= 0x0080)
47
        {
48
            LED1_Taste1 = 1;
49
        }
50
    else
51
        {
52
            LED1_Taste1 = 0;
53
        }
54
55
}

von Michael (Gast)


Lesenswert?

G**gel mal nach "gleitender Mittelwert"

http://www.rn-wissen.de/index.php/Gleitender_Mittelwert_in_C

von Karl H. (kbuchegg)


Lesenswert?

Na ja.

Von EINER Messung wirst du wohl kaum einen Mittelwert machen können. Du 
brauchst schon mehrere Messungen.


Ein µC Programm sieht normalerweise grundsätzlich so aus
1
...
2
3
void main(void)
4
{
5
6
  // Initialisierung und Konfiguration der
7
  // benötigten Hardware Teile
8
9
  // diverse Variablen auf ihren Startwert setzen
10
  // sofern notwendig
11
12
  while( 1 )
13
  {
14
15
    // in dieser Endlosschliefe befindet sich dann
16
    // die eigentliche Logik des Programmes. Also
17
    // das was es zu tun hat
18
19
  }
20
}


In deinem Code vermisse ich die zentrale Endlosschleife! Dein Code wird 
ein einziges mal abgearbeitet und was danach passiert (wenn main() zu 
Ende ist), das wissen nur die Götter.


Also: Du brauchst die zentrale Schleife, in der du immer wieder 
ADC-Messungen machst. Diese verrechnest du so, dass du einen Mittelwert 
bilden kannst. Zb machst du das so, dass du 16 mal misst und die 
Einzelergebnisse aufsummierst. Und nach dem 16-mal messen berechnest du 
aus dieser Summe deinen gewünschten Mittelwert und lässt dann die 
entsprechende Entscheidung treffen (das if). Danach setzt du wieder 
deine Variablen wieder auf 0 zurück, damit die nächsten 16 Messungen 
wieder frisch aufsummiert werden können.

Dein Programm könnte also zb als Programmskizze so aussehen
1
...
2
3
void main(void)
4
{
5
6
  // Initialisierung und Konfiguration der
7
  // benötigten Hardware Teile
8
9
  // diverse Variablen auf ihren Startwert setzen
10
  // sofern notwendig
11
12
  AnzahlMessungen = 0;
13
  SummeMessungen = 0;
14
15
  while( 1 )
16
  {
17
18
    ... eine ADC Messung vornehmen ...
19
20
    SummeMessungen += Ergebnis;
21
    AnzahlMessungen++;
22
23
    if( AnzahlMessungen == 16 )
24
    {
25
      // Berechne Mittelwert
26
      Ergebnis = SummeMessungen / AnzahlMessungen;
27
28
      // und mach was damit
29
      if( Ergebnis >= 128 )
30
        LED1_Taste1 = 1;
31
      else
32
        LED1_Taste1 = 0;
33
34
      // und für den nächsten Messzyklus vorbereiten
35
      SummeMessungen = 0;
36
      AnzahlMessungen = 0;
37
    }
38
  }
39
}

von el p. (elpistolero84)


Lesenswert?

Hallo,

Michael danke für den link..jedoch war es mir etwas zu komplex :) wie 
gesagt ich mache es zum ersten mal..

karl heinz das ist wirklich genial..so einen beitrag kann ich auf jeden 
fall gebrauchen..wie erwähnt dies ist mein zweites programm und daher 
habe ich auch mit einigen fehlenden schleifen gerechnet und daher auch 
das code reinkopiert..ich werde es mal jetzt so ausprobieren..ich hoffe 
das ich es auch dementsprechend einsetzen kann :)

von Michael S. (rbs_phoenix)


Lesenswert?

Karl Heinz Buchegger schrieb:
>   while( 1 )
>   {
>
>     ... eine ADC Messung vornehmen ...
>
>     SummeMessungen += Ergebnis;

Ich hätte da "SummeMessungen += ADRESH;" geschrieben oder? Ergebnis ist 
ja noch das Ergebnis der Addierten Werte / 16.


Mit der genannten Möglichkeit hast du alle 16 Werte einen Mittelwert 
über Diese. Es geht aber auch, dass du über die letzten 16 Werte einen 
Mittelwert bildest, ist allerdings Rechenzeitintensiver:
1
char Messwerte[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
2
3
// Messung..
4
5
Messwerte[15] = Messwerte[14];
6
Messwerte[14] = Messwerte[13];
7
Messwerte[13] = Messwerte[12];
8
Messwerte[12] = Messwerte[11];
9
Messwerte[11] = Messwerte[10];
10
Messwerte[10] = Messwerte[9];
11
Messwerte[9] = Messwerte[8];
12
Messwerte[8] = Messwerte[7];
13
Messwerte[7] = Messwerte[6];
14
Messwerte[6] = Messwerte[5];
15
Messwerte[5] = Messwerte[4];
16
Messwerte[4] = Messwerte[3];
17
Messwerte[3] = Messwerte[2];
18
Messwerte[2] = Messwerte[1];
19
Messwerte[1] = Messwerte[0];
20
21
Messwerte[0] = ADRESH;
22
23
Summe = Messwerte[0] + Messwerte[1] + ... + Messwerte[15];
24
Ergebnis = Summe / 16;
25
26
27
28
// Oder das ganze mit Schleifen:
29
30
// Messung..
31
32
33
34
for(i=15; i>0; i--){
35
  Messwerte[i] = Messwerte[i-1];
36
}
37
Messwerte[0] = ADRESH;
38
39
Summe = 0;
40
for(i=0; i<=15; i++){
41
  Summe += Messwerte[i];
42
}
43
Ergebnis = Summe / 16;

Wenn du die wahl hast, würde ich 2^n Messungen mitteln, sprich 
1,2,4,8,16 usw. Denn wenn du dadurch Teilst, macht der Compiler einen 
Shift draus, die Bits werden also nur verschoben. Wenn du z.B. 10 
Messungen hast, muss er "echt" Teilen und es dauert länger.

von el p. (elpistolero84)


Lesenswert?

hallo,

AnzahlMessungen und SummeMessungen müssten ja auch definiert werden !?

von Michael S. (rbs_phoenix)


Lesenswert?

el pistolero schrieb:
> AnzahlMessungen und SummeMessungen müssten ja auch definiert werden !?

Klar müssen sie das. Genauso wie die Initialisierungen. Du bekommst hier 
Lösungsansätze aber keine komplett fertigen Codes. Du musst also 
überlegen, was für Daten du erwartest.

Für mein Beispiel z.B.:
In Summe werden 16 8bit-Zahlen addiert. Eine 8bit-Zahl kann maximal 255 
sein. Wenn man also 16mal den Maximalen Wert addieren und in Summe 
speichern können soll, dann muss es also mindestens 255*16 fassen 
können, also die Zahl 4080. Char hat 8 bit, kann es somit nicht. int 
(manchmal auch int_16) hat bei Microcontrollern meist 16bit. Damit 
kannst du also die Zahlen von 0 - 65535 speichern (unsigned) oder aber 
-32768 bis +32767 (signed). Es ist also egal ob signed oder nicht, doch 
eine 16bit Variable muss es sein.

Bei Ergebnis wird die Summe durch 16 geteilt. Durch die Überlegung von 
eben heißt also, dass die größte Zahl, die ich haben kann, (also 4080 
druch 16) 255 ist. Somit reicht dafür wieder eine 8bit Variable.

von Karl H. (kbuchegg)


Lesenswert?

el pistolero schrieb:
> hallo,
>
> AnzahlMessungen und SummeMessungen müssten ja auch definiert werden !?

Du brauchst ein C-Buch

Und komm mir jetzt nicht mit der Ausrede, dass das dein 2.tes Programm 
wäre. Für dein 2.tes Programm ist das sowieso schon viel zu heftig.
Das erste Programm ist LED ein/LED aus
Das zweite Programm ist LED blinken
Das dritte Programm ist: Taste drücken -> LED geht an, Taste loslassen 
LED geht aus.
Das vierte Programm ist ...

Das fünfundvierzigste Programm ist: Auswerten eines kapazitiven 
Tastenfelds.

von el p. (elpistolero84)


Lesenswert?

hallo karl heinz,

das erste programm war das ich 12 led zum blinken gebrahct habe :)

und das ist jetzt das zweite programm für eine kapazitive taste..später 
muss ich das ganze auf 12 kapazitive tasten erwaitern..daher möchte ich 
auch die "Ergebnis" auch 'Glätten' für die Störfaktoren...

das code sieht folgendermaßen aus!

wenn ich  if(Ergebnis <= 0x00C8) in der zeile breakpoint setzte(mplabx) 
und debugge und eine zeile drüber also --> Ergebnis = SummeMessungen / 
AnzahlMessungen; mit dem cursor auf "Ergebnis" gehe kann ich den wert 
ablesen. Die Ergebnis lautet 0x0000...das darf doch nicht passieren 
oder????


#include <stdio.h>
#include <stdlib.h>
#include <p18lf45k22.h>

/* Konfiguration */
#pragma config FOSC = INTIO67          // Interne Oszillator
#pragma config PWRTEN = ON             // Power Up Timer
#pragma config BOREN = OFF             // Brown of Reset
#pragma config WDTEN = OFF             // Watchdog Timer
#pragma config LVP = OFF               // Low Voltage ICSP
#pragma config MCLRE = EXTMCLR         // externer MCLR
#pragma code

#define Taste1_Abfrage 0b01000101     // ADCON für AN17 der Taste 1 
definiert - 0x45

#define LED1_Taste1 LATDbits.LATD2    // Ausgang RD2 wird auf 
LED1_Taste1 übergeben

#define GODONE ADCON0bits.GO_DONE

unsigned int Ergebnis;
int SummeMessungen;
int AnzahlMessungen;

void main(void)
{

  TRISCbits.TRISC5 = 1;   // Taste1 Eingang

  TRISDbits.TRISD2 = 0;   // LED1 Ausgang

  ANSELCbits.ANSC5 = 1;   // Analogeingang AN17 für Taste1

  ADCON1 = 0x80;          // VDD(+3.3V) und VSS(0V) als Referenzspannung

  ADCON2 = 0xB1;          // Rechtsbündig; 8Tad; FOSC/8 = 500kHz ADC 
Taktfrequenz

  OSCCON = 0x54;          // Register für die Interne Oszillator


    while(1)
    {
    ADCON0 = Taste1_Abfrage;
    GODONE = 1;

    Ergebnis = ADRESH;
    Ergebnis = Ergebnis <<8;
    Ergebnis = Ergebnis + ADRESL;

    SummeMessungen += Ergebnis;
    AnzahlMessungen++;

        if(AnzahlMessungen == 16)
        {
            Ergebnis = SummeMessungen / AnzahlMessungen;

            if(Ergebnis <= 0x00C8)
            {
                LED1_Taste1 = 1;
            }
            else
            {
            LED1_Taste1 = 0;
            }

            SummeMessungen = 0;
            AnzahlMessungen = 0;
        }
    }
}

von Karl H. (kbuchegg)


Lesenswert?

> Ergebnis = SummeMessungen / AnzahlMessungen;

Und was ist die Summe?
(ANzahl wissen wir, das müsste eigentlich 16 sein)

Dann musst du jetzt eben die Dinge rückwärts verfolgen. Wo kommen, die 
Einzelteile her, wie entstehen sie, welche Werte hatten sie dort. Wie 
sind diese Dinge wiederrum entstanden, etc. etc. So lange bis du die 
Problemstelle gefunden hast, an der die Dinge aus dem Ruder zu laufen 
beginnen.

von Horst H. (horha)


Lesenswert?

Hallo,

Man kan es ja wie in rn-wissen machen.
Die benutzen einen zirkulären Speicher, der älteste Wert wird durch den 
neuesten ersetzt.
Zudem braucht man bei integer-Werten die Summe nicht immer neu zu 
berechnen, sondern nur den ältesten abziehen und den neuesten 
aufsummieren.
1
const int MaxMessAnzahl=16
2
  
3
int idx, GesSumme,GleitenderDurchschnitt;
4
char Messwerte[MaxMessAnzahl] ;
5
6
7
//init
8
idx=0;
9
GesSumme=0;
10
GleitenderDurchschnitt=0;
11
for ( int i = 0,i<MaxMessAnzahl;i++) 
12
  Messwerte[i] = 0;
13
....
14
  
15
//Hauptprogramm
16
while(1) {
17
  GesSumme -= Messwerte[idx];// aeltesten Messwert subtrahieren
18
  Messwerte[idx]= ADRESH;    //<--  neuer Messwert
19
  GesSumme += Messwerte[idx];//  neuesten Messwert addieren
20
  // neuer Index 
21
  idx++;
22
  if (idx >= MaxMessAnzahl)
23
    idx= 0;
24
      
25
  GleitenderDurchschnitt = SummeMessungen / MaxMessAnzahl;
26
  // und mach was damit
27
  if( GleitenderDurchschnitt >= 128 )
28
    LED1_Taste1 = 1;
29
  else
30
    LED1_Taste1 = 0;
31
}

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Horst Hahn schrieb:
> Man kan es ja wie in rn-wissen machen.
Haben die auch das Rad erfunden?
So ein Ringpuffer ist ein uralter Hut aus dem letzten Jahrtausend. Der 
findet sich dann als Beispiel für Zeigeroperationen auch in jedem 
brauchbaren C-Buch...

von Karl H. (kbuchegg)


Lesenswert?

Horst Hahn schrieb:
> Hallo,
>
> Man kan es ja wie in rn-wissen machen.
> Die benutzen einen zirkulären Speicher, der älteste Wert wird durch den
> neuesten ersetzt.

Gemach, gemach.
Er hat noch ganz andere Probleme.
Lass ihn erst mal gehen lernen, ehe du ihm die Diretissima durch die 
Dolomiten zeigst.


Jetzt soll er erst mal den Fehler in der ADC Abfrage suchen, den er 
unabsichtlich eingebaut hat.

von el p. (elpistolero84)


Lesenswert?

hallo,

der code was von dem hersteller vorgegeben ist sieht folgendermaßen aus! 
ich muss es für die obere single button anwendung i.wie umschreiben! und 
anschließend eine mittelwert der ergebnis bilden. die vorschläge für die 
mittelwert bildung sehen brauchbar aus. jedoch muss die auswertung erst 
einmal funktionieren...

// Port initialization
ANSEL = 0b01010000; // A/D-clock 2uS, all pins are digital
PORTA = 0b00000000;// all pins are low (output)
TRISA = 0b00001000; // everything is output,except RA3 (MCLR)
// Reading the sensor
TRISA |= 0b00000001; // sensor 1 pin becomes input (RA0)
ADCON0 = 0b10000001; // select A/D-channel 0 (CVD happens here)
GODONE = 1; // start the conversion
TRISA &= 0b11111110; // sensor 1 pin becomes output again

von Karl H. (kbuchegg)


Lesenswert?

el pistolero schrieb:
> hallo,
>
> der code was von dem hersteller vorgegeben ist sieht folgendermaßen aus!
> ich muss es für die obere single button anwendung i.wie umschreiben! und
> anschließend eine mittelwert der ergebnis bilden. die vorschläge für die
> mittelwert bildung sehen brauchbar aus. jedoch muss die auswertung erst
> einmal funktionieren...

Nö.
Du musst nur verstehen was da eigenlich passiert und den Code korrekt 
kopieren. Vergleich dein erstes Posting mit deinem letzten und such nach 
den Unterschieden. Und dann überleg, was dieser Unterschied wohl für 
Auswirkungen haben wird.

von Wolfgang (Gast)


Lesenswert?

Lothar Miller schrieb:
> So ein Ringpuffer ist ein uralter Hut aus dem letzten Jahrtausend. Der
> findet sich dann als Beispiel für Zeigeroperationen auch in jedem
> brauchbaren C-Buch...

Nachteil vom Ringpuffer ist der je nach Mittelungsbreite nicht 
unerhebliche Speicherbedarf. Normalerweise tut's ein IIR-Filter, z.B.
1
  Summe  := Summe + Messwert - Mittel
2
  Mittel := Summe / 16
Das benötigt nur einen zusätzlichen Speicher für den Summenwert.

von el p. (elpistolero84)


Lesenswert?

Hallo nochmals an alle,

ich habe das problem was ich mit dem "Ergebnis = 0x0000" hatte bereits 
gelöst. es funktioniert soweit sehr gut. sodass ich mit 12 tasten, 12 
leds zum leuchten bringe.

als nächstes werde ich wie oben erwähnt eine mittelwert der adc werte 
bilden. jedoch weiss ich nicht wie ich es am besten machen könnte. die 
oben genannten ideen konnte ich hier nicht einbauen bzw wusste nicht wie 
ich es machen soll !? :)

für weitere hilfen bin ich euch sehr dankbar

hier das code


ADCON2 habe ich TOSC = 125kHz(4MHz/32) Kondensatorladezeit = 8TAD(64us)
kann ich hier auch anders takten? z.B TOSC = 500kHz und 
Kondensatorladezeit(acquisition time)= 2TAD(4us) ???????????
1
void main(void)
2
{
3
4
    Initialisierung();                  // Initialisierung wird fortgesetzt
5
6
    do
7
    {
8
9
        Taste1();
10
        Taste2();
11
12
    }while(1);
13
14
}
15
16
17
void Vreferenz(void)
18
{
19
    // In dieser Funktion wird der Sample&Hold Kondensator aufgeladen //
20
21
    ADCON0 = 0b01111101;    // Vref Referenzspannung
22
    GODONE =1;
23
    while(GODONE == 1);
24
}
25
26
void Taste1(void)
27
{
28
    unsigned int Ergebnis;      // Dekleration Ergebnis
29
    unsigned int AnzahlMessungen;
30
31
32
    Vreferenz();                // Aufruf der Funktion Vreferenz()
33
                                //
34
35
    TRISCbits.TRISC5 = 1;       // Taste1 als Eingang gewählt
36
37
    //for(AnzahlMessungen = 1; AnzahlMessungen <= 16; AnzahlMessungen++)
38
    //{
39
    ADCON0 = 0b01000101;        // AN17 Eingang Taste1 Abfrage
40
    GODONE = 1;                 // Umwandlung wird gestartet
41
    while(GODONE == 1);
42
43
    Ergebnis = Ergb();          // Taste ungedrückt Wert von Ergebnis = 0x016B 
44
    //}
45
46
    if(Ergebnis <= 0x0163)      // Schwellwert
47
    {
48
        LED1 = 1;        // LED1 geht an
49
    }
50
    else
51
    {
52
        LED1 = 0;        // LED1 geht nicht an
53
    }
54
55
    TRISCbits.TRISC5 = 0;       // Taste1 wieder als Ausgang
56
}
57
58
void Taste2(void)
59
{
60
    unsigned int Ergebnis;
61
62
    Vreferenz();
63
64
    TRISDbits.TRISD5 = 1;     // Als Eingang
65
66
    ADCON0 = 0b01100101;     // AN18 Eingang Taste2 Abfrage
67
    GODONE = 1;              // Umwandlung wird gestartet
68
    while(GODONE == 1);      
69
70
    Ergebnis = Ergb();
71
72
    if(Ergebnis <= 0x0160) // Schwellwert
73
    {
74
        LED2 = 1;          // LED geht an
75
    }
76
    else
77
    {
78
        LED2 = 0;          // LED geht aus
79
    }
80
81
    TRISDbits.TRISD5 = 0;    // Wieder als Ausgang
82
}
83
84
unsigned int Ergb(void)
85
{
86
    unsigned int Ergebnis;          // Dekleration Ergebnis
87
88
    Ergebnis = ADRESH;              // Die Wert in dem Register ADRESH 
89
    Ergebnis = Ergebnis << 8;       // Ergebnis wird um 8 bit von rechts 
90
    Ergebnis = Ergebnis + ADRESL;   // Die Wert in dem Register ADRESL 
91
92
    
93
    return Ergebnis;                // Ergebnis wird weitergegeben
94
    Ergebnis = 0;                   // Ergebnis wieder auf Null gesetzt
95
}

von el p. (elpistolero84)


Angehängte Dateien:

Lesenswert?

Hallo nochmals,

ich habe eine Gleitende Mittelwert gebildet! Mit dem C-Code(siehe 
Anhang) die auf der Seite RN-WISSEN ist.

Ich habe es auch zum laufen gebracht, sodass ich die 16 Werte abfangen 
kann.

Weiss jetzt leider nicht wie ich es mit der unteren if Anweisung bzw mit 
dem Schwellwert Regeln könnte !? Die LED soll ja leuchten beim Betätigen 
auf die Taste, dass heißt beim Betätigen auf die Taste wird die Spannung 
geringer(also unter 0x0160).Das Problem ist: Die Spannung fällt auch 
Automatisch darunter wenn sich die z.B. die Temperatur verändert!

Meine Frage ist, wie kann ich eine Tastenbetätigung erkennen, wenn sich 
die Temperatur verändert ???

el pistolero schrieb:
> if(Ergebnis <= 0x0160) // Schwellwert
>
>     {
>
>         LED2 = 1;          // LED geht an
>
>     }
>
>     else
>
>     {
>
>         LED2 = 0;          // LED geht aus
>
>     }

von pompete (Gast)


Lesenswert?

el pistolero schrieb:
> Meine Frage ist, wie kann ich eine Tastenbetätigung erkennen, wenn sich
> die Temperatur verändert ???

...gleitender Mittelwert als Langzeitwert....damit folgst du langsam dem 
Drift durch die Temperaturänderung und kompensierst diesen....

von el p. (elpistolero84)


Lesenswert?

pompete schrieb:
> ...gleitender Mittelwert als Langzeitwert....damit folgst du langsam dem
>
> Drift durch die Temperaturänderung und kompensierst diesen....

Kann mir das einer etwas Ausführlicher erklären !? :)

Mfg

von Karl H. (kbuchegg)


Lesenswert?

el pistolero schrieb:
> pompete schrieb:
>> ...gleitender Mittelwert als Langzeitwert....damit folgst du langsam dem
>>
>> Drift durch die Temperaturänderung und kompensierst diesen....
>
> Kann mir das einer etwas Ausführlicher erklären !? :)

Temperaturänderungen sind selten instantan.
Soll heißen: die geschehen langsam!

Drückst du aber auf die Taste, dann ist das ein schneller Vorgang.

d.h. dein Schwellwert, den du zur UNterscheidung benutzt kann nicht eine 
fixe Zahl sein, sondern ist zb ein laaaaaaaanger Mittelwert aus der 
Vergangenheit.


Denk dir was aus! Das ist doch der halbe Spass in der Programmierung - 
sich was ausdenken, es implementieren und nachsehen ob man richtig 
gedacht hat.

von el p. (elpistolero84)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Temperaturänderungen sind selten instantan.
>
> Soll heißen: die geschehen langsam!
>
>
>
> Drückst du aber auf die Taste, dann ist das ein schneller Vorgang

Ist Logisch! Was könnt ihr mir für den dynamischen Schwellwert 
empfehlen? Bzw wie kann ich es implementieren?

Den Gleitenden Mittelwert habe ich als "Ausgang" implementiert!

if(Ausgang < Schwellwert) ... ?

vorher war es ja so gewesen!

el pistolero schrieb:
>> if(Ergebnis <= 0x0160) // Ergebnis->ADCwert und 0x0160->Schwellwert
>
>>
>
>>     {
>
>>
>
>>         LED2 = 1;          // LED geht an
>
>>
>
>>     }
>
>>
>
>>     else
>
>>
>
>>     {
>
>>
>
>>         LED2 = 0;          // LED geht aus
>
>>
>
>>     }

von el p. (elpistolero84)


Lesenswert?

Hallo,

es ist mir was eingefallen ! kann das vllcht so funktionieren ?


for(AnzahlMessungen=0; AnzahlMessungen < SIZE_OF_AVG; AnzahlMessungen++) 
//Gleitende Mittelwertbildung der ADC Werte
    {

        Vreferenz();

        TRISCbits.TRISC5 = 1;       // Taste1 als Eingang gewählt

        ADCON0 = Taste1_Abfrage;    // AN17 Eingang

        Ergebnis = Ergb();          //


        TRISCbits.TRISC5 = 0;       // Taste1 wieder als Ausgang bzw.


        // hier werden die Ergebnisse summiert
        NeuWertSchreiben(&zeigerAvgFilter, Ergebnis);
    }
     // hier ist der gefilterten wert also Ausgang
     Ausgang = BerechneAusgangswert(&zeigerAvgFilter);

     if( Ergebnis <= Ausgang) /*Ergebnis aktueller wert!? Ausgang ist 
Gleitender Mittelwert */
        {
             LED = ON;
        }
        else
        {
            /* LED = OFF;
        }

von el p. (elpistolero84)


Lesenswert?

Ein durchlauf des Programmes dauert ca 50us, das heißt wenn ich eine 
Gleitende Mittelwertbildung von 60s haben möchte, muss ich das ganze 
60s/50us= 1.200.000 mal laufen lassen.

Wenn der aktuelle Wert des ADC Wandler, kleiner als der Gleitende 
Mittelwert ist wird eine Tastendruck erkannt!? Ist dasselbe was ihr da 
meint????

Oder was schlägt ihr mir da vor?

Gruss

von el p. (elpistolero84)


Lesenswert?

Kann mir wirklich keiner weiterhelfen?

von Karl H. (kbuchegg)


Lesenswert?

Ich finde:
Schön langsam wirds Zeit, dass du selbst auch irgendwas tust.

2 Mittelwerte:

Einer der laaange Messwertintervalle in der Vergangenheit zusammenfasst. 
Der reagiert auf Veränderungen in der Temperatur. Die Veränderung durch 
einen Tastendruck wird hingegen diesen Mittelwert nicht sonderlich 
verändern.

Einer der nur die letzten Paar Messwerte zusammenfasst und nur das 
Schwanken am Pin etwas begradigen soll.
Der reagiert zwar auch auf die Temperatur aber er reagiert auch auf 
einen Tastendruck.

In 0-stellung sind beide MIttelwerte gleich oder nahezu gleich. Bei 
Temperaturänderungen (die langsam erfolgen) folgen beide Mittelwerte 
mehr oder weniger parallel dieser Änderung. Bei einem Tastendruck 
hingegen, reagiert der kurze MIttelwert sofort und die beiden 
Mittelwerte laufen auch sofort extrem auseinander.

Soweit die Idee, mit der ich es probieren würde.

von el p. (elpistolero84)


Lesenswert?

Hallo Karl,

danke für deine Antwort.. ich werde es mal ausprobieren :)

gruss

von pompete (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Ich finde:
> Schön langsam wirds Zeit, dass du selbst auch irgendwas tust.

el pistolero schrieb:
> Hallo Karl,
>
> danke für deine Antwort..

...wie gut das es den Karl Heinz gibt, ihm geht die puste irgendwie nie 
aus ;-)

von el p. (elpistolero84)


Lesenswert?

pompete schrieb:
> ...wie gut das es den Karl Heinz gibt, ihm geht die puste irgendwie nie
>
> aus ;-)

das kannst du laut sagen :)

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.