AN 1006: Obtención de medidas de los acondicionadores de señal TFC

Descripción

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.

Análogo

Both the 1-6200-007 y 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 Esquema para conectar el 1-6200-007 a Arduino utilizando el sistema analógico

Tenga en cuenta que el acondicionador de señal 1-6200-012 no tiene una salida analógica de temperatura, por lo que la temperatura debe ser leída usando RS-232. Consulte la sección sobre RS-232 para obtener más información sobre la lectura de la temperatura del 1-6200-012.

Con el circuito montado los datos pueden ser leídos usando la función analogRead() de Arduino. A continuación se muestra un ejemplo de esto:

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

El resultado de este código será un valor crudo que representa el voltaje en los pines analógicos. La resolución de esta medida dependerá del hardware utilizado para leer el voltaje; en un Arduino Uno, los pines analógicos tienen una resolución de 10 bits.

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 Esquema para conectar el 1-6200-007 a Arduino usando PWM

Tengan en cuenta que las salidas PWM se pueden conectar a cualquier pin digital del Arduino, no sólo a los pines PWM. En este ejemplo, se utilizan los pines D7 y D8, ambos pines no PWM.

La lectura de una señal PWM con un Arduino se hace mejor con la función pulseIn(). La función pulseIn() cronometrará cuánto tiempo dura un pulso en el estado alto o bajo. En este caso, cronometramos el estado alto.

x = pulseIn(XPIN, ALTA);
y = pulseIn(YPIN, ALTA);
temperatura = analog Read(A0);

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

El resultado será la duración del pulso en microsegundos. La función pulseIn() puede leer pulsos tan cortos como 10 µs, lo que significa que su medición del pulso de hasta 8ms tendrá una precisión similar a una salida de 10 bits. Esta precisión será mayor si el dispositivo que lee puede detectar pulsos más pequeños.

SPI

SPI es un protocolo de comunicación serial sincrónico disponible en el acondicionador de señales 1-6200-005. El protocolo funciona en una técnica maestro/esclavo usando 4 conexiones: MISO (Master In Slave Out), MOSI (Master Out Slave In), CLK (Serial Clock), y SS (Slave Select). El maestro enviará comandos al esclavo a través de MOSI (etiquetada IN en el 1-6200-005), y el esclavo responderá a través de MISO (etiquetada OUT en el 1-6200-005). CLK es un reloj creado por el maestro que sincroniza la comunicación del esclavo. SS se utiliza para habilitar un esclavo; este pin es la forma en que SPI soporta múltiples dispositivos en un bus (ver la sección "SPI Bus" para más información).

El Arduino Uno tiene pines predefinidos para el MOSI, MISO, y CL. Estos se muestran en la siguiente tabla:

MOSI D11
MISO D12
CLK D13

El esquema para conectarlas al Arduino se muestra en la figura 3. Wiring Schematic for the 1-6200-005 SPI signal conditioners with an Arduino Uno

Figura 3 Esquema para conectar el 1-6200-005 a Arduino con SPI

Para comunicarnos con el sensor, usaremos la biblioteca SPI de Arduino. SPI.begin() inicializará la biblioteca SPI (sin embargo no abrirá las comunicaciones). Como este circuito sólo tiene un dispositivo SPI, el pin 10 (SS) se pondrá en LOW, habilitando al esclavo controlado por ese pin. Esto permanecerá en LOW durante todo el programa; no hay razón para desactivar el esclavo en este circuito.

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

Ahora que hemos inicializado la biblioteca, debemos abrir la conexión con el acondicionador de señales. Esto se hace usando la función SPI.beginTransaction(). Esta función toma un argumento, un objeto SPISettings. Este objeto proporcionará toda la información necesaria para crear la conexión. El objeto SPISettings tiene tres argumentos:

  1. Máxima velocidad de reloj del esclavo, que es de 20Mhz en el 1-6200-005.
  2. El segundo argumento determina si la interfaz SPI utilizará primero el bit más significativo o el menos significativo. Para el 1-6200-005 este es el bit más significativo primero (o MSBFIRST).
  3. El tercer argumento determina el modo SPI; para el 1-6200-005, se utiliza el modo SPI 2 (CPOL=1, CPHA=0).
