Analogwerte schwanken nach Neustart, ungenau mit ADS1115 GY-61 am ESP8266

Hallo zusammen,

nach einer Dekade Pause widme ich mich einem neuen Arduino Projekt. Leider komme ich an einer Stelle nicht weiter und brauche eure Unterstützung.

Beim Auslesen der Analogwerte des GY-61 über einen ADS1115 am ESP8266-12F treten immer wieder schwankende Werte auf. Ich habe den Sensor kalibriert und mir eine kleine Tabelle dazu angelegt, da die Werteverhältnisse des Sensors nicht linear sind. Mit der multiMap() Finktion bekomme ich die Werte prima ins Raster. Es fällt allerdings auf, dass sich die ausgelesenen Messwerte nach jedem Neustart des ESP verändern.

Nach etwas Recherche soll das an schwankenden Spannungen liegen. Ich betreibe die Schaltung daher nun hinter einem 3,3V Festspannungsregler LF33CV und einem 100uF Kondensator.
Bei den Arduino Onboard ADC lässt sich der Referenzwert der Spannung nach entsprechender Verdrahtung einbeziehen. Wenn ich es richtig verstanden habe, benötigt man das beim ADS1115 nicht, da ein interner Komperator das selber macht.

Da ich nur die X-Achse benötige, und auch nur 0°-90° habe ich den GY-61 nur mit X an den A2 des ADS115 angeschlossen. Ein 10kOhm Widerstand in Pull-down zieht den Eingang dann auf GND.

Habt ihr einen Tipp für mich, wie ich die Messwerte so stabil bekomme, dass die Winkelanzeige auch Grad-genau funktioniert?

Vielen Dank!

Anbei ein paar Code Schnipsel:

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <Adafruit_ADS1X15.h>
#include "MultiMap.h"

Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */

// Variable declaration ADC for ADS1115
uint16_t adc0, adc1, adc2, adc3, adc4;
float volts0, volts1, volts2, volts3;

//Variable declaration Y average
const int yAvgNo = 20;
int yAvg[yAvgNo];
int yAvgSum;
float yAngle;

// Variable Declaration transmission cycle sent to LOXONE
unsigned long previousMillis = 0; 
const long sendInterval = 500; 

void setup() {
  // Serial Output
  Serial.begin(115200);
  Serial.println("Booting");
  
  // Define GPIO
  pinMode(LED_BUILTIN, OUTPUT);

  // Send UDP Ready 
  sendUDP("UDP Ready", 1);

 // The ADC input range (or gain) can be changed via the following
  // functions, but be careful never to exceed VDD +0.3V max, or to
  // exceed the upper and lower limits if you adjust the input range!
  // Setting these values incorrectly may destroy your ADC!
  //                                                                ADS1015  ADS1115
  //                                                                -------  -------
  // ads.setGain(GAIN_TWOTHIRDS);  // 2/3x gain +/- 6.144V  1 bit = 3mV      0.1875mV (default)
     ads.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV  (perfect for 3.3V)
  // ads.setGain(GAIN_TWO);        // 2x gain   +/- 2.048V  1 bit = 1mV      0.0625mV
  // ads.setGain(GAIN_FOUR);       // 4x gain   +/- 1.024V  1 bit = 0.5mV    0.03125mV
  // ads.setGain(GAIN_EIGHT);      // 8x gain   +/- 0.512V  1 bit = 0.25mV   0.015625mV
  // ads.setGain(GAIN_SIXTEEN);    // 16x gain  +/- 0.256V  1 bit = 0.125mV  0.0078125mV
  
  ads.begin();
}

void loop() {
  ArduinoOTA.handle();
  readADS1115();
  yAngleCalc();
  

  // Read ADC with interval
  unsigned long currentMillis = millis(); 
    if (currentMillis - previousMillis >= sendInterval) { 
        sendUDP("Photo.Top: ", volts0);
        sendUDP("Photo.Bottom: ", volts1);
        sendUDP("Gyro.Y.Analog: ", adc2);
        sendUDP("Gyro.Y.Volt: ", volts2);
        sendUDP("Gyro.Y.Angle: ", yAngle);
      previousMillis = currentMillis;      
  }

  digitalWrite(LED_BUILTIN, millis() % 2000 > 900 ? LOW : HIGH);

}


// Function to read ADC Data from ADS 1115 in 16bit
void readADS1115(){
  adc0 = ads.readADC_SingleEnded(0);
  volts0 = ads.computeVolts(adc0);

  adc1 = ads.readADC_SingleEnded(1);
  volts1 = ads.computeVolts(adc1);

  adc2 = ads.readADC_SingleEnded(2);
  volts2 = ads.computeVolts(adc2);

  adc3 = ads.readADC_SingleEnded(3);
  volts3 = ads.computeVolts(adc3);
}


//Function to calculate Y Angle by using average of yAvg(20)
void yAngleCalc(){
  
for (int i = yAvgNo-1; i>0; i--){
  yAvg[i] = yAvg[i - 1];
  yAvgSum+=yAvg[i];
}
yAvg[0] = ads.readADC_SingleEnded(2);
yAvgSum+=yAvg[0];
yAvgSum = yAvgSum / yAvgNo;

int inputArray[] = {2632, 2647, 2670, 2715, 2784, 2866, 2957, 3061, 3170, 3277};
int outputArray[] = {90, 80, 70, 60, 50, 40, 30, 20, 10, 0};

yAngle = multiMap(yAvgSum, inputArray, outputArray, 10);

    Serial.print("Y average Sum: ");
    Serial.print(yAvgSum);
    Serial.print(" Winkel: ");
    Serial.println(yAngle);
}


// Hypofunction to send UDP packets
void sendUDP(String text, float value){
    Udp.beginPacket(RecipientIP, RecipientUdpPort);
    Udp.print(text);
    Udp.print(value);
    Udp.endPacket();
    delay(2);
}

Hast Du dir mal das Datenblatt vom LF33 angeschaut? Darin steht, dass er mit einer Ausgangskapazität ab 2,2μF stabil arbeitet. Es könnte sein, dass Du mit 100μF eine viel zu große Ausgangskapazität verwendest und der LDO deswegen schwingt. Versuch es doch mal mit einem max. 10μF Elko am Ausgang und 100nF Kerko am Eingang.

Kann sein, dass es hilft…

1 Like

Moin Kai,

danke für den Tipp!

Ne hatte ich nicht, das war gestern der letzte Schritt bevor ich einen Thread auf mache und es war spät :slight_smile:

Hab die Schaltung dahingehend angepasst, allerdings war das Verhalten auch schon vorher mit dem Steckernetzteil.

Hatte die Schaltung heute den Tag über immer mal wieder ein und aus geschaltet und jedes Mal weicht mein Winkel um 2-3° ab. Mal nach oben, mal nach unten und das nach jedem Einstecken des Steckernetzteils reproduzierbar, jedoch weiß man vorher nicht ob nach oben oder unten.

Ich berechne den Mittelwert über 20 Zyklen, bei 30 wird es schon merkenswert langsamer und die Winkelanzeige zieht nach. Aber auch das ändert nichts an der Ungenauigkeit.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.