AN 1006: Erhalten von Messungen von TFC-Signalwandlern

Beschreibung

This Application Note explains how to obtain tilt measurements from an electrolytic tilt sensor and signal conditioner. It covers schematics and code for each protocol available on signal conditioners from The Fredericks Company. All examples will show code and circuits with an Arduino Uno, so there will be differences in code when using other platforms. Each example will provide a raw output from the sensor in a variety of units. Any of these units can be converted to degrees using the methods explained in Application Note 1005.

Analog

Both the 1-6200-007 and 1-6200-012 signal conditioners have analog outputs. On the 1-6200-007, both axes and the temperature are output from pins XA, YA, and T respectively. Connecting to the Arduino requires direct connections from the signal conditioner to the analog input pins of the Arduino.

Abbildung 1 Schaltplan für den Anschluss des 1-6200-007 an den Arduino über Analog

Beachten Sie, dass der Signaltrenner 1-6200-012 keinen analogen Temperaturausgang hat, sodass die Temperatur über RS-232 ausgelesen werden muss. Weitere Informationen zum Auslesen der Temperatur aus dem 1-6200-012 finden Sie im Abschnitt über RS-232.

Wenn die Schaltung aufgebaut ist, können die Daten mit der Funktion analogRead() des Arduino gelesen werden. Ein Beispiel hierfür ist unten dargestellt:

x = analogLesen(A0);
y = analogLesen(A1);
Temperatur = analogLesen(A2);

Das Ergebnis dieses Codes ist ein Rohwert, der die Spannung an den analogen Pins darstellt. Die Auflösung dieser Messung hängt von der zum Lesen der Spannung verwendeten Hardware ab; bei einem Arduino Uno haben die Analogpins eine Auflösung von 10 Bit.

PWM

PWM-Messungen sind für den Signalkonditionierer 1-6200-007 verfügbar. Mit PWM können die x- und y-Neigungswinkel an den digitalen XP- und YP-Pins des Signalwandlers abgelesen werden. Da es keinen PWM-Ausgang für die Temperatur gibt, muss diese über den analogen Pin abgelesen werden. Ein Schaltplan für diesen Aufbau ist in Abbildung 2 dargestellt.

Abbildung 2 Schaltplan zum Anschluss des 1-6200-007 an den Arduino mit PWM

Beachten Sie, dass die PWM-Ausgänge an beliebige digitale Pins des Arduino angeschlossen werden können, nicht nur an die PWM-Pins. In diesem Beispiel werden die Pins D7 und D8 verwendet, beides Nicht-PWM-Pins.

Das Lesen eines PWM-Signals mit einem Arduino wird am besten mit der pulseIn()-Funktion durchgeführt. Die pulseIn()-Funktion misst, wie lange ein Impuls entweder im Highoder Low-Zustand dauert. In diesem Fall werden wir den High-Zustand messen.

x = pulseIn(XPIN, HIGH);
y = pulseIn(YPIN, HIGH);
Temperatur = analogRead(A0);

char res[50];
sprintf(res, "X: %i, Y: %i, Temperatur: %i", x, y, Temperatur);
Serial.println(res)

Das Ergebnis ist die Länge des Impulses in Mikrosekunden. Die Funktion pulseIn() kann Impulse mit einer Länge von bis zu 10 µs lesen, was bedeutet, dass ihre Messung des bis zu 8 ms langen Impulses eine ähnliche Genauigkeit wie ein 10-Bit-Ausgang hat. Diese Genauigkeit wird höher sein, wenn das Gerät, das sie liest, kleinere Pulse erkennen kann.

SPI

SPI ist ein synchrones serielles Kommunikationsprotokoll, das auf dem Signalkonditionierer 1-6200-005 verfügbar ist. Das Protokoll arbeitet in einer Master/Slave-Technik mit 4 Anschlüssen: MISO (Master In Slave Out), MOSI (Master Out Slave In), CLK (Serial Clock) und SS (Slave Select). Der Master sendet Befehle an den Slave über MOSI (mit IN auf dem 1-6200-005 beschriftet), und der Slave antwortet über MISO (mit OUT auf dem 1-6200-005 beschriftet). CLK ist ein vom Master erzeugter Takt, der die Kommunikation des Slaves synchronisiert. SS wird verwendet, um einen Slave zu aktivieren; mit diesem Pin unterstützt SPI mehrere Geräte an einem Bus (siehe Abschnitt "SPI-Bus" für weitere Informationen).

Der Arduino Uno hat vordefinierte Pins für MOSI, MISO und CL. Diese sind in der folgenden Tabelle dargestellt:

