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

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

|
Добрый день! Возникла проблема при подключении к мк атмега32 компаса HMC5883. Устанавливаю состояние старт, а вот затем посылаю адрес для записи, в ответ на который получаю состояние регистра статуса twi равное 0х20, что означает: данные переданы, получен Not ack. Вот такие дела. Причем коды состояния я получаю только лишь при работе на частоте 1 МГц, на 8Мгц не могу получить даже состояние старт. Код прилагаю даже в двух вариантах. Также в архив положил даташит на компас. Вот участок кода где я проверяю статус: Код void HMC5843(void) { //unsigned char xh, xl, yh, yl, zh, zl; long xo, yo, zo; i2cSendStart(); i2cWaitForComplete(); i2cWrite_Address(0x3C); //write to HMC i2cWaitForComplete(); status_er = i2cGetStatus(); i2cWrite_Data(0x02); //mode register i2cWaitForComplete(); i2cWrite_Data(0x00); //continuous measurement mode i2cWaitForComplete(); //status_er = i2cGetStatus(); //i2cCheckForMT_SLA(); i2cSendStop(); Полезные ссылки: 1)http://www.seeedstudio.com/wiki/index.php?title=Twig_-_3-axis_Compass_v1.0b
Эскизы прикрепленных изображений
|
|
|
|
|
May 13 2012, 18:01
|

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

|
В архиве компас есть полный код программы(для CVAVR), так вот там есть функция: 1-й вариант CODE void i2cSetBitrate(unsigned short bitrateKHz) { //unsigned char bitrate_div; // set i2c bitrate // SCL freq = F_CPU/(16+2*TWBR*4^TWPS)) //TWSR &= ~(1<<TWPS0); //set zero for TWPS = 1 //TWSR &= ~(1<<TWPS1); //calculate bitrate division //bitrate_div = ((F_CPU/4000l)/bitrateKHz); //if(bitrate_div >= 16) // bitrate_div = (bitrate_div-16)/2; //TWBR = bitrate_div; unsigned char bitrate_div; // set i2c bitrate // SCL freq = F_CPU/(16+2*TWBR)) //#ifdef TWPS0 // for processors with additional bitrate division (mega128) // SCL freq = F_CPU/(16+2*TWBR*4^TWPS) // set TWPS to zero cbi(TWSR, TWPS0); cbi(TWSR, TWPS1); //#endif // calculate bitrate division bitrate_div = ((F_CPU/4000l)/bitrateKHz); if(bitrate_div >= 16) bitrate_div = (bitrate_div-16)/2; outb(TWBR, bitrate_div); } 2-й вариант Код TWBR=0x01; // Bit rate TWSR=(0<<TWPS1)|(0<<TWPS0); // Setting prescalar bits // SCL freq= F_CPU/(16+2(TWBR).4^TWPS) А сама установка скорости в основной программе называется i2cInit(): CODE void i2cInit(void) { // set i2c bit rate to 40KHz i2cSetBitrate(100); // enable TWI (two-wire interface) //TWCR = 1<<TWEN; // Enable TWI sbi(TWCR, TWEN); } void main(void) { i2cInit(); delay_ms(100); USART_Init(); #asm("sei"); while(1) { HMC5843(); delay_ms(200); //at least 100ms interval between measurements if (1){ USART_SendChar('p'); //отвечаем компу USART_SendChar('r'); USART_SendChar('i'); USART_SendChar('v'); USART_SendChar('e'); USART_SendChar('t'); USART_SendChar(zl); USART_SendChar(zh); USART_SendChar(error); USART_SendChar(status_er); delay_ms(200); } } }
Сообщение отредактировал IgorKossak - May 14 2012, 06:29
Причина редактирования: [codebox] для длинного кода
|
|
|
|
|
May 14 2012, 11:08
|
Частый гость
 
Группа: Участник
Сообщений: 105
Регистрация: 9-09-11
Пользователь №: 67 080

|
с I2C не сталкивался, но пытаясь разобраться вот на что наткнулся: Код bitrate_div = ((F_CPU/4000l)/bitrateKHz); if(bitrate_div >= 16) bitrate_div = (bitrate_div-16)/2; outb(TWBR, bitrate_div); допустим F_CPU= 1 000 000 , тогда 1000000/4000=250, 250/100 = 2.5 bitrate_div=2 если F_CPU = 8 000 000, тогда 8000000/4000=2000, 2000/100 = 20 20 >=16 истина, тогда 20-16=4, 4/2= 2 bitrate_div =2. Т.О. при любой частоте запишется число 2. Или я чего то не учел ?
|
|
|
|
|
May 14 2012, 11:46
|

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

|
Дак а почему тогда вариант номер 2 не катит? Код TWBR=0x01; // Bit rate TWSR=(0<<TWPS1)|(0<<TWPS0); // Setting prescalar bits // SCL freq= F_CPU/(16+2(TWBR).4^TWPS) Первый вариант взят из примера для компаса HMC5843, он по моему с точки зрения кода ничем не отличается особо. Ну мы устанавливаем частоту передачи на i2c, по даташиту на компас она может быть до 400КГц. Дак вот не все равно что я запишу в TWBR? Пусть TWBR = 1, тогда Частота f_SCL = 1000000/(16 +2*1*4) = 41666Гц, ну и 41666<400000, Пусть частота будет 8Мгц, тогда 41666*8 = 333328, что тоже меньше 400000.
|
|
|
|
|
May 14 2012, 15:38
|

Гуру
     
Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106

|
Цитата(Kruftin @ May 14 2012, 17:39)  Сейчас я подаю на него минимальное 3.3 Вольта(Vdd). Судя по приложенному Вами DS, 3.3V это не минимальное а МАКСИМАЛЬНО необходимое значение АVDD. А на DVDD вообще максимальное 2.0V. Или я чегото не понимаю?
|
|
|
|
|
May 14 2012, 17:49
|

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

|
Нет я ошибся Цитата Судя по приложенному Вами DS, 3.3V это не минимальное а МАКСИМАЛЬНО необходимое значение АVDD. А на DVDD вообще максимальное 2.0V. Или я чего то не понимаю? Там стабилизатор на его плате на 2.5 В и допускается схема включения как я привёл выше Цитата "Прим.: TWBR должен быть равен не менее 10, если TWI работает в ведущем режиме. Если TWBR меньше 10, то ведущий может генерировать некорректное состояние на линиях SDA и SCL. Проблема возникает при работе в ведущем режиме при передаче условий СТАРТ+ПОДЧИН_АДР+ ЧТЕНИЕ/ЗАПИСЬ подчиненному." Совершенно верно. Поэтому ему надо оставить TWBR=1 и Цитата поиграться прескалером. Хотя это тоже не вариант. Код 08 после старта возвращается?
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
May 14 2012, 18:11
|

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

|
Ну питание на платку я могу подать до 5 Вольт. Так вот TWBR, то почему я должен в единичку поставить, если у меня контроллер то в ведущем режиме работает(master)? Ну я не думаю что у меня калькулятор меня обманывает, вроде частоту верно рассчитал. http://www.seeedstudio.com/wiki/index.php?...s_Compass_v1.0b - тут написано про платку на которой компас После старта код 0х08 возвращается при работе на 1МГц. А при работе на 8МГц 0xF8 возвращается, что и после старта, ну это косяк скорости. Дак вот настроить бы хоть на 1МГц. Может питание поднять у компаса, хотя ведь он вроде как посылает not ack или это в линии по умолчанию?
Сообщение отредактировал Kruftin - May 14 2012, 18:49
|
|
|
|
|
May 14 2012, 18:46
|

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

|
Цитата(Kruftin @ May 14 2012, 22:11)  Ну питание на платку я могу подать до 5 Вольт. Так вот TWBR, то почему я должен в единичку поставить, если у меня контроллер то в ведущем режиме работает(master)? Ну я не думаю что у меня калькулятор меня обманывает, вроде частоту верно рассчитал. Верно. Давайте остановимся на 8 мгц TWBR=0x03 частота = 200000гц Блин , забыл в своей формуле 4 TWBR=(SYSCLK/(2*SCL_Freq)-8) /4
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
May 14 2012, 18:50
|

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

|
Ну сейчас попробую. Он даже старт не может выставить 08. На 1МГц все также 0х30. И еще кстати есть подвижки в лучшую сторону: если я ставлю TWBR больше 10, то у меня старт проходит на 8МГц, но 0х30 в ответе на посылку адреса. Т.е. может быть скорость то та?Кстати попробовал поставить делитель 4 вместо 1, так вот старт не проходит, хм странно, а может быть такое, что компас только на одну скорость настроен? Скажу сразу, что на 8МГц все значения TWBR ниже 10 не катят, а вот на 1МГц катят все значения.
Сообщение отредактировал Kruftin - May 14 2012, 19:14
|
|
|
|
|
May 14 2012, 19:14
|

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

|
Цитата(Kruftin @ May 14 2012, 22:50)  Ну сейчас попробую. Он даже старт не может выставить 08. На 1МГц все также 0х30. И еще кстати есть подвижки в лучшую сторону: если я ставлю TWBR больше 10, то у меня старт проходит на 8МГц, но 0х30 в ответе на посылку адреса. Т.е. может быть скорость то та?Кстати попробовал поставить делитель 4 вместо 1, так вот старт не проходит, хм странно, а может быть такое, что компас только на одну скорость настроен? А адрес то какой 0x3D или 0x1E
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
May 14 2012, 19:15
|

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

|
Код i2cSendStart(); i2cWaitForComplete(); i2cWrite_Address(0x3C); //write to HMC i2cWaitForComplete(); 0х3С разумеется идет на запись в регистр Адрес по идее устройства 0х1Е, но ты добавляй бит на запись или чтение и будет 0х3С на запись и 0х3D на чтение.
Сообщение отредактировал Kruftin - May 14 2012, 19:25
Эскизы прикрепленных изображений
|
|
|
|
|
May 14 2012, 19:31
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(Kruftin @ May 14 2012, 21:50)  а может быть такое, что компас только на одну скорость настроен? Не может. Задана только максимальная скорость. Либо - это новое слово в науке и технике. Нашёл такой пунктик в DS на м88. Может ваш случай? Цитата TWBR should be 10 or higher if the TWI operates in Master mode. If TWBR is lower than 10, the Master may produce an incorrect output on SDA and SCL for the reminder of the byte. The prob- lem occurs when operating the TWI in Master mode, sending Start + SLA + R/W to a Slave (a Slave does not need to be connected to the bus for the condition to happen).
|
|
|
|
|
May 14 2012, 20:00
|

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

|
Цитата(Kruftin @ May 14 2012, 23:45)  Ладно завтра перепаяю, и дам ему чизбургеров на 5Вольт. Хотя щас попробую. От 5 Вольт лучше не стало. 5V и на mege? Цитата TWBR should be 10 or higher if the TWI operates in Master mode. If TWBR is lower than 10, the Master may produce an incorrect output on SDA and SCL for the reminder of the byte. The prob- lem occurs when operating the TWI in Master mode, sending Start + SLA + R/W to a Slave (a Slave does not need to be connected to the bus for the condition to happen). Артём , это есть выше , но в 32 мы этого не нашли . Если в TWBR будет хотя бы 10 то при 8 мгц SCL=83333
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
May 14 2012, 20:11
|

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

|
Страно это Цитата если я ставлю TWBR больше 10, то у меня старт проходит на 8МГц, но 0х30... - это ответ на данные а не на адрес. Почему он адрес воспринимает как данные , только в том случае если адрес он уже принял и всё остальное считает данными.
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
May 15 2012, 06:21
|

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

|
Между компасом и моей отладочной? Расстояние сантиметров 7-8.  Никто случаем не знает какой-нибудь нормальный зарубежный форум, где могут подсказать по атмеге, avrfreaks регистрацию приостановил? Похоже единственный энтузиаст ILYAUL исчерпал фантазии, печально похоже придется использовать обычный компас, а не цифровой).
Сообщение отредактировал Kruftin - May 15 2012, 16:45
|
|
|
|
|
May 15 2012, 18:41
|

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

|
У меня фантазии хватает, тока вот применить я ее не в силах, сейчас вот думаю ножками подрыгать(как пример http://avrlab.com/node/127). Может дело в TWI модуле атмеги. Кстати вот что интересного про ошибку почерпнул отсюда http://easyelectronics.ru/avr-uchebnyj-kur...oj-iic-i2c.html 0×20 SLA+W+NACK Мы отправили адрес с битом записи, а нас послали NACK. Обидно, сгенерим ошибку или повторим еще раз. 0×30 Byte+NACK Мы послали байт, но подтверждение не получили. Видимо ведомый уже сыт по горло нашими подачками или он захлебнулся в данных. Либо его ВНЕЗАПНО посреди передачи данных украли инопланетяне. Просто когда я с уартом разбирался, там больше было возможностей для маневра, а тут только осциллограф в руки. Не я все равно добью этот компас  P.S. Как это я в коде не разобрался?!Он простейший, я все что делаю понимаю, мне регистры уже снятся. А вот осциллографом я должен быстро получается отлавливать передачу от компаса?Он же когда я к нему не стучусь не кидает ничего на линию? Поясни если можно поподробнее как осциллографом данные от компаса словить и что должно быть в идеале.
Сообщение отредактировал Kruftin - May 15 2012, 18:57
|
|
|
|
|
May 15 2012, 19:26
|

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

|
По коду в котором явно задается регистр TWBR: Код TWBR=0x11; // Bit rate TWSR=(0<<TWPS1)|(0<<TWPS0); // Setting prescalar bits // SCL freq= F_CPU/(16+2(TWBR).4^TWPS) Завтра пойду смотреть что осциллограф кажет. Так питание я включил, контроллер прошил, затем мне опять питание отключить и включить как я понимаю. Ладно зациклю посылку адреса или посылку значения в регистр(0х5А тоже тогда нельзя).
Сообщение отредактировал Kruftin - May 15 2012, 19:41
|
|
|
|
|
May 17 2012, 18:34
|

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

|
На данный момент все проверки проходят по даташиту как часы, однако от компаса получаю старший байт 0xFF, младший байт 0x00 и так для всех координат (x,y,z). Похоже надо поразбираться с даташитом компаса или компас нерабочий в плане расчетов координат. Даташит на компас прилагаю.
Сообщение отредактировал Kruftin - May 18 2012, 04:58
|
|
|
|
|
May 18 2012, 15:07
|

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

|
Цитата(Kruftin @ May 17 2012, 22:34)  На данный момент все проверки проходят по даташиту как часы, однако от компаса получаю старший байт 0xFF, младший байт 0x00 и так для всех координат (x,y,z). Похоже надо поразбираться с даташитом компаса или компас нерабочий в плане расчетов координат. Может для начала откалибровать. У меня например в машине , надо задать своё положение (начальную точку- занести начальные координаты в регистр) и сделать круг на машине . Вот тогда показывает все стороны света. У него появляется от чего плясать , а в Вашем они есть. Помоему на их сайте есть applicattion по калибровке компасов.
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
May 20 2012, 13:09
|

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

|
Цитата(_Артём_ @ May 20 2012, 00:05)  При выключении калибровка не теряется? Почему же их тогда на заводе настроить нельзя? Не знаю . Но вот так написано в инструкции по калибровке компаса. Не теряется , если только аккум не снять , повидимому в EEPROM не пишут Код Не ну какие-то данные он должен сразу скинуть, даже если он на месте стоит. А он кидает FF и 00, значит компас глючит Для какого полушария данные он должен скинуть , для южного или северного?
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
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 тогда оживут
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
May 23 2012, 11:45
|

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

|
Дак и LSB меняются, усиление меняешь дак они сильнее меняются. Надо вообщем прочитать про калибровку. Ну получается был глюк с продвижением указателя по регистрам, хотя может так и надо к каждому регистру по отдельности обращаться. Вот рабочий код. А еще как мне тип дабл по уарту передать(по уарту я могу передать 8 бит максимум)? Я же получу градусы по следующей формуле: angle= atan(y/x)* (180 / 3.14159265) +180; // angle in degrees где x = xl|xh << 8 y = yl|yh << 8 Это получится мне нужно градусы передать как два байта за раз, поскольку я сливаю старший и младший байты?
Сообщение отредактировал Kruftin - May 23 2012, 12:16
|
|
|
|
|
May 23 2012, 16:53
|

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

|
Вот нашел пример преобразования. Только надо чтобы число был в один байт. Вопрос в том получится(уместится) ли значение angle в один байт. У меня же angle меняется от 0 до 360 даже если я к целому преобразую, а в один байт влазит до 255
Сообщение отредактировал Kruftin - May 23 2012, 17:18
Эскизы прикрепленных изображений
|
|
|
|
|
May 23 2012, 18:49
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(Kruftin @ May 23 2012, 19:53)  Вот нашел пример преобразования. Мутный пример какой-то. Цитата(Kruftin @ May 23 2012, 19:53)  Вот нашел пример преобразования. Только надо чтобы число был в один байт. Ну 360 не вместится, разве что на 2 поделить. Пример Код void SendToUart(unsigned char new_byte) { // посылка в порт } #include <stdio.h>
void SendAngle(double angle) { unsigned short tmp=(unsigned short)Value; char Buf[20]; unsigned char l=sprintf(Buf,"Angle=%d\n\r", tmp); for (char i=0; i<l; i++) { SendToUart(Buf[i]); }
|
|
|
|
|
May 24 2012, 05:29
|

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

|
Т.е. в массиве Buf будут лежать десятичные цифры? Если число 180.52, то в Buf[0]=1 Buf[1] = 8 Buf[3] = . Buf[4] = 5? Если да, то это круто). Или просто число будет разбито по байтам? Спасибо огромное ILYAUL и Артем!!!  Не знаю что бы я без вас делал. Поехал сейчас компас покупать. Код отредактировал маленько: Код void SendAngle(float angle) { unsigned short tmp=(unsigned short)angle; //преобразуем угол в целое число char Buf[20]; //создаем массив unsigned char l=sprintf(Buf,"Angle=%d\n\r", tmp); //записываем в буфер значение угла по цифрам unsigned char i = 0; for (i=0; i<l; i++) { USART_SendChar(Buf[i]);//выводим все по уарту } }
Сообщение отредактировал Kruftin - May 24 2012, 07:57
Эскизы прикрепленных изображений
|
|
|
|
|
May 24 2012, 17:57
|

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

|
Так вот только формула для определения севера неверная походу, хотя написана тут http://www.seeedstudio.com/wiki/index.php?...s_Compass_v1.0bПо ней получается, что значения меняются от 180 до 268, учитывая что по даташиту значения регистров меняются от 0xF800 to 0x07FF получается по формуле xv = xh << 8|xl; yv = zh << 8|zl; angle = atan2(yv,xv)*(180/3.14)+180; имеем от 180 до 268 значения угла. В даташите вот ни слова нету как вычислить угол. Но компас вроде как верно работает. Хотя если считать как angle = atan2(yv,xv) то можно получать значения от 0 до 90 со странные перескоками с 30 на 60 и т.д. Поскольку нету отрицательных значений. Режим postive и negative bias как я понял для самотестирования. Сделать компас под выдачу нормальных данных так и не удалось и в даташите про расчет углов ничего вроде как нету. Смотрел пример расчета и калибровки для ардуино, так вот чето не все понял. Мда столько времени на него потратил, а он самый последний шаг сделать не получается. Код для ардуино приложил.
Сообщение отредактировал Kruftin - May 25 2012, 12:45
|
|
|
|
|
May 31 2012, 13:06
|

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

|
Мда, на данный момент я получаю правдивые значения углов в диапазоне от 0 до 270 градусов, в оставшемся компас выдает скачущие и неверные данные. Правдивыми являются данные angle от 0 до -135, это результат atan2(yv,xv)*180/pi, где xv = (xh << 8)|xl; yv = (yh << 8)|yl; Причем относительно реального севера нулевая отметка смещена градусов на 30, но это не проблема, главное что изменение градусов он показывает верно(правда надо умножить значение на 2) но только в диапазоне от 0 до 270 градусов. Похоже это баг компаса моего, либо надо поиграть усилением, но ведь на 75% значений при вращении оно не влияет. Код на сегодня приложил. P.S. Хотя судя по примеру для ардуино я должен получать сразу значение от - 180 до 180, не умножая на два.
|
|
|
|
|
Apr 14 2013, 20:31
|
Участник

Группа: Участник
Сообщений: 68
Регистрация: 24-10-10
Из: Minsk
Пользователь №: 60 382

|
А кто знает, как смещение по Z координате корректировать?
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|