Librería MMA8452Q – Miuva

Descargar librería en español

Descargar librería en inglés

El módulo de acelerómetro de Intesc incluye un sensor MMA8452Q de 12 bits digital, el cual tiene diferentes funciones embebidas como la detección de orientación y la detección de pulsos.

Con esta librería se podrá hacer uso de algunas de las funciones principales del sensor.

Definición de pines

El primer paso es definir los pines donde estará conectado el sensor en nuestra tarjeta, para ello tendremos que editar el archivo MMA8452.h.

INT1_PIN: Pin donde estarán asociadas las interrupciones 1 de las diferentes funciones del sensor.

INT2_PIN: Pin donde estarán asociadas las interrupciones 2 de las diferentes funciones del sensor.

SCL_PIN: Pin de señal de reloj para comunicación I2C.

SDA_PIN: Pin de datos para comunicación I2C.

Definición de constantes

Será importante definir diferentes constantes dependiendo de las características con las que estemos trabajando.

DR_DEFAULT: Data Rate usado para las diferentes funciones embebidas. Este puede ser seleccionado entre:

  • DR_800: Para 800 Hz
  • DR_400: Para 400 Hz
  • DR_200: Para 200 Hz
  • DR_100: Para 100 Hz
  • DR_50: Para 50 Hz
  • DR_12_5: Para 12.5 Hz
  • DR_6_25: Para 6.25 Hz
  • DR_1_56: Para 1.56 Hz

En caso de utilizar la función de detección de pulsos, se tendrán que configurar los siguientes parámetros:

Rangos de valor de escala

  • X_G
  • Y_G
  • Z_G

Conteo para cada registro, esto es para lograr los tiempos adeucados para los registros de Time Limit, Latency y Window, estos conteos dependen de el DR seleccionado, el modo de trabajo con el que estemos operando (Normal, Baja potencia, Alta resolución o Bajo ruido Baja energía) y el filtro pasa bajas. La información de cada modo se puede encontrar en la hoja de datos del sensor, en el capítulo 6.5.

Por ejemplo, utilizando los valores por default de la librería (ODR = 800HZ, Modo normal, Filtro pasa bajas desactivado). Encontraremos en la sección correspondiente de la hoja de datos la siguiente información para Time Limit:

Imagen1. Tabla de configuración para PULSE_TMLT

Por lo tanto si queremos un tiempo de 60ms, tendremos [60ms] / [0.625ms] = 96

Para el caso de Latency y Window, tenemos la siguiente tabla:

Imagen2. Tabla de configuración PULSE_LTCY y PULSE_WIND

Por lo tanto si quieremos un tiempo de 200ms, tendremos [200ms] / [1.25ms] = 160

Funciones

Las funciones declaradas en librería son las siguientes:

Inicialización

void MMA8452_init(int32 mask)

Esta debe ser la primer función utilizada para poder obtener información del sensor, inicializa el mismo configurando los registros de control.

Parámetros de entrada:

  • int32 mask: Información para la configuración adecuada.

La variable mask contendrá toda la información necesaria para esta inicialización, los valores tendrán que estar separados por un “OR” ( | ) y estos pueden ser:

//Frecuencia de muestreo de Auto wake up cuando el dispositivo está dormido
#define  ASLP_RATE_50      0x00000000     // 50Hz
#define  ASLP_RATE_12_5    0x00000040     // 12.5 Hz
#define  ASLP_RATE_6_25    0x00000080     // 6.25 Hz
#define  ASLP_RATE_1_56    0x000000C0     // 1.56 Hz
//Seleccion de data rate
#define  DR_800            0x00000000     // 800 Hz
#define  DR_400            0x00000008     // 400 Hz
#define  DR_200            0x00000010     // 200 Hz
#define  DR_100            0x00000018     // 100 Hz
#define  DR_50             0x00000020     // 50 Hz
#define  DR_12_5           0x00000028     // 12.5 Hz
#define  DR_6_25           0x00000030     // 6.25 Hz
#define  DR_1_56           0x00000038     // 1.56 Hz

