Beschreibung
In diesem Anwendungshinweis wird erläutert, wie Neigungsmessungen mit einem elektrolytischen Neigungssensor und einem Signalaufbereiter durchgeführt werden können. Sie umfasst Schaltpläne und Code für jedes Protokoll, das für Signalaufbereiter von The Fredericks Company verfügbar ist. Alle Beispiele zeigen Code und Schaltungen mit einem Arduino Uno, so dass es Unterschiede im Code gibt, wenn andere Plattformen verwendet werden. Jedes Beispiel liefert eine Rohausgabe des Sensors in einer Vielzahl von Einheiten. Jede dieser Einheiten kann mit den in Application Note 1005 beschriebenen Methoden in Grad umgerechnet werden.
Analog
Both the 1-6200-007 und 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 measurements are available on the 1-6200-007 signal conditioner. With PWM, the x and y tilt angles can be read from the digital XP and YP pins on the signal conditioner. There is no temperature PWM output, so that will have to be read from the analog pin. A schematic for this setup is shown in figure 2.
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:
- Maximale Taktrate des Slaves, die beim 1-6200-005 20Mhz beträgt.
- 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).
- 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
It is also possible to connect 1-6200-005 signal conditioners together in an SPI bus. An SPI Bus allows all SPI devices to share the CLK, MISO, and MOSI connections. Each slave, however, gets its own SS connection, allowing the master to select which slave it wants to communicate with. The number of SPI devices you can use at once is limited by the number of independent SS connections you can make. Figure 4 shows the schematic for 2 sensors on an SPI bus with pins D9 and D10 used as the SS signals.
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(); }
Die Definitionen aller RS-232-Befehle sind auf dem Datenblatt des Signalaufbereiters zu finden.
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.