Создание собственной системы стабилизации
Вполне, но зараза в пиках до 45гр греется, да Алексей писал что тормоза на авр бывают 😦
да у меня что-то rc5 что-ли даже не помню, раз когда аксель калибровал через терминал - версия видна была, короче три дня назад сдёрнут git, а ну да ещё на трёхе секас аксель калибровать - ставил на край стола на лыжу боком и держал так примерно перпендикулярно столу ну т.д.
Вполне, но зараза в пиках до 45гр греется
ну так этож фигня! что такое 45 град для чипов, т.е. полупроводников… т.е. считай холодный… 😃
или для stm32 это уже много? лень в даташит лезть 😃
Вобщем смотрим обсуждаем:
Спасибо,Сергей! Основа работает! ГПС и тд пляшут от ровного горизонта, т.е. при наличии погоды всё будет нормально.
потом залил свою прошиву и стабильность вернулась…
Саш, тут важна РЕГУЛЯРНОСТЬ чтения акселя, если она превосходит бирейт, т.е. БЕЗ пропусков отсчётов, то нормально. В противном случае будет ловить случайное отклонение от вектора G. PX4 (ну и F4BY) должен читать 1000Гц отсчётов.
Видимо твоя прошыва больше усредняет, меньше влияния акселя на горизонт, возможно ПИДы ИНС завышены.
Кста, я тут к версии Ф3Дисковери МПУ6050 прикрутил ТОЛЬКО в качестве АКСЕЛЯ, похоже та же ситуация, но пока не разбирался.
ну и потом надо помнить что у тебя всеж F4, т.е. алгоритмика пашет без провалов по таймингам в лупе…
собсно об этом выше писал
Надо будет твою прошивку в baseflight допилить (если время будет) посмотреть как оно 😃
ставил на край стола на лыжу боком и держал так примерно перпендикулярно столу ну т.д.
А вот это для ИНС ОБЯЗАТЕЛЬНО!
Нужно для компенсации дрейфа акселя.
или для stm32 это уже много? лень в даташит лезть
не нестрашно, да и датчики отодвинуты от проца, на baseflight холодный был…
А вот это для ИНС ОБЯЗАТЕЛЬНО!
в следующий раз, даст бог, на квадрике на заводской раме калибровать буду 😃
Видимо твоя прошыва больше усредняет, меньше влияния акселя на горизонт, возможно ПИДы ИНС завышены.
ранее, когда мучил свою ИНС (а конкретно улучшайзер удержания позиции по гпс), так и не подобрал оптимальные коэф. соотношения аксель-гпс и отключил ее в итоге, хотя по графикам все ок было, т.е. в осях и знаках ошибок нет… уверен на 95% 😃 Теперь осознаю, что всеж надо было вибрации на платформе пофиксить сперва… иначе похоже никак. Для оси Z с инерциалкой попроще, т.к. для компенсации интеграторов используется быстрый и относительно точный (по сравнению с гпс) барометр. А вот для X,Y осей картинка другая, т.к. для повышения точности нужно больше доверия полагать на аксель (из-за того что гпс врет в большом диапазоне + тормозит по координатам на 1-2 сек), а тут уже вибрации выводят интеграторы из состояния равновесия… ну и да, для инерциалки по X,Y нужно калибровку шкал акселя по всем осям добавлять, что в арду 3.0.х и сделали на сколько помню… по Z необязательно, т.к. можно больше веры полагать на баро в компл. фильтре… т.е. баро устаканивает Z интегратор и по вибрациям и по нелинейностям шкалы акселя…
Кста, я тут к версии Ф3Дисковери МПУ6050 прикрутил ТОЛЬКО в качестве АКСЕЛЯ, похоже та же ситуация, но пока не разбирался.
а что за I2C драйвер использовал для F3? на сколько помню драйвер от F4 не подходит (хотя и то и то Cortex-M4) и там нужен какой то изврат или стороннюю либу пользовать…
а что за I2C драйвер использовал для F3? на сколько помню драйвер от F4 не подходит (хотя и то и то Cortex-M4) и там нужен какой то изврат или стороннюю либу пользовать…
не i2c практически одинаковы, есть мелкие нюансы, сводящиеся к настройке портов, по моему я больше ничего не переделывал, а на сколько понимаю то периферия в f3 больше похожа на f1 чем на f4?
Самое главное забыл. ВЫ МОЛОДЦЫ! 😃
Давно пора порвать всякие там не бюджетные PX4 и пиксхавки! Не останавливайтесь! 😃
А тут какбы обратной дороги нет уже 😃 я чё в попыхах запускал в небо всё это дело - ибо уже надо 😃
Ставь 1600 733 8g с адресом по барабану если регистры разные, читаешь/пишешь всё равно адрес->регистр, должно переварится
Собственно сделал все как Вы посоветовали. Честно говоря нечем было снимать ролик кроме телефона,а он был в этот момент вибростендом.
Датчик приклеил к экрану обычным 2х сторонним скочем,поставил в режим вибровызова и позвонил))) С указанными Вами настройками по оси Z в гуевских попугаях прыгало в пределах 2х единиц,по осям X и Y в пределах 4-5ти единиц (телефон полз по столу в момент вибрации)
Делитель был подобран таким образом,что в крайних положениях он был 1G= 256
Компас так и не настроил. Что-то не могу разобраться какие Гауссы и частоту чтения надо выставлять?И что надо выбрать,хай или лоу резолюшн?
Да,датчик в Москве в дорогом магазине стоит 130руб,но по идее,можно взять по 60-70руб. Вроде как уже скоро должен придти и L3GD20,правда подозреваю что не тот,что в пиксхавке.
Я более склонен полагать, что у него возникает резонанс с вибрацией от моторов примерно на частоте 4-5 кГц т.е. как раз на середине газа…
Мы так и не услышали начальника транспортного цеха пока нет никаких данных не по iris не по его контроллеру pixhawk 😦
Я более склонен полагать, что у него возникает резонанс с вибрацией от моторов примерно на частоте 4-5 кГц т.е. как раз на середине газа…
Понял,тогда испытаю на коптере. Единственное,это будет мелколет на 3" пропеллерах.
ПС,есть что-то типа хубсана,сейчас попробую на него прилепить))
Я движки по акселю балансировал включал по одному с хомутом из стяжки и смотрел - хомут ворочал, потом снял колокольчики и на подшипниках повесил посмотреть - попал 😃
Ну,попробовал.По осям X и Y скачет в пределах 20-25 гуе-единиц,а вот по оси Z пипец,проседает единиц на 90.
Что интересно,прикрепленная сверху МПУ6050 показала по осям X и Y почти тот же разброс (фильтры в прошивке выключены),но по оси Z проседала не более чем на 40- 50 гуе-единиц.Испытания производились одновременно на 2х датчиках и 2х запущенных ГУИ.
Блин,извиняюсь,данные ошибочные.Не правильно сконфигурировал один из регистров и он видимо работал по умолчанию.Просто удивился,что при каждом включении приходилось делать калибровку.
Вообщем при тех настройках что были выше и при тех же условиях испытания.По оси X и Y разброс 5-6 гуе-единиц,по оси Z в пределах 3-4 гуе-единиц.
т.е. если сделать 1G = 512 так и будет как я и говорил, около 50 попугаев, так вот похоже фильтры MPU могут сгладить всё это, а в lsm нет, или же спектр другой, на мелколёте он повыше, так-же допускаю что аксель в 6000 лучше намного чем 6050, не думаю, что только из-за интерфейса они на столько разнятся в цене…
осталось увидеть iris не в рекламе, а у реальных пользователей…
ранее, когда мучил свою ИНС (а конкретно улучшайзер удержания позиции по гпс), так и не подобрал оптимальные коэф
а Вы не пробовали передавать показания акселя/гиры в сам жпс (ublox)?, хочю папробывать, и вот думаю может не сотит и ктото уже пробывал:)
Вы хотите сказать, что ublox поддерживает “ИНС-режим” и ему можно отдать сырые данные акселя и гиры?! первый раз такое слышу… в теории наверное это возможно, но в таком случае ublox прошива должна иметь такую опцию и данные гиры акселя должны быть каким либо образом нормализованы для подачи на вход… еще это оч. сомнительно, т.к. чипы в гпс модулях и так еле справляются с обсчетом координат на сколько знаю, а вы говорите про доп. обсчет ИНС… сомнительно это… разве что какие нить дорогие спец. модули…
т.е. если сделать 1G = 512 так и будет как я и говорил, около 50 попугаев
Ну да,по факту, если сделать 1G = 512, получается в районе 20 попугаев по оси X Y и в районе 15 по оси Z. Видимо МПУ6000 действительно супер-пупер,т.к 6050 показывает почти те же попугаи.Ну на самом деле,чего стоит ожидать от датчика за пару баксов)))
Вы хотите сказать, что ublox поддерживает “ИНС-режим” и ему можно отдать сырые данные акселя и гиры?!
тыкался с модулем, разбирался с настройками, и когда читал мануал, то мельком eвидел:
1.9 Automotive Dead Reckoning
Automotive Dead Reckoning (ADR) is u-blox’ industry proven off-the-shelf Dead Reckoning solution for tier-one
automotive customers. u-blox’ ADR solution combines GPS and sensor digital data using a tightly coupled
Kalman filter. This improves position accuracy during periods of no or degraded GPS signal.The NEO-6V provides ADR functionality over its software sensor interface. A variety of sensors (such as wheel
ticks and gyroscope) are supported, with the sensor data received via UBX messages from the application
processor. This allows for easy integration and a simple hardware interface, lowering costs. By using digital
sensor data available on the vehicle bus, hardware costs are minimized since no extra sensors are required for
Dead Reckoning functionality. ADR is designed for simple integration and easy configuration of different sensor
options (e.g. with or without gyroscope) and vehicle variants, and is completely self-calibrating.
вот думал стоит вникать и разбираться или нет, оно это или нет 😃
вот еще про “это” www.u-blox.com/en/dead-reckoning.html
Теперь осознаю, что всеж надо было вибрации на платформе пофиксить сперва… иначе похоже никак. Для оси Z с инерциалкой попроще, т.к. для компенсации интеграторов используется быстрый и относительно точный (по сравнению с гпс) барометр. А вот для X,Y осей картинка другая, т.к. для повышения точности нужно больше доверия полагать на аксель (из-за того что гпс врет в большом диапазоне + тормозит по координатам на 1-2 сек), а тут уже вибрации выводят интеграторы из состояния равновесия…
полностью согласен
ну и да, для инерциалки по X,Y нужно калибровку шкал акселя по всем осям добавлять, что в арду 3.0.х и сделали на сколько помню… по Z необязательно, т.к. можно больше веры полагать на баро в компл. фильтре… т.е. баро устаканивает Z интегратор и по вибрациям и по нелинейностям шкалы акселя…
Не знаю как в вие, но у меня допустим надо обязательно калибровку по всем осям, т.к. суммарный вектор ускорения по мировым Х,У легко может иметь не хилую проекцию на Z-ось акселя.
а что за I2C драйвер использовал для F3? на сколько помню драйвер от F4 не подходит (хотя и то и то Cortex-M4) и там нужен какой то изврат или стороннюю либу пользовать…
Использовал штатный СТшный драйвер от ЛСМ303 для настройки (т.е. записи в МПУ), и свой обработчик для чтения по прерываниям. Переписал нутексовый драйвер МПУ в Стшном стиле 😃
void Accel_Config(void)
{
MPU6000_InitTypeDef MPU6000_InitStruct;
LSM303DLHCAcc_InitTypeDef LSM303DLHCAcc_InitStructure;
/* необходимо для настройки интерфейса i2c */
LSM303DLHC_AccInit(&LSM303DLHCAcc_InitStructure);
/* настройка MPU6050 */
MPU6000_InitStruct.Reset = MPU6000_H_RESET;
MPU6000_InitStruct.PowerConf = MPU6000_CLK_SEL_PLLGYROZ;
MPU6000_InitStruct.StandbyConf = MPU6000_NO_STANDBY;
MPU6000_InitStruct.UserConf = MPU6000_NO_USER_CFG;
MPU6000_InitStruct.DataOutputRate = 50;
MPU6000_InitStruct.GyroFullScale = MPU6000_FS_2000DPS;
MPU6000_InitStruct.GyroLPFConf = MPU6000_DLPF_CFG_98HZ;
MPU6000_InitStruct.AccFullScale = MPU6000_AFS_8G;
MPU6000_InitStruct.AccHPFConf = MPU6000_NO_ACC_HPF_CNG;
MPU6000_InitStruct.InterruptConf = MPU6000_RAW_RDY_EN;
MPU6000_InitStruct.InterruptPinConf = MPU6000_INT_ANYRD_2CLEAR;
MPU6000_Init(&MPU6000_InitStruct);
}
вот тело читалки и2ц (Александр mahowik, я тебе вроде весь проект по Ф3 отправлял? там есть)
/* обработчик прерывания по событиям и буферу и2ц ИНС
внутренний адрес размещаем в buf[0]*/
void I2C_INS_ISR(void)
{
switch(i2c_sts) /* конечный автомат и2ц*/
{
case pustoy:
#ifdef MPU60x0_ACC
NVIC_EnableIRQ(MPU60x0_I2C_INT_EXTI_IRQn);
#else
NVIC_EnableIRQ(LSM303DLHC_I2C_INT1_EXTI_IRQn);
#endif
break;
case Sp: /* Stop */
/* Clear STOPF flag */
if (I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_STOPF) == SET){
/*сбросим флаги запросов прерываний */
I2C_ClearITPendingBit(LSM303DLHC_I2C,I2C_IT_STOPI);
I2C_ClearFlag(LSM303DLHC_I2C, I2C_ICR_STOPCF);
i2c_sts = pustoy;
/* здесь вызов метода-заполнителя данных объекта ИНС */
switch(i2c_DeviceAddr){
case MPU_I2C_ADDRESS:
case ACC_I2C_ADDRESS: AccDataRdy(); break;
/* чтение магнитометра */
case MAG_I2C_ADDRESS: MagmDataRdy(); break;
}
}
#ifdef MPU60x0_ACC
NVIC_EnableIRQ(MPU60x0_I2C_INT_EXTI_IRQn);
#else
NVIC_EnableIRQ(LSM303DLHC_I2C_INT1_EXTI_IRQn);
#endif
break;
case Ra: /* Start */
if (I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_TXIS) == RESET) break;
if(NumByteToRead>1)
i2c_RegAddr |= 0x80;
/* Send Register address */
I2C_SendData(LSM303DLHC_I2C, (uint8_t)i2c_RegAddr);
i2c_sts = Rs;
break;
case Rs: /* ожидание передачи адреса регистра для чтения */
if (I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_TC) == RESET) break;
/* формируем повторный старт*/
I2C_TransferHandling(LSM303DLHC_I2C, i2c_DeviceAddr, NumByteToRead, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
i2c_sts = Rd;
break;
case Rd: /* Чтение очередного байта */
if (I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_RXNE) == RESET) break;
if (NumByteToRead) {
AccMag_buf[AccMag_buf_inx++] = I2C_ReceiveData(LSM303DLHC_I2C);
if (--NumByteToRead==0) i2c_sts = Sp;
} else
i2c_sts = Sp;
break;
default: /* не понятное состояние = ошибка интерфейса */
/*сбросим интерфейс */
I2C_SoftwareResetCmd(LSM303DLHC_I2C);
/*сбросим флаги запросов прерываний */
I2C_ClearITPendingBit(LSM303DLHC_I2C, I2C_IT_TCI|I2C_IT_STOPI|I2C_IT_RXI|I2C_IT_TXI);
i2c_sts = pustoy;
break;
}
/* проверим выход указателя за пределы буфера */
if (AccMag_buf_inx > sizeof AccMag_buf)
AccMag_buf_inx = sizeof AccMag_buf;
/*сбросим флаги запросов прерываний */
I2C_ClearITPendingBit(LSM303DLHC_I2C, I2C_IT_TCI|I2C_IT_STOPI|I2C_IT_RXI|I2C_IT_TXI);
}
драйвера МПУ в архиве.
не i2c практически одинаковы, есть мелкие нюансы, сводящиеся к настройке портов, по моему я больше ничего не переделывал, а на сколько понимаю то периферия в f3 больше похожа на f1 чем на f4?
Нее, Сергей, Ф1 и Ф3 сильно разные. Как раз у Ф3 периферия, я думаю, наиболее продвинутая. А конкретно i2c интерфейс у Ф1 и Ф4 совершенно одинаковый, сам выполняет только отдельные операции на шине, т.е. Start, Stop и передача/приём байта, “пока не пнёшь не полетит” ). У Ф3 всё интересней, он сам поддерживает полный цикл обмена, от Start до Stop, в прерываниях только запрашивает, либо получает данные. Вот штатная функция от Ф3Дисковери:
/**
* @brief Writes one byte to the LSM303DLHC.
* @param DeviceAddr : specifies the slave address to be programmed.
* @param RegAddr : specifies the LSM303DLHC register to be written.
* @param pBuffer : pointer to the buffer containing the data to be written to the LSM303DLH.
* @retval LSM303DLHC Status
*/
uint16_t LSM303DLHC_Write(uint8_t DeviceAddr, uint8_t RegAddr, uint8_t* pBuffer)
{
/* Test on BUSY Flag */
LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
while(I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_BUSY) != RESET)
{
if((LSM303DLHC_Timeout--) == 0) return LSM303DLHC_TIMEOUT_UserCallback();
}
/* Configure slave address, nbytes, reload, end mode and start or stop generation */
I2C_TransferHandling(LSM303DLHC_I2C, DeviceAddr, 1, I2C_Reload_Mode, I2C_Generate_Start_Write);
/* Wait until TXIS flag is set */
LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
while(I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_TXIS) == RESET)
{
if((LSM303DLHC_Timeout--) == 0) return LSM303DLHC_TIMEOUT_UserCallback();
}
/* Send Register address */
I2C_SendData(LSM303DLHC_I2C, (uint8_t) RegAddr);
/* Wait until TCR flag is set */
LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
while(I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_TCR) == RESET)
{
if((LSM303DLHC_Timeout--) == 0) return LSM303DLHC_TIMEOUT_UserCallback();
}
/* Configure slave address, nbytes, reload, end mode and start or stop generation */
I2C_TransferHandling(LSM303DLHC_I2C, DeviceAddr, 1, I2C_AutoEnd_Mode, I2C_No_StartStop);
/* Wait until TXIS flag is set */
LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
while(I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_TXIS) == RESET)
{
if((LSM303DLHC_Timeout--) == 0) return LSM303DLHC_TIMEOUT_UserCallback();
}
/* Write data to TXDR */
I2C_SendData(LSM303DLHC_I2C, *pBuffer);
/* Wait until STOPF flag is set */
LSM303DLHC_Timeout = LSM303DLHC_LONG_TIMEOUT;
while(I2C_GetFlagStatus(LSM303DLHC_I2C, I2C_ISR_STOPF) == RESET)
{
if((LSM303DLHC_Timeout--) == 0) return LSM303DLHC_TIMEOUT_UserCallback();
}
/* Clear STOPF flag */
I2C_ClearFlag(LSM303DLHC_I2C, I2C_ICR_STOPCF);
return LSM303DLHC_OK;
}
т.е надо только вызвать функцию подготовки интерфейса I2C_TransferHandling(LSM303DLHC_I2C, DeviceAddr, 1, I2C_Reload_Mode, I2C_Generate_Start_Write), а дальше по флагу освобождения регистра передатчика I2C_ISR_TXIS подталкивать данные.