Autor Tema: JM60 y Sensor capacitivo MPR121 por I2C..  (Leído 8526 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado LABmouse

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3575
    • Juntos es mejor
JM60 y Sensor capacitivo MPR121 por I2C..
« en: 23 de Noviembre de 2010, 21:09:58 »
Hola,

Bueno pues ya teniendo listo el I2C para la EEPROM, decido enfrentarme a un reto mayor y es el sensor capacitivo MPR121


Features
• 1.71 V to 3.6 V operation
• 29 μA supply current with 12 electrodes being monitored with 64 ms response time and IRQ enabled
• 3 μA shutdown current
• 12 electrodes
• Continuous independent auto-calibration for each electrode input
• Separate touch and release trip thresholds for each electrode, providing hysteresis and electrode independence
• I2C interface, with optional IRQ output to advise electrode status changes
• 3 mm x 3 mm x 0.65 mm 20 lead QFN package
• LED driver functionality with maximum of 8 LEDs
• -40°C to +85°C operating temperature range



El primer reto para trabajar con el es el tamaño del chip... :shock:


Un QFN (El mas pequeño que he logrado soldar a la fecha)..

Al cual le diseñe y fabrique un pequeño PCB de prueba con los 12 electrodos...




Ahora vienen la programación para el JM60, y quedo así:

Código: C
  1. void mpr121Write(UINT8 direccion, UINT8 dato){
  2.   i2c_start();                      //Genera señal de Start
  3.   i2c_write(MPR121_W);              //Envia apuntador de dispositivo I2C
  4.   i2c_write(direccion);             //Envia direccion LSB
  5.   i2c_write(dato);                  //Envia dato a escribir
  6.   i2c_stop();                       //Genera señal de Stop
  7. }


Código: C
  1. UINT8 mpr121Read(UINT8 direccion){
  2.         char dato;
  3.         i2c_start();                      //Genera señal de Start
  4.   i2c_write(MPR121_W);              //Envia dato por bus I2C    
  5.         i2c_write(direccion);               //Envia direccion de registro a leer
  6.   i2c_restart();                    //Genera señal de Restart
  7.   i2c_write(MPR121_R);              //Envia apuntador de dispositivo I2C
  8.   dato=i2c_read(0);                 //Toma dato de la memoria
  9.   i2c_stop();                       //Genera señal de STOP
  10.   return(dato);
  11. }

Código: C
  1. void mpr121QuickConfig(void)
  2. {
  3.         // Section A
  4.         // This group controls filtering when data is > baseline.
  5.         mpr121Write(MHD_R, 0x01);
  6.         mpr121Write(NHD_R, 0x01);
  7.         mpr121Write(NCL_R, 0x00);
  8.         mpr121Write(FDL_R, 0x00);
  9.        
  10.         // Section B
  11.         // This group controls filtering when data is < baseline.
  12.         mpr121Write(MHD_F, 0x01);
  13.         mpr121Write(NHD_F, 0x01);
  14.         mpr121Write(NCL_F, 0xFF);
  15.         mpr121Write(FDL_F, 0x02);
  16.        
  17.         // Section C
  18.         // This group sets touch and release thresholds for each electrode
  19.         mpr121Write(ELE0_T, TOU_THRESH);
  20.         mpr121Write(ELE0_R, REL_THRESH);
  21.         mpr121Write(ELE1_T, TOU_THRESH);
  22.         mpr121Write(ELE1_R, REL_THRESH);
  23.         mpr121Write(ELE2_T, TOU_THRESH);
  24.         mpr121Write(ELE2_R, REL_THRESH);
  25.         mpr121Write(ELE3_T, TOU_THRESH);
  26.         mpr121Write(ELE3_R, REL_THRESH);
  27.         mpr121Write(ELE4_T, TOU_THRESH);
  28.         mpr121Write(ELE4_R, REL_THRESH);
  29.         mpr121Write(ELE5_T, TOU_THRESH);
  30.         mpr121Write(ELE5_R, REL_THRESH);
  31.         mpr121Write(ELE6_T, TOU_THRESH);
  32.         mpr121Write(ELE6_R, REL_THRESH);
  33.         mpr121Write(ELE7_T, TOU_THRESH);
  34.         mpr121Write(ELE7_R, REL_THRESH);
  35.         mpr121Write(ELE8_T, TOU_THRESH);
  36.         mpr121Write(ELE8_R, REL_THRESH);
  37.         mpr121Write(ELE9_T, TOU_THRESH);
  38.         mpr121Write(ELE9_R, REL_THRESH);
  39.         mpr121Write(ELE10_T, TOU_THRESH);
  40.         mpr121Write(ELE10_R, REL_THRESH);
  41.         mpr121Write(ELE11_T, TOU_THRESH);
  42.         mpr121Write(ELE11_R, REL_THRESH);
  43.        
  44.         // Section D
  45.         // Set the Filter Configuration
  46.         // Set ESI2
  47.         mpr121Write(FIL_CFG, 0x04);
  48.        
  49.         // Section E
  50.         // Electrode Configuration
  51.         // Enable 6 Electrodes and set to run mode
  52.         // Set ELE_CFG to 0x00 to return to standby mode
  53.         mpr121Write(ELE_CFG, 0x0C);     // Enables all 12 Electrodes
  54.         //mpr121Write(ELE_CFG, 0x06);           // Enable first 6 electrodes
  55.        
  56.         // Section F
  57.         // Enable Auto Config and auto Reconfig
  58.         /*mpr121Write(ATO_CFG0, 0x0B);
  59.         mpr121Write(ATO_CFGU, 0xC9);    // USL = (Vdd-0.7)/vdd*256 = 0xC9 @3.3V
  60.         mpr121Write(ATO_CFGL, 0x82);    // LSL = 0.65*USL = 0x82 @3.3V
  61.         mpr121Write(ATO_CFGT, 0xB5);*/  // Target = 0.9*USL = 0xB5 @3.3V
  62. }


Esas funciones fueron portadas de un ejemplo que hay en internet para el arduino por: Jim Lindblom.



Ahora bien, después de intentar 10 veces, siempre se queda colgado el I2C al intentar escribir algo en el MPR121. Se me ocurre que se debe a que no llega nunca el ACK del sensor.

Investigando en internet, tenemos que al parecer hay una confusión con la dirección del MPR121 en el Bus I2C, en el datasheet hablan de 0x4D pero según muchos esta mal y la real es 0x5A. Pero!!!! A mi no me funciona ninguna de las 2.

Foro de Freescale

En el Bus I2C tengo la EEPROm y el MPR121 y la EEPROM contesta bien y se deja leer bien, lo que quita duda sobre el I2C desde el micro. Me queda seguir intentando.

Si tienen alguna recomendación, estaría muy agradecido por ello.

Saludos!


« Última modificación: 23 de Noviembre de 2010, 21:15:13 por LABmouse »

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: JM60 y Sensor capacitivo MPR121 por I2C..
« Respuesta #1 en: 23 de Noviembre de 2010, 21:58:19 »
Mirando el datasheet rápidamente y como ADDR lo has colocado a GND, como palabra de control deberías de enviar 0x9A o 0x9B para escribir y para leer.


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado LABmouse

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3575
    • Juntos es mejor
Re: JM60 y Sensor capacitivo MPR121 por I2C..
« Respuesta #2 en: 23 de Noviembre de 2010, 22:52:54 »
Hola,
Analizando el datasheet e intentando determinar la Dirección a enviar por I2C tenemos:

Según la hoja No4 del datasheet.

The device has a configurable I2C address by connecting the ADDR pin to the VSS, VDD, SDA
or SCL lines. The resulting I2C addresses are 0x5A, 0x5B, 0x5C and 0x5D respectively.


ahora bien, teniendo en cuenta que esta ADDR son los 7 bits MSB del dato a enviar, obtendría que:

ADDR para escribir es: 0xB4
ADDR para leer es: 0xB5


Después de un intento siguió bloqueado, entonces implemente un retardo entre dato y dato que se le envía al MPR121 y se sigue bloqueando.  :?       
« Última modificación: 23 de Noviembre de 2010, 23:17:18 por LABmouse »

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: JM60 y Sensor capacitivo MPR121 por I2C..
« Respuesta #3 en: 23 de Noviembre de 2010, 23:26:05 »
En la página 48 de este datasheet dice que es de 7-bits, y para ADDR a GND es 0x4D. Entonces el byte de control sería:

(0x4D<<1) y (0x4D<<1) | 0x01  :?
No contesto mensajes privados, las consultas en el foro

Desconectado LABmouse

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3575
    • Juntos es mejor
Re: JM60 y Sensor capacitivo MPR121 por I2C..
« Respuesta #4 en: 24 de Noviembre de 2010, 00:03:56 »
Pues ya tengo avances en el tema!!!   :P
Código: C
  1. #define MPR121_R 0xB5   // Direccion de Lectura
  2. #define MPR121_W 0xB4   // Direccion de Escritura
  3.  
  4.  
  5. UINT8 mpr121Read(UINT8 direccion){
  6.         char dato;
  7.         i2c_start();                      //Genera señal de Start
  8.   i2c_write(MPR121_W);              //Envia dato por bus I2C    
  9.         i2c_write(direccion);               //Envia direccion de registro a leer
  10.   i2c_restart();                    //Genera señal de Restart
  11.   i2c_write(MPR121_R);              //Envia apuntador de dispositivo I2C
  12.   dato=i2c_read(1);                 //Toma dato de la memoria
  13.   i2c_stop();                       //Genera señal de STOP
  14.   return(dato);
  15. }
  16.  
  17. void mpr121Write(UINT8 direccion, UINT8 dato){
  18.   i2c_start();                      //Genera señal de Start
  19.   i2c_write(MPR121_W);              //Envia apuntador de dispositivo I2C
  20.   i2c_write(direccion);             //Envia direccion LSB
  21.   i2c_write(dato);                  //Envia dato a escribir
  22.   i2c_stop();                       //Genera señal de Stop
  23.   delay_ms(5);                      //Retardo entre escritura y escritura
  24. }


Con esas Funciones estoy trabajando. Si se fijan me toco agregarle retardo en la de escribir byte en sensor, ahora el sensor da señal IRQ cuando detecta actividad en sus electrodos.

Pero solo puedo leer un Byte, pues se queda bloqueado después de leerle la dirección con los 8 bits LSB de los electrodos (Pos 0x00)


Amigo Suky, efectivamente esa es la confusión que hay en internet por todos lados, pues el mismo datasheet se contradice en esos 2 puntos, pero ya me funciona bien enviando por I2C los Bytes:

Byte para escribir es: 0xB4
Byte para leer es: 0xB5
« Última modificación: 24 de Noviembre de 2010, 00:14:47 por LABmouse »

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: JM60 y Sensor capacitivo MPR121 por I2C..
« Respuesta #5 en: 24 de Noviembre de 2010, 00:15:13 »
Seguro que no le envías un NACK al leer el primer dato?

Amigo Suky, efectivamente esa es la confusión que hay en internet por todos lados, pues el mismo datasheet se contradice en esos 2 puntos, pero ya me funciona bien enviando por I2C los Bytes:

Byte para escribir es: 0xB4
Byte para leer es: 0xB5


 :5] Y parecen gente sería!
