millis и прерывания
- Войдите на сайт для отправки комментариев
Ср, 11/02/2015 - 00:38
Доброго времени суток
Есть такой код, подсчитывающий время между включением и отключением датчика:
01 | unsigned long inductDuration; // длительность срабатывания датчика |
02 | boolean inductChange = false ; |
03 |
04 | void setup (){ |
05 | attachInterrupt(0, _InductionOn, RISING); |
06 | attachInterrupt(0, _InductionOff, FALLING); |
07 | } |
08 |
09 | void loop (){ |
10 | if (inductChange){ |
11 | Serial .println(inductDuration); |
12 | inductChange = false ; |
13 |
14 | остальной код программы |
15 | } |
16 | } |
17 |
18 | // >>>>>>>>>>>>>>> функция прерывания, высокий уровень на датчике индуктивности |
19 | void _InductionOn(){ |
20 | inductDuration = millis(); |
21 | } |
22 |
23 | // >>>>>>>>>>>>>>> функция прерывания, низкий уровень на датчике индуктивности |
24 | void _InductionOff(){ |
25 | inductDuration = millis() - inductDuration; |
26 | inductChange = true ; |
27 | } |
Но поскольку в прерывании millis() нельзя использовать, нужен какой то другой вариант решения. Что то ничего в голову не приходит.
А что, в прерывании действительно нельзя использовать millis() ?
А что, в прерывании действительно нельзя использовать millis() ?
Ну у меня почему то первое прерывание возвращает в mills() - 0.
Вот тут написано
Замечание по использованию
Внутри функции обработки прерывания не работает delay(), значения возвращаемые millis() не изменяются. Возможна потеря данный передаваемых по последовательному соединению (Serial data) в момент выполнения функциии обработки прерывания. Переменные, изменяемые в функции, должным быть объявлены как volatile.
использовать внешний счетчик времени, DS1302/DS1307.
Проверять сейчас не буду, поэтому сразу мои извинения, если навру. :)
Но по-моему читать значение millis в прерывании можно. А вот ждать в прерывании, пока оно изменится - это да, дело бесполезное, потому что изменяется оно вдругом прерывании, которое не начнёт выполняться, пока мы не выйдем из нашего.
Думаю, delay() не работает как раз по этой причине - он ждёт изменения millis() на заданное значение.
Потеря данных последовательного порта - тоже понятно. Данные теряются, если не удалось вовремя вызвать обработчик прерывания com-порта, из-за того что слишком долго обрабатывалось какое-то другое прерывание.
Так что, пробуйте. Не вижу причин, чтобы не работало. Главное, чтобы время между RISING и FALLING прерываниями не было слишком коротким - иначе счётчик millis действительно может просто не успеть ничего насчитать.
Эхех, так и думал что часы реального времени применять придется
Проверять сейчас не буду, поэтому сразу мои извинения, если навру. :)
Накатал такой код для проверки:
01
unsigned
long
inductDuration1;
02
unsigned
long
inductDuration2;
03
boolean inductChange =
false
;
04
05
void
setup
(){
06
Serial
.begin(9600);
07
attachInterrupt(0, _InductionOn, RISING);
08
attachInterrupt(0, _InductionOff, FALLING);
09
}
10
11
void
loop
(){
12
if
(inductChange){
13
Serial
.println(inductDuration1);
14
Serial
.println(inductDuration2);
15
inductChange =
false
;
16
}
17
}
18
19
// >>>>>>>>>>>>>>> функция прерывания, высокий уровень на датчике индуктивности
20
void
_InductionOn(){
21
inductDuration1 = millis();
22
}
23
24
// >>>>>>>>>>>>>>> функция прерывания, низкий уровень на датчике индуктивности
25
void
_InductionOff(){
26
inductDuration2 = millis();
27
inductChange =
true
;
28
}
В консоли получаю:
У меня просто не срабатывает прерывание attachInterrupt(0, _InductionOn, RISING); соответственно потому в переменной inductDuration1 всегда ноль. Почему так?
Удалил attachInterrupt(0, _InductionOff, FALLING);, первая функция заработала, ничего не понимаю
Если написать так:
1
attachInterrupt(0, _InductionOff, FALLING);
2
attachInterrupt(0, _InductionOn, RISING);
Срабатывает самое нижнее прерывание, первое игнорируется. Пробовал менять местами, так же - работает только нижнее. Почему?
Если написать так:
1
attachInterrupt(0, _InductionOff, FALLING);
2
attachInterrupt(0, _InductionOn, RISING);
Срабатывает самое нижнее прерывание, первое игнорируется. Пробовал менять местами, так же - работает только нижнее. Почему?
все правильно работает, второй строчкой вы затираете то, что настроили первой
Значит у меня единственное решение, использовать CHANGE
attachInterrupt(0, _InductionOff, CHANGE);
и отслеживать состояние пина?
И еще почитайте про volatile здесь: http://arduino.ua/ru/prog/Volatile
Всем привет.! Такой вопрос : есть три импульса, заведенных на нулевой вход прерывания, так же каждый из них приходит на свой цифровой вход. Нужно в момент прерывания (по любому из импульсов ) определять, какой именно импульс вызвал прерывание, отсчитывать время и давать импульс на определенный выход , и так со всеми тремя импульсами по кругу. Пробовал по принципу если произошло прерывание смотрим на каком из трех входов лог. Единица - ждем и даем импульс на соответствующий выход но импульсы получаются через раз не сбильные подкиньте индейка как побороть ?
Стабильные .
Частота импульсов примерно 100 герц.
ПС:От туда Следует отметить, что выпускникам ВУЗов, не знающим принципы работы триггеров, достаточно сложно найти работу.
Всем привет есть такой код на каждый вход прерывания подается сигнал по очереди одно прерывание работает второе нет подскажите почему ???
01
#define dimPin 8
02
#define dimPin1 9
03
#define zeroPin1 3
04
#define zeroPin 2
05
#include <CyberLib.h>
06
volatile
int
tic, Dimmer;
07
volatile
int
tic1, Dimmer1;
08
void
setup
() {
09
Serial
.begin(9600);
10
pinMode(dimPin, OUTPUT);
11
pinMode(dimPin1, OUTPUT);
12
digitalWrite(dimPin, 0);
13
digitalWrite(dimPin1, 0);
14
pinMode(zeroPin, INPUT);
15
pinMode(zeroPin1, INPUT);
16
attachInterrupt(0, detect_up, FALLING);
17
attachInterrupt(1, detect_up1, FALLING);
18
StartTimer1(timer_interrupt, 40);
19
StartTimer1(timer_interrupt1, 40);
20
StopTimer1();
21
22
Serial
.println(
"Start"
);
23
}
24
25
void
loop
() {
26
27
Dimmer = map(analogRead(0), 0, 1023, 240, 0);
28
Dimmer1 = map(analogRead(0), 0, 1023, 240, 0);
29
30
}
31
32
void
timer_interrupt1() {
33
tic1++;
34
if
(tic1 > Dimmer1)
35
digitalWrite(dimPin1, 1);
36
}
37
void
detect_up1() {
38
tic1 = 0;
39
ResumeTimer1();
40
attachInterrupt(1,detect_down1, RISING);
41
}
42
43
void
detect_down1() {
44
tic1 = 0;
45
StopTimer1();
46
digitalWrite(dimPin1, 0);
47
attachInterrupt(1, detect_up1, FALLING);
48
}
49
void
timer_interrupt() {
50
tic++;
51
if
(tic > Dimmer )
52
digitalWrite(dimPin, 1 ) ;
53
54
}
55
56
void
detect_up() {
57
tic = 0;
58
ResumeTimer1();
59
attachInterrupt(0, detect_down, RISING);
60
}
61
62
void
detect_down() {
63
tic = 0;
64
StopTimer1();
65
digitalWrite(dimPin, 0);
66
attachInterrupt(0, detect_up, FALLING);
67
68
}
Всем привет есть такой код на каждый вход прерывания подается сигнал по очереди одно прерывание работает второе нет подскажите почему ???
А вот это правильно?
1
StartTimer1(timer_interrupt, 40);
2
StartTimer1(timer_interrupt1, 40);
Какой обработчик будет у таймера 1?
Как минимум потому, что Вы на один таймер пытаетесь два обработчика повесить (строки 18 и 19).
Я так и дкмал. Как тогда зделать три отдельных таймера ???
Думал