AdSense

Samstag, 31. August 2013

Beschleunigungssensor MPU-6050 mit ATMega 16A auslesen

(English version) Der Beschleunigungssensor MPU-6050 ist ziemlich vielseitig, klein und billig. Er kann mit bis zu 6 V betrieben werden und liefert Beschleunigungswerte und sogar Gyroskopwerte (also Drehung in Grad pro Sekunde). So ein Sensor ist also das ideale Kernstück für einen Quadrocopter.

In diesem Post möchte ich nun auch das Auslesen mit einem ATMega zeigen, da sich der Post mit dem Raspberry PI ziemlich großer Beliebtheit erfreut (http://physudo.blogspot.de/2013/07/beschleunigungssensor-mpu-6050-mit.html). Für I2C benutze ich am ATMega diese Implementierung: http://physudo.blogspot.de/2013/07/atmega-ic-master.html.

Zuerst einmal habe ich mir zwei Funktionen gebastelt, die entweder ein Register auslesen oder in ein Register reinschreiben:

void TWIM_WriteRegister(char reg, char value)
{
    TWIM_Start(addr, TWIM_WRITE); // set device address and write mode
    TWIM_Write(reg);
    TWIM_Write(value);
    TWIM_Stop();
}

char TWIM_ReadRegister(char reg)
{
    TWIM_Start(addr, TWIM_WRITE);
    TWIM_Write(reg);
    TWIM_Stop();

    TWIM_Start(addr, TWIM_READ); // set device address and read mode
    char ret = TWIM_ReadNack();
    TWIM_Stop();
    return ret;
}


Als nächstes möchte ich die Beschleunigung bzw. die Werte des Gyrometers auslesen. Zu beachten ist, dass zuerst der Sleep Mode deaktiviert werden muss, das geschieht mit TWIM_WriteRegister(107, 0). Zum auslesen der Werte habe ich mir wieder 2 Funktionen gebaut:

double MPU6050_ReadAccel(int axis)//x = 0; y = 1; z = 2
{
  char reg = axis * 2 + 59;
  char AFS_SEL = TWIM_ReadRegister(28);
  double factor = 1<<AFS_SEL;
  factor = 16384/factor;
  int val = 0;
  double double_val = 0;
  char ret = 0;

  ret = TWIM_ReadRegister(reg);
  val = ret << 8;

  ret = TWIM_ReadRegister(reg+1);  
  val += ret;

  if (val & 1<<15)
  val -= 1<<16;


   
  double_val = val;
 
  double_val = double_val / factor;

  return double_val;
}

double MPU6050_ReadGyro(int axis)//x = 0; y = 1; z = 2
{
  char reg = axis * 2 + 67;
  char FS_SEL = TWIM_ReadRegister(27);
  double factor = 1<<FS_SEL;
  factor = 131/factor;
  int val = 0;
  double double_val = 0;
  char ret = 0;

  ret = TWIM_ReadRegister(reg);
  val = ret << 8;

  ret = TWIM_ReadRegister(reg+1);  
  val += ret;

  if (val & 1<<15)
  val -= 1<<16;


  double_val = val;

  double_val = double_val / factor;

  return double_val;
}


Die Werte sind in Grad / Sekunde für das Gyrometer und in Einheiten von g für den Beschleunigungsmesser, mehr dazu gibt es auch in der Register Map, besonders bei der Erklärung von FS_SEL und AFS_SEL: http://www.invensense.com/mems/gyro/documents/RM-MPU-6000A.pdf

Donnerstag, 29. August 2013

Tageszeitabhängige Header-Grafik

Bei einer Homepage, die ich betreue, wollte ich in der Kopfzeile eine Header-Grafik haben, die sich je nach Tageszeit ändert (tagsüber ein Bild von einem Gebäude bei Tag, in der Nacht ein entsprechendes Bild des Gebäudes bei Nacht). Das lässt sich leicht mit PHP umsetzen:

Zuerst muss die aktuelle Uhrzeit erfasst und in einer Variable gespeichert werden:

$time = date("G", time())

Die Funktion time() liefert den aktuellen UNIX-Timestamp des Servers. Der UNIX-Timestamp ist die Anzahl der Sekunden seit dem 01.01.1979 um 1 Uhr - damit kann man also recht wenig anfangen. Daher kommt noch die Funktion date() zum Einsatz. Sie wandelt den Timestamp in ein verwertbares Format. Das genaue Format wird über den ersten Parameter der Funktion gewählt. Im Beispiel wird der Paramter "G" verwendet - es werden die vollen Stunden ohne führende Null angegeben. Möglich sind aber auch noch viele andere Formate wie Wochentag, Monat und so weiter. Alle möglichen Parameter sind auf dieser Seite zu finden.

Die aktuelle volle Stunde wurde also in der Varible $time gespeichert und kann nun weiter verwendet werden. Wichtig zu wissen ist, dass die Zeit in UTC (Weltzeit) angegeben wird - für MEZ oder MESZ müssten entsprechend 1 oder 2 Stunden addiert werden.

Nun kann anhand der aktuellen Zeit die passende Header-Grafik ausgewählt werden:

if ($time > 7 && $time < 21 ) {
   $pfad = "http://hierdiedomaindeservers.de/images/header_tag.jpg";
 }

else {
    $pfad = "http://hierdiedomaindeservers.de/images/header_nacht.jpg";
}

Ist die Stundenzahl größer als 7 und kleiner als 21 (ist es also zwischen 8:00 und 20:59), dann wird der Pfad der "Tag-Grafik" in der Variable $pfad gespeichert - sonst der Pfad der "Nacht-Grafik".

Zum Schluss wird die Grafik via HTML in der Homepage eingebunden:

<img src="<?php echo $pfad; ?>" width="123" height="456" alt="" />

Mit dieser Methode können natürlich nicht nur tageszeitabhängige sondern auch beispielsweise jahreszeitabhängige oder wochentagsabhängige Grafiken erzeugt werden.

Mittwoch, 28. August 2013

Arduino-Code auf dem ATtiny

Wer meine letzten Beiträge aufmerksam verfolgt hat weiß, dass ich gerade an einer Funkfernbedienung für meinen Rolladen arbeite. Für diesen Zweck ist der "normale" ATmega8 eher nicht geeignet (zu groß, 5V Betriebsspannung, teuer). Das Projekt soll also auf einem ATtiny basieren. Trotzdem möchte ich den gewohnten Komfort und die Libraries der Arduino-Entwicklungsumgebung nutzen. Wie man die Arduino IDE nutzen kann, um einen "nackten" ATmega8 zu programmieren, habe ich in meinem ersten Gastbeitrag hier beschrieben. Hierfür waren keine weitere Schritte nötig, da Arduino den ATmega8 von Haus aus unterstützt.
Für den ATtiny gilt das nicht, allerdings lässt sich die Arduino IDE mit wenigen Schritten mit dem ATtiny "vertraut" machen. Mit der folgenden Anleitung könnt ihr ATtiny45 und ATtiny85 sowie ATtiny24, ATtiny44 und ATtiny84 zur Arduino IDE hinzufügen.

Als erstes ladet ihr diese Datei herunter und entpackt sie. Den enthaltenen Ordner "attiny" kopiert ihr dann in den Ordner "hardware" eurer Arduino-Installation. Ihr solltet dann also z.B. folgende Ordnerstruktur haben: "C:\Programme\Arduino\hardware\attiny".

Der Ordner enthält eine Datei "boards.txt". Die Datei enthält alle Infos zu den verwendeten "Boards" - in diesem Fall natürlich nur ein "nackter" ATtiny. Dazu zählen Fuse-Einstellung, Taktfrequenz usw. Nur die in dieser Datei gelisteten "Boards" erscheinen nachher auch in der IDE. Die Datei enthält allerdings nur die Einstellungen für den Betrieb mit interner Taktquelle.

Natürlich könnte man den Tiny auch mit einer externen Taktquelle und entsprechendem Takt betreiben. Dann müsste eben ein weiterer passender Eintrag eingefügt werden.

Wichtig ist aber in jedem Fall, dass die Fuses für die Taktfrequenz am ATtiny auch entsprechend richtig eingestellt sind, sonst passt das Timing nicht!

Nun muss man der IDE natürlich noch die Pin-Belegung des ATiny beibringen. Dazu ist der Ordner "variants" mit den Unterordnern "tiny8" und "tiny14" enthalten. Sie enthalten jeweils die Datei "pins_arduino.h" in der die Pin-Belegung festgelegt ist. Der Datei kann auch entnommen werden, welcher Pin des ATtiny mit welchen Arduino-Funktionen belegt ist. Beim ATtiny24/44/84 wäre das z.B.
                                          +-\/-+
                                VCC  1|    |14  GND
                      (D 10)  PB0  2|    |13  AREF (D  0)
                       (D  9)  PB1  3|    |12  PA1  (D  1)
                                 PB3  4|    |11  PA2  (D  2)
    PWM  INT0  (D  8)  PB2  5|    |10  PA3  (D  3)
       PWM        (D  7)  PA7  6|    |9   PA4  (D  4)
       PWM        (D  6)  PA6  7|    |8   PA5  (D  5)        PWM
                                          +----+
Mit (D x) sind die entsprechenden Arduino-Pins bezeichnet.

Wenn die Arduino IDE nun gestartet wird, sollten unter Tools-Board die neu eingefügten ATtinys auftauchen:


Nun kann wie gewohnt programmiert werden. Je nach Funkstionsumfang des verwendeten ATtinys kann es natürlich Einschränkungen geben, z.B. bei den Interrups. Außerdem muss zum Programmieren ein Programmer wie z.B. der USBasp verwendet werden.

Die Anleitung gilt so im Prinzip auch für alle anderen ATtinys (und auch ATmegas) - man muss lediglich die passende "pins_arduino.h" auftreiben bzw. selber erstellen.

C# WPF - DataBinding

(English version) DataBindings in WPF sind ziemlich mächtig und nützlich. Heute will ich hier die Grundlagen beschreiben. Die Grundidee dahinter ist: Ich habe ein Anzeigeelement und eine Variable (eigentlich ein Feld). Wenn ich die Variable verändere, will ich, dass sich das Anzeigeelement ändert, umgekehrt will ich aber auch, dass sich bei Veränderung des Anzeigeelements (z.B. Texteingabe) die Variable ändert. Hier nun mal ein kleines Beispiel. Zuerst die XAML-Seite:

<TextBox Name="InputText" Grid.Row="0" Text="{Binding BindingText, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"></TextBox>
<TextBlock Name="OutputText" Grid.Row="1" Text="{Binding BindingText, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"></TextBlock>


Als nächstes braucht man irgendein Objekt, an welches gebindet wird. Das ist bei mir die Klasse "AnyClass", welche das Feld "BindingText" enthält, man könnte jedoch auch genausogut einfach MainWindow.xaml.cs benutzen. Um jetzt das Objekt an welches gebindet wird festzulegen geht man folgendermaßen vor:

AnyClass anyClass = new AnyClass();
InputText.DataContext = anyClass;
OutputText.DataContext = anyClass;


Man könnte auch einfach this.DataContext = anyClass; machen, was prinzipiell auch richtig ist, ich will hier aber möglichst viele Möglichkeiten zeigen. Ebenfalls könnte ich einfach in MainWindow.xaml.cs das entsprechende Feld "BindingText" erstellen und dann this.DataContext = this; aufrufen.

Nun komme ich zur Klasse AnyClass. Zuerst eine kurze Einführung zum Thema Felder. Ein Feld kann wie eine Variable verwendet werden, jedoch kann ein Feld keine Werte direkt speichern. Ein minimales Feld sieht folgendermaßen aus:

public string BindingText
{
    get { return _BindingText; }
    set { _BindingText = value; }
}
private string _BindingText = "";


Das ist also ein Feld. Im get und set Block kann man nun viele lustige Dinge tun, wie z.B. Überprüfen von Eingaben, Events werfen (also ein event, wenn das Feld abgefragt wird z.B.) und eigentlich auch alles andere denkbare.

Nun zeige ich die Klasse AnyClass, welche der letzte fehlende Baustein für das DataBinding ist:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DataBindingExample
{
    public class AnyClass : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string BindingText
        {
            get { return _BindingText; }
            set
            {
                _BindingText = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs("BindingText"));
                }
            }
        }
        private string _BindingText = "<empty>";
    }
}


