Создать мертвую зону для джойстика

Я пытаюсь создать мертвую зону, чтобы джойстик полностью выключил двигатель, когда он находится в центральном положении. Он слишком чувствителен и заведет мотор, если к нему едва прикоснуться. Как я мог бы исправить код так, чтобы выключенное положение джойстика было больше? Это исходный код.

#include <Servo.h> //Использование библиотеки сервоприводов для управления ESC

Servo esc; //Создание класса servo с именем esc

void setup()
{
  esc.attach(9); //Укажите пин сигнала esc,здесь как D9
  esc.writeMicroseconds(1000); //инициализируйте сигнал до 1000
  Serial.begin(9600);
}

void loop()
{
  int val; //Создание переменной val
  val = analogRead(A0); //Считывание входных данных с аналогового вывода a0 и сохранение их в val
  val = map(val, 0, 1023, 1000, 2000); //сопоставление val к минимуму и максимуму(изменение при необходимости)
  esc.writeMicroseconds(val); //использование val в качестве сигнала для esc
}

, 👍2

Обсуждение

Пожалуйста, разместите свой код внутри тега кода для удобства чтения. Как сообщает вам ошибка компилятора, похоже, что вы используете переменную с именем "adc_center", которая не объявлена. Знакомы ли вы с C++?, @Sacha

При редактировании вопроса не удаляйте теги ("\"\"\"c++ "и"\"\"") timemage и я разместили вокруг кода. На то есть свои причины., @Edgar Bonet


3 ответа


0

Мой метод состоит в том, чтобы отделить направление от величины:

  • Вычтите значение "центр", чтобы создать диапазон ±
  • Используйте знак чтобы указать направление
  • Возьмите пресс чтобы придать ему величину
  • Вычтите "пороговое" значение
  • Если отрицательно установите значение равным нулю

Итак, с примерами значений:

int val = analogRead(0);          // необработанное значение
val -= 512;                       // вычесть значение центра (512)
int direction = val < 0 ? -1 : 1; // направление либо -1, либо +1
val = abs(val);                   // удалить знак (модуль)
val -= 10;                        // вычесть пороговое значение (10)
if (val < 0) val = 0;             // Все что ниже нуля-это ноль
// val теперь равен 0-501 с мертвой зоной, а направление--1 или +1.
,

Спасибо за ответ, я пробовал вашу модификацию, теперь я получаю ошибку: "val" не называет тип., @edrummer

Тогда вы, должно быть, неправильно реализовали его. Этот фрагмент кода прекрасно компилируется, когда он завернут в функцию., @Majenko

Я уверен, что реализовал его неправильно. Не могли бы вы показать мне, как обернуть его в функцию? Я не программист., @edrummer

Мне нужно было его скомпилировать, но теперь двигатель ничего не делает. Может кто-нибудь помочь мне с этим, пожалуйста?, @edrummer

@edrummer Вам придется отредактировать свой вопрос и добавить в него обновление с вашим новым кодом, чтобы мы могли увидеть, что вы сделали не так., @Majenko

Я вставил исходный код без каких-либо изменений. Если фрагмент добавит мертвую зону. пожалуйста, скажите мне, куда его положить и все остальное, что мне нужно знать, чтобы он работал., @edrummer

Возможна опечатка? int val = analogRead(0); Должно ли это быть "A0` вместо "0"?, @tim

@тим Эти двое-одно и то же., @Majenko

Как же так? "int analogPin = A0; Последовательный.println(analogPin)" выводит 14. Что я упускаю?, @tim

@тим, тебе этого не хватает: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/wiring_analog.c#L53, @Majenko


1

Вот как создать новый отображенный диапазон с мертвой зоной. Я использовал функцию Servo.write (), которая определяет положение в градусах, потому что не мог понять, какие микросекундные тайминги вам нужны, но изменить их обратно будет несложно. Я также добавил несколько отладочных операторов для печати val при перемещении джойстика.

#include <Servo.h>

// Константы для сервоуглов в градусах.
const int SERVO_MIN = 0;
const int SERVO_MID = 90;
const int SERVO_MAX = 180;

// Константы для необработанных значений АЦП положений джойстика.
const int ANALOGUE_MIN = 0;
const int ANALOGUE_MID = 512;
const int ANALOGUE_MAX = 1023;
const int ANALOGUE_THRESHOLD = 100;

Servo esc;

void setup()
{
  esc.attach(9);         // Укажите сигнальный вывод esc как D9.
  esc.write(SERVO_MID);  // Переместите сервопривод в среднее положение в градусах.
  Serial.begin(115200);
  Serial.println();
  Serial.println("Servo Test");
}

void loop()
{
  static int old_val = -1;   // Инициализировать недопустимое значение.
  int val = analogRead(A0);  // Считывание входного сигнала с аналогового вывода A0.

  // Process val, если он изменился.
  if (val != old_val)
  {
    old_val = val;
    Serial.print(val);
    Serial.print(", ");

    // Создайте мертвую зону в соответствии с алгоритмом Майенко.
    val -= ANALOGUE_MID;
    int direction = val < 0 ? -1 : +1;
    val = abs(val);
    val -= ANALOGUE_THRESHOLD;
    if (val < 0) val = 0;

    // Создайте новый отображенный диапазон с мертвой зоной.
    val *= direction;
    val += ANALOGUE_MID;
    Serial.print(val);
    Serial.print(", ");
    val = map(val, ANALOGUE_MIN + ANALOGUE_THRESHOLD, ANALOGUE_MAX - ANALOGUE_THRESHOLD, SERVO_MIN, SERVO_MAX);
    Serial.println(val);

    // Переместите сервопривод на новый угол в градусах.
    esc.write(val);
  }
}
,

0

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

Карта тогда:

  • [0, 500] → [1000, 1500] (уклон =1)
  • [500, 523] → 1500 (наклон = 0)
  • [523, 1023] → [1500, 2000] (наклон = 1)

В коде:

/*
 * Map:
 *   [  0,  500] -> [1000, 1500]
 *   [500,  523] ->  1500
 *   [523, 1023] -> [1500, 2000]
 */
if (val < 500)
    val = 1000 + val;
else if (val < 523)
    val = 1500;
else
    val = (1500 - 523) + val;
,