Прерывания.

Обсуждаем Arduino, Raspberry Pi и другие электронные компоненты и проекты DIY
Ответить
Marvin
Сообщения: 22
Зарегистрирован: 05 май 2012, 19:04

Прерывания.

Сообщение Marvin »

У меня в механическом спидометре, на TLC-80, обнаружился геркон, который замыкается 4 раза за 1 оборот вала (одной ногой сидит на земле).
Я подозревал, что геркон может дребезжать, поэтому решил сначала потренироваться на кошках велосипеде. Там так же имеется геркон.

За основу взял код из дружеской темы: http://www.compcar.ru/forum/showthread.php?t=5871

Т.к. срабатывание геркона приводит к появлению логического нуля я решил использовать attachInterrupt(0, int_on, LOW);

Код: Выделить всё

#define PinA  2
static boolean output = HIGH;
int pulse = 0;

void setup() 
{   
  pinMode(PinA, INPUT); 
  digitalWrite(PinA, HIGH);     // подключить подтягивающий резистор
  attachInterrupt(0, int_on, LOW);  // настроить прерывание interrupt 0 на pin 2
  
  Serial.begin(9600);
} 

void loop()
{
  delay(100);
  Serial.println(pulse);
}

// обработка прерывания
void  int_on()
{
  digitalWrite(13, (output==HIGH) ? output=LOW : output=HIGH);
  pulse++;
}
Кручу колесо рукой и выясняется, что при прохождении магнита около геркона фиксируется от 2 000 - 15 000 вызовов прерывания, в зависимости от скорости вращения.

Меняем работу с прерыванием на attachInterrupt(0, int_on, CHANGE), получаем от 1 до 5 вызовов за одно прохождение.

RISING дает 2 вызова: первый когда геркон замыкатеся, второй когда размыкается и, наконец FALLING стабильно дает 2 вызова при замыкании геркона.

Интересно получается. Судя по описанию:
LOW - вызов прерывания когда пин устанавливается в 0.
CHANGE - пин меняет состояние (0->1 или 1->0)
RISING - 0 -> 1
FALLING - 1 -> 0

Т.е. по всех случаях кроме CHANGE должен происходить один вызов прерывания за один проход магнита мимо датчика.

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

Код: Выделить всё

#define PinA  2
static boolean output = HIGH;
int pulse = 0;
bool prev = false;

void setup() 
{   
  pinMode(PinA, INPUT); 
  digitalWrite(PinA, HIGH);     // подключить подтягивающий резистор
  attachInterrupt(0, int_on, FALLING);  // настроить прерывание interrupt 0 на pin 2
  
  Serial.begin(9600);
} 

void loop()
{
  delay(100);
  Serial.println(pulse);
}

// обработка прерывания
void  int_on()
{
  digitalWrite(13, (output==HIGH) ? output=LOW : output=HIGH);
  if(!prev)
  {
    pulse++;
  }
  prev = !prev;
}
Сегодня протестировал на автомобиле: 8 импульсов на 1 оборот колеса (1 импульс = ~31см).
Аватара пользователя
Mr.Kubikus
Сотрудник ПАКПАК
Сообщения: 1020
Зарегистрирован: 22 окт 2010, 23:57

Re: Прерывания.

Сообщение Mr.Kubikus »

Тут вроде бы все соответствует описанию attachInterrupt(), не?
С уважением, Григорий
GitHub FB ВК
Marvin
Сообщения: 22
Зарегистрирован: 05 май 2012, 19:04

Re: Прерывания.

Сообщение Marvin »

Mr.Kubikus писал(а):Тут вроде бы все соответствует описанию attachInterrupt(), не?
Ввиду того, что причина вызова прерывания замыкание контактов имеющих дребезг, возникают интересные эфекты зависящие от третьего параметра функции attachInterrupt.
Аватара пользователя
Mr.Kubikus
Сотрудник ПАКПАК
Сообщения: 1020
Зарегистрирован: 22 окт 2010, 23:57

Re: Прерывания.

Сообщение Mr.Kubikus »

С вашего позволения добавлю еще несколько интересных материалов по "дребезгу" контактов.

Если сесть осциллографом на контакты переключателя, то можно увидеть такую картинку в момент замыкания:
switchbounce.jpg
switchbounce.jpg (78.34 КБ) 16081 просмотр
На картинке хорошо видна серия хаотичных всплесков сигнала в момент переключения. Вот эта "борода" и приводит к многократным вызовам обработчика прерывания в первой версии кода. Что-то специальное для антидребезга изобретать не потребуется. Все Уже придумано до нас - для Arduino есть библиотека Bounce специально для "умной" обработки сигналов от электромеханических контактов.

Сссылки
С уважением, Григорий
GitHub FB ВК
Marvin
Сообщения: 22
Зарегистрирован: 05 май 2012, 19:04

Re: Прерывания.

Сообщение Marvin »

В Bounce нужно задавать временной интервал, внутри которого дребезг будет считаться за одно нажатие. Для нажатия кнопок пользователем это хорошо, а при срабатывании геркона может привести к пропускам импульсов. А RISING и FALLING прекрасно решают проблему дребезга.
С 31см. я погорячился :) Нужно начинать отсчет расстояние не по заметке на колесе, а начиная с момента срабатывания импульса.

Доработал обработку следующим образом: Регистрирую импульс когда геркон размыкается. Зажигаю белый светодид с момента замыкания до момента размыкания - это предупреждение, что скоро придет импульс. Затем надо сделать заметку как только белый погаснет первый раз, до того как погаснет второй раз. Но было уже темно. Поэтому я взял два Озика с разными навигаторами, ездил по улицам и фиксировал показания GPS-одометров и Arduino-вского. На Arduino получается не намного большие значения, чем на GPS (понятно, что дрейф нулевой точки ни кто не отменял).
Ответить