Arduino Mikrocontroller Tutorials - Module

ADC Wandler (Bsp. ADS1115)

Bild ADS1115

Beim IC ADS115 handelt es sich um einen Analog zu Digital Converter (ADC) mit 16 Bit Auflösung. Die Auflösung des Messbereiches kann zu der erwarteten Spannungshöhe eingestellt werden. Die maximal messbare Spannung ist ±6,144V. Es gibt 4 Analoge Messeingänge die mit Bezug auf GND oder als Differenz zweier Eingänge zueinander ausgegeben werden können. Die Messrate kann eingestellt werden. Von einer Messung erst auf Anforderung zu einer Dauermessung von bis zu 860 SPS (Samples Per Second). Im IC ist auch ein Komparator integriert. Bei erreichen einer einstellbaren Spannungsschwelle wird am Ausgang ALERT ein Signal ausgegeben.

Pinbelegung
VDD Spannungsversorgung +
GND Masse -
ADDR Pin um die I2C Adresse einzustellen.
Mit offenem Eingang ist die Adresse in 0x48
AIN0-AIN3 Analoge Messeingänge
ALERT/RDY
SDA I2C Datenleitung
SCL I2C Clockleitung

Funktionsweise ADS1115

Multiplexer (MUX)

Funktionsschaubild ADS1115

Über den Multiplexer wird der Eingang ausgewählt, welcher gemessen wird und dessen Messwert im Messwertspeicher abgelegt wird. Es kann nur ein Eingang oder eine Differenzspannung von zwei Eingängen gleichzeitig gemessen werden.

Verstärker (PGA)

Noch vor dem eigentlichen ADC können die analogen Signale mit einem 'Programmable Gain Amplifier' durch die Erhöhung der Gain-Spannung verstärkt werden. Da das ausgehende und in den ADC eingehende Signal eine Auflösung von 215=32768 hat ändert sich dadurch auch die Auflösung der Spannungsmessung. Wenn ±0,256V maximal gemessen werden werden ist die Auflösung 7,8125μV (0.256V/3278). Müssen die 32768 Stufen auf ±6,144V aufgeteilt werden ist die Auflösung mit 187.5 μV deutlich gröber.
Hinweis: Da eine Stelle des 16bit ADC für die Polarität (+/-) reserviert ist, beträgt die eigentliche Auflösung nur 15 Bit übrig.

ADC

Der hier verwendete Analog Digital Converter arbeitet nach dem Delta-Sigma (ΔΣ) Prinzip. Ein interner Komparator ist dabei so verschaltet, dass bis zur Schaltschwelle zuerst ein Kondensator geladen sein muss. Wie schnell der Kondensator geladen wird ist spannungsabhängig.
Der Ausgang des Komparators wird, gesteuert durch einem Oszillator, regelmäßig abgefragt und die Clock-Pulse dabei bis zum Schalten des Komparators gezählt. Wenig Pulse bis zum Schalten entsprechen dann einer hohen Spannung. Vergehen viele Pulse bis zum Erreichen der Schaltschwelle liegt eine geringere Spannung an.

Komparator

Der ALERT Ausgang wird durch einen oder zwei Komparatoren angesteuert. Bei der 'konventionellen' Einstellung ist ein Komparator aktiv welcher beim Überschreiten der High-Schwelle ein Signal auf den Ausgang gibt. Bei der 'window' Einstellung sind zwei Komparatoren aktiv und der Messwert muss innerhalb eines Fensters bleiben. Beim Überschreiten der High-Schwelle oder beim Unterschreiten der Low-Schwelle wird der ALERT Ausgang angesteuert.

I2C Kommunikation

Der ADS1115 hat 5 Register die über I2C von außen zugänglich sind. Standardmäßig greift I2C mit dem ersten übertragenen byte auf das Address Pointer Register zu. In diesem Register wird dann ein Pointer zu einem der 4 anderen Register gesetzt. Das dann folgende Übertragungsbyte wird dann in das verwiesene egister geschrieben oder Daten von dort angefordert.

Die 4 Register auf die das 'Address Pointer Register' verweist sind: Das Config Register in dem sämtliche Einstellungen vorgenommen werden, das Conversion Register in dem die Messwerte zur Abholung gespeichert sind, und noch 2 Register um eine obere (Hi_thresh Register) und eine untere (Lo_thresh Register) Alarmschwelle für den ALERT Ausgang anzugeben.

Registereinträge ändern

Zum ändern von Registereinträgen wird mit Wire.beginTransmission(Adresse) der ADC Slave über seine I2C Adresse angesprochen und zum Lesen aufgefordert. Das erste byte landet im 'Address Pointer Register'. Dort kann man dann den Pointer für die folgenden Daten beispielsweise auf das 'Config Register' setzten. Das 'Config Register' ist 16 Stellen lang. Es müssen also zwei weitere Bytes übertragen werden. Mit Wire.endTransmission() wird die I2C Übertragung durch den Mikrocontroller (Master) beendet.

Wire.beginTransmission(0x48); Wire.write(B00000001); // Pointer im Addressregister auf 'Config Register' setzen Wire.write(B01000010); // MSB (Bits 15-8) des 'Config Registers' setzen Wire.write(B00000010); // LSB (Bits 7-0) des 'Config Registers' setzen Wire.endTransmission();

Registereinträge anfordern

Auch hier müssen wir zunächst das Pointer Register mit dem Verweis auf das Messwerteregister beschreiben.

