Ошибка компиляции кода для Arduino/Genuino Uno. "multiple definition of `__vector_7"

#include <PulseSensorPlayground.h>

int pulsePin = A0;                 // Пурпурный провод датчика пульса подключен к аналоговому выводу A0
int Redled = 7;  // Вывод для красного светодиода, который уведомляет вас, если частота сердечных сокращений увеличивается.
int Greenled = 8; // Вывод для зеленого светодиода, который уведомляет вас, если ваш сердечный ритм стабилен.
int buzzer = 9; // Вывод для пьезоэлемента, который воспроизводит музыку, когда частота сердечных сокращений увеличивается.
int music[] = {261, 277, 294, 311, 330, 349, 370, 392, 415, 440};//Частота, которую будет воспроизводить пьезо.


// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0;         // последний раз, когда выходной вывод был переключен
long debounce = 200;   // время debounce увеличивается, если выход мерцает
//кнопочный стопор деталей

// Volatile Переменные, используемые в подпрограмме обслуживания прерываний!
volatile int BPM;                   // int, который содержит необработанный аналог в 0. обновляется каждые 2 мс
volatile int Signal;                // содержит входящие необработанные данные
volatile int IBI = 600;             // int, который содержит интервал времени между ударами! Должно быть, посеяно! 
volatile boolean Pulse = false;     // "True" при обнаружении живого сердцебиения пользователя. "Фальшивый", когда не "живой ритм". 
volatile boolean QS = false;        // становится истинным, когда Arduoino находит ритм.

static boolean serialVisual = true;   // По умолчанию установлено значение false.  Установите значение "true", чтобы увидеть визуальный импульс ASCII Arduino Serial Monitor 

volatile int rate[10];                      // array to hold last ten IBI values
volatile unsigned long sampleCounter = 0;          // used to determine pulse timing
volatile unsigned long lastBeatTime = 0;           // used to find IBI
volatile int P = 512;                      // используется для поиска пика в импульсной волне, посеянной
volatile int T = 512;                     // используется для нахождения впадины в импульсной волне, seeded
volatile int thresh = 525;                // используется для нахождения мгновенного момента биения сердца, seeded
volatile int amp = 100;                   // используется для удержания амплитуды импульсной волны, seeded
volatile boolean firstBeat = true;        // используется для массива скорости посева, поэтому мы запускаемся с разумным BPM
volatile boolean secondBeat = false;      // используется для массива скорости посева, поэтому мы запускаемся с разумным BPM

void setup()
{



 pinMode(Redled, OUTPUT); //Это определяет вывод
 pinMode(Greenled, OUTPUT);//Это определяет, что зеленый светодиод будет выходом.
 pinMode(buzzer,OUTPUT);//Это определяет, что пьезо-вывод будет выходом.


  Serial.begin(115200);
  interruptSetup();                // настраивает считывание импульсного сигнала датчика каждые 2 мс
                                    // Аналоговая связь(ВНЕШНЯЯ);   

}


// Непрерывный и не останавливающий
void loop()
{



   serialOutput();  

  if (QS == true) // Было обнаружено сердцебиение
    {     
      // BPM и IBI были определены
      // Quantified Self "QS" true when arduino находит сердцебиение
      serialOutputWhenBeatHappens(); // Произошел удар, выведите его на serial.     
      QS = false; // сбросить флаг Quantified Self для следующего раза    
    }
   if (BPM > 50){ //Если частота сердечных сокращений превышает 55 ударов в минуту, то...

    digitalWrite(Redled, HIGH);//Красный светодиод загорится
    digitalWrite(Greenled, LOW);//Зеленый светодиод погаснет

   }
   else if(BPM < 50)//Если частота сердечных сокращений ниже 55 ударов в минуту, то...
   {
   digitalWrite(Redled, LOW);//Красный светодиод останется выключенным
   digitalWrite(Greenled, HIGH);//Зеленый светодиод останется включенным
   tone(3, 500, 1000);

   }
  delay(20); // take a breakx


  }

