Nixie-Projekt


von Merk und Reiser

Projekt Sommersemester 2011: Gasgefüllte Kaltkathoden-Anzeigeröhren

Nixie-Pulsmesser

Nixie-HRM (Pulsmesser mit Röhrenanzeige)

Peter Reiser & Christian Merk

Inhalt:

1. Einleitung
2. Bedienung
3. Aufbau
4. Arduino Code
5. Anhang
5.1 Stückliste
5.2 Blockschaltbild
5.3 Quellcode

1. Einleitung

Basierend auf dem Arduino Board und dem Heart Rate Monitor Interface (HRMI) wurde einen Pulsmesser aufgebaut.
Als besonderes optisches Extra erfolgt die Anzeige über nostalgische Nixie-Röhren.
Das Arduino Board bietet eine einfache Entwicklerplattform, welche auf dem ATmega328 µC mit USB und I²C Schnittstellen aufbaut. Über I²C daran angeschlossen ist das HRMI, welches als Empfänger für den Polar Coded Transmitter (T31) dient.
Die verwendeten Röhren sind vom Typ ZM1020.


2. Bedienung

Um das Gerät in Betrieb zu nehmen wird es über ein Netzteil an 9V DC angeschlossen und der Wert 000 BPM leuchtet auf.
Ist ein angelegter Brustgurt in Reichweite (ca. 80 cm) wird die Pulsrate an die Empfangseinheit übertragen und nachdem ausreichend Daten vorliegen über die Röhren angezeigt. Der Brustgurt sollte nicht zu locker sitzen und die Elektroden sollten vor dem Anlegen befeuchtet werden, um Störungen der Herzfrequenzmessung zu vermeiden.
Wenn zwischenzeitlich 0 BPM angezeigt werden obwohl der Brustgurt angelegt ist, zeugt dies keineswegs vom spontanen Ableben des Trägers, sondern der Brustgurt kann entweder keine Herzfrequenz messen (Kontaktproblem) oder die Funkverbindung wurde unterbrochen.


3. Aufbau

Bei der Auswahl des Gehäuses sollte beachtet werden, dass die beiden Anzeigeplatinen eine Fläche von mindestens 80 x 160 mm benötigen. Um alle Platinen problemlos darin unterzubringen sollte das Gehäuse zudem mindestens 70 mm hoch sein. Wir haben das Axxatronic Universalgehäuse Serie 101 ABS (L x B x H) 190 x 115 x 75 mm Hell-Grau gewählt. Um von außen sichtbare Schrauben zu vermeiden haben wir die Platinen mit Abstandshaltern auf eine 100 x 160 mm große Lochrasterplatine geschraubt.


Abb.1: Aufbau auf der Lochrasterplatine

Abb.2: Anzeigeplatinen mit Abstandshalter befestigt

Das Arduino Board mit HRMI-Shield und die 170V Spannungsplatine wurden dicht oberhalb der Bodenplatte angebracht, während die Anzeigeplatinen mit 3,5 mm langen Abstandshaltern darüber montiert wurden. Die Verdrahtung erfolgte nach Blockschaltbild und seitlich am Gehäuse wurde eine Buchse für die 9V Spannungsversorgung angebracht. Anschließend wurde die Bodenplatte mitsamt Aufbau mit den Befestigungsdomen am Gehäuseunterteil verschraubt. Zuletzt wurde der Deckel mit 30 mm Bohrungen für die Nixie-Röhren aufgeschraubt. Die Beschriftung erfolgte über ein bedrucktes Klebeetikett, das in die Vertiefung am Deckel eingepasst wurde.


Abb.3: Platinen im Gehäuse befestigt

Abb.4: Fertiger Nixie-HRM

                                             

4. Arduino Code

Der Code wurde mit Hilfe des Arduino Development Environment geschrieben. Es werden zwei Header benötigt:
Wire.h:
Konfiguration und Kommunikation über I²C
Die Dokumentation der Wire.h gibt es hier.

Nixie.h:
Ansteuerung der Röhren. Detailierte Informationen sind bei den Kollegen der Anzeigegruppe zu finden.
Zunächst müssen diverse Konstanten definiert werden:

I²C:
#define hrmi_Address 0x7F  - I²C Adresse vom HRMI
#define hrmi_Baudrate 9600 - I²C Baudraute
#define heart_data 12      - Anzahl der auszulesenden Werte + 2 Status Bytes

Nixie Anzeige:
#define dataPin 2          - data line pin (SER)
#define clockPin 3         - clock pin (SCK)
#define latchPin 4         - latch pin (RCK)
#define numDigits 4        - Anzahl Digit

Funktion 'setup':
void setup()
{
  nixie.clear(numDigits);  - Nixie Anzeige zurücksetzen
  Wire.begin();            - Arduino als Master am I²C Bus
  Serial.begin(9600);      - Seriellen Port (USB) auf 9600 Baud konfigurieren
}

