Программа перестает работать

snoeger
Offline
Зарегистрирован: 23.02.2019
/*Код должен включать и выключать светодиод по двойному щелчку.
Используется цифровой вывод микрофонного модуля.
Проблема в том, что ВНЕЗАПНО, программа прекращает нормальную работу.
Это начинает происходить спустя случайный промежуток времени, всегда разный. 
Перезагрузка помогает.
ЧЯДНТ?*/
#define analogPin A0
#define digitalPin 2
#define led 4
void setup() {

 pinMode(analogPin, INPUT);
 pinMode(digitalPin, INPUT);
 pinMode(led, OUTPUT);
Serial.begin(9600);
attachInterrupt(0, Up , RISING);

} 
volatile bool flag=0;
volatile unsigned  long timer=0;
void Up(){
   timer = millis() - timer;
    if(timer<4000&&timer>20){if (flag==0){
    digitalWrite(led, HIGH);
    flag=1;
      }else{
         digitalWrite(led, LOW);
         flag=0;      
  }
  timer = 0;
      }
  }
 
 void loop() {
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Зарядите Serial на 115200 и после строки 22 временно поставьте Serial.println(timer);

Это, конечно, вызовет тошноту у программистов микроконтроллеров, но поможет понять, почему не выполняется условие.

snoeger
Offline
Зарегистрирован: 23.02.2019

Не понял. 

Типы одинаковые.

Почему-то таймер не обнуляется.

Как заставить это работать? 

 

KindMan
Offline
Зарегистрирован: 19.12.2018

Ну так оно работает, ровно так, как написано. В прерывании вы должны только проверить длительность и количество щелчков, и ничего другого. В лупе меняйте состояние выхода.

sadman41
Offline
Зарегистрирован: 19.10.2016

Не обнуляется потому что не попадает в условие. А как заставить... Ну, придётся еще подумать, не исключено, что найти другой алгоритм.

snoeger
Offline
Зарегистрирован: 23.02.2019

Ничего не выходит.

Можете помочь с кодом?

KindMan
Offline
Зарегистрирован: 19.12.2018

snoeger пишет:

Ничего не выходит.


Покажите, как пытаетесь исправить.
Я бы попробывал замерить длительность сигнала с датчика, и на основании этого уже определять хлопки. Делать это конечно лучше таймером, а это тема довольно сложная, если вы новичок, то попробуйте для начала в loop'е это всё сделать, а в прерывании менять состоянии переменной, для отсчета времени. Не знаю, что за датчик, может надо применить не миллис а микрос

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

snoeger пишет:

Ничего не выходит.

Можете помочь с кодом?

могу, только словами скажите, что хотите сделать, не увидел в коде двойного щелчка совсем

а вот так?
 

#define pinLed  13
#define pinINT0 2
#define Scetchik 1

void ledInvert(void)
{
  static unsigned long j = Scetchik;
  if(!j--){ 
    digitalWrite(pinLed, ! digitalRead(pinLed));
   j=Scetchik;
    }
}

void setup() {
  pinMode(pinLed,OUTPUT);
  attachInterrupt(0, ledInvert, RISING );
 }

void loop() {

}

 

snoeger
Offline
Зарегистрирован: 23.02.2019

Проблема в том, что я не могу победить дребезг- не нашёл конденсатор, и теперь процесс поиска ошибок превращается в ад.
Хочу, чтобы при поступлении лог.1 за 4 секунды дважды, прерываясь, зажигался диод.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

snoeger пишет:
Проблема в том, что я не могу победить дребезг- не нашёл конденсатор, и теперь процесс поиска ошибок превращается в ад. Хочу, чтобы при поступлении лог.1 за 4 секунды дважды, прерываясь, зажигался диод.

победить дребезг на прерывании не возможно, надо настраивать ваш аккустический датчик, чтобы дребезга не было

KindMan
Offline
Зарегистрирован: 19.12.2018

Какой дребезг? У вас там механические контакты? Если вы имеете ввиду шум, то, ещё раз повторяю, меряйте длительность шума, потом тишину, опять шум, и если попал подходящий вам интервал, включайте/выключайте свой выход. Если датчик постоянно вам посылает помехи на порт, то без дополнительных элементов не добиться стабильной работы.

snoeger
Offline
Зарегистрирован: 23.02.2019

Я менял, не помогает.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

snoeger пишет:
Я менял, не помогает.

Внутри функции обработки прерывания не работает delay(), значения возвращаемые millis() не изменяются. Возможна потеря данный передаваемых по последовательному соединению (Serial data) в момент выполнения функциии обработки прерывания. Переменные, изменяемые в функции, должным быть объявлены как volatile.

snoeger
Offline
Зарегистрирован: 23.02.2019

Ну да, я там все без задержек написал.
С переменными вчера разобрался.
Возможно такое, что, если отключить сериал, она заработает нормально?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

snoeger пишет:
Ну да, я там все без задержек написал. С переменными вчера разобрался. Возможно такое, что, если отключить сериал, она заработает нормально?

нет, логика не соответствует требуемой, начните с моего скетча, где отрабатывается два щелчка

snoeger
Offline
Зарегистрирован: 23.02.2019

Отключил сериал, стабильность работы стала лучше, но программа снова не работает.
Как найти этот скетч?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016
#define pinLed  13
#define pinINT0 2
#define Scetchik 1
volatile unsigned int j = Scetchik;
unsigned old_millis = 0;
#define timer 4000
int flag = 0;

void ledInvert(void)
{
    if(!j--){ 
    digitalWrite(pinLed, ! digitalRead(pinLed));
    j=Scetchik;
    }
}

void setup() {
  pinMode(pinLed,OUTPUT);
  attachInterrupt(0, ledInvert, RISING );
 }

void loop() {
if(j==0 && flag==0){old_millis=millis();flag=1;}
if(millis()-old_millis > timer && flag==1){j=Scetchik; flag = 0;} // начинай сначала )))

}

 

#define pinLed  13
#define pinINT0 2
#define Scetchik 1
#define tau_drebezg 200
#define timer 4000

volatile unsigned int j = Scetchik;
unsigned old_millis = 0;
unsigned tau_millis = 0;
byte flag = 0;

void ledInvert(void)
{
    if(millis()-tau_millis > tau_drebezg){
        if(!j--){ 
        digitalWrite(pinLed, ! digitalRead(pinLed));
        j=Scetchik;
                }
                tau_millis=millis();
                                         } // 
}
    
void setup() {
  pinMode(pinLed,OUTPUT);
  pinMode(3,OUTPUT);
  digitalWrite(3,HIGH);
  delay(20);
  attachInterrupt(0, ledInvert, RISING );
 }

void loop() {
if(j==0 && flag==0){old_millis=millis();flag=1;}  //ждём 4 секунды 2-й хлопок
if(millis()-old_millis > timer && flag==1){j=Scetchik; flag = 0;} // нет хлопка -начинай сначала )))

}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

snoeger пишет:
ЧЯДНТ?

ННП НФВКЩИС.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

И, да, как исправить ошибку я уже написал в #17, а ещё есть замечание по объёму кода.

Вот эта конструкция

if (flag == 0) {
	digitalWrite(led, HIGH);
	flag = 1;
} else {
	digitalWrite(led, LOW);
	flag = 0;
}

легко заменяется на существенно более короткую и прозрачную

digitalWrite (led, flag = !flag);
ВН
Offline
Зарегистрирован: 25.02.2016

ua6em пишет:
победить дребезг на прерывании не возможно.....

несколько спорное утверждение

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ВН пишет:

ua6em пишет:
победить дребезг на прерывании не возможно.....

несколько спорное утверждение

ну так совсем ничего невозможного нет...
интересна Ваша мысль, как будете отличать дребезг от недребезга изменение сигнала вызвавшего прерывание

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

ВН пишет:

несколько спорное утверждение

Не "несколько", а на полноценный холивар в котором все будут правы :)