MOSI D11
MISO D12
CLK D13

Das Schaltbild zum Anschluss an den Arduino ist in Abbildung 3 dargestellt.

Abbildung 3 Schaltplan zum Anschluss des 1-6200-005 an den Arduino mit SPI

Um mit dem Sensor zu kommunizieren, verwenden wir die SPI-Bibliothek von Arduino. Mit SPI.begin() wird die SPI-Bibliothek initialisiert (die Kommunikation wird jedoch nicht geöffnet). Da diese Schaltung nur ein SPI-Gerät hat, wird Pin 10 (SS) auf LOW gesetzt, wodurch der über diesen Pin gesteuerte Slave aktiviert wird. Dieser wird für das gesamte Programm auf LOW gesetzt bleiben; es gibt keinen Grund, den Slave in dieser Schaltung zu deaktivieren.

void setup() {
    SPI.begin(); // initialize SPI
    digitalWrite(10, LOW); // enable slave 1
}

Nachdem wir nun die Bibliothek initialisiert haben, müssen wir die Verbindung mit dem Signalaufbereiter öffnen. Dies geschieht mit der Funktion SPI.beginTransaction(). Diese Funktion nimmt ein Argument entgegen, ein SPISettings-Objekt. Dieses Objekt stellt alle notwendigen Informationen zur Verfügung, um die Verbindung herzustellen. Das SPISettings-Objekt hat drei Argumente:

  1. Maximale Taktrate des Slaves, die beim 1-6200-005 20Mhz beträgt.
  2. Das zweite Argument legt fest, ob die SPI-Schnittstelle das Most Significant Bit oder das Least Significant Bit First verwenden soll. Für den 1-6200-005 ist dies Most Significant Bit First (oder MSBFIRST).
  3. Das dritte Argument bestimmt den SPI-Modus; beim 1-6200-005 wird der SPI-Modus 2 (CPOL=1, CPHA=0) verwendet.
// SPI-Kommunikation öffnen
SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE2));

Die Funktion SPI.transfer() wird zum Senden und Empfangen von Daten verwendet. Sie sendet gleichzeitig den Befehl und gibt zurück, was sie vom MISO-Pin liest. Beachten Sie, dass der Slave immer einen Taktzyklus benötigt, um zu antworten; daher wird das Ergebnis von jedem Befehl erst im nächsten Zyklus empfangen. Im folgenden Code zum Beispiel gibt die Funktion, die die Anforderung des Low-Bytes der X-Achse sendet, aufgrund dieser Verzögerung den High-Byte-Wert der X-Achse zurück.

Beachten Sie, dass der Befehl 0x39 wichtig ist, um gute Messungen zu erhalten. Dieser Befehl weist die Karte an, eine neue Messung der Neigung zu erhalten. Im untenstehenden Code wird er einmal am Anfang und einmal am Ende der if-Anweisung gesendet, wo das Bit für die niedrige Temperatur empfangen wird.

    SPI.transfer(0x39); // update sensor data
    delay(1); // wait for SPI response
    res = SPI.transfer(0x31); // get status, request high x byte
    delay(1); // wait for SPI response

    if (res == 0x2A) { // verify sensor data updated successfully
        high = SPI.transfer(0x32); // get high x byte, request low x byte
        delay(1); // wait for SPI response
        low = SPI.transfer(0x33); // get low x byte, request high y byte
        x = (high << 8) | low; // merge low and high bytes into int

        delay(1); // wait for SPI response
        high = SPI.transfer(0x34); // get high y byte, request low y byte
        delay(1); // wait for SPI response
        low = SPI.transfer(0x35); // get low y byte, request high temperature byte
        y = (high << 8) | low; // merge low and high bytes into int

        delay(1); // wait for SPI response
        high = SPI.transfer(0x36); // get high temp byte, request low temp byte
        delay(1); // wait for SPI response
        low = SPI.transfer(0x39); // get low temperature byte, update sensor data
        temperature = (high << 8) | low; // merge low and high bytes into int
    }

    SPI.endTransaction(); // close the SPI communication

Note that the responses will be in separate high and low bytes. The code above converts these to 16-bit integers using the expression (high << 8) | low.

SPI-Bus

Es ist auch möglich, 1-6200-005 Signalkonditionierer in einem SPI-Bus zusammenzuschalten. Ein SPI-Bus ermöglicht es allen SPI-Geräten, sich die Anschlüsse CLK, MISO und MOSI zu teilen. Jeder Slave erhält jedoch seinen eigenen SS-Anschluss, so dass der Master auswählen kann, mit welchem Slave er kommunizieren möchte. Die Anzahl der SPI-Bausteine, die Sie gleichzeitig verwenden können, ist durch die Anzahl der unabhängigen SS-Verbindungen begrenzt, die Sie herstellen können. Abbildung 4 zeigt den Schaltplan für 2 Sensoren an einem SPI-Bus, wobei die Pins D9 und D10 als SS-Signale verwendet werden.

