Forum: Mikrocontroller und Digitale Elektronik MSP430 Sprünge bei Erfassung mit ADC12


von Martin S. (martins)


Lesenswert?

Hallo,

ich erfasse mit dem MSP430F169 eine Spannung zwischen 0,6 und 2,2V 
(Externe Referenz liegt an eREF+ und VeREF-)
Die Messspannung ist an P6.5 / A5 angelegt

Den gemessenen Wert zwischen 0 und 4095 gebe ich auf einem Display aus, 
bzw betrachte ihn im Debugger.

Bei einer langsamen Änderung der Eingangsspannung kann ich nicht alle 
Werte erfassen, es gibt Sprünge im Messwert.

Hier ein Auszug, welche Messwerte möglich sind.
Diese Werte werden durch langsames erhöhen der Eingangsspannung 
angezeigt.
1571  011000100011
1603  011001000011
1619  011001010011
2051  100000000011
2083  100000100011
2115  100001000011
2131  100001010011
2155  100001101011
2259  100011010011
2339  100100100011

Auch beim Debuggen und beobachten des ADC12MEM0 bekomme ich genau diese 
Werte angezeigt.
Es fällt auf, dass immer die letzten 3 Binärstellen "011" sind.
Ich schaffe es also nicht, irgendeinen Zwischenwert bei den obigen 
Messwerten einzustellen. Dieses Problem zieht sich über den gesamten 
Messbereich hin.




Hier mein Code:
Erst mal die Initialisierung...
1
ADinternInit()  //Grundeinstellung AD-Wandler
2
{
3
    ADC12CTL0 = ADC12ON + SHT0_0 + REFON;   // ADC12ON:ADC in Bereitschaft
4
                                  // REFON zwar eingeschaltet, aber nicht verwendet, da externe Spannung ADC12 anschalten,
5
  ADC12CTL1 = SHP;            // Sampling Timer benutzen  (SHP = Sample-and-hold-pulse) Einstellungen werden automatisch vorgenommen
6
            // -----------------------------
7
            // ADC12MCTL0 steuert ADC12MEM0. Das Conversion-Ergebnis steht im 16Bit-Register ADC12MEM0.
8
            // Die führenden 4 Bit sind "0"
9
  ADC12MCTL0 = SREF_6 + INCH_5;    // SREF_6: Referenzspannung einstellen: Verwendet wird: Extern: VeREF+ und Extern: VeREF-
10
                                   // INCH=Input Channel A0 bis A11. Gewählt: P6.5 = A5
11
  ADC12CTL0 |= ENC;       // jetzt anfangen ...   Enable Conversion muß HIGH sein um zu starten
12
13
}

Hier der Aufruf im Programm:
1
int temperaturmessung()
2
{
3
        extern int ADCkty;                  // Die externe Variable ADCkty verwenden
4
        ADC12CTL0 |= ADC12SC;               // Konvertierung durchfuehren
5
        while ((ADC12IFG & BIT0)==0)        // Wenn das Bit 0 auf 1 geht, dann ist ein Wert in ADC12MEM0 geschrieben worden.
6
        {};                                  //warten....
7
        ADCkty=ADC12MEM0;                   // ADCkty den Wert zuweisen(Bereich von 0 bis 4095)
8
}


Da die Messung zeilich nicht kritisch ist, verwende ich keine 
Interrupts, sondern warte auf den Abschluß der Wandlung.

Was muss ich ändern, damit ich auch ALLE Zwischenwerte angezeigt 
bekomme?

Martin

von Christian R. (supachris)


Lesenswert?

Du könntest etwas mit der Sample and Hold Zeit rumspielen, aber die 011 
sieht nach einem generellen Problem aus. Sehr komisch, hatte ich noch 
nie.

von Branko G. (branko)


Lesenswert?

Ich bezweifle dass du  richtiges Programm angehängt  hast.
Bei
1
  
2
int temperaturmessung()
3
..
fällt dir nämlich Rückgabewert(return) und
Compiler kann so etwas nicht Kompilieren.
1
Diese Werte werden durch langsames erhöhen der Eingangsspannung.
Wie  erhöhst du der Spannung? Mit einem Poti?
Ist "langsam" auch  präzis?
Ich meine, nimm besser einer Spindelpoti oder Trimmer mit 10-20 
Umdrehungen.
Nur so ist "langsam" auch "präzis".

von Jörg S. (Gast)


Lesenswert?

Komische Effekte im Zusammenhang mit dem ADC kenne ich nur wenn der 
Port-Pin nicht auf ADC Funktion geschaltet ist.

von Martin S. (martins)


Lesenswert?

@Branko:
Rückgabewert ist nicht nötig, da eine externe Variable beschrieben wird.

