Создание собственной системы стабилизации
Блин ещё вчера вечером перекопал все а туда даже не глянул, спасибо!!!
И цифирки правильные побежали:)😃😃
Ура)
Попытался запустить один из фильтров из нета (псевдокальман) показания хреновые пойду другим путём, ой чует моё сердце придётся всё считать, ладно хоть идеи появились😁
Зубрю страшную книженцию “Фильтр Калмана-Бьюси” books.tr200.ru/v.php?id=363192
А с гироскопами можно просто до одурения поступить, как впринципе сделано в куке по причине того что “Углова́я ско́рость — векторная величина, характеризующая скорость вращения тела. Вектор угловой скорости по величине равен углу поворота тела в единицу времени, а направлен по оси вращения согласно правилу буравчика, то есть, в ту сторону, в которую ввинчивался бы буравчик с правой резьбой, если бы вращался в ту же сторону.” - из учебника. Тоесть можно взять показания с гироскопа и сказать что это угол, а не угловая скорость и работать с этим углом, в куке ведь работает только какойнибудь коэффициент придумать?
Тоесть можно взять показания с гироскопа и сказать что это угол, а не угловая скорость и работать с этим углом, в куке ведь работает только какойнибудь коэффициент придумать?
Можно - но это будет стабилизация по угловой скорости ,режим Акро. Для стабилизации по углу необходимо численно интегрировать угловую скорость.
а если угловую скорость разделить на время, то узнаем на сколько градусов мы уже наклонились =)
Сергей, будут конкретные вопросы - пишите тут, не стесняйтесь.
умножить
Сергей, будут конкретные вопросы - пишите тут, не стесняйтесь.
Сергей, будут конкретные вопросы - пишите тут, не стесняйтесь.
Я не стесняюсь, просто сейчас есть проблемы, так что занимаюсь этим делом как есть свободная минутка, а так пока пробую различные варианты просчётов гир и акселя параллельно изучаю язык, на счёт простого расчёта без интегрирования тоже задумывался, записываем время и отнимаем от него предыдущее получаем дельта t и теперь можно считать угол как угодно хоть через интеграллы хоть через кватернионы…
нашол на просторах интернета процедурку для просчёта времени, буду пробовать
а, забыл ещё синезубом через USART обзавёлся…
если Вы на каждой итерации считаете Dt, а потом на него умножаете угловую скорость, то это и есть интегрирование.
под ардуино
void loop
{
time=micros();
Dt=time-oldtime;
angle+=omega*Dt;
oldtime=time;
}
Вот и все…
Подключил сегодня гироскоп mlx90609 через ADC пины ардуины, уж очень не хочется с SPI возиться… Правда за удобство приходится платить заменой 11-ти битного АЦП на 10-ти( Написал удаление байеса, но при интегрировании уж очень быстро набегает ошибка - примерно градус в минуту.Видимо надо повышать разрешение и переходить не интегрирование Рунге-Кутом. Я все никак c SPI разобраться не могу, может поделитесь кодом и комментариями?
Я все никак 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 включен (всмысле акселерометр)
интегрирование Рунге-Кутом
У когото в коде встречал данный метод будет время поищу
а тут даже с примером ru.wikipedia.org/wiki/Метод_Рунге_—_Кутты
По моему у меня не проходит колибровка датчиков
//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 значений лёжа на столе, а потом задефинить и больше их не трогать?
А setup и loop можно глянуть? кстати, если в for одна строчка, {} можно не ставить. Мой коптер уже поднялся в воздух, пока стабилизация только по угловой скорости и настроена не очень.Калибровку можно дефайнить если не боитесь температурных дрифтов байеса, а они будут.
Пока только предположения, я думаю проблема в переменных я суммирую CHAR а потом делю на 10 в десятичной, оно наверно не переваривает этого, надо наверно ввести дополнительную переменную дабы конвертировать это дело в один формат, вот с чем сейчас воюю пока без шим:
ещё проблемка, нормально стабилизацию по курсу без магнитометра никак?
А setup и loop можно глянуть? кстати, если в for одна строчка, {} можно не ставить. Мой коптер уже поднялся в воздух, пока стабилизация только по угловой скорости и настроена не очень.Калибровку можно дефайнить если не боитесь температурных дрифтов байеса, а они будут.
А на ваше программое можно глянуть, или это секрет?
Да с переменной Char не всё так просто, это знак а не число, как его правильно интерпретировать?
Попробуйте делить на 10.0 и использовать int. Курс без магнитометра никак(
используйте int оно от -32768 до 32768, char от -127 до 128
есть еще тип unsigned он знак игнорирует.
используйте int оно от -32768 до 32768, char от -127 до 128
есть еще тип unsigned он знак игнорирует.
прикол в следующем если я буду принимать данные с акселерометра в любую другую переменную не char я тупо теряю знак числа(уже экспериментировал) и тогда получается значение от 0 до 255 а в какую сторону он наклонен бог его знает, я уже писал выше что получалось ускорение свободного падения 55 перевернуть 200 нужно всётаки принять в char, а потом конвертировать как-то?
аксель мне даёт показания в дополнительном коде😢
если в int положить char, то знак потеряться не должен. в процедуре усреднения можно попробовать так:
int middle;
char temp;
middle = 0;
for (c=0; c < сколько циклов усреднения; c++){
temp = процедура чтения акселерометра;
middle = middle + temp;
}
middle = middle / сколько циклов усреднения;
вот так точно будет работать =)
если все совсем плохо, можно использовать float для переменной middle