Funktion 'anzeigen':
void anzeigen(int HRate)                     - Ansteuern der Nixie-Röhren, Puls wird als Integer übergeben
{
  int arrayNums[numDigits];

  arrayNums[0] = 0;                          - Algorithmus zum Aufteilen der Zahl auf die
  arrayNums[1]= HRate %10;                     einzelnen Stellen. Da auf einer Platine zwei Röhren
  arrayNums[2]= (HRate %100) / 10;             vorgesehen sind hat das Array die Größe 4. Da aber nur
  arrayNums[3]= HRate / 100;                   drei Röhren bestückt sind, hat die erste Stelle den Wert 0.

  nixie.writeArray( arrayNums, numDigits);   - Serielle Ausgabe zur Anzeigeplatine
}

Funktion 'loop':
void loop()                                      - Entspricht der main Funktion als Endlosschleife
{
  int average = 0, count = 0;
  Wire.beginTransmission(hrmi_Address);          - Aufbau der I²C Verbindung zum HRMI
  Wire.send(0x47);                               - Anfrage der Pulswerte
  Wire.send(heart_data);                         - 10 Pulswerte + 2 Statusbytes sollen übertragen werden
  Wire.endTransmission();                        - Schließen der I²C Verbindung
  Wire.requestFrom(hrmi_Address, heart_data);    - Empfangen der Pulswerte vom HRMI und speichern in ein Array
  if (Wire.available()) {
    for (int i = 0; i < heart_data; i++){
      HeartRate[i] = Wire.receive();
    }
  }
  for (int i = 2; i < heart_data; i++){
    Serial.print(HeartRate[i] , DEC);            - Ausgabe der Werte über USB zur Arduino IDE
    if (HeartRate[i] != 0) {                     - Summe aus den einzelnen Werten bilden. Ungültige Werte
      average = HeartRate[i] + average;            werden als 0 übertragen, diese werden ignoriert.
      count ++;
    }
  }
  Serial.print(average, DEC);                    - Ausgabe der Summe über USB
  if (count == 0) average = 0;                   - Division durch 0 verhindern und Wert 0 speichern
  else average = average / count;                - Mittelwert berechnen
  anzeigen(average);                             - Wert anzeigen lassen
  Serial.print(count, DEC);                      - Weitere Werte über USB ausgeben
  Serial.print("  Puls: ");
  Serial.print(average, DEC);
  Serial.println();
  delay(1000);                                   - Pause von 1sec
}

5. Anhang

5.1 Stückliste

- Gehäuse: Axxatronic Universalgehäuse Serie 101 ABS (L x B x H) 190 x 115 x 75 mm Hell-Grau (Conrad Best-Nr. 531079 - 62
- Brustgurt: Polar Coded Transmitter (T31)
- Empfänger: HRMI von Sparkfun
- Prototyping Platform: Arduino UNO
- 9V Netzteil
- Hochvoltplatine
- Anzeigeplatine

5.2 Blockschaltbild

Blockschaltbild



5.3 Quellcode

Download als puls.pde.
#include <Wire.h>        //Header für I2C
#include <Nixie.h>      //Header für Nixies

#define hrmi_Address 0x7F     //I2C Adresse von HRMI (keine Jumper = 127)
#define hrmi_Baudrate 9600
#define heart_data 12        //Anzahl der auszulesenden Werte + 2 Status Bytes

#define dataPin 2    // data line or SER
#define clockPin 3   // clock pin or SCK
#define latchPin 4   // latch pin or RCK
#define numDigits 4  // Anzahl Digits

Nixie nixie(dataPin, clockPin, latchPin); //Erzeugen eines Objektes nixie der Klasse Nixie
byte HeartRate[heart_data];

void setup()
{
  nixie.clear(numDigits);      //Anzeige zurücksetzen
  Wire.begin();                //Arduino als Master am I2C Bus
  Serial.begin(9600);
}

void anzeigen(int HRate)      //Fkt. zur Nixieanzeige
{
  int arrayNums[numDigits];

  arrayNums[0] = 0;
  arrayNums[1]= HRate %10;
  arrayNums[2]= (HRate %100) / 10;
  arrayNums[3]= HRate / 100;

  nixie.writeArray( arrayNums, numDigits);
}


void loop()
{
  int average = 0, count = 0;
  Wire.beginTransmission(hrmi_Address);
  Wire.send(0x47);                  //Get Heart Rate
  Wire.send(heart_data);
  Wire.endTransmission();
  Wire.requestFrom(hrmi_Address, heart_data);
  if (Wire.available()) {                    //Daten von HRMI empfangen
    for (int i = 0; i < heart_data; i++){
      HeartRate[i] = Wire.receive();
    }
  }
  for (int i = 2; i< heart_data; i++){  //nur zur serial Ausgabe
    Serial.print(HeartRate[i] , DEC);
    if (HeartRate[i] != 0) {
      average = HeartRate[i] + average;
      count ++;
    }
  }
  Serial.print(average, DEC);
  if (count == 0) average = 0;      //Wenn kein Puls 0 anzeigen
  else average = average / count;
  anzeigen(average);
  Serial.print(count, DEC);
  Serial.print("  Puls: ");
  Serial.print(average, DEC);
  Serial.println();
  delay(1000);
}