Вешается Нано при использовании if
- Войдите на сайт для отправки комментариев
Добрый вечер! Рискую разжечь много стульев под старожилами форума, и прослыть недалёким человеком. Но всё же.
В электронике любитель со стажем, а вот программирование недавно начал постигать. Повторял пару готовых проектов на ардуино, все достаточно легко получилось, теперь захотелось сделать своё что-то, поскольку готового один в один проекта под мои нужды нет, решил постепенно собирать свой скетч используя примеры. Проект - это банальный селектор на 4 аудиовхода на реле, с перебиранием входов 1 кнопкой, выводом названия входа на 3 матрицы 8х8+МАХ7219, и в период бездействия выводом спектроанализатора. Код закомментирован мной, что как должно работать построчно понимаю, алгоритм тоже понимаю. Но Закоментированный if в 80-82 строке вешает ардуино, если его расскоментировать. По моей логике проверяемый там btnflagPush должен отправлять в функцию вывода бегущей строки tape, она его выводит и сбрасывает флаг, указывая что вывод был, дальше проверяется каждый цикл, флаг поднимается при нажатии кнопки- изменении состояния и tape, все, дальше должно крутится loop, если условие не выполняется Сам спектроанализатор(код в loop) крутится, в конце проверяется изменение btnflagPush , опрашивается функция кнопки. Вообще подумал, что ардуино издохло, когда оно зависло.
Запаситесь льдом при просмотре моего скетча.!
/* Д.КР. Copyright (c) 2021 Переключение последовательно кнопкой четырех реле, для коммутации входов D3-вход кнопки, на землю, подтяжка резистором 10К к плюсу. D4, D5, D6, D7 - выходы на реле. */ //Общие настройки, библиотеки #include <SPI.h> // Подключаем библиотеку SPI #include <Adafruit_GFX.h> // Подключаем библиотеку Adafruit_GFX #include <Max72xxPanel.h> // Подключаем библиотеку Max72xxPanel int pinCS = 10; // Указываем к какому выводу подключен контакт CS int numberOfHorizontalDisplays = 1; // Количество матриц по горизонтали int numberOfVerticalDisplays = 3; // Количество матриц по-вертикали Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays); // Настройки для функции вывода бегущей строки list() String tape = ""; // Слово для вывода на матрицу int wait = 50; // интервал, чем меньше тем бытрее бежит строка int spacer = 1; // Промежуток между символами (кол-во точек) int width = 5 + spacer; // Ширина шрифта составляет 5 пикселей // Конец настроек // Настройки для функции переключения реле modeChange() int modeState = 4; // Переменная, которая указывает номер включенного реле, по умолчанию включается реле с этим номером сразу при запуске bool btnflagPush = true; // Флаг что кнопка была нажата bool btnflag = false; // Флаг, который будет помнить состояние кнопки uint32_t btnTimer = 0; // таймер нажатия для антидребезга // Конец настроек void setup() { // отладка Serial.begin(9600); // Инициализация выводов для pinMode(3, INPUT); // D3 как вход pinMode(4, OUTPUT); // D4 как выход pinMode(5, OUTPUT); // D5 как выход pinMode(6, OUTPUT); // D6 как выход pinMode(7, OUTPUT); // D7 как выход digitalWrite(modeState, HIGH); // высокий сигнал на реле, по умолчанию включается это реле // Начальная инициализация матрицы и вывод приветствия matrix.setIntensity(5); // Задаем яркость от 0 до 15 matrix.setRotation(1); // Направление текста 1,2,3,4 tape = utf8rus("Морион Э-103"); // Приветствие 1 раз, возвращается, utf8rus Функцией перекодировки русских букв из UTF-8 в Win-1251 tape = list(tape); // Отправляем на вывод в функцию list btnflagPush = true; // Флаг поднимаем, что бы вевести надпись про вход } void loop() { Serial.println(modeState); // Для отладки Serial.println(btnflagPush); // Для отладки modeChange (); // Проверка состояния кнопки и переключение режимов входа //if (btnflagPush == true) { // tape = list(tape); // Проверяем было ли нажатие на кнопку и выводим на матрицу //} } void modeChange() { bool btnState = !digitalRead(3); // читаем инвертированное значение для удобства if (btnState && !btnflag && millis() - btnTimer > 100) { btnflag = true; // Кнопка нажата btnTimer = millis(); } if (!btnState && btnflag && millis() - btnTimer > 100) { btnflag = false; // Кнопка отпущена btnflagPush = true; // Было действие на кнопке btnTimer = millis(); Serial.println("release");// Для отладки modeState = modeState + 1; } { switch (modeState) { // Переключаем последовательно выходы D4-D7 case 4: digitalWrite(5, LOW); // выключается это реле digitalWrite(6, LOW); // выключается это реле digitalWrite(7, LOW); // выключается это реле digitalWrite(4, HIGH); // высокий сигнал на реле, включается это реле tape = utf8rus("Вход 1"); // Присваиваем название для вывода на матрицу break; case 5: digitalWrite(4, LOW); // выключается это реле digitalWrite(6, LOW); // выключается это реле digitalWrite(7, LOW); // выключается это реле digitalWrite(5, HIGH); // высокий сигнал на реле, включается это реле tape = utf8rus("Вход 2"); // Присваиваем название для вывода на матрицу break; case 6: digitalWrite(4, LOW); // выключается это реле digitalWrite(5, LOW); // выключается это реле digitalWrite(7, LOW); // выключается это реле digitalWrite(6, HIGH); // высокий сигнал на реле, включается это реле tape = utf8rus("Вход 3"); // Присваиваем название для вывода на матрицу break; case 7: digitalWrite(4, LOW); // выключается это реле digitalWrite(5, LOW); // выключается это реле digitalWrite(6, LOW); // выключается это реле digitalWrite(7, HIGH); // высокий сигнал на реле, включается это реле tape = utf8rus("Вход 4"); // Присваиваем название для вывода на матрицу break; default: modeState = 4; // выполнить, если значение не совпадает ни с одним из case break; } } } String list(String source) { for ( int i = 0 ; i < width * tape.length() + matrix.width() - spacer; i++ ) { matrix.fillScreen(LOW); int letter = i / width; // номер символа выводимого на матрицу int x = (matrix.width() - 1) - i % width; int y = (matrix.height() - 8) / 2; // отцентрировать текст по вертикали while ( x + width - spacer >= 0 && letter >= 0 ) { if ( letter < tape.length() ) { matrix.drawChar(x, y, tape[letter], HIGH, LOW, 1); } letter--; x -= width; } matrix.write(); // выведим значения на матрицу delay(wait); } btnflagPush = false; // Сбрасываем флаг кнопки, поскольку вывели надпись 1 раз } /* Функция перекодировки русских букв из UTF-8 в Win-1251 */ String utf8rus(String source) { int i, k; String target; unsigned char n; char m[2] = { '0', '\0' }; k = source.length(); i = 0; while (i < k) { n = source[i]; i++; if (n >= 0xC0) { switch (n) { case 0xD0: { n = source[i]; i++; if (n == 0x81) { n = 0xA8; break; } if (n >= 0x90 && n <= 0xBF) n = n + 0x2F; break; } case 0xD1: { n = source[i]; i++; if (n == 0x91) { n = 0xB7; break; } if (n >= 0x80 && n <= 0x8F) n = n + 0x6F; break; } } } m[0] = n; target = target + String(m); } return target; }
А-я-яй, молодой человек! Нехорошо дедушек обманывать!
В 81 строке Вы чего пишете? А в п/п list() где return?
Я бы от такого тоже повесился.
Функция list не возвращает ничего. Вы это ничего присваиваете переменной tape, а потом в наглую используете, как если бы это было не ничего, а прямо-таки строка "
Ну, и кто ты сможет не повеситься?
А-я-яй, молодой человек! Нехорошо дедушек обманывать!
В 81 строке Вы чего пишете? А в п/п list() где return?
Я бы от такого тоже повесился.
Функция list не возвращает ничего. Вы это ничего присваиваете переменной tape, а потом в наглую используете, как если бы это было не ничего, а прямо-таки строка "
Ну, и кто ты сможет не повеситься?
А как правильно передать тогда аргумент в функцию? list(tape); ? Если в 81 и до кучи уж в 56 так написать, то всё равно виснет на втором нажатии, вход1 при запуске пишет, клик кнопкой вход 2 и висяк. Может дело в синтаксисе, чего то простого не догоняю? или переполнение чего то? Но ведь без if , если просто тупо в луп выводить на матрицу значение тейп (постоянно пишет какой вход) можно кнопкой щелкать по кругу режимы(ну если момент поймать когда лист возвращается.)
А как правильно передать тогда аргумент в функцию?
Вы правильно передаёте аргумент (если не считать необоснованного расхода памяти, но если памяти хватает, то и хрен с ним).
Ваша проблема не в передаче аргумента, а в том, что Ваша функция НЕ возвращает никакого значения
Вы правильно передаёте аргумент (если не считать необоснованного расхода памяти, но если памяти хватает, то и хрен с ним).
Ваша проблема не в передаче аргумента, а в том, что Ваша функция НЕ возвращает никакого значения
Спасибо, но еще вас помучаю.
Смотрите, я передаю в функцию list глобальную переменную tape, функция выводит её на матрицу, заканчивает вывод, возвращается в loop, в то место откуда она вызвалась по условию. Она не меняет tape. Что она должна возвратить, ничего? Пусть в моем первом посте коряво написано tape = list(tape); Ставим list(tape); так же виснет ардуинка. Флаг, который в конце вывода list сбрасывается в false, указывает, что вывод был, и поднимается только после нажатия кнопки. Всё правильно?
155 строка у меня вызывает сомнение. tape.length()
Выведите-ка это в ком-порт
Она не меняет tape. Что она должна возвратить, ничего?
Тогда зачем вы пишите tape = list(tape) ?
так же виснет ардуинка. Флаг, который в конце вывода list сбрасывается в false, указывает, что вывод был, и поднимается только после нажатия кнопки. Всё правильно?
В чем выражается зависание?
Я дико извиняюсь, но где-то читал что во избежание ошибок компиляции лучше организовать прогу так что бы была с начала описана функция а потом следовал ее вызов
Я дико извиняюсь, но где-то читал что во избежание ошибок компиляции лучше организовать прогу так что бы была с начала описана функция а потом следовал ее вызов
При чем здесь это? Если функция ничего не возвращает, зачем присваивать переменной значение этой функции?
155 строка у меня вызывает сомнение. tape.length()
Выведите-ка это в ком-порт
Это длина слова переменной тейп, к библиотеке Adafruit_GFX относится
Ну и какова длина этой переменной после присвоения ей значения "ничто"?
Тогда зачем вы пишите tape = list(tape) ?
В чем выражается зависание?
Чуть исправился на list(tape);
Перестает ардуинка реагировать на кнопку, не выводит ничего на монитор порта. ресет только.
Тогда зачем вы пишите tape = list(tape) ?
В чем выражается зависание?
Чуть исправился на list(tape);
Перестает ардуинка реагировать на кнопку, не выводит ничего на монитор порта. ресет только.
А вы везде исправили? У вас же эта функция не в одном месте вызывается
Есть такая штука, как монитор порта.
Что мешает прописать вывод в этот самый монитор, на каждом шаге программы ?
ЗЫ: неясна работа в цикле while, я бы там покопал.
да 56 и 81 строка
Не могу понять, если убрать это в 81 строке, то опрос кнопки, присвоение тейп значения, корректно, если убрать if, оставить list(tape); тоже корректно входы переключаются, но на постоянку выводится название тейп Может еще в условии нужно что учитывать, не только флаг btnflagPush = true; // Было действие на кнопке 95 строка?
Если вы про функцию list(), то это взято отсюда, только выделил в функцию, поскольку она не часто нужна.
да 56 и 81 строка
Не могу понять, если убрать это в 81 строке, то опрос кнопки, присвоение тейп значения, корректно
Если корректно, то в чем проблема?
если убрать if, оставить list(tape); тоже корректно входы переключаются, но на постоянку выводится название тейп
Это естественно, по другому и быть не может. Зачем убирать if ?
Это естественно, по другому и быть не может. Зачем убирать if ?
С if работать перестаёт. Это условия, по моему мнению, должно работать для однократной отправки tape для вывода на матрицу, проверяемый там btnflagPush должен отправлять в функцию вывода бегущей строки tape, она его выводит и сбрасывает флаг, указывая что вывод был, дальше проверяется каждый цикл, флаг поднимается при нажатии кнопки- изменении состояния и tape, все, дальше должно крутится loop, пока снова флаг не поднимется. А вот с if виснет и не меняется modeState (32 и 98 строка), т соотв tape
Возможно, у меня тупой обработчик кнопки, и с этим связано зависание. Всё равно спасибо всем за участие !
А выражение tape = list(tape);- меняет. Присваивает tape то, что вернула функция. Всё, с этого момента tape угроблена.
Ставим list(tape); так же виснет ардуинка
Я не видел этого кода, потому ничего сказать не могу. Вы же этот вариант засекретили.
Кстати, если эта tape глобальна, НАФИГА Вы передаёте её копию? И вообще, Вы в utf8rus копии строк передайте. Вам память девать некуда?
А выражение tape = list(tape);- меняет. Присваивает tape то, что вернула функция. Всё, с этого момента tape угроблена.
Я не видел этого кода, потому ничего сказать не могу. Вы же этот вариант засекретили.
Кстати, если эта tape глобальна, НАФИГА Вы передаёте её копию? И вообще, Вы в utf8rus копии строк передайте. Вам память девать некуда?
Спасибо за критику! Памяти хватает для этого применения, я только в самой нулевой точке в ардуино. Более опытный человек, напишет лучше, я не сомневаюсь.
Ошибка моя была в неправильном типе данных, при названии функции String list(String source), при замене на void все заработало как надо. Ниже приведу нынешний скетч, работает как задумано, есть микрокосяк с переключателем с последнего режима на первый, но реально это не мешает.
Еще раз всем спасибо за участие!