AN 1006: Ottenere misure dai condizionatori di segnale TFC

Descrizione

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.

Analogico

Both the 1-6200-007 e 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. Wiring Schematic for the 1-6200-007 and 1-6200-012 analog signal conditioners with an Arduino Uno

Figura 1 Schema per il collegamento di 1-6200-007 ad Arduino utilizzando l'analogico

Si noti che il condizionatore di segnale 1-6200-012 non ha un'uscita analogica di temperatura, quindi la temperatura deve essere letta con RS-232. Vedere la sezione su RS-232 per maggiori informazioni sulla lettura della temperatura dal 1-6200-012.

Con il circuito assemblato i dati possono essere letti utilizzando la funzione AnalogRead() di Arduino. Un esempio di questo è mostrato di seguito:

x = analogicoLettura(A0);
y = analogicoLettura(A1);
temperatura = analogicoLettura(A2);

Il risultato di questo codice sarà un valore grezzo che rappresenta la tensione sui pin analogici. La risoluzione di questa misura dipenderà dall'hardware utilizzato per leggere la tensione; su un Arduino Uno, i pin analogici hanno una risoluzione di 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. Wiring Schematic for the 1-6200-007 PWM signal conditioners with an Arduino Uno

Figura 2 Schema per il collegamento di 1-6200-007 ad Arduino con PWM

Si noti che le uscite PWM possono essere collegate a qualsiasi pin digitale di Arduino, non solo ai pin PWM. In questo esempio vengono utilizzati i pin D7 e D8, entrambi non PWM.

La lettura di un segnale PWM con un Arduino si fa meglio con la funzione pulseIn(). La funzione pulseIn() cronometra la durata di un impulso nello stato alto o basso. In questo caso, si cronometrerà lo stato alto.

x = pulseIn(XPIN, HIGH);
y = pulseIn(YPIN, ALTO);
temperatura = analogicoLettura(A0);

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

Il risultato sarà la lunghezza dell'impulso in microsecondi. La funzione pulseIn() può leggere impulsi corti fino a 10 µs, il che significa che la sua misurazione dell'impulso fino a 8ms avrà una precisione simile a quella di un'uscita a 10 bit. Questa accuratezza sarà maggiore se il dispositivo che lo legge è in grado di rilevare impulsi più piccoli.

SPI

SPI è un protocollo di comunicazione seriale sincrono disponibile sul condizionatore di segnale 1-6200-005. Il protocollo funziona su una tecnica master/slave utilizzando 4 connessioni: MISO (Master In Slave Out), MOSI (Master Out Slave In), CLK (Serial Clock) e SS (Slave Select). Il master invierà i comandi allo slave su MOSI (etichettato IN sul 1-6200-005), e lo slave risponderà su MISO (etichettato OUT sul 1-6200-005). CLK è un orologio creato dal master che sincronizza la comunicazione dello slave. SS è usato per abilitare uno slave; questo pin è il modo in cui SPI supporta più dispositivi su un unico bus (vedere la sezione "SPI Bus" per maggiori informazioni).

L'Arduino Uno ha dei pin predefiniti per il MOSI, MISO e CL. Questi sono mostrati nella seguente tabella:

MOSI D11
MISO D12
CLK D13

Lo schema per il collegamento di questi all'Arduino è mostrato in figura 3. Wiring Schematic for the 1-6200-005 SPI signal conditioners with an Arduino Uno

Figura 3 Schema per il collegamento di 1-6200-005 ad Arduino con SPI

Per comunicare con il sensore, useremo la libreria SPI di Arduino. SPI.begin() inizializzerà la libreria SPI (ma non aprirà le comunicazioni). Poiché questo circuito ha un solo dispositivo SPI, il pin 10 (SS) sarà impostato su LOW, abilitando lo slave controllato da quel pin. Questo rimarrà impostato su LOW per l'intero programma; non c'è motivo di disabilitare lo slave in questo circuito.

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