void interruptSetup()
{     
  // Инициализирует Timer2 для прерывания каждые 2 мс.
  TCCR2A = 0x02;     // ОТКЛЮЧИТЕ ШИМ НА ЦИФРОВЫХ ВЫВОДАХ 3 И 11 И ПЕРЕЙДИТЕ В РЕЖИМ CTC
  TCCR2B = 0x06;     // НЕ ПРИНУДИТЕЛЬНО СРАВНИВАТЬ, ПРЕСКАЛЕР 256 
  OCR2A = 0X7C;      // УСТАНОВИТЕ ВЕРХНЮЮ ЧАСТЬ СЧЕТА НА 124 ДЛЯ ЧАСТОТЫ ДИСКРЕТИЗАЦИИ 500 ГЦ
  TIMSK2 = 0x02;     // ВКЛЮЧИТЬ ПРЕРЫВАНИЕ ПРИ СОВПАДЕНИИ TIMER2 И OCR2A
  sei();             // УБЕДИТЕСЬ, ЧТО ГЛОБАЛЬНЫЕ ПРЕРЫВАНИЯ ВКЛЮЧЕНЫ      
} 

void serialOutput()
{   // Решите, как вывести Serial. 
 if (serialVisual == true)
  {  
     arduinoSerialMonitorVisual('-', Signal);   // переходит к функции, которая делает Последовательный монитор визуализатором
  } 
 else
  {
      sendDataToSerial('S', Signal);     // переходит к функции sendDataToSerial
   }        
}

void serialOutputWhenBeatHappens()
{    
 if (serialVisual == true) //  Code to Make the Serial Monitor Visualizer Work
   {            
     Serial.print(" Heart-Beat Found ");  //ASCII Art Madness
     Serial.print("BPM: ");
     Serial.println(BPM);

     delay(300);

   }
 else
   {
     sendDataToSerial('B',BPM);   // отправить частоту сердечных сокращений с префиксом 'B' 
     sendDataToSerial('Q',IBI);   // время отправки между ударами с префиксом 'Q' 
   }   
}

void arduinoSerialMonitorVisual(char symbol, int data )
{    
  const int sensorMin = 0;      // минимум датчика, обнаруженный в ходе эксперимента
  const int sensorMax = 100;    // максимум датчика, обнаруженный в ходе эксперимента
  int sensorReading = data; // сопоставьте диапазон датчиков с диапазоном из 12 вариантов:
  int range = map(sensorReading, sensorMin, sensorMax, 0, 11);
  // сделайте что-то другое в зависимости от 
  // значение диапазона:
}


void sendDataToSerial(char symbol, int data )
{
   Serial.print(symbol);
   Serial.println(data);                
}

