Как сделать, чтобы Rotary Encoder делал 10 шагов одновременно?
Я использую поворотный энкодер на моем Arduino Micro, который должен делать один или десять шагов одновременно, в зависимости от того, в каком положении находится переключатель.
Ротари: https:// www.reichelt.de/drehimpulsegeber-15-impulse-30-rastungen-vertikal-ec11mvbfx-p315144.html?&nbc=1 (на этом сайте также есть изображения и спецификации.)
Переключатель: https: //www.reichelt.de/miniatur-kippschalter-ein-aus-ein-3-a-250-v-goobay-10023-p285990.html?&nbc=1
Проводка: (изображение ниже)
1--------Pin16 | Pin A3----Switch Rotary 2--------GND | GND-------| 3--------PIN17 |
Поворотный энкодер не выдает никаких выходных данных, ни Serial.print, ни игровой контроллер. Также нет выхода ни в одном из положений переключателя.
ОБНОВЛЕНИЕ: После использования массивов и циклов, как научил меня @jsotola, он работает почти так, как должен, но иногда, хотя переключатель выключен, он щелкает десять раз. Код выглядит сокращенно теперь
#include <Arduino.h>
#include <Joystick.h>
#include <BasicEncoder.h>
#include <TimerOne.h>
int EncoderPins[] = {
4, 5, 6, 7, 8, 9, 10, 11
};
int EncoderCount = 8;
BasicEncoder encoder4(EncoderPins[6], EncoderPins[7], HIGH, 2);
void timer_service() {
encoder4.service();
}
#define joyButton16 EncoderPins[6] // Rotary4
#define joyButton17 EncoderPins[7] // Rotary4
#define joyButton18 21 // HDG_SWITCH := Переключатель для выбора между одинарным и 10 шагами
// Джойстик (джойстик HID ID, тип джойстика, количество кнопок, количество переключателей, включить X, включить Y, включить Z, включить Rx, включить Ry, включить Rz, включить руль направления, включить дроссельную заслонку, включить акселератор, включить тормоз, включить рулевое управление )
Joystick_ Joystick(0x15, JOYSTICK_TYPE_JOYSTICK, 19, 0,
true /*X*/, false/*Y*/, false/*X*/,
false/*Rx*/, false/*Ry*/, false/*Rz*/,
false/*Rudder*/, false/*Throttle*/, false/*Acc*/,
false/*Brake*/, false/*Steer*/);
const bool initAutoSendState = true; // код отправляется непрерывно и не ждет опроса
int EncoderState[] = {
0, 0, 0, 0
};
void setup() {
for (int q = 0; q < EncoderCount; q++)
{
pinMode(EncoderPins[q], INPUT_PULLUP);
}
Serial.begin(9600);
Joystick.begin();
Timer1.initialize(100);
Timer1.attachInterrupt(timer_service);
}
void loop() {
GET_CHANGE();
int CurrentButton18State = !digitalRead(joyButton18);
switch(CurrentButton18State){
case 0:
switch(EncoderState[3]){
case 1: clickButton(15); Serial.println(EncoderState[3]); break;
case -1: clickButton(16); Serial.println(EncoderState[3]); break;
} break;
case 1:
switch(EncoderState[3]){
case 1: clickTen(15); break;
case -1: clickTen(16); break;
} break;
}
}
void clickButton(int pin) {
Joystick.setButton(pin, 1);
delay(2);
Joystick.setButton(pin, 0);
}
void clickTen(int pin) {
for (int ii = 0; ii < 10; ii++)
{
clickButton(pin);
Serial.println("step: "); Serial.println(ii);
delay(10);
}
}
void GET_CHANGE()
{
for(int E = 0; E<4; E++)
switch(E) {
case 3: EncoderState[E] = encoder4.get_change(); break;
}
}
@Chritzeltopf, 👍-2
Обсуждение1 ответ
Это не ответ на вопрос, а совет по упрощению кода.
Это фрагмент вашего кода.
void loop() {
// еще немного кода здесь
int encoder1State = encoder1.get_change();
switch (encoder1State) {
case 1:
Joystick.setButton(8, 1);
delay(25);
Joystick.setButton(8, 0);
//Serial.println(encoder1State);
break;
case -1:
Joystick.setButton(9, 1);
delay(25);
Joystick.setButton(9, 0);
//Serial.println(encoder1State);
break;
case 0:
break;
}
int encoder2State = encoder2.get_change();
switch (encoder2State) {
case 1:
Joystick.setButton(10, 1);
delay(25);
Joystick.setButton(10, 0);
//Serial.println(encoder1State);
break;
case -1:
Joystick.setButton(11, 1);
delay(25);
Joystick.setButton(11, 0);
//Serial.println(encoder1State);
break;
case 0:
break;
}
int encoder3State = encoder3.get_change();
switch (encoder3State) {
case 1:
Joystick.setButton(12, 1);
delay(25);
Joystick.setButton(12, 0);
//Serial.println(encoder1State);
break;
case -1:
Joystick.setButton(13, 1);
delay(25);
Joystick.setButton(13, 0);
//Serial.println(encoder1State);
break;
case 0:
break;
}
int currentButton20State = !digitalRead(joyButton20);
int encoder4State = encoder4.get_change();
switch (currentButton20State) {
case 0:
switch (encoder4State) {
case 1:
Joystick.setButton(14, 1);
delay(25);
Joystick.setButton(14, 0);
Serial.println(encoder4State);
break;
case -1:
Joystick.setButton(15, 1);
delay(25);
Joystick.setButton(15, 0);
Serial.println(encoder4State);
break;
case 0:
break;
} break;
case 1:
switch (encoder4State) {
case 1:
TenRotaryStepsUP();
break;
case -1:
TenRotaryStepsDOWN();
break;
case 0:
break;
} break;
}
//ПолучитьПарамИзFS2020();
//ПоказатьFlightParam();
delay(10);
}
void TenRotaryStepsUP()
{
for (int i = 0; i < 10; i++)
{
Joystick.setButton(14, 1);
delay(25); //для тестирования установите большее число, например 500
Joystick.setButton(14, 0);
Serial.println("step: "); Serial.println(i);
delay(10);
}
}
void TenRotaryStepsDOWN()
{
for (int i = 0; i < 10; i++)
{
Joystick.setButton(15, 1);
delay(25);
Joystick.setButton(15, 0);
Serial.println("step: "); Serial.println(i);
delay(10);
}
}
Его можно упростить, поместив повторяющийся код в функции.
void loop() {
// еще немного кода здесь
int encoder1State = encoder1.get_change();
//Serial.println(encoder1State);
switch (encoder1State) {
case 1:
clickButton(8);
break;
case -1:
clickButton(9);
break;
case 0:
break;
}
int encoder2State = encoder2.get_change();
switch (encoder2State) {
case 1:
clickButton(10);
break;
case -1:
clickButton(11);
break;
case 0:
break;
}
int encoder3State = encoder3.get_change();
switch (encoder3State) {
case 1:
clickButton(12);
break;
case -1:
clickButton(13);
break;
case 0:
break;
}
int currentButton20State = !digitalRead(joyButton20);
int encoder4State = encoder4.get_change();
switch (currentButton20State) {
case 0:
switch (encoder4State) {
case 1:
clickButton(14);
break;
case -1:
clickButton(15);
break;
case 0:
break;
} break;
case 1:
switch (encoder4State) {
case 1:
clickTen(14);
break;
case -1:
clickTen(15);
break;
case 0:
break;
} break;
}
//ПолучитьПарамИзFS2020();
//ПоказатьFlightParam();
delay(10);
}
void clickButton(int pin) {
Joystick.setButton(pin, 1);
delay(25);
Joystick.setButton(pin, 0);
}
void clickTen(int pin) {
for (int i = 0; i < 10; i++)
{
clickButton(pin);
Serial.println("step: "); Serial.println(i);
delay(10);
}
}
Вы даже можете отформатировать свой код таким образом.
switch (encoder3State) {
case 1: clickButton(12); break;
case -1: clickButton(13); break;
case 0: break;
}
ИЗМЕНИТЬ
Также см. следующее об использовании массивов в качестве переменных для указания контактов вместо имен отдельных переменных
https://www.arduino.cc/en/Tutorial/BuiltInExamples/Arrays
например. используйте lastButtonState[1]
вместо lastButton1State
и joyButton[1]
вместо joyButton1
что позволит использовать циклы for
для повторения одного и того же действия для нескольких контактов
int currentButton2State = !digitalRead(joyButton2);
if (currentButton2State != lastButton2State) {
Joystick.setButton(1, currentButton2State);
if (currentButton2State == 1) {
delay(1);
Joystick.setButton(1, 0);
}
lastButton2State = currentButton2State;
}
становится
int currentButtonState[pin] = !digitalRead(joyButton[pin]);
if (currentButtonState[pin] != lastButtonState[pin]) {
Joystick.setButton(pin-1, currentButtonState[pin]);
if (currentButtonState[pin] == 1) {
delay(1);
Joystick.setButton(pin-1, 0);
}
lastButtonState[pin] = currentButtonState[pin];
}
Спасибо @jsotola, попробую, когда вернусь домой!, @Chritzeltopf
добавил больше информации, @jsotola
Спасибо, я попробую это сегодня днем (также я уменьшу код в вопросе), @Chritzeltopf
Вы также можете обрабатывать несколько шагов кодировщика с помощью чего-то вроде if(encoder3State>0) while(encoder3State--) clickButton(12); if(encoder3State<0) while(encoder3State++) clickButton(13);
., @Edgar Bonet
- Считывание нескольких поворотных энкодеров
- Использование поворотных энкодеров с прерываниями смены контактов
- Выводы прерываний Arduino Mega 2560 и отображение портов с помощью поворотного энкодера
- Взаимодействие с датчиком SSI?
- Чтение нескольких аналоговых входных контактов
- Будет ли простой RC-фильтр работать с механическим поворотным энкодером или понадобится триггер Шмитта?
- Проблема с преобразованием выходного сигнала поворотного энкодера в угол.
- Чтение двух квадратурных кодировщиков с помощью одного ардуино
Пожалуйста, сократите код до минимума, который обеспечивает описанное вами поведение. Этот код предназначен для Arduino Uno? Если это так, контакт A3 Arduino (контакт вашего переключателя) физически совпадает с контактом 17 (один из контактов вашего энкодера). Контакты 0 и 1 — это контакты Serial RX/TX, которые вы не можете использовать для других целей, если вам нужен ввод/вывод через последовательный порт., @StarCat
@StarCat, там написано Arduino Micro, @Juraj
@StarCat, поскольку «A3» является маркером на самой плате, я подумал, что это будет легче понять, конечно, каждый аналоговый вывод можно использовать как цифровой (в коде я так делаю). Я выкладываю полный скетч, потому что я не знаю, может быть проблема в другой части, то в двух переключателях. Кнопки на контактах 0/1 могут быть подключены к распределителю напряжения на другом контакте., @Chritzeltopf
почему вы говорите о выборе между 10 шагами и 1 шагом, когда вы не можете заставить работать энкодер? ... пожалуйста, сосредоточьте свой вопрос на проблеме, @jsotola
Нет выхода, ни во включенном, ни в выключенном положении переключателя, @Chritzeltopf
Какой «поворотный энкодер» и «переключатель» вы имеете в виду? Когда я гуглю эти слова, кажется, что есть миллионы вариантов. Переключатель встроен в поворотный энкодер? У меня проблемы с просмотром вашего поворотного энкодера с моего компьютера. Как насчет того, чтобы поделиться ссылкой на производителя, спецификацией или изображением?, @VE7JRO
*Я выкладываю полный скетч, потому что не знаю, может быть, проблема в другой части, а не в двух переключателях.* - Если бы вы сократили код только до части энкодера, вы бы это обнаружили, не так ли?, @Nick Gammon
@jsotola Ротари выше, к которым не подключен переключатель, работают., @Chritzeltopf
@VE7JRO добавил их, @Chritzeltopf
Опять же, пожалуйста, сократите свой источник до минимума, который все еще раскрывает вашу проблему., @the busybee
1. Я присоединяюсь к другим комментаторам: вы публикуете слишком много кода. См. [Как создать минимальный воспроизводимый пример] (https://stackoverflow.com/help/minimal-reproducible-example). 2. Может быть не связано с вашей проблемой, но ваш код предполагает, что
BasicEncoder::get_change()
всегда возвращает −1, 0 или 1. Это может быть не всегда так, особенно если учесть, что у вас довольно многоdelay()
` в вашем коде., @Edgar Bonet@EdgarBonet Я прочитал ссылку, которую вы разместили, и сегодня днем уменьшу код (с помощью Jsotola). get_change() должна выдавать либо 1, либо - 1, если используется ротор, и 0, если он стоит на месте, не так ли?, @Chritzeltopf
Что касается значения, возвращаемого
get_change()
: как [указано в документации] (https://github.com/micromouseonline/BasicEncoder#get_change),get_change()
возвращает «количество отсчетов с момента последнего вызова метод". Если цикл выполняется очень быстро, это почти всегда будет в пределах ±1. В документации предлагается: «Попробуйте добавить задержку вloop()
, чтобы увидеть более крупные изменения». У вас уже довольно много задержек., @Edgar Bonet@EdgarBonet, так что вы думаете, я должен сравнить, выше или ниже, чем 1 v -1?, @Chritzeltopf
И это я мог бы зациклить, чтобы оно нажимало кнопку, которую я часто поворачивал, не так ли?, @Chritzeltopf
я хочу извинить за сокращение кода, что поздно, но теперь это так, раньше не было времени и забыл, когда я написал вопрос, @Chritzeltopf