- LiTime Speicher und Akkus         
Ergebnis 1 bis 8 von 8

Thema: ATXmega128A1 Rev. H unerklärliches ADC-Phänomen

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    14.09.2012
    Beiträge
    15

    ATXmega128A1 Rev. H unerklärliches ADC-Phänomen

    Anzeige

    Praxistest und DIY Projekte
    Hallo zusammen,

    ich habe ein mir nicht ganz erklärliches Phänomen bei einem Projekt von mir.
    Wie der Titel schon vermuten lässt, geht es um die AD-Wandlung auf meinem ATXmega128A1-Breakoutboard.

    Ich habe zwei Linearpotentiometer als unbelasteten Spannungsteiler, mit denen ich eine Position ermitteln möchte, was auch vom Prinzip her funktioniert, dank der Hilfe von Kampis Tutorial. Leider tritt an bestimmten Stellungen der Potentiomer das Phänomen auf, dass die AD-Wandlung 10 mal funktioniert und dann wird der maximale Wert, der als Referenz gemessen wurde über USART rausgeschrieben. Ich bilde zusätzlich den Mittelwert der letzten 10 Messwerte, um ein wenig das Flattern bei der 12Bit-Auflösung rauszunehmen.

    Die Ausgabe sieht dann zum Beispiel so aus:
    Code:
    USART up and running.
    lower: 745		upper: 812
    lower:3644		upper:3645
    Correction Lower: 2.899	Correction Upper: 2.833
    
    ...
    lower: 1014		upper: 6
    lower: 1014		upper: 1014
    lower: 1014		upper: 7
    lower: 1014		upper: 6
    lower: 1014		upper: 7
    lower: 1014		upper: 7
    lower: 1014		upper: 7
    lower: 1014		upper: 8
    lower: 1014		upper: 7
    lower: 1014		upper: 7
    lower: 1014		upper: 7
    lower: 1014		upper: 7
    lower: 1014		upper: 1014
    lower: 1014		upper: 8
    lower: 1014		upper: 4
    lower: 1014		upper: 8
    lower: 1014		upper: 4
    ...
    An diesem Beispiel ist glaube ich relativ ersichtlich, dass die Messungen mit upper:1014 zwischendrinne ziehmlicher mumpitz sind.
    Ein ähnliches Phänomen habe ich in der genau anderen Richtung auch, nur dass da ein negativer Wert auftauch mit -430. Als Ausgabe sieht das dann ungefähr so aus:
    Code:
    ...
    lower: 4		upper: 1014
    lower: 3		upper: -430
    lower: 0		upper: 1014
    lower: 1		upper: 1014
    lower: 3		upper: 1014
    lower: 4		upper: 1014
    lower: 3		upper: 1014
    lower: 5		upper: 1014
    lower: 5		upper: 1014
    lower: 4		upper: 1014
    lower: 3		upper: 1014
    lower: 2		upper: 1014
    lower: 5		upper: -430
    lower: 3		upper: 1014
    lower: 4		upper: 1014
    lower: 2		upper: 1014
    lower: 3		upper: 1014
    ...
    Jetzt ist vielleicht noch interessant, wie ich auf diese Werte komme und das passiert mit folgender Berechnung:

    Position = (Messwert - Offset)/((maximalerMesswert - minimalerMesswert)/anzahlMesspunkte)

    AnzahlMesspunkte ist in meinem Fall 1000.

    Damit wäre beschrieben, wie ich auf diese lustigen Werte komme.
    Da der Beitrag wahrscheinlich schon lang genug ist, packe ich die wichtigsten Auszüge aus meinem Code in den Anhang.

    Die ADC ist als 12Bit Singleended unsigned mit einer externen Referenzspannung von 3,3V an Pin0 initalisiert. (näheres im Code)

    Um die Frage nochmal zu konkretisieren, die ich habe:
    Kennt jemand das Problem und hat evtl. eine Lösung dafür, oder muss ich mit diesen "Ausreißern" leben, die mir evtl das Leben ein wenig schwerer machen könnten. Sprich ich muss eine Plausibilitätsprüfung für die Werte einfügen.

    Achja, wer auch eine Idee hat, wie ich die werksseitigen Kalibrierungswerte rausbekomme, so dass ich zum Schluss kein Offset mehr habe von der ADC, der darf sie auch gerne Posten, da wäre ich nicht sauer drüber

    Danke und Grüße

    Oreas

    P.S.: habe versucht so viel wie geht zusammen zu kürzen im Anhang und hoffe alles ausreichend kommentiert zu haben. Sollte dem nicht der Fall sein, so stehe ich gerne Rede und Antwort. Und sry, dass alles in einer Datei gelandet ist ^^
    Angehängte Dateien Angehängte Dateien

  2. #2
    Moderator Robotik Einstein Avatar von Kampi
    Registriert seit
    21.11.2009
    Ort
    Monheim, Nordrhein-Westfalen, Germany
    Alter
    34
    Beiträge
    3.501
    Blog-Einträge
    9
    Hey,

    Kalibrationsregister auslesen habe ich hier beschrieben:

    http://kampis-elektroecke.de/?page_id=1302

    Was ich gestern nicht gesehen habe....du hast in deiner ISR vom Timer einen 2ms Delay. Delay-Funktionen sind mehr so Schätzwerte.....du hast geschrieben das die ISR mit 100kHz ausgelöst wird aber du wartest dort 2ms drin? Sicher das der Unsinn bei der Ausgabe nicht deswegen kommt?
    Weil bei so einem periodischen Fehler würde ich wirklich auf einen Timer tippen.....
    Wenn dir der Timer während des Delays usw. dazwischen funkt kann es Probleme geben.
    Schaut ruhig mal auf meiner Homepage vorbei :
    http://kampis-elektroecke.de

    Oder folge mir auf Google+:
    Daniel Kampert

    Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.

    Gruß
    Daniel

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    14.09.2012
    Beiträge
    15
    Hey Daniel,

    hatte ich auf deiner HP auch schon gesehen, aber der Compiler wehrt sich wehement mit folgender Fehlermeldung dagegen:
    "expected identifier before '__builtin_offsetof'"
    und da bin ich seit gestern Abend noch nicht weiter gekommen.
    Ich hatte in einem anderen Forum http://www.mikrocontroller.net/topic/120008 diesen Beitrag gefunden und das mal eingebaut und der Compiler beschwert sich nicht. Was mich daran aber etwas Stutzig macht ist, dass
    ADCA. CALL = 255
    ADCA.CALH = 0
    ist und das kann ich irgendwie schwer glauben.

    Das Delay hatte ich eingebaut, weil ich festgestellt hatte, dass die Werte dann zuverlässiger kommen, als wenn ich das weg lasse, aber ich nehme es mal raus. Das mit den 100kHz im Kommentar (habe ich gerade eben erst gesehen) stimmt leider nicht meht ^^ das sind nur 10kHz wir im Kommentar zum Timer beschrieben. Lade dann noch gleich eine geänderte Version hoch, sry.

    Aber im Endeffekt wirst du wahrscheinlich recht haben, dass ich ein richtiges Timing-Problem generiert habe, dass der Interrupt einfach zu lange braucht und ich mir was andere einfallen lassen muss.

    Trotzdem gerne weiter Kommentare/Anregungen posten, wie ich mein Problem lösen kann. Ich entwickel auch gerne unter Anleitung selbst, solange jemand dann mal drüber schaut, ob das, was ich gemacht habe nicht vllt doch etwas Mist ist

    EDIT: da ist sie schon
    Angehängte Dateien Angehängte Dateien

  4. #4
    Moderator Robotik Einstein Avatar von Kampi
    Registriert seit
    21.11.2009
    Ort
    Monheim, Nordrhein-Westfalen, Germany
    Alter
    34
    Beiträge
    3.501
    Blog-Einträge
    9
    Hey,

    nein die Calibrationsregister sind immer leer. Du musst sie während des Programmdurchlaufs mit den Werten aus den werksseitig beschriebenen Registern beschreiben.
    Aber selbst bei 10kHz ist ein 2ms Delay viel zu lang ....10kHz heißt ja das die ISR 10000x pro Sekunde aufgerufen wird....also 10x pro Milisekunde. Und dann wartest du in der ISR 2ms? In der Zeit sind schon wieder 20 Interrupts geschehen (oder sehe ich das falsch )?
    Ich schau heute Nachmittag mal in meinem C-Programm....evtl. habe ich nur was vergessen mit rein zu schreiben. Weil bei mir meckert der Compiler nicht.

    Edit:
    Füge mal den Include mit ein:

    Code:
    #include <stdlib.h>
    Und fürs Kalibrieren kannst du dir mal in meinem Bastelprogramm:

    https://www.dropbox.com/s/8d18pojnfu27b7g/XMega.c

    Die Funktion "LeseKalibrationsregister" und "DACB_Cal" anschauen.
    Geändert von Kampi (22.11.2012 um 10:27 Uhr)
    Schaut ruhig mal auf meiner Homepage vorbei :
    http://kampis-elektroecke.de

    Oder folge mir auf Google+:
    Daniel Kampert

    Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.

    Gruß
    Daniel

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    14.09.2012
    Beiträge
    15
    jaja, ich sehs ja ein, dass ich mich da mit den 2 ms verschätzt habe
    aber selbst ohne ist es nicht besser geworden.

    Habe nochmal nachgedacht: da es sich um eine Positionsbestimmung von einem nicht hochdynamischen System handelt, sollte es auch ausreichen, wenn man zum Beispiel 250 Hz (also 250 Messungen die Sekunde macht).

  6. #6
    Moderator Robotik Einstein Avatar von Kampi
    Registriert seit
    21.11.2009
    Ort
    Monheim, Nordrhein-Westfalen, Germany
    Alter
    34
    Beiträge
    3.501
    Blog-Einträge
    9
    Musst du mal ausprobieren wie viel du brauchst. Ansonsten musst du auf einen externen ADC umsteigen da diese glaube ich schneller sind als die internen (hängt ja zum Teil auch mit dem Verfahren zusammen wie die messen).
    Schaut ruhig mal auf meiner Homepage vorbei :
    http://kampis-elektroecke.de

    Oder folge mir auf Google+:
    Daniel Kampert

    Es gibt 10 Arten von Menschen. Die einen können Binär, die anderen nicht.

    Gruß
    Daniel

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    14.09.2012
    Beiträge
    15
    Interessant finde ich nur, dass wenn ich ausschließlich die ADC in der Main laufen lasse und nur diese beiden Werte ausgebe, dass das wunderbar funktioniert.

    Naja ich glaube ich werde um einen neuen Aufbau meines Codes nicht drumherum kommen und vielleicht behebt sich das Problem dann damit.

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    14.09.2012
    Beiträge
    15
    sooooo,

    nach diversen Terminen habe ich endlich die Zeit gefunden eine Lösung für die unkonstanten Werte zu finden. Ergibt sich aus den Errata aus den Manuals ...
    Siehe in Kapitel 35: Errata unter Punkt 8

    "8. Accuracy lost on first three samples after switching input to ADC gain stage
    Due to memory effect in the ADC gain stage, the first three samples after changing input
    channel must be disregarded to achieve 12-bit accuracy.
    Problem fix/Workaround
    Run three ADC conversions and discard these results after changing input channels to ADC
    gain stage."

    also einfach sowas wie:
    Code:
    for(int i = 0; i <= 2; i++){
    	get_adcb(&(ADCA.CH0),3);
    	delay_us(10);
    }
    value = get_adcb(&(ADCA.CH0),3);
    für jede AD-Wandlung einbauen (vorausgesetzt man verwendet mehr als einen Kanal).

    Ein Problem, was ich aber immer noch nicht gelöst habe ist die Kalibrierung der ADC. Ich habe leider immer noch ein Offset von im Schnitt 50-75 Inkrementen die eine genaue Bestimmung der Werte vermiesen und eine Ungenauigkeit von ca 11% hineinbringen. Also wenn da jemand ne gute Idee hat ... immer her damit

Ähnliche Themen

  1. Mikrocontroller ATXmega128A1 Programmier-Problem
    Von Drazhoath im Forum AVR Hardwarethemen
    Antworten: 6
    Letzter Beitrag: 08.05.2012, 18:48
  2. Cortex M3 unerklärliches Interrupt Verhalten
    Von Siro im Forum ARM - 32-bit-Mikrocontroller-Architektur
    Antworten: 8
    Letzter Beitrag: 18.01.2012, 17:20
  3. ET TFT240320TP-3.2 Rev. B kaputt?
    Von flooh im Forum Elektronik
    Antworten: 0
    Letzter Beitrag: 02.04.2010, 16:35
  4. BASCOM und ATxmega128A1
    Von Hellmut im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 7
    Letzter Beitrag: 07.10.2008, 11:31
  5. Heron Robot Project - Rev. 1.02
    Von bart im Forum Vorstellungen+Bilder von fertigen Projekten/Bots
    Antworten: 25
    Letzter Beitrag: 16.03.2008, 00:06

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiTime Speicher und Akkus