|
|
  |
atmega32 + HMC5883 (по i2c), подключение компаса к мк |
|
|
|
May 21 2012, 05:14
|

Частый гость
 
Группа: Участник
Сообщений: 115
Регистрация: 30-05-11
Из: Екатеринбург
Пользователь №: 65 365

|
Я использую режим continious mode (получается записью 0х00 в регистр 0х02). Код который использую сейчас прилагаю. Пробовал посмотреть статусный регистр компаса - результат 0xff. Подтяжка из резисторов на линиях sda и scl на результаты от компаса же никак не может повлиять? Все проверки проходят компас подтверждает прием и запись с чтением из его регистров. Раньше я дополнительно делал подтяжку на линиях, а сейчас убрал ее и все вроде также работает, т.е. подтяжка есть на плате с компасом как я понимаю. Пробовал single mode результат все равно ff - MSB, 00 - LSB. Надо может прочитать все регистры конфигурационные или какой план действий? Вот прочитал регистр configuration A получил 0xf0, что судя по даташиту не совсем гуд, а вот в регистре configuration B получил 0х20, что вроде как по дефолту.
Сообщение отредактировал Kruftin - May 21 2012, 18:53
|
|
|
|
|
May 22 2012, 10:48
|

Частый гость
 
Группа: Участник
Сообщений: 115
Регистрация: 30-05-11
Из: Екатеринбург
Пользователь №: 65 365

