Práctica 9 con Miuva. Mod ACEL: Acelerómetro I2C con PIC C

[fusion_builder_container hundred_percent=”no” equal_height_columns=”no” menu_anchor=”” hide_on_mobile=”small-visibility,medium-visibility,large-visibility” class=”” id=”” background_color=”” background_image=”” background_position=”center center” background_repeat=”no-repeat” fade=”no” background_parallax=”none” parallax_speed=”0.3″ video_mp4=”” video_webm=”” video_ogv=”” video_url=”” video_aspect_ratio=”16:9″ video_loop=”yes” video_mute=”yes” overlay_color=”” overlay_opacity=”0.5″ video_preview_image=”” border_size=”” border_color=”” border_style=”solid” padding_top=”” padding_bottom=”” padding_left=”” padding_right=””][fusion_builder_row][fusion_builder_column type=”1_1″ layout=”1_1″ background_position=”left top” background_color=”” border_size=”” border_color=”” border_style=”solid” border_position=”all” spacing=”yes” background_image=”” background_repeat=”no-repeat” padding=”” margin_top=”0px” margin_bottom=”0px” class=”” id=”” animation_type=”” animation_speed=”0.3″ animation_direction=”left” hide_on_mobile=”small-visibility,medium-visibility,large-visibility” center_content=”no” last=”no” min_height=”” hover_type=”none” link=””][fusion_text]

En esta práctica aprenderemos a utilizar el protocolo I2C para obtener información de un acelerómetro y encender los leds de la barra de leds correspondientes a la inclinación del mismo.

Para usar este protocolo es necesario que definamos lo siguiente:

#use I2C(MASTER, SCL=PIN_A1, SDA=PIN_A2)  //Configuración del I2C

En la parte de configuración tenemos que definir en que pines estará conectado nuestro dispositivo, en este caso el pin SCL está en el pin A1 y el pin SDA en el A2.

Para poder comunicarnos con los dispositivos I2C haremos uso de las siguientes funciones:

i2c_start();       //Envía la condición de inicio
i2c_write(0x3A);   //Envía información
y = i2c_read(0);   //Recibe información y la almacena en y
i2c_stop();        //Envía la condición de paro

Los pasos necesarios para establecer comunicación por medio de este protocolo son los siguientes:

Envío de información

1. Enviar condición de inicio

2. Enviar dirección esclava de escritura

3. Enviar registro al que se va a escribir

4. Enviar el dato que se va a escribir

5. Enviar condición de paro

i2c_start();
i2c_write(DIR_ESCLAVO_W);
i2c_write(registro);
i2c_write(dato);
i2c_stop();

Recepción de información

1. Enviar condición de incio

2. Enviar dirección esclava de escritura

3. Registro que se va a leer

4. Condición de inicio

5. Enviar dirección esclava de lectura

6. Recibe información del registro

7. Condición de paro

i2c_start();
i2c_write(DIR_ESCLAVO_W);
i2c_write(registro);
i2c_start();
i2c_write(DIR_ESCLAVO_R);
y = i2c_read(0);
i2c_stop();

Es conveniente que definamos una función para escritura que realice todo el proceso para no repetir tantas líneas y lo mismo para la lectura. Quedando de la siguiente forma:

void escritura(unsigned int registro, unsigned int dato){
   i2c_start();
   i2c_write(DIR_ESCLAVO_W);
   i2c_write(registro);
   i2c_write(dato);
   i2c_stop();
}

int lectura(unsigned int registro){
   int y;
   i2c_start();
   i2c_write(DIR_ESCLAVO_W);
   i2c_write(registro);
   i2c_start();
   i2c_write(DIR_ESCLAVO_R);
   y = i2c_read(0);
   i2c_stop();
   return y;
}

De esta forma podremos crear otra función que sirva para inicializar el módulo del acelerómetro, enviando la información correspondiente a cada registro del mismo, de la siguiente forma:

void acel_init(){
//Inicialización del módulo del acelerómetro
   escritura_acel(0x0B, 0x01); 
   escritura_acel(0x2A, 0x20);
   escritura_acel(0x2B, 0x19);
   escritura_acel(0x2C, 0x02);
   escritura_acel(0x2D, 0x01);
   escritura_acel(0x2E, 0x01);
   escritura_acel(0x2A, 0x21);
}

En el datasheet del acelerómetro podemos encontrar por que se pusieron esos valores en los registros.

Para esta práctica vamos a estar leyendo continuamente el registro 0x03 el cual contiene el valor del eje y del acelerómetro, después de leer ese registro lo compararemos con valores entre -20 y 20 para definir cual led se tendrá que encender, según la siguiente imagen:

Imagen1. Intervalos de encendido de cada led

De esta forma podemos crear el siguiente código:

Código para PIC C:

#include<18f4550.h>
#fuses HSPLL, NOWDT, NOPROTECT, NOLVP, NODEBUG, USBDIV, PLL2, CPUDIV1, VREGEN
#use delay (clock=48M)
#use standard_io(b)
#use standard_io(c)
#use I2C(MASTER, SCL=PIN_A1, SDA=PIN_A2)  //Configuración del I2C

signed int eje_y = 0;

//Prototipo de funciones para iniciar, escribir y leer en el 
//Mod-Acel
void acel_init();
void escritura_acel(unsigned int registro, unsigned int dato);
int leer_y();

void main(){
   set_tris_b(0b00000000); //Configurar como salidas
   acel_init();            //Inicializar acelerómetro
   while(TRUE){

      if (input_state(PIN_A0)){
         eje_y = leer_y();    //Leer el valor del eje y
                              //Comparar los valores obtenidos del registro para
                              //encender los leds correspondientes a la 
                              //inclinación del acelerómetro
         if (eje_y < -20){
            output_b(0x01);
         }
         else if (eje_y < -15){
            output_b(0x02);
         }
         else if(eje_y < -10){
            output_b(0x04);
         }
         else if (eje_y < -5){   
         output_b(0x08);
         }
         else if (eje_y > 20){
            output_b(0x80);
         }
         else if (eje_y > 15){
            output_b(0x40);
         }
         else if (eje_y > 10){
            output_b(0x20);
         }
         else if (eje_y > 5){
            output_b(0x10);
         }
      }
         else{
            output_b(0xAA);
      }
   }

}

void acel_init(){
//Inicialización del módulo del acelerómetro
   escritura_acel(0x0B, 0x01); 
   escritura_acel(0x2A, 0x20);
   escritura_acel(0x2B, 0x19);
   escritura_acel(0x2C, 0x02);
   escritura_acel(0x2D, 0x01);
   escritura_acel(0x2E, 0x01);
   escritura_acel(0x2A, 0x21);
}

void escritura_acel(unsigned int registro, unsigned int dato){
   i2c_start();
   i2c_write(0x3A);
   i2c_write(registro);
   i2c_write(dato);
   i2c_stop();
}

int leer_y(){
   int y;
   i2c_start();
   i2c_write(0x3A);
   i2c_write(0x03);  //Registro del eje y del acelerómetro
   i2c_start();
   i2c_write(0x3B);
   y = i2c_read(0);
   i2c_stop();
   return y;
}

Conexiones

Observa el video demostrativo

Descarga el proyecto en PIC C o Mikro C

Menú