Indem man PropertyChanged auslöst bekommt das Anzeigeelement gesagt, dass ein neuer Variablenwert existiert und aktualisiert sich. Das sollte die Grundlagen zum Thema DataBinding abdecken, falls es Fragen gibt, beantworte ich diese gerne in den Kommentaren.

Einen Post zu diesem Thema, der auch etwas weiter greift und z.B. Converter erklärt gibt es auf C# Tipps und Tricks.

Freitag, 23. August 2013

Ein Musikplayer mit C#

(English version) Tja, es gibt viele Musikplayer auf der Welt. Jeder hat Vorteile und Nachteile, bisher habe ich keinen "perfekten" Musikplayer gefunden. Daher habe ich mich mal drangesetzt und einen eigenen Programmiert. Den Player kann man hier herunterladen. Zur Bedienung: Man muss einmal einen Ordner als Musikbibliothek auswählen und mit Refresh Library wird diese dann geladen. Play Pause, etc sollte selbsterklärend sein. Was mir ganz wichtig ist sind die Hotkeys: "AltGr" + "NachRechts" spielt das nächste (zufällige) Lied, mit "AltGr" + "NachLinks" das vorherige. Außerdem kann die Wiedergabe mit "AltGr" + "Leertaste" angehalten und fortgesetzt / gestartet werden. Unter dem Fortschrittsbalken des aktuellen Liedes gibt es ein Such-Fenster, hier kann man Suchbegriffe eintippen. Ein Doppelklick auf ein Lied startet dieses dann. Zwei kleine Programmierkonzepte werde ich hier nun vorstellen: Einerseits das Abspielen von Medien-Dateien mit C# und WPF, andererseits das Verwenden von Hotkeys. Übrigens kann man hier eine grundlegende Einführung in WPF finden: C# Tipps und Tricks.