Ora che abbiamo inizializzato la libreria, dobbiamo aprire la connessione con il condizionatore di segnale. Questo viene fatto usando la funzione SPI.beginTransaction(). Questa funzione prende un argomento, un oggetto SPISettings. Questo oggetto fornirà tutte le informazioni necessarie per creare la connessione. L'oggetto SPISettings ha tre argomenti:

  1. Velocità massima di clock dello slave, che è di 20Mhz sul 1-6200-005.
  2. Il secondo argomento determina se l'interfaccia SPI utilizzerà il Bit più significativo o il Bit meno significativo in primo luogo. Per l'1-6200-005 questo è Most Significant Bit First (o MSBFIRST).
  3. Il terzo argomento determina il modo SPI; per il 1-6200-005 si usa il modo SPI 2 (CPOL=1, CPHA=0).
// aprire la comunicazione SPI
SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE2));

La funzione SPI.transfer() viene utilizzata per inviare e ricevere dati. Essa invia contemporaneamente il comando e restituisce qualsiasi cosa legga dal pin MISO. Si noti che lo slave impiegherà sempre un ciclo di clock per rispondere; pertanto, il risultato di ogni comando non sarà ricevuto fino al ciclo successivo. Per esempio, nel codice qui sotto, la funzione che invia la richiesta dell'asse X a basso byte restituisce il valore del byte alto dell'asse X a causa di questo ritardo.

Si noti che il comando 0x39 è essenziale per ottenere buone misure. Questo comando dice alla scheda di ottenere una nuova misurazione dell'inclinazione. Nel codice sottostante, viene inviato una volta all'inizio, e ancora una volta alla fine dell'istruzione if, dove viene ricevuto il bit di bassa temperatura.

    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. Wiring Schematic for the 1-6200-005 SPI Bus signal conditioners with an Arduino Uno

Figura 4 Schema per il collegamento di due 1-6200-005 ad Arduino con un bus SPI. Notare le connessioni /SS separate per ogni dispositivo

Questo codice è molto simile a quello del singolo dispositivo SPI; si noti che i pin SS vengono modificati per controllare con quale slave viene comunicato.

// 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

Si noti che se 2 slave SPI sono abilitati contemporaneamente e viene inviato un messaggio, i segnali interferiscono e la risposta non viene letta correttamente.

RS-232

RS-232 (TIA-232) è un protocollo di comunicazione seriale comune. Una versione a 3 fili di RS-232 è disponibile sia sui condizionatori di segnale 1-6200-006 che 1-6200-012. Il collegamento RS-232 consiste nel collegare tra loro le masse e nel collegare ogni Rx al Tx dell'altro dispositivo.

In questa applicazione, useremo la libreria SoftwareSerial di Arduino per creare una porta seriale virtuale da utilizzare. Questa libreria ci dà la possibilità di invertire i segnali sulla porta, necessaria per comunicare con il sensore. Mantiene anche la porta seriale hardware disponibile per altri usi. Per creare il circuito per RS-232, è sufficiente collegare D10 (il nostro pin RX virtuale) all'OUT e D11 (il nostro TX virtuale) all'IN. Questo è mostrato in figura 5.

Figura 5 Schema per il collegamento di 1-6200-006 ad Arduino con RS-232 e la libreria SoftwareSerial

Utilizzando SoftwareSerial, è possibile inizializzare la porta seriale virtuale con il seguente codice:

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

Si noti che i dispositivi con porte seriali UART TTL (come Arduino) necessitano di una connessione seriale invertita, altrimenti non saranno in grado di comunicare. Con un Arduino, questo viene fatto con il terzo argomento quando si crea la porta seriale virtuale ("true" per un segnale invertito).

Per leggere l'inclinazione attraverso RS-232, prima inviare il comando per i dati desiderati, poi leggere i dati dalla porta. Il codice per leggere i valori dell'asse x, dell'asse y e della temperatura è riportato di seguito:

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.

La risposta di questo codice sarà un array di caratteri a 8 byte, terminato con caratteri di ritorno a capo e a capo (0x0a, 0x0d). Non sarà una stringa, quindi molto probabilmente dovrà essere convertita in una stringa. Se necessario, può anche essere convertita in un int.

// convertire l'array di caratteri in stringa
    x[b - 2] = '\0';

   // convertire la stringa in int a 16 bit
    xInt = atoi(x);

Il codice sopra riportato sostituisce il carattere newline con il carattere null, terminando la stringa immediatamente dopo l'ultimo carattere. Questo richiede l'utilizzo della variabile b, quindi probabilmente dovrà essere fatto immediatamente dopo aver ricevuto la misura. Per ottenere questo risultato senza usare la variabile b, il carattere di terminazione può anche essere posizionato alla fine della stringa, ma questo lascerà spazi e caratteri di tracciamento.

