Translate

03 Mai 2016

Verbesserte Strommessung per I²C AD-Wandler

........wenns schon mit meinem Triebwerk nicht weitergeht,
weil ich meine Nabe noch immer nicht habe......
oder einfach mal als kleines Lebenszeichen von mir!

Zwischendurch mal ein kleines bisschen Elektronik und Programmierung.
Diesmal ganz entgegen meiner sonstigen Gewohnheit auf einem Arduino!
Eine kleine Arduino-Übung für mich, und für die Allgemeinheit wohl besser
geeignet als Bascom, womit ich eigentlich lieber arbeite, weil man da insbesondere bei
PWM-Geschichten flexibler ist und viel problemloser Quarzfrequenzen und Vorteiler
an die persönlichen Bedürfnisse anpassen kann.
Na ja, alles hat seine Vor-und Nachteile.Ein ganz besonderer "Liebling" von mir ist ja der
Freeduino serial v2.0 den es z.B. bei Watterott günstigst gibt.
Die "echte" Serielle Schnittstelle hat was! Damit lässt sich so manches anfangen,
was mit USB nicht möglich ist,wenn man nicht gerade an einem PC hängt.

Die Problematik bei der Strommessung in der Franzbox ist nach wie vor
nicht behoben.
Zur Erinnerung: Ich messe den Strom mit einem LEM HASS200S Wandler.
Dieser wird an 5V betrieben und liefert ein Ausgangssignal von theoretisch
0V = -800A  2,5V= 0A und 5V=800A sowie eine Referenzspannung für den Nullpunkt
(Nur zum Berechnen, in der Praxis sind +-600A möglich, da die Ausgangsspannung
nicht bis 0V bzw 5V geht)
Ich habe die Referenz nicht verwendet, sondern nur auf 0A abgeglichen
und das Ausgangssignal direkt auf einen ADC-Eingang des Atmega gelegt.
Die Genauigkeit bei hohen Strömen (Entnahme) ist ausreichend,aber
bei geringeren Strömen (Ladevorgang) ist die Auflösung einfach zu grob
um wirklich verlässliche Werte zu bekommen.

es hätte hier auch keinen Sinn gemacht, die Referenzspannung auszuwerten.
Das Problem kann eigentlich nur mit einem deutlich feiner auflösenden ADC
mit differentiellem Eingang gelöst werden.
Ich habe vor einiger Zeit schon mal sehr erfolgreiche Versuche mit einem
solchen Baustein gemacht, aber die Verfügbarkeit sowie die winzige Bauform
waren nicht optimal.

Nun habe ich es nochmal mit einer Platine von Adafruit versucht.
Der 12Bit-Wandler ADS1015 ist für diese Aufgabe auch wunderbar geeignet und fertig verlötet
problemlos lieferbar.
Es gibt auch eine Pin-kompatible Version ADS1115 mit 16Bit Auflösung,
die hier noch Vorteilhaft sein könnte.
Der ADS1115 ist etwas langsamer, aber locker schnell genug.

I²C braucht nur zwei Leitungen, und ist notfalls auch "galvanisch getrennt" machbar.
Beim Stromwandler gehts ohne Trennung, aber wenn auch noch die Akkuspannung
gemessen werden sollte wird das ein Thema.
Der ADS1015 hat vier Analogeingänge die per internem Multiplexer wahlweise
gegen GND oder als zwei Differenzeingänge konfiguriert werden können.

in Default-Konfiguration beträgt die Auflösung 3mV, das ist nicht sehr viel besser,
als die bisherigen ca 5mV, aber da auch der Bereich von +-2,048V bezogen auf die
Referenz von 2,5V ausreicht, um den LEM-Sensor auszulesen kommt man dann
auf eine Auflösung von 1mV, und das ist dann das fünffache (korrekt 1/5 ;-)  )an Auflösung, verglichen mit dem Atmega-Onboard-ADC bzw  0.0625mV Auflösung bei
Verwendung des ADS1115. (Das ist dann eine ganz andere Liga!)

Für den ersten Funktionstest Test habe ich es mir einfach gemacht und ein Demo-Programm
angepasst. Alles nur mal auf dem Breadboard zusammengesteckt und getestet.
Der "Freeduino serial V2.0" links im Bild dient hier übrigens nur als 5V-Netzteil.
Ein Arduino Nano war auf dem Steckbrett deutlich besser zu handhaben.

Mein Versuchsaufbau:


































Das Arduino-Programm:

Ich habe hier nur ein Demoprogramm von Adafruit, das die Daten seriell
über USB/serial ausgibt um eine LCD-Anzeige ergänzt.
Die Library gibts bei Adafruit zum Downloaden.
Achtung! die Zeilenumbrüche könnten hier im kopierten Text etwasverschoben sein,
und das Einfügen von Text in spitzen Klammern nach include  der Libs klappt hier nicht!

#include  Wire.h
#include  Adafruit_ADS1015.h
#include  LiquidCrystal.h



LiquidCrystal lcd(11, 10, 2, 3, 4, 5);
// Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */
Adafruit_ADS1015 ads;     /* Use thi for the 12-bit version */

void setup(void)
{
lcd.begin(16, 2);
lcd.setCursor(0, 0);

  Serial.begin(9600);
  Serial.println("Hello!");

  Serial.println("Getting differential reading from AIN0 (P) and AIN1 (N)");
  Serial.println("ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015, 0.1875mV/ADS1115)");

  // 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
  // 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(void)
{
  int16_t results;

  /* Be sure to update this value based on the IC and the gain settings! */
  float   multiplier = 3.0F;    /* ADS1015 @ +/- 6.144V gain (12-bit results) */
  //float multiplier = 0.1875F; /* ADS1115  @ +/- 6.144V gain (16-bit results) */

  results = ads.readADC_Differential_0_1();
 
  Serial.print("Differential: "); Serial.print(results); Serial.print("("); Serial.print(results * multiplier); Serial.println("mV)");


lcd.setCursor(0, 0);
lcd.print("ADC Wert:");
lcd.print(results);
lcd.print("  ");
lcd.setCursor(0, 1);
lcd.print(results*multiplier);
lcd.print(" mV  ");

  delay(100);



Keine Kommentare:

Kommentar veröffentlichen