Musik wiedergeben

Da ich WPF verwende ist das total simpel: In der xaml-Datei habe ich einfach als Element (so wie z.B. ein Button) ein MediaElement:

<MediaElement Height="10" Width ="10"  LoadedBehavior="Manual" Name="mediaElement1" VerticalAlignment="Top" />

Das MediaElement ist unsichtbar. Um jetzt Musik abzuspielen geht man folgendermaßen vor:

mediaElement1.Source = new Uri(pathToMediaFile);
mediaElement1.Play();


Das war auch schon alles was man dazu sagen muss. Man kann sich jetzt noch an Events hängen, z.B. an mediaElement1_MediaEnded, sodass man weiß, wann die Wiedergabe aufgehört hat (um z.B. das nächste Lied zu starten).

Hotkeys

Anmerkung: Inzwischen benutze ich eine "bessere" Implementierung der Hotkeys, welche man hier nachlesen kann.

Hotkeys zu verwenden ist recht einfach. Zuerst muss man ein paar Zeilen in das Programm einfügen:

[DllImport("User32.dll")]
private static extern bool RegisterHotKey(
    [In] IntPtr hWnd,
    [In] int id,
    [In] uint fsModifiers,
    [In] uint vk);

[DllImport("User32.dll")]
private static extern bool UnregisterHotKey(
    [In] IntPtr hWnd,
    [In] int id);

