Forum: Mikrocontroller und Digitale Elektronik ESP32 analogRead Schwankungen


von Ahmad A. (hmd96)


Lesenswert?

Hallo,
Ich bin momentan an meinem ersten Projekt und zwar ist es etwas recht 
einfaches: eine Lichtschranke bestehend aus einem Laser und LDR Modul, 
welche über die Blynk App einen Alarm an das Smartphone sendet.
Der Alarm wird dann ausgelöst, wenn das Modul einen analogen Wert über 
einem bestimmten Grenzwert liest.
Ich habe mir am Anfang das IoT Wifi Board von Conrad geholt (entspricht 
Arduino Nano mit ESP8266). Mit diesem funktioniert alles sehr gut aber 
aus Interesse und zum Vergleich habe ich mir heute ein ESP32 Dev Board 
geholt. Beim Anschluss des LDR Moduls habe ich festgestellt, dass dieses 
nicht über spezielle analoge Pins verfügt sondern jeder Pin durch den 
ADC auch einen analogen Wert auslesen kann. Diesen lass ich mir über den 
seriellen Monitor anzeigen. Das funktioniert auch und ich bemerke, dass 
der ESP32 viel schneller bootet und die Verbindung zum WLAN aufbaut aber 
ich habe sehr hohe Schwankungen festgestellt(20-100), das stört sehr da 
die Schwankungen teilweise den Alarm auslösen. Bei dem erstgenannten 
Board habe ich diese Schwankungen nicht also liegst denke ich, nicht am 
Modul
Leider kenne ich mich mit den Entwicklerboards noch nicht gut genug aus, 
sodass ich nicht selbst auf die Ursache komme.
Weiß jemand, was zu den Schwankungen führt und ob sich diese verhindern 
lassen?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ahmad A. schrieb:
> aber ich habe sehr hohe Schwankungen festgestellt(20-100)
Bei wieviel Bit ADC Auflösung?

> Weiß jemand, was zu den Schwankungen führt
Störeinkopplungen und schlechte Masseführung sind die Ursachen

> und ob sich diese verhindern lassen?
Störung abblocken und Masseführung optimieren.

Oder im Klartext: zeig doch mal deinen Aufbau und dessen Versorgung und 
teile zu den verwendeten Bauteilen greibare Daten mit.

von Blabla (Gast)


Lesenswert?

Keine Ahnung was das für ein Dev Board ist, aber in der Regel sind die 
ADC die in den ESP Controllern verbaut sind nicht sonderlich brauchbar. 
Zumindest ist das mein Eindruck.
Evtl kann man es mit Filtern und Stabilisierung der Versorgungsspannung 
noch verbessern. Es könnte auch helfen den Controller beim Messen 
schlafen zu legen, ich weiß aber nicht ob er das so unterstützt.
Eine einfache Lösung aus meiner Sicht wäre einen externen ADC zu 
verwenden der entsprechend deiner Anforderungen zu Parametrisieren.

Beitrag #5852279 wurde von einem Moderator gelöscht.
von Peter C. (peter_c49)


Lesenswert?

Hallo Ahmad,

wie "blabla" sagte, die ADC in den ESP's sind nicht so wie gut in 
anderen MCU's.
Ich habe mit dem ESP32 gar schlechtere ergebnisse als beim ESP8266 
erlebt.
Wer damit messen möchte, es gibt ein paar threads dazu in anderen Foren, 
sollten via go***e auffindbar sein.
Mein letzter bisher bester fund war hier: 
https://github.com/G6EJD/ESP32-ADC-Accuracy-Improvement-function.
Damit war es halbwegs linear und beunutzbar für meine 
Drucksensorauswertung (4-20mA gerät).
Besser einen externen ADC nehmen.

mfG
Peter ;-)

von Ahmad A. (hmd96)


Lesenswert?

Also was das auslesen angeht, lässt sich der Aufbau vereinfachen.
Das ESP Board ist dieses:
http://anleitung.joy-it.net/?goods=nodemcu-esp32

Das LDR Modul ist von Amazon: 
https://www.amazon.de/gp/product/B07DP1YM5X/ref=ppx_yo_dt_b_asin_title_o05_s02?ie=UTF8&psc=1

