Gyver Stepper, вопросы по библиотеке

KovAlex

✩✩✩✩✩✩✩
9 Фев 2022
25
0
В процессе создания контроллера управления поворотным устройством антенны, споткнулся с проблемой отказа работы ОДНОЙ кнопки аналоговой клавиатуры.
Сразу поясню, почему спрашиваю здесь.
Причина такова - ТОЛЬКО после останова ШД(GStepper2 ISR) на заданной позиции, подпрограмма обработки клавиатуры перестаёт "видеть" одну кнопку.
Тупо не видит и тупо ОДНУ кнопку!
Клавиатура примитивная - три резистора, соединённых последовательно с VCC, три кнопки подключают "GND" с точек соединения резисторов.
Первая "точка соединения" подключена к А3 ардуино нано.
Работать перестаёт кнопка, подключающая "GND" на пин А3.
Код:
Код:
#include <EncButton.h>

EncButton enc(2, 3, 4);                 // энкодер с кнопкой CLK, DT, SW
VirtButton btnUP;
VirtButton btnDWN;
VirtButton btnSET;

// создаём массив значений сигналов с кнопок
int16_t sigs[3] = {
  340, 140, 0
};

enum {
  None = 0,
  UpClick,
  DownClick,
  UpHold,
  DownHold,
  SelClick,
  SelHold,
  TurnRight,
  TurnLeft,
  TurnRH,
  TurnLH,
  EClick
};

#include "AnalogKey.h"

// указываем пин, количество кнопок и массив значений
AnalogKey<A3, 3, sigs> keys;

// подпрограмма чтения клавиатуры

int8_t ReadKey() {
  int8_t code = 0;
  if (btnUP.tick(keys.status(0))) {
    if (btnUP.click()) code = UpClick;
    if (btnUP.hold())  code = UpHold;
  }
  if (btnDWN.tick(keys.status(1))) {
    if (btnDWN.click())code = DownClick;
    if (btnDWN.hold()) code = DownHold;
  }
  if (btnSET.tick(keys.status(2))) {
    if (btnSET.click())code = SelClick;
    if (btnSET.hold()) code = SelHold;
  }
  if (code) return code;
  else return None;
}
Другие две кнопки (btnUP и btnDWN) ReadKey в это время "видит", кнопку btnSET - ни в какую..

Третий день выношу мозг себе и коллеге.. :(
 
Изменено:

poty

★★★★★★✩
19 Фев 2020
2,990
895
... три резистора, соединённых последовательно с VCC, три кнопки подключают "GND" с точек соединения резисторов. Первая "точка соединения" подключена к А3 ардуино нано.
Т.е.:
VCC
-
R1
|-----A3----btnSET---GND
R2
|---btnUP---GND
R3
|---btnDWN---GND

Так? А каковы номиналы резисторов? Возможно, что кнопка имеет плохой контакт и не даёт точного нуля на выходе. Можно попробовать увеличить последнее значение в массиве sigs.
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,190
1,280
Москва
Возможность выводить отладочные сообщения в монитор порта есть ? Если есть -просто вывести перед чтением клавиатуры аналоговое значение с пина А3 и посмотреть на сколько значение меняется до управления и после управления при нажатии на кнопку set
Не хватает кода части где выдается результат метода keys.status(n)
 

KovAlex

✩✩✩✩✩✩✩
9 Фев 2022
25
0
Да, клавиатура такая, как вы "нарисовали".
Аппаратной проблемы нет однозначно. Кнопки новые, все напряжения +- соответствуют указанным в массиве числам.
Ещё раз повторюсь - клавиатура работает без нареканий во всех частях софта до момента использования моторов.
После чего перестаёт работать ТОЛЬКО кнопка btnSEL. Как будто какая-то "маска" накладывается на данные порта А3.
Кстати, сейчас моторы не подключены( это я про то, что могли влиять импульсы от обмоток двигателей).
Не хватает кода части где выдается результат метода keys.status
Не понял, о чём вы?..

P.S. Интересное кино.. Чтобы посмотреть значения на пине клавиатуры, добавил в начало ReadKey следующее
Код:
void ReadKey() {
int16_t v = analogRead(A3);
Serial.print("A3=");
Serial.println(v);
...
}
и кнопка перестала реагировать на работу stepper-а!! Работает во всех случаях.
Я в ступоре... Что за такую "защёлку" ставит stepper, которую "снимает" analogRead?? :unsure:
Кстати, данные analogRead соответствуют (небольшой +-, конечно) измеренным напряжениям.
И btnSEL выдаёт "чистый 0".
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,190
1,280
Москва
Ну а какие значения то выдает при нажатой кнопке без работы и с работой степера ? на сколько разные/одинаковые ?
 

KovAlex

✩✩✩✩✩✩✩
9 Фев 2022
25
0
Одинаковые.

P.S. Методом дедукции с коллегой удалось родить грандиозный и непонятный костыль.
В setup (!!!) скетча добавили строку - analogRead(A3);
И проблема ушла..

ЧуднЫ дела твои, ARDUINO! :)
 
Изменено:

tirukaly

