www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MSP4030F2013 Poti einlesen


Autor: Opachl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ich möchte gerne einen Drehpoti einlesen.

Für meine Schaltung habe ich aber P1.0 bis P1.5 schon verbaut.

Daher wollte ich den Poti an P1.6 bzw P1.7 anschließen. doch irgendwie 
bekomme ich keine Daten.

Ich initialiesiere meine Hardware so :
#include "msp430x20x3.h"

// port 1 configuration11
#define P1OUT_INIT      0x20
#define P1DIR_INIT      0x1F
#define P1REN_INIT      0x20
#define P1IES_INIT      0x20
#define P1IE_INIT      0x20

#define WDT_STOP      WDT_PW + WDTHOLD  
#define INIT_RSEL      15
#define INIT_DCO                        3
#define INIT_MOD                        26
#define INIT_DCOCTL      (INIT_DCO << 5) + INIT_MOD

#define TACTL_INIT                      TASSEL1 + MC0
#define TACCTL0_INIT                    CCIE
#define TIMER_COUNT0                    16000

#define INIT_BCSCTL1      INIT_RSEL    
#define INIT_BCSCTL2                    0
#define INIT_BCSCTL3                  0 

//ADC INIT
#define INIT_SD16CTL                    SD16SSEL1
#define INIT_SD16INCTL0                 SD16INCH_3
#define INIT_SD16CCTL0                  SD16SC + SD16UNI
#define INIT_SD16AE                     SD16AE3

void Init_Mcu (void)
{
   DCOCTL = INIT_DCOCTL;
   BCSCTL1= INIT_BCSCTL1;   
   BCSCTL2 = INIT_BCSCTL2;
   BCSCTL3 = INIT_BCSCTL3;

   TACCR0 = TIMER_COUNT0;
   TACCTL0 = TACCTL0_INIT;   
   TACTL = TACTL_INIT;   
   
   SD16CTL = INIT_SD16CTL;
   SD16INCTL0 = INIT_SD16INCTL0;
   SD16CCTL0 =  INIT_SD16CCTL0;
   SD16AE = INIT_SD16AE;
}

void Init_Ports (void)
{
  P1OUT = P1OUT_INIT;
  P1REN = P1REN_INIT;
  P1DIR = P1DIR_INIT;
  P1IES = P1IES_INIT;
  P1IFG = 0;
  P1IE = P1IE_INIT;
}

void main (void)
{
      WDTCTL = WDT_STOP;
      Init_Ports ();
      Init_Mcu ();  
      _EINT();

  while (1)
  {
           XXXXXXX // Meine Funktionen
        }

Wäre nett wenn ihr mir sagen könntet wo hier mein Fehler liegt evt lese 
ich die Daten auch falsch ein.

Der Poti selbst ist an +5V und -5V angeschlossen der Abgreifer liegt 
zurzeit an P1.6.

Ich brauche für meine Funktion eine Dauerkonvertierung da ich mit Hilfe 
des Poti die Geschwindigkeit einer Funktion beinflussen möchte. Die 
Funktion benötigt dazu einen UINT Wert als Übergabe den ich vom poti 
haben wollte.

Es handelt sich um einen F2013 den ich mit IAR programmiere.

Danke schon mal für evt Hilfe ;)
mfg Opachl

Autor: Matze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guck dir mal die Beispielprogramme zum Thema "ADC" von TI an, ich kann 
bei dir von der Wandlung nichts finden. oder willst du nur wissen ob der 
Pin HIGH oder LOW ist?

P.S. die Spannung überm Poti zwischen -5 und 5V ist doof, weil der ADC 
seinen Wert zwischen 0V und Vref misst, also wäre die spannung 0 und 5V 
am Poti angebracht.

