COKPOWEHEU Опубликовано 15 марта, 2019 Поделиться Опубликовано 15 марта, 2019 Решил разобраться с модулем компаса GY-271 - одним из немногих модулей, которые вообще сумел найти. Пол-интернета заполнены утверждениями что собран данный модуль на микросхеме HMC5883L, которая общается по I2C и отзывается на адрес 0x1E (соответственно, 0x3C/0x3D для записи и чтения). На практике же посылка этого адреса натыкалась на глухой таймаут, мол знать не знаем такого адреса, и вообще мы не оно. Целенаправленные, но больше случайные поиски по интернету дали наводку что данное чудо техники, возможно, отзовется на адрес 0x0D (0x1A/0x1B для записи и чтения) и действительно, по такому адресу удалось добиться ответа, правда не совсем того, что ожидалось. К примеру, без "шаманской" (опять же, советы из "Всезнающего") записи единицы по адресу 9, ответ был нулевым. Потом более-менее осмысленные данные появились, но не с адреса 0x03, как положено по даташиту, а вовсе даже с 0x00. Очередная случайная находка дала направление, что заботливые китайцы запаяли на плату не HMC5883L, а вовсе даже QMC5883L - совсем другую микросхему с другими регистрами. И вот она действительно похожа по настройкам и адресу. Стал бы я создавать тему, если бы все было так хорошо... Хотя ответ от микросхемы и есть, как-то он слабо похож на нормальные данные. Теоретически, в регистрах 1:0, 3:2, 5:4 должны быть проекции магнитного поля на оси X, Y, Z. То есть вдали от магнитов и массивных железяк, геометрическая сумма значений должны быть примерно 0.5 Гс, то есть ~32000 единиц модуля, причем пока модуль лежит на столе, сильно меняться значениям не с чего. Привожу лог снятых данных (во вложении исходный код прошивки: вся работа с периферией идет руками, без автоконфигураторов и тому подобного). За все время съема этого лога модель лежал на столе в одном положении, но данные по осям скачут достаточно произвольным образом. I2C test FB FF 0A 00 14 00 00 A8 F5 0D 00 01 01 00 Write 0F 00 05 00 F1 FF 04 99 F5 | 15 5 -15 2337 FB FF 00 00 05 00 00 9A F5 | -5 0 5 2338 0F 00 05 00 00 00 00 8F F5 | 15 5 0 2327 E2 FF 00 00 F6 FF 00 93 F5 | -30 0 -10 2331 28 00 F6 FF FB FF 00 90 F5 | 40 -10 -5 2328 05 00 FB FF FB FF 00 99 F5 | 5 -5 -5 2337 00 00 00 00 00 00 00 97 F5 | 0 0 0 2335 00 00 0F 00 D6 FF 00 99 F5 | 0 15 -42 2337 32 00 E2 FF 00 00 00 94 F5 | 50 -30 0 2332 E7 FF EC FF 00 00 00 97 F5 | -25 -20 0 2335 05 00 F6 FF 00 00 04 92 F5 | 5 -10 0 2330 Продублирую код чтения регистра (насколько я знаю, он довольно типичный, но мало ли...). Естественно, код писался в первую очередь под конкретную задачу - оптимизация будет потом, если оно вообще заработает. void I2C_Read(uint8_t device, uint8_t addr, uint8_t *buf, uint8_t count){ //start I2C2->CR1 |= I2C_CR1_START; while(!(I2C2->SR1 & I2C_SR1_SB)){} (void) I2C2->SR1; //device I2C2->DR = (device<<1) &~(1<<0); while(!(I2C2->SR1 & I2C_SR1_ADDR)){} (void) I2C2->SR1; (void) I2C2->SR2; //addr I2C2->DR = addr; while(!(I2C2->SR1 & I2C_SR1_TXE)){} I2C2->CR1 |= I2C_CR1_STOP; //restart I2C2->CR1 |= I2C_CR1_START; while(!(I2C2->SR1 & I2C_SR1_SB)){} //device I2C2->DR = (device<<1) | (1<<0); while(!(I2C2->SR1 & I2C_SR1_ADDR)){} (void) I2C2->SR1; (void) I2C2->SR2; //data for(uint8_t i=0; i<count-1; i++){ //I2C2->CR1 &=~ I2C_CR1_ACK; I2C2->CR1 |= I2C_CR1_ACK; while(!(I2C2->SR1 & I2C_SR1_RXNE)){} buf[i] = I2C2->DR; } I2C2->CR1 &=~I2C_CR1_ACK; while(!(I2C2->SR1 & I2C_SR1_RXNE)){} buf[count-1] = I2C2->DR; //stop I2C2->CR1 |= I2C_CR1_STOP; } #define QMC5883L 0x0D I2C_Read(QMC5883L, 0, data, 14); for(uint8_t i=0; i<14; i++){ UART_HEX(data[i]); UART_putc(USART, ' '); } data[0] = 0x80; I2C_Write(QMC5883L, 10, data, 1); data[0] = 0x01; I2C_Write(QMC5883L, 0x0B, data, 1); data[0] = (0b00<<6) | (0b00<<4) | (0b11<<2) | (0b01<<0); //oversampling = 512 //range = 2 G //ODR = 200 Hz //mode = continuous I2C_Write(QMC5883L, 9, data, 1); UART_puts(USART, "Write\x0d\n"); while(1){ I2C_Read(QMC5883L, 0, data, 9); for(uint8_t i=0; i<9; i++){ UART_HEX(data[i]); UART_putc(USART, ' '); } i16a x,y,z,t; x.u8val[0] = data[0]; x.u8val[1] = data[1]; y.u8val[0] = data[2]; y.u8val[1] = data[3]; z.u8val[0] = data[4]; z.u8val[1] = data[5]; t.u8val[0] = data[7]; t.u8val[1] = data[8]; t.ival += 3000+2000; sprintf(str,"| %i %i %i %i", x.ival, y.ival, z.ival, t.ival); UART_puts(USART, str); Собственно, вопрос: что я делаю не так и как сделать так, чтобы модуль отдавал правильные данные магнитного поля? compass.rar 0 Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз. Часть моих наработок. Ссылка на комментарий Поделиться на другие сайты Поделиться
AVI-crak Home Опубликовано 15 марта, 2019 Поделиться Опубликовано 15 марта, 2019 Там проблема с сохранением результатов измерений, если не успеть забрать - портятся. Есть два варианта: Читать статус в режиме нонстоп , и быть привязанным к тактовому генератору компаса (там +- лапоть). Или запускать однократное измерение по таймеру мк (событие - чтение значений - новый запуск). 0 RtoS Ссылка на комментарий Поделиться на другие сайты Поделиться
20% скидка на весь каталог электронных компонентов в ТМ Электроникс!Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!Перейти на страницу акции Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849
COKPOWEHEU Опубликовано 16 марта, 2019 Автор Поделиться Опубликовано 16 марта, 2019 Добавил ожидание флага DRDY (сначала он возникает вместе с флагом DOR), считываю регистры, потом снова дожидаюсь бита DRDY: while(1){ ... do{ I2C_Read(QMC5883L, 6, &data[6], 1); }while(!(data[6] & 1)); UART_HEX(data[6]); UART_putc(USART, ' '); I2C_Read(QMC5883L, 0, data, 6); UART_HEX(data[0]); UART_putc(USART, ' '); do{ I2C_Read(QMC5883L, 6, &data[6], 1); }while(!(data[6] & 1)); UART_HEX(data[6]); UART_putc(USART, ' '); I2C_Read(QMC5883L, 0, &data[1], 6); ... } Особой разницы нет: 05 00 01 00 05 00 14 00 F1 FF 00 F5 | 1280 5120 -3840 2184 05 BD 01 BD DD FF 00 00 FB FF 00 F5 | -8771 255 -1280 2184 05 14 01 14 23 00 0F 00 1E 00 00 F5 | 8980 3840 7680 2184 05 00 01 00 F6 FF 0F 00 F6 FF 00 F5 | -2560 4095 -2560 2184 05 00 01 00 00 00 00 00 D1 FF 00 F5 | 0 0 -12032 2184 05 14 01 14 DD FF 2D 00 1E 00 00 F5 | -8940 11775 7680 2184 здесь первый байт - считанный регистр 0x06 с битами DRDY+DOR, потом 0-й регистр (считываются-то все, но отображается только он), потом еще раз 6-й регистр (теперь видно, что выставлен только бит DRDY, то есть данные вроде как готовы). Потом считываю данные, но модуль опять выдает непонятно что. Если запускать одиночные преобразования - как это делать? В даташите алгоритма или подходящих регистров не нашел. 0 Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз. Часть моих наработок. Ссылка на комментарий Поделиться на другие сайты Поделиться
Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторовОбязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей. Подробнее>>Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161
AVI-crak Home Опубликовано 16 марта, 2019 Поделиться Опубликовано 16 марта, 2019 Я кажется спутал QMC5883L с другим датчиком, у которого был одиночный режим. Сейчас покопался в своём бардаке, оказывается я его нагло сбрасывал на перемагничивание (калибровку) , и читал по внешнему таймеру. Кстати, у этого датчика есть неприятный глюк - он помнит магнитное поле если оно превышало определённый порог. То-есть если поднести магнитик - то значения магнитного поля не спадают. Мягкий сброс очищает эту память. У датчика на макетке из китая есть стаб 3,3в, он полезен когда внешнее питание 5в. Но при питании от 3,3в - на стабе будут пульсации. Резисторы которые стоят на шине - мне китайцы поставили по 100к, перепаял на 1к. Ну и самое простое, когда датчик используется на собственной ПП: под ним должен быть массивный полигон, чем больше -тем лучше. Не, датчик не греется, но зато идеально ловит 50герц наводку от сети. 0 RtoS Ссылка на комментарий Поделиться на другие сайты Поделиться
COKPOWEHEU Опубликовано 16 марта, 2019 Автор Поделиться Опубликовано 16 марта, 2019 6 часов назад, AVI-crak Home сказал: Мягкий сброс очищает эту память. мягкий сброс у меня есть, перед бесконечным циклом. Но это ни на что не влияет, даже на первое измерение. 6 часов назад, AVI-crak Home сказал: У датчика на макетке из китая есть стаб 3,3в, он полезен когда внешнее питание 5в. Но при питании от 3,3в - на стабе будут пульсации. Резисторы которые стоят на шине - мне китайцы поставили по 100к, перепаял на 1к. То есть советуете запитать сам модуль от 5 В и проверить резисторы подтяжки? Попробую, хотя раз проблем с обменом нет, вряд ли дело в резисторах. 6 часов назад, AVI-crak Home сказал: Ну и самое простое, когда датчик используется на собственной ПП: Нет, используется готовый модуль GY-271. Перепаивать буду если заработает, но пока до этого далеко В любом случае спасибо за предупреждение. 6 часов назад, AVI-crak Home сказал: Сейчас покопался в своём бардаке, оказывается я его нагло сбрасывал на перемагничивание (калибровку) , и читал по внешнему таймеру. Может, поделитесь кодом? 0 Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз. Часть моих наработок. Ссылка на комментарий Поделиться на другие сайты Поделиться
COKPOWEHEU Опубликовано 17 марта, 2019 Автор Поделиться Опубликовано 17 марта, 2019 Проверил резисторы. Оказалось 2.2к. Вроде нормальные. Попробовал подать на модуль пятивольтовое питание - без изменений. 0 Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз. Часть моих наработок. Ссылка на комментарий Поделиться на другие сайты Поделиться
AVI-crak Home Опубликовано 17 марта, 2019 Поделиться Опубликовано 17 марта, 2019 Скрытый текст i2xdata.data[0] = 0x00; /// adres_reg - 1 i2xdata.read_write = 1; i2xdata.nBytes = 1; i2c_RW_master(); i2xdata.read_write = 0; i2xdata.nBytes = 9; i2xdata.read_write = 0; i2c_RW_master(); i2xdata.Sdata[0] = i2xdata.data[0]; i2xdata.Sdata[0] |= i2xdata.data[1] <<8; // i2xdata.Sdata[0] += 998; i2xdata.Sdata[1] = i2xdata.data[2]; i2xdata.Sdata[1] |= i2xdata.data[3] <<8; // i2xdata.Sdata[1] += 63; i2xdata.Sdata[2] = i2xdata.data[4]; i2xdata.Sdata[2] |= i2xdata.data[5] <<8; // i2xdata.Sdata[2] -= 40; i2xdata.Sdata[3] = i2xdata.data[7]; i2xdata.Sdata[3] |= i2xdata.data[8] << 8; Проблема в том что HMC5883L был первым датчиком что я хотел подружить с stm. Непонимание того как работает протокол шины и аппаратная часть мк - дало очень забавного уродца. Массив i2xdata.data - это то что я записывал или читал из чипа. Запуск чипа делался до победного конца, пока его не отпустит. Для HMC5883L есть режим залипания, когда он позволяет только читать свои регистры, и больше ни на что не реагирует. То-есть в случае сброса всей системы - вполне возможно получить ситуацию когда данные прочитались частично, а датчик не имеет аппаратного сброса. Скрытый текст volatile struct _i2xdata { uint8_t adres_mx; uint8_t nBytes; uint8_t read_write; ///0-1 uint8_t status; uint8_t data[10]; int16_t Sdata[4]; float Sdata2[4]; }i2xdata; ---------------- i2xdata.adres_mx = 0x0d; do { i2xdata.status = 0; i2xdata.adres_mx = 0x0d; i2xdata.data[0] = 0x0a; i2xdata.data[1] = 0x80; i2xdata.read_write = 1; i2xdata.nBytes = 2; i2c_RW_master(); sDelay_mc(50); i2xdata.data[0] = 0x0B; /// adres_reg - 1 i2xdata.data[1] = 1; /// demagnetization i2xdata.read_write = 1; i2xdata.nBytes = 2; i2c_RW_master(); sDelay_mc(10); i2xdata.data[0] = 0x09; /// adres_reg - 1 i2xdata.data[1] = 0x1; i2xdata.read_write = 1; i2xdata.nBytes = 2; i2c_RW_master(); } while (i2xdata.status); 0 RtoS Ссылка на комментарий Поделиться на другие сайты Поделиться
COKPOWEHEU Опубликовано 18 марта, 2019 Автор Поделиться Опубликовано 18 марта, 2019 @AVI-crak Home , спасибо, код посмотрел, но вряд ли поможет. HappyEnd: Раздобыл Ардуину и нашел несколько разных скетчей для нее (с I2C под stm32 работаю впервые, все же мог накосячить). Даже прогрел строительным феном (вдруг какой контакт не пропаялся). Ничего не меняется: коннект прекрасный, I2C работает замечательно, даже температура считывается, а вот вместо магнитного поля рандомное дерганье. Значит, скорее всего, просто датчик бракованный попался. Тут ничего не поделаешь, буду искать другой. 0 Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз. Часть моих наработок. Ссылка на комментарий Поделиться на другие сайты Поделиться
ARV Опубликовано 18 марта, 2019 Поделиться Опубликовано 18 марта, 2019 Может, на него окружающие магнитные поля действуют? 0 Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют... Ссылка на комментарий Поделиться на другие сайты Поделиться
COKPOWEHEU Опубликовано 19 марта, 2019 Автор Поделиться Опубликовано 19 марта, 2019 Кусок лога данных я выкладывал, все время измерения модуль просто лежал на столе, без движения. Даже если мусорное магнитное поле есть, оно должно складываться с полем Земли, то есть должно быть колебание в районе 8000, а вовсе не +/- 50. Поднесение магнита и повороты датчика тоже не дают видимого эффекта 0 Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз. Часть моих наработок. Ссылка на комментарий Поделиться на другие сайты Поделиться
AVI-crak Home Опубликовано 19 марта, 2019 Поделиться Опубликовано 19 марта, 2019 В запись цикле: адрес 0x0d, регистр назначения 0x0a, данные 0x80, ждём 10-50мс. адрес 0x0d, регистр назначения 0x0B, данные 0x01, ждём 10-50мс. адрес 0x0d, регистр назначения 0x09, данные 0x01. До тех пор пока его не отпустит. Датчик очень чувствительно реагирует на паузы между командами, по этому лишнего кода там быть не должно. 0 RtoS Ссылка на комментарий Поделиться на другие сайты Поделиться
COKPOWEHEU Опубликовано 19 марта, 2019 Автор Поделиться Опубликовано 19 марта, 2019 Мой код в первом посте, все это я делал. Запись в 0x0B даже уменьшает разброс "показаний". Хуже всего что чужой код дает ровно те же результаты, хотя там народ отписывался что "работает прекрасно". Да и по моему коду видно, что проблемы с I2C нет, микросхема отвечает, на запись в регистры реагирует, даже выдает что-то, что считает данными. 0 Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз. Часть моих наработок. Ссылка на комментарий Поделиться на другие сайты Поделиться
AVI-crak Home Опубликовано 19 марта, 2019 Поделиться Опубликовано 19 марта, 2019 В том и есть весь прикол, что заставить адекватно реагировать QMC5883L - достаточно трудно. Это не память, которую можно читать вдоль и поперёк, это отдельный процессор с программным I2C. На обращения к регистрам есть небольшие окна - в которые нужно попасть. А потом он начнёт оцифровывать датчики, и в этот момент его трогать нельзя, иначе получится каша. 0 RtoS Ссылка на комментарий Поделиться на другие сайты Поделиться
MasterElectric Опубликовано 19 марта, 2019 Поделиться Опубликовано 19 марта, 2019 Тогда это шлак а не нормальный датчик. 0 Ссылка на комментарий Поделиться на другие сайты Поделиться
COKPOWEHEU Опубликовано 19 марта, 2019 Автор Поделиться Опубликовано 19 марта, 2019 @AVI-crak Home еще раз: я дожидаюсь, когда взведется флаг, никакой разницы нет. Я проверял на готовом коде и готовом железе, где, по уверениям народа, это работает. Более того, народ хвалит датчик, говорит что он менее шумящий, чем HMC5883. И я прекрасно знаю, как выглядят подобные обвинения "компилятор виноват, контроллер неисправен" когда на самом деле у автора руки кривые. И именно ради этого я искал Ардуину и готовые чужие скетчи, да и по косвенным признакам не вижу других объяснений. Лучшей проверкой было бы найти другой модуль или микросхему (уж развести под него плату не проблема) и проверить на нем, но у меня его под рукой нет. Хотя если в Москве, а лучше в Щелково или рядом, найдется человек, готовый одолжить аналогичный модуль на пару минут, можно проверить и так. 0 Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз. Часть моих наработок. Ссылка на комментарий Поделиться на другие сайты Поделиться
COKPOWEHEU Опубликовано 2 апреля, 2019 Автор Поделиться Опубликовано 2 апреля, 2019 Happy end. Сегодня зашел туда же, где покупал модуль и попросил другой для тестирования. С собой захватил и предыдущего пациента и платку для тестирования. К моему удивлению продавец без вопросов распаковал другой модуль и позволил ткнуть в адскую конструкцию, заляпанную местами суперклеем. Как и предполагалось, свежий модуль заработал нормально (что интересно, он был сделан на том же чипе QMC). А тот пациент, который мой, работать как не хотел, так и не стал. Но что еще удивительнее - продавец был готов бесплатно поменять мой модуль на рабочий. Если бы я над своим не успел поиздеваться (пайка, прогрев феном). Естественно, меня это не расстроило. Так что все в порядке, с живыми QMC5883 я работать умею, а вот с мертвыми пока нет. Есть к чему стремиться! 0 Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз. Часть моих наработок. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.