Abbildung 4 Schaltplan für den Anschluss von zwei 1-6200-005 an Arduino mit einem SPI-Bus. Beachten Sie die separaten /SS-Anschlüsse für jedes Gerät

Dieser Code ist dem Code für das einzelne SPI-Gerät sehr ähnlich; beachten Sie, dass die SS-Pins geändert werden, um zu steuern, mit welchem Slave kommuniziert wird.

// open SPI communication

    SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE2));
    digitalWrite(10, LOW); // enable the slave controlled by D10

    SPI.transfer(0x39); // request status
    delay(1);
    res = SPI.transfer(0x31); // get status, request high x byte
    delay(1);

    if (res == 0x2A) {
        hi = SPI.transfer(0x32); // get high x byte, request low x byte
        delay(1);
        lo = SPI.transfer(0x33); // get low x byte, request high y byte
        x = (hi << 8) | lo;

        delay(1);
        hi = SPI.transfer(0x34); // get high y byte, request low y byte
        delay(1);
        lo = SPI.transfer(0x35); // get low y byte, request high temperature byte
        y = (hi << 8) | lo;

        delay(1);
        hi = SPI.transfer(0x36); // get high temperature byte, request low temperature byte
        delay(1);
        lo = SPI.transfer(0x39); // get low temperature byte
        temperature = (hi << 8) | lo;
    }

    digitalWrite(10, HIGH); // disable the slave controlled by D10
    digitalWrite(9, LOW); // enable the slave controlled by D9

    SPI.transfer(0x39); // request status
    delay(1);
    res = SPI.transfer(0x31); // get status, request high x byte
    delay(1);

    if (res == 0x2A) {
        hi = SPI.transfer(0x32); // get high x byte, request low x byte
        delay(1);
        lo = SPI.transfer(0x33); // get low x byte, request high y byte
        x = (hi << 8) | lo;

        delay(1);
        hi = SPI.transfer(0x34); // get high y byte, request low y byte
        delay(1);
        lo = SPI.transfer(0x35); // get low y byte, request high temperature byte
        y = (hi << 8) | lo;

        delay(1);
        hi = SPI.transfer(0x36); // get high temperature byte, request low temperature byte
        delay(1);
        lo = SPI.transfer(0x39); // get low temperature byte
        temperature = (hi << 8) | lo;
    }

    digitalWrite(9, HIGH); // disable the slave controlled by D9
    SPI.endTransaction(); // close the SPI communication

Beachten Sie, dass, wenn 2 SPI-Slaves gleichzeitig aktiviert sind und eine Nachricht gesendet wird, die Signale sich gegenseitig stören und die Antwort nicht richtig gelesen werden kann.

RS-232

RS-232 (TIA-232) ist ein gängiges serielles Kommunikationsprotokoll. Eine 3-Draht-Version von RS-232 ist sowohl bei den Signalkonditionierern 1-6200-006 als auch 1-6200-012 verfügbar. Der Anschluss von RS-232 besteht darin, die Erdungen miteinander zu verbinden und jeden Rx mit dem Tx des anderen Geräts zu verbinden.

In dieser Anwendung werden wir die SoftwareSerial-Bibliothek des Arduino verwenden, um eine virtuelle serielle Schnittstelle zu erstellen und zu verwenden. Diese Bibliothek gibt uns die Möglichkeit, die Signale an der Schnittstelle zu invertieren, was für die Kommunikation mit dem Sensor erforderlich ist. Außerdem bleibt die serielle Hardware-Schnittstelle für andere Zwecke verfügbar. Um die Schaltung für RS-232 zu erstellen, verbinden Sie einfach D10 (unseren virtuellen RX-Pin) mit OUT und D11 (unseren virtuellen TX) mit IN. Dies ist in Abbildung 5 dargestellt.

Abbildung 5 Schaltplan zum Anschluss des 1-6200-006 an den Arduino mit RS-232 und der SoftwareSerial-Bibliothek

Mit SoftwareSerial können Sie die virtuelle serielle Schnittstelle mit folgendem Code initialisieren:

SoftwareSerial Sensor(10, 11, true); //RX, TX, inverse
void setup() {
    Sensor.begin(9600); //RX, TX, invert
}

