Donnerstag, 22. August 2013

Dynamische Messung der Stromaufnahme

Um die Belastung der Batterie unter realen Bedingungen zu messen, wurde der Stromverbrauch des Gesamtsystems in einer dem Zustand bei der tatsächlichen Messung ähnlichen Konfiguration bestimmt. Die Messungen wurden ohne Sensor durchgeführt, da verschiedene Sensoren einen unterschiedlichen Stromverbrauch haben. Falls der Sensor keine erhebliche Stromaufnahme oder (insbesondere) eine erhebliche Anlaufzeit benötigt, ist dieser für die folgende Betrachtung zu vernachlässigen.

Die Stromaufnahme des Arduino im sleep-mode (powerDown, ADC_OFF, BOD_OFF) beträgt statisch gemessen ca. 40 µA (direkte Strommessung, Philips PM 2503).

Konfiguration: Arduino Fio, XBee Series 2, LiPo Akku 850 mAh, LowPower V. 1.30 https://github.com/rocketscream/Low-Power)

Die dynamischen Messungen wurden als Spannungsmessungen über einem 1 Ω 1% Widerstand mit einem HP 54200A Digitaloszilloskop ausgeführt.

Um zu prüfen, ob die Stromaufnahme, insb. des XBee-Moduls beim Einschalten einen höheren Peak als während des Betriebs hat, wurde eine Kontrollmessungen mit einem analogen Speicheroszilloskop (HP1741A) durchgeführt, die keine Anzeichen dafür lieferten.


Zunächst wurde der Stromverbrauch des Arduino-Boards ohne XBee-Modul gemessen:

Dazu wurde der Controller 15msec in den sleep Modus versetzt, dann über die Standard-delay-Funktion 100msec gewartet. Die Stromaufnahme des Controllers beträgt etwa 5mA.
Die sleep-Dauer scheint nicht ganz der Angabe von 15msec zu entsprechen, sondern eher etwa 20msec zu betragen. Bei Bedarf sollte dies durch eine genauere Messung geklärt werden. Die Messung wurde bei längeren sleep-Dauern wiederholt, um eine erhöhte Stromaufnahme bei längerer Dauer auszuschließen. Dafür ergab sich kein Anhaltspunkt.

Daraufhin wurde die Stromaufnahme mit XBee-Modul gemessen.

Da das XBee-Modul mindestens etwa 3 Sekunden „wach“ blieb[1], wurde im Versuch eine sleep-Dauer von 8 Sekunden (der Maximalwert) verwendet. Die Abbildung zeigt, dass die Stromaufnahme jetzt etwa 40 mA beträgt. Dies deckt sich mit statischen Messungen (Digital- und Analog-Voltmeter) und ist auch plausibel. Man erkennt eine leicht erhöhte Stromaufnahme zu Beginn (etwa 3 mA mehr Stromverbrauch für etwa 300 msec). Auch dies ist plausibel. In einer Messung (von etwa 50, kein Bild) erschienen einzelne Datenpunkte, die einen höheren Stromverbrauch zu Beginn andeuten könnten, diese konnten aber durch Messungen mit einem analogen Speicheroszilloskop nicht verifiziert werden und werden deshalb als Artefakte (etwa Einstreuung des benachbarten PCs oder Lötstation) interpretiert. Bei Bedarf sollte eine präzise Messung – etwa per analoger Integration und Mittelung – durchgeführt werden. Der hierfür nötige Aufwand scheint aber nur gerechtfertigt, falls Probleme mit überlasteten Batterien auftreten.

NB: Die Messungen wurden insbesondere durchgeführt, da ein Testaufbau mit einem Arduino-Leonardo und XBee-Shield bei weitem nicht die erwartete Betriebsdauer erzielte, sondern nur gut eine Woche aus 4 Standard-Mignon-Zellen. Dies rührte aber, wie zu Beginn der Messungen klar wurde, vom Ruhestrom des Spannungsreglers des XBee-Shields, der bei etwa 10 mA lag. Dies würde dann zu einer Batteriekapazität von etwa 10 Tagen x 24 Stunden x 10 mA = 2400 mAh (plus die eigentlich nötige Stromaufnahme von Board und XBee-Modul, die bei etwa 1 mA im Mittel liegt und damit vernachlässigbar ist), also einem plausiblen Wert.
Dies führt zu folgenden Betriebsdauern:


Quellcode des Programms zur Messung mit XBee-Modul. Für die Messung ohne XBee-Modul wurde der entsprechende Code auskommentiert und die Zeit im Aufruf von powerDown auf 15Ms gesetzt.

/**
* Short sleep cycles to measure power consumption
* essentially a fast blink with sleep during off time
**/

#include "LowPower.h"

char c = 'A';

const int XBEE_WAKE = 7;

void setup() {
  Serial.begin(9600);
  // Send XBee to sleep, never wake it up
  digitalWrite(XBEE_WAKE,HIGH); // just in case
  // XBee pins are clamped internally
  pinMode(XBEE_WAKE,INPUT);
}

