AdSense

Dienstag, 10. Februar 2015

Serielle Kommunikation mit Matlab oder C#

(English version) Im vorigen Post (Herzschlag-Sensor ansteuern) habe ich erklärt, wie man mit einem Arduino über die serielle Schnittstelle den Wert des Herzschlag-Sensors sendet. In diesem Post will ich nun erklären, wie man diese Daten mit Matlab oder C# ausliest. Anfangen werde ich mit Matlab. Zuerst muss ein serieller Port geöffnet werden:

s = serial('COM3');
fopen(s);


Hier muss man einfach den entsprechenden COM-Port eintragen. Danach kann man auch schon alle verfügbaren Zeichen einlesen:

str = fscanf(s);

Das Problem daran ist allerdings, dass es auch sein kann, das eine Nachricht vom Arduino erst halb gesendet wurde und alle bisher gesendeten Zeichen eingelesen werden. Das kann man umgehen indem man z.B. alle gelesenen Zeichen in einen String schreibt und diesen dann ausliest. Am Ende sollte man nicht vergessen, den Port wieder zu schließen:

fclose(s);

Als nächstes möchte ich nun erklären wie man mit C# kommuniziert. Prinzipiell muss hier auch zuerst ein Port geöffnet werden:

port = new SerialPort("COM3", 9600);
port.Open();

Danach kann man direkt alle existierenden Zeichen lesen (analog zum Beispiel mit Matlab):

string indata = sp.ReadExisting();

In C# muss man den Port nicht unbedingt schließen, da dies beim Beenden des Programmes automatisch passiert.

Samstag, 24. Januar 2015

Herzschlag-Sensor ansteuern

(English version) Wenn man bei ebay nach "heartbeat sensor" sucht, findet man eine kleine Platine, welche mit LED und Phototransistor bestückt ist, welche angeblich den Herzschlag messen kann. Ich habe mir so ein Teil gekauft und es ausprobiert. Leider gibt es sehr wenig (ok, gar keine) Dokumentation dazu und nichtmal eine Seriennummer, alles was ich weiß ist das auf meinem Sensor xinda und Lcup drauf steht.
Der Herzschlag-Sensor
Der Sensor hat 3 Anschlüsse welche auch sehr toll beschriftet sind. Einer mit -, das ist der Anschluss für GND. Der nächste Anschluss hat ein S, das steht für Sensor, hier wird der Phototransistor ausgelesen. Dann gibt es noch den Pin in der Mitte ohne Beschriftung, das ist der Pin für die LED. Beschaltet wird der Chip ganz einfach: +5V an die LED und den Sensor-Ausgang an einen Analog-Eingang des Arduinos.

Das Programm liest nun praktisch den Sensor-Wert und sendet diesen über die serielle Schnittstelle an den Computer wo die Daten weiterverarbeitet werden können (z.B. mit Matlab, darüber werde ich vielleicht im nächsten Post etwas schreiben). Hier ist ein Bild von den geplotteten Daten mit Matlab und darunter der Code für den Arduino.
//Define pins for LED and sensor.
int ledPin = 13;
int sensorPin = 0;
//alpha is used in the original proposed code by the company (see below).
double alpha = 0.75;
//lasttime is used to have a very precise measurement of the time so the calculated pulse is correct.
unsigned long lasttime;

void setup ()
{
  //Switch on the LED.
  pinMode (ledPin, OUTPUT);
  digitalWrite(ledPin,HIGH);
  Serial.begin (9600);
  lasttime = micros();
}

void loop ()
{
  //Also used for smoothening the signal.
  static double oldValue = 0;
  
  //Wait 10 ms between each measurement.
  while(micros() - lasttime < 10000)
  {
    delayMicroseconds(100);
  }
  
  //Read the signal.
  int rawValue = analogRead (sensorPin);
  lasttime += 10000;
  
  //In the "original" code example, "value" was sent to the computer. This calculation basically smoothens "rawValue".
  //double value = alpha * oldValue + (1 - alpha) * rawValue;
  
  //Send back the measured value.
  Serial.println (rawValue);
  oldValue = value;
}