Beachten Sie, dass Geräte mit seriellen UART-TTL-Ports (wie der Arduino) eine invertierte serielle Verbindung benötigen, da sie sonst nicht kommunizieren können. Bei einem Arduino wird dies mit dem dritten Argument beim Erstellen der virtuellen seriellen Schnittstelle gemacht ("true" für ein invertiertes Signal).

Um die Neigung über RS-232 zu lesen, senden Sie zuerst den Befehl für die gewünschten Daten und lesen dann die Daten vom Anschluss. Der Code zum Lesen der Werte für die x-Achse, die y-Achse und die Temperatur ist unten aufgeführt:

Sensor.print('x'); // send command for x axis tilt
delay(50); // delay to give time for response
b = 0;
while (Sensor.available() != 0 && b < 8) {
    x[b++] = Sensor.read(); // read received bytes into char array
}

Sensor.print('y'); // send command for y axis tilt
delay(50);
b = 0;
while (Sensor.available() != 0 && b < 8) {
    y[b++] = Sensor.read();
}

Sensor.print('t'); // send command for temperature
delay(50);
b = 0;
while (Sensor.available() != 0 && b < 8) {
    temperature[b++] = Sensor.read();
}

The definitions of all RS-232 commands are available on the datasheet for the signal conditioner.

Die Antwort dieses Codes ist ein 8-Byte-Zeichenarray, das durch Zeilenumbruch- und Wagenrücklaufzeichen (0x0a, 0x0d) abgeschlossen wird. Es handelt sich nicht um eine Zeichenkette, daher muss sie wahrscheinlich in eine Zeichenkette konvertiert werden. Falls erforderlich, kann es auch in einen int konvertiert werden.

// Char-Array in String umwandeln
    x[b - 2] = '\0';

   // String in 16-Bit-Int konvertieren
    xInt = atoi(x);

Der obige Code ersetzt das Newline-Zeichen durch das Null-Zeichen und beendet die Zeichenkette unmittelbar nach dem letzten Zeichen. Dies erfordert die Verwendung der b-Variablen, so dass es wahrscheinlich sofort nach dem Empfang der Messung erfolgen muss. Um dies zu erreichen, ohne die b-Variable zu verwenden, kann das Terminierungszeichen auch am Ende des Arrays platziert werden, aber dies hinterlässt Leerzeichen und Zeichen.

RS-485

RS-485 (TIA-485) ist ein serieller Kommunikationsstandard, der über große Entfernungen und in elektrisch verrauschten Umgebungen gut funktioniert. Er ist auf dem Signalaufbereiter 1-6200-008 verfügbar. Der Arduino Uno unterstützt RS-485 nicht selbst, aber ein Konverter kann verwendet werden, um die Kommunikation mit einem unserer RS-485-Produkte zu erleichtern.

Bei den meisten RS-485-Konvertern sind DI (Data In) und RO (Receive Out) der Rx bzw. Tx. RE (Receive Enable) und DE (Data Enable) steuern, wann der Konverter RS-485-Daten sendet und empfängt; diese können im Allgemeinen miteinander verbunden und umgeschaltet werden (High zum Senden von Daten, Low zum Empfangen von Daten). Die Anschlüsse A und B am Konverter werden mit A und B am Signalaufbereiter verbunden. Das Schaltbild für diese Schaltung ist in Abbildung 6 dargestellt.

Abbildung 6 Schaltplan zum Anschluss des 1-6200-008 an den Arduino mit RS-485. RS-485-Konverter als Zwischenglied verwendet

Die RS-485-Befehle, die zur Kommunikation mit dem Signalaufbereiter verwendet werden, verwenden das folgende Format:

*xxyy*.

Der * ist das Startzeichen, mit dem jeder Befehl beginnt. xx ist die Adresse, an die der Befehl gesendet wird. Standardmäßig ist dies 99 auf dem 1-6200-008. yy ist der Befehl selbst. Das # signalisiert das Ende des Befehls. Zum Beispiel lautet der Befehl zum Lesen der Neigung der x-Achse auf Adresse 99 *9911#. Alle verfügbaren Befehle finden Sie auf dem Datenblatt des 1-6200-008.

Mit dem Inline-Konverter RS-232 zu RS-485 können diese Befehle mit RS-232 an den Konverter gesendet werden. Der Konverter sendet sie dann an den Signalkonditionierer mit RS-485. Die Setup-Funktion ist dann die gleiche wie beim RS-232-Signalaufbereiter. Der nachstehende Code zeigt, wie diese Konfiguration verwendet werden kann, um Daten aus dem Signalkonditionierer zu lesen:

