Forum: Mikrocontroller und Digitale Elektronik Berechnung immer Null warum?


von Fabian H. (Firma: keine) (eimer)


Lesenswert?

Hallo Leute,

in meinem Programm möchte ich einen RMS ausrechnen, dazu benutze ich zum 
teilen ein Bitshift und eine fastsqrt die ich aus einem Interrupt 
anspringe. Jetzt kommt aber immer NULL ruas egal was ich mache?
Hoff jemand kann sich das erklären.
1
#include  <msp430x14x.h>
2
#include  <math.h>
3
#include  <inttypes.h>
4
5
unsigned int i=0;
6
unsigned long long int SUM_SIG1,SUM_SIG2,SUM_SIG3,SUMT_SIG1,SUMT_SIG2,SUMT_SIG3;
7
unsigned int RMS_SIG1,RMS_SIG2,RMS_SIG3;
8
unsigned long int MW_SIG1,MW_SIG2,MW_SIG3,Modulus_quadrature;
9
unsigned int Modulus;
10
int Measure;
11
12
static unsigned julery_isqrt(unsigned long val) {
13
      unsigned long temp, g=0, b = 0x8000, bshft = 15;
14
      do {
15
          if ( val >= ( temp = (((g << 1) + b)<<bshft--) ) ) {
16
             g += b;
17
             val -= temp;
18
          }
19
      } while (b >>= 1);
20
      return g;
21
  }
22
23
void main(void)
24
{
25
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
26
  DCOCTL = DCO0 + DCO1 + DCO2;              //Max. CLK
27
  BCSCTL1 |= RSEL0 + RSEL1 + RSEL2;
28
  P4DIR |= 0xFF;                            // P4.0 output
29
  P4OUT=0;                                  //Reset Outputs
30
  //P5SEL |= 0xFF;                          //MCLK Rausführen
31
  P5DIR |= 0xFF;
32
  P5OUT=0;
33
  CCTL0 = CCIE;                             // CCR0 interrupt enabled
34
  CCR0 = 3;                                 //32768/4 =8192
35
  TACTL = TASSEL_1 + MC_1;                  // ACLK, upmode
36
  MW_SIG1=0;
37
  MW_SIG2=0;
38
  MW_SIG3=0;
39
  RMS_SIG1=0;
40
  RMS_SIG2=0;
41
  RMS_SIG3=0;
42
  SUM_SIG1=0;
43
  SUM_SIG2=0;
44
  SUM_SIG3=0;
45
  SUMT_SIG1=0;
46
  SUMT_SIG2=0;
47
  SUMT_SIG3=0;
48
  Modulus_quadrature=0;
49
  Modulus=0;
50
  Modulus_quadrature=0;
51
  Measure=0;
52
  _BIS_SR(LPM0_bits + GIE);                 // Enter LPM0 w/ interrupt I=85uA 
53
  while(1){
54
    if(Measure==1){
55
      P5OUT=0xFF;                //HIER KOMMT IMMER NULL RAUS
56
      MW_SIG1=SUMT_SIG1>>13;                   //Mean of RMS /j=8192 =>2^13
57
      MW_SIG2=SUMT_SIG2>>13;
58
      MW_SIG3=SUMT_SIG3>>13;
59
      RMS_SIG1=julery_isqrt(MW_SIG1);         //sqrt of RMS
60
      RMS_SIG2=julery_isqrt(MW_SIG2);
61
      RMS_SIG3=julery_isqrt(MW_SIG3);
62
      SUMT_SIG1=0;
63
      SUMT_SIG2=0;
64
      SUMT_SIG3=0;
65
      Measure=0;
66
      Modulus_quadrature=RMS_SIG1*RMS_SIG1+RMS_SIG2*RMS_SIG2+RMS_SIG3*RMS_SIG3;
67
      Modulus=julery_isqrt(Modulus_quadrature);
68
      P5OUT=0x00;
69
    }else{}
70
  };
71
}
72
73
// Timer A0 interrupt service routine
74
#pragma vector=TIMERA0_VECTOR
75
__interrupt void Timer_A (void)
76
{
77
  P4OUT ^= 0xFF;                             // Toggle P1.0
78
  P6SEL |= 0x70;                            // Enable A/D channel A0
79
  ADC12CTL0 = ADC12ON+SHT0_0+MSC;           // Turn on ADC12, set sampling time
80
  ADC12CTL1 = ADC12DIV_0+ADC12SSEL_3+CONSEQ_1+SHP;  // Use sampling timer, set mode
81
  ADC12MCTL0 = INCH_4+SREF_0;               // channel = A4
82
  ADC12MCTL1 = INCH_5+SREF_0;               // channel = A5
83
  ADC12MCTL2 = INCH_6+EOS+SREF_0;           // channel = A6
84
  ADC12IE = 0x01;                           // Enable ADC12IFG.6
85
  ADC12CTL0 |= ENC;                         // Enable conversions
86
  ADC12CTL0 |= ADC12SC;                     // Start conversion
87
  i++;
88
}
89
90
#pragma vector=ADC12_VECTOR
91
__interrupt void ADC12ISR (void)
92
{
93
  unsigned long int ADC_SIG1,ADC_SIG2,ADC_SIG3;
94
    //P5OUT=0xFF;
95
    //TACTL = TASSEL_1 + MC_1;        TimerA off
96
  if(i<8192){
97
    ADC_SIG1=ADC12MEM0;
98
    ADC_SIG2=ADC12MEM1;
99
    ADC_SIG3=ADC12MEM2;
100
    SUM_SIG1 += ADC_SIG1 * ADC_SIG1;      //Sum over quadrature
101
    SUM_SIG2 += ADC_SIG2 * ADC_SIG2;
102
    SUM_SIG3 += ADC_SIG3 * ADC_SIG3;
103
104
    //P5OUT=0x00;
105
  }else{
106
    //ADC_SIG1=ADC12MEM0;
107
    SUMT_SIG1=SUM_SIG1;
108
    SUMT_SIG2=SUM_SIG2;
109
    SUMT_SIG3=SUM_SIG3;
110
    SUM_SIG1=0;
111
    SUM_SIG2=0;
112
    SUM_SIG3=0;
113
    Measure=1;              
114
    i=0;
115
    __low_power_mode_off_on_exit();           //I=300uA
116
  }
117
  //P5OUT=0x00;
118
  ADC12CTL0 &= ~ENC;                         // Enable conversions
119
}