Sonntag, 18. Januar 2015

Eine Spieltisch für Tabletops

(English version) Für Tabletop-Spiele benötigt man natürlich eine Unterlage auf der man spielen kann. Für den Anfang reicht ein kleiner Tisch oder auch der Boden, wer aber große Schlachten austragen will braucht dann etwas größeres. Die standard-Größe bei Tabletop-Tischen für 28 mm Tabletops ist etwa 6 x 4 Fuß, das entspricht etwa 183 x 122 cm. So ein Tisch ist ziemlich groß und nimmt viel Platz weg, wenn man nur eine kleine Wohnung hat ist das dann nicht mehr so einfach möglich da mit so einem großen Tisch bereits ein ganzer Raum in Anspruch genommen wird. Daher habe ich einen Tisch gebaut, welchen man in 2 Minuten auf- und abbauen kann.

Die Grundidee ist simpel: Auf einen bestehenden Couch-Tisch wird eine große Holzplatte gelegt. Da mein Couch-Tisch nur 110 x 70 cm groß ist würde eine Platte der Größe 183 x 122 cm herunterhängen. Also benötigt der Spieltisch auch noch Füße. Das Ergebnis besteht nun aus zwei Platten der Größe 183 x 61 cm, welche man zusammenstecken kann. Eine Seite des Spielfeldes wird dann auf den Couch-Tisch gelegt, unter dem anderen Ende sind 2 Füße angebracht. Ich will nun auf die einzelnen Teile eingehen.
Der komplette Tisch.
Die Platten
Für die Platten habe ich eine 8 mm starke Spanplatte benutzt. Eine dickere Platte ist natürlich generell stabiler und verbiegt sich nicht so stark, jedoch erhöht sich dabei auch das Gewicht und der Preis. 8 mm funktionieren bei mir ziemlich gut, auf den Tisch sollte man sich jedoch nicht setzen.

Die Füße
Am Ende jeder Platte ist ein Fuß über ein Scharnier befestigt. Wird der Tisch weggeräumt, so klappt man den Fuß ein und er nimmt nicht übermäßig Platz weg. Für den ausgeklappten Zustand ist noch die Befestigung mit einem Spannverschluss geplant, davon kann ich allerdings keine Bilder zeigen, da ich noch auf den Artikel warte. Die Scharniere gibt es in jedem Baumarkt billig zu kaufen, ebenso das Holz für die Tischbeine.
Die Befestigung des Tischbeines.
Das Zusammenstecken
Beim Obi gibt es spezielle Schranktür-Verschlüsse, welche man einfach ineinander stecken kann. Diese habe ich an die beiden Platten gebaut sodass die Platten ineinander gesteckt werden können.
Die Steckverbindung zwischen den Platten.
Positionierung auf dem Couchtisch
Am Ende habe ich noch kleine Holzblöcke unten an die Platten geklebt, sodass der Tisch sich nicht mehr bewegen kann, und perfekt auf dem Couch-Tisch sitzt.
Links im Bild der Couch-Tisch mit dem Holzblock unten an der Tischplatte.
Auf dem Tisch kann nun das Gelände verteilt werden oder eine Grasmatte ausgebreitet werden. Alternativ könnte man die Platten auch mit Gras bedecken oder einem farbigen Stoff, oder, wenn man es ganz simpel halten will, einfach in einer Farbe anmalen, das könnte z.B. für große Wasserflächen praktisch werden.

Dienstag, 13. Januar 2015

Arduino - Keypad auslesen