// x axis tilt
    digitalWrite(9, HIGH); // enable transmission
    Sensor.print("*9911#"); // send x axis command
    digitalWrite(9, LOW); // enable reception
    delay(25); // wait for sensor to respond
    b = 0;
    while (Sensor.available()) {
        x[b++] = Sensor.read(); // store response in a char array
    }

    // y axis tilt
    digitalWrite(9, HIGH); // enable transmission
    Sensor.print("*9921#"); // send y axis command
    digitalWrite(9, LOW); // enable reception
    delay(25);
    b = 0;
    while (Sensor.available()) {
        y[b++] = Sensor.read(); // store response in char array
    }

    // temperature
    digitalWrite(9, HIGH); // enable transmission
    Sensor.print("*9941#"); // send temperature command
    digitalWrite(9, LOW); // enable reception
    delay(25);
    b = 0;
    while (Sensor.available()) {
        temperature[b++] = Sensor.read(); // store response
    }

Wie bei RS-232 ist die Antwort ein Zeichenarray, das durch eine neue Zeile und einen Wagenrücklauf abgeschlossen wird. Wenn Sie das Array als String behandeln möchten, müssen Sie das Null-Zeichen ('\0') anhängen.

Adressiert RS-485

Es ist möglich, bis zu 32 Signalkonditionierer 1-6200-008 an einen einzigen Bus anzuschließen. Den Signalkonditionierern können dann Adressen zugewiesen werden, so dass jeder Sensor bestimmen kann, ob er reagieren soll. Beachten Sie, dass es wichtig ist, den Anschluss mehrerer Sensoren mit derselben Adresse zu vermeiden, da die Sensoren die Übertragungen der anderen Sensoren stören.

Standardmäßig ist die Adresse des Signalkonditionierers 99. Um sie zu ändern, stellen Sie sicher, dass es das einzige angeschlossene Gerät mit dieser Adresse ist. Verwenden Sie dann den Befehl *xx81Azz#, wobei xx für die aktuelle Adresse und zz für die neue Adresse steht. Zum Beispiel:

Sensor.print("*9981A01#"); // Adresse von 99 auf 01 ändern

Sobald die Adresse geändert wurde, können Sie nicht mehr mit Befehlen, die mit 99 beginnen, auf den Sensor zugreifen. Stattdessen wird die neue Adresse 01 die 99 in allen Befehlen ersetzen. Zum Beispiel würde sich der Befehl zum Lesen der Produktinfo von *9980# auf *0180# ändern, nachdem Sie den obigen Befehl ausgeführt haben.

Sobald jedem Sensor eine eindeutige Adresse zugewiesen wurde, können sie an den Schaltkreis angeschlossen werden. Jeder Signalaufbereiter kann ohne zusätzliche Komponenten oder Anschlüsse an denselben Bus angeschlossen werden. Siehe Abbildung 7 für ein Schaltbild, das dies zeigt.

Abbildung 7 Schaltplan für den Anschluss von (4) Signaltrennern 1-6200-008 an einen Arduino mit RS-485

Nachfolgend finden Sie ein Beispiel für ein Programm, das von mehreren adressierten RS-485-Sensoren liest. Dieser Code ist für eine Schaltung geschrieben, die an 4 Sensoren angeschlossen ist, die mit 8 - 11 adressiert sind.

char addr[4][3] = {"08", "09", "10", "11"};
for (int i = 0; i < 4; i++) { // run this code for every address
    // x axis tilt
    digitalWrite(9, HIGH); // enable transmission
    sprintf(cmd, "*%2s11#", addr[i]); // create x axis command
    Sensor.print(cmd); // send x axis command
    digitalWrite(9, LOW); // enable reception
    delay(25); // wait for sensor to respond
    b = 0;
    while (Sensor.available()) {
        x[b++] = Sensor.read(); // store response from sensor in a char array
    }

    // y axis tilt
    digitalWrite(9, HIGH); // enable transmission
    sprintf(cmd, "*%2s21#", addr[i]); // create command
    Sensor.print(cmd); // send command
    digitalWrite(9, LOW); // enable reception
    delay(25);
    b = 0;
    while (Sensor.available()) {
        y[b++] = Sensor.read(); // store response
    }

    // temperature
    digitalWrite(9, HIGH); // enable transmission
    sprintf(cmd, "*%2s41#", addr[i]); // create command
    Sensor.print(cmd); // send command
    digitalWrite(9, LOW); // enable reception
    delay(25);
    b = 0;
    while (Sensor.available()) {
        temperature[b++] = Sensor.read(); // store response
    }
}

Die Antworten sind 8-Byte-Zeichen-Arrays, die die ASCII-Zeichen für eine 16-Bit-Zahl enthalten.