RS-485

RS-485 (TIA-485) è uno standard di comunicazione seriale che funziona bene su lunghe distanze e in ambienti elettricamente rumorosi. È disponibile sul condizionatore di segnale 1-6200-008. Arduino Uno non supporta l'RS-485 da solo, ma un convertitore può essere utilizzato per facilitare la comunicazione con uno qualsiasi dei nostri prodotti RS-485.

Sulla maggior parte dei convertitori RS-485, il DI (Data In) e RO (Receive Out) sono rispettivamente Rx e Tx. Il RE (Receive Enable) e il DE (Data Enable) controllano quando il convertitore invierà e riceverà i dati RS-485; questi possono essere generalmente collegati e commutati insieme (alto per inviare dati, basso per ricevere dati). Le connessioni A e B sul convertitore si collegano ad A e B sul condizionatore di segnale. Lo schema di questo circuito è mostrato in figura 6.

Figura 6 Schema per il collegamento di 1-6200-008 ad Arduino con RS-485. Convertitore RS-485 utilizzato come intermediario

I comandi RS-485 usati per comunicare con il condizionatore di segnale utilizzano il seguente formato:

*xxyy#

L'* è il carattere di inizio, che inizia ogni comando. xx è l'indirizzo a cui il comando viene inviato. Per impostazione predefinita, questo sarà 99 sul 1-6200-008. yy è il comando stesso. Il # segnala la fine del comando. Ad esempio, il comando per leggere l'inclinazione dell'asse x sull'indirizzo 99 è *9911#. Tutti i comandi disponibili si trovano sul datasheet 1-6200-008.

Con il convertitore da RS-232 a RS-485 in linea, questi comandi possono essere inviati al convertitore con RS-232. Il convertitore li invierà poi al condizionatore di segnale con RS-485. La funzione di setup sarà la stessa di quella del condizionatore di segnale RS-232. Il codice sottostante mostra come questa configurazione può essere usata per leggere i dati dal condizionatore di segnale:

// 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
    }

Come per RS-232, la risposta sarà un array di caratteri terminato da una nuova linea e ritorno a capo. Se si vuole trattare l'array come una stringa, si dovrà aggiungere il carattere nullo ('\0').

Indirizzato RS-485

E' possibile collegare fino a 32 condizionatori di segnale 1-6200-008 ad un singolo bus. Ai condizionatori di segnale possono poi essere assegnati indirizzi, fornendo un modo per ogni sensore di determinare se rispondere o meno. Si noti che è importante evitare di collegare più sensori con lo stesso indirizzo, poiché i sensori interferiranno con le reciproche trasmissioni.

Per impostazione predefinita, l'indirizzo del condizionatore di segnale sarà 99. Per cambiarlo, assicurarsi che sia l'unico dispositivo collegato con quell'indirizzo. Quindi, utilizzare il comando *xx81Azz#, dove xx è l'indirizzo corrente e zz è il nuovo indirizzo. Per esempio:

Sensor.print("*9981A01#"); // cambiare indirizzo da 99 a 01

Una volta cambiato l'indirizzo, non sarà più possibile accedere al sensore con comandi che iniziano con 99. Al contrario, il nuovo indirizzo 01 sostituirà il 99 in tutti i comandi. Ad esempio, il comando per leggere le informazioni sul prodotto cambierebbe da *9980# a *0180# dopo l'esecuzione del comando di cui sopra.

Una volta che ad ogni sensore è stato assegnato un indirizzo univoco, esso può essere collegato al circuito. Ogni condizionatore di segnale può collegarsi allo stesso bus senza componenti o collegamenti aggiuntivi. Vedere la figura 7 per uno schema che lo mostra.

Figura 7 Schema per il collegamento (4) 1-6200-008 dei condizionatori di segnale ad un Arduino con RS-485

Di seguito è riportato un esempio di lettura del programma da più sensori RS-485 indirizzati. Questo codice viene scritto per un circuito collegato a 4 sensori, indirizzati 8 - 11.

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
    }
}

Le risposte saranno array di caratteri a 8 byte contenenti i caratteri ASCII per un numero a 16 bit.