Dieses Programm zeigt die Speichernutzung einer Partition sehr übersichtlich an, wie man im folgenden Bild sehen kan:
Eine Sammlung von meinen Projekten aus den Bereichen Physik, Elektronik, Informatik und sogar ein bisschen Botanik. Dieser Blog soll einerseits Hilfestellung bei Problemen geben aber andererseits auch als Anregung für weitere Projekte dienen. Falls es zu einem Thema Fragen oder Anregungen gibt: Einfach schnell einen Kommentar schreiben oder das Kontaktformular rechts unten benutzen, ich beantworte das normalerweise innerhalb von einem Tag.
AdSense
Sonntag, 5. Oktober 2014
Speichernutzung übersichtlich anzeigen - WinDirStat
(English version) Bei zunehmender Datenmenge wird es immer schwieriger, die Datenmengen zu kontrollieren und so passiert es immer öfter dass die Festplatte voll ist und man eigentlich keine Ahnung hat was die Speicherfresser sind. Um dieses Problem anzugehen gibt es ein sehr nützlichen Programm: WinDirStat.
Dieses Programm zeigt die Speichernutzung einer Partition sehr übersichtlich an, wie man im folgenden Bild sehen kan:
Man kann Ordner auswählen und sieht sofort einen weißen Rahmen der den Speicherplatz des gesamten Ordners anzeigt. Jede Datei entspricht einem Rechteck, sodass man einzelne große Dateien sofort ausmachen kann. Ich persönlich habe mit diesem Programm bereits einige viele Gigabyte an unnötigen Daten gelöscht und kann es nur jedem weiterempfehlen.
Dieses Programm zeigt die Speichernutzung einer Partition sehr übersichtlich an, wie man im folgenden Bild sehen kan:
Sonntag, 31. August 2014
Spannung überwachen am Arduino, ATmega oder ATtiny
(English version)
Wer seinen Arduino oder einen ATmega bzw. ATtiny über eine Batterie mit Spannung versorgt muss immer damit rechnen, dass die irgendwann einmal leer ist und dann der Mikrocontroller ohne Vorwarnung den Dienst einstellt. Hier ist es hilfreich, die Versorgungsspannung zu überwachen. Sollte sie unter einen bestimmten kritischen Wert fallen, kann man sich zum Beispiel durch anschalten einer LED warnen lassen.
Die Überwachung der Spannung kann ohne zusätzliche Hardware erfolgen. Möglich macht es der AD-Wandler. Dieser arbeitet ja bekannterweise nach folgender Formel:
WERT_ADC = V_EINGANG * 1023/V_REFERENZ
Nun könnte man natürlich meinen: "Ich lege einfach meine Versorgungsspannung an den Eingang des AD-Wandlers und kann diese so messen". Das funktioniert leider nicht, da die Referenzspannung des AD-Wandler ebenfalls die Versorgungsspannung ist. Der Wert des AD-Wandlers wäre als immer 1023.
Doch es gibt einen Trick: jeder Mikrocontroller erzeugt eine interne Referenzspannung, die so genannte "Bandgap Voltage" V_BG. Diese beträgt beim ATmega328, der im Arduino Uno zum Einsatz kommt, 1.1V. Diese Spannung lässt sich auf den Eingang des AD-Wandlers legen. mit V_EINGANG = V_BG und V_REFERENZ = V_CC ergibt sich dann:
WERT_ADC = V_BG * 1023/V_CC
oder umgeformt:
V_CC = V_BG * 1023/WERT_ADC
Setzt man nun ein V_BG = 1100 (in mV) ergibt sich:
V_CC = 1100 * 1023/WERT_ADC
V_CC ist nun der Wert der Spannungsversorgung in mV
Umgesetzt in Code sieht das dann so aus:
In der loop() wird dann die Messung durch setzen des Bits ADSC gestartet. Ist die Messung beendet (ADSC ist wieder 0) wird das Ergebnis der Wandlung aus den Registern ADCL (die unteren 8 Bit) und ADCH (die oberen 2 Bit) ausgelesen und zu einem 10-Bit-Ergebnis zusammengesetzt. Aus diesem wird dann nach der obigen Formel die Versorgungsspannung bestimmt. Liegt sie unter 5V, wird eine LED eingeschaltet.
Diese Methode funktioniert prinzipiell mit allen ATmegas oder ATtinys. Je nach verwendetem µC müssen allerdings in den Registern des AD-Wandlers andere Bits gesetzt werden. Welche das genau sind, kann dem Datenblatt entnommen werden.
Wer seinen Arduino oder einen ATmega bzw. ATtiny über eine Batterie mit Spannung versorgt muss immer damit rechnen, dass die irgendwann einmal leer ist und dann der Mikrocontroller ohne Vorwarnung den Dienst einstellt. Hier ist es hilfreich, die Versorgungsspannung zu überwachen. Sollte sie unter einen bestimmten kritischen Wert fallen, kann man sich zum Beispiel durch anschalten einer LED warnen lassen.
Die Überwachung der Spannung kann ohne zusätzliche Hardware erfolgen. Möglich macht es der AD-Wandler. Dieser arbeitet ja bekannterweise nach folgender Formel:
WERT_ADC = V_EINGANG * 1023/V_REFERENZ
Nun könnte man natürlich meinen: "Ich lege einfach meine Versorgungsspannung an den Eingang des AD-Wandlers und kann diese so messen". Das funktioniert leider nicht, da die Referenzspannung des AD-Wandler ebenfalls die Versorgungsspannung ist. Der Wert des AD-Wandlers wäre als immer 1023.
Doch es gibt einen Trick: jeder Mikrocontroller erzeugt eine interne Referenzspannung, die so genannte "Bandgap Voltage" V_BG. Diese beträgt beim ATmega328, der im Arduino Uno zum Einsatz kommt, 1.1V. Diese Spannung lässt sich auf den Eingang des AD-Wandlers legen. mit V_EINGANG = V_BG und V_REFERENZ = V_CC ergibt sich dann:
WERT_ADC = V_BG * 1023/V_CC
oder umgeformt:
V_CC = V_BG * 1023/WERT_ADC
Setzt man nun ein V_BG = 1100 (in mV) ergibt sich:
V_CC = 1100 * 1023/WERT_ADC
V_CC ist nun der Wert der Spannungsversorgung in mV
Umgesetzt in Code sieht das dann so aus:
int led = 13; //Pin der LED int adc_low, adc_high; //Zwischenspeicher für die Ergebnisse des ADC long adc_result; //Gesamtergebnis der Messung des ADC long vcc; //Versorgungsspannung void setup() { pinMode(led, OUTPUT); ADMUX |= (1<<REFS0); //VCC als Referenzspannung für den AD-Wandler ADMUX |= (1<<MUX3) | (1<<MUX2) | (1<<MUX1); //1.1V Referenzspannung als Eingang für ADC delay(10); //warten bis sich die Referenzspannung eingestellt hat ADCSRA |= (1<<ADEN); //ADC aktivieren } // the loop routine runs over and over again forever: void loop() { ADCSRA |= (1<<ADSC); //Messung starten while (bitRead(ADCSRA, ADSC)); //warten bis Messung beendet ist //Ergebnisse des ADC zwischenspeichern. Wichtig: zuerst ADCL auslesen, dann ADCH adc_low = ADCL; adc_high = ADCH; adc_result = (adc_high<<8) | adc_low; //Gesamtergebniss der ADC-Messung vcc = 1125300L / adc_result; //Versorgungsspannung in mV berechnen (1100mV * 1023 = 1125300) //wenn Spannung kleiner als 5V if (vcc < 5000) { digitalWrite(led, HIGH); //schalte LED an } //wenn größer oder gleich 5V else { digitalWrite(led, LOW); //schalte LED aus } delay(500); }In der setup()-Funktion wird zuerst der AD-Wandler so eingestellt, dass zum einen die Versorgungsspannung V_CC als Referenz und zum anderen die Bandgap-Spannung V_BG als Eingang für den AD-Wandler dienen. Nach einer kurzen Wartezeit wird der AD-Wandler dann aktiviert.
In der loop() wird dann die Messung durch setzen des Bits ADSC gestartet. Ist die Messung beendet (ADSC ist wieder 0) wird das Ergebnis der Wandlung aus den Registern ADCL (die unteren 8 Bit) und ADCH (die oberen 2 Bit) ausgelesen und zu einem 10-Bit-Ergebnis zusammengesetzt. Aus diesem wird dann nach der obigen Formel die Versorgungsspannung bestimmt. Liegt sie unter 5V, wird eine LED eingeschaltet.
Diese Methode funktioniert prinzipiell mit allen ATmegas oder ATtinys. Je nach verwendetem µC müssen allerdings in den Registern des AD-Wandlers andere Bits gesetzt werden. Welche das genau sind, kann dem Datenblatt entnommen werden.
Mittwoch, 20. August 2014
ATmega - Bodenfeuchte von Zimmerpflanzen messen
(English version) Heute möchte ich vorstellen, wie man einen Feuchtigkeitssensor baut und ansteuert. Die Grundidee dahinter ist, zu messen wie feucht die Erde einer Pflanze ist und dann dementsprechend zu wissen wann man gießen muss.
Für den Bau des Sensors wird nicht viel benötigt. Ich habe ein kleines Stück Streifenrasterplatine, 2 Nägel und Stiftleisten benutzt. Der Sensor sieht dann so aus:
Nun misst man den Widerstand zwischen den zwei Nägeln (wenn der Sensor in der Erde steckt) und schon kann man Rückschlüsse auf die Bodenfeuchte ziehen. In der Schaltung sieht das dann folgendermaßen aus:
Bei feuchter Erde leiter der Sensor gut, also misst der ATmega eine hohe Spannung (zu interpretieren als Erde ist feucht). Bei trockener Erde steigt der Widerstand, daher sinkt die gemessene Spannung. Natürlich kann man jetzt noch überlegen welche Einheiten die Achsen bekommen und so weiter, ich denke jedoch es ist sinniger, einfach 0 bis 5 V aufzutragen (oder 0 bis 100%) und dann selbst zu überprüfen wann die Pflanze gegossen werden muss - dies ist dann der Wert bei dessen Unterschreitung eine rote Lampe an geht oder eine automatische E-Mail gesendet wird.
Für den Bau des Sensors wird nicht viel benötigt. Ich habe ein kleines Stück Streifenrasterplatine, 2 Nägel und Stiftleisten benutzt. Der Sensor sieht dann so aus:
Nun misst man den Widerstand zwischen den zwei Nägeln (wenn der Sensor in der Erde steckt) und schon kann man Rückschlüsse auf die Bodenfeuchte ziehen. In der Schaltung sieht das dann folgendermaßen aus:
Bei feuchter Erde leiter der Sensor gut, also misst der ATmega eine hohe Spannung (zu interpretieren als Erde ist feucht). Bei trockener Erde steigt der Widerstand, daher sinkt die gemessene Spannung. Natürlich kann man jetzt noch überlegen welche Einheiten die Achsen bekommen und so weiter, ich denke jedoch es ist sinniger, einfach 0 bis 5 V aufzutragen (oder 0 bis 100%) und dann selbst zu überprüfen wann die Pflanze gegossen werden muss - dies ist dann der Wert bei dessen Unterschreitung eine rote Lampe an geht oder eine automatische E-Mail gesendet wird.
Montag, 9. Juni 2014
Helligkeitssensor BH1750FVI
(English version) Für mein "Home Automation"-Projekt habe ich auch eine Automatisierung des Rollladens geplant. Dabei soll der Rollladen geschlossen werden, wenn die Sonne ins Zimmer scheint um so ein Aufheizen des Zimmers zu verhindern. Um Sonneneinstrahlung zu erkennen verfolge ich im Moment zwei Ansätze: Erkennung über Helligkeit und Temperatur.
Zur Erkennung der Sonneneinstrahlung über die Helligkeit setze ich einen Helligkeitssensor vom Typ BH1750FVI ein. Dieser ist (wie so oft) für unter 2 Euro bei Ebay erhältlich.
Der Sensor misst die Helligkeit zwischen 0 und 65535 lx und schickt das Ergebnis der Messung über den I2C-Bus an den Mikrocontroller. Die Messung der Helligkeit kann kontinuierlich oder einmalig mit einer Auflösung von 0.5, 1 oder 4 lx erfolgen.
Die Ansteuerung des Sensors bzw. die Abfrage der Helligkeit über I2C funktioniert "von Hand" schon ziemlich einfach, noch komfortabler wird es jedoch mit dem Arduino unter Verwendung der passenden Library. Ich habe die Lib von Christopher Laws verwendet.
Der Sensor wird einfach über VCC und GND mit 5V verbunden, SDA und SCL werden an die entsprechenden Pins des Arduino, ATmega oder ATtiny angeschlossen.
Dann kann der Beispiel-Code der Library übertragen werden:
Zur Erkennung der Sonneneinstrahlung über die Helligkeit setze ich einen Helligkeitssensor vom Typ BH1750FVI ein. Dieser ist (wie so oft) für unter 2 Euro bei Ebay erhältlich.
Der Sensor misst die Helligkeit zwischen 0 und 65535 lx und schickt das Ergebnis der Messung über den I2C-Bus an den Mikrocontroller. Die Messung der Helligkeit kann kontinuierlich oder einmalig mit einer Auflösung von 0.5, 1 oder 4 lx erfolgen.
Die Ansteuerung des Sensors bzw. die Abfrage der Helligkeit über I2C funktioniert "von Hand" schon ziemlich einfach, noch komfortabler wird es jedoch mit dem Arduino unter Verwendung der passenden Library. Ich habe die Lib von Christopher Laws verwendet.
Der Sensor wird einfach über VCC und GND mit 5V verbunden, SDA und SCL werden an die entsprechenden Pins des Arduino, ATmega oder ATtiny angeschlossen.
Dann kann der Beispiel-Code der Library übertragen werden:
#include <Wire.h> #include <BH1750.h> BH1750 lightMeter; void setup(){ Serial.begin(9600); lightMeter.begin(); Serial.println("Running..."); } void loop() { uint16_t lux = lightMeter.readLightLevel(); Serial.print("Light: "); Serial.print(lux); Serial.println(" lx"); delay(1000); }
Der Code ist weitestgehend selbsterklärend. Im Setup wird der Sensor mit der begin()-Funktion initialisiert. Wenn gewünscht kann hier durch Übergabe eines entsprechenden Parameters der Mess-Modus (einmalig/kontinuierlich bzw. die Auflösung) eingestellt werden. Näheres dazu ist dem h-File der Library zu entnehmen. Der aktuelle Helligkeitswert in Lux kann dann über die Funktion readLightLevel() ausgelesen werden. Und das war es auch schon, mehr gibts dazu nicht zu sagen ;)
Kategorien:
Arduino,
ATmega,
ATtiny,
Home Automation
Mittwoch, 23. April 2014
Arduino - I2C Scanner
(English version) Ich habe schon öfters das Problem gehabt, dass ich ein cooles I2C-Gerät hatte, leider aber keine Ahnung hatte, welche Adresse es hatte. Das kann frustrierend sein, da die Adresse meistens als bekannt vorausgesetzt wird. Daher möchte ich heute ein simples Programm vorstellen, welches alle verfügbaren I2C-Geräte scannt.
Die Funktionsweise ist simpel: Ein Counter zählt von 0 hoch und versucht ein I2C-Gerät anzusprechen. Gelingt dies nicht, so fährt er mit der nächsten Adresse fort. Das sieht dann folgendermaßen aus:
Statt dem lcd.print kann man auch jede beliebige andere Ausgabe benutzen. Sobald ein Gerät gefunden wurde, wird eine Sekunde gewartet, danach wird weiter gescannt.
Die Funktionsweise ist simpel: Ein Counter zählt von 0 hoch und versucht ein I2C-Gerät anzusprechen. Gelingt dies nicht, so fährt er mit der nächsten Adresse fort. Das sieht dann folgendermaßen aus:
for (int i = 0; i < 120; i++)
{
Wire.beginTransmission(i);
error = Wire.endTransmission();
sprintf(buf, "scan %i - %i",i,error);
lcd.setCursor(0,1);
lcd.print(buf);
if (error == 0)
{
//success!
delay(1000);
}
}
Statt dem lcd.print kann man auch jede beliebige andere Ausgabe benutzen. Sobald ein Gerät gefunden wurde, wird eine Sekunde gewartet, danach wird weiter gescannt.
Kategorien:
Arduino
Sonntag, 23. März 2014
Handy - Kameraabdeckung zerkratzt, Fotos unscharf
(English version) Mein Bruder besitzt ein HTC Desire Z. Seit einiger Zeit sind alle Fotos die er macht verschwommen. Ein Blick auf die Kameraabdeckung verrät auch warum: Die Mitte ist zerkratzt, nur der Rand sieht noch gut aus.
Das Problem ist, dass auf der Abdeckung ein Anti-Reflex-Coating drauf ist. Das sorgt einerseits für schönere Bilder, sobald es jedoch zerkratzt ist bringt es nichts mehr.
Die Lösung für das Problem ist nun, das Coating komplett weg zu polieren. Dazu nimmt man einfach Zahnpaste und ein Wattestäbchen und rubbelt ca. 2 Minuten lang über das Glas. Anschließend sollte es dann so aussehen:
Es gibt einen Qualitätsunterschied zwischen den beiden Bildern. Dennoch ist die Qualität nach dem Polieren deutlich besser als vor dem Polieren, wo alle Bilder unscharf waren.
![]() |
| Leicht zerkratzte Kameraabdeckung, das Bild wurde durch eine polierte Kameraabdeckung aufgenommen. |
Die Lösung für das Problem ist nun, das Coating komplett weg zu polieren. Dazu nimmt man einfach Zahnpaste und ein Wattestäbchen und rubbelt ca. 2 Minuten lang über das Glas. Anschließend sollte es dann so aussehen:
![]() |
| Polierte Kameraabdeckung, das Bild wurde durch eine nicht-polierte Kameraabdeckung aufgenommen. |
Es gibt einen Qualitätsunterschied zwischen den beiden Bildern. Dennoch ist die Qualität nach dem Polieren deutlich besser als vor dem Polieren, wo alle Bilder unscharf waren.
Sonntag, 2. März 2014
Register Pointer - mit Arduino bestimmte Register über I2C ansprechen
(English Version) Bei manchen Anwedungen ist es erforderlich, dass man beim lesen und schreiben über den I2C-Bus ein ganz bestimmtes Register eines I2C-Slaves ausliest oder beschreibt, z.B. wenn man bei der Real Time Clock DS1307 nur die Stunden auslesen bzw. ändern möchte.
Dazu gibt es die sogenannten Register Pointer. Mit diesen Pointern "zeigt" man auf das Register, das man lesen oder beschreiben möchte.
Mit dem Arduino funktioniert das denkbar einfach: beim Schreibzugriff wird mit dem ersten über den write()-Befehl gesendeten Byte der Register Pointer gesetzt. Ein Beispiel anhand des DS1307 soll das verdeutlichen;
Beim Auslesen von Daten aus einem bestimmten Register wird ähnlich vorgegangen:
Dazu gibt es die sogenannten Register Pointer. Mit diesen Pointern "zeigt" man auf das Register, das man lesen oder beschreiben möchte.
Mit dem Arduino funktioniert das denkbar einfach: beim Schreibzugriff wird mit dem ersten über den write()-Befehl gesendeten Byte der Register Pointer gesetzt. Ein Beispiel anhand des DS1307 soll das verdeutlichen;
Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x02); //Pointer auf Register 2 setzen Wire.write(decToBcd(hour)); //Wert für Stunden ins Register 2 schreiben
Wire.write(decToBcd(weekDay)); //Wert für Wochentag ins Register 3 schreiben
Wire.endTransmission();Das erste geschriebene Byte nach dem Befehl beginTransmission() setzt hier den Pointer auf das Register 2 (hier werden die Stunden gespeichert). Mit dem zweiten write()-Befehl wird dann der eigentlich Wert in dieses Register geschrieben. Dann wird automatisch ins nächste Register gesprungen. Der folgende write()-Befehl schreibt also ins Register 3 und so weiter.
Beim Auslesen von Daten aus einem bestimmten Register wird ähnlich vorgegangen:
Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x02); //Pointer auf Register 2 setzen Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS, 7);//Datenabfrage ab Register 2 beginnen int hour = bcdToDec(Wire.read()); //Stunden aus Register 2 auslesen int weekDay = bcdToDec(Wire.read()); //Wochentag aus Register 3 auslesenAuch hier wird zuerst der Pointer durch Senden einer 2 auf das Register 2 gesetzt. Dann können mit dem Befehl requestFrom() Daten angefordert werden. Der read()-Befehl liest daraufhin Daten aus dem Register 2 aus. Dann wird wieder automatisch zum nächsten Register gesprungen, so dass der nächste read()-Befehl das Register 3 ausliest und so weiter.
Abonnieren
Posts (Atom)