(English version) Heute möchte ich kurz vorstellen wie man ein simples Keypad, wie im folgenden Bild zu sehen, mit dem Arduino auslesen kann. Man könnte dazu z.B. dieses hier von ebay nehmen: Keypad.
Das Keypad hat 8 Anschlüsse. Jeweils 4 sind dabei für die Zeilen bzw. Spalten. Ein Tastendruck verbindet nun zwei dieser Anschlüsse. 4 Anschlüsse werden am Arduino als Output genutzt, die anderen 4 als Input. Ich habe Pin 22, 24, 26 und 28 als Output benutzt und 30, 32, 34, 36 als Input, man kann das Display dadurch sehr einfach anschließen, indem man eine Stiftleiste benutzt.
Nun legt man nacheinander an jeden Output eine Spannung an und misst dabei, welcher Input diese Spannung abbekommt. Dadurch weiß man sofort welche Tasten gedrückt wurden. Mein Code liest die Tasten aus und sendet, sobald sich der Status einer Taste geändert hat, dies über die serielle Schnittstelle an den Computer.


//For different sizes of Keypads, you can adjust the numbers here. Important: Also change the keyValues array!
const int numOuts = 4;
const int numIns = 4;
//These are the 4 output pins, adjust it if you use a different pin mapping
int outs[numOuts] = {22, 24, 26, 28};
//These are the 4 input pins, adjust it if you use a different pin mapping
int ins[numIns] = {30, 32, 34, 36};
//This array contains the values printed to the different keys
char keyValues[numOuts][numIns] = {{'1','2','3','A'},{'4','5','6','B'},{'7','8','9','C'},{'*','0','#','D'}};
//This array contains whether a pin is pressed or not
boolean pressed[numOuts][numIns];

void setup() {  
  Serial.begin(9600);
  //Define all outputs and set them to high
  for (int i = 0; i < numOuts; i++)
  {
    pinMode(outs[i], OUTPUT);
    digitalWrite(outs[i], HIGH);
  }
  //Define all inputs and activate the internal pullup resistor
  for (int i = 0; i < numIns; i++)
  {
    pinMode(ins[i], INPUT);
    digitalWrite(ins[i], HIGH);
  }
}

//Read whether a key is pressed
void KeyPressed()
{
  for (int i = 0; i < numOuts; i++)
  {
    //Activate (set to LOW) one output after another
    digitalWrite(outs[i], LOW);
    //Wait a short time
    delay(10);
    for (int j = 0; j < numIns; j++)
    {
      //Now read every input and invert it (HIGH = key not pressed (internal pullup), LOW = key pressed (because the output was set to LOW)
      boolean val = !digitalRead(ins[j]);
      //If the value changed, send via serial to the computer and save the value in the "pressed" array
      if (pressed[i][j] != val)
      {
        char str[255];
        sprintf(str, "%c pressed: %d", keyValues[i][j], val);
        Serial.println(str);
        pressed[i][j] = val;
      }
      
    }
    //Deactivate (set back to HIGH) the output
    digitalWrite(outs[i], HIGH);
  }
}

//Yeah, do this forever...
void loop()
{
  KeyPressed();
}

Sonntag, 14. Dezember 2014

Arduino - Barometrischen Höhensensor GY-65 auslesen

(English version) Eine weit verbreitete Möglichkeit, relative Höhen zu messen ist das Benutzen eines barometrischen Höhensensors. Dieser misst einfach den Druck und aus der barometrischen Höhenformel (Wikipedia) lässt sich daraus eine Höhe bestimmen. Da der Luftdruck sehr stark vom Tag abhängt wird normalerweise an einer bekannten Höhe der Sensor kalibriert und dann die restlichen Höhen relativ zu dieser Höhe und dem dort gemessenen Druck berechnet. Das liefert Höhen mit einer Genauigkeit von bis zu 1 Meter.

Wenn man bei ebay nach GY-65 sucht, findet man den entsprechenden Sensor für ca. 5 Euro. Der Sensor hat ein normales I2C-Interface, sodass nur 2 Kabel nötig sind. Für den Arduino braucht man dann die I2Cdev Library, die gibt es hier zum runterladen. Der Quellcode an sich ist maximal simpel, zuerst wird der Sensor initialisiert, dann wird eingestellt, dass der Druck gemessen werden soll und anschließen der Druck ausgelesen und daraus die Höhe berechnet. Ein komplettes, simples Beispielprogramm sieht so aus:


