Ви не увійшли.
Здравствуйте .
Помогите пожалуйста понять основы. вторые сутки не получается считать количество нажатий кнопки .
или я не правильно понимаю операторы или не правильно работаю с переменными . или совсем ничего не понимаю
//#define p 12 // обьявляю константу для обращения к 12 пину - заремил
int count=0; // выделение памяти для переменной счетчика нажатий
int val=0;// выделение памяти для переменной состояния порта
void setup() //процедура setup
{
pinMode(12, INPUT); //объявляем пин как вход - изначально он притянут резистором к земле и при нажатии на кнопку там появляется +5в
Serial.begin(9600);
}
void loop() //процедура loop
{
val = digitalRead(12); //читаем данные с порта
while ( val==LOW ) count=count; //в цикле ничего не делаем пока не изменится состояние порта с "0" на "1"
count=count++ ; //когда изменилось состояние инкриминируем счетчик нажатий кнопки
Serial.print( count); //выводим в порт
while ( val==HIGH ) count=count; // ожидаем появление опять "0"
}
буду благодарен за любую помощь в разьяснении ))))))спасибо !
Неактивний
Для того что бы считать количество ( без пропусков ) нажатий кнопки нужно использовать внешнее прерывание. Обязательно вставить небольшой delay для устранения дребезга или повесить кондер небольшой (порядка 0.1 мкф). Циклы while в принципе тут не уместны и вообще циклы старайтесь их не использовать за редким исключением если Вам необходимо изменить какое то множество, и то в таком случае используют for, цикл while может повесить всю программу. В помощь http://arduino.ua/ru/prog/AttachInterrupt
Остання редакція Nefreemen (2016-04-17 14:24:49)
Неактивний
Примерно где то так:
volatile int count=0; // выделение памяти для переменной счетчика нажатий
void setup() //процедура setup
{
pinMode(12, INPUT); //объявляем пин как вход - изначально он притянут резистором к земле и при нажатии на кнопку там появляется +5в
Serial.begin(9600);
attachInterrupt(1, bootom, RISING); // можете выбрать другое прерывание ( согласно используемой arduino)
}
void loop() //процедура loop
{
Serial.println( count); //выводим в порт
delay(20); //???
}
void bootom()
{
count++;
}
Остання редакція Nefreemen (2016-04-17 14:40:40)
Неактивний
Спасибо большое )) я просто до прерываний еще не добрался - буду учить ))
а мой код я понял почему не работает : я опрашиваю кнопку только один раз перед циклом while и всё . А в цикле не опрашиваю - поэтому с чего же ему прерываться ? вот он навсегда и крутится .
вот так я сделал ))
int count=0; // выделение памяти для переменной счетчика нажатий
int val=0;// выделение памяти для переменной состояния порта
void setup() //процедура setup
{
pinMode(12, INPUT); //объявляем пин как вход
Serial.begin(9600);
}
void loop() //процедура loop
{
while ( digitalRead(12)==LOW ) ; //в цикле ничего не делаем пока не изменится состояние порта с "0" на "1"
count=count+1 ; //когда изменилось состояние инкриминируем счетчик
Serial.print( count); //выводим в порт
while ( digitalRead(12)==HIGH ) ; // ожидаем появление опять "0"
}
Неактивний
ya_serega, вы заблокировали работу программы пока кнопку не отпустят ) в этой задаче, нормально, будет работать, но давайте сразу делать правильно, на прерываниях )
Остання редакція NoName (2016-04-17 17:56:20)
Неактивний
Спасибо большое )) я просто до прерываний еще не добрался - буду учить ))
а мой код я понял почему не работает : я опрашиваю кнопку только один раз перед циклом while и всё . А в цикле не опрашиваю - поэтому с чего же ему прерываться ? вот он навсегда и крутится .
вот так я сделал ))int count=0; // выделение памяти для переменной счетчика нажатий
int val=0;// выделение памяти для переменной состояния порта
void setup() //процедура setup
{
pinMode(12, INPUT); //объявляем пин как вход
Serial.begin(9600);}
void loop() //процедура loop
{
while ( digitalRead(12)==LOW ) ; //в цикле ничего не делаем пока не изменится состояние порта с "0" на "1"
count=count+1 ; //когда изменилось состояние инкриминируем счетчик
Serial.print( count); //выводим в порт
while ( digitalRead(12)==HIGH ) ; // ожидаем появление опять "0"}
Считает? А что считает? Перестает считать когда кнопка нажата? Иначе как понимать Ваше:
{
pinMode(12, INPUT); //объявляем пин как вход - изначально он притянут резистором к земле и при нажатии на кнопку там появляется +5в
Serial.begin(9600);
}
Неактивний
Считает? А что считает? Перестает считать когда кнопка нажата?
эта програмка считает количество импульсов ( если точнее переходов с "0" в "1")
изначально на 12 выводе земля ( вывод обьявлен входом и соединен резистором 10 ком с землей что бы избежать Z состояния)
при каждом появлении "1" сount инкриминируется и я ничего не делая ожидаю "0" при его появлении начинаю всё сначала .. и так до бесконечности .
Иначе как понимать Ваше:
{
pinMode(12, INPUT); //объявляем пин как вход - изначально он притянут резистором к земле и при нажатии на кнопку там появляется +5в
Serial.begin(9600);
}
а этот вопрос я не понял - что я не правильно сделал в рамках моей задачи ? .. но я написал что всё уже заработало и указал в чем была моя ошибка )))
Неактивний
ya_serega. Ваш последний скетч говорит о том что Вы не понимаете одну очень важную вещь.
Процедура setup(){
здесь инициализация (назначение переменных) и всякой другой фигни, выполняется она ОДИН РАЗ перед стартом ОСНОВНОГО тела программы
}
loop(){
Основное тело программы выполняется постоянно. Это ЦИКЛ по СУТИ тот же while.
}
Вашем примере получается:
loop(){
// здесь будут какие то
действия
Например Serial.print
прицепим еще один цикл
И войдем в него по условию
while( true){
ждем пока станет false при этом код который выше не выполняется, так и тот который ниже!
}
// здесь тоже команды
}
Поэтому даже если Вы не хотите использовать прерывание то правильно будет проверять условие
loop(){
if (digitalRead(12) == HIGH){
count++
}
Serial.print(count);
}
Обращаю еще раз Ваше внимание что при использовании цикла while() высока вероятность "повесить" программу. При использовании этого цикла желательно использовать сторожевой таймер. Так как событие которое ожидает этот цикл может и вовсе не произойти.
Неактивний
и я по вашему совету попробовал сделать то же самое только через прерывание- получилось )) спасибо )) но мне нечем больше занять процессор ,
да и не знаю куда потом я это буду использовать .. может на более важные вещи мне прерывания понадобятся ..) я
теперь пытаюсь понять как из этой програмки сделать отдельную циклическую функцию ..? если я ее описываю как int val () то она проходит один раз и всё - (( void она крутится и работает ... а если я ее описываю как void val() то компилятор начинает матюкаться на скобки внутри этой функции ((( .. и как потом вызывать эту функцию void () ?
вот до чего я доработал эту програмку и теперь не могу сделать из нее функцию что бы вызывать когда потребуется .
int count = 0; // выделение памяти для переменной счетчика нажатий
unsigned long counttime;
void setup() //процедура setup
{
pinMode(12, INPUT); //объявляем пин как вход
Serial.begin(9600);
}
void loop() //процедура loop
{ //начало
while ( digitalRead(12) == LOW ) ; //в цикле ничего не делаем пока не изменится состояние порта с "0" на "1"
while ( digitalRead(12) == HIGH ) ; // ожидаем появление опять "0"
count = count + 1; //инкриминируем счетчик
counttime = millis(); // запустили таймер
while ( digitalRead(12) == LOW ) { // ожидаем одно из условий выхода из цикла
if (millis() - counttime > 120)break; // либо появление "1" либо прошло времени больше чем 120 мс
}
if (millis() - counttime > 120) //если пауза было больше 120 то выводим счетчик в порт и обнуляем его
{ // Скобка начала условия if
Serial.println( count);
count = 0;
}// если время не прошло то просто переходим в начало
} //конец loop
Неактивний
всё что я нашел по процедурам это вот : http://arduino.ru/Reference/Void и http://arduino.ru/Reference/FunctionDeclaration
но я там не нашел ответ на мой вопрос ((
Неактивний
ya_serega. Ваш последний скетч говорит о том что Вы не понимаете одну очень важную вещь.
Процедура setup(){
здесь инициализация (назначение переменных) и всякой другой фигни, выполняется она ОДИН РАЗ перед стартом ОСНОВНОГО тела программы
}
loop(){
Основное тело программы выполняется постоянно. Это ЦИКЛ по СУТИ тот же while.
}Вашем примере получается:
loop(){
// здесь будут какие то
действия
Например Serial.print
прицепим еще один цикл
И войдем в него по условию
while( true){
ждем пока станет false при этом код который выше не выполняется, так и тот который ниже!
}
// здесь тоже команды}
Поэтому даже если Вы не хотите использовать прерывание то правильно будет проверять условие
loop(){
if (digitalRead(12) == HIGH){
count++
}
Serial.print(count);
}
Обращаю еще раз Ваше внимание что при использовании цикла while() высока вероятность "повесить" программу. При использовании этого цикла желательно использовать сторожевой таймер. Так как событие которое ожидает этот цикл может и вовсе не произойти.
да. я прекрасно это понимаю , спасибо еще раз )) wile не самый надежный оператор . но ваш пример мне немного не подходит - там пока на порту 1 count будет постоянно инкриминироваться пока не прийдет 0 . а мне нужно только 1 инкримент . наверное умнее в данном случае завести еще переменную в которой хранить предыдущее состояние пина и при его изменении с 0 в 1 делать один раз ++ ... но я же только учусь )) поэтому решил попробовать как работают все операторы и начал с самого простого )))) .. и еще в данной задаче если не будет на этом входе импульсов то и делать то больше программе нечего будет )))
Неактивний
Считает? А что считает? Перестает считать когда кнопка нажата?
эта програмка считает количество импульсов ( если точнее переходов с "0" в "1")
изначально на 12 выводе земля ( вывод обьявлен входом и соединен резистором 10 ком с землей что бы избежать Z состояния)
при каждом появлении "1" сount инкриминируется и я ничего не делая ожидаю "0" при его появлении начинаю всё сначала .. и так до бесконечности .Иначе как понимать Ваше:
{
pinMode(12, INPUT); //объявляем пин как вход - изначально он притянут резистором к земле и при нажатии на кнопку там появляется +5в
Serial.begin(9600);}
а этот вопрос я не понял - что я не правильно сделал в рамках моей задачи ? .. но я написал что всё уже заработало и указал в чем была моя ошибка )))
Ну что здесь не понятно? Вы написали что на входе сигналом должна быть лог. един. Вашем примере при отсутствии 1 программа влетает по LOW в первый while и плюсует count до те пор пока не появится 1 ( условие станет false). И что у Вас работает? Мало того что просто ОЧЕНЬ НЕ ПРАВИЛЬНО логически. Банальная лень ставить {} (или нет? А так задумано?) Что вообще не понятно где заканчивается первый while и что происходит дальше. Если "любитель" циклов дальше будет так писать то далеко не уйдет цикл он видите ли по сути "круг" .
Неактивний
Nefreemen пише:ya_serega. Ваш последний скетч говорит о том что Вы не понимаете одну очень важную вещь.
Процедура setup(){
здесь инициализация (назначение переменных) и всякой другой фигни, выполняется она ОДИН РАЗ перед стартом ОСНОВНОГО тела программы
}
loop(){
Основное тело программы выполняется постоянно. Это ЦИКЛ по СУТИ тот же while.
}Вашем примере получается:
loop(){
// здесь будут какие то
действия
Например Serial.print
прицепим еще один цикл
И войдем в него по условию
while( true){
ждем пока станет false при этом код который выше не выполняется, так и тот который ниже!
}
// здесь тоже команды}
Поэтому даже если Вы не хотите использовать прерывание то правильно будет проверять условие
loop(){
if (digitalRead(12) == HIGH){
count++
}
Serial.print(count);
}
Обращаю еще раз Ваше внимание что при использовании цикла while() высока вероятность "повесить" программу. При использовании этого цикла желательно использовать сторожевой таймер. Так как событие которое ожидает этот цикл может и вовсе не произойти.да. я прекрасно это понимаю , спасибо еще раз )) wile не самый надежный оператор . но ваш пример мне немного не подходит - там пока на порту 1 count будет постоянно инкриминироваться пока не прийдет 0 . а мне нужно только 1 инкримент . наверное умнее в данном случае завести еще переменную в которой хранить предыдущее состояние пина и при его изменении с 0 в 1 делать один раз ++ ... но я же только учусь )) поэтому решил попробовать как работают все операторы и начал с самого простого )))) .. и еще в данной задаче если не будет на этом входе импульсов то и делать то больше программе нечего будет )))
В рамках поставленных условий один путь ПРЕРЫВАНИЕ. Цикл while в loop() НЕ ПРАВИЛЬНО! А дальше как хотите, не хотите слышать флаг в руки и кило гвоздей в карман дабы ветром не сдуло (шутка). Удачи.
Неактивний
ya_serega. Ваш последний скетч говорит о том что Вы не понимаете одну очень важную вещь.
Процедура setup(){
здесь инициализация (назначение переменных) и всякой другой фигни, выполняется она ОДИН РАЗ перед стартом ОСНОВНОГО тела программы
}
loop(){
Основное тело программы выполняется постоянно. Это ЦИКЛ по СУТИ тот же while.
}
извините за дотошность - но вы подняли еще один мой вопрос - он как раз касается процедуры setup и назначения всяких переменных ))
вот он : если я переменные обьявляю до setup то всё нормально компилится а если в этом цикле то компилятор на них матюкается . что здесь я делаю не так ?
//int count = 0; // выделение памяти для переменной счетчика нажатий
//unsigned long counttime;
void setup() //процедура setup
{
int count = 0; // выделение памяти для переменной счетчика нажатий
unsigned long counttime;
pinMode(12, INPUT); //объявляем пин как вход
Serial.begin(9600);
}
вот кусок того что я ваяю .. две строчки
int count = 0; // выделение памяти для переменной счетчика нажатий
//unsigned long counttime;
я заремил над setup и перенес внутрь . до этого всё хорошо работало ,а если они внутри- компилятор не видит эти переменные в void loop() . почему ?
Неактивний
Неактивний
спасибо ))) действительно самое правильное решение )) учить мат.часть )))
Неактивний
ya_serega пише:Nefreemen пише:В рамках поставленных условий один путь ПРЕРЫВАНИЕ. Цикл while в loop() НЕ ПРАВИЛЬНО! А дальше как хотите, не хотите слышать флаг в руки и кило гвоздей в карман дабы ветром не сдуло (шутка). Удачи.
да не зацикливаюсь я на циклах .... а может и зацикливаюсь ..(( просто я пытаюсь с асм перейти на что-то попроще для моих задач.. а это попроще оказывается и не намного проще ..)) а в каких случаях тогда корректней можно использовать while ? .
Неактивний
Угу. Учите. А как же. А то объявляем переменную а значение не определяем. Засовываем в loop с не определенным значением и хотим то бы компилятор каждый раз в цикле назначал память под не понятное значение.
Неактивний
ya_serega пише:Считает? А что считает? Перестает считать когда кнопка нажата?
эта програмка считает количество импульсов ( если точнее переходов с "0" в "1")
изначально на 12 выводе земля ( вывод обьявлен входом и соединен резистором 10 ком с землей что бы избежать Z состояния)
при каждом появлении "1" сount инкриминируется и я ничего не делая ожидаю "0" при его появлении начинаю всё сначала .. и так до бесконечности .Иначе как понимать Ваше:
{
pinMode(12, INPUT); //объявляем пин как вход - изначально он притянут резистором к земле и при нажатии на кнопку там появляется +5в
Serial.begin(9600);}
а этот вопрос я не понял - что я не правильно сделал в рамках моей задачи ? .. но я написал что всё уже заработало и указал в чем была моя ошибка )))
Ну что здесь не понятно? Вы написали что на входе сигналом должна быть лог. един. Вашем примере при отсутствии 1 программа влетает по LOW в первый while и плюсует count до те пор пока не появится 1 ( условие станет false). И что у Вас работает? Мало того что просто ОЧЕНЬ НЕ ПРАВИЛЬНО логически. Банальная лень ставить {} (или нет? А так задумано?) Что вообще не понятно где заканчивается первый while и что происходит дальше. Если "любитель" циклов дальше будет так писать то далеко не уйдет цикл он видите ли по сути "круг" .
где же здесь плюсуется по кругу ???
while ( digitalRead(12) == LOW ) ; //в цикле ничего не делаем пока не изменится состояние порта с "0" на "1"
здесь просто ожидаем 1
while ( digitalRead(12) == HIGH ) ; // ожидаем появление опять "0"
здесь просто ожидаем 0
count = count + 1; //инкриминируем счетчик
здесь один раз плюсанули
counttime = millis(); // запустили таймер
while ( digitalRead(12) == LOW ) { // ожидаем одно из условий выхода из цикла
здесь опять ожидаем 1 ))
а следующий плюс будет только при следующем импульсе !!!!! после данных трех циклов в count всего лиш 1 будет ...
Неактивний
Nefreemen пише:ya_serega пише:Считает? А что считает? Перестает считать когда кнопка нажата?
эта програмка считает количество импульсов ( если точнее переходов с "0" в "1")
изначально на 12 выводе земля ( вывод обьявлен входом и соединен резистором 10 ком с землей что бы избежать Z состояния)
при каждом появлении "1" сount инкриминируется и я ничего не делая ожидаю "0" при его появлении начинаю всё сначала .. и так до бесконечности .Иначе как понимать Ваше:
{
pinMode(12, INPUT); //объявляем пин как вход - изначально он притянут резистором к земле и при нажатии на кнопку там появляется +5в
Serial.begin(9600);}
а этот вопрос я не понял - что я не правильно сделал в рамках моей задачи ? .. но я написал что всё уже заработало и указал в чем была моя ошибка )))
Ну что здесь не понятно? Вы написали что на входе сигналом должна быть лог. един. Вашем примере при отсутствии 1 программа влетает по LOW в первый while и плюсует count до те пор пока не появится 1 ( условие станет false). И что у Вас работает? Мало того что просто ОЧЕНЬ НЕ ПРАВИЛЬНО логически. Банальная лень ставить {} (или нет? А так задумано?) Что вообще не понятно где заканчивается первый while и что происходит дальше. Если "любитель" циклов дальше будет так писать то далеко не уйдет цикл он видите ли по сути "круг" .
где же здесь плюсуется по кругу ???
while ( digitalRead(12) == LOW ) ; //в цикле ничего не делаем пока не изменится состояние порта с "0" на "1"
здесь просто ожидаем 1
while ( digitalRead(12) == HIGH ) ; // ожидаем появление опять "0"
здесь просто ожидаем 0
count = count + 1; //инкриминируем счетчик
здесь один раз плюсанули
counttime = millis(); // запустили таймер
while ( digitalRead(12) == LOW ) { // ожидаем одно из условий выхода из циклаздесь опять ожидаем 1 ))
а следующий плюс будет только при следующем импульсе !!!!! после данных трех циклов в count всего лиш 1 будет ...
Задам только один вопрос в каком цикле у Вас происходит плюс count?
Неактивний
"а в каких случаях тогда корректней можно использовать while ? ." никогда
кроме 2 случаев
1. рабочий цикл main
2. задача в RTOS ) task
3. визуальное оформление выглядит читабельней, но не забываем break / return со статусом ошибки, иначе а чего эт ваша программа зависла, хотя каюсь сам юзаю )
та ладно будет работать, но нужно ли такое использовать, вот в чем вопрос?)
{ // loop
while ( digitalRead(12) == HIGH );
count ++;
while ( digitalRead(12) != HIGH);
}
Неактивний
vvr, всем стоять, работает программист ) ya_serega, осваивает Си после асма
ну и начал соответственно с jnc и иных goto ) пусть развлекается, вам жалко? он просто обязан пройти все велосипеды
Неактивний
"а в каких случаях тогда корректней можно использовать while ? ." никогда
кроме 2 случаев
1. рабочий цикл main
2. задача в RTOS ) task
3. визуальное оформление выглядит читабельней, но не забываем break / return со статусом ошибки, иначе а чего эт ваша программа зависла, хотя каюсь сам юзаю )та ладно будет работать, но нужно ли такое использовать, вот в чем вопрос?)
{ // loop
while ( digitalRead(12) == HIGH );
count ++;
while ( digitalRead(12) != HIGH);
}
Даа...Тогды у меня вопрос по поводу целесообразности while в main чего в нем ожидать? Аппаратного события или что то считать? И плюнуть на все остальное?
Остання редакція Nefreemen (2016-04-18 21:39:22)
Неактивний