|
Фатал. Как оказалось компас базируется не на HMC5883, а на HMC5883L и они немного отличаются, правда отличия не критичные. Т.е. код для 5883 должен работать и на 5883L. Даташит новый я приложил. Там кстати есть примеры, по которым я сегодня код отредактировал и получил незначительное изменение: в X (MSB - 0x83 LSB 0xFF ), Y (0xFF,0xFF), Z(0xFF,0xFF). В даташите написано, что переполнение регистров возможно, если шум выставлен неверно, так вот я выставлял его на все варианты, не помогает. Правда есть еще строчка в даташите, которую я не понимаю как реализовать: Send 0x3D 0x06 что это делает мне непонятно(смотри картинку из даташита). Пробовал все режимы - безрезультатно. Вот код основной: CODE void HMC5843(void) { //unsigned char xh, xl, yh, yl, zh, zl; long xo, yo, zo; i2cSendStart(); i2cWaitForComplete(); i2cWrite_Address(0x3C); //write to HMC i2cWaitForComplete(); i2cWrite_Data(0x00); //confA reg i2cWaitForComplete(); i2cWrite_Data(0x70); //value for confA i2cWaitForComplete(); i2cSendStop(); delay_ms(5); i2cSendStart(); i2cWaitForComplete(); i2cWrite_Address(0x3C); //write to HMC i2cWaitForComplete(); i2cWrite_Data(0x01); //confB reg i2cWaitForComplete(); i2cWrite_Data(0xA0); //value for confB i2cWaitForComplete(); i2cSendStop(); delay_ms(5); i2cSendStart(); i2cWaitForComplete(); i2cWrite_Address(0x3C); //write to HMC i2cWaitForComplete(); i2cWrite_Data(0x02); //mode register i2cWaitForComplete(); i2cWrite_Data(0x01); //continuous measurement mode i2cWaitForComplete(); //status_er = i2cGetStatus(); //i2cCheckForMT_SLA(); i2cSendStop(); delay_ms(10); i2cSendStart(); i2cWaitForComplete(); i2cWrite_Address(0x3C); //write to HMC i2cWaitForComplete(); i2cWrite_Data(0x09); //status register i2cWaitForComplete(); i2cSendStop(); delay_ms(10); i2cSendStart(); i2cWaitForComplete(); i2cRead_Address(0x3D); //write to HMC i2cWaitForComplete(); reg_stcmp = i2cRead_Data(); //status register i2cWaitForComplete(); i2cSendStop(); delay_ms(10); i2cSendStart(); i2cWaitForComplete(); i2cWrite_Address(0x3C); //write to HMC i2cWaitForComplete(); i2cWrite_Data(0x02); //mode register i2cWaitForComplete(); i2cSendStop(); delay_ms(10); //must read all six registers plus one to move the pointer back to 0x03 i2cSendStart(); i2cWaitForComplete(); i2cRead_Address(0x3D); //read from HMC i2cWaitForComplete(); i2cReceiveByte(TRUE); //i2cWaitForComplete(); xh = i2cRead_Data(); //x high byte i2cWaitForComplete(); i2cReceiveByte(TRUE); i2cWaitForComplete(); xl = i2cRead_Data(); //x low byte i2cWaitForComplete(); xo = xl|(xh << 8); i2cReceiveByte(TRUE); i2cWaitForComplete(); yh = i2cRead_Data(); //y high byte i2cWaitForComplete(); i2cReceiveByte(TRUE); i2cWaitForComplete(); yl = i2cRead_Data(); //y low byte i2cWaitForComplete(); yo = yl|(yh << 8); i2cReceiveByte(TRUE); i2cWaitForComplete(); zh = i2cRead_Data(); i2cWaitForComplete(); //z high byte i2cReceiveByte(TRUE); i2cWaitForComplete(); zl = i2cRead_Data(); //z low byte i2cWaitForComplete(); zo = zl|(zh << 8); //i2cRead_Data(); //must reach 0x09 to go back to 0x03 //i2cWaitForComplete(); // i2cReceiveByte(TRUE); //i2cWaitForComplete(); status_er = i2cGetStatus(); i2cSendStop(); }
void main(void)
Сообщение отредактировал IgorKossak - May 22 2012, 16:44
Причина редактирования: [codebox] для длинного кода!!!
Эскизы прикрепленных изображений
|
|
|
|
|
May 22 2012, 17:56
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
3. Write Mode (02) – send 0x3C 0x02 0x00 (Continuous-measurement mode) Код i2cWrite_Data([b]0x01[/b]); //continuous measurement mode !!!!!!!!! Вот эту часть не понял, ну прочёл ты статусный регистр , а зачем? Если проверить RDY то где она? Код i2cSendStart(); i2cWaitForComplete(); i2cWrite_Address(0x3C); //write to HMC i2cWaitForComplete(); i2cWrite_Data(0x09); //status register i2cWaitForComplete(); i2cSendStop(); delay_ms(10); i2cSendStart(); i2cWaitForComplete(); i2cRead_Address(0x3D); //write to HMC i2cWaitForComplete(); reg_stcmp = i2cRead_Data(); //status register i2cWaitForComplete(); i2cSendStop(); delay_ms(10); Здесь поставил адрес на mode register , а начал читать измеренные данные Код i2cSendStart(); i2cWaitForComplete(); i2cWrite_Address(0x3C); //write to HMC i2cWaitForComplete(); i2cWrite_Data(0x02); //mode register i2cWaitForComplete(); i2cSendStop(); delay_ms(10); //must read all six registers plus one to move the pointer back to 0x03 i2cSendStart(); i2cWaitForComplete(); i2cRead_Address(0x3D); //read from HMC i2cWaitForComplete(); i2cReceiveByte(TRUE); //i2cWaitForComplete(); xh = i2cRead_Data(); //x high byte i2cWaitForComplete(); Так они показали, что в continuous measurement mode , Цитата 5. Loop Send 0x3D 0x06 - это (Read all 6 bytes. If gain is changed then this data set is using previous gain) Convert three 16-bit 2’s compliment hex values to decimal values and assign to X, Z, Y, respectively. Send 0x3C 0x03 (point to first data register 03) Wait about 67 ms (if 15 Hz rate) or monitor status register or DRDY hardware interrupt pin End_loop не нужно посылать вот это, снова и снова - достаточно одной таблетки Цитата 1. Write CRA (00) – send 0x3C 0x00 0x70 (8-average, 15 Hz default, normal measurement) 2. Write CRB (01) – send 0x3C 0x01 0xA0 (Gain=5, or any other desired gain) 3. Write Mode (02) – send 0x3C 0x02 0x00 (Continuous-measurement mode) 4. Wait 6 ms or monitor status register or DRDY hardware interrupt pin И разберись с delays , что-то их до хрена , как мне кажется. И где-то надо бы подождать 67ms , а не 10. Если сделаешь проверку RDY то delays вообще не нужны, но код придётся подправить
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
May 22 2012, 21:34
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Цитата(Kruftin @ May 22 2012, 23:30)  Т.е. 0х3D 0x06 - из этого послать надо только 0х3D, а 0х06 означает, что надо считать все регистры осей. Да под одним стартом прочитать подряд все 6 регистров и затем вернуться к началу 0х3С 0х03 Цитата To clock out the new data, send: 0x3D, and clock out DXRA, DXRB, DZRA, DZRB, DYRA, and DYRB located in registers 3 through 8....... А Вы смотрите данные пересылая их на комп? Может в пересылке что-то не так ?
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
May 23 2012, 03:08
|

Частый гость
 
Группа: Участник
Сообщений: 115
Регистрация: 30-05-11
Из: Екатеринбург
Пользователь №: 65 365

|
По идее, так и по даташиту, код который составлен на сегодня должен работать для режима single mode. И хоть какие-то регистры должны быть считаны верно. Пересылка на комп стандартно по уарту, смотрю через терминал. Сомневаюсь, что данные именно регистров могут исказиться, посылка остальных символов еще ни разу не давала сбоев. Я полазил по зарубежным сайтам, так там нашел только мистическое изменение адреса компаса с 0x1E на 0x1C. Но раз он тут нам все подтверждает, значит адрес верен. Кстати раз написано Send 0x3D 0x06, так значит надо послать 0x06, а только потом считывать данные. Нашел на компас errata sheet http://www.kamami.pl/dl/hmc5883l_datasheet_errata.pdf
Сообщение отредактировал Kruftin - May 23 2012, 07:12
|
|
|
|
|
May 23 2012, 08:00
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Цитата(Kruftin @ May 23 2012, 07:08)  Кстати раз написано Send 0x3D 0x06, так значит надо послать 0x06, а только потом считывать данные. Куда послать? 3D - это чтение! Цитата(Kruftin @ May 23 2012, 07:08)  Нашел на компас errata sheet ... Так они обещали всё исправить к 1 кварталу 2011 года Посмотри твой когда выпущен. И попробуй сделать это SELF TEST OPERATION
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
May 23 2012, 09:06
|

Частый гость
 
Группа: Участник
Сообщений: 115
Регистрация: 30-05-11
Из: Екатеринбург
Пользователь №: 65 365

|
Ща попробую self-test. На нем тока написано L883 2048 и даты изготовления нету. В X регистре получаю в self test изменяющиеся при мневре компасом значения 0xFF - LSB 0XC1 - MSB, ну вместо C1 бывает С4 - С6(ну хоть куда вращай где эти числа меняются в районе C1-C6). Регистры Y,Z по прежнему 0xFF. Ого регистр X начал реагировать в обычном continuous measurement mode режиме MSB начал выдавать правдивый результат, а вот с остальными регистрами пока тихо. Странные чувства заработала часть регистра X. А остальные нет. Может я считываю не так остальные регистры? CODE //must read all six registers plus one to move the pointer back to 0x03 i2cSendStart(); i2cWaitForComplete(); i2cRead_Address(0x3D); //read from HMC i2cWaitForComplete(); delay_ms(200); i2cReceiveByte(TRUE); i2cWaitForComplete(); xh = i2cRead_Data(); //x high byte i2cWaitForComplete(); i2cReceiveByte(TRUE); i2cWaitForComplete(); xl = i2cRead_Data(); //x low byte i2cWaitForComplete(); xo = xl|(xh << 8); i2cReceiveByte(TRUE); i2cWaitForComplete(); yh = i2cRead_Data(); //y high byte i2cWaitForComplete(); i2cReceiveByte(TRUE); i2cWaitForComplete(); yl = i2cRead_Data(); //y low byte i2cWaitForComplete(); yo = yl|(yh << 8); i2cReceiveByte(TRUE); i2cWaitForComplete(); Да похоже, что косяк при считывании данных из регистров. Считывается только xh, т.е. значение первого регистра, а остальные просто не считались потому и ff.
Сообщение отредактировал IgorKossak - May 23 2012, 13:11
Причина редактирования: [codebox] для длинного кода!!!
|
|
|
|
|
May 23 2012, 10:22
|

Частый гость
 
Группа: Участник
Сообщений: 115
Регистрация: 30-05-11
Из: Екатеринбург
Пользователь №: 65 365

|
Ну в общем заметен прогресс. Менял я сейчас значение с которого начинать читать и вот в результате значения правильные есть во всех трех MSB байтах, а в LSB 0xFF. Осталось только придумать как считывать все регистры сразу, а не по одному меняя код. Код i2cSendStart(); i2cWaitForComplete(); i2cWrite_Address(0x3C); //write to HMC i2cWaitForComplete(); i2cWrite_Data(0x08); //mode register i2cWaitForComplete(); i2cSendStop(); delay_ms(200); //must read all six registers plus one to move the pointer back to 0x03 i2cSendStart(); i2cWaitForComplete(); i2cRead_Address(0x3D); //read from HMC i2cWaitForComplete(); i2cReceiveByte(TRUE); i2cWaitForComplete(); xh = i2cRead_Data(); //x high byte i2cWaitForComplete(); Все кароче пошла рыбка  Только вот пока LSB байты остаются FF. Написал я считывание к каждому регистры по отдельности и заработало в single mode. ILYAUL  Правда из-за обращения к каждому регистру индивидуально код получился довольно громоздким.
Сообщение отредактировал Kruftin - May 23 2012, 10:29
|
|
|
|
|
May 23 2012, 11:11
|

Профессионал
    
Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339

|
Посмотри, что вот так будет CODE i2cSendStart(); i2cWaitForComplete(); i2cWrite_Address(0x3C); //write to HMC i2cWaitForComplete(); i2cWrite_Data(0x03); //XH register i2cWaitForComplete(); //i2cSendStop(); delay_ms(67); //must read all six registers plus one to move the pointer back to 0x03 i2cSendStart(); i2cWaitForComplete(); i2cRead_Address(0x3D); //read from HMC i2cWaitForComplete(); i2cReceiveByte(TRUE); //i2cWaitForComplete(); xh = i2cRead_Data(); //x high byte i2cWaitForComplete(); i2cReceiveByte(TRUE); i2cWaitForComplete(); xl = i2cRead_Data(); //x low byte i2cWaitForComplete(); xo = xl|(xh << 8); i2cReceiveByte(TRUE); i2cWaitForComplete(); yh = i2cRead_Data(); //y high byte i2cWaitForComplete(); i2cReceiveByte(TRUE); i2cWaitForComplete(); yl = i2cRead_Data(); //y low byte i2cWaitForComplete(); yo = yl|(yh << 8); i2cReceiveByte(TRUE); i2cWaitForComplete(); zh = i2cRead_Data(); i2cWaitForComplete(); //z high byte i2cReceiveByte(TRUE); i2cWaitForComplete(); zl = i2cRead_Data(); //z low byte i2cWaitForComplete(); zo = zl|(zh << 8); i2cSendStop(); Цитата Только вот пока LSB байты остаются FF Всё таки доделай self test до конца , как они рекомендуют выставить коэффициент усиления. Может и LSB тогда оживут
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|