Данные магнитометра на MPU-9250 (uClinux)

Я нашел несколько других людей, которые спрашивают об этом, но все они кодируют в Arduino, и я изо всех сил пытаюсь перевести это в свой проект.

Я работаю в исследовательской группе, разрабатывающей Cube Satellite для запуска, и моя роль заключается в связи с периферийными устройствами, включая IMU (MPU-9250). Я кросс-компилирую с uClinux, кодирую на C.

Пока что я могу успешно считать показания акселерометра, гироскопа и температуры, но не могу получить показания магнитометра. Магнитометр (AK8963) имеет собственный адрес (0x0C), и я пытался связаться с ним, записывая в I2C_SLV0_ADDR(0x25), I2C_SLV0_REG(0x26), и I2C_SLV0_CTRL (0x27). Когда я не получил никаких результатов, я попытался решить эту проблему, написав в FIFO Enable (0x23) и I2C Master Control (0x24)

Таблица данных и карта регистров подразумевают, что значения, полученные с магнитометра, хранятся в регистрах External Sensor Data (0x49-0x60), но я ничего не получаю в этих регистрах, когда пытаюсь это сделать.

Вот код, который показывает данные, которые я записываю в регистры:

write_register(0x23, 0x04);
write_register(0x24, 0b11110000);
write_register(0x25,0x8c);
write_register(0x26,0x00);
write_register(0x27,0b11110001);

Итак, мои вопросы таковы: 1. Правильно ли я отношусь к этому процессу, или я полностью ошибаюсь?

  1. Если я на правильном пути, читаю ли я из правильных регистров?

Спасибо за вашу помощь всем! Дайте мне знать, если мне нужно что-то уточнить!


person Connor Olsen    schedule 11.05.2017    source источник
comment
Ну, я не знаю устройство, но я не понимаю, как чтение набора регистров не может ничего "получить"?   -  person ThingyWotsit    schedule 11.05.2017


Ответы (1)


Хорошо! Я сам разобрался со своим вопросом :)

1) Я действительно шел по этому пути неправильно. Есть гораздо более простой способ сделать это, и я подробно покажу, как это сделать.

2) Я не читал из правильных регистров. Я покажу, что делать ниже.

Таким образом, подключение к магнитометру очень простое, но совершенно не интуитивное. Он действует как собственное ведомое устройство со своим собственным ведомым адресом, но изначально этот адрес недоступен.

Поскольку я выполняю кросс-компиляцию с uClinux, я могу использовать команду bash i2cdetect 0 (при просмотре в моем SmartFusion2), чтобы проверить все подчиненные устройства на моей шине i2C 0. Когда я выполняю эту команду после сброса платы, я получаю распечатку следующей карты адресов:

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 

Таким образом, вы можете видеть, что отображается только адрес для IMU (0x68). Чтобы магнитометр отображался правильно, вы должны включить бит обхода в INT_PIN_CFG (0x37). Я прикрепил свой код ниже на случай, если кому-то понадобится повторить это.

#include <stdio.h>
//#include <linux/i2c-dev.h>

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define IMU_ADDR 0x68 
#define IMU_WHO_AM_I 0x75


int file;

void i2c_init();
void write_register(uint8_t register_address, uint8_t value);
uint8_t read_register(uint8_t register_address);

void i2c_init(address){
    int adapter_nr = 0;
    char filename[20];

    snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
    file = open(filename, O_RDWR);
    if(file < 0)
        printf("Error: Failed to open file %s\n", filename);
    int success= (ioctl(file, I2C_SLAVE, address));
    if(file < 0) {
        printf("Error: IMU I2C Failed to Open\n");
        //return -1;
    }
}
void write_register(uint8_t register_address, uint8_t value){
    uint8_t data[]={register_address,value};
    write(file, data,ARRAY_SIZE(data));
}
uint8_t read_register(uint8_t register_address){
    uint8_t value;
    if(write(file, &register_address, sizeof(register_address)) !=1)
    {
        printf("%d\n",write(file, &register_address, sizeof(register_address)));
        printf("Failed to send data\n");
    }
    read(file, &value, sizeof(value));
    return value;
}

int main(){
    i2c_init(IMU_ADDR);

    printf("\nNow testing the 'Who am I?' IMU register. Output should be 0x71\n");
    printf("Register 0x75: 0x%02X \n", read_register(IMU_WHO_AM_I));

    write_register(0x37, 0x22);
    i2c_init(0x0C);
        printf("\nNow testing the 'Who am I?' Magnetometer register. Output should be 0x48\n");

    printf("Register 0x00: 0x%02x\n", read_register(0x00));

    return 0;
}

После компиляции и запуска кода команда i2cdetect 0 возвращает следующую карту данных.

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- 0c -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 

Программа также возвращает 0x48, правильное значение при чтении с магнитометра «кто я?» регистр. Магнитометр теперь можно считывать так же, как и любой другой регистр. Надеюсь это поможет!!

person Connor Olsen    schedule 12.05.2017