Wire.beginTransmission(0x48); Wire.write(0b00000000); // Pointer im Addressregister auf 'Config Register' setzen Wire.endTransmission();

Wenn der Pointer für die folgenden Übertragung gesetzt ist können die Messwerte mit Wire.requestFrom(Adresse, Anzahl erwarteter Bytes) angefordert werden. Bei der I2C Übertragung werden die Daten immer Byteweise übertragen. Um das 16 bit Register des Messwerts zu übertragen werden also zwei Bytes gesendet. Zuerst das HighByte, dann das LowByte.

Wire.requestFrom(0x48, 2); unsigned int messWert = Wire.read() << 8 ; // High Byte 8 Stellen nach links schieben messWert = messWert | Wire.read(); // Low Byte hinzufügen

Register des ADS1115

Address Pointer Register

Das Register hat die Größe von einem byte. Nur die zwei LSB werden für die Adressierung benötigt. Das Register kann nur beschrieben werden.
B00000000 : Conversion register (default)
B00000001 : Config register
B00000010 : Lo_thresh register
B00000011 : Hi_thresh register

Conversion Register

In diesem 16 Bit Register wird der Messwert der letzten Messung gespeichert. Es ist nur der Messwert gespeichert welcher im Config Register ausgewählt wurde. Das MSB kennzeichnet ob es sich um einen Minus oder Pluswert handelt. Der eigentliche Messwert hat damit ein Auflösung von 215 = 32768. Das Register kann nur gelesen werden.

Config Register

Dieses Register hat eine Größe von 16 Bit. Das Config Register kann neu beschrieben oder die Einstellwerte ausgelesen werden.

MSB Einzelmessung auslösen
0 : keine Auslösung
1 : Auslösung wenn mt bit 8 Einzelmessung eingestellt ist
14-12 Hier werden die Messeingänge ausgewählt (Multiplexer)
000 : Differenz zwischen AIN0 und AIN1 (Standard)
001 : Differenz zwischen AIN0 und AIN3 (default)
010 : Differenz zwischen AIN1 und AIN3
011 : Differenz zwischen AIN2 und AIN3
100 : Differenz zwischen AIN0 und GND
101 : Differenz zwischen AIN1 und GND
110 : Differenz zwischen AIN2 und GND
111 : Differenz zwischen AIN3 und GND
11-9 Verstärkungsfaktor auswählen (PGA)
Der Messbereich kann angepasst werden, so dass kleine Messwerte verstärkt werden um die 16 bit Auflösung auszunutzen.
000 : ±6.144 V
001 : ±4.096 V
010 : ±2.048 V (default)
011 : ±1.024 V
100 : ±0.512 V
101 : ±0.256 V
8 Messmodus auswählen
0 : kontinuierliche Messung
1 : Einzelmessung auf Anforderung über MSB (default)
7-5 Messfrequenz (Abtastrate) einstellen
000 : 8 SPS (Samples per Second)
001 : 16 SPS
010 : 32 SPS
011 : 64 SPS
100 : 128 SPS (default)
101 : 250 SPS
110 : 475 SPS
111 : 860 SPS
4 Komparator-Modus einstellen
0 : nur oberer Grenze aktiv (default)
1 : Window Komparator mit aktiver oberen und unteren Grenze
3 Polarität des ALERT Ausgangs einstellen
0 : Active low (default)
1 : Active high
2 ALERT Ausgang auf 'latch' stellen
0 : latch nicht aktiviert (ALERT ist nur aktiv solange die Messwerte außerhalb der Grenzen ist)
1 : latch aktiviert (ALERT bleibt bis zum Lesen der Messwerte angesteuert)
1-LSB Einstellen wie oft die der Komparator eine Grenzverletzung erkennen muss, bevor ALERT angesteuert wird
00 : nach einer einer Überschreitung
01 : nach zwei Überschreitungen
10 : nach vier Überschreitungen
11 : Komparator ausgescchlatet (default)

Lo_thresh Register

Hier wird in 16 bit die untere Toleranzgrenze für die Ansteuerung des ALERT Ausgangs angegeben

Hi_thresh Register

Hier wird in 16 bit die obere Toleranzgrenze für die Ansteuerung des ALERT Ausgangs angegeben.

Programmcode

#include "Wire.h" void setup() { Serial.begin(9600); Wire.begin(); } void loop() { // Konfigurationsregister einstellen Wire.beginTransmission(0x48); Wire.write(B00000001); // Pointer im 'Address Register' auf 'Config Register' setzen Wire.write(B11000001); // MSB (Bits 15-8) des 'Config Registers' setzen Wire.write(B00000000); // LSB (Bits 7-0) des 'Config Registers' setzen Wire.endTransmission(); // Pointer auf das Ergebnisregister stellen Wire.beginTransmission(0x48); Wire.write(0b00000000); // Pointer im 'Address Register' auf 'Config Register' setzen Wire.endTransmission(); // Messwert auslesen (2 Byte) Wire.requestFrom(0x48, 2); unsigned int messWert = Wire.read() << 8 ; // High Byte 8 Stellen nach links schieben messWert = messWert | Wire.read(); // Low Byte hinzufügen // Messwert ausgeben Serial.print(messWert); Serial.print("\t"); Serial.print(map(messWert, 0, 32767, 0, 6144)); Serial.println(" mV"); delay(250); }