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

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? кто мешает нормально делить и перемножать числа как и указано в даташите? Сами себе проблемы ищете.

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

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

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

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

oleg70
Drinker:

с такими операцыями типа <<8 и >>23

В моем случае деление на число=2^23 дает тот же результат…

djdron:

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

К сожалению, Андрей, не прошло и так…
Тут я понял однозначно: компиллер отказывается (?) понимать беззнаковые переменные при операциях деления или сдвига вправо, … он их считает знаковыми, независимо от непосредственного указания типа…
Хотя на сам тип реагирует - “warning”, если ему подсунуть uint16_t на проверку на “<0”…

djdron

не знаю что может быть с кейлом, вроде не должно быть такого, сам пишу в иаре, попробовал в иаре все работает:
unsigned short int C5 = 33464;
unsigned short int C6 = 28312;
unsigned int D2 = 16777215;
signed int dT = D2 - ((unsigned int)C5<<8);
signed int TEMP = 2000 + (((long long)dT*C6)>>23);
под ARM пишете?

Drinker
oleg70:

MS_temper=((int64_t)dT*28312)>>23; MS_temper выходит -131, хотя должно быть 5…

MS_temper ранее был объявлен как int32_t …почему он вдруг должен стать int64_t ?
И наверное MS_temper = 2000+dT*C6/2^23; Не?

oleg70
djdron:

не знаю что может быть с кейлом

Тут, скорее всего, ключ какой то нужен для компиллера, или еще какая “магия”…
Был удивлен, но : пишу
uint32_t K=57438; при компиляции он мне:
<main.c(78): warning: #68-D: integer conversion resulted in a change of sign>
т.е. он мне “великодушно” решил преобразовать беззнаковую в константу в знаковую (увидел старший бит)…
Не скажу что я программист, STM32 недавно только освоил, но ранее как то не сталкивался с этим (заморочки)…

Drinker:

почему он вдруг должен стать int64_t

произведение двух переменных в скобках больше 32-х разрядов, а они мне все нужны 😃