private HwndSource _source;
private const int HOTKEY_ID = 9000;

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);
    var helper = new WindowInteropHelper(this);
    _source = HwndSource.FromHwnd(helper.Handle);
    _source.AddHook(HwndHook);
    RegisterHotKey();
}

protected override void OnClosed(EventArgs e)
{
    _source.RemoveHook(HwndHook);
    _source = null;
    UnregisterHotKey();
    base.OnClosed(e);
}

private void UnregisterHotKey()
{
    var helper = new WindowInteropHelper(this);
    UnregisterHotKey(helper.Handle, HOTKEY_ID);
}

private IntPtr HwndHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    const int WM_HOTKEY = 0x0312;
    switch (msg)
    {
        case WM_HOTKEY:
            OnHotKeyPressed(wParam.ToInt32());
            break;
    }
    return IntPtr.Zero;
}


Als nächstes habe ich die drei Hotkeys, welche ich benötige definiert:

private void RegisterHotKey()
{
    var helper = new WindowInteropHelper(this);
    const uint VK_RIGHT = 0x27;
    const uint VK_LEFT = 0x25;
    const uint VK_SPACE = 0x20;
    const uint MOD_ALT = 0x0001;
    const uint MOD_CTRL = 0x0002;

    if (!RegisterHotKey(helper.Handle, HOTKEY_ID+2, MOD_CTRL + MOD_ALT, VK_RIGHT))
    {
        // handle error
    }
    if (!RegisterHotKey(helper.Handle, HOTKEY_ID+1, MOD_CTRL + MOD_ALT, VK_LEFT))
    {
        // handle error
    }
    if (!RegisterHotKey(helper.Handle, HOTKEY_ID, MOD_CTRL + MOD_ALT, VK_SPACE))
    {
        // handle error
    }
}