ВН
Offline
Зарегистрирован: 25.02.2016

ЕвгенийП пишет:
Не "несколько", а на полноценный холивар в котором все будут правы :)

(смеясь) ну да, ну да =)

зы. ua6em, чуть позже отвечу. некогда щас

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

ВН пишет:

несколько спорное утверждение

Не "несколько", а на полноценный холивар в котором все будут правы :)

мои компетенции говорят о том, что срани в аппаратных прерываниях быть не должно, зачищать надо на аппаратном уровне...иное, попытка переложить ответственность за кривые руки разработчика на программиста )))

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Антидребезг в прерывании - Может так

#define button 2
bool kn = 0;
volatile uint32_t time;

void setup()
{
  pinMode(button, INPUT_PULLUP);
  attachInterrupt(0, butDreb, CHANGE);
}

void loop()
{
  if(kn)
  {
    // bla-bla-bla
    kn = 0;
  }
}

void butDreb()
{
  if(!digitalRead(button))time = millis(); 
  if(digitalRead(button)){
    if(millis() - time > 50) kn = 1;
  }
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

А если дребезга нет, то как будет второй раз вызван butDreb() и выставлен kn = 1?

snoeger
Offline
Зарегистрирован: 23.02.2019

Вернусь к этому как-нибудь потом.  

Когда достану конденсатор.

Спасибо всем, кто пытался помочь, но мой говнокод на 2й день не читается.

Кто его писал?

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

sadman41 пишет:

А если дребезга нет, то как будет второй раз вызван butDreb() и выставлен kn = 1?

Если был клик то будет и единица

Ну а обработку проведем в лооп и сбросим в 0

ВН
Offline
Зарегистрирован: 25.02.2016


в прерывании 24 строка не сработает, милис загрузить получится, но его значение до выхода из прерывания изменятся не будет.

недавно здесь описыал рабочий алгоритм одного из вариантов антидребезга с прерыванием 

http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/obrabotka-knopki-na-preryvaniipower-down-mode-gde-oshibka#comment-432995

ua6em, вроде недавно искал и использовал для энкодера код от Димакса, (ежели память е изменяет), я его тоже тестил с год назад, но то ли у меня больно глючный энк. попался, то еще хз что, но пропуски и ошибки с тем кодом  были. В результате написал такой, и он меня вполне устроил. конденсаторы ко все пинам энка по 0,1 мкф, подтяжка может быть только внутренними резисторами ардуины на голом энке.

​void encoder()  //  Обработка прерывания энкодера
{
  char j=0;
  for(byte i=0; i<7; i++)                 // несколько раз читаем состояния пина dt
    {if(digitalRead(DT)) j++; else j--; } // для защиты от дребезга контактов
      if(j>0) enc--;  else enc++;         // и по результатам тестов принимаем решение

  switch(MENU)                            // ограничение вводимых параметров
     {  case 1:  if(enc <0) enc = 0; 
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

snoeger пишет:

Вернусь к этому как-нибудь потом.  

Когда достану конденсатор.

Спасибо всем, кто пытался помочь, но мой говнокод на 2й день не читается.

Кто его писал?

И что? код из поста #16 не работает?

 Пороюсь найду датчик, сам проверю )))