// comunicación abierta del SPI
SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE2));

La función SPI.transfer() se utiliza para enviar y recibir datos. Enviará simultáneamente el comando y devolverá lo que sea que lea del pin MISO. Tenga en cuenta que el esclavo siempre tardará un ciclo de reloj en responder; por lo tanto, el resultado de cada comando no se recibirá hasta el siguiente ciclo. Por ejemplo, en el siguiente código, la función que envía la solicitud de byte bajo del eje X devuelve el valor de byte alto del eje X debido a este retraso.

Tenga en cuenta que el comando 0x39 es esencial para obtener buenas mediciones. Este comando le dice al tablero que obtenga una nueva medida de la inclinación. Se envía una vez al principio y otra vez al final de la declaración if, donde se recibe el bit de baja 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.

Bus SPI

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 Esquema para conectar dos 1-6200-005's a Arduino con un bus SPI. Observe las conexiones /SS separadas para cada dispositivo

Este código es muy similar al código para el dispositivo SPI único; observe que los pines SS se cambian para controlar con qué esclavo se comunica.

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

Tenga en cuenta que si se activan 2 esclavos SPI al mismo tiempo y se envía un mensaje, las señales interferirán y la respuesta no se leerá correctamente.

RS-232

RS-232 (TIA-232) es un protocolo de comunicación en serie común. Una versión de 3 cables de RS-232 está disponible en los acondicionadores de señal 1-6200-006 y 1-6200-012. La conexión de RS-232 consiste en conectar las tierras juntas, y conectar cada Rx al Tx del otro dispositivo.

En esta aplicación, usaremos la biblioteca SoftwareSerial de Arduino para crear un puerto serie virtual para usar. Esta biblioteca nos da la capacidad de invertir las señales del puerto, lo que es necesario para comunicarse con el sensor. También mantiene el puerto serie del hardware disponible para otros usos. Para crear el circuito para RS-232, simplemente conecte D10 (nuestro pin RX virtual) a OUT y D11 (nuestro TX virtual) a IN. Esto se muestra en la figura 5.

Figura 5 Esquema para conectar el 1-6200-006 a Arduino con RS-232 y la biblioteca SoftwareSerial

Usando SoftwareSerial, puedes inicializar el puerto serie virtual con el siguiente código:

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

Tenga en cuenta que los dispositivos con puertos serie UART TTL (como el Arduino) necesitan una conexión serie invertida, o no será capaz de comunicarse. Con un Arduino, esto se hace con el tercer argumento cuando se crea el puerto serie virtual ("true" para una señal invertida).

Para leer la inclinación a través de RS-232, primero, envía el comando para los datos que quieras, luego lee los datos del puerto. El código para leer el eje x, el eje y y los valores de temperatura está abajo:

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 respuesta de este código será una matriz de caracteres de 8 bytes, terminada por caracteres de nueva línea y de retorno de carro (0x0a, 0x0d). Esto no será una cadena, por lo que lo más probable es que tenga que ser convertido en una cadena. Si es necesario, también puede ser convertido en un int.

// convertir la matriz de caracteres en cadena
    x[b - 2] = '\0';

   // convertir la cadena a 16-bit int
    xInt = atoi(x);

El código anterior sustituye el carácter de nueva línea por el carácter nulo, terminando la cadena inmediatamente después del último carácter. Para ello es necesario utilizar la variable b, por lo que es probable que tenga que hacerse inmediatamente después de recibir la medición. Para lograrlo sin utilizar la variable b, el carácter de terminación también puede colocarse al final de la matriz, pero esto dejará espacios y caracteres de arrastre.

