Inspire-подобная рама своими руками с нуля

skm
Slevin757:

Толи деревья мешают, толи что, но время от времени теряются спутники и коптер начинает плавать.

А это нормально.
У меня не так давно работа была по съемке здания с инспайра.
Приходилось взлетать из узкого, метров 15-20 диаметром колодца образованного высоким сталинским зданием осаженном густыми тополями.
Внизу при взлете инспайр унитазило метра на два с 9 спутниками, по мере подьема до крыши и выше их добралось до 17, с 11 всякий унитазинг прекратился.

Slevin757:

(6 спутников) и мне казалось что это должно быть вполне себе достаточное количество для удержания.

Нет, это крайне мало, меньше 7 на назе/вуконге лучше вообще не летать чуть далече, ибо мало ли ли какой сбой, и с пяти дрон уже начнет неконтролируемо сдувать ветром.

Slevin757
skm:

Внизу при взлете инспайр унитазило метра на два с 9 спутниками

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

Slevin757

Заказал для пробы приводной винт Т6 с шагом 12 мм. Хочется ускорить подъем/спуск лучей и интересно потянет ли такой шаг серва.

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

Логику работы вижу так:

yadi.sk/i/O5E5oRYu3a42MR

На одном из трехпозиционных тумблеров получатся режимы: “Авто”, ручной “Полет”, ручной “Приземление”

CZC

А автоматическом режиме нужно будет всегда летать выше пороговой высоты, а то получится - “лучи вверх”-“лучи вниз”-“лучи вверх”-“лучи вниз”-“лучи вверх”-“лучи вниз”-“лучи вверх”.
В идеале -вывести информирование о приближении к пороговой высоте, о достижении пороговой высоты и о полете ниже пороговой высоты на пульт.

skm
CZC:

а то получится

У инспайра же не “получается”

Кстати у меня сейчас хоть и не инспайр, а мозг даже поумнее будет, но ноги тоже автоматом поднимаются-опускаются самим мозгом.
При этом делают это похоже с помощью двух систем - по баро, и по команде “посадка”. По команде “посадка” ноги опускаются автоматом даже на высоте метров 50
И тоже ноги самопроизвольно никуда не бегают

PS. Кстати когда то брал для колхоза с автоподьемом ног такую вот штучку - goodluckbuy.com/ultrasonic-wave-ranging-module-led…
Работает до 4м, настраиваются пороги. Но не пригодилось

CZC

Я просто проанализировал блок-схему.

Slevin757
CZC:

А автоматическом режиме нужно будет всегда летать выше пороговой высоты, а то получится - “лучи вверх”-“лучи вниз”…

Да, по логике так оно и будет. Но если вариант с новым винтом (шаг 12 мм) сработает, то опускание шасси будет происходить за секунды и я смогу выставить пороговую высоту небольшой, около 1 - 1.5 м. На такой высоте не планирую много летать, а в исключительных случаях можно будет перейти в ручной режим.

Если же на старом винте придется остаться, то метра 2.5. придется поставить. Но опять же в отдельных случаях ручным попользуюсь.

На сколько я понимаю, чтобы вывести на пульт информацию надо будет одним каналом пожертвовать. Жалко) Хотя за идею спасибо, возможно в будущем к ней добавятся еще какие-то показания для передачи.

skm:

Кстати когда то брал для колхоза с автоподьемом ног такую вот штучку

Любопытная штуковина. Разброс цен на них какой-то странный.

Накрапал скетч для ардуины:

#include <Servo.h>

Servo myservo;

int button = 6; // кнопка перевода в транспортное положение
int pin = 2; // вход с приемника
unsigned long duration; // длинна сигнала

unsigned int dist = 1200; // пороговое расстояние до земли

unsigned int HighLen = 0;
unsigned int LowLen = 0;
unsigned int Len_mm = 0;

void setup()
{
myservo.attach(3);

pinMode(5, OUTPUT);
pinMode(button, INPUT);
pinMode(pin, INPUT);
digitalWrite(5, HIGH);
Serial.begin(9600);
}

void loop()

{

if (digitalRead(button) == HIGH) // если кнопка транспортного положения нажата
myservo.write(90); // лучи в среднем положении

duration = pulseIn(pin, HIGH); // считывается длинна сигнала

if (duration > 1800) // если тумблер в нижнем положении
myservo.write(0); // лучи опускаются вниз

if ((duration > 1200) & (duration < 1800)) // если тумблер посередине
myservo.write(180); // лучи поднимаются вверх

if (duration <= 1000) // если тумблер в верхнем положении
// замеряется расстояние до земли:
{
Serial.flush();
Serial.write(0x55);
delay(10);
if (Serial.available() >= 2)
{
HighLen = Serial.read();
LowLen = Serial.read();
Len_mm = HighLen * 256 + LowLen;
Serial.print(Len_mm, DEC);
Serial.println(“mm”);
}

if (Len_mm <= dist) // если расстояние ниже, равно пороговому
myservo.write(0); // лучи лучи опускаются вниз

if (Len_mm > dist) // если расстояние выше порогового
myservo.write(180); // лучи поднимаются вверх
}

}

На счет его работоспособности пока утвердительного мнения нет. Вроди бы все работает (и кнопка и управление с пульта и автомат). Но в транспортном положении серва периодически подергивается, а должна тико стоять.
Ну и в одну сторону крутится ровно, а в другую с дерганьями (то ровно, то дергается, то встанет, то опять раскрутится). Хотя вне схемы крутится как надо.
Затрудняюсь предполагать в чем может быть дело. Для меня ардуиновская тематика, это почти как шаманизм. Заморочился с ней для удобства, но если не получится достичь стабильной работы, то опять откажусь.

