Comment interfacer un accéléromètre en I2C ?

NIVEAU 4

Objectifs

  • Mettre en oeuvre le protocole I2C
  • Trouver les informations dans une documentation technique complexe
  • Ecrire des fonctions pour une application spécifique

Pré-requis

Accéléromètre et I2C

ADXL 350

Documentation technique

Dans la rubrique I2C de la documentation technique (pages 20 et 21), on trouve l’adresse du composant.
Il est mentionné plusieurs adresses possibles selon quels potentiels sont appliqués sur certaines broches.

L’adresse de base est 0x1D. Mais sur ce module, c’est l’adresse alternative qui est utilisée et qui vaut 0x53.

Altimu 10v5

Interfaçage et récupération de données

ADXL 350

Brochage

Afin de pouvoir utiliser l’accéléromètre 3 axes ADXL350, il est indispensable de l’alimenter.
Pour cela, il faut relier les deux broches GND du module accéléromètre à la masse de votre circuit de pilotage.
Il faut également connecter les broches VS (alimentation du capteur) et VIO (alimentation de la partie numérique) à un potentiel de 3.3V (par exemple celui de la carte Nucléo).

Ensuite, pour pouvoir échanger des informations, il faut relier les broches SDA et SCL de la liaison I2C de l’accéléromètre avec les broches SDA et SCL de la carte de commande (voir schéma ci-dessous – tirée de la Documentation technique).

Les résistances de Pull-Up sont obligatoires. Elles dépendent de la fréquence du réseau I2C voulue et du type de connectique utilisée. Essayez avec des résistances de \(1.2k\Omega\) pour une fréquence de 100kHz. Selon l’allure des signaux sur SCL et SDA, il faudra peut-être les modifier.

Il faut également relier la broche CS à un potentiel de 3.3V. Il peut aussi être intéressant de forcer la broche SDO à 0V pour être sur de l’adresse (ici adresse alternative 0x53).

Initialisation

Récupération des données

Exemple complet

#include "mbed.h"

#define     ADXL_ADDR   0x53        // Specifique module ADXL350

#define     ADXL_DEVID      0x00
#define     ADXL_BW_RATE    0x2C
#define     ADXL_POWER_CTL  0x2D
#define     ADXL_DATAX0     0x32
#define     ADXL_DATAX1     0x33
#define     ADXL_DATAY0     0x34
#define     ADXL_DATAY1     0x35
#define     ADXL_DATAZ0     0x36
#define     ADXL_DATAZ1     0x37


DigitalOut myled(LED1);
I2C my_i2c(D14, D15);
Serial pc(SERIAL_TX, SERIAL_RX);

int k1, k2;
char data[10];
char acceleration[6];
char device_reg;
int adxl_x_data, adxl_y_data, adxl_z_data;


/*
 * Envoyer une donnée dans un registre de l'ADXL350
 */
void ADXL350_setReg(char ad_reg, char value){
    data[0] = ad_reg;
    data[1] = value;
    k1 = my_i2c.write(ADXL_ADDR << 1, data, 2);   // write       
    pc.printf("K1 = %d / WRITE \r\n");  
    return;
}

/*
 * Recevoir une donnée d'un registre de l'ADXL350
 */
char ADXL350_getReg(char ad_reg){
    char data_reg;
    device_reg = ad_reg;
    k1 = my_i2c.write(ADXL_ADDR << 1, &device_reg, 1, true);   // write
    k2 = my_i2c.read(ADXL_ADDR << 1, &data_reg, 1, false);   // read   
    pc.printf("K1 = %d / K2 = %d / READ \r\n");  
    return data_reg;
}

/*
 * Recevoir des données de registres successifs de l'ADXL350
 */
char ADXL350_getReg(char ad_reg, char *dat, int n_data){
    char data_reg;
    device_reg = ad_reg;
    k1 = my_i2c.write(ADXL_ADDR << 1, &device_reg, 1, true);   // write
    k2 = my_i2c.read(ADXL_ADDR << 1, dat, n_data, false);   // read   
    pc.printf("K1 = %d / K2 = %d / READ \r\n");  
    return data_reg;
}

/*
 * Initialisation de l'ADXL350
 */
bool ADXL350_begin(void) {
    ADXL350_setReg(ADXL_BW_RATE, 0b00001000);       // 25 Hz 
    wait_ms(10);
    ADXL350_setReg(ADXL_POWER_CTL, 0b00001000);     // Normal Mode / Measurement mode 
    wait_ms(10);        
    return true;
}

/*
 * Lecture des données X, Y, Z de l'ADXL350
 */
void ADXL350_read(void) {
    ADXL350_getReg(ADXL_DATAX0, data, 6);  
    
    adxl_x_data = data[0] << 8 + data[1];
    adxl_y_data = data[2] << 8 + data[3];
    adxl_z_data = data[4] << 8 + data[5];
    return;
}



/* Fonction principale */
int main() {
    /* Initialisation */
    int i;
    char adxl_reg = 0;
    my_i2c.frequency(100000); 
    myled = 1; // LED is ON
    
    wait(0.2);
    ADXL350_begin();   
    
    adxl_reg = ADXL350_getReg(ADXL_DEVID);
    pc.printf("REG = %x \r\n", adxl_reg);
    
    /* Boucle principale */
    while(1) {
        i++;
        ADXL350_read();
        pc.printf("[%d] X = %d / Y = %d / Z = %d \r\n", i, adxl_x_data, adxl_y_data, adxl_z_data);
        myled = !myled;
        wait_ms(500);
    }
}

MInE Prototyper Prototyper avec Nucleo et MBED

Nucléo – Interfacer un accéléromètre en I2C