#define  NOISE_NORMAL      0x00000000     // Ruido normal
#define  NOISE_RED         0x00000004     // Ruido reducido

#define  NO_FAST_READ      0x00000000     // Modo normal
#define  FAST_READ         0x00000002     // Modo de lectura rápida

//Power mode
#define  NORMAL_MODE       0x00000000     // Normal
#define  LOW_NOISEPOWER    0x00000100     // Bajo ruido baja energía
#define  HIGH_RES          0x00000200     // Alta resolución
#define  LOW_POWER         0x00000300     // Baja potencia

#define  NO_AUTOSLEEP      0x00000000     // Autosleep no habilitado
#define  AUTOSLEEP         0x00000400     // Autosleep habilitado

#define  SW_RST            0x00000800     // Reset por software habilitado
#define  NO_SWR            0x00000000     // Reset por software no habilitado

#define  SELFTEST          0x00001000     // Self test habilitado
#define  NO_SELFTEST       0x00000000     // Self test deshabilitado

#define  PUSH_PULL         0x00000000     // Push pull
#define  OPEN_DRAIN        0x00002000     // Open drain

//Polaridad en la señal de interrupción
#define  IPOL_LOW          0x00000000     // Activa bajo
#define  IPOL_HIGH         0x00004000     // Activa alto

//Funciones que pueden despertar al sistema o no en modo DORMIDO
#define  WAKE_FFMT         0x00008000     // Caída libre / Movimiento
#define  WAKE_FFMT_OFF     0x00000000     // Caída libre / Movimiento apagado
#define  WAKE_PULSE        0x00010000     // Pulso
#define  WAKE_PULSE_OFF    0x00000000     // Pulso apagado
#define  WAKE_LNDPRT       0x00020000     // Paisaje / Portaretrato
#define  WAKE_LNDPRT_OFF   0x00000000     // Paisaje / Portaretrato apagado
#define  WAKE_TRANS        0x00080000     // Transient
#define  WAKE_TRANS_OFF    0x00000000     // Transient apagado

#define  INT1_DATAREADY    0x04100000     // Interrupción de DATOS LISTOS conectada a INT1 
#define  INT2_DATAREADY    0x00100000     // Interrupción de DATOS LISTOS conectada a INT2 
#define  INT1_FFMT         0x08200000     // Interrupción de Caída libre / Movimiento conectada a INT1
#define  INT2_FFMT         0x00200000     // Interrupción de Caída libre / Movimiento conectada a INT2
#define  INT1_PULSE        0x10400000     // Interrupción de pulso conectada a INT1
#define  INT2_PULSE        0x00400000     // Interrupción de pulso conectada a INT1
#define  INT1_LNDPRT       0x20800000     // Interrupción de Paisaje / Portaretrato conectada a INT1
#define  INT2_LNDPRT       0x00800000     // Interrupción de Paisaje / Portaretrato conectada a INT2
#define  INT1_TRANS        0x41000000     // Interrupción de Transient conectada a INT1
#define  INT2_TRANS        0x01000000     // Interrupción de Transient conectada a INT2
#define  INT1_ASLP         0x82000000     // Interrupción Auto dormir/despertar conectada a INT1
#define  INT2_ASLP         0x02000000     // Interrupción Auto dormir/despertar conectada a INT2

Los valores por defecto son los siguientes:

  • ASLP Rate: 50 Hz
  • ODR: 800 Hz
  • Ruido: Normal
  • Lectura rápida desactivada
  • Modo Normal
  • Sin Autosleep
  • Sin reset por software
  • Auto prueba deshabilitada
  • Push Pull
  • Polaridad de las interrupciones en bajo
  • Sin interrupciones

Parámetros de salida:

  • Sin parámetros

Ejemplo de uso:

MMA8452_init(IPOL_HIGH|INT1_DATAREADY|INT2_LNDPRT|INT2_PULSE);
     //Polaridad de las interrupciones en alto
     //Interrupciones por datos listos en INT1
     //Interrupciones por cambio de orientación (Landscape/Portrait) en INT2
     //Interrupciones por pulso en INT2
