Hallo zusammen,
ich versuche seit einiger Zeit den ADC-Wert des Attiny24 auszulesen.
Nachdem ich das -nach Datenblatt- für einen Kanal hinbekommen habe
gelingt mir leider das Umschalten auf einen 2. Kanal nicht.
Daraufhin habe ich mir das AVR-GCC-Tutorial angesehen und mich da
entlang gehangelt, doch leider klappt aktuell noch nicht mal mehr bei
einem Kanal die Wandlung :-(
Seht ihr vielleicht auf Anhieb, wo sich der Fehler versteckt?
Die Spannung wurde mittels Multimeter am uC-Pin überprüft, diese liegt
mit knapp 0,5V an.
Da ich keine Debugschnittstelle habe, verändere ich in Abhängigkeit von
dem ADC-Wert das Signal an PB0.
Danke und Gruß
Fabian
C-Code
Hallo,
STK500-Besitzer schrieb:> Fabian S. schrieb:>> adc_current_summe = adc_lesen_avg(0, 16);> Wenn du auch immer nur Kanal 0 ausliest...
aktuell will es es (wieder) hinbekommen, einen Kanal richtig auslesen zu
können.
Aus diesem Grund lese ich immer nur Kanal 0 ein/aus.
Karl M. schrieb:> frage Dich bitte mal, in welcher Reihenfolge das Lesen erfolgt:return> ((ADCH << 8) | ADCL);> Und was steht im Datenblatt?> Und was ist dann das "ADCW"?
In dem Datenlatt des Attiny24 gibt es meines Erachtens kein ADCW.
"... ADCL must be read first, then ADCH" steht im Datenblatt.
In meinem Code wird jedoch erst ADCH gelesen.
Folglich müsste ich das so schreiben?(ADCL|(ADCH << 8))
Das interpretiere ich so, dass erst ADCL gelesen wird, anschließend wird
ADCH gelesen, um 8 Bit nach links verschoben und mit ADCL "verodert"?
Danke und Gruß
Fabian
Fabian S. schrieb:> Folglich müsste ich das so schreiben?(ADCL|(ADCH << 8))> Das interpretiere ich so, dass erst ADCL gelesen wird,
Vorsicht! Der oder-Operator ist kein sequence point, die Reihenfolge ist
nicht garantiert. Deine Interpretation kann vom Compiler ignoriert
werden. Ich wuerde zwei getrennte Befehle verwenden.
leo
Aus dem Datenblatt hast Du für 16 Bit Zugriffe die richtige Reihenfolge
gefunden.
In Assembler erst ADCL und danach ADCH.
Für C gibt es deshalb ADCW als 16 Bit Zugriff!
Hallo,
leo schrieb:> Vorsicht! Der oder-Operator ist kein sequence point, die Reihenfolge ist> nicht garantiert. Deine Interpretation kann vom Compiler ignoriert> werden. Ich wuerde zwei getrennte Befehle verwenden.
Gut zu wissen, dann werde ich es separat machen oder wie von Karl. M.
beschrieben mit ADCW.
Karl M. schrieb:> Fabian S. schrieb:>> In dem Datenlatt des Attiny24 gibt es meines Erachtens kein ADCW.>> Hatte ich auch nicht geschrieben!
Da hatte ich jedoch als erstes gesucht...
Karl M. schrieb:> Aus dem Datenblatt hast Du für 16 Bit Zugriffe die richtige Reihenfolge> gefunden.>> In Assembler erst ADCL und danach ADCH.>> Für C gibt es deshalb ADCW als 16 Bit Zugriff!
Super, danke für die Erklärung. Das hätte ich (so schnell) nicht
gefunden.
Ich habe
1
((ADCH<<8)|ADCL)
durch
1
ADCW
ersetzt, doch leider bin ich noch nicht zufrieden mit dem Ergebnis.
Aktuell liegt eine Spannung von 487 mV an dem Pin an (Multimeter und
Oszilloskop liefern den gleichen Wert). Was bei der internen
Referenzspannung einem Wert von 453 entsprechen müsste.
Die Abfrage:
1
adc_current_summe>=430
ist nicht wahr, was bedeutet, dass ich eine Abweichung von über 23
habe. Irgendwo muss ich noch einen Fehler haben.
Habt ihr noch eine Idee?
Den Quarz des Controllers habe ich überprüft (Pin High, 10ms warten, Pin
Low), dieser war mit 1MHz passend eingestellt.
Hallo,
die Eingangsimpedanz soll laut Datenblatt <=10KΩ sein.
Es müssen sich erst Eingangskondensator(en) umladen.
Entweder einen OPV als Impendanzwandler nehmen,
oder einen kleinen Kondensator ~10nF an jeden ADC-Eingang legen.
Und nach der Wahl des Eingangs, eine Zeitspanne warten ~1µs, bis man die
erste Wandlung startet!
Ich messe dann immer mehrmals nacheinander und bilde einen Mittelwert:
2^n; mit n E { 2,..,6 }.
> ... Abweichung ...
Wie gerechnet? Laut Datenblatt unter 'ADC Characteristics' liegt die
interne Referenz zwischen 1.0 und 1.2 V.
Ein kleiner Fehler entsteht auch durch den zu hohen ADC-Takt mit 500
kHz, der Vorteiler steht nämlich auf /2:
Fabian S. schrieb:> Die Abfrage: adc_current_summe>=430 ist nicht wahr, w
Gänzlich ungeeignet.
Wenn du weder Debugger noch Display hast, dann häng dein Oszi an 2
freie pins: und toggle die: den einen mit jedem Zyklus, den anderen wenn
++i > adc_current_summe ist (und dabei i=0).
Wenn dein Zyklus genau z.b.1ms ist, kannst Du den ADC-wert direkt am
Oscar ablesen.
an Fabian S., vielleicht als Vergleich:
Wenn ich im vorgestellten Programm die fehlende Klammer einfüge, an zwei
Stellen ADCW verwende und das Delay auf ein erträgliches Maß herabsetze,
so erhalte ich bei meinem ATtiny84A eine Schaltschwelle von 426 mV.
Hallo,
Karl M. schrieb:> die Eingangsimpedanz soll laut Datenblatt <=10KΩ sein.Karl M. schrieb:> Dann hat der ADC noch Fehler, die sind in 2-3 Application Notes> beschrieben.
Ich habe mir die Application Notes angesehen, ja mein Spannungsteiler
ist zu hochohmig. Ich habe diesen nun auf einen Widerstand kleiner 10 kΩ
ausgelegt.
Obwohl es eigentlich, mit dem von dir vorgeschlagenen Kondensator und
einer "langsamen" Abtastung nacheinander auch funktionieren müsste.
S. Landolt schrieb:> Ein kleiner Fehler entsteht auch durch den zu hohen ADC-Takt mit 500> kHz, der Vorteiler steht nämlich auf /2:
Nach dem Datenblatt, welches ich gefunden habe, entspricht meine
Einstellung einem Teiler von 8. Oder habe ich da etwas falsch
interpretiert?
Datenblattlink
[http://ww1.microchip.com/downloads/en/devicedoc/Atmel-7701_Automotive-Microcontrollers-ATtiny24-44-84_Datasheet.pdf]
S. Landolt schrieb:> Wie gerechnet? Laut Datenblatt unter 'ADC Characteristics' liegt die> interne Referenz zwischen 1.0 und 1.2 V.
Ich habe das noch einmal nachgerechnet und ja du hast (leider) Recht.
Die Schwankungen der ADC-Zählwerte liegen alle in dem Bereich, welcher
aufgrund der Referenzspannungsschwankung vorliegen kann.
A. S. schrieb:> Fabian S. schrieb:>> Die Abfrage: adc_current_summe>=430 ist nicht wahr, w>> Gänzlich ungeeignet.
Muss ich dir leider zustimmen. Habe es mir mit dem Oszilloskop noch
einmal angesehen...
S. Landolt schrieb:> Wenn ich im vorgestellten Programm die fehlende Klammer einfüge, an zwei> Stellen ADCW verwende und das Delay auf ein erträgliches Maß herabsetze,> so erhalte ich bei meinem ATtiny84A eine Schaltschwelle von 426 mV.
Danke, für die Messung. Das ist ungefähr vergleichbar mit meinem
Ergebnis.
Vielen Dank für eure ganzen Tipps.
Ich werde an der Beschaltung noch einiges anpassen müssen.
So werde ich z.B. an den Aref-Pin eine genauere Referenzspannung
anlegen, um die Genauigkeit zu erhöhen.
Die ADC-Wandlung sollte aber jetzt soweit funktionieren, wenn auch
relativ ungenau. Ich werde jetzt erst einmal den weiteren C-Code
schreiben.
Danke und Gruß
Fabian
Du kannst, wie oben schon mal erwähnt, den ADC sehr beruhigen, wenn du
am Eingang einen kleinen C gegen Masse schaltest. Da sind z.B. schon 1nF
- 4,7nF sehr hilfreich. Auch etwaiges 'Mitziehen' von Nachbarkanälen ist
dann so gut wie verschwunden.
S. Landolt schrieb:> Mit der zweiten Zeile wird die erste annuliert, im Wortsinn.
Jetzt sehe ich es auch.
Datenblatt richtig gelesen, jedoch einen Fehler beim umsetzen :-(.
Matthias S. schrieb:> Du kannst, wie oben schon mal erwähnt, den ADC sehr beruhigen, wenn du> am Eingang einen kleinen C gegen Masse schaltest. Da sind z.B. schon 1nF> - 4,7nF sehr hilfreich. Auch etwaiges 'Mitziehen' von Nachbarkanälen ist> dann so gut wie verschwunden.
Ich hatte da bereits schon einen Kondensator in meiner Schaltung.
Danke und Gruß
Fabian
Matthias S. schrieb:> Du kannst, wie oben schon mal erwähnt, den ADC sehr beruhigen, wenn du> am Eingang einen kleinen C gegen Masse schaltest. Da sind z.B. schon 1nF> - 4,7nF sehr hilfreich.
Für dieses Problem schon richtig.
Allerdings muss dann die Abtastperiode deutlich länger sein als das tau
aus dem Quellwiderstand und diesem C (≈ 10 tau, abhängig von der
ADC-Auflösung).
Ist sie zu kurz, so wir an diesem äußeren Kondensator die durch den
Samplingkondensator entnommene Ladungsmenge nicht wieder vollständig
aufgefüllt werden und es ergibt sich eine Ablage. Die sollte kleiner als
ein halbes LSB sein.
HildeK schrieb:> Ist sie zu kurz, so wir an diesem äußeren Kondensator die durch den> Samplingkondensator entnommene Ladungsmenge nicht wieder vollständig> aufgefüllt werden und es ergibt sich eine Ablage.
Für den internen S&H Kondensator im Tiny 24 gibt das Datenblatt einen
Wert von etwa 14pF an (in Reihe mit einem 1-100k Widerstand(!)) Der
externe C ist also in jedem Fall sehr viel grösser, so das es das
Problem nicht gibt.
Der Eingangspfad ist sowieso sehr viel unbestimmter durch die grosse
Streuung des Serienwiderstandes als alle Berechnung von Ladungen. Die
durch den 14pF entnommene Ladungsmenge ist also nur theoretisch
interessant.
Matthias S. schrieb:> Der> externe C ist also in jedem Fall sehr viel grösser, so das es das> Problem nicht gibt.
Das Problem gibt es immer, wenn die ext. Zeitkonstante zu groß ist im
Verhältnis zur Abtastperiode.
Man entnimmt eine geringe Ladung, die Spannung am Cext sinkt ein wenig
ab. Wird sie nicht bis zum nächsten Abtastzeitpunkt wieder ausgeglichen,
sinkt sie beim nächsten sampeln weiter ab. Und so fort, bis die
Differenzspannung Uin-U_Cext so groß wird, dass die Nachladung von Cext
gerade den Verlust ausgleicht. Das führt zu einer dauerhaften Ablage,
die mehrere LSB betragen kann, je nach fa und 1/tau.
Macht man den externen Kondensator größer, verlängert sich tau und bei
gleichbleibender Abtastfrequenz wird der Fehler größer.
Der Effekt ist in der Literatur beschrieben, leider selten zu finden.
Ich selber bin vor einigen Jahren von einem Xilinx Support-Ingenieur
darauf aufmerksam gemacht worden.