Irinka
04.Август.2023 12:00:41
1
Здравствуйте.
К аналоговому входу ардуины подключен подтягивающий резистор 10к.
К этому же входу, через кнопки, подключены стягивающие резисторы разного номинала.
Соответственно при нажатии разных кнопок будут разные показания в порту.
Для удобства я написала класс обработки показаний с порта, а так же сделала функцию антидребезга, удержания кнопки.
Всё ли верно?
Спойлер
#define REMOTE_PIN A2
#define BUTTONS_PIN A3
class Resistive_keyboard {
public:
Resistive_keyboard(uint16_t min, uint16_t max, uint8_t pin, uint16_t delay);
bool get();
private:
uint16_t _min;//Минимальные показания
uint16_t _max;//Максимальные показания
uint8_t _pin;//Номер аналогового порта
uint16_t _delay;//АнтиДребезг'
uint32_t _tmr;
uint8_t _stage;
bool _status;
};
Resistive_keyboard::Resistive_keyboard(uint16_t min, uint16_t max, uint8_t pin, uint16_t delay) {
_min = min;
_max = max;
_pin = pin;
_delay = delay;
}
bool Resistive_keyboard::get() {
uint16_t _sensor = analogRead(_pin);
_status = false;
switch (_stage) {
case 0:
if (_sensor > _min && _sensor < _max) {
_stage = 1;
_tmr = millis();
}
break;
case 1:
if (_sensor > _min && _sensor < _max) {
if (millis() - _tmr >= _delay) _status = true;
} else {
_stage = 0;
}
break;
}
return _status;
}
Resistive_keyboard Up(80,100,3,500);
Resistive_keyboard Down(270,300,2,1000);
void setup() {
}
void loop() {
if (Up.get()){}
if (Down.get()){}
}
te238s
04.Август.2023 12:18:10
2
Мне кажется,в таком деле нужно усреднять показания АЦП. Это не совсем антидребезг.
А кнопки 2 только? Ну может прокатит.
Irinka
04.Август.2023 12:26:30
3
Кнопок будет 6 штук.
Resistive_keyboard Up(80, 100, BUTTONS_PIN, 500);
Почему срабатывает только один раз при старте прогаммы?
Спойлер
#define REMOTE_PIN A2
#define BUTTONS_PIN A3
#define MOTOR1_PIN 1//Вверх
#define MOTOR2_PIN 2//Вниз
#define MOTOR1_ON digitalWrite(MOTOR1_PIN, HIGH)
#define MOTOR1_OFF digitalWrite(MOTOR1_PIN, LOW)
#define MOTOR2_ON digitalWrite(MOTOR2_PIN, HIGH)
#define MOTOR2_OFF digitalWrite(MOTOR2_PIN, LOW)
#define MAX_TIME_UP 2000
#define MAX_TIME_DOWN 2000
bool motor_flag;
uint32_t motor_tmr;
uint32_t motor_off;
class Resistive_keyboard {
public:
Resistive_keyboard(uint16_t min, uint16_t max, uint8_t pin, uint16_t delay);
bool get();
private:
uint16_t _min;
uint16_t _max;
uint8_t _pin;
uint16_t _delay;
uint32_t _tmr;
uint8_t _stage;
bool _status;
};
Resistive_keyboard::Resistive_keyboard(uint16_t min, uint16_t max, uint8_t pin, uint16_t delay) {
_min = min;
_max = max;
_pin = pin;
_delay = delay;
}
bool Resistive_keyboard::get() {
uint16_t _sensor = analogRead(_pin);
_status = false;
switch (_stage) {
case 0:
if (_sensor > _min && _sensor < _max) {
_stage = 1;
_tmr = millis();
}
break;
case 1:
if (_sensor > _min && _sensor < _max) {
if (millis() - _tmr >= _delay) _status = true;
} else {
_stage = 0;
}
break;
}
return _status;
}
Resistive_keyboard Up(80, 100, BUTTONS_PIN, 500);
Resistive_keyboard Down(270, 300, BUTTONS_PIN, 500);
void setup() {
pinMode(MOTOR1_PIN, OUTPUT);
pinMode(MOTOR2_PIN, OUTPUT);
MOTOR1_OFF;
MOTOR2_OFF;
}
void loop() {
if (Up.get()) {
MOTOR1_ON;
MOTOR2_OFF;
motor_flag = true;
motor_tmr = millis();
motor_off = MAX_TIME_UP;
}
if (Down.get()) {
MOTOR1_OFF;
MOTOR2_ON;
motor_flag = true;
motor_tmr = millis();
motor_off = MAX_TIME_DOWN;
}
if (motor_flag && millis() - motor_tmr >= motor_off ) {
motor_flag = false;
MOTOR1_OFF;
MOTOR2_OFF;
}
}
Лучше как-то так:
private:
uint8_t counter = 0x00;
bool buttonActive = false;
....
read() {
...
counter = counter << 1 | (_sensor > _min && _sensor < _max);
if (counter == 0xFF) { buttonActive = true; }
if (counter == 0x00) { buttonActive = false; }
}
Только внутри read() по типу “блинк без дилей” читать и анализировать каждую 1мс.
1 лайк
te238s
04.Август.2023 12:33:08
5
Очевидно,потому что где-то какой-то флаг не сбрасывается обратно. Сложно сказать,не совсем понятна логика работы.
Irinka
04.Август.2023 12:35:03
6
Если я свои показания (80-100 и 270-300) передаю в класс непосредственно в loop, то всё работает правильно.
Спойлер
#define REMOTE_PIN A2
#define BUTTONS_PIN A3
#define MOTOR1_PIN 1
#define MOTOR2_PIN 2
#define MOTOR1_ON digitalWrite(MOTOR1_PIN, HIGH)
#define MOTOR1_OFF digitalWrite(MOTOR1_PIN, LOW)
#define MOTOR2_ON digitalWrite(MOTOR2_PIN, HIGH)
#define MOTOR2_OFF digitalWrite(MOTOR2_PIN, LOW)
#define MAX_TIME_UP 2000
#define MAX_TIME_DOWN 2000
bool motor_flag;
uint32_t motor_tmr;
uint32_t motor_off;
class Resistive_keyboard {
public:
Resistive_keyboard(uint8_t pin, uint16_t delay);
bool get(uint16_t min, uint16_t max);
private:
uint8_t _pin;
uint16_t _delay;
uint32_t _tmr;
uint8_t _stage;
bool _status;
};
Resistive_keyboard::Resistive_keyboard(uint8_t pin, uint16_t delay) {
_pin = pin;
_delay = delay;
}
bool Resistive_keyboard::get(uint16_t min, uint16_t max) {
uint16_t _sensor = analogRead(_pin);
_status = false;
switch (_stage) {
case 0:
if (_sensor > min && _sensor < max) {
_stage = 1;
_tmr = millis();
}
break;
case 1:
if (_sensor > min && _sensor < max) {
if (millis() - _tmr >= _delay) _status = true;
} else {
_stage = 0;
}
break;
}
return _status;
}
Resistive_keyboard Up(BUTTONS_PIN, 500);
Resistive_keyboard Down(BUTTONS_PIN, 500);
void setup() {
pinMode(MOTOR1_PIN, OUTPUT);
pinMode(MOTOR2_PIN, OUTPUT);
MOTOR1_OFF;
MOTOR2_OFF;
}
void loop() {
if (Up.get(80,100)) {
MOTOR1_ON;
MOTOR2_OFF;
motor_flag = true;
motor_tmr = millis();
motor_off = MAX_TIME_UP;
}
if (Down.get(270,300)) {
MOTOR1_OFF;
MOTOR2_ON;
motor_flag = true;
motor_tmr = millis();
motor_off = MAX_TIME_DOWN;
}
if (motor_flag && millis() - motor_tmr >= motor_off ) {
motor_flag = false;
MOTOR1_OFF;
MOTOR2_OFF;
}
}
Иринка, если Вы не пожадничаете поставить SPDT кнопки и к ним микросхему CD4043BE в качестве RS-триггера (одной хватает на 4 кнопки), то можете использовать классическую схему R-2-R и напрочь забыть о дребезге - его не будет просто по определению.
Вот тема с объяснением про R-2-R , а вот продолжение , где и появляется эта микросхема.
У меня работает на ура.
Irinka
04.Август.2023 13:24:51
8
Большое спасибо.
А можно попросить схему подключения?
Такие не подойдут, вместо CD4043?
Я себе на будущие проекты хочу заказть.
А в данной ситуации, резисторы уже распаяны на плате.
нет, 4043 это RS тригер, а 4011 это логика 4 - 2И-НЕ.
1 лайк
Да, конечно. Тут смотрите по распиновке слева пины S (1-4), R (1-4) и Q(1-4). А справа нарисовано как подключить одну SDPT кнопку в пинам S, R и Q.
Т.е. на одну микросхему 4 кнопки.
Сама микросхема не редкая. Сейчас посмотрел - и на ali навалом и в России. Если Вас не смущает корпус SOP, то вон в чипедипе всего по 11 рублей . В корпусе DIP подороже , но на ali есть по 17 рублей .
1 лайк
Irinka
04.Август.2023 14:42:27
11
Косячный у меня класс получился. Добавила третью кнопку, и задержка на первой не работает. При нажатии сразу срабатывает.
В автомобильной кнопке для управления стеклоподъемником два положения туда и два обратно. Я её не разбирал, но там, вроде, делитель с переменным плечом. При переключении в воздухе контакт не болтается совсем уж беспредельно. Со счётчиком фильтруется нормально.
Upper
04.Август.2023 16:54:58
14
У меня на UNO в протеусе работает не один раз (наверно как задумано). Код из поста номер 3, без изменений. Кнопки R3 и R4
Irinka
04.Август.2023 18:35:35
15
Работает.
Значит какие-то проблемы с аттини13 в протеусе.
Upper
04.Август.2023 19:35:47
16
Возможно просто оперативки не хватает, и протеус не виноват.
1 лайк
Irinka
05.Август.2023 06:33:17
17
Ресурсов ПК точно хватает, с UNO всё правильно работает в протеусе, проверила.
Спойлер
Upper
05.Август.2023 06:43:33
18
Я про память ОЗУ аттини13 писал. (Наверное зря применил термин “оперативки”)
1 лайк
Irinka
05.Август.2023 06:47:42
19
Поняла. Проверю по устройстве. Спасибо.
Upper
05.Август.2023 07:00:02
20
А как вы это планируете проверить на устройстве?
ПРОВЕРЯТЬ можно в поротеусе. Ставите условие прерывания для порогового значения указателя стека и смотрите. (Сам правда на практике к такому не прибегал).
1 лайк
Irinka
05.Август.2023 09:24:20
21
Так то да, иде даже писала что недостаточно памяти)