Создать мертвую зону для джойстика
Я пытаюсь создать мертвую зону, чтобы джойстик полностью выключил двигатель, когда он находится в центральном положении. Он слишком чувствителен и заведет мотор, если к нему едва прикоснуться. Как я мог бы исправить код так, чтобы выключенное положение джойстика было больше? Это исходный код.
#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
}
@edrummer, 👍2
Обсуждение3 ответа
Мой метод состоит в том, чтобы отделить направление от величины:
- Вычтите значение "центр", чтобы создать диапазон ±
- Используйте знак чтобы указать направление
- Возьмите
пресс
чтобы придать ему величину - Вычтите "пороговое" значение
- Если отрицательно установите значение равным нулю
Итак, с примерами значений:
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
Вот как создать новый отображенный диапазон с мертвой зоной. Я использовал функцию 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);
}
}
Обратите внимание, что в вашем случае ширина входного диапазона (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;
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- как быстро loop() работает в Arduino
- Использовать Arduino Nano V3 для программирования другого Arduino (Pro Mini)?
- Как прочитать значение PIN PWM-выхода?
- Как мигать светодиодом и одновременно запускать другой код?
- Подключение Arduino Nano к Raspberry Pi Zero
- Как автоматически сбросить модуль NRF24L01
- Программа Nano Every с использованием порта UPDI
Пожалуйста, разместите свой код внутри тега кода для удобства чтения. Как сообщает вам ошибка компилятора, похоже, что вы используете переменную с именем "adc_center", которая не объявлена. Знакомы ли вы с C++?, @Sacha
При редактировании вопроса не удаляйте теги ("\"\"\"c++ "и"\"\"") timemage и я разместили вокруг кода. На то есть свои причины., @Edgar Bonet