Bei eigenen Projekten ist es meistens gut zu wissen, wie viel Strom benötigt wird. Besonders bei Akku-betriebenen Schaltungen ist es wichtig, um die Akkulaufzeit abzuschätzen und bei niedriger Spannung das System herunterzufahren bevor der Akku ausfällt. Gleichzeitig lässt sich dadurch die Lebensdauer des Akkus verlängern.
Daten per I2C auslesen
Bei Systemen mit I2C-Bus können die Daten wie Spannung, Strom und Leistung über diesen Bus ausgelesen werden. Ich verwende dazu den Baustein INA226 von Texas Instruments.
Beschaltung des INA226
Die Beschaltung ist relativ einfach. Es muss nur ein zusätzlicher Shunt verbaut werden. Ich verwende hier einen mit 10 mOhm. Damit können Ströme bis 8,192 A gemessen werden, da der INA226 beim Shunt einen Messbereich von +- 81,92 mV hat.
Konfiguration
Nach einem Reset bzw. Power-Up sind alle Register des INA226 bereits so gesetzt, dass er funktioniert. Lediglich im Register 05h muss noch der entsprechende Wert für den Shunt gesetzt werden, dass Strom und Leistung richtig berechnet werden. Mit den 15-bit Auflösung bei der Strommessung erreicht man 250 µA/Bit. Mit den Formeln aus dem Datenblatt errechnet sich ein Kalibrierwert von 2048 = 0800h.
Programmierung
Im weiteren Betrieb müssen dann nur noch die folgenden Register ausgelesen werden. Register 02h enthält den Wert für die Spannung. Der Wert hat eine Auflösung von 1,25 mV / Bit. Das heißt, wenn man denn ausgelesenen Wert mit 0,00125 multipliziert erhält man die Spannung in V. Register 04h enthält den Wert für die Stromstärke. Dieser muss mit dem oben festgesetzten Wert von 250 µA / Bit, also mit 0,00025, multipliziert werden, damit man den Strom in A erhält. Im Register 03h steht die aktuelle Leistung. Dazu wird der Stromwert erst mit 25 und dann mit dem Spannungswert multipliziert. Der hier ausgelesene Wert muss mit 0,0625 multipliziert werden, damit man die Leistung in W erhält.
Beispielcode für Beaglebone Black
Im Folgenden findest du einen Beispielcode für den Beaglebone Black. Der INA226 muss mit dem I2C2 vom Beaglebone Black verbunden sein und dieser muss aktiviert sein.
#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <linux/i2c-dev.h> #include <fcntl.h>
int read_reg16(int file, char reg) { char buf[2]={0}; int x;
buf[0]=reg; write(file,buf,1); // set read register read(file,buf,2); // read 2 bytes x=((buf[0])<<8)+buf[1]; // combine bytes
return x; }
int main(void) { int file; int addr=0x40; // adress of INA226 char buf[10]={0}; int x;
printf("INA226\n"); if((file=open("/dev/i2c-1",O_RDWR))<0) // open i2c-bus { perror("cannot open i2c-1"); exit(1); } if(ioctl(file, I2C_SLAVE, addr)<0) // open slave { perror("cannot open slave address"); exit(1); } buf[0]=0x05; buf[1]=0x08; buf[2]=0x00; // set shunt resistor 10 mOhm write(file,buf,3);
x=read_reg16(file, 0x02); printf(" Spannung: %f V (%i)\n",(float)x*0.00125, x); x=read_reg16(file, 0x04); printf(" Strom: %f A (%i)\n",(float)x*0.00025, x); x=read_reg16(file, 0x03); printf(" Leistung: %f W (%i)\n",(float)x*0.00625, x);
close(file);
return 0; }
Update 18.01.2016
Ansteuerung mit i2c-dev
Es hat sich herausgestellt, dass es sinnvoller ist, den I2C-Bus gleich mit der i2c-dev-Library von Linux anzusteuern. Diese Library bringt Funktionen mit denen direkt Bytes und Words aus I2C-Geräten ausgelesen werden können. Bevor die Library verwendet werden kann, müssen allerdings die passenden header-Dateien installiert werden. Das geschieht mit folgendem Befehl:
sudo apt-get install libi2c-dev
Allerdings liefert der INA226 beim Auslesen mit i2c_smbus_read_word_data() die Bytes in vertauschter Reihenfolge. Deshalb gibt es nicht die Funktion swap_bytes(), die die Bytes wieder in die richtige Reihenfolge bringt.
Das komplette Programm sieht dann so aus:
#include <stdio.h> #include <stdlib.h> #include <sys/stat.h> #include <linux/i2c-dev.h> #include <fcntl.h>
unsigned short int swap_bytes(unsigned short int input) { return (((input & 0xff) << 8) | ((input >> 8) & 0xff)); }
int main(void) { int file; int addr=0x40; // adress of INA226 int x;
printf("INA226\n"); if((file=open("/dev/i2c-1",O_RDWR))<0) // open i2c-bus { perror("cannot open i2c-1"); exit(1); } if(ioctl(file, I2C_SLAVE, addr)<0) // open slave { perror("cannot open slave address"); exit(1); } i2c_smbus_write_word_data(file,0x05,swap_bytes(0x0800)); // set shunt resistor 10 mOhm
x=swap_bytes(i2c_smbus_read_word_data(file, 0x02)); printf(" Spannung: %f V (%i)\n",(float)x*0.00125, x); x=swap_bytes(i2c_smbus_read_word_data(file, 0x04)); printf(" Strom: %f A (%i)\n",(float)x*0.00025, x); // 10 mOhm x=swap_bytes(i2c_smbus_read_word_data(file, 0x03)); printf(" Leistung: %f W (%i)\n",(float)x*0.00625, x); // 10 mOhm
close(file);
return 0; }
auf dem Raspberry Pi
Das Programm läuft ohne Änderungen auch auf dem Raspberry Pi. Bevor der I2C-Bus verwendet werden kann, muss er aktiviert werden. Das geschieht mit dem Programm raspi-config.
Kommentare
Kommentarfunktion für diesen Artikel geschlossen.