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

SergDoc

И так, пока проблемы две:
Таймеры заняты шимами - опрос гир и акселя придётся проводить поллингом;
Акселерометр - прыгает( 0-255) скорей всего попадаю на перезапись

SergDoc

Дошло наконец, 0 = 255 данные акселерометра представляются так положительное ускорение от 0 до 255 а отрицательное от 255 до 0, или наоборот ещё толком не понял щас проблема, как это представить да ещё без ошибок ибо одинаковые значения и в плюсе и в минусе могут быть, для примера Z= 55 в горизонтальном лежачем положении (ускорение свободного падения) переворачиваем плату получаем 200 - резко дёргаем вверх (низом к верху) получаем опять 55 - ну и в какую сторону летим блин…

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

или пока сделать например 128 - 0 отрицательное 0 - 126 -положительное а как же, большие ускорения

смотреть в гироскоп какой угол? а если гира в 0 - смещение по оси без крена или неуспел гироскоп уже не показывает угловую скорость?

вроде понял в мультивийной прошивке - I2C Accelerometer ADXL345 также работает только адресация регистров другая буду пробовать…

ivereninov

С гироскопов снимаем угловую скорость, пересчитываем по формуле omega=U*gain+bias , интегрируем для получения угла. Трехосевой акселерометр позволяет определять положение с точностью до поворота вокруг вектора .Кладем на горизонтальную поверхность , по оси Z Датчик должен мерить g, по остальным нули.По степени вхождения g в оси x y можно определить крен и тангаж при отсутствии линейных ускорений.

SergDoc
ivereninov:

С гироскопов снимаем угловую скорость, пересчитываем по формуле omega=U*gain+bias , интегрируем для получения угла. Трехосевой акселерометр позволяет определять положение с точностью до поворота вокруг вектора .Кладем на горизонтальную поверхность , по оси Z Датчик должен мерить g, по остальным нули.По степени вхождения g в оси x y можно определить крен и тангаж при отсутствии линейных ускорений

Как работает гироскоп и акселерометр я знаю, проблема в другом - программирование (я в этом не силён), акселерометр выдаёт byte - восмиразрядное беззнаковое число максимум 255 при этом он его выдаёт в дополнительном коде тобиш от 0 до +177 и от -1 до -178 я же вижу числа от 0 до +255 сейчас решаю проблему как это считать…

ivereninov

А переменная в которую пишется результат точно signed?

Просто в Вашем сообщение противоречие.

SergDoc:

беззнаковое число максимум 255 при этом он его выдаёт в дополнительном коде тобиш от 0 до +177 и от -1 до -178 я же вижу числа от 0 до +255 сейчас решаю проблему как это считать…

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

SergDoc
ivereninov:

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

а как правильно обозвать? sbyte оно не понимает.

в бинарном виде так и есть он выдаёт знаковое

SergDoc

Блин ещё вчера вечером перекопал все а туда даже не глянул, спасибо!!!

И цифирки правильные побежали:)😃😃

SergDoc

Попытался запустить один из фильтров из нета (псевдокальман) показания хреновые пойду другим путём, ой чует моё сердце придётся всё считать, ладно хоть идеи появились😁

SergDoc

А с гироскопами можно просто до одурения поступить, как впринципе сделано в куке по причине того что “Углова́я ско́рость — векторная величина, характеризующая скорость вращения тела. Вектор угловой скорости по величине равен углу поворота тела в единицу времени, а направлен по оси вращения согласно правилу буравчика, то есть, в ту сторону, в которую ввинчивался бы буравчик с правой резьбой, если бы вращался в ту же сторону.” - из учебника. Тоесть можно взять показания с гироскопа и сказать что это угол, а не угловая скорость и работать с этим углом, в куке ведь работает только какойнибудь коэффициент придумать?

ivereninov
SergDoc:

Тоесть можно взять показания с гироскопа и сказать что это угол, а не угловая скорость и работать с этим углом, в куке ведь работает только какойнибудь коэффициент придумать?

Можно - но это будет стабилизация по угловой скорости ,режим Акро. Для стабилизации по углу необходимо численно интегрировать угловую скорость.

RW9UAO

а если угловую скорость разделить на время, то узнаем на сколько градусов мы уже наклонились =)
Сергей, будут конкретные вопросы - пишите тут, не стесняйтесь.

SergDoc
RW9UAO:

Сергей, будут конкретные вопросы - пишите тут, не стесняйтесь.

RW9UAO:

Сергей, будут конкретные вопросы - пишите тут, не стесняйтесь.

Я не стесняюсь, просто сейчас есть проблемы, так что занимаюсь этим делом как есть свободная минутка, а так пока пробую различные варианты просчётов гир и акселя параллельно изучаю язык, на счёт простого расчёта без интегрирования тоже задумывался, записываем время и отнимаем от него предыдущее получаем дельта t и теперь можно считать угол как угодно хоть через интеграллы хоть через кватернионы…

SergDoc

нашол на просторах интернета процедурку для просчёта времени, буду пробовать

а, забыл ещё синезубом через USART обзавёлся…

ivereninov

если Вы на каждой итерации считаете Dt, а потом на него умножаете угловую скорость, то это и есть интегрирование.

