millis и прерывания

rene
Offline
Зарегистрирован: 21.01.2014

Доброго времени суток

Есть такой код, подсчитывающий время между включением и отключением датчика:

unsigned long inductDuration; // длительность срабатывания датчика
boolean inductChange = false;

void setup(){
  attachInterrupt(0, _InductionOn, RISING);
  attachInterrupt(0, _InductionOff, FALLING);
}

void loop(){
    if (inductChange){
    Serial.println(inductDuration);
    inductChange = false;

    остальной код программы
  }
}

// >>>>>>>>>>>>>>> функция прерывания, высокий уровень на датчике индуктивности
void _InductionOn(){
  inductDuration = millis();
}

// >>>>>>>>>>>>>>> функция прерывания, низкий уровень на датчике индуктивности
void _InductionOff(){
  inductDuration = millis() - inductDuration;
  inductChange = true;
}

Но поскольку в прерывании millis() нельзя использовать, нужен какой то другой вариант решения. Что то ничего в голову не приходит.

Datak
Offline
Зарегистрирован: 09.10.2014

А что, в прерывании действительно нельзя использовать  millis()  ?

rene
Offline
Зарегистрирован: 21.01.2014

Datak пишет:

А что, в прерывании действительно нельзя использовать  millis()  ?

Ну у меня почему то первое прерывание возвращает в mills() - 0.

Вот тут   написано

Замечание по использованию

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

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

использовать внешний счетчик времени, DS1302/DS1307.

Datak
Offline
Зарегистрирован: 09.10.2014

Проверять сейчас не буду, поэтому сразу мои извинения, если навру. :)

Но по-моему читать значение  millis  в прерывании можно. А вот ждать в прерывании, пока оно изменится - это да, дело бесполезное, потому что изменяется оно  вдругом прерывании, которое не начнёт выполняться, пока мы не выйдем из нашего.

Думаю,  delay()  не работает как раз по этой причине - он ждёт изменения  millis()  на заданное значение.

Потеря данных последовательного порта - тоже понятно. Данные теряются, если не удалось вовремя вызвать обработчик прерывания com-порта, из-за того что слишком долго обрабатывалось какое-то другое прерывание.

Так что, пробуйте. Не вижу причин, чтобы не работало. Главное, чтобы время между RISING и FALLING прерываниями не было слишком коротким - иначе счётчик  millis  действительно может просто не успеть ничего насчитать.

rene
Offline
Зарегистрирован: 21.01.2014

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

rene
Offline
Зарегистрирован: 21.01.2014

Datak пишет:

Проверять сейчас не буду, поэтому сразу мои извинения, если навру. :)

Накатал такой код для проверки:

unsigned long inductDuration1;
unsigned long inductDuration2;
boolean inductChange = false;

void setup(){
  Serial.begin(9600);
  attachInterrupt(0, _InductionOn, RISING);
  attachInterrupt(0, _InductionOff, FALLING);
}

void loop(){
  if (inductChange){
    Serial.println(inductDuration1);
    Serial.println(inductDuration2);
    inductChange = false;
  }
}

// >>>>>>>>>>>>>>> функция прерывания, высокий уровень на датчике индуктивности
void _InductionOn(){
  inductDuration1 = millis();
}

// >>>>>>>>>>>>>>> функция прерывания, низкий уровень на датчике индуктивности
void _InductionOff(){
  inductDuration2 = millis();
  inductChange = true;
}

В консоли получаю:

0
3761
0
4692
0
5410
 
т.е. в функции _InductionOn millis() мне возвращает 0, а в функции _InductionOff работает нормально

 

rene
Offline
Зарегистрирован: 21.01.2014

У меня просто не срабатывает прерывание attachInterrupt(0, _InductionOn, RISING); соответственно потому в переменной inductDuration1 всегда ноль. Почему так?

Удалил attachInterrupt(0, _InductionOff, FALLING);, первая функция заработала, ничего не понимаю

rene
Offline
Зарегистрирован: 21.01.2014

Если написать так:

  attachInterrupt(0, _InductionOff, FALLING);
  attachInterrupt(0, _InductionOn, RISING);

Срабатывает самое нижнее прерывание, первое игнорируется. Пробовал менять местами, так же - работает только нижнее. Почему?

axill
Offline
Зарегистрирован: 05.09.2011

rene пишет:

Если написать так:

  attachInterrupt(0, _InductionOff, FALLING);
  attachInterrupt(0, _InductionOn, RISING);

