Создание собственной системы стабилизации

SergDoc

Есди ДУСы дают нам угловую скорость, а нам нужен угол - тут как бы только интегрирование 😃

rual
oleg70:

Хотелось бы поинтерqесоваться у искушенной публики: - что делают с сырыми данными акселя и гиры в разных открытых проектах перед подачей в алгоритм IMU ??
Сам посмотрел у AQ32 , вроде понятно, что сначала интегрируют их, потом усредняют и обсчет в IMU ведется с частотой 500 гц вроде…

Ничего не надо делать, подавайте сразу в алгоритм, нужно только правильно выбрать постоянную интегрирования.

oleg70
SergDoc:

тут как бы только интегрирование

Не, я не об этом… (это мне уже понятно 😃), в “чистом” виде я их уже подавал в своем предыдущем проекте, работало и так… , тут мысли возникают направить мощь STM на предварительную фильтрацию данных, и для оценки разных подходов (если таковые вообще есть) и спрашиваю…
Просто гляжу, судя по постам в теме, что знаний чужого кода у меня в разы меньше (а вернее нет) чем у других…

rual:

постоянную интегрирования.

Вот как раз это мне и интересно…
Сейчас суммарный обсчет положения сделал (благо MPU) 1000 Гц, разницы с предыдущим проектом 200 Гц субъективно не наблюдается, - мораль: а надо ли гнаться за частотой ? Может наоборот герц эдак 100 сделать ? (вот и вам и DLPF получится). Всеж хочется добиться в своем (хенд мэйд) проекте каких то результатов по качеству.
Кстати у MPU аксель, у меня, дает шум +/- 100 ед. при шкале 4G это нормально ?

mahowik
SergDoc:

видяху то ставит, а вот cuda ни в какую 😦

Накати сперва все обновления и все решится скорее всего…

Sir_Alex
oleg70:

Сейчас суммарный обсчет положения сделал (благо MPU) 1000 Гц, разницы с предыдущим проектом 200 Гц субъективно не наблюдается, - мораль: а надо ли гнаться за частотой ? Может наоборот герц эдак 100 сделать ? (вот и вам и DLPF получится). Всеж хочется добиться в своем (хенд мэйд) проекте каких то результатов по качеству. Кстати у MPU аксель, у меня, дает шум +/- 100 ед. при шкале 4G это нормально ?

MPU внутри работает на 1(8)КГц, а данные суммирует в зависимости от выходной частоты. Поэтому нету особой разницы где суммировать, на стороне CPU или MPU - результат один и тот же 😃

SergDoc
mahowik:

Накати сперва все обновления и все решится скорее всего…

Я уже бубунту с wine накатил 😃 - теперь и мои дела работают и сына 😃
блин такое желание старый контроллер разобрать и собрать новый - нее подожду деталек…

Drinker
Sir_Alex:

MPU внутри работает на 1(8)КГц, а данные суммирует в зависимости от выходной частоты. Поэтому нету особой разницы где суммировать, на стороне CPU или MPU - результат один и тот же

Привет! А что означает суммирование в мпу?

rual
oleg70:

тут мысли возникают направить мощь STM на предварительную фильтрацию данных

Смысла нет, лучше эту мощь в алгоритме использовать.

oleg70:

а надо ли гнаться за частотой ?

не надо, нет смыла задирать скорость выше скорости реакции приводов (серв, моторов и тп).

Drinker:

А что означает суммирование в мпу?

Вот это хз… но смысл такой, что ДУС там всегда работает на 1000Гц, а скорость выдачи данных, одновременно ДУС+аксель, получается делением на настраиваемый коэффициент K, дык вот за время dt = (к+1)/1000 отсчёты ДУС усредняются.

oleg70

Очередной затык, теперь с 5611, “пихаю” 24-х битное число (из трех uint8_t) в uint32_t так:

D1=(uint32_t)((b1<<24)|(b2<<16)|(b3<<8)); - // по моему не правильно, но работает…
или
D1=(uint32_t)((b1<<16)|(b2<<8)|b3); -// по моему правильно но результат - не тот…

Где я туплю ??

oleg70
Alexey_1811:

Правильно так:
D2=(uint32_t)((b1<<16)|(b2<<8)|b3);