Nun braucht es nur noch die Funktion, welche die gewünschten Aktionen ausführt, wenn man einen Hotkey drückt:

private void OnHotKeyPressed(int key)//9000 = space, 9001 = left, 9002 = right
{
    //System.Console.Write("KeyPressed! {0}\n", key);
    switch (key)
    {
        case 9000: if (playing) { pause(); } else { play(); }
            break;
        case 9001: back();
            break;
        case 9002: next();
            break;
        default:
            break;
    }
    // do stuff
}


Was genau hier passiert ist auch relativ simpel zu erkennen und sollte selbsterklärend sein. Für die Hotkeys muss man nun weiter nichts mehr tun. Zu beachten ist jedoch, dass diese Hotkeys nur bei meinem Programm funktionieren, solange es offen ist. Würde ich also z.B. "AltGr" + "0" als Hotkey nehmen, so könnte ich kein } mehr schreiben, während das Programm läuft.

Mittwoch, 21. August 2013

PHP - Chat auf eigenem Server "sicher" machen

(English version) Einen Chat mit PHP zu realisieren ist nicht weiter schwer. Relativ schnell merkt man dann auch, dass man Bilder und alles über HTML-Code einfügen kann. Das heißt aber auch, dass man PHP-Code ausführen kann. Das ist natürlich eine große Sicherheitslücke, mit den entsprechenden Befehlen kann man so z.B. den Server formatieren oder ähnliches.

Um das Ausführen von Code zu verhindern kann man nun wie folgt vorgehen: Bevor die Chatnachricht angezeigt wird, wird z.B. das < Symbol durch das entsprechende HTML-Äquivalent ersetzt. Dies wäre &lt;. In PHP funktioniert das so: $chatMessage = str_replace("<", "&lt;", $chatMessage);. Nun kann man keinen PHP-Code mehr ausführen, leider jedoch auch keinen HTML-Code. Um HTML-Code wieder zu aktivieren könnte man z.B. detektieren, ob es sich um bestimmte HTML-Tags (Bild, Link) handelt oder nicht und dementsprechend das Zeichen austauschen.