Срабатывает самое нижнее прерывание, первое игнорируется. Пробовал менять местами, так же - работает только нижнее. Почему?

все правильно работает, второй строчкой вы затираете то, что настроили первой

rene
Offline
Зарегистрирован: 21.01.2014

Значит у меня единственное решение, использовать CHANGE

attachInterrupt(0, _InductionOff, CHANGE);

и отслеживать состояние пина?

Araris
Offline
Зарегистрирован: 09.11.2012

И еще почитайте про volatile здесь: http://arduino.ua/ru/prog/Volatile

mag155
Offline
Зарегистрирован: 21.12.2017

Всем привет.! Такой вопрос : есть три импульса, заведенных на нулевой вход прерывания, так же каждый из них приходит на свой цифровой вход. Нужно в момент прерывания (по любому из импульсов ) определять, какой именно импульс вызвал прерывание, отсчитывать время и давать импульс на определенный выход , и так со всеми тремя импульсами по кругу. Пробовал по принципу если произошло прерывание смотрим на каком из трех входов лог. Единица - ждем и даем импульс на соответствующий выход но импульсы получаются через раз не сбильные подкиньте индейка как побороть ?

mag155
Offline
Зарегистрирован: 21.12.2017

Стабильные .

mag155
Offline
Зарегистрирован: 21.12.2017

Частота импульсов примерно 100 герц.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

mag155 пишет:
как побороть ?
апаратно . Повесте триггеры http://digteh.ru/CVT/trigg/

ПС:От туда Следует отметить, что выпускникам ВУЗов, не знающим принципы работы триггеров, достаточно сложно найти работу.

mag155
Offline
Зарегистрирован: 21.12.2017

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

#define dimPin 8
#define dimPin1 9
#define zeroPin1 3
#define zeroPin 2
#include <CyberLib.h> 
volatile int  tic, Dimmer;
volatile int  tic1, Dimmer1;
void setup() {
  Serial.begin(9600);
  pinMode(dimPin, OUTPUT);
 pinMode(dimPin1, OUTPUT);
  digitalWrite(dimPin, 0);
 digitalWrite(dimPin1, 0);
  pinMode(zeroPin, INPUT);                 
 pinMode(zeroPin1, INPUT); 
  attachInterrupt(0, detect_up, FALLING); 
attachInterrupt(1, detect_up1, FALLING); 
  StartTimer1(timer_interrupt, 40);        
  StartTimer1(timer_interrupt1, 40); 
  StopTimer1();                            
 
  Serial.println("Start");
}

void loop() {
  
   Dimmer = map(analogRead(0), 0, 1023, 240, 0);
 Dimmer1 = map(analogRead(0), 0, 1023, 240, 0);

}

void timer_interrupt1() {      
  tic1++;                      
  if (tic1 > Dimmer1)            
    digitalWrite(dimPin1, 1);   
}
void  detect_up1() {   
  tic1 = 0;                                 
  ResumeTimer1();                           
  attachInterrupt(1,detect_down1,  RISING);  
}

void  detect_down1() { 
  tic1 = 0;                                  
  StopTimer1();                             
  digitalWrite(dimPin1, 0);                    
attachInterrupt(1, detect_up1, FALLING);  
}
void timer_interrupt() {       
  tic++;                      
  if (tic > Dimmer  )     
  digitalWrite(dimPin, 1 ) ;
    
}

void  detect_up() {   
  tic = 0;                                 
  ResumeTimer1();                           
  attachInterrupt(0, detect_down, RISING);  
}

void  detect_down() { 
  tic = 0;                                  
  StopTimer1();                             
  digitalWrite(dimPin, 0);                    
attachInterrupt(0, detect_up, FALLING);  

}

 

andryn
Offline
Зарегистрирован: 08.06.2018

mag155 пишет:

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

А вот это правильно?

StartTimer1(timer_interrupt, 40);       
StartTimer1(timer_interrupt1, 40);

Какой обработчик будет у таймера 1?

kalapanga
Offline
Зарегистрирован: 23.10.2016

Как минимум потому, что Вы на один таймер пытаетесь два обработчика повесить (строки 18 и 19).

mag155
Offline
Зарегистрирован: 21.12.2017

Я так и дкмал. Как тогда зделать три отдельных таймера ???

mag155
Offline
Зарегистрирован: 21.12.2017

Думал