void loop () {
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
    digitalWrite(13, HIGH);
  // Send to XBee Module
  // first wake it up
  pinMode(XBEE_WAKE,OUTPUT);
  digitalWrite(XBEE_WAKE,LOW);
  // wait a little bit
  delay(100);
  Serial.print(c);
  Serial.flush();
  // wait a little bit and send XBee to sleep again
  delay(100);
  digitalWrite(XBEE_WAKE,HIGH); // just in case
  // XBee pins are clamped internally
  pinMode(XBEE_WAKE,INPUT);


    delay(100);
    digitalWrite(13, LOW);
}



[1] Vermutlich wurde das so konfiguriert, prüfen ! Ist aber nicht so kritisch. Letztlich sollte per Versuch – aufwendig – geklärt werden, wie lange das Modul mindestens wach bleiben muß, um eine verlässliche Übertragung zu gewährleisten. 3 Sekunden sind meiner Erinnerung nach der default und realistisch.

Samstag, 10. August 2013

AD7714 - die Software

Der AD7714 - ein 24 Bit Sigma-Delta-Wandler mit integrierter Signalaufbereitung - ist ein toller Chip (und wenn man bedenkt, wie aufwendig es wäre, all diese Funktionen selbst aufzubauen, nicht mal teuer), aber leider gibt es (bisher) keine Beispiele im Web, wie man ihn an einen Arduino anbindet, das ist nämlich nicht ganz trivial. Also los.

Angebunden wird er über die SPI-Schnittstelle. Da ich nur einen SPI-Chip verwende, wird das /CS-Signal (Pin 19) nicht verwendet, sondern fest auf low gelegt. So braucht man nur drei Leitungen, MISO (Daten vom Wandler, Pin 21), MOSI (Daten vom Arduino, Pin 22) und SCK (Takt, Pin 1).

SPI ist kein "absoluter" Standard, sondern ein de-facto-Industriestandard, heisst, es gibt verscheidene Ausprägungen. Deshalb muss zunächst festgelegt werden, wie die Daten übertragen werden: Zunächst der SPI-Mode, der festlegt, welche Polarität das Taktsignal hat und welche Flanke zur Signalübernahme dient. Wir nehmen  Mode 2, das bedeutet Takt ist aktiv low und die Daten werden bei der fallenden Flanke übernommen. Das wird chipseitig durch die entsprechenden Pins festgelegt (POL, Pin 4 auf high) und Arduino-seitig durch

SPI.setDataMode(SPI_MODE2);

Der AD7714 liefert (und erwartet) die Daten MSB first, das wird mit

SPI.setBitOrder(MSBFIRST);

definiert. Bleibt noch die Taktrate, wir haben es nicht allzu eilig und nehmen

SPI.setClockDivider(32);

das müssten 500kHz sein.

Der Zugriff auf die internen Register erfordert zunächst die Auswahl des zu schreibenden oder zu lesenden Registers. Dies geschieht durch Schreiben des Communication Registers. Dieses legt in den unteren drei Bits den Kanal des Wandlers fest. Wir verwenden nur einen Kanal, den aber differentiell an AIN1 und AIN2, dieser hat den Code 100 (also 4 dezimal). Das nächste Bit definiert, ob gelesen oder geschrieben wird, 1 bedeutet Lesen (also 8 dezimal).  Die nächsten drei Bits geben das Register an, auf das als nächstes zugegriffen werden soll.


CodedezimalRegister
0000Communications Register
00116Mode Register
01032Filter High Register
01148Filter Low Register
10064Test Register
10180Data Register

Die Codes 110 und 111 sind die Calibration Registers und im Moment uninteressant.

Das oberste Bit des Communication Registers ist das /DRDY muss beim Schreiben immer 0 sein, beim Lesen liefert es den Wert des /DRDY-Pins (low, wenn Daten gelesen werden können).

Zur Initialisierung des AD7714 wird zunächst das Filter konfiguriert, das durch Schreiben von 4 (Kanal AN1+AN2, Schreibzugriff) + 32 (Filter High Register) = 36 (0x24) ausgewählt wird.

Im Filter-Register werden im oberen Byte einige Parameter konfiguriert, hier unipolare Operation, 24 Bit Auflösung der zu lesenden Daten, Current Boost (da wir mit hoher Verstärkung und hohem Takt arbeiten) und ohne Clock Disable. Dies ergibt 1110 für die oberen 4 Bit. Die unteren 4 Bit sind die höherwertigen Bits des Filter-Teilers. Die niedrigste Filterfrequenz ergibt sich mit dem Teiler 4000 (0xfa0), nämlich fCLOCK/128/4000 = 4,8 Hz. Da die Zeitkonstante des zu messenden Temperatursignals sicher länger ist, ist die Genauigkeit umso besser, je niedriger die Filterfrequenz.

Also zunächst das Filter High-Register auswählen (0x24), dann die Werte schreiben (0x4f), dann das Filter-Low-Register auswählen (0x34) und das untere Byte (0xa0) schreiben.

Als nächstes muss das Mode-Register konfiguriert werden, dazu zunächst Mode-Register für einen Schreibzugriff auswählen 0x14 (20)