« Última modificación: 24 de Noviembre de 2010, 00:20:22 por Suky »
No contesto mensajes privados, las consultas en el foro

Desconectado LABmouse

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3575
    • Juntos es mejor
Re: JM60 y Sensor capacitivo MPR121 por I2C..
« Respuesta #6 en: 24 de Noviembre de 2010, 00:20:10 »
Pues realmente estoy enviando un ACK, voy a intentar no enviándolo a ver que tal va...Lo que pasa es que mire en el datasheet pagina 49 que según dice que para leerle un byte debe llegarle un ACK al final después de la llegada de esta al MCU.

Desconectado LABmouse

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3575
    • Juntos es mejor
Re: JM60 y Sensor capacitivo MPR121 por I2C..
« Respuesta #7 en: 24 de Noviembre de 2010, 00:34:38 »
Pues amigo, le diste en el clavo!!!!
Efectivamente al decirle NO ACK va fluido el tema, ahora a  organizar la información y les dejare un video para que vean lo bien que funciona!.
 :P :P :P


Muchas gracias Suky!

 

Desconectado Suky

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: JM60 y Sensor capacitivo MPR121 por I2C..
« Respuesta #8 en: 24 de Noviembre de 2010, 00:37:59 »
 :-/  Yo estoy haciendo mis primeros pasos en Freescale, pero ya habrá noticias  ;-)


