Официальный сайт компании Arduino по адресу arduino.cc
Какой тип возвращаемых данных у функции?
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Пт, 01/03/2019 - 23:38
Не могу понять почему компилятор не видит тип данных, если я его явно указываю вот так
enum BTN_scan_states{ NOT_PRESSED_ = 0, PRESSED_ = 1, HOLDED_ = 2, RELEASED_ = 3 };
При компиляции вылазит: 'BTN_scan_states' does not name a type! То есть компилятор буквально говорит, что это не тип данных?
Подсчечивается строка
BTN_scan_states button_scan(){
Первое слово - тип возращаемого значения функции. По идее она должна вернуть состояние кнопки. Насколько я понял, компилятор не понимает, этот тип данных? Код целиком
#define LED_Pin 0 #define BTN_Pin 4 #define interval_slow 500UL #define interval_fast 50UL #define ext_interval 2000UL void setup(){ pinMode(LED_Pin, OUTPUT); pinMode(BTN_Pin, INPUT_PULLUP); } bool progTimer(unsigned long interval){ static unsigned long prevTime=0; if(millis()-prevTime>interval){ prevTime=millis(); return false; } else return true; } enum BTN_scan_states{ NOT_PRESSED = 0, PRESSED_ = 1, HOLDED_ = 2, RELEASED_= 3 }; BTN_scan_states button_scan(){ static bool prev_BTN_State = FALSE; // предыдущее состояние кнопки (нажата или нет) bool BTN_State = !(digitalRead(BTN_Pin)); // текущее состояние кнопки if (BTN_State==FALSE && prev_BTN_State==FALSE) {prev_BTN_State==FALSE; return NOT_PRESSED;} // кнопка не нажата if (BTN_State==TRUE && prev_BTN_State==FALSE) {prev_BTN_State==TRUE; return PRESSED_;} // кнопка нажата if (BTN_State==TRUE && prev_BTN_State==TRUE) {prev_BTN_State==TRUE; return HOLDED;} // кнопка удерживается if (BTN_State==FALSE && prev_BTN_State==TRUE) {prev_BTN_State==FALSE; return RELEASED_;} // отпущена } void loop(){ static BTN_scan_states b_state = button_scan(); switch(b_state){ case: NOT_PRESSED {Blink (LED_Pin, interval_slow); break;} // не нажата case: PRESSED {Blink (LED_Pin, interval_fast); break;} // нажатие case: HOLDED {Blink (LED_Pin, interval_fast); break;} // удержание кнопки нажатой case: RELEASED {if (progTimer(ext_interval)){Blink (LED_Pin, interval_fast)} else{Blink (LED_Pin, interval_slow);} break;} //отпускание } }
Три строчки кода в правильности написания которых сомневаюсь, я выделил! Посмотрите пожалуйста, кто разбирается!
enum это не тип данных , это "способ" переименования ряда целых чисел.
enum становиться типом данных когда :
вы его типом обьявляете
enum при более накрученых кодах склонен сбивать компилятор. Так что рекомендую делать так.
и возвращаемый тип будет byte.
Сорри, написал не разобравшись. Удалил
Не, ну почему все идут "через жо..у и сваркой"? Неужели нет других способов ну, например, #define?
Не, ну почему все идут "через жо..у и сваркой"? Неужели нет других способов ну, например, #define?
а что плохого в enum? Когда какая-то переменная принимает несколько фиксированных значений - я как раз обычно enum использую - это и нагляднее, и надежнее. С #define вы можете случайно присвоить переменной какое-то левое значение, а с enum вам компилятор даст выбрать только заранее описанные.
а что плохого в enum? Когда какая-то переменная принимает несколько фиксированных значений - я как раз обычно enum использую - это и нагляднее, и надежнее. С #define вы можете случайно присвоить переменной какое-то левое значение, а с enum вам компилятор даст выбрать только заранее описанные.
Ну, переменной присвоить значение с помощью #define, конечно надо постараться. Но идею я понял. При достаточно больших программах - enum является защитой, но в указанном случае - пожирателем пространства и вые-ом, извините за грубость.
При достаточно больших программах - enum является защитой, но в указанном случае - пожирателем пространства и вые-ом, извините за грубость.
не знаю, что он там пожирает
Вот эти два кода абсолютно идентичны по "пожиранию пространства"
через enum
через дефайны
У енума есть хороший побочный эффект: когда его свичуешь, к примеру, компилятор проверяет - все ли значения попали в свич. Если не все, то предупреждает, что какое-то не обрабатывается, не забыл ли про него уважаемый автор исходника?
Не понимаю, как, но этот мой код наконец-то заработал! Примерно так как предполагалось.
Хотя интервалы времени (задержки перехода светодиода в другой режим) иногда отличаюся! Наверно стоит добавить ещё защиту от дребезга!
А кусочек кода с enum там такой:
Я не знаю, что такое в данном случае BTN_st. Переменная или название перечисления, но обратите внимние, что в коде её вообще нету! Была строка
Но она закомментирована! А буквально её можно было бы расшифровать так: создать переменную типа BTN_st с названием b_state и присвоить ей значение NOT_PRESSED_ (кнопка не нажата). Или я ошибаюсь, и компилятор понимает это как-то по другому?
Мужики, Вас куда-то понесло, правда.
ТС, Всё Вы правильно объявили, всё нормально. И тип там нормальный и всё нормально (в коде полно других неправильностей на которые ругается компилятор, но с enum как раз всё окей).
Проблема стара как Ардуино IDE - охренительно дружественное для чайников решение, которое выносит все объявления функций в начало файла.
Для того, чтобы тип заработал нормально достаточно этот enum (никак не меняя) вынести в отдельный файл и включить его в основной при помощи #include. Включать надо как можно выше (например, первой строкой программы).
Всё сказанное относится к коду из стартового поста.
У енума есть хороший побочный эффект
И это не единственный его хороший эффект.
Им можно объявлять значения переменных для битовых полей и он сам позаботится, чтобы они влезли ы нужное количество бит. См. пример здесь.
Насколько я запомнил - выносить во внешний .h необязательно, достаточно объявить прототипы после enum и тогда IDE не будет их пихать выше радуги.
А вообще, вот так примерно с енумами обхожусь:
достаточно объявить прототипы после enum и тогда IDE не будет их пихать выше радуги.
Вполне возможно, я подробно не разбирался. Наткунлся как-то - выматерился и запомнил. Мне-то пофиг - я всегда много файлов пложу.
В люьом случае, ТС должен понимать, что у него всё нормально, проблема в "умности" IDE.
В люьом случае, ТС должен понимать, что у него всё нормально, проблема в "умности" IDE.
да где ж нормально, Евгений Петрович? Посмотрите на второй абзац заглавного сообщения,
Первое слово - тип возращаемого значения функции. По идее она должна вернуть состояние кнопки.
о какой функции тут вообще идет речь?
О функции button_scan
Вот, пожалуйста.
Файл xxx.ino
Файл kaka.h
Можете убедиться, что всё компилируется нормально. И работать будет нормально, уверяю Вас.
Можете убедиться, что всё компилируется нормально. И работать будет нормально, уверяю Вас.
ну да, я уж и сам увидал - после первого вашего сообщения. Поначалу не заметил эту функцию в коде - думал это ТС так enum повторно описывает....
У меня появился ещё вопрос насчет НЕ логичного возвращение функцией значения! Вроде бы проще не бывает.
Тип bool, то есть функция возвращает 0 или 1. По идее она должна возвращать:
1. false в обычном состоянии - кнопка не нажата
2. true при нажатии кнопки и ещё в течении заданного времени (значение ext_interval) например 2 секунды.
На самом же деле false она возвращает только до нажатия кнопки, а дальше всё время true! Впечатление такое, что таймер запуcкается и прокручивается всё время, даже если кнопка не нажата! То есть условие
как бы игнорируется? Посмотрите пожалуйста, кто разбирается, вот код целиком
Я гляну на код, но пока есть методологическое замечание. Ваши рассуждения правильны и полезны, но не на этой стадии работы. Я имею в ввиду вот это:
1. false в обычном состоянии - кнопка не нажата
2. true при нажатии кнопки и ещё в течении заданного времени (значение ext_interval) например 2 секунды.
Так рассуждают, когда проектируют программу и думают как её написать.
А вот на этапе поиска ошибки (на котором Вы сейчас находитесь) от таких рассуждений пользы не много. На этом этапе рассуждают на более низком уровен, а именно "По идее она должна возвращать true, если TimerSet равно true, и false в противном случае".
И, кстати, если бы Вы рассуждали так, то Вы бы немедленно заметили, что код можно упростить, а именно
А более простой код - это не только и не столько машинная эффективность, сколько "лучшая читаемость человеком", а значит лучший поиск ошибок.
Да. Вы правы. Такая запись гораздо проще. Я просто ещё плохо разбираюсь в синтаксисе! Спасибо за подсказку!
Если не сложно, подскажите пожалуйста, в данном случае
таймер ведь будет обнуляться сам? Или нужно ещё что-то дописывать? Точнее переменная TimerSet сама обнулится, когда функция progTimer вернет false?
На самом же деле false она возвращает только до нажатия кнопки, а дальше всё время true! Впечатление такое, что таймер запуcкается и прокручивается всё время, даже если кнопка не нажата! То есть условие
как бы игнорируется?
вы сами написали это условие так, что после отпускания кнопки оно игнорируется, ведь при отпущенной кнопке BTN_State - false. Так что таймер запускается, отсчитывает свои 2 сек и останоавливается, но поскольку переменную TimerSet вы не обновляете - она остается true
переменная TimerSet сама обнулится, когда функция progTimer вернет false?
конечно нет. С чего бы?
а как её можно обнулить? Напишите пожалуйста!
Переходите на стадию размышлений... Иначе как вы поймёте, что написанное кем-то будет работать, как полагается, а не случайным образом?
а как её можно обнулить? Напишите пожалуйста!
например, если TimerSet == true , запрашиваем состояние таймера и обновляем TimerSet
Большое спасибо за поссказку!
Те две черточки в строке
Означают ИЛИ. То есть буквально
если кнопка нажата ИЛИ переменная TimerSet равна true, то присвоить переменной TimerSet значение из функции progTimer(ext_interval).
В итоге, если кнопка не нажата, то через интервал (ext_interval) в переменную TimerSet попадет false и функция вернет false!
junior_developer - все верно