Сервоприводы не работают должным образом с джойстиком

arduino-uno servo joystick

Итак, я работал над проектом, в котором я использовал модуль джойстика для управления двумя сервоприводами одновременно. Джойстик управляет сервоприводами таким образом, что когда джойстик перемещается по оси x, оба сервопривода перемещаются в одном направлении, но когда джойстик перемещается по оси y, сервоприводы перемещаются в разных направлениях. У меня есть эта программа:

#include <Servo.h>
Servo servo1;
Servo servo2;
int joyx = 0;
int joyy = 5;
int joyval;
int joyvalx; 
int joyvaly;
void setup() {
    Serial.begin(9600);
    servo1.attach(3);
    servo2.attach(5);

}

void loop() {
    Serial.println(joyvalx + "," + joyvaly);
    int x = analogRead(joyx);
    int y = analogRead(joyy);
    if(x != joyvalx){
        joyval = map(x, 0, 1023, 0, 180);
        servo1.write(joyval);
        servo2.write(joyval);
    } 
    if (y != joyvaly){
        joyval = map(y, 0, 1023, 0, 180);
        servo1.write(joyval);
        servo2.write(1023-joyval);
    }
}

Однако сервоприводы, похоже, работают неправильно. Один сервопривод работает нормально, а другой просто застревает. Кроме того, если я использую код только для одного направления (ось x или y), удалив код для другого, то оба сервопривода работают хорошо. Я не могу понять проблему. Если кто-то понимает, пожалуйста, помогите мне.

, 👍2

Обсуждение

1. Вы не инициализируете joyvalx и joyvaly. 2. Вы никогда ничего не назначаете joyvalx или joyvaly., @Majenko

+1 за красиво отформатированный код, @jsotola

ваш ответ здесь: «если я использую код только для одного направления (оси x или y), удалив код для другого, то оба сервопривода будут работать хорошо». У вас есть два фрагмента кода, которые похожи на двух собак, дерующихся за кость., @jsotola

1023-joyval, что составляет от 0 до 180? ..., @frarugi87


1 ответ


Лучший ответ:

2

Проблема, как указал jsotola, в том, что ваш код очень быстро записывает совершенно разные значения в сервоприводы. Вы не объединяете два значения с джойстика, а просто перезаписываете предыдущее значение сервопривода. Так что это не может работать.

Как я понимаю ваше описание, вы хотите, чтобы ось x перемещала оба сервопривода на одинаковую величину в одном направлении (в единстве), в то время как ось y определяет разницу в положении между ними. Если вы перемещаете ось y в одну сторону, первый сервопривод немного повернет по часовой стрелке, а другой немного против часовой стрелки. Когда вы затем перемещаете ось x, оба сервопривода будут перемещаться в соответствующем направлении, сохраняя при этом разницу в положении.

Лучше сначала написать формулу, как вы будете рассчитывать каждое положение сервопривода из заданных значений джойстика. Вышеуказанное поведение можно описать этими формулами:

servo_1_value = mapped_x + mapped_y;
servo_2_value = mapped_x - mapped_y;

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

mapped_x = map(x, 0, 1023, 0, 180);
mapped_y = map(y, 0, 1023, -90, 90);

Обратите внимание, что вам следует изменить параметры для отображения y на нужные вам значения. В приведенном выше коде они установлены на максимум (это означает, что перемещение оси y в любой конец фактически отключит ось x, поскольку сервопривод не может двигаться дальше 0 или 180 градусов).

Вам не нужно проверять, изменилось ли значение. Но если вы действительно хотите, вам следует проверить вычисленные значения для каждого сервопривода отдельно. Что-то вроде этого:

if(servo_1_value != old_servo_1_value){
    servo1.write(servo_1_value);
}
if(servo_2_value != old_servo_2_value){
    servo2.write(servo_2_value);
}

Но вам на самом деле не нужно проверять наличие изменений здесь.

,

Мне нравится этот ответ; я бы только добавил одну очень важную вещь: вы не должны вызывать функции на максимальной скорости, а вызывать их, скажем, раз в 10 мс. Отзывчивость все еще высока, но 1) другие части программы работают лучше и 2) вы не пытаетесь давать механическим компонентам команды, которые слишком быстры, @frarugi87

Да, вы можете это сделать, но я не думаю, что запись на максимальной скорости действительно сделает что-то плохое. Сервопривод управляется через ШИМ, и он будет двигаться в указанное положение так быстро, как только сможет, вы не можете контролировать его скорость. При записи медленнее (с задержкой или конструкцией millis()), тогда будут только меньшие позиции между ними, но общее изменение значения будет таким же; на максимуме мгновенный скачок от 0° до 180°. С другой стороны, это предотвратит джиттер, если вы измеряете большее количество аналоговых значений и записываете в сервопривод только среднее., @chrisl

на самом деле, пункт 2 не должен применяться для серводвигателей (я проверил библиотеку, и она обновляет значение один раз при переполнении таймера, поэтому она автоматически игнорирует все остальные команды). Тем не менее, по моему мнению, наличие человеческого интерфейса в постоянном получении данных не является чем-то очень целесообразным; это истощает ресурсы (даже если в этом случае не нужно выполнять никаких других «задач») и заваливает бесполезной информацией приемник (например, ПК на другом конце последовательного канала). Это, опять же, помимо механических проблем, которые в этом случае отсутствуют из-за конструкции библиотеки, @frarugi87

Вы правы, для более крупной программы это важно. Я не включил это для простоты, но это определенно хороший момент для замечания., @chrisl

Спасибо @chrisl, твой ответ сработал. Теперь оба сервопривода работают отлично. Большое спасибо., @Faiq Irfan