Я тоже так думаю, но после нехитрых вычислений далее (расчет температуры 5611 по даташиту):
dT=(int32_t)(D2 -C5*256);
MS_temper=2000 + dT*C6/8388608;
, нужный результат почему то получается именно при “неправильном” способе присвоения…

SergDoc

если про это


static uint32_t ms5611_read_adc(void)
{
    uint8_t rxbuf[3];
    i2cRead(MS5611_ADDR, CMD_ADC_READ, 3, rxbuf); // read ADC
    return (rxbuf[0] << 16) | (rxbuf[1] << 8) | rxbuf[2];
}

`  int64_t dT = ms5611_ut - ((int32_t)ms5611_c[5] << 8);
    int64_t off = ((uint32_t)ms5611_c[2] << 16) + ((dT * ms5611_c[4]) >> 7);
    int64_t sens = ((uint32_t)ms5611_c[1] << 15) + ((dT * ms5611_c[3]) >> 8);
    temp = 2000 + ((dT * ms5611_c[6]) >> 23);

драйвера есть все в открытом доступе, тут даже смысла не вижу изобретать?

oleg70
SergDoc:

тут даже смысла не вижу изобретать

Сам не хотел изобретать, сначала взял готовый кусок кода, но фиг там … Похоже надо с компилятором повнимательней разобраться (с указанием типов), где то переполнение вылазит., так что “скопипастить” не получилось…

oleg70

Мда… Все ж компиллер как то теряет знаковый тип при сдвиге (делении) больших чисел, отсюда и косяк у меня,…
Не было печали…
Keil вроде с оффсайта качал, правда он с ограничениями… (не в этом ли дело?)…

djdron
oleg70:

Мда… Все ж компиллер как то теряет знаковый тип при сдвиге (делении) больших чисел, отсюда и косяк у меня,…
Не было печали…
Keil вроде с оффсайта качал, правда он с ограничениями… (не в этом ли дело?)…

кейл с ограничениями тут не причем, компилятор “считает” с права налево и выполняет действия согласно приоритетам операций. Может он что то не то сначала вычисляет.
эти формулы не правильно считаются?
dT=(int32_t)(D2 -C5*256);
MS_temper=2000 + dT*C6/8388608;
покажите кусок кода и какие типы переменных используются.

oleg70
djdron:

покажите кусок кода

Вот переменные:
int32_t dT,MS_temper;
uint32_t D2;
uint16_t C5,C6;

Вот расчет:
dT=D2 - (uint32_t)C5<<8; //( dT здесь получается 1700, проверял)
MS_temper=((int64_t)dT*28312)>>23;

MS_temper выходит -131, хотя должно быть 5…

Если пишу прям так: MS_temper=(1700*28312)>>23;
или присваиваю ранее dT=1700; - то как раз 5 и выходит…
Такое ощущение что c типом int64_t что то не так…

djdron

при умножении вылазит за 32 бита, попробуйте заменить на double, если заработает посмотрите как определен тип int64.
Возможно int64 определен как long, а компилятор его считает 32 битным, вспомнил (long long) 64 бита целочисленное.

oleg70
djdron:

Возможно int64 определен как long

Да, спасибо Вам за наводку, похоже где то здесь косяк… (первый признак, проверенные примеры из инета не работают…) буду копать.

djdron

Если “быстро” поправить то можно написать:
MS_temper=((long long)dT*28312)>>23;

Drinker

Камрады, а зачем вы геммороитесь с такими операцыями типа <<8 и >>23? кто мешает нормально делить и перемножать числа как и указано в даташите? Сами себе проблемы ищете.

Или наносекунды экономите?

это касается и возведения в степень

заранее двойку в степень возведите и усе

djdron
oleg70:

Вот расчет:
dT=D2 - (uint32_t)C5<<8; //( dT здесь получается 1700, проверял)

вот здесь еще косяк, не хватает скобочек:
dT=D2 - ((uint32_t)C5<<8);

Drinker:

Камрады, а зачем вы геммороитесь с такими операцыями типа <<8 и >>23? кто мешает нормально делить и перемножать числа как и указано в даташите? Сами себе проблемы ищете.

Или наносекунды экономите?

это касается и возведения в степень

заранее двойку в степень возведите и усе

можно и без << >>, просто это пример из интернета, вот его и разбирали почему не работает