ISR(TIMER2_COMPA_vect) //срабатывает, когда Timer2 отсчитывает до 124
{  
  cli();                                      // отключите прерывания, пока мы это делаем
  Signal = analogRead(pulsePin);              // считывать импульсный датчик
  sampleCounter += 2;                         // отслеживать время в мС с помощью этой переменной
  int N = sampleCounter - lastBeatTime;       // отслеживать время с момента последнего удара, чтобы избежать шума
                                              // найти пик и впадину пульсовой волны
  if(Signal < thresh && N > (IBI/5)*3) // избегайте дихротического шума, ожидая 3/5 последнего IBI
    {      
      if (Signal < T) // T-корыто
      {                        
        T = Signal; // отслеживать самую низкую точку в импульсной волне
      }
    }

  if(Signal > thresh && Signal > P)
    {          // условие обмолота помогает избежать шума
      P = Signal;                             // P-пик
    }                                        // следите за самой высокой точкой пульсовой волны

  // ТЕПЕРЬ ПРИШЛО ВРЕМЯ ИСКАТЬ СЕРДЦЕБИЕНИЕ
  // сигнал повышается по значению каждый раз, когда возникает импульс
  if (N > 250)
  {                                   // избегайте высокочастотного шума
    if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) )
      {        
        Pulse = true;                               // установите флаг Pulse, когда мы думаем, что есть импульс

        IBI = sampleCounter - lastBeatTime;         // измерьте время между ударами в МС
        lastBeatTime = sampleCounter;               // отслеживание времени для следующего импульса

        if(secondBeat)
        {                        // если это второй удар, если secondBeat == TRUE
          secondBeat = false;                  // очистить флаг secondBeat
          for(int i=0; i<=9; i++) // seed the running total to get a realisitic BPM at startup
          {             
            rate[i] = IBI;                      
          }
        }

        if(firstBeat) // если мы впервые нашли ритм, if firstBeat == TRUE
        {                         
          firstBeat = false;                   // очистить флаг firstBeat
          secondBeat = true;                   // установить флаг второго такта
          sei();                               // снова включить прерывания
          return;                              // Значение IBI ненадежно, поэтому отбросьте его
        }   
      // сохранить общее количество последних 10 значений IBI
      word runningTotal = 0;                  // очистить переменную runningTotal    

      for(int i=0; i<=8; i++)
        {                //данные сдвига в массиве rate
          rate[i] = rate[i+1];                  // и отбросить самое старое значение IBI 
          runningTotal += rate[i];              // сложите 9 самых старых значений IBI
        }

      rate[9] = IBI;                          // добавить последний IBI в массив rate
      runningTotal += rate[9];                // добавить последний IBI в runningTotal
      runningTotal /= 10;                     // усреднение последних 10 значений IBI 
      BPM = 60000/runningTotal;               // сколько ударов может поместиться в минуту? это BPM!
      QS = true;                              // установить флаг Quantified Self
      // ФЛАГ QS НЕ ОЧИЩАЕТСЯ ВНУТРИ ЭТОГО ISR
    }                       
  }

  if (Signal < thresh && Pulse == true)
    {   // когда значения снижаются, ритм заканчивается
      Pulse = false;                         // сбросьте флаг Pulse, чтобы мы могли сделать это снова
      amp = P - T;                           // получить амплитуду импульсной волны
      thresh = amp/2 + T;                    // установить thresh на 50% амплитуды
      P = thresh;                            // сбросьте их в следующий раз.
      T = thresh;
    }

  if (N > 2500)
    {                           // если 2,5 секунды проходят без такта
      thresh = 512;                          // установить thresh по умолчанию
      P = 512;                               // установить P по умолчанию
      T = 512;                               // установить T по умолчанию
      lastBeatTime = sampleCounter;          // обновите
      firstBeat = true;                      // установите их, чтобы избежать шума
      secondBeat = false;                    // когда мы получим сердцебиение обратно
    }

  sei();                                   // включите прерывания, когда закончите!
}// конец isr

Это код ошибки, который я получаю

Arduino: 1.8.10 (Windows 10), Board: "Arduino Uno"

Tone.cpp.o (symbol from plugin): In function `timer0_pin_port':

(.text+0x0): multiple definition of `__vector_7'

sketch\Heart_Beat_Sensor_Code.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

collect2.exe: error: ld returned 1 exit status

Multiple libraries were found for "PulseSensorPlayground.h"
 Used: C:\Users\amaan\Documents\Arduino\libraries\PulseSensor_Playground
exit status 1
Error compiling for board Arduino Uno.

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

, 👍0

Обсуждение

Вы используете две библиотеки, которые пытаются использовать таймер 0 (библиотека PulseSensor и функция tone ())., @Majenko

Как бы я это исправил?, @guest11111

Вам придется переписать (или иным образом отредактировать) эту библиотеку "pulse sensor playground" (что бы это ни было), чтобы использовать другой таймер. Или не используйте tone()., @Majenko


1 ответ


1

Как команда tone (), так и библиотека PulseSensor_Playground используют прерывание таймера 0. Это означает, что существует две реализации ISR для этого прерывания. Однако у вас может быть только одна реализация функции или ISR, поэтому она конфликтует.

Вам придется изменить библиотеку PulseSensor_Playground, чтобы использовать другой таймер. Возможно, в коде уже есть способ (некоторые библиотеки реализуют такую вещь) - если нет, то вам придется переписать библиотеку, чтобы использовать другой таймер.

,