rc468
Slevin757:

myservo.write(0); // лучи опускаются вниз

Slevin757:

myservo.write(90); // лучи в среднем положении

Slevin757:

myservo.write(180); // лучи поднимаются вверх

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

Slevin757
rc468:

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

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

ssilk

Хе-хе…) Вот Вы неугомонный…) То у Вас автопилот интеллектуал, хоть в “ЧтоГдеКогда” играй, теперь в серву что то можно записать…)
Серва просто поворачивается на угол, соответствующий ширине сервоимпулься на выходе ардуины…) Ширина 1000 микросекунд равна углу 0 градусов, ширина 1500 - 90 градусов, ширина 2000=180 градусов. До тех пор пока на выходе ардуины эта ширина не изменится, мотор сервы не сдвинется с места.
В данном случае, команда write(90) заставляет МК выставить на заранее определенном пине импульсы длительностью 1500 и частотой 50 герц. И эта хрень будет там присутствовать до тех пор, пока не поступит команда с другой длительностью…

Slevin757
ssilk:

теперь в серву что то можно записать

Я имел ввиду перезапись и обновление переменных на ардуине в соответствии с управляющими командами.

Считывал ширину входящего сигнала ардуиной, получилось что значения немного плавают, поэтому ставил граничные условия вроде “if ((duration > 1200) & (duration < 1800))” вместо четчих чисел. Чтобы сигнал с приемника точно попал в пределы.

rc468
Slevin757:

Я имел ввиду перезапись и обновление переменных на ардуине в соответствии с управляющими командами.

Попробуйте не писать в цикле одни и те же значения.
А сделать следующим образом:

до цикла:
int servo_mode = -1;

Slevin757:

if (digitalRead(button) == HIGH) // если кнопка транспортного положения нажата myservo.write(90); // лучи в среднем положении

меняем на:
if (digitalRead(button) == HIGH) { // если кнопка транспортного положения нажата
if (servo_mode != 90) {

myservo.write(90); // лучи в среднем положении
servo_mode = 90;
}
}

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

Slevin757
rc468:

Попробуйте не писать в цикле одни и те же значения.
А сделать следующим образом:

О! Круто! не знал про такой прием. Испробую!
Стесняюсь спросить - а что означает восклицательный знак после имени переменной?) “servo_mode != 90”

rc468
Slevin757:

а что означает восклицательный знак

== это равно
!= это не равно

Slevin757
rc468:

== это равно
!= это не равно

А, блин, точно, он же к логическому оператору относится, а не к имени))… программист из меня еще тот

rc468

Да, и еще.
Допустим, у вас нажата кнопка.
Тогда срабатывает
myservo.write(90); // лучи в среднем положении

Но вслед за этим проверяется длина сигнала и может сработать что-то еще.
Т.е. если нажата кнопка, то в цикле у вас получится так, что сначала всегда пишется 90, а затем пишется что-то еще в зависимости от длины сигнала.

Slevin757
rc468:

Но вслед за этим проверяется длина сигнала и может сработать что-то еще.

А может тогда дописать еще одно условие после проверки кнопки?

if (digitalRead(button) != HIGH)
{
… и пошло дальше

rc468

Вот такой оптимизированный цикл:
int last_servo_mode = -1;
int servo_mode = -1;

void loop() {
if (digitalRead(button) == HIGH) {
// если кнопка транспортного положения нажата
servo_mode = 90; // лучи в среднем положении
}

duration = pulseIn(pin, HIGH); // считывается длинна сигнала

if (duration > 1800) {
// если тумблер в нижнем положении
servo_mode = 0; // лучи опускаются вниз
} else if (duration > 1200) {
// если тумблер посередине
servo_mode = 180; // лучи поднимаются вверх
} else {
// если тумблер в верхнем положении
// замеряется расстояние до земли:
Serial.flush();
Serial.write(0x55);
delay(10);
if (Serial.available() >= 2) {
HighLen = Serial.read();
LowLen = Serial.read();
Len_mm = HighLen << 8 + LowLen;
Serial.print(Len_mm, DEC);
Serial.println(“mm”);
}

if (Len_mm <= dist) {
// если расстояние ниже, равно пороговому
servo_mode = 0; // лучи лучи опускаются вниз
} else {
// если расстояние выше порогового
servo_mode = 180; // лучи поднимаются вверх
}
}

if (servo_mode != last_servo_mode) {
myservo.write(servo_mode);
last_servo_mode = servo_mode;
}
}

Slevin757:

А может тогда дописать еще одно условие после проверки кнопки?

А у вас кнопка или переключатель имеет приоритет? Если кнопка, то после обработки кнопки надо пропустить остальную часть (поместить ее в else), если переключатель, то оставить как есть. (Но писать все равно один раз за цикл, как я запостил выше).

Slevin757
rc468:

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

Кнопка в приоритете. Так как нажимается только при подготовке к полету и при завершении.

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

rc468

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

Slevin757

Вот так?

… if (Len_mm <= dist) {

servo_mode = 0;
}
else
{
servo_mode = 180;
}
}

if (digitalRead(button) == HIGH) {
// если кнопка транспортного положения нажата
myservo.write(90); // лучи в среднем положении
servo_mode = 90;
}

if (servo_mode != last_servo_mode) {
myservo.write(servo_mode);

last_servo_mode = servo_mode;
}

}

На кнопку стал правильно реагировать, но вращение мотора испортилось. После первой рекомендации он в АВТО плохо себя вел, но зато в ручном крутил отлично. А сейчас в обоих режимах в одну сторону крутит, а в другую дергается.