под ардуино
void loop
{
time=micros();
Dt=time-oldtime;
angle+=omega*Dt;
oldtime=time;
}

Вот и все…

ivereninov

Подключил сегодня гироскоп mlx90609 через ADC пины ардуины, уж очень не хочется с SPI возиться… Правда за удобство приходится платить заменой 11-ти битного АЦП на 10-ти( Написал удаление байеса, но при интегрировании уж очень быстро набегает ошибка - примерно градус в минуту.Видимо надо повышать разрешение и переходить не интегрирование Рунге-Кутом. Я все никак c SPI разобраться не могу, может поделитесь кодом и комментариями?

SergDoc
ivereninov:

Я все никак c SPI разобраться не могу, может поделитесь кодом и комментариями?

Вот похожее дело, только адреса менять нужно:
// полуаппаратный обмен по SPI допиленный до нужного формата
// если в value приходит 0xaa, то читаем по adr.
// если что либо другое,то пишем это по adr
char SPI(char adr, char value)
{
PORTD &= ~(1<<PD4); // прижимаем CS к земле, давая понять что передача пошла
if (value==0xaa) {adr |= (1<<7);} // ставим флаг чтения
else {adr &= ~(1<<7);} // или записи
USIDR = adr; // заносим в регистр данных USI адрес
TCNT0 = 0x00; // обнуляем таймер
TIMSK |= (1<<TOIE0); // и разрешаем его прерывания
loop_until_bit_is_set(USISR,USIOIF);// ждем передачи байта адреса
USIDR = value; // заносим в регистр данных USI значение
loop_until_bit_is_set(USISR,USIOIF);// ждем передачи байта адреса
TIMSK &= ~(1<<TOIE0); // turn off Timer0 interrupt
PORTD |= (1<<PD4); // отпускаем CS - конец передачи
return USIDR; // возвращаем считанное значение
}

У меня на данный момент по I2C включен (всмысле акселерометр)

ivereninov:

интегрирование Рунге-Кутом

У когото в коде встречал данный метод будет время поищу

а тут даже с примером ru.wikipedia.org/wiki/Метод_Рунге_—_Кутты

18 days later
SergDoc

По моему у меня не проходит колибровка датчиков

//gyros
int inputGyroX[10];//x-axis
float resultGyroX;

int inputGyroY[10];//y-axis
float resultGyroY;

int inputGyroZ[10];//z-axis
float resultGyroZ;

//accelerometers
char inputX[10];//x-axis
float resultX;

char inputY[10];//y-axis
float resultY;

char inputZ[10];//z-axis
float resultZ;

//gyros
int calibrateGyroX()
{
Serial.println(“Calibration Start”);
for(int i=0;i<10;i++)
{

inputGyroX[i] = analogRead(gX);
}
for(int i=0;i<10;i++)
{
resultGyroX += inputGyroX[i];
}
resultGyroX = resultGyroX/10;
return resultGyroX;
Serial.print(resultGyroX);Serial.print(“resultGyroX”);
}

int calibrateGyroY()
{
for(int i=0;i<10;i++)
{
inputGyroY[i] = analogRead(gY);
}
for(int i=0;i<10;i++)
{
resultGyroY += inputGyroY[i];
}
resultGyroY = resultGyroY/10;
return resultGyroY;
}

int calibrateGyroZ()
{
for(int i=0;i<10;i++)
{
inputGyroZ[i] = analogRead(gZ);
}
for(int i=0;i<10;i++)
{
resultGyroZ += inputGyroZ[i];
}
resultGyroZ = resultGyroZ/10;
return resultGyroZ;
}

//accelerometers
int calibrateX()
{
for(int i=0;i<10;i++)
{
Wire.beginTransmission(i2cID);
Wire.send(aX);
Wire.endTransmission();

Wire.requestFrom(i2cID, 1);
if(Wire.available())
{
inputX[i] = Wire.receive();
}

}
for(int i=0;i<10;i++)
{
resultX += inputX[i];
}
resultX = resultX/10;
return resultX;
}

int calibrateY()
{
for(int i=0;i<10;i++)
{
Wire.beginTransmission(i2cID);
Wire.send(aY);
Wire.endTransmission();

Wire.requestFrom(i2cID, 1);
if(Wire.available())
{
inputY[i] = Wire.receive();
}
}
for(int i=0;i<10;i++)
{
resultY += inputY[i];
}
resultY = resultY/10;
return resultY;
}

int calibrateZ()
{
for(int i=0;i<10;i++)
{
Wire.beginTransmission(i2cID);
Wire.send(aZ);
Wire.endTransmission();

Wire.requestFrom(i2cID, 1);
if(Wire.available())
{
inputZ[i] = Wire.receive();
}
}
for(int i=0;i<10;i++)
{
resultZ += inputZ[i];
}
resultZ = resultZ/10;
return resultZ;
Serial.println(“Calibration OK”);
}

Выводит только “Calibration Start”, а дальше молчёк, думаю по сей причине и показания абы что?

Может плюнуть на это дело и написать сразу нулевые значения, ну посчитать их например из 1000 значений лёжа на столе, а потом задефинить и больше их не трогать?