✩✩✩✩✩✩✩
26 Сен 2023
3
0
Здравствуйте. Помогите!) Всю голову уже сломал. Шаговый мотор имеет несколько режимов работы. По Serial передается переменная, на основании этой переменной выбирается функция. Но функция должна работать до передачи другой переменной, а в моем случае работает только на долю секунды: один шаг мотора, я подозреваю. Второй день гуглю, все бестолку.
C++:
#define SMOOTH_ALGORITHM
#include <GyverStepper.h>
GStepper<STEPPER2WIRE> stepper(6400, 4, 3, 2);
int speed;

void setup() {
  Serial.begin(9600);
}
void loop() {
  speed = Serial.read ();
  switch (speed) {
    case 's': Slow ();
    break;
    case 'f': Fast ();
    break;
  }
}
    
void Slow () {
  stepper.setRunMode(FOLLOW_POS);
  stepper.setMaxSpeed(400);
  stepper.setAcceleration(500);
  if  (!stepper.tick()) {
        static bool dir;
        dir = !dir;
        stepper.setTarget(dir ? -400 : 400);
      }
}

void Fast () {
  stepper.setRunMode(FOLLOW_POS);
  stepper.setMaxSpeed(2000);
  stepper.setAcceleration(2000);
  if  (!stepper.tick()) {
        static bool dir;
        dir = !dir;
        stepper.setTarget(dir ? -400 : 400);
      }
}
 

poty

★★★★★★✩
19 Фев 2020
2,990
895
@tirukaly,
1. Что делает Ваш код, если входной команды нет? Вы это как-то обрабатываете сейчас? Мне вот интересно, что Вы "гуглите" по этой проблеме?
2. Если Вы будете постоянно вызывать функции Slow и Fast, для того, чтобы они "работали", что Вы получите? (Подсказка - переменная dir)
 
  • Лойс +1
Реакции: tirukaly

tirukaly

✩✩✩✩✩✩✩
26 Сен 2023
3
0
@poty, до поступления команды через Serial мотор стоит, после поступления должен непрерывно работать в одном из режимов. Потом еще команда - и дальше непрерывно в другом режиме.
Гуглил я многое. Сначала думал, что неправильно посылаю сигналы на Serial, пока не вычитал про отладку. Потом думал (и все еще думаю), что есть какие-то особенности с использованием if, либо с связанные с тем, что loop выполняется циклично, а значит в переменная speed постоянно обнуляется. Так то опыт программирования небольшой есть, но только на С, поэтому хватаю везде по верхам, чтобы задуманное решить.
Вот про dir не понял. Это же просто направление вращения?
 

vortigont

★★★★★✩✩
24 Апр 2020
900
487
Saint-Petersburg, Russia
@tirukaly, вы хоть в документацию заглянули о том что возвращает функция
Serial.read()? Подсказка: она возвращает (-1) если через сериал ничего не пришло. Дальше думайте сами что получится у вас в switch и почему все стоит кроме одного шага когда все-таки вы иногда что-то отправляете в порт.
 
  • Лойс +1
Реакции: poty

tirukaly

✩✩✩✩✩✩✩
26 Сен 2023
3
0
@vortigont, Спасибо за ответы. Я немного поправил код. Теперь Сериал отфильтровывает -1, в терминале вижу только f, carriage return и line feed (повторил простой скетч с управлением светодиодом, там они не мешают, подумал, что и здесь значение не должны иметь). Так же поменял свитч на более понятные мне условия. Однако проблема все равно на месте. Можете дать более очевидную подсказку?) С обеда сижу, ковыряюсь и так и эдак. Код управления мотором взят из библиотеки Алекса, отдельно от условий работает как надо.
C++:
#define SMOOTH_ALGORITHM
#include <GyverStepper.h>
GStepper<STEPPER2WIRE> stepper(6400, 4, 3, 2);
char speed;

void setup() {
  Serial.begin(9600);
  Serial.println ("test_begin");
  stepper.setRunMode(FOLLOW_POS);
}
void loop() {
 
  if (Serial.available() > 0) {
    speed = Serial.read ();
    Serial.print("I received: ");
    Serial.println(speed);
  }
    
  if (speed == 's') {
    stepper.setMaxSpeed(400);
    stepper.setAcceleration(500);
    if  (!stepper.tick()) {
        static bool dir;
        dir = !dir;
        stepper.setTarget(dir ? -400 : 400);
      }
  }
  else if (speed == 'f') {
    stepper.setRunMode(FOLLOW_POS);
    stepper.setMaxSpeed(4000);
    stepper.setAcceleration(4000);
    if  (!stepper.tick()) {
        static bool dir;
        dir = !dir;
        stepper.setTarget(dir ? -400 : 400);
      }
  }
  else {
    stepper.setMaxSpeed(100);
    stepper.setAcceleration(100);
    if  (!stepper.tick()) {
        static bool dir;
        dir = !dir;
        stepper.setTarget(dir ? -40 : 40);
      }
  }
 
}
@tirukaly, решение лежало на поверхности... Пишу для тех, кто столкнется с такой же проблемой. Всем спасибо.
C++:
static char speed = 0;
  if (Serial.available() > 0) {
    char input = Serial.read();
      if (input != '\n' && input != '\r') {
        speed = input;
        }
  }
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,190
1,280
Москва
Не надо ничего фильтровать, кроме базара.
У сериал есть отличная функция : Serial.available(), что возвращает ttue в случае наличия в буфере новых , непрочитанных данных.