und ich verbinde eigentlich nur VCC mit dem 3.3V Pin, A0 mit dem ADC0/VP 
Pin und GND an GND.
Dann lese ich über analogRead den Wert aus und gib ihn im seriellen 
Monitor aus, während das Arduino fake bei gleichem Aufbau einen stabilen 
Wert von z.B. 200 anzeigt, gibt das ESP Schwankungen zwischen 150 und 
250.
Zwischenschaltungen habe ich keine.

Wie sähe so ein externer ADC aus und wo kriegt man das her?
Ich möchte es auch einfach halten, da ich wie gesagt noch am Anfang 
stehe.

An sich funktioniert es auch gut, nur haben mich die Schwankungen beim 
ESP verwirrt, scheint aber auch nicht zuverlässig zu sein, wenn ich mir 
die Antworten durchlese.

von Michael U. (amiga)


Lesenswert?

Hallo,

Du kannst Di ja hier mal durchwühlen:
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/adc.html

Ansonsten auf jeden Fall ADC1 nutzen (GPIOs 32 - 39), ADC2 wird vom WLAN 
gestört.

Gruß aus Berlin
Michael

von Andreas B. (bitverdreher)


Lesenswert?

Am besten geht das, wenn man WLAN (+ hier Bluetooth) während der Messung 
abstellt. Das ist fast immmer ein Problem mit den ESPs.

von olaf (Gast)


Lesenswert?

> Wie sähe so ein externer ADC aus und wo kriegt man das her?

Er sieht aus wie ein normales IC halt so aussieht. Sowas wird von 
Dutzenden Firmen hergestellt und jede hat wohl zwischen 10 und 100 im 
Programm. Und jeder Elektronikhaendler hat mindestens ein Dutzend Typen 
auf Lager.

> Ich möchte es auch einfach halten, da ich wie gesagt noch am Anfang
> stehe.

Du erreichst aber gerade Gebiete wo es nicht mehr einfach sein kann. .-)

Man hat dir schon gesagt das es sehr auf das Layout ankommt. Mit 
steigender Anforderung an die Aufloesung um so mehr. Ein HF-Sender auf 
der Platine zu haben macht es leider auch nicht einfacher.

Was man dir noch nicht gesagt hat:

1. Es kann sinnvoll sein einen kleinen Kondensator (z.B 100pF) direkt am 
ADC-Eingang zu haben. Der sollte dann HF wegfiltern.

2. Es gibt ADCs die ziehen beim samplen jedesmal etwas Strom und wenn du 
eine sehr hochohmige Quelle hast dann kann auch ein grösserer 
Kondensator (100nF) am Eingang nicht schaden.

3. Manchmal schadet ein 100nF aber leider deiner Signalquelle, z.B wenn 
da OP drauf ist der mit der kapazitiven Belastung nicht klar kommt. Da 
gibt es dann wieder andere Strategien.

Wenn du dir einen externen ADC aussuchst dann achte darauf einen mit 
interner Referenz zu nehmen und einen mit einem seriellen Bus (entweder 
SPI oder I2C) mit dem du klar kommst. Und liess vorher das Datenblatt. 
Waehle den Baustein nach der Lesbarkeit des DAtenblatts aus.

Olaf

von Klaus R. (klara)


Lesenswert?

Hallo Ahmad,
Du hast doch schon zwei vielversprechende Tipps erhalten.

Michael U. schrieb:
> Du kannst Di ja hier mal durchwühlen:
> 
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/adc.html

Dort findest Du:

Note

Since the ADC2 is shared with the WIFI module, which has higher 
priority, reading operation of adc2_get_raw() will fail between 
esp_wifi_start() and esp_wifi_stop(). Use the return code to see whether 
the reading is successful.

>
> Ansonsten auf jeden Fall ADC1 nutzen (GPIOs 32 - 39), ADC2 wird vom WLAN
> gestört.

Andreas sagt es noch deutlicher:

Andreas B. schrieb:
> Am besten geht das, wenn man WLAN (+ hier Bluetooth) während der Messung
> abstellt. Das ist fast immmer ein Problem mit den ESPs.

Gerade beim WLAN nimmt der ESP32 ganz schön Strom auf. Die Spannung 
bricht dann für kurze Zeit ein. Probiere zuerst den ADC1, dann wenn noch 
keine Besserung eintritt, schalte WLAN (+ hier Bluetooth) während der 
Messung ab.