von Lehrmann M. (ubimbo)


Lesenswert?

Ich hab gerade nicht die Zeit mir das alles durchzulesen aber dein 
Problem dürfte sich "Typ-Cast" nennen.

Das ist C-Grundwissen:

beispiel

int x=8,y=66;
float erebnis;

ergebnis=x/y

-> ergebnis ist 0 !

von Karl H. (kbuchegg)


Lesenswert?

Fabian Hof schrieb:

> Hoff jemand kann sich das erklären.

Premature Optimization is the root of all evil


Wenn du teilen willst, dann benutz auch eine Division.

Für den unwahrscheinlichen Fall, dass dein Compiler tatsächlich zu 
dämlich ist, eine Division durch eine 2-er Potenz durch eine 
Schiebeoperation zu ersetzen (Multiplikation ist dasselbe), kannst du 
hinten nach immer noch deinen Code zu einem "Obfuscated C Code 
Contest"-Beitrag umwandeln.

Aber zuerst machs richtig, dann machs schnell.

Ansonsten: Eingangswerte ansehen, Zwischenwerte ansehen, nachvollziehen 
was passiert.

von Dennis (Gast)


Lesenswert?

Lehrmann Michael schrieb:
> int x=8,y=66;
> float erebnis;
>
> ergebnis=x/y
>
> -> ergebnis ist 0 !

Jo, das kann gut sein - mindestens ein Beteiligter in der Rechnung muss 
dann ebenfalls ein float sein.

Also:
1
int x = 8;
2
int y = 6;
3
4
float ergebnis;
5
6
ergebnis = (float) x / y;

von Karl H. (kbuchegg)


Lesenswert?

1
volatile int Measure;

Wenn ich deinen Kommentar
1
      P5OUT=0xFF;                //HIER KOMMT IMMER NULL RAUS
wörtlich nehme, dann wird der if Teil nie betreten. Measure volatile 
machen.

von Karl H. (kbuchegg)


Lesenswert?

Hab ich Tomaten auf den Augen, oder wird in
1
#pragma vector=ADC12_VECTOR
2
__interrupt void ADC12ISR (void)
3
{

die Variable i überhaupt nie erhöht?

(i ist aber auch ein selten schlecht gewählter Name für eine globale 
Variable, die die Anzahl der Messungen mitprotokollieren soll. Gewöhn 
dir an: Globale Variablen - nicht weniger als 5 Zeichen im Namen.)

von ... (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> die Variable i überhaupt nie erhöht?

Die wird im Timer-Interrupt erhöht :)
Muß allerdings auch volatile sein.

von Dennis (Gast)


Lesenswert?

Und wenn du sie im Interrupt erhöst, dann kann ein volatile auch nicht 
schaden.

von Dennis (Gast)


Lesenswert?

Fabian Hof schrieb:
>   Modulus_quadrature=0;
>   Modulus=0;
>   Modulus_quadrature=0;
>   Measure=0;

Und welchen Sinn hat das hier?

Außerdem fehlt dir im ADC12CTL1 das CSTARTADD_x Bit, was du bei dir zu 
CSTARTADD_0 setzen musst.


Gruß, Dennis

von Karl H. (kbuchegg)


Lesenswert?

... schrieb:
> Karl heinz Buchegger schrieb:
>> die Variable i überhaupt nie erhöht?
>
> Die wird im Timer-Interrupt erhöht :)

Gefunden.
Ich würd sie trotzdem in den ADC Interrupt verfrachten.

Dann ist die Funktionalität nicht über 25 Funktionen verstreut.

von Fabian Hof (Gast)


Lesenswert?

Leute morgen bin ich wieder an der Hardware dann werd ich alles machen 
was ihr sagt. Ich bedanke mich für die Nacht.

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.