Forum: Mikrocontroller und Digitale Elektronik Effektivwert berechnen


von Mehdi M. (med)


Lesenswert?

hallo,
Ich versuche gerade der Effektivwert im Bezug auf Mittelwert zu 
berechnen, komme leider nicht weiter, programm laüft auch nicht

Ich habe den folgenden Formal benutzt
 Effektivwert= (1/N-1)[sum of squares-(sum^2)/N]
Das ist gerade mein Programm

#define sqrt

void main()
   {
    int16 value[100],mittel,min,max,Effwert;
    unsigned int16 sum,sumQ;
    int i ;


    setup_adc_ports(AN0_TO_AN1|VSS_VDD);
    setup_adc(ADC_CLOCK_DIV_4|ADC_TAD_MUL_16);
    setup_spi(SPI_SS_DISABLED);
    setup_wdt(WDT_OFF);
    setup_timer_0(RTCC_INTERNAL);
    setup_timer_1(T1_DISABLED);
    setup_timer_2(T2_DISABLED,0,1);
    setup_comparator(NC_NC_NC_NC);
    setup_vref(FALSE);

   while(1)
   {
    if(input(pin_b1)==1)
     {
      for (i=0;i<1;i++)
       {
         set_adc_channel(1);

           for (i=0;i<100;i++)
               {
                 value[i]=read_adc();
                 delay_us(500);
               }
                sum=0;

                 for(i=0;i<100;i++)
                  {
                    sum=sum+value[i];
                    sumQ=sumQ+value[i]^2;
                  }
                  mittel=sum/100;

                     sumQ=0;
                     for(i=0;i<100;i++)
                         { if (i=1)
                             Effwert=0;
                           else
                             Effwert=sqrt (sumQ-(sum^2/i))/(i-1);
                         }
                             min=value[0];
                             max=value[0];

                             for(i=0;i<100;i++)
                              {
                                if (value[i]>max)
                                    max=value[i];
                                if (value[i]<min)
                                    min=value[i];
                              }

         }
                                for(i=0;i<100;i++)

                                    printf("%Li\n", value[i]);
                                    printf("mittelwert %li\n", mittel);
                                    printf("min %Li\n", min);
                                    printf("max %Li\n", max);
                                    printf("Summe %Lu\n", sum);
                                    printf("summeQuadrat %Lu\n",sumQ);
                                    printf("Effektivwert 
%Li\n",Effwert);



   }
  }
 }

von Kai G. (runtimeterror)


Lesenswert?

>Ich versuche gerade der Effektivwert im Bezug auf Mittelwert zu
>berechnen, komme leider nicht weiter, programm laüft auch nicht

Was heißt "läuft nicht"?
- Compiliert nicht? Welche Fehlermeldung?
- Falsche Ergebnisse? Welche?
- Absturz?

Welche Architektur?
Verpass deinem Code bei der Gelegenheit noch ein paar Kommentarzeilen - 
das ist im Moment unnötig schwer zu lesen!

von Karl H. (kbuchegg)


Lesenswert?

Eine Frage:

Was, um Himmels willen, hast du dir dabei gedacht?

>
> #define sqrt
>

Du weist schon, dass du damit deine Wurzel Operation
effektiv auf eine 'Tu nichts' Operation umdefiniert hast?

Wenn dein Compiler wegen der sqrt Funktion gemault hat
dann ist die Lösung dafür math.h zu inkludieren und nicht
den Funktionsaufruf auszuhebeln.

von Benedikt K. (benedikt)


Lesenswert?

Der Code kompiliert mit Sicherheit nicht. Und wenn doch, dann ist immer 
noch einiges falsch, wie z.B. #define sqrt ohne was dahinter. ^2 hat in 
C auch eine andere Bedeutung. Dann noch das Thema Überlauf usw.

von med (Gast)


Lesenswert?

Compilieren tut er schon .nun keine Ergebnisse
#define sqrt

void main()
   {
    int16 value[100],mittel,min,max,Effwert;
    unsigned int16 sum,sumQ;
    int i ;


    setup_adc_ports(AN0_TO_AN1|VSS_VDD);
    setup_adc(ADC_CLOCK_DIV_4|ADC_TAD_MUL_16);
    setup_spi(SPI_SS_DISABLED);
    setup_wdt(WDT_OFF);
    setup_timer_0(RTCC_INTERNAL);
    setup_timer_1(T1_DISABLED);
    setup_timer_2(T2_DISABLED,0,1);
    setup_comparator(NC_NC_NC_NC);
    setup_vref(FALSE);

   while(1)
   {
    if(input(pin_b1)==1)  // vom Kanal 1 einlesen
     {
      for (i=0;i<1;i++)
       {
         set_adc_channel(1);

           for (i=0;i<100;i++)
               {
                 value[i]=read_adc();    //Werte einlesen
                 delay_us(500);
               }
                sum=0;

                 for(i=0;i<100;i++)
                  {
                    sum=sum+value[i];    // Summe bilden
                    sumQ=sumQ+value[i]^2;  //Summe Quadrat bilden
                  }
                  mittel=sum/100;

                     sumQ=0;
                     for(i=0;i<100;i++)
                         { if (i=1)
                             Effwert=0;
                           else
                             Effwert=sqrt (sumQ-(sum^2/i))/(i-1);  // 
Effektivwert oder Standard Abweichung bilden
                         }
                             min=value[0];
                             max=value[0];

                             for(i=0;i<100;i++)
                              {
                                if (value[i]>max)    //Min und Max 
suchen
                                    max=value[i];
                                if (value[i]<min)
                                    min=value[i];
                              }

         }
                                for(i=0;i<100;i++)

                                    printf("%Li\n", value[i]);
                                    printf("mittelwert %li\n", mittel);
                                    printf("min %Li\n", min);
                                    printf("max %Li\n", max);
                                    printf("Summe %Lu\n", sum);
                                    printf("summeQuadrat %Lu\n",sumQ);
                                    printf("Effektivwert 
%Li\n",Effwert);



   }
  }
 }

von med (Gast)


Lesenswert?

#include math.h
 er erkennt die sqrt () einfach nicht

von Karl H. (kbuchegg)


Lesenswert?

med wrote:
> Compilieren tut er schon

So wie du ihn gepostet hast: Nein
int16 ist kein Standard Datentyp, damit das klappt muss irgendein
Include vorausgehen, der int16 definiert. Die includes hast du aber
nicht gezeigt.

Aber abgesehen davon: Ob ein Code compiliert oder nicht, sagt nichts
darüber aus, ob die Logik stimmt. Der Compiler überprüft, ob dein
Code die Sprachregeln erfüllt. Für die Logik ist immer noch
der Programmierer zuständig.

"Ich esse den Lastwagen mit einem Fernrohr."
ist auch ein gültiger deutscher Satz, dadurch dass er die Grammatik-
regeln erfüllt. Sinn macht er trotzdem nicht.

von Karl H. (kbuchegg)


Lesenswert?

med wrote:
> #include math.h

#include <math.h>

und der
#define sqrt
muss natürlich raus.

>  er erkennt die sqrt () einfach nicht

Vielleicht hat dein Compiler keine sqrt() Funktion in der math.h
eingetragen? Bei µC Systemen kommt das schon mal vor.

Häng doch mal dein komplettes File hier an.

PS: Wie weiter oben schon gesagt wurde: ^ ist nicht die Potenz
Funktion. ^ macht etwas völlig anderes (bitweises XOR).

Wenn du ein Qudrat haben willst, dann ist die einfachste Variante
einfach x*x zu rechnen.

von med (Gast)


Lesenswert?

Ich bin auch nicht sicher ob er der Effektivwert so berechnen kann.

von Karl H. (kbuchegg)


Lesenswert?

>                     for(i=0;i<100;i++)
>                         { if (i=1)

Ich glaube nicht, dass du hier eine Zuweisung haben willst.
Du willst mit Sicherheit einen Vergleich

                          { if (i == 1 )

und so wie die Logik in diesem Programmteil läuft, möchtest du
auch nicht auf 1 vergleichen, sondern auf 0

                          { if (i == 0 )


Ich rate dir, dir einen PC Compiler zuzulegen. Damit kannst
du Funktionalitäten erst mal auf dem PC testen, ehe du sie
in dein µC Programm einbaust. Der Vorteil: Auf einem PC hast
du einen wesentlich besseren Debugger mit dem du deinem
Programm, während es läuft, auf die Finger schauen kannst
und nachvollziehen kannst, was den so im Programm passiert.

von med (Gast)


Lesenswert?

Das ist einfach zu vermeiden wenn  i=1

von Karl H. (kbuchegg)


Lesenswert?

med wrote:
> Ich bin auch nicht sicher ob er der Effektivwert so berechnen kann.

Das glaube ich allerdings auch nicht.
Vor allen Dingen frage ich mich, warum du den Effektivwert 100 mal
(mit jeweils einem anderen i) berechnest. Der Effektivwert hängt
doch nicht vom i ab. Du hast 100 Messwerte und von diesen 100
Messwerten berechnest du einmal den Effektivwert.

von med (Gast)


Lesenswert?

Ich  probiere es gerade auf meinem Pic 18F2620 und benutze dafür ein CCS 
compiler. Normalerweise muss er die 100 werte ausgeben , dann 
Mittelwert, summe ,min ,max, summequadrat und effektivwert

von Karl H. (kbuchegg)


Lesenswert?

med wrote:
> Das ist einfach zu vermeiden wenn  i=1

Gewöhn dir schleunigst an, einen Unterschied zwischen Zuweisung
und Vergleich zu machen.
Eine Zuweisung schreibt sich in C mit einem '='.
Ein Vergleich auf Gleichheit schreibt sich in C mit 2 '=', also als '=='

    if( i = 1 )

ist nicht dasselbe wie

    if( i == 1 )


OK, das hab ich verbockt. In der Division steht dann i - 1
und damit da nicht durch 0 dividiert wird, machst du für
i gleich 1 eine Sonderbehandlung.

Ändert aber nichts an der Tatsache, dass deine Berechnung eigentlich
nicht für alle i von 0 bis 99 gemacht werden muss. Das N in deiner
urspünglichen Formel ist die Anzahl der Messwerte, und die ist bei
dir 100. Die ist immer 100, egal welchen Wert i gerade hat.
Und damit braucht diese Berechnung auch nicht in der for-Schleife
gemacht werden, sondern sie muss nur ein einziges mal gemacht
werden!

von Karl H. (kbuchegg)


Lesenswert?

Was ist eigentlich aus der schönen Einrückung geworden, die ich dir
in einem anderen Post gezeigt habe. Damals hast du selbst
gesagt, dass das um einiges übersichtlicher ist.

Und jetzt kommst du wieder mit demselben Scheiss!
Glaub es endlich: Mit deiner unsystematischen Einrückerei
schiesst du dir selbst ins Bein, weil du nicht mehr erkennen
kannst, welche Programmteile unter der Kontrolle welcher Schleife
stehen! Und damit platzierst du Berechnungen (auf gut Glück)
an Programmstellen, wo sie nicht hingehören.

von med (Gast)


Lesenswert?

Ich habe das Programm natürlich probiert , das Problem lag es daran 
später dass er mir nur 99 werte ausgibst und manchmal auch 98 werte

von med (Gast)


Lesenswert?

könnte mir villeicht jemand helfen, komme ich nicht weiter!!
SummeQuarat stimmt nicht
Effektivwert stimmmt auch nicht

#define NR_VALUES 100
#include <math.h>

int16 value[NR_VALUES];
int16 mittel,min, max,Effwert ;
unsigned int16 sum, sumQ;

void SetupHardware()
{
  setup_adc_ports(AN0_TO_AN1|VSS_VDD);
  setup_adc(ADC_CLOCK_DIV_4|ADC_TAD_MUL_16);
  setup_spi(SPI_SS_DISABLED);
  setup_wdt(WDT_OFF);
  setup_timer_0(RTCC_INTERNAL);
  setup_timer_1(T1_DISABLED);
  setup_timer_2(T2_DISABLED,0,1);
  setup_comparator(NC_NC_NC_NC);
  setup_vref(FALSE);
}

void ReadValues()
{
  int16 i;


  set_adc_channel( 1 );
  for( i = 0; i < NR_VALUES; i++ )
  {
    value[i] = read_adc();
    delay_us( 500 );
  }
}

void BerechneMittel()
{

  int16 i;


  sum = 0;
  for( i = 0; i < NR_VALUES; i++ )
  sum = sum + value[i];
  mittel = sum / NR_VALUES;
}
void BerechneEffektiv()
{
  int16 i;

  sumQ=0;
  for(i=0;i<NR_VAlUES;i++)
  sumQ=sumQ+(value[i]*value[i]);
  Effwert=sqrt(sumQ-((sum*sum)/NR_VALUES))/(NR_VALUES-1);
}

void BerechneMinMax()
{
  int16 i;

  min = value[0];
  max = value[0];

  for( i = 0; i < NR_VALUES; i++ )
  {
    if( value[i] > max )
      max = value[i];

    if( value[i] < min )
      min = value[i];
  }
}

void PrintErgebnisse()
{
  int16 i;


  for( i = 0; i < NR_VALUES; i++ )
  printf("%Li\n", value[i]);
  printf( "mittelwert %li\n", mittel );
  printf( "min %Li\n", min );
  printf( "max %Li\n", max );
  printf( "Summe %Lu\n", sum );
  printf( "SummeQuadrat %Lu\n",sumQ);
  printf( "Effektivwert %Lu\n",Effwert);

}

  void main()
  {

  int i;

  SetupHardware();

  while( 1 )
  {
    if( input( pin_b1 ) == 1 )
    {
      ReadValues();
      BerechneMittel();
      BerechneEffektiv();
      BerechneMinMax();
      PrintErgebnisse();
    }
  }
}
Ausgabe lautet:
550
550
549
550
548
546
546
546
547
546
546
546
547
545
546
543
546
542
543
543
542
541
541
540
539
539
538
538
538
537
537
536
536
535
535
535
535
534
533
533
530
531
531
530
530
530
529
528
528
527
527
527
526
526
526
525
524
523
524
523
522
521
521
520
520
519
519
519
519
518
515
515
514
516
515
515
514
509
512
512
510
509
508
508
507
506
507
506
505
505
504
504
504
504
503
503
503
503
502
mittelwert 526
min 502
max 550
Summe 52679
SummeQuadrat 55369
Effektivwert 2

von Karl H. (kbuchegg)


Lesenswert?

Dein 1. Messwert ist beispielsweise 550
In der Effektivwert Funktion berechnest du 550*550
Das ergibt 302500. Bei einem 16 Bit unsigned int ist aber
bei 65535 Schluss.
Du musst die Berechnung auf int32 hochziehen.
1
unsigned int16 sum
2
unsigned int32 sumQ;
3
4
....
5
6
void BerechneEffektiv()
7
{
8
  int16 i;
9
10
  sumQ = 0;
11
  for(i = 0; i < NR_VAlUES; i++ )
12
    sumQ = sumQ + ( ((unsigned int32)value[i]) * value[i] );
13
14
  Effwert = sqrt( sumQ - (( ((unsigned int32)sum)*sum)/NR_VALUES))/(NR_VALUES-1);
15
}

PS: Übrigens hast du bei deiner normalen Summe grosses Glück, dass
sich das vom Wertebereich her noch ausgeht. Wenn deine Zahlen einmal
ein klein wenig höher sind, dann passiert dir in sum genau
das Gleiche. ADC Werte können bis 1024 hoch gehen. Du hast 100
Werte, das heist die höchste Summe die möglich ist, lautet
100 * 1024 = 102400. Und auch das liegt über dem was ein unsigned
int16 zu speichern vermag (65535)

von med (Gast)


Lesenswert?

Wie sieht es aus wenn ich float benutze, ich habe es schon mal 
ausprobiert
da kommt aber immer ein negatives wert raus

von med (Gast)


Lesenswert?

sumQ = sumQ + ( ((unsigned int32)value[i]) * value[i] );

 Effwert = sqrt( sumQ - (( ((unsigned 
int32)sum)*sum)/NR_VALUES))/(NR_VALUES-1);

kann ich unsigned int32 oben mit dem variablen deklarieren?

Effektivwert ist leider auch gleich geblieben(1)

von Karl H. (kbuchegg)


Lesenswert?

med wrote:

> kann ich unsigned int32 oben mit dem variablen deklarieren?

> sumQ = sumQ + ( ((unsigned int32)value[i]) * value[i] );
                       |
das hier --------------+
ist ein cast. Er wandelt den value[i] auf 32 Bits hoch, damit
die Multiplikation nicht als 16 Bit Multiplikation sondern als
32 Bit Multiplikation ausgeführt wird.

Und sumQ solltest do sowieso als   unsigned int32  definieren,
so wie ich das in der Codekorrektur gemacht habe.

>
>  Effwert = sqrt( sumQ - (( ((unsigned
> int32)sum)*sum)/NR_VALUES))/(NR_VALUES-1);

Hier ist es das Einfachste und auch das Vernünftigste, wenn du
sum ebenfalls als unsigned int32 definierst. Dann brauchst du
hier keine castings und kannst ganz normal schreiben

   Effwert = sqrt( sumQ - ( (sum*sum)/NR_VALUES))/(NR_VALUES-1);

Dadurch dass sum dann ein unsigned int32 ist, wird diese Multiplikation
sowieso immer als 32-Bit Multiplikation ausgeführt.


unsigned int32 sum, sumQ;

von med (Gast)


Lesenswert?

Mein Problem  liegt jetzt an der Effektivwert , welche variable typ 
werde ich am besten benutzen um ein vernünftiges ergebnis zu haben

von Karl H. (kbuchegg)


Lesenswert?

int16 ist doch ok.

PS: Hast du drann gedacht, dass die Formatangaben in deinen printf
für die unsigned int32 angepasst werden müssen?

von pcbfreak (Gast)


Lesenswert?

kleiner Tip: es heißt den oder dem Effektivwert.

>>Ich versuche gerade den Effektivwert im Bezug auf...
>>0Mein Problem  liegt jetzt an dem Effektivwert...

Warum benutzt du nicht den Debugger oder Simulator,
da kannste Schritt für Schritt sehen was dein Programm macht.

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.