Melde Dich dann.
mfg Klaus

: Bearbeitet durch User
von Klaus R. (klara)


Lesenswert?

Ahmad A. schrieb:
> aber
> ich habe sehr hohe Schwankungen festgestellt(20-100)

Lothar M. schrieb:
> Ahmad A. schrieb:
>> aber ich habe sehr hohe Schwankungen festgestellt(20-100)
> Bei wieviel Bit ADC Auflösung?

Hallo Ahmad,
wie sieht denn Dein Code aus? Mit welcher Auflösung wird gemessen?

adc1_config_width(ADC_WIDTH_BIT_12);

The value read in both these examples is 12 bits wide (range 0-4095).

Also bei 12 Bit Auflösung hätten wir bei einem Störwert von 100 und das 
sind nur 2,4% vom Maximalwert. Das ist eigentlicht nicht allzu schlecht.

Noch ein Hinweis zur Minimierung von Störungen.
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/adc.html#minimizing-noise
mfg klaus

von Ahmad A. (hmd96)


Lesenswert?

Also da ist ja einiges an Infos zusammengekommen. Ich danke euch auch 
wegen eurer Geduld, wie gesagt ist das mein erster Kontakt mit dem ESP 
daher konnte ich mich noch nicht wirklich einarbeiten.
Ich werde auf jeden Fall daran denken, es nur an ADC1 anzuschließen, 
wegen des WLAN Problems, das hatte ich auch bereits gelesen.


olaf schrieb:
> 1. Es kann sinnvoll sein einen kleinen Kondensator (z.B 100pF) direkt am
> ADC-Eingang zu haben. Der sollte dann HF wegfiltern.
>
> 2. Es gibt ADCs die ziehen beim samplen jedesmal etwas Strom und wenn du
> eine sehr hochohmige Quelle hast dann kann auch ein grösserer
> Kondensator (100nF) am Eingang nicht schaden.
>
> 3. Manchmal schadet ein 100nF aber leider deiner Signalquelle, z.B wenn
> da OP drauf ist der mit der kapazitiven Belastung nicht klar kommt. Da
> gibt es dann wieder andere Strategien.


Ich habe es außerdem einmal mit den Kondensatoren ausprobiert. Einen 
wirklichen Unterschied konnte ich nicht feststellen. Also der 
Kondensator käme sozusagen zwischen den Pin und das Modul?

Klaus R. schrieb:
> Also bei 12 Bit Auflösung hätten wir bei einem Störwert von 100 und das
> sind nur 2,4% vom Maximalwert. Das ist eigentlicht nicht allzu schlecht.

Ich habe tatsächlich nicht daran gedacht, genau es ist eine 12 Bit 
Auflösung. Lässt sich das über adc1_config_width(ADC_WIDTH_BIT_12); 
einstellen, sodass ich auf 0-1023 komme und kässt sich das einfach so 
übernehmen?
Betrachtet man das in dem Rahmen ist das tatsächlich nicht so schlimm. 
Dennoch wäre es hilfreich die Ausreißer zu verhindern. Wie schon im 
Beispiel vorher genannt liegt der Wert bei Tageslicht bei ca. 200 und 
schwankt von 150-250, zwischendurch gibt es aber auch Ausreißer die bei 
z.b. 500 liegen.


Ein anderes Problem habe ich mittlerweile gefunden, wenn ich den 
digitalRead Befehl nutze (das verwendete Modul hat einen analogen und 
einen digitalen Anschluss). Das funktioniert in meinem Code gar nicht 
mit dem ESP32 aber mit dem Arduino.


Ich benutze die Arduino IDE.
Hier mal beide Codes.
Der Erste ist zum Auslesen des LDR Moduls:
1
const int ldranalog = A0; 
2
3
void setup()
4
{
5
  pinMode(ldranalog, INPUT);
6
  Serial.begin(115200);
7
}
8
9
void loop()
10
{
11
   int analogValue = analogRead(ldranalog);
12
   Serial.println(analogValue);
13
   delay(500);  
14
}

