Inspire-подобная рама своими руками с нуля
Я просто проанализировал блок-схему.
А автоматическом режиме нужно будет всегда летать выше пороговой высоты, а то получится - “лучи вверх”-“лучи вниз”…
Да, по логике так оно и будет. Но если вариант с новым винтом (шаг 12 мм) сработает, то опускание шасси будет происходить за секунды и я смогу выставить пороговую высоту небольшой, около 1 - 1.5 м. На такой высоте не планирую много летать, а в исключительных случаях можно будет перейти в ручной режим.
Если же на старом винте придется остаться, то метра 2.5. придется поставить. Но опять же в отдельных случаях ручным попользуюсь.
На сколько я понимаю, чтобы вывести на пульт информацию надо будет одним каналом пожертвовать. Жалко) Хотя за идею спасибо, возможно в будущем к ней добавятся еще какие-то показания для передачи.
Кстати когда то брал для колхоза с автоподьемом ног такую вот штучку
Любопытная штуковина. Разброс цен на них какой-то странный.
Накрапал скетч для ардуины:
#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); // лучи поднимаются вверх
}
}
На счет его работоспособности пока утвердительного мнения нет. Вроди бы все работает (и кнопка и управление с пульта и автомат). Но в транспортном положении серва периодически подергивается, а должна тико стоять.
Ну и в одну сторону крутится ровно, а в другую с дерганьями (то ровно, то дергается, то встанет, то опять раскрутится). Хотя вне схемы крутится как надо.
Затрудняюсь предполагать в чем может быть дело. Для меня ардуиновская тематика, это почти как шаманизм. Заморочился с ней для удобства, но если не получится достичь стабильной работы, то опять откажусь.
myservo.write(0); // лучи опускаются вниз
myservo.write(90); // лучи в среднем положении
myservo.write(180); // лучи поднимаются вверх
Нужно ли эти значения постоянно записывать в серву в цикле или достаточно записать один раз, чтобы серва приняла нужное положение и удерживала его?
Нужно ли эти значения постоянно записывать в серву в цикле или достаточно записать один раз, чтобы серва приняла нужное положение и удерживала его?
Мои познания в программировании ограничиваются универским курсом и гуглом, но на сколько я понимаю, если записать что-то окончательно, то потом программа перестанет обновлять переменную и схема перестанет реагировать на новые команды. Такой вариант как прямое управление с пульта тут не сработает - все тело программы это цикл.
Хе-хе…) Вот Вы неугомонный…) То у Вас автопилот интеллектуал, хоть в “ЧтоГдеКогда” играй, теперь в серву что то можно записать…)
Серва просто поворачивается на угол, соответствующий ширине сервоимпулься на выходе ардуины…) Ширина 1000 микросекунд равна углу 0 градусов, ширина 1500 - 90 градусов, ширина 2000=180 градусов. До тех пор пока на выходе ардуины эта ширина не изменится, мотор сервы не сдвинется с места.
В данном случае, команда write(90) заставляет МК выставить на заранее определенном пине импульсы длительностью 1500 и частотой 50 герц. И эта хрень будет там присутствовать до тех пор, пока не поступит команда с другой длительностью…
теперь в серву что то можно записать
Я имел ввиду перезапись и обновление переменных на ардуине в соответствии с управляющими командами.
Считывал ширину входящего сигнала ардуиной, получилось что значения немного плавают, поэтому ставил граничные условия вроде “if ((duration > 1200) & (duration < 1800))” вместо четчих чисел. Чтобы сигнал с приемника точно попал в пределы.
Я имел ввиду перезапись и обновление переменных на ардуине в соответствии с управляющими командами.
Попробуйте не писать в цикле одни и те же значения.
А сделать следующим образом:
до цикла:
int servo_mode = -1;
if (digitalRead(button) == HIGH) // если кнопка транспортного положения нажата myservo.write(90); // лучи в среднем положении
меняем на:
if (digitalRead(button) == HIGH) { // если кнопка транспортного положения нажата
if (servo_mode != 90) {
myservo.write(90); // лучи в среднем положении
servo_mode = 90;
}
}
и аналогично для других режимов.
в результате значения будут писаться только один раз при смене режима.
возможно, это повлияет на подергивания сервы.
Попробуйте не писать в цикле одни и те же значения.
А сделать следующим образом:
О! Круто! не знал про такой прием. Испробую!
Стесняюсь спросить - а что означает восклицательный знак после имени переменной?) “servo_mode != 90”
а что означает восклицательный знак
== это равно
!= это не равно
== это равно
!= это не равно
А, блин, точно, он же к логическому оператору относится, а не к имени))… программист из меня еще тот
Да, и еще.
Допустим, у вас нажата кнопка.
Тогда срабатывает
myservo.write(90); // лучи в среднем положении
Но вслед за этим проверяется длина сигнала и может сработать что-то еще.
Т.е. если нажата кнопка, то в цикле у вас получится так, что сначала всегда пишется 90, а затем пишется что-то еще в зависимости от длины сигнала.
Но вслед за этим проверяется длина сигнала и может сработать что-то еще.
А может тогда дописать еще одно условие после проверки кнопки?
if (digitalRead(button) != HIGH)
{
… и пошло дальше
Вот такой оптимизированный цикл:
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;
}
}
А может тогда дописать еще одно условие после проверки кнопки?
А у вас кнопка или переключатель имеет приоритет? Если кнопка, то после обработки кнопки надо пропустить остальную часть (поместить ее в else), если переключатель, то оставить как есть. (Но писать все равно один раз за цикл, как я запостил выше).
А у вас кнопка или переключатель имеет приоритет?
Кнопка в приоритете. Так как нажимается только при подготовке к полету и при завершении.
я тут пока испробовал код по первой рекомендации - в транспортном положении стоит ровно, не гудит и не дергается. А в остальных режимах дергает.
Сейчас разберусь в коде второй рекомендации. Благодарю, что потратили время на написание.
Тогда обработку кнопки достаточно перенести вниз после обработки переключателя и до записи окончательного значения в серву. Она будет выполняться последней и переустановит любое значение, которое было установлено до этого.
Вот так?
… 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;
}
}
На кнопку стал правильно реагировать, но вращение мотора испортилось. После первой рекомендации он в АВТО плохо себя вел, но зато в ручном крутил отлично. А сейчас в обоих режимах в одну сторону крутит, а в другую дергается.
Вот так?
Да.
вращение мотора испортилось
Трудно понять на расстоянии. Буду думать.
Тааакс… Подправил граничные условия в одном месте, вернул старый скетч эхолота и стер фрагмент про кнопку - пошло на пользу. Мотор ровно крутит в обе стороны и в обоих режимах. На сонар реагирует корректно.
Теперь надо фрагмент про кнопку правильно вставить.
…
Нее, если в то место вставляю, то картина портится.
Попробую в начало
…
Не, чет не то… Без кнопки все прям прекрасно работает. А фрагмент с кнопкой все резко портит. Андрей, кажется вы писали про оператор Continue, но потом редактировали. Он может помочь при размещении кода кнопки в начале цикла?
…
Текущее работоспособное состояние цикла без кнопки:
void loop()
{
duration = pulseIn(pin, HIGH);
if (duration > 1800)
{
servo_mode = 0;
} else if ((duration > 1300)&(duration <= 1700))
{
servo_mode = 180;
}
else
{
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)
{
servo_mode = 0;
}
else
{
servo_mode = 180;
}
}
if (servo_mode != last_servo_mode)
{
myservo.write(servo_mode);
last_servo_mode = servo_mode;
}
}
писали про оператор Continue, но потом редактировали
continue это переход на следующий шаг цикла с текущего места, его использовать нельзя, потому что это не цикл for или while, поэтому я и отредактировал. Он не может помочь.
Надо понять, почему кнопка влияет так.
А вы можете наоборот все убрать и оставить только кнопку?
Оставить только кнопку и дополнить реакцию на отжатие:
if (digitalRead(button) == HIGH) {
// если кнопка транспортного положения нажата
servo_mode = 90; // лучи в среднем положении
} else {
servo_mode = 0; // в любом другом положении
}
А вы можете наоборот все убрать и оставить только кнопку?
Сама по себе стопорит она нормально. Но своим присутствием этот фрагмент кода влияет на остальной цикл и серва начинает неровно крутиться, стопориться, дергалься
if (digitalRead(button) == HIGH)
{myservo.write(90);
servo_mode = 90;}
Мне кажется хорошо бы воткнуть его вначале, чтобы программа проверила его, и если кнопка включена, то оставшаяся часть кода была бы проигнорирована за ненадобностью.
А если кнопка не нажата, то цикл выполнялся бы полностью.
А вы можете наоборот все убрать и оставить только кнопку?
сейчас попробую…
Но своим присутствием этот фрагмент кода влияет на остальной цикл и серва начинает неровно крутиться, стопориться, дергалься if (digitalRead(button) == HIGH) {myservo.write(90); servo_mode = 90;}
Погодите, именно этот фрагмент?
С ним будет дергаться, потому что в нем запись происходит. В нем должно быть только servo_mode = 90 и больше ничего. Запись производится после всех проверок один раз в конце цикла.