...а то как в призказке...пиво без водки деньги на ветер )))

snoeger
Offline
Зарегистрирован: 23.02.2019

ua6em пишет:

snoeger пишет:

Вернусь к этому как-нибудь потом.  

Когда достану конденсатор.

Спасибо всем, кто пытался помочь, но мой говнокод на 2й день не читается.

Кто его писал?

И что? код из поста #16 не работает?

 Пороюсь найду датчик, сам проверю )))
...а то как в призказке...пиво без водки деньги на ветер )))


Он работает, но тоже с дебезгом, если подуть - мигает.

Однако, целью было не заставить его работать, а понять, почему условие моего кода не выполняется.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

snoeger пишет:
ua6em пишет:

snoeger пишет:

Вернусь к этому как-нибудь потом.  

Когда достану конденсатор.

Спасибо всем, кто пытался помочь, но мой говнокод на 2й день не читается.

Кто его писал?

И что? код из поста #16 не работает?

 Пороюсь найду датчик, сам проверю )))
...а то как в призказке...пиво без водки деньги на ветер )))

Он работает, но тоже с дебезгом, если подуть - мигает. Однако, целью было не заставить его работать, а понять, почему условие моего кода не выполняется.

Подуть это у ДПС, настраивайте на хлопок руками )))
Он работает так, как написали, а задумывали, так как написано у меня ...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:

Зарядите Serial на 115200 и после строки 22 временно поставьте Serial.println(timer);

Это, конечно, вызовет тошноту у программистов микроконтроллеров, но поможет понять, почему не выполняется условие.

это и так понятно, если после первого включения до срабатывания прерывания прошло более 4 секунд код никогда не выполнится

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

ВН пишет:



в прерывании 24 строка не сработает, милис загрузить получится, но его значение до выхода из прерывания изменятся не будет.

Посмотрите код внимательнее - millis() в преывании не должен и не будет меняться.
1е прерывание идет по нажатию кнопки (Засекаем время)
2е прерывание идет по отпускании кнопки - вот здесь мы и проверяем - был дребезг или нажатие.
ВН
Offline
Зарегистрирован: 25.02.2016

согласен, невнимательно посмотрел, сорри =)

но тоже обработка со своими нюансами.

sadman41
Offline
Зарегистрирован: 19.10.2016

В таком случае это не столько защита от дребезга, сколько определение клика. Потому что просто push оно ловить не сможет.

ВН
Offline
Зарегистрирован: 25.02.2016

не может + там множественный вызов прерывания в случае дребезга

7/8 предыдущео поста стер, чтобы не влезать во все эти хреновы тонкости, бо и так понятно, что где-то такой вариант годится, а где-то нет.

почему тему про се ЕвгенийП  и обозвал -холиваром

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Ну я так и написал в #27 что это клик, а если надо удержание и клик то надо добавить еще одну переменную. Например так

//Антидребезг в прерывании (НАЖАТИЕ КЛИК)

#define button 2
volatile bool kn = 0;
volatile bool fl_kn = 0;
volatile uint32_t time;

void setup()
{
  pinMode(button, INPUT_PULLUP);
  attachInterrupt(0, butDreb, CHANGE);
}

void butDreb()
{
  if(!digitalRead(button)){//Прерывание по нажатию
    time = millis(); 
    fl_kn = 1;
  }
  if(digitalRead(button)){ // Прерывание по отпусканию или дребезг
    if(millis() - time > 50) kn = fl_kn;//Был клик (Если прога длинная и в лооп не успели)
    fl_kn = 0;
  }
}

void loop()
{
  if(fl_kn)
  {
    if(millis() - time > 50) //Было нажатие
    {
      kn = 1;
      fl_kn = 0;
    }
  }
  if(kn)
  {
    // bla-bla-bla
    kn = 0;
  }
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

можно конечно и дребезг обработать, то-есть все прерывния после первого во временном промежутке до 20 миллисекунд считать за дребезг, а именно при первом прерывании запоминать миллис и выставлять флаг, за второй хлопок считать прерывание поступившее за пределом этого временного отрезка, но правильнее сделать датчик без дребезга... #16