RS-485

RS-485 (TIA-485) es un estándar de comunicación en serie que funciona bien en largas distancias y en ambientes eléctricamente ruidosos. Está disponible en el acondicionador de señal 1-6200-008. El Arduino Uno no es compatible con RS-485 por sí solo, pero se puede utilizar un convertidor para facilitar la comunicación con cualquiera de nuestros productos RS-485.

En la mayoría de los convertidores RS-485, la DI (Entrada de datos) y la RO (Recepción de salida) son la Rx y la Tx respectivamente. El RE (Recepción de entrada) y el DE (Recepción de datos) controlan cuándo el convertidor enviará y recibirá datos RS-485; generalmente pueden conectarse y conmutarse juntos (alto para enviar datos, bajo para recibir datos). Las conexiones A y B del convertidor se conectan a A y B en el acondicionador de señales. El esquema de este circuito se muestra en la figura 6.

Figura 6 Esquema para conectar el 1-6200-008 a Arduino con RS-485. El convertidor RS-485 usado como intermediario

Los comandos RS-485 utilizados para comunicarse con el acondicionador de señal utilizan el siguiente formato:

*xxyy#

El * es el carácter de inicio, que inicia cada comando. xx es la dirección a la que se envía el comando. Por defecto, esta será 99 en el 1-6200-008. yy es el comando en sí. El # señala el final del comando. Por ejemplo, el comando para leer la inclinación del eje x en la dirección 99 es *9911#. Todos los comandos disponibles se pueden encontrar en la hoja de datos del 1-6200-008.

Con el convertidor de RS-232 a RS-485 en línea, estos comandos pueden ser enviados al convertidor con RS-232. El convertidor los enviará entonces al acondicionador de señales con RS-485. La función de configuración será la misma que la del acondicionador de señal RS-232. El código que aparece a continuación muestra cómo se puede usar esta configuración para leer los datos del acondicionador de señales:

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

Como en el RS-232, la respuesta será una matriz de caracteres terminada por una nueva línea y retorno de carro. Si quieres tratar la matriz como una cadena, tendrás que añadir el carácter nulo ('\0').

Dirigido a RS-485

Es posible conectar hasta 32 1-6200-008 acondicionadores de señal a un solo bus. A los acondicionadores de señal se les pueden asignar direcciones, lo que permite a cada sensor determinar si debe responder. Tenga en cuenta que es importante evitar la conexión de múltiples sensores con la misma dirección, ya que los sensores interferirán con las transmisiones de los demás.

Por defecto, la dirección del acondicionador de señal será 99. Para cambiarlo, asegúrese de que es el único dispositivo conectado con esa dirección. Luego, use el comando *xx81Azz#, donde xx es la dirección actual y zz es la nueva dirección. Por ejemplo:

Sensor.print("*9981A01#"); // cambiar la dirección de 99 a 01

Una vez cambiada la dirección, ya no podrá acceder al sensor con los comandos que empiezan por 99. En su lugar, la nueva dirección 01 reemplazará a la 99 en todos los comandos. Por ejemplo, el comando para leer la información del producto cambiaría de *9980# a *0180# después de ejecutar el comando anterior.

Una vez que a cada sensor se le ha asignado una dirección única, se pueden conectar al circuito. Cada acondicionador de señal puede conectarse al mismo bus sin componentes o conexiones adicionales. Véase la figura 7 para un esquema que muestra esto.

Figura 7 Esquema para conectar (4) 1-6200-008 acondicionadores de señal a un Arduino con RS-485

A continuación se muestra un ejemplo de un programa de lectura de múltiples sensores RS-485 dirigidos. Este código está escrito para un circuito conectado a 4 sensores, con dirección 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
    }
}

Las respuestas serán matrices de caracteres de 8 bytes que contienen los caracteres ASCII para un número de 16 bits.