Registros

Existe una función para leer y otra para escribir en los registros del sensor directamente, esto se puede utilizar en caso de que se requiera alguna configuración diferente a la de la librería, entonces podrás escribir mediante I2C en cualquier registro del sensor.

void writeReg(unsigned int reg, unsigned int data)

Escribe información en un registro.

Parámetros de entrada:

  • unsigned int reg: Registro en el que se escribe
  • unsigned int data: Información que se escribe en el registro indicado

Parámetros de salida

  • Sin parámetros

Ejemplo de uso:

// Colocar en modo standby
temp = readReg(0x2A);          //Almaceno el valor del registro de control 1
writeReg(0x2A, temp & 0xFE);   //Descativo el bit 0 del registro de control 1

int readReg(unsigned int reg)

Lee información de un registro.

Parámetros de entrada:

  • int reg: Registro que se va a leer

Parámetros de salida:

  • int: Valor del registro leído

Ejemplo de uso:

xh =  readReg(0x01);     //Leo la parte más significativo del Eje X
¿Conectado?

Con esta función podremos saber si el sensor se encuentra conectado y se pudo establecer comunicación entre él y nuestra tarjeta, o si por otro lado, está desconectado o no fue posible realizar esta comunicación.

int MMA8452_is_connected()

Lee la información del registro Who Am I, y la compara con la información que se tendría que haber recibido.

Parámetros de entrada:

  • Sin parámetros

Parámetros de salida:

  • int: Información sobre el estado del sensor, esta puede ser:
    • MMA8452_CONNECTED = 1
    • MMA8452_NOT_CONNECTED = 0

Ejemplo de uso:

