Алексей
я взял старый вариант которому больше двух лет где описывал каждую кпопку отдельно
Алексей
и тоже только три кнопки работает
Алексей
я хз, в чем дело
Ivansuper
Алексей Тюрин, [09.09.20 15:52]
это main.cpp
Алексей Тюрин, [09.09.20 15:52]
#include <Arduino.h>
//#include <LiquidCrystal_I2C.h>
//const uint8_t COLUMN = 20;
//const uint8_t LINE = 4;
//LiquidCrystal_I2C lcd(0x27,COLUMN, LINE);
bool btn_menu = false;
bool btn_up = false;
bool btn_down = false;
bool btn_left = false;
bool btn_right = false;
//#include <_general.h>
#include <_button.h>
//#include <_lcd.h>
void setup()
{
//Get_LCD_Print();
Serial.begin(9600);
}
void loop()
{
// Set_Button(8, btn_right);
Set_Button_Left(9);
if (btn_left == true)
{
Serial.print("LEFT ");
}
Set_Button_Down(10);
if (btn_down == true)
{
Serial.print("DOWN ");
}
Set_Button_Up(11);
if (btn_up == true)
{
Serial.print("Up ");
}
Set_Button_Menu(12);
if (btn_menu == true)
{
Serial.print("Menu ");
}
}
Алексей Тюрин, [09.09.20 15:53]
это _button.h
Алексей Тюрин, [09.09.20 15:53]
//bool Set_Delay_Millis(uint32_t, uint32_t);
void Set_Button_Menu(const uint8_t PIN_BTN_MENU)
{
static bool setup = false;
if (!setup)
{
pinMode(PIN_BTN_MENU, INPUT_PULLUP);
setup = true;
}
btn_menu = false;
uint32_t first_time = millis();
uint32_t click_timer;
while (digitalRead(PIN_BTN_MENU))
{
btn_menu = false;
}
click_timer = millis();
if (click_timer - first_time < 20)
return;
click_timer = millis();
btn_menu = true;
}
void Set_Button_Up(const uint8_t PIN_BTN_UP)
{
static bool setup = false;
if (!setup)
{
pinMode(PIN_BTN_UP, INPUT_PULLUP);
setup = true;
}
btn_up = false;
uint32_t first_time = millis();
uint32_t click_timer;
while (digitalRead(PIN_BTN_UP))
{
btn_up = false;
delay(1);
}
click_timer = millis();
if (click_timer - first_time < 20)
return;
click_timer = millis();
btn_up = true;
}
void Set_Button_Down(const uint8_t PIN_BTN_DOWN)
{
static bool setup = false;
if (!setup)
{
pinMode(PIN_BTN_DOWN, INPUT_PULLUP);
setup = true;
}
btn_down = false;
uint32_t first_time = millis();
uint32_t click_timer;
while (digitalRead(PIN_BTN_DOWN))
{
btn_down = false;
delay(1);
}
click_timer = millis();
if (click_timer - first_time < 20)
return;
click_timer = millis();
btn_down = true;
}
void Set_Button_Left(const uint8_t PIN_BTN_LEFT)
{
static bool setup = false;
if (!setup)
{
pinMode(PIN_BTN_LEFT, INPUT_PULLUP);
setup = true;
}
btn_left = false;
uint32_t first_time = millis();
uint32_t click_timer;
while (digitalRead(PIN_BTN_LEFT))
{
btn_left = false;
delay(1);
}
click_timer = millis();
if (click_timer - first_time < 20)
return;
click_timer = millis();
btn_left = true;
}
/*void Set_Button(const uint8_t &PIN, bool &a)
{
static bool setup = false;
if (!setup)
{
pinMode(PIN, INPUT_PULLUP);
setup = true;
}
a = false;
uint32_t first_time = millis();
uint32_t click_timer;
while (digitalRead(PIN))
{
a = false;
if (Set_Delay_Millis(click_timer, first_time, 20))
a = true;
}
}
*/
Алексей Тюрин, [09.09.20 15:53]
это _general.h
Алексей Тюрин, [09.09.20 15:53]
bool Set_Delay_Millis(uint32_t &a, uint32_t &b, const uint8_t &DELAY_MILLIS)
{
a = millis();
if (a - b < DELAY_MILLIS)
return false;
a = millis();
return true;
}
Для начала -- после return писать код бесполезно
Ivansuper
Для продолжения -- здесь вряд ли, но лучше не пользоваться скоростями сериала низкими. Там задержка на принт символа огромная, и при достаточных количествах вывода код начнет задыхаться
Алексей
ну как бы выход вункциb void если время меньше 20 миллисекунд, что бы дальнейшее не обрабатывать,
Алексей
так и если монитор подключить, если три функции кнопки то можно менять значение любой цифры в плюс в минул если их 4 то все , не работают они тупо
Василий
данный код обречен, он взаимо зависим, надо переписывать - что бы небыло никаких ожиданий и переключений на ходу
Ivansuper
И финал -- ты в функциях для кнопок поставил while циклы безвыходные пока с пина не свалится ноль. В итоге если кнопка не нажата, то код застрянет в цикле
Василий
лучше сделать вообще по прерыванию
Ivansuper
Ты должен один раз проверить и выйти из функции
Ivansuper
Алексей
Ivansuper
Ivansuper
Вбей в гугл, найдешь примеры
Ivansuper
Главное с прерываниями помни про аттрибут IRAM_ATTR. Ибо функция обязана быть в RAM и только там
Алексей
Ivansuper
Во-первых — видео и голосовые кидать это не очень хорошо. Не у всех есть возможность их прослушать, чтобы продолжить беседу
Алексей
ну извените
Ivansuper
Во-вторых — код изначально проблемный, поэтому аргумент "раньше работало" не очень хороший
Ivansuper
Я понимаю, что у тебя эмоции отчасти зло на неработающий код
Ivansuper
Но переделай ты нормально
Ivansuper
Что за плата у тебя?
Ivansuper
http://arduino.ru/Reference/AttachInterrupt
Ivansuper
Все. Это прерывания в ардуино
Алексей
ардуино уно, я по разному делал и с while и без него, но все работает ровно до трех кнопок. Спасибо буду читать
Ivansuper
Вешаешь прерывания на спад сигнала, по прерыванию ставишь button_pressed = true
Ivansuper
Ivansuper
Ivansuper
Но на уно их только два. Капец
Алексей
Ну я вот и прочел про два, поэтому у меня и вопрос этот появился
Ivansuper
Ivansuper
И че то я не пойму, ты еще в булевыми финты какие то делаешь
Ivansuper
btn_menu = digitalRead() == LOW;
Все
Алексей
Ну да если кнопка нажата, тоесть цикk while но время меньше 20 миллисекунд прошло то в любом случае это лож, а если , больше то это истина
Ivansuper
По скольку ты сделал PULLUP, у тебя по умолчанию оно вверх подтянуто, и для нажатия тебе надо коротить к земле
Алексей
это антидребезг
Ivansuper
К слову может ты кнопку коротишь не к земле, и от того у тебя часть работает а часть нет
Алексей
Ладно, спасибо за помощь, буду переделывать
romanetz
Эх, не работал человек с ПЛК....
Там если время скана (цикла while(1) главного) превысишь - по башке от гипервизора прилетает )) сразу учишься писать код без бесконечных циклов
romanetz
И непонятных ожиданий )
romanetz
Фронт задетектил нужный, таймер запустил - и дальше опрашивать )
Алексей
romanetz
А почему, собсно, он ничего не делает? Пусть крутится в основном цикле тогда ) если нужно будет, чтобы делал - сможет
romanetz
Например, я делал аналогичную затею с зажатием кнопок в меню, только на "заднем плане" ещё строчки бегущие на дисплей выводились
romanetz
Названия песен, по-моему, если помню правильно
Ivansuper
А разве ардуина не сделает суицид и ребут от долгой работы в лупе без yield?
Алексей
как мне обьясняли что пока кнопку не отпустишь то в любом разе контроллер не на что не реагирует, не принимает с датчиков значения и тд и тп
Ivansuper
romanetz
Алексей
Ну если бы это был двух ядерный контроллер, попробуйте нажать кнопку при передаче данных в сериал, много будет передаваться их туда?
romanetz
Да все, собсно, которые должны быть отправлены
romanetz
При нажатиях кнопок интересуют их фронты и длительность состояния
romanetz
Фсё!
romanetz
Не надо там сто ядер для этого
Алексей
пробую не получается, вы уж ссаными тряпками не кидайтесь , я совсем новичок
romanetz
typedef struct
{
bool prev_button_state;
bool changed;
unsigned long state0_length;
unsigned long state1_length;
} button_struct;
void button_processing (bool button_state,button_struct* t,unsigned long scantime)
{
t->changed=(button_state!=t->prev_button_state);
t->state0_length=!button_state?t->state0_length+scantime:0;
t->state1_length=button_state?t->state1_length+scantime:0;
t->prev_button_state=button_state;
}
romanetz
я бы как-то так это замутил
romanetz
по вкусу прибавить проверки на нулевой указатель, объявления переменных и работу в цикле
Ivansuper
Он сказал, что он не программист совсем. У него там паника начнется
romanetz
scantime берётся из таймера какого-нибудь, как время между вызовами функции
Алексей
Ivansuper
: )
romanetz
romanetz
328 мега - это старшая сестра 48/88/168? а там PCINT были... давно с аврками дел не имел, поправьте, если что
romanetz
как раз прерывания по фронтам/портам, почти по всем ножкам
Алексей
Ivansuper
а там PCINT нету разве?
К сожалению тут не скажу ничего. Те часы, что я провел за нативными ардуино платами, можно по пальцам пересчитать
Василий
romanetz
Ну тоды, если очень хочется, можно поспать даже контроллеру, если ему больше делать нефиг )) уменьшим жор МК и свой вклад в глобальное потепление )))
AntikillerVova 🇷🇺
Как он реагирует на на фронты я точно не знаю, но скорее всего если отработать надо по спаду, то он фиксирует "1", и после каждого пролёта строчки где указан отработать по спаду он сравнивает с "1" если без изменений то пролетает дальше, если было изменение то он выполняет код
AntikillerVova 🇷🇺
Может я не прав
AntikillerVova 🇷🇺
Но как мне говорили, что код выполняется по очереди(по строчно)
AntikillerVova 🇷🇺
Ах да, на ардуино используй miles вместо delay
AntikillerVova 🇷🇺
Чтобы мк не халявничел