Arduino als Logic Analyzer

Wie in einem meiner "Home Automation"-Beiträge versprochen, erkläre ich in diesem Beitrag, wie man ganz einfach in wenigen Schritten das Arduino-Board als einen Logic Analyzer verwenden kann.

Zuerst muss die nötige Software für den Arduino herunter geladen werden. Diese ist HIER erhältlich. Je nachdem, ob ihr Sampling-Raten von 2 oder 4 Mhz benötigt oder ob euch maximal 1 Mhz ausreichen, muss dort der passende Sketch herunter geladen und auf den Arduino gespielt werden. Außerdem muss muss noch die Datei "ols.profile-agla.cfg" herunter geladen werden. Diese wird später benötigt.

Nachdem ihr den Sketch auf euren Arduino gespielt habt, könnte ihr probehalber den Serial Monitor öffnen, eine Baud-Rate von 115200 einstellen und entweder eine 1 oder eine 2 über die serielle Schnittstelle an den Arduino schicken. Wenn er mit einer Statusmeldung antwortet, hat soweit alles geklappt.

Als nächstes brauchen wir eine Software, die die analysierten Daten sauber auf dem PC darstellt. Dazu verwenden wir das Programm "Logic Sniffer". Das Programm basiert auf Java, kann also sowohl unter Windows als auch unter Linux verwendet werden. Ladet unter "Download" die neueste Version herunter und entpackt sie. In den Ordner "plugins" kommt die vorher herunter geladene Datei "ols.profile-agla.cfg. Nun kann das Programm gestartet werden - je nach OS mit run.bat oder run.sh. Es öffnet sich die Benutzeroberfläche:
Mit einem Klick auf "Capture"-"Begin capture" öffnet sich folgendes Fenster:
Hier stellt ihr den COM-Port ein, an dem der Arduino hängt. Im Zweifel muss auch die Baud-Rate noch passend eingestellt werden. Bei "Device type" muss der Arduino ausgewählt werden. Ein Klick auf "Show device metadata" sollte dann diverse Daten zum Vorschein bringen.
Im folgenden Reiter "Acquisition" können Details zur Datenerfassung wie z.B. die Sampling-Rate oder die Aufnahmegröße eingestellt werden.
Im letzten Reiter "Triggers" kann nun noch eingestellt werden, ob die Aufnahme durch einen Trigger gestartet werden soll. Ein Haken in der Mask-Reihe gibt an, welcher Kanal getriggert werden soll. Value gibt an, ob bei einem HIGH-Pegel (Haken gesetzt) oder bei einem LOW-Pegel (kein Haken gesetzt) aufgenommen werden soll. Die "Before/After ratio" gibt an, welcher Zeitraum vor und nach dem Trigger ausgegeben werden soll. Im abgebildeten Beispiel werden also 5% der Zeit VOR dem Trigger und 95% der Zeit NACH dem Trigger ausgegeben.

Falls noch nicht geschehen, schließt nun das zu untersuchende Signal an den Arduino an. Dabei entspricht der Kanal 0 dem Pin 8 am Arduino, Kanal 1 ist Pin 9 usw. 6 Kanäle werden unterstützt.

Wenn alles passend eingestellt und angeschlossen ist, kann der "Capture"-Knopf gedrückt werden. Wenn ihr alles richtig gemacht habt, solltet ihr nun euer Signal auf dem Bildschirm vor euch sehen:

Natürlich kann dieser Logic Analyzer nicht mit "großen" Geräten mithalten. Vorallem der Speicher für eure Aufnahmen ist begrenzt. Man kann also nur recht kurze Signale bei geringen Sampling-Raten untersuchen. Für kleine Projekte sollte es aber auf jeden Fall reichen.