#include <I2Cdev.h>
#include "BMP085.h"
#include <Wire.h>

BMP085 barometer;

double pressure;
double altitude;


void setup() {
  Wire.begin();
  
  Serial.begin(9600);
  Serial.println("starting...");
    
  //initialize the barometer
  barometer.initialize();
}

void loop()
{
  // request pressure (3x oversampling mode, high detail, 23.5ms delay).
  // Let's just wait a bit more to be sure...
  barometer.setControl(BMP085_MODE_PRESSURE_3);
  delay(30);
  // read calibrated pressure value in Pascals (Pa)
  pressure = barometer.getPressure();
  // calculate absolute altitude in meters based on known pressure
  // (may pass a second "sea level pressure" parameter here,
  // otherwise uses the standard value of 101325 Pa)
  altitude = barometer.getAltitude(pressure); 
  
  // print back the calculated altitude
  Serial.println(altitude);
  // do this every second
  delay(1000);
}

I2C OLED Display

(english version) Wer bei Ebay nach "Arduino OLED Display" sucht, stößt auf ein OLED-Display mit einer Bildschirmdiagonale von ca. 1 Zoll und einer Auflösung von 128x84 Pixel. Das Display ist für weniger als 4 Euro zu haben. Angesteuert wird es über I2C. 1 Zoll ist natürlich nicht viel, aus Interesse habe ich mir das Display aber dennoch bestellt. Damit man sich vorstellen kann, wie klein es wirklich ist, habe ich eine Münze zum Vergleich daneben gelegt:

Dank Ansteuerung über I2C ist die Verkabelung denkbar übersichtlich: neben der Spannungsversorgung sind nur zwei Kabel für den I2C-Bus nötig, das wars. Nun stellt sich natürlich die Frage: wie steuere ich das Ding an? Nach kurzer Recherche habe ich heraus gefunden, dass es sich bei dem Display um einen Nachbau des OLED-Displays mit der Bezeichnung SSD1306 von Adafruit handelt. Dafür bietet Adafruit eine fertige Arduino-Library an, welche HIER erhältlich ist. Außerdem muss die Adafruit-GFX-Library herunter geladen und installiert werden. In der Arduino IDE findet sich dann unter "Adafruit_SSD1306" das Beispiel "ssd1306_128x64_i2c". Wer dieses Beispiel nun einfach so 1:1 auf den Arduino überträgt sieht erstmal: gar nichts. Das China-Display hat eine andere I2C-Adresse wie das Original von Adafruit, daher muss in der setup()-Funktion eine kleine Änderung durchgeführt werden: die Adresse muss von 0x3D in 0x3C geändert werden. Aus
  display.begin(SSD1306_SWITCHCAPVCC, 0x3D);  // initialize with the I2C addr 0x3D (for the 128x64)
wird
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64).
Dann dann kann das Beispiel auf den Arduino übertragen werden. Ihr solltet jetzt eine kleine Demonstration der verschiedenen Funktionen der GFX-Library auf dem Display sehen. Da die Funktionen und somit auch das Beispiel sehr umfangreich sind, werde ich sie nicht im Detail erläutern. Im Prinzip sind die Funktionen im Beispiel alle selbsterklärend. Bei Unklarheiten schaut in die Header-Datei der GFX-Library, dort ist auch erläutert, welche Parameter die einzelnen Funktionen erwarten. Es gibt die Möglichkeit Text auszugeben, außerdem lassen sich Linien und diverse Formen (Rechteck, Dreieck, ...) mit und ohne Füllung zeichnen. Auch das Invertieren des Bildschirms sowie das Scrollen sind möglich.

