Прерывания AVR по смене контакта срабатывают безошибочно

Итак, я использую ATMega168 с NerdKits и подключите к нему ЖК-дисплей, используя два прерывания INT0 и INT1. Я хочу подключить монитор сердечного ритма Grove, который я подключил к PCINT1 и попытался включить и использовать

void hrm_init()
{
//clear pin
  DDRB &= ~(1<<DDB0);
  PORTB |= (1<<PORTB0);
//turn on pull up
  PCICR |= (1<<PCIE0);   //enable pcint 1
  PCMSK0 |= (1<<PCINT1); //Trigger on change of PCINT1 (PB1)
  sei();
}

ISR(PCINT0_vect)
{
   uint8_t changedBits;

   changedBits = PINB ^ porthistory;
   porthistory = PINB;

   //pin has changed
   if (changedBits & (1<<PB1)) 
   {     
      beats += ((PINB & _BV(PB1)) ? 1 : 0); //add a beat on the rising edge 
   }
}

(Код счетчика ударов украден у кого-то в сети, отсюда и использование макроса.)

Это работает в большинстве случаев, но может добавить дополнительные удары здесь и там, я видел целых 10, в то время как у меня также есть прерывание по таймеру (которое я буду использовать для расчета ударов в минуту).

void clock_init() 
{
  TCCR0A |= (1<<WGM01);
  TCCR0B |= (1<<CS02) | (1<<CS00);
  OCR0A = 143;
  TIMSK0 |= (1<<OCIE0A);
}

SIGNAL(SIG_OUTPUT_COMPARE0A) {
  the_time++;

  if (the_time > 500)
  {
    bpm = beats;
    bpm *= 12; //60 seconds divided by 5

    the_time = 0;
    beats = 0;
  }
}

person Ross Drew    schedule 17.11.2013    source источник


Ответы (1)


Вероятно, на сигнале пульсометра присутствует шум. Есть несколько способов справиться с этим. Один из них — аппаратный фильтр, но вы можете работать с ним программно, используя механизм «устранения дребезга» или «устранения сбоев».

Вот один из механизмов «устранения сбоев». Вы не ожидаете, что два удара сердца будут происходить с интервалом в несколько миллисекунд друг от друга. Таким образом, вы можете отклонить (пропустить соответствующий счетчик) любой нарастающий фронт в пределах, скажем, двух миллисекунд от предыдущего нарастающего фронта.

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

Используйте беззнаковую арифметику, чтобы вычесть и сравнить результат с двумя миллисекундами. Таким образом, вам не нужно беспокоиться о переносе таймера.

ISR(PCINT0_vect)
{
   static uint16_t last_rising_edge = 0;
   uint8_t changedBits;

   changedBits = PINB ^ porthistory;
   porthistory = PINB;

   //pin has changed
   if (changedBits & (1<<PB1)) 
   {
      uint16_t now = get_milliseconds();

      if (0 != (PINB & _BV(PB1) && (now - last_rising_edge) >= 2u)
      {
          beats += 1; //add a beat on the rising edge
          last_rising_edge = now;
      }
   }
}
person Doug Currie    schedule 17.11.2013
comment
Я слышал о дребезге, но я предположил, что однострочный цифровой сигнал не будет подвержен этому, очевидно, я ошибся. Спасибо, я попробую и соглашусь, если это сработает. - person Ross Drew; 18.11.2013
comment
Если вы ожидаете сбоев на выводе, который используется для запуска прерываний, вам следует либо изменить прерывание на механизм опроса, либо добавить аппаратный фильтр нижних частот. В противном случае вход теоретически может повесить весь ваш ЦП, так что он ничего не делает, кроме выполнения прерываний. Это особенно верно для медленных 8-битных микроконтроллеров. - person Lundin; 18.11.2013
comment
Сначала я пытался опрашивать около 10 раз в секунду, но, похоже, получались странные результаты, несколько включенных или выключенных ударов подряд, а затем большие перерывы между ударами (это по сравнению с работающими часами). Прерывания, казалось, работали намного лучше. Поскольку мое сердце не может биться чаще, чем 4 раза в секунду, и пока я держу код в своей процедуре прерывания коротким, должно ли это оставаться проблемой? Кроме того, будет ли фильтр нижних частот лучшим средством устранения дребезга, чем программное обеспечение? - person Ross Drew; 18.11.2013
comment
Импульсы от монитора сердечного ритма выглядят довольно короткими, если трассировка прицела на их веб-странице вообще точна; Я бы оценил рабочий цикл менее чем в 1%. Так что опрос не пройдет. Я считаю, что решение, которое я представил в ответе выше, является лучшим программным подходом. Он также будет работать с аппаратным фильтром. - person Doug Currie; 18.11.2013