M5-int ADC: Unterschied zwischen den Versionen

Aus Attraktor Wiki

Wechseln zu: Navigation, Suche
K (Wie schnell ist der ADC)
 
(5 dazwischenliegende Versionen des gleichen Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
 
{{kpst-email|M5-HW-iADC-...}}
 
{{kpst-email|M5-HW-iADC-...}}
  
{{Template:In Arbeit}}
+
<!-- {{Template:In Arbeit}} -->
  
 
== Übersicht ==
 
== Übersicht ==
Zeile 45: Zeile 45:
  
 
Es ist dort auch von der großen Ungenauigkeit zwischen verschiedenen Chips von +- 6% die Rede und es wird darauf hingewiesen, dass die Esprif-IDE Methoden zur Kompensation zur Verfügung stellt. Inwieweit die Kompensationsmethoden in die Programmierung der MicroPython und Blockly Elemente eingeflossen sind ist mir nicht bekannt.
 
Es ist dort auch von der großen Ungenauigkeit zwischen verschiedenen Chips von +- 6% die Rede und es wird darauf hingewiesen, dass die Esprif-IDE Methoden zur Kompensation zur Verfügung stellt. Inwieweit die Kompensationsmethoden in die Programmierung der MicroPython und Blockly Elemente eingeflossen sind ist mir nicht bekannt.
 +
 +
ADC
 +
 +
import machine
 +
 +
# pin number must > 36 
 +
adc=machine.ADC(pin)
 +
# value: ATTN_0DB (range 0 ~ 1.1V)
 +
#        ATTN_2_5DB (range 0 ~ 1.5V)
 +
#        ATTN_6DB (range 0 ~ 2.5V)
 +
#        ATTN_11DB (range 0 ~ 3.9V)
 +
adc.atten(value)
 +
# value: WIDTH_9BIT - capture width is 9Bit
 +
#        WIDTH_10BIT - capture width is 10Bit
 +
#        WIDTH_11BIT - capture width is 11Bit
 +
#        WIDTH_12BIT - capture width is 12Bit
 +
adc.width(value)
 +
# Read the ADC value as voltage (in mV)
 +
data = adc.read()
 +
 +
  
 
== Meine Motivation ==
 
== Meine Motivation ==
Zeile 755: Zeile 776:
 
Eine einzelne Messung in Blockly [[Image:M5-HW-iADC-002.png|ADC-Messdauer]] dauert ca. 78µs. Das entspricht knapp 13.000 Messungen in der Sekunde :( Von 2MSps ist da nicht viel übrig geblieben.
 
Eine einzelne Messung in Blockly [[Image:M5-HW-iADC-002.png|ADC-Messdauer]] dauert ca. 78µs. Das entspricht knapp 13.000 Messungen in der Sekunde :( Von 2MSps ist da nicht viel übrig geblieben.
  
Eine For-Schleife mit 10.000 Messungen benötigt gut 1.400 ms. Bei 1000 Messungen wären das 140ms also ca. 7 Messungen in der Sekunde.
+
Eine For-Schleife mit 10.000 Messungen benötigt gut 1.400 ms. Bei 1000 Messungen wären das 140ms also ca. 7000 Messungen in der Sekunde.
  
 
Ein Blick auf den Micropythoncode zeigt, dass neben der Messwertabfrage auch noch range() abgearbeitet werden muss:
 
Ein Blick auf den Micropythoncode zeigt, dass neben der Messwertabfrage auch noch range() abgearbeitet werden muss:

Aktuelle Version vom 29. Juni 2020, 18:44 Uhr

Von Peter (peter@attraktor.org)

Bilderprefix: M5-HW-iADC-...


Übersicht

Dem internen ADC des ESP32 geht der Ruf voraus, dass er ziemlich unbrauchbar sein soll.

Im Datenblatt sind zum ADC folgende Daten zu finden:

  • DNL (Differential nonlinearity) von -7 bis 7 LSB > 0,17% auf den Maximalen Messwert bezogen und
  • INL (Integral nonlinearity) von -12 bis 12 LSB > 0,29% auf den Maximalen Messwert bezogen
  • 200kSps bei RTC-Takt
  • 2MSps bei normalem Takt

Der maximale Messfehler beträgt lt. Datenblatt:

Description Min Max Unit
Atten=0, effective measurement range of 100 ~ 950 mV –23 23 mV
Atten=1, effective measurement range of 100 ~ 1250 mV –30 30 mV
Atten=2, effective measurement range of 150 ~ 1750 mV –40 40 mV
Atten=3, effective measurement range of 150 ~ 2450 mV –60 60 mV

Es ist dort auch von der großen Ungenauigkeit zwischen verschiedenen Chips von +- 6% die Rede und es wird darauf hingewiesen, dass die Esprif-IDE Methoden zur Kompensation zur Verfügung stellt. Inwieweit die Kompensationsmethoden in die Programmierung der MicroPython und Blockly Elemente eingeflossen sind ist mir nicht bekannt.

ADC

import machine

  1. pin number must > 36

adc=machine.ADC(pin)

  1. value: ATTN_0DB (range 0 ~ 1.1V)
  2. ATTN_2_5DB (range 0 ~ 1.5V)
  3. ATTN_6DB (range 0 ~ 2.5V)
  4. ATTN_11DB (range 0 ~ 3.9V)

adc.atten(value)

  1. value: WIDTH_9BIT - capture width is 9Bit
  2. WIDTH_10BIT - capture width is 10Bit
  3. WIDTH_11BIT - capture width is 11Bit
  4. WIDTH_12BIT - capture width is 12Bit

adc.width(value)

  1. Read the ADC value as voltage (in mV)

data = adc.read()


Meine Motivation

Da ich auf der Suche nach einer einfachen Möglichkeit war die Temperatur eines Leistungs-MOS-Fet zu überwachen, hat es mich interessiert, ob dieser ADC zusammen mit einem NTC dazu in der Lage ist.

Dazu habe ich ein kleines Programm mit UIFlow-Blockly geschrieben, das den Wert des ADC ausliest daraus einen maximalen und minimalen Wert ermittelt und ggf. speichert. Weiterhin wird die Summe aller Mesungen gebildet und daraus der Mittelwert ermittelt. Schließlich wird der Mittelwert, der Max- und der Min-Wert und die Anzahl der Durchläufe auf dem Display des M5-StickC angezeigt. Damit habe ich erste Erkenntnisse gewonnen. Leider kann ich dieses Programm hier nicht veröffentlichen, weil ich es in der OnLine-Version von UIFlow entwickelt habe, der Rechner zwischen drinnen abgestürtzt ist und ich natürlich noch nichts gespeichert hatte - weil ich ja noch in der Entwicklung war. Ich weiss, ich verdiene kein Mitgefühl - ich habe ganz einfach selber schuld! Zum Glück hatte ich es schon im M5StickC gespeichert, so dass ich weiterhin damit arbeiten konnte.

Messaufbau

Die Ergebnisse der Messungen mit einem Vorteiler von 6dB:

Messspannung[mV] Messungen Mittelwert[mV] Max[%] Min[%] Bemerkung
99,65 100 107,2 8,19 -0,20 kleinste Spannung gemäß Datenblatt 100mV
99,65 500 107,2 18,5 -0,17
99,65 1000 107,2 24,1 -0,16
99,65 2000 107,2 24,1 -0,16
99,65 3000 107,1 24,1 -0,14
99,65 4000 107,1 24,1 -0,13
256,0 100 257,1 2,32 -0,82 Spannung am NTC bei 125°C
256,0 500 257,0 7,02 -7,40
256,0 1000 256,9 10,56 -11,24
256,0 2000 256,9 10,55 -11,27
256,0 3000 257,0 10,90 -11,28
256,0 4000 257,0 10,90 -11,30
443,2 100 441,5 4,61 -5,18 Spannung am NTC bei 100°C
443,2 500 442,1 6,31 -6,81
443,2 1000 442,2 6,28 -6,84
443,2 2000 442,1 6,30 -6,81
443,1 3000 442,1 6,31 -6,81
443,1 4000 442,1 6,32 -6,81
705,2 100 702,0 1,09 -2,17 Spannung am NTC bei 80°C
705,2 500 702,5 3,50 -3,92
705,2 1000 702,6 3,48 -3,92
705,2 2000 702,6 4,05 -3,93
705,2 3000 702,5 4,05 -3,93
705,2 4000 702,5 4,06 -4,06
1141,7 100 1137,4 1,12 -0,47 Spannung am NTC bei 60°C
1141,7 500 1137,4 2,43 -1,97
1141,7 1000 1137,4 2,43 -1,97
1141,7 2000 1137,4 2,78 -2,67
1141,7 3000 1137,3 2,78 -2,67
1141,7 4000 1137,3 2,79 -2,67

Fazit der Einzelmessungen

Der ADC des ESP32 macht seinem Schlechten Ruf alle Ehre! Die Abweichung einzelner Messungen zwischen fast 3% am oberen Ende des Messbereichs und mit bis zu 25% am unteren Ende sind schlechter als die eines alten Drehspulmessgerätes mit 1,5% am Skalenendwert.

Nun gibt es aber ein Licht am Horizont, wenn man die Mittelwerte der Messungen betrachtet. Hier sind die Abweichungen erheblich geringer. Deshalb habe ich aus den Werten der ersten Tabelle eine weitere angefertigt, die die Abweichung der Mittelwerte von den tatsächlichen Spannungswerten ausgibt:

Messspannung[mV] Messungen Mittelwert[mV] Abweichung [mV] Abweichung[%]
99,65 100 107,2 7,55 7,58
99,65 500 107,2 7,55 7,58
99,65 1000 107,2 7,55 7,58
99,65 2000 107,2 7,55 7,58
99,65 3000 107,1 7,45 7,48
99,65 4000 107,1 7,45 7,48
256,0 100 257,1 1,1 0,43
256,0 500 257,0 1,0 0,39
256,0 1000 256,9 0,9 0,35
256,0 2000 256,9 0,9 0,35
256,0 3000 257,0 1,0 0,39
256,0 4000 257,0 1,0 0,39
443,2 100 441,5 -1,7 -0,38
443,2 500 442,1 -1,1 -0,25
443,2 1000 442,2 -1,0 -0,23
443,2 2000 442,1 -1,1 -0,25
443,2 3000 442,1 -1,1 -0,25
443,2 4000 442,1 -1,1 -0,25
705,2 100 702,0 -3,2 -0,45
705,2 500 702,5 -2,7 -0,38
705,2 1000 702,6 -2,6 -0,37
705,2 2000 702,6 -2,6 -0,37
705,2 3000 702,5 -2,7 -0,38
705,2 4000 702,5 -2,7 -0,38
1141,7 100 1137,4 -4,3 -0,38
1141,7 500 1137,4 -4,3 -0,38
1141,7 1000 1137,4 -4,3 -0,38
1141,7 2000 1137,4 -4,3 -0,38
1141,7 3000 1137,3 -4,4 -0,39
1141,7 4000 1137,3 -4,4 -0,39

Fazit der kumulierten Messungen

Diese Tabelle bestätigt die Annahme, dass mit kumulierten Messungen die Genauigkeit deutlich erhöht werden kann und extremen Schwankungen der Messwerte gemildert werden können. Bei der Spannung von 99,65 mV treten zwar noch immer Abweichungen 7,5% auf, aber alle Spannungen > 256 mV werden mit einer Genauigkeit besser 0,5% erkannt. Damit lässt sich arbeiten.

Nun interessiert noch der Bereich zwischen 99,65 mV und 256 mV.

Messung des Übergangsbereichs

Nun möchte ich nicht mit einer weiteren Tabelle nerven, deshalb stelle ich die Ergebnisse hier nur kurz dar:

Die interessantesten Messen waren bei 244,2 mV mit 1,09% und 255,5mV mit 0,47% maximaler Abweichung. Bei niedrigeren Spannungen stieg die Abweichung diskontinuierlich an (156,9mV - 2,74%). Die Abweichungen für höhere Spannungen sind schon bekannt.

Ab ~250mV sind die Messwerte also gut zu gebrauchen.

Nun wird sich mancher schon gefragt haben, warum ich mit so krummen Spannungen arbeite. Der Grund ist das HM8040-2 Netzgerät aus dem ich Spannung bezogen habe. Es ist eine analoge Konstruktion die 2 Poti's (Grob/Fein) zur Spannungseinstellung bereitstellt. Damit lässt sich die Spannung nicht auf 0,1mV genau einstellen. Die Anzeige des Gerätes löst nur in 100mV-Schritten auf.

Wie viele Messungen sind erforderlich?

Dazu habe ich mir überlegt, dass je mehr Messungen gemacht werden, der Einfluss einer einzelnen Messung immer geringer wird. Ich muss also so viele Messungen durchführen bis der Einfluss der nächsten Messung unter einem festgelegten Limit bleibt.

    Anzahl der Messungen = Max. Abweichung einer Messung / Limit

Die Maximale Abweichung der Messungen lag bei knapp 12%. Ich nehme mal 15% an, um auf der sicheren Seite zu liegen.

    15% / 0,1%  =  150 Messungen
    15% / 0,01% = 1500 Messungen

Je nach Genauigkeitsanspruch sind also mit Sicherheitsabstand 200 bis 2000 Messungen erforderlich. Soweit die Theorie.

Nun zur Praxis

Um die Anzahl erforderlicher Messungen zu ermitteln habe ich wieder ein Programm geschrieben - und gleich gesichert. Ihr könnt es Euch am Ende dieser Seite herunterladen.

Dieses Programm Summiert eine Anzahl Messungen (Var: messDistance) auf. Errechnet daraus den Mittelwert und speichert diesen in der Liste messungen ab. Das erfolgt solange bis die vorgegebenen Anzahl Einzelmessungen (Var: anzahl) erreicht ist.

Anschliessend wird die Liste messungen ausgewertet. Es wird der Mittelwert aller Einträge errechnet, der größte und kleinste Wert und deren Abweichungen vom Mittelwert in % ermittelt sowie die Anzahl der Einzelmessungen bis zum ersten Auftreten dieser Werte ermittelt.

Diese Werte werden schließlich angezeigt. Mit einem Druck auf Taste A kann ein weiterer Messdurchgang gestartet werden.


Durch ändern der Werte von messDistance und anzahl können die Messparameter geändert werden. Die maximale Anzahl von Einzelmessungen die noch ohne Fehlermeldung abgearbeitet wird findet Ihr in der folgenden Tabelle:

messdistance anzahl max.
10 80000
20 160000
50 400000
100 800000

Spielt gerne mal ein wenig damit herum. Es macht Spass und man lernt etwas dabei. Allerdings dauert ein Messdurchgang bei einer großen Anzahl von Messungen schon mehrere Minuten! Verlasst Euch nicht auf einen Messdurchgang bei einer Spannung - hier spielt der Zufall mit - deshalb wundert Euch nicht wenn Ihr unterschiedliche Ergebnisse bekommt. Achtet auf die Abweichungen.

Ich habe Messungen mit den in der Liste oben aufgeführten Parametern durchgeführt und zu meinem Erstaunen festgestellt, dass die Abweichungen zwischen dem Mittelwert und den Extremen nie größer als 1 mV waren und auch die Mittelwerte verschiedener Messungen variierten nur um 1 mV. Das ist übrigens die kleinste Einheit, da das Programm errechnete Werte auf ganzzahlige mV Beträge rundet / abschneidet. Ich habe zuerst mit mit 2 Nachkommastellen gearbeitet, aber das war nur verwirrend. Ohne Nachkommastellen wurde plötzlich alles viel klarer.

Hier ein paar Beispiele:

mess distance anzahl max. Referenz [mV] Mittelwert[mV] nach Messungen Max. [mV] Max. [%] nach Messungen Min. [mV] Min. [%] nach Messungen Auf treten
1 5000 100,0 99 1 100 1,01 2 99 0,0 1 1
100,0 99 14 105 5,0 3 99 -1,0 1 1
100,0 100 2 102 2,0 1 99 -1,0 4 1
100,0 99 1 100 1,01 7 99 0,0 1 1
100,0 100 2 103 3,0 3 100 0,0 2 1
100,0
10 80000 100,0 100 10 100 0,0 10 100 0,0 10 1
100,0 99 10 / 30 100 1,01 20 / 10 99 0,0 10 / 30 2
100,0 100 30 / 10 101 1,0 10 / 40 100 0,0 30 / 10 2
20 100000 100,0 99 20 100 1,01 40 / 140 99 0,0 20 4
100,0 100 20 100 0,0 20 100 0,0 20 1
50 100000 100,0 99 1100 / 50 / 1850 / 50 100 1,01 50 / 250 / 100 99 0,0 1100 / 50 / 1850 / 50 4
100,0 100 100 101 1,0 50 100 0,0 100 1
100,0 100 50 100 0,0 50 100 0,0 50 1
100 100000 100,1 99 100 100 1,01 300 99 0,00 100 2
100,1 100 100 100 0,00 100 100 0,00 100 5


Diese Ergebnisse sagen nichts über Messgenauigkeit aus! Sie sagen nur etwas darüber aus, wie zuverlässig diese Messmethode ist! Da die Abweichungen in der Größenordnung des kleinsten dargestellen Wertes ist kann ich sie uneingeschränkt empfehlen.

Nun ist aber noch die Frage offen wie viele Einzelmessungen man denn nun kumulieren muss, um zu einem zuverlässigen Wert zu kommen. Das könnt Ihr mit dem Programm ADC_Abweichung.m5f selbst ermitteln dabei Eure individuellen Bedürfnisse zu grunde legen.

Für denjenigen, der nich lange herum experimentieren möchte hie meine Empfehlung:

Wie genau misst der ADC

Um das heraus zu bekommen habe ich wieder ein Programm geschrieben oder besser zusammen gepuzzelt. Damit ich alle Berechnungen im M5-StickC machen kann und nicht noch händisch Werte auf den PC übertragen muss, habe ich die Keyboard-Unit angeschlossen. So kann ich dem Programm die exakten Referenzwerte übergeben und alles andere mach der M5-StickC ):

Wie schnell ist der ADC

Wenn viele kumulierende Messungen erforderlich sind um zu einem brauchbaren Ergebnis zu gelangen, dann interessiert auch wie schnell die Messungen durchgeführt werden können. Das Datenblatt sagt, das 2 MSps also 2.000.000 Messungen in der Sekunde möglich sind. Es schweigt sich jedoch darüber aus, ob dieser Wert für die volle Auflösung von 12bit gilt oder nur bei reduzierter Auflösung. Es hilft alles nichts - es ist wieder Messen angesagt.

Eine einzelne Messung in Blockly ADC-Messdauer dauert ca. 78µs. Das entspricht knapp 13.000 Messungen in der Sekunde :( Von 2MSps ist da nicht viel übrig geblieben.

Eine For-Schleife mit 10.000 Messungen benötigt gut 1.400 ms. Bei 1000 Messungen wären das 140ms also ca. 7000 Messungen in der Sekunde.

Ein Blick auf den Micropythoncode zeigt, dass neben der Messwertabfrage auch noch range() abgearbeitet werden muss:

    for count2 in range(10000):
        messwert = adc0.read()

... und das auch noch interpretiert. Für schnelle Programme ist also C oder Assembler erforderlich.

Damit hat die Realität uns wieder. Für meine Temperaturüberwachung dürfte das aber ausreichen.

Dieses mal habe ich beim Programmieren alles richtig gemacht und kann das Programm unten auf dieser Seite zum Download bereitstellen.

Zusammenfassung

Zuerst möchte ich betonen, dass die hier vorgestellten Messungen mit einem M5-StickC mit der Seriennummer ... gemacht wurden und deshalb auch nur für diesen stimmen. Ich weiss nicht, wie es sich bei anderen Exemplaren verhält. Da Esprif selbst im Datenblatt Exemplarstreuungen +- 6 % angibt, ist damit zu rechnen, dass entsprechende Abweichungen auftreten werden.

Zusammenfassend lässt sich feststellen, dass der interne ADC des ESP-32 seinen schlechten Ruf nicht zu unrecht trägt. Das bedeutet aber nicht , dass er unbrauchbar ist. Durch kumulieren einer Reihe von Messungen lassen sich durchaus aktzeptable Ergebnisse erzielen.

Wie kommt die große Streuung der Messwerte zustande?

Downloads

Zum Download des Programms bitte mit der rechten Mousetaste auf den Link klicken und dann auf "Ziel speichern unter ..." mit der linken Mousetaste klicken. (Ich habe leider keine bessere Möglichkeit gefunden.)

ADC-Messdauer

ADC-Abweichung

Links

https://github.com/espressif/esp-idf/issues/164

https://github.com/espressif/arduino-esp32/issues/92

https://esp32.com/viewtopic.php?f=19&t=2881

https://esp32.com/viewforum.php?f=23&sid=430dca374801718984590f3b24158ced

https://www.instructables.com/id/Do-You-Know-About-ESP32-ADC-Adjustment/

https://www.youtube.com/watch?v=RlKMJknsNpo

https://github.com/G6EJD/ESP32-ADC-Accuracy-Improvement-function

https://www.youtube.com/watch?v=S34R4zg03uE

Diese Seite wurde zuletzt am 29. Juni 2020 um 18:44 Uhr geändert. Diese Seite wurde bisher 18.450 mal abgerufen.