Außerdem kann ein vordefiniertes Bitmap ausgegeben werden. Dies möchte ich kurz näher erklären:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#define XPOS 50
#define YPOS 25
#define BITMAP_HEIGHT 16 
#define BITMAP_WIDTH  16 
static const unsigned char PROGMEM bitmap[] =
{ B00000001, B10000000,
  B00000010, B01000000,
  B00000100, B00100000,
  B00001000, B00010000,
  B00010000, B00001000,
  B00111111, B11111100,
  B00101000, B00010100,
  B00100100, B00100100,
  B00100010, B01000100,
  B00100001, B10000100,
  B00100010, B01000100,
  B00100100, B00100100,
  B00101000, B00010100,
  B00110000, B00001100,
  B00111111, B11111100,
  B00000000, B00000000 };

void setup()   {                

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x64)
  
  //clear display buffer
  display.clearDisplay();
  //draw a bitmap stored in variable bitmap with given size at XPOS, YPOS in color white
  display.drawBitmap(XPOS, YPOS, bitmap, BITMAP_WIDTH, BITMAP_HEIGHT, WHITE);
  display.display();
 
}


void loop() { 
}

In diesem Beispiel zeichnen wir ein Bitmap mit einer Größe von 16x16 Pixeln. Die Größe des Bitmaps kann natürlich angepasst werden. Das Bitmap muss in einem Character-Array hinterlegt sein. Besonders wichtig ist hier bei der Deklaration das Schlüsselwort "PROGMEM". Es sorgt dafür, dass die Variable im Flash-Speicher des Arduinos abgelegt wird. Dies wird von der Library so erwartet. Im Beispiel speichern immer jeweils zwei Character in insgesamt 16 Bit den Inhalt einer Zeile. Ist ein Bit gesetzt, wird beim später Zeichnen ein Pixel gesetzt. Der Übersicht halber habe ich im Code Zeilenumbrüche eingefügt. Eine Zeile im Code entspricht nachher eine Zeile des Bitmaps. Zur Darstellung des Bitmaps wird dann der Befehl drawBitmap() aufgerufen. Als Parameter werden übergeben: die X- und Y-Position des Bitmaps, die Variable, in der das Bitmap gespeichert ist, die Breite und die Höhe des Bitmaps sowie die Farbe (WHITE oder BLACK), in der ein gesetzter Pixel dargestellt werden soll.
Das Ergebnis:

Freitag, 5. Dezember 2014

Einen Pinsel wieder anspitzen

(English version) Ein neu gekaufter Pinsel ist normalerweise sehr spitz und auch etwas hart, sodass man damit sehr gut feine Linien malen kann. Nach einer Weile fangen die Häärchen aber an, in alle Richtungen abzustehen, sodass man den Pinsel eigentlich nicht mehr benutzen kann. Um den Pinsel wieder so spitz wie am Anfang zu bekommen kann man einen ganz einfachen Trick benutzen.
Ein benutzer Pinsel mit welchem keine feinen Malarbeiten mehr möglich sind.
Zuerst wird Zuckerwasser hergestellt. Einfach Wasser und Zucker mischen und gut umrühren. Danach wird der Pinsel in die Lösung getaucht. Die Oberflächenspannung hält die Pinselhaare dann schon grob zusammen.
Pinselspitze mit Zuckerlösung. Die Haare werden von alleine zusammengehalten (Oberflächenspannung).
Um den Pinsel jetzt perfekt spitz zu bekommen streicht man ihn sehr vorsichtig ab, dadurch wird er noch spitzer. Wenn man ihn jetzt noch trocknen lässt bildet sich wieder die Spitze wie bei einem neu gekauften Pinsel. Ich benutze Pinsel der Größe 00, die gibt es meistens ganz billig (1 €) in jedem Spielwarenhandel. Wenn man den Pinsel dann entsprechend pflegt bleibt die Spitze auch so perfekt und man kann ihn nahezu unendlich lange benutzen.
Der wieder spitze Pinsel.