Autor: Bernd N (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich sehe nirgends einen ADC Code. Vermutlich ist dein F2013 eh schon 
abgeraucht denn mehr als 0 - 0.6V geht da nicht an den Eingängen. Auch 
wenn der ADC differenzeingänge hat, so darf ADC- nicht negativ (< 0 
Volt) werden.

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Matze schrieb:
> also wäre die spannung 0 und 5V
> am Poti angebracht

Beachte bitte, dass die maximal zulässige Spannung für den MSP 3.6V 
beträgt!
Die Eingänge dürfen natürlich auch nicht mehr Spannung sehen - auf die 
Clamp-Dioden würde ich mich hier nicht verlassen, da du ab >Vref eh 
nurnoch 0xFFFF bekommst.

Hier mal ein Beispiel aus einem alten Programm:
...

SD16INCTL0 = SD16INCH_2;                  // Setze Multiplexer auf A2 (INCH_6 fuer Temperatursensor)
  SD16CTL = SD16REFON + SD16SSEL_1;         // Referenzspannung intern 1V2 + SMCLK
  SD16CCTL0 = SD16IE + SD16SNGL + SD16UNI;  // Interrupt + Single Conversion + unipolar

_BIS_SR(LPM1_bits + GIE);                 // Low-Power-Mode 1 + Globaler Interrupt aktiviert
...
#pragma vector=SD16_VECTOR                  // ISR nach fertiger Wandlung
__interrupt void Wandler (void)
{
  ergebnis_adc = SD16MEM0;                  // Wandlungsergebnis auslesen
...}

So holt sich dein Controller das Ergebnis in der ISR selbst und schiebt 
es in deine Variable. Diese solltest du dann global als volatile 
deklarieren.

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Er hier muss natürlich noch irgendwo auftauchen. Idealerweise dann in 
der ISR, nachdem du das Ergebnis abgeholt hast:
SD16CCTL0 |= SD16SC;                  // Starte Wandlung (SC: Start Conversion)

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und noch als Tip: Gewöhn dir die Schreibweise mit dem "+" anstelle des 
üblichen "|" garnicht erst an...das ist absolut unüblich und ich habe 
das bisher auch nur bei den TI-Examples gesehen.

Autor: Opachl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke schon mal für die viele Anregungen

Bernd N schrieb:
> Ich sehe nirgends einen ADC Code. Vermutlich ist dein F2013 eh schon
> abgeraucht denn mehr als 0 - 0.6V geht da nicht an den Eingängen. Auch
> wenn der ADC differenzeingänge hat, so darf ADC- nicht negativ (< 0
> Volt) werden.

Das war ein Fehler meinerseits die gesamte Schaltung wird über den 
USB-Dongle
ez430-F2013 betrieben dieser hat ja eine Spannungsbegrenzung.

Somit ist der Chip noch vollig i.O.

Dennis schrieb:
> Er hier muss natürlich noch irgendwo auftauchen. Idealerweise dann in
> der ISR, nachdem du das Ergebnis abgeholt hast:SD16CCTL0 |= SD16SC; 
// Starte Wandlung (SC: Start Conversion)


muss das wirklich gemacht werden ? ich habe im ersten beitrag eine 
Continuos mode eingestellt. Und ihm in der Main Routine durch definition 
das erste mal Eingeschaltet.

Dennis schrieb:
> Und noch als Tip: Gewöhn dir die Schreibweise mit dem "+" anstelle des
> üblichen "|" garnicht erst an...das ist absolut unüblich und ich habe
> das bisher auch nur bei den TI-Examples gesehen.

Danke werds in Zukunft mal berücksichtigen bin noch total neu auf im uc 
Bereich

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Opachl schrieb:
> Dennis schrieb:
>> Und noch als Tip: Gewöhn dir die Schreibweise mit dem "+" anstelle des
>> üblichen "|" garnicht erst an...das ist absolut unüblich und ich habe
>> das bisher auch nur bei den TI-Examples gesehen.

Begründung:

> #define INIT_SD16CCTL0  SD16SC + SD16UNI

Wenn man, was beim Testen und Herantasten an eine Funktion geschehen 
kann, versehentlich zweimal den gleichen Ausdruck addiert

> #define INIT_SD16CCTL0  SD16SC + SD16UNI
> ...
> #define INIT_SD16CCTL0_FINALENDLICHGEHTS INIT_SD16CCTL0 + SD16UNI

dann kommen äußerst interessante Nebenwirkungen dabei heraus.

Wenn man hingegen mit OR (|) arbeitet, kann man einzelne Terme sooft 
verwenden wie man will, es ändert am Ergebnis nichts.


> #define INIT_SD16CCTL0  SD16SC | SD16UNI
> ...
> #define INIT_SD16CCTL0_FINALENDLICHGEHTS INIT_SD16CCTL0 | SD16UNI

Nein, das soll natürlich ganz und gar kein Beispiel dafür sein, wie 
man sich an derartige Dinge herantasten soll, auch nicht dafür, wie 
Quelltext auszusehen hat -- allein, es hilft Nebenwirkungen unschädlich 
zu machen.

Gerade beim Testen und Inbetriebnehmen neuer, einem unbekannter 
Hardwaremodule kann es im Eifer des Gefechts passieren, daß da so eine 
Konstante zweimal auftaucht.

Autor: Opachl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bins nochmal der ADC geht zwar nun allerdings springen die 
Zahlenwerte zufällig hoch und runter.

BSP:
Wenn ich den Poti zb in die Mittelpostition stelle zeigt das ergebniss 
im Debugmodus beim ersten mal FF an danach ohne den Poti zu verstellen 
einen Wert um 400 danach kommt was mit 3000 raus der 3 te wert ist 
meistens wieder FF.

Ich weiß langsam nicht mehr was nicht stimmt. habe die interne Ref 
(1.2v) auch eingeschaltet der poti selbst hat 10k ohm zur sicherheit des 
uc habe ich allerdings zusätzlich 2x widerstände a 10k ohm drangeklemmt 
somit komm ich also auf einen gesamtwert von 30 k ohm.


Hoffe evt auf eine weitere Idee


danke schonmal

Autor: Bernd N (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der AD Wandler des F2013 ist mit Vorsicht zu genießen. Überlege mal, 
0-0,6 V bei angeblich 16 BIT was für eine "Schrittweite" wirst du da 
wohl herausbekommen ?

Dann einen Blick ins DB in die Rubrik S/N, wären das wirklich 16 BIT 
dann würde dort 96 dB stehen... steht da aber nicht.

Mit entsprechendem Aufwand bekommst du stabile 14 BIT heraus wobei an 
P1.3 ein 100 nF nach GND gehört. Errata nicht vergessen und dann sieht 
die Initialisierung so aus:
    #define VREFOUT  BIT3                          // schalte VREF an Ausgang P1.3

/*
    The SD16_A internal reference can be adjusted to operate within the specification by
    writing 0x61 to memory location 0xBF. This corrects the temperature coefficient of the
    internal reference and centers the typical voltage to 1.20 V.
*/
    __no_init char SD16_A @0xBF;                   // center 1,2V temp. drift 50ppm/K (Errata, ADC)

    P1SEL |= VREFOUT;                              // REFOUT 100nF gegen GND

    SD16_A = 0x61;                                 // center 1,2V temp. drift 50ppm/K (Errata, ADC)

    SD16CTL = SD16REFON + SD16SSEL_1 + SD16DIV_0;  // VREF=1.2V, fM=SMCLK (SD16CTL=REF+Taktauswahl)
    SD16INCTL0 = SD16INCH_2;                       // ADC Eingang zuweisen (SD16INCH_2)
    SD16CCTL0 = SD16UNI + SD16OSR_1024;            // OverSamplingRatio=1024, Messeingang=unipolar
    SD16AE = SD16AE4;                              // P1.4 A1+, Eingang freigeben, DVSS=AGND
Für die Wandlung machst du dann mal eine Mittelwertbildung über n 
Schleifen.

    SD16CCTL0 &= ~SD16IFG;                         // clear ADC Interrupt Flag
    SD16CCTL0 |= SD16SC;                           // AD Wandler starten
    while (!(SD16CCTL0 & SD16IFG));                // AD Wandlung fertig ?
    AvgSum += SD16MEM0;                            // Mittelwert über n Messungen

Kann sein das ich hier andere Eingänge als du verwendet habe, kannst du 
ja wieder an deinen Code anpassen.

OSR mal heraufschrauben und dann wirds schon :-)

Autor: Opachl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd N schrieb:

>     __no_init char SD16_A @0xBF;                   // center 1,2V temp. >drift 
50ppm/K (Errata, ADC)

Wenn ich das schreibe gibt mir der IAR Compiler einen Fehler aus.

Error[Be009]: memory attributes not allowed on auto variables or 
parameters


Ansonsten sehen meine Inits nun so aus:
#define VREFOUT  BIT7                                // schalte VREF an Ausgang P1.7
#define INIT_SD16CTL       SD16REFON + SD16SSEL_1 + SD16DIV_0;  
#define INIT_SD16INCTL0    SD16INCH_3
#define INIT_SD16CCTL0     SD16IE + SD16UNI + SD16OSR_1024;
#define INIT_SD16AE        SD16AE6

//Interrupt Schleife
#pragma vector = SD16_VECTOR
__interrupt void SD16ISR(void)
{
   if (SD16MEM0 != 65535)
   {     
      if(Count != 0)
      {
         while (!(SD16CCTL0 & SD16IFG));                // AD Wandlung fertig ?
         u16_Ergebnis += SD16MEM0;
      }
      
      if(Count == 0) Count = 3;
   }
}

Autor: Opachl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Opachl schrieb:
> //Interrupt Schleife
> #pragma vector = SD16_VECTOR
> __interrupt void SD16ISR(void)
> {
>    if (SD16MEM0 != 65535)
>    {
>       if(Count != 0)
>       {
>          while (!(SD16CCTL0 & SD16IFG));                // AD Wandlung fertig ?
>          u16_Ergebnis += SD16MEM0;
>       }
>
>       if(Count == 0) Count = 3;
>    }
> }
Das die neue Variante:
Der Wert springt immer noch sehr heftig leider...

Mir ist weiterhin aufgefallen das der ADC auch nur auf den poti im 
letzten drittel reagiert alle einstellungen kleiner lösen keinen 
Interupt aus.

#pragma vector = SD16_VECTOR
__interrupt void SD16ISR(void)
{
   if (SD16MEM0 != 65535)
   {
      if(Count1 != 0)
      {
         while (!(SD16CCTL0 & SD16IFG));                // AD Wandlung 
fertig ?
         u16_Ergebnis += SD16MEM0;
         Count1--;
      }

      if(Count1 == 0)
      {
         Count1 = 10;
         u16_Ergebnis_10 = u16_Ergebnis / 10;
         u16_Ergebnis = 0;
      }
   }
}

Autor: Bernd N (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keine Ahnung was du da machst, versuche es doch erst einmal so wie ich 
es dir gesagt habe. Mittelwert über 512 Werte bilden und dann auf 14 BIT 
herunter:
uint16_t getAdcValue (void)
{
    uint16_t AvgCount = 0;
    uint32_t AvgSum = 0;

    for (AvgCount = 0; AvgCount < 512; AvgCount ++) {
        SD16CCTL0 &= ~SD16IFG;                                    // clear ADC Interrupt Flag
        SD16CCTL0 |= SD16SC;                                      // AD Wandler starten
        while (!(SD16CCTL0 & SD16IFG));                           // AD Wandlung fertig ?
        AvgSum += SD16MEM0;                                       // Mittelwert über 512 Messungen
    }
    return AvgSum >> 11;
}


Hast du meine vorhergehenden Erklärungen verstanden ?

Also, 0-0.6V bei 16 BIT = 0,0000091552734375 Volt = 9,1 µV pro Schritt. 
Deine Versorgungsspannung beziehst du über die USB Schnittstelle, was 
glaubst du wie gut die wohl abgeblockt ist ?

Und dann laß mal die ISR weg und mach es mit einer einfachen Schleife 
wie oben gezeigt.

Es wäre hilfreich wenn du mal deinen kompletten Code hier anhängst statt 
die Fragmente. Wie gibst du den Wert aus ? Display, SoftUart... ?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.