Éxitos!  8)


Saludos!
No contesto mensajes privados, las consultas en el foro

Desconectado RICHI777

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1498
Re: JM60 y Sensor capacitivo MPR121 por I2C..
« Respuesta #9 en: 24 de Noviembre de 2010, 17:04:12 »
Felicitaciones Ernesto eres un grande de verdad !!!, lastima que no pueda aportar nada, entre vos y el amigo Suky solucionan todo y muy rápido.

Saludos !

Desconectado Diego E.

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1086
Re: JM60 y Sensor capacitivo MPR121 por I2C..
« Respuesta #10 en: 25 de Junio de 2012, 13:51:41 »
Hola amigos, estoy tratando de poner en funcionamiento este sensor capacitivo, pues como notengo claro muchas de las configuraciones que aparecen en el datasheet traté de darle una configuracion automática.

Estoy leyendo los primero 8 electrodos

Me está funcionando, aunque no del todo bien, unas veces lee bien el dato otras no.

Agradecería revisaran esta configuración a ver si ven algo extraño, muchas gracias

Saludos

Código: C
  1. #include <12F1822.h>
  2. #use delay(clock=4000000)
  3. #fuses wdt, put, brownout, nomclr, intrc_io
  4. #use rs232(baud=9600, xmit=pin_a4,rcv=pin_a5)   //configuración del puerto
  5. #use i2c(master,sda=pin_a2,scl=pin_a1)
  6.  
  7. #byte   porta = 0x0c
  8. #byte   wpua = 0x20c
  9. #byte   option_reg = 0x95
  10.  
  11. int const dir_escribir = 0b10110100;
  12. int const dir_leer = 0b10110101;       
  13.        
  14. short ban_500ms;
  15.  
  16. int dato_rec;
  17. int teclas;
  18.  
  19. char cadena[4];
  20.  
  21. void confi_mpr121();
  22. void leer_mpr121();
  23.  
  24. ///////////////////////////////////////////////////////////////////////////////
  25. #int_rda                                //vector de interrupcion de la recepcion de datos
  26. void interrupcion_rx()  //por el usart, el dato es pasado al dac
  27. {
  28.         dato_rec = getc();     
  29. }
  30. ///////////////////////////////////////////////////////////////////////////////
  31. #int_timer1
  32. void interrupcion_tmr1()
  33. {
  34.         set_timer1(3039);
  35.         ban_500ms = 1;
  36. }
  37. ///////////////////////////////////////////////////////////////////////////////
  38. #zero_ram   //Borrado de la memoria ram
  39.  
  40. void main()      //Rutina principal
  41. {
  42.         set_tris_a(0b101111);
  43.         enable_interrupts(global);
  44.         enable_interrupts(int_rda);             //habilitación de todas las interrupciones
  45.         enable_interrupts(int_timer1);  //Habilitación de la interrupción tmr1
  46.         setup_timer_1(t1_internal | t1_div_by_8);
  47.         set_timer1(0);
  48.        
  49.         setup_oscillator(osc_4mhz | osc_normal | osc_pll_off);
  50.         setup_wdt(wdt_1s);
  51.        
  52.         setup_comparator(nc_nc);        //se deshabilita comparador
  53.        
  54.         setup_adc(adc_off);
  55.         setup_dac(dac_off);
  56.        
  57.         porta = 0;
  58.        
  59.         delay_ms(500);
  60.         ban_500ms = 0; 
  61.         confi_mpr121();
  62.        
  63.  //////////////////////////////////////
  64.         while(true)
  65.         {
  66.                 restart_wdt();
  67.                
  68.                 if(ban_500ms)   //tiempo de 0.5seg
  69.                 {
  70.                         ban_500ms = 0;
  71.                        
  72.                         leer_mpr121();
  73.                         sprintf(cadena,"%03u",teclas);
  74.                         printf("Teclas = %\s\r",cadena);                       
  75.                 }
  76.         }
  77. }
  78. ///////////////////////////////////////////////////////////////////////////////
  79. ///////////////////////////////////////////////////////////////////////////////
  80. void leer_mpr121()
  81. {
  82.         i2c_start();                    //Start
  83.         i2c_write(dir_escribir);        //direccion
  84.         i2c_write(0x00);                        //registro de control
  85.         i2c_start();                    //Start
  86.         i2c_write(dir_leer);            //Control para lectura
  87.        
  88.         teclas = i2c_read();            //Se lee la 8 primeras teclas
  89.        
  90.         i2c_stop();                     //Stop 
  91. }///////////////////////////////////////////////////////////////////////////////
  92. void confi_mpr121()
  93. {
  94.         i2c_start();                    //Start
  95.         i2c_write(dir_escribir);        //direccion
  96.         i2c_write(0x5e);                        //habilitar electrodos
  97.         i2c_write(0b00111111);          //dato a escribir
  98.         i2c_stop();                     //Stop 
  99.        
  100.         delay_ms(10);
  101.        
  102.         i2c_start();                    //Start
  103.         i2c_write(dir_escribir);        //direccion
  104.         i2c_write(0x7b);                        //auto-configuración
  105.         i2c_write(0b00101111);          //dato a escribir
  106.         i2c_stop();                     //Stop
  107. }


 

anything