Einstellgenauigkeit:
20-fach Spindel-Trimmer im Spannungsteiler, mit dem ich die Spannung in 
< mV-Auflösung einstellen kann.
Das kann auch kein Problem sein, da immer wieder die GLEICHEN Werte 
nicht angezeigt werden.


@Jörg:
Portdefinition:
1
P6SEL = 0x20;
2
P6DIR = 0xDF;
3
P6OUT = 0x00;

@Christian:
Ich verwende ADC12CTL1 = SHP. So sollte doch alles soweit automatisch 
funktionieren? Habe keine schnellen Änderungen im Signal.

von Branko G. (branko)


Lesenswert?

1
@Branko:
2
Rückgabewert ist nicht nötig, da eine externe Variable beschrieben wird.

Warum schreibst du dann:
1
int temperaturmessung...
statt
1
void temperaturmessung...

von Martin S. (martins)


Lesenswert?

Stimmt, mein Fehler. Hatte zuvor eine Version mit Rückgabewert, die ich 
aber dann geändert habe. Das int hatte ich vergessen wegzunehmen.

Ich habe jetzt nochmal alles zusammengefasst. Dieses Programm liefert 
genau den gleichen Fehler:

Beim drehen am Poti springt der Wert z.B. von 2051 direkt auf 2083 und 
dann auf 2115

Ich lese am Breakpoint den Wert von ADC12MEM0 in IAR aus.
1
#include  <msp430x16x.h>
2
int ADCkty=0;
3
main()
4
{
5
      WDTCTL = WDTPW + WDTHOLD;   // Stop Watchdogtimer
6
// Port init
7
      P1SEL = 0x00;
8
      P1DIR = 0xF3;
9
      P1OUT = 0x03;
10
      P2SEL = 0x00;
11
      P2DIR = 0xEF;
12
      P2OUT = 0x00;
13
      P3SEL = 0x30;
14
      P3DIR = 0xCF;
15
      P3OUT = 0x00;
16
      P4SEL = 0x00;
17
      P4DIR = 0xFF;
18
      P4OUT = 0x00;
19
      P5SEL = 0x00;
20
      P5DIR = 0xFF;
21
      P5OUT = 0x8C;
22
      P6SEL = 0x20;
23
      P6DIR = 0xDF;
24
      P6OUT = 0x00;
25
26
//AD-Init
27
      ADC12CTL0 = ADC12ON + SHT0_0 + REFON + REF2_5V;   // ADC12ON:ADC in Bereitschaft
28
      ADC12CTL1 = SHP;            // Sampling Timer benutzen  (SHP = Sample-and-hold-pulse) Einstellungen werden automatisch vorgenommen
29
      ADC12MCTL0 = SREF_6 + INCH_5;    // Extern: VeREF+ und Extern: VeREF-   INCH=Input Channel A0 bis A11. Gewählt: P6.5 = A5
30
      ADC12CTL0 |= ENC;       // jetzt anfangen ...   Enable Conversion muß HIGH sein um zu starten
31
32
33
for(;;)
34
  {
35
        ADC12CTL0 |= ADC12SC;               // Konvertierung durchfuehren
36
        while ((ADC12IFG & BIT0)==0)        // Wenn das Bit 0 auf 1 geht, dann ist ein Wert in ADC12MEM0 geschrieben worden.
37
        {};                                  //warten....
38
                                            // Das Ergebnis der Wandlung steht in ADC12MEM0 (rechten 12 Bit)
39
        ADCkty=ADC12MEM0;      //BREAKPOINT             // ADCkty behält immer den ADC-Wert.
40
  }// end for
41
42
} //end main

von Arc N. (arc)


Lesenswert?

Kann es sein das dies durch die extrem kurze S&H-Zeit (4-Takte, SHT0_x) 
und den hohen Takt (kein Vorteiler, ADC12DIVx) verursacht wird?

von Christian R. (supachris)


Lesenswert?

Oder es ist ein Offset drauf. Weiß ja nicht, wie du die Ref-Quelle 
angeschlossen hast. Du musst ja die Differenz bei dir. Aber so konstant 
ist auch verwunderlich. Mal ins Errata-Sheet geschaut? Vielleichthat 
dein ADC12 ja einen bekannten Bug?

von Wolfgang-G (Gast)


Lesenswert?

hatte ähnliche Probleme; siehe 
Beitrag "MSP430 Erfahrungsaustausch zu ADC12 gesucht",
vielleicht ist etwas brauchbares dabei

von Martin S. (martins)


Lesenswert?

Hallo Wolfgang,

danke für den Tipp.
Genau das war auch mein Problem.
Mit Kondensatoren funktioniert es jetzt einwandfrei, ohne irgendwelche 
Änderung des Programmes!

Danke

Gruß
Martin

von Wolfgang-G (Gast)


Lesenswert?

Ich freue mich über Deine Rückmeldung und dass ich Dir helfen konnte.
MfG
Wolfgang

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.