Descripción
Esta Nota de Aplicación explica cómo obtener medidas de inclinación a partir de un sensor de inclinación electrolítico y un acondicionador de señal. Cubre esquemas y código para cada protocolo disponible en los acondicionadores de señal de The Fredericks Company. Todos los ejemplos mostrarán código y circuitos con un Arduino Uno, por lo que habrá diferencias en el código cuando se utilicen otras plataformas. Cada ejemplo proporcionará una salida en bruto del sensor en una variedad de unidades. Cualquiera de estas unidades puede ser convertida a grados utilizando los métodos explicados en la Nota de Aplicación 1005.
Análogo
Tanto el 1-6200-007 y 1-6200-012 Los acondicionadores de señal tienen salidas analógicas. En el 1-6200-007, ambos ejes y la temperatura se emiten desde los pines XA, YA y T respectivamente. La conexión al Arduino requiere conexiones directas desde el acondicionador de señal a los pines de entrada analógica del Arduino.
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
Las mediciones PWM están disponibles en el 1-6200-007 acondicionador de señal. Con PWM, los ángulos de inclinación x e y se pueden leer desde los pines digitales XP e YP en el acondicionador de señal. No hay salida PWM de temperatura, por lo que tendrá que ser leído desde el pin analógico. Un esquema para esta configuración se muestra en la figura 2.
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.
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:
- Máxima velocidad de reloj del esclavo, que es de 20Mhz en el 1-6200-005.
- 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).
- 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
También es posible conectar 1-6200-005 acondicionadores de señal juntos en un bus SPI. Un bus SPI permite a todos los dispositivos SPI compartir las conexiones CLK, MISO y MOSI. Cada esclavo, sin embargo, obtiene su propia conexión SS, permitiendo al maestro seleccionar con qué esclavo quiere comunicarse. El número de dispositivos SPI que puedes utilizar a la vez está limitado por el número de conexiones SS independientes que puedes hacer. La Figura 4 muestra el esquema para 2 sensores en un bus SPI con los pines D9 y D10 usados como señales SS.
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(); }
Las definiciones de todos los comandos RS-232 están disponibles en la hoja de datos del acondicionador de señal.
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.