Данные магнитометра на 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)
Таблица данных и карта регистров подразумевают, что значения, взятые из магнитометра, сохраняются в регистрах данных внешнего датчика(0x49-0x60), но я не получаю ничего в этих регистрах, когда пытаюсь это сделать.
Вот некоторый код, который показывает данные, которые я записываю в регистры:
write_register(0x23, 0x04);
write_register(0x24, 0b11110000);
write_register(0x25,0x8c);
write_register(0x26,0x00);
write_register(0x27,0b11110001);
Итак, мои вопросы: 1. Правильно ли я иду в этом процессе, или я полностью выключен?
- Если я на правильном пути, я читаю из правильных регистров?
Спасибо за вашу помощь всем! Дайте мне знать, если есть что-то, что мне нужно уточнить!
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, ®ister_address, sizeof(register_address)) !=1)
{
printf("%d\n",write(file, ®ister_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, правильное значение при чтении с магнитометра "кто я?" регистр. Теперь магнитометр может быть считан так же, как и любой другой регистр. Надеюсь это поможет!!