if (MMA8452_is_connected() == MMA8452_CONNECTED){
     printf(lcd_putc, "\fCONNECTED");
}
else{
     printf(lcd_putc, "\fNOT CONNECTED);
}
EJE X / EJE-Y / EJE-Z

Podremos configurar cada uno de los ejes así como obtener la información del valor de la posición de cada uno.

void MMA8452_xyz_conf(int mask)

Con esta función se configura el rango de escala y el filtro pasa altas.

Parámetros de entrada:

  • int mask: Información necesaria para la configuración.

La variable mask contendrá toda la información necesaria para esta inicialización, los valores tendrán que estar separados por un “OR” ( | ) y estos pueden ser:

#define  HIGH_PASS_ON      0b00010000     //Activar pasa altas en datos de salida
#define  HIGH_PASS_OFF     0b00000000     //Filtrar los datos de salida
//Rangos de valores de escala
#define  SET_2G            0b00000000     //2g
#define  SET_4G            0b00000001     //4g
#define  SET_8G            0b00000010     //8g

Los valores por defecto son:

  • Filtro passa altas desactivado
  • Seleccionado 2G

Parámetros de salida:

  • Sin parámetros

Ejemplo de uso:

MMA8452_xyz_conf(HIGH_PASS_OFF|SET_4G);
     //Activa el filtro pasa altas
     //Selecciona 4g

signed long int MMA8452_x_read()
signed long int MMA8452_y_read()
signed long int MMA8452_z_read()

Recibe la información del valor de cada posición de los ejes.

Parámetros de entrada:

  • Sin parámetros

Parámetros de salida:

  • signed long int: Valor del eje correspondiente

Ejemplo de uso:

ejex = MMA8452_x_read();   // Leemos el eje X
ejey = MMA8452_y_read();   // Leemos el eje Y
ejez = MMA8452_z_read();   // Leemos el eje Z
printf(lcd_putc, "\fX=%4ld", ejex);
lcd_gotoxy(1,2);
printf(lcd_putc, "Y=%4ld Z=%4ld", ejey,ejez);
Orientación

Con estas funciones podremos obtener información de la orientación del sensor, esta puede ser en modo portaretrato o en modo paisaje, así como saber si está boca arriba o boca abajo.

void MMA8452_enPortLand()

Esta función debe ser utilizada para activar la detección de orientación.

Parámetros de entrada:

  • Sin parámetros

Parámetros de salida:

  • Sin parámetros

Ejemplo de uso:

MMA8452_enPortLand(); //Activa detección de orientación

int MMA8452_newOrientation()

Esta función nos hará saber si la orientación cambió o se ha mantenido igual.

Parámetros de entrada:

  • Sin parámetros

Parámetros de salida:

  • int: Información sobre si cambió o no:
    • MMA8452_ORIEN_CHANGED = 1
    • MMA8452_ORIEN_NOT_CHANGED = 0

Ejemplo de uso:

if (MMA8452_newOrientation() == MMA8452_ORIEN_CHANGED){
     printf(lcd_putc, "New Orientation");
}
else{
     printf(lcd_putc, "No New Orient");
}

int MMA8452_LaPo() 

Nos indica la orientación actual.

Parámetros de entrada:

  • Sin parámetros

Parámetros de salida:

  • int: Devuelve información de la orientación.
    • MMA8452_PORTRAIT_UP = 0
    • MMA8452_PORTRAIT_DOWN = 1
    • MMA8452_LANDSCAPE_RIGHT = 2
    • MMA8452_LANDSCAPE_LEFT = 3

Ejemplo de uso:

lapo = MMA8452_LaPo();     // ¿Portland o Landscape?
if (lapo == MMA8452_PORTRAIT_UP){
   printf(lcd_putc, "\fPortrait Up");
}
else if (lapo == MMA8452_PORTRAIT_DOWN){
   printf(lcd_putc, "\fPortrait Down");
}
else if (lapo == MMA8452_LANDSCAPE_RIGHT){
   printf(lcd_putc, "\fLandscape Right");
}
else{
   printf(lcd_putc, "\fLandscape Left");
}

int MMA8452_BaFro()

Nos indica la orientación entre arriba o abajo.

Parámetros de entrada:

  • Sin parámetros

Parámetros de salida:

  • int: Información de la orientación.
    • MMA8452_FRONT_FACE = 0
    • MMA8452_BACK_FACE = 1

Ejemplo de uso:

bafro = MMA8452_BaFro();   // ¿Back o Front?
if (bafro == MMA8452_FRONT_FACE){
   printf(lcd_putc, "\nFront");
}
else{
   printf(lcd_putc, "\nBack");
}
Detección de pulsos

Podremos saber si nuestro sensor ha detectado un pulso sencillo o un pulso doble. Es importante ajustar los valores de los conteos en la sección de constantes para hacer que coincidan con la configuración de la tarjeta.

void MMA8452_enTapDet(int mask)

Es necesario habilitar primero la detección de los pulsos e indicar la configuración de la misma.

Parámetros de entrada:

  • int mask: Información de la configuración.

La variable mask contendrá toda la información necesaria para esta inicialización, puede ser:

//Detección de pulso
#define  SINGLE_TAP        0b00000000     //Detección sencilla activada
#define  DOUBLE_TAP        0b00000001     //Detección doble activada
#define  SINGLE_DOUBLE     0b00000010     //Detección sencilla y doble activada

Parámetros de salida:

  • Sin parámetros

Ejemplo de uso:

MMA8452_enTapDet(SINGLE_DOUBLE);    //Habilitamos la detección de pulsos

int MMA8452_getTap()

Nos dará información de el tipo de pulso recibido.

Parámetros de entrada:

  • Sin parámetros

Parámetros de salida:

  • int: Información sobre el pulso recibido.
    • MMA8452_NO_PULSE = 0
    • MMA8452_DOUBLE_PULSE = 1
    • MMA8452_SINGLE_PULSE = 2

Ejemplo de uso:

pulso = MMA8452_getTap();     // Verificamos si fue sencillo o doble
if (pulso == MMA8452_DOUBLE_PULSE){           // Si fue doble
   output_toggle(PIN_E2);  // Encendemos un led
}  
else if (pulso == MMA8452_SINGLE_PULSE){      // Si fue sencillo
   output_toggle(PIN_E1);  // Encendemos un led
}

Código de ejemplo

El siguiente código hace uso de la librería del sensor para leer la información de los 3 ejex y mostrarla en una LCD, al presionar el pulsador ubicado en el pin C0 se cambiará la información de la LCD por la información de la orientación del sensor. Y alternaremos el valor de dos leds cada que se reciban pulsaciones pudiendo ser sencillas par aun led o dobles para el otro.

#include<18f4550.h>
#fuses HSPLL, NOWDT, NOPROTECT, NOLVP, NODEBUG, USBDIV, PLL2, CPUDIV1, VREGEN
#use delay (clock=48M)
#include <MLCD.c>
#include "MMA8452Q.c"
#use  standard_io(e)
#use  standard_io(c)

void main(){
//Definición de variables
   signed long int ejex = 0, ejey = 0, ejez = 0;
   int   lapo = 0, bafro = 0;
   int   pulso = 0;
   int   pantalla = 0;

   set_tris_c(0xFF); //Habilitamos el puerto C como entrada
   set_tris_e(0x00); //Habilitamos el puerto E como salida 
   output_e(0x07);   //Apagamos el led RGB
   lcd_init(); //Inicializamos la LCD
   MMA8452_init(IPOL_HIGH|INT1_DATAREADY|INT2_LNDPRT|INT2_PULSE); //Inicializamos el sensor
   MMA8452_enPortLand();   // Habilitamos la detección de orientación
   MMA8452_enTapDet(SINGLE_DOUBLE);    //Habilitamos la detección de pulsos
   
   while(TRUE){
//Detección de pulsador para modificar la información de la pantalla
      if (input_state(PIN_C0)){     // ¿Se presionó el pulsador?
         delay_ms(200);
         pantalla++;                // Aumentamos el valor de pantalla
         if (pantalla >= 2){        // Si pantalla es mayor o igual a 2
            pantalla = 0;           // la reiniciamos a 0
         }
      }

//LECTURA DE LOS 3 EJES
      if (input_state(INT1_PIN)){   // ¿Hubo interrupción del PIN 1 del sensor?
         ejex = MMA8452_x_read();   // Leemos el eje X
         ejey = MMA8452_y_read();   // Leemos el eje Y
         ejez = MMA8452_z_read();   // Leemos el eje Z
      }

// TAP DETECTION
      if (input_state(INT2_PIN)){   // ¿Hubo interrupción del PIN 2 del sensor?
      pulso = MMA8452_getTap();     // Verificamos si fue sencillo o doble
         if (pulso == MMA8452_DOUBLE_PULSE){           // Si fue doble
            output_toggle(PIN_E2);  // Encendemos el led AZUL
         }  
         else if (pulso == MMA8452_SINGLE_PULSE){      // Si fue sencillo
            output_toggle(PIN_E1);  // Encendemos el led ROJO 
         }      
      }
// LECTURA DE LA ORIENTACION      
      if (input_state(INT2_PIN)){   // ¿Hubo interrupción del PIN 2 del sensor?
         lapo = MMA8452_LaPo();     // ¿Portland o Landscape?
         bafro = MMA8452_BaFro();   // ¿Back o Front?
      }
      
// MOSTRAMOS LA INFORMACIÓN EN LA LCD
      if (pantalla == 0){
         printf(lcd_putc, "\fX=%4ld", ejex);
         lcd_gotoxy(1,2);
         printf(lcd_putc, "Y=%4ld Z=%4ld", ejey,ejez);
         delay_ms(200);
      }
      else{  
         if (lapo == MMA8452_PORTRAIT_UP){
            printf(lcd_putc, "\fPortrait Up");
         }
         else if (lapo == MMA8452_PORTRAIT_DOWN){
            printf(lcd_putc, "\fPortrait Down");
         }
         else if (lapo == MMA8452_LANDSCAPE_RIGHT){
            printf(lcd_putc, "\fLandscape Right");
         }
         else{
            printf(lcd_putc, "\fLandscape Left");
         }
         if (bafro == MMA8452_FRONT_FACE){
            printf(lcd_putc, "\nFront");
         }
         else{
            printf(lcd_putc, "\nBack");
         }
         delay_ms(200);
      }
   }
}

 

Menú