und das zweite ist der Code, wo ich das Problem mit digitalRead habe. 
Ist der Code so nicht anwendbar? Ich habe es so weit es geht gekürzt:
1
const int ldrdigital = 32;  
2
boolean Alarm = false;   
3
4
void loop()
5
{
6
  int digitalValue = (digitalRead(ldrdigital)
7
  if (digitalValue == HIGH){                 
8
  Alarm = true;
9
  
10
  if (Alarm){
11
12
     Serial.println("Der Alarm wurde ausgelöst!");
13
  } 
14
}

von Klaus R. (klara)


Lesenswert?

Ahmad A. schrieb:
> Ich habe tatsächlich nicht daran gedacht, genau es ist eine 12 Bit
> Auflösung. Lässt sich das über adc1_config_width(ADC_WIDTH_BIT_12);
> einstellen, sodass ich auf 0-1023 komme und kässt sich das einfach so
> übernehmen?

https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/adc.html#api-reference

The full-scale voltage is the voltage corresponding to a maximum reading 
(depending on ADC1 configured bit width, this value is: 4095 for 
12-bits, 2047 for 11-bits, 1023 for 10-bits, 511 for 9 bits.)

https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/adc.html#_CPPv425adc1_config_channel_atten14adc1_channel_t11adc_atten_t

Set the attenuation of a particular channel on ADC1, and configure its 
associated GPIO pin mux.

The default ADC full-scale voltage is 1.1V. To read higher voltages (up 
to the pin maximum voltage, usually 3.3V) requires setting >0dB signal 
attenuation for that ADC channel.

Dem ADC kann noch intern ein Verstärker zugeschaltet werden.

When VDD_A is 3.3V:

    0dB attenuaton (ADC_ATTEN_DB_0) gives full-scale voltage 1.1V
    2.5dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5V
    6dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2V
    11dB attenuation (ADC_ATTEN_DB_11) gives full-scale voltage 3.9V 
(see note below)

Aber in der Praxis geht der Meßbereich nicht hinunter zu 0 V und 3,9 V 
macht der bei VDD_A = 3,3 V auch nicht.

    At 11dB attenuation the maximum voltage is limited by VDD_A, not the 
full scale voltage.

    0dB attenuaton (ADC_ATTEN_DB_0) between 100 and 950mV
    2.5dB attenuation (ADC_ATTEN_DB_2_5) between 100 and 1250mV
    6dB attenuation (ADC_ATTEN_DB_6) between 150 to 1750mV
    11dB attenuation (ADC_ATTEN_DB_11) between 150 to 2450mV

Diese Einschränkungen lassen sich aber per Software kalibrieren.

https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/adc.html#calibration-values

Es gibt dazu auch vollständige Beispiele.
mfg Klaus

von äxl (Gast)


Lesenswert?

Ahmad A. schrieb:
> Ist der Code so nicht anwendbar? Ich habe es so weit es geht gekürzt:
> const int ldrdigital = 32;
> boolean Alarm = false;
>
> void loop()
> {
>   int digitalValue = (digitalRead(ldrdigital)
>   if (digitalValue == HIGH){
>   Alarm = true;
>
>   if (Alarm){
>
>      Serial.println("Der Alarm wurde ausgelöst!");
>   }
> }

fehlt irgendwie 'ne Klammer?
Oder ist die schliessende "void loop(){...}" einfach jetzt weggelassen 
worden?
Ansonsten hätte ich das evtl. auch so gemacht.
"Alarm" wirst Du sicher woanders noch brauchen, also alles richtig, 
würde ich sagen...

von Ahmad A. (hmd96)


Lesenswert?

äxl schrieb:
> fehlt irgendwie 'ne Klammer?
> Oder ist die schliessende "void loop(){...}" einfach jetzt weggelassen
> worden?
> Ansonsten hätte ich das evtl. auch so gemacht.
> "Alarm" wirst Du sicher woanders noch brauchen, also alles richtig,
> würde ich sagen...

Ja anscheinend sind einige Klammern beim kürzen verloren gegangen, daran 
liegt es aber nicht.
Der Fehler liegt darin, dass der Alarm immer auslöst, egal wie stark die 
Lichteinstrahlung ist, obwohl das Modul sogar ein integriertes 
Potentiometer hat, mit dem man einstellen kann bei welcher Spannung es 
"schaltet".
Und wie gesagt mit dem Arduino geht das, mit dem ESP32 schaltet es halt 
immer auf Alarm.

von Gnorm (Gast)


Lesenswert?

: und ) fehlt auch. Also bitte richtig kopieren.

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.