ATtiny85: Timer interrupt vector conflict

I’m trying to use an ATtiny85 as a timer using an OLED screen and I’m getting an error on both timers like:

C:\Users\Michael\AppData\Local\arduino\sketches\31451F490CE4F6C6E5EA5B61DD97CD4D\core\Tone.cpp.o (symbol from plugin): In function _noTone': 
(.text+0x0): multiple definition of __vector_4'
C:\Users\Michael\AppData\Local\arduino\sketches\31451F490CE4F6C6E5EA5B61DD97CD4D\sketch\Timer_test.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
exit status 1

Compilation error: exit status 1

I think this is saying the Interrupt service routine is already in use?

How do I find out what library is using the timers? Or have I missed the point somewhere?

I tried right clicking on the ‘TIM1_OVF_vect’ and clicking go to definition but I don’t really know what I’m doing at this point, I’m new to embedded programming.

I’m using an Arduino uno to program the ATtiny.

The PinChangeInterrupt library is for a different part of the project, there will be a button and rotary encoder

Please feel free to comment on any other aspects of my code that could be better.

Code below:

#include <TinyWireM.h>
#include <Tiny4kOLED.h>
#include <PinChangeInterrupt.h>


//timer overflow counter
volatile uint8_t cntr = 0;
//elapsed time variables
volatile uint8_t seconds = 0;
volatile uint8_t minutes = 0;
volatile uint8_t hours = 0;
volatile uint8_t days = 0;


void setup() {
  // initialise OLED
  oled.begin(128, 64, sizeof(tiny4koled_init_128x64r), tiny4koled_init_128x64r);
  //OLED font size
  oled.setFont(FONT8X16);
  //Clear OLED
  oled.on();
  oled.clear();

  /*
  //initialise timer 0
  //Set all control register bits to 0
  TCCR0A=0x00;
  TCCR0B=0x00;
  //Set prescaler to 1024
  TCCR0B |= (1<<CS00) | (1<<CS01);
  //start timer from 0
  TCNT0=0;
  //enable timer 0 overflow interrupt
  TIMSK |= (1<<TOIE0);
  */

  //initialise timer 1
  //Set all control register bits to 0
  TCCR1=0x00;
  //TCCR0B=0x00;
  //Set prescaler to 1024
  TCCR1 |= (1<<CS13) | (1<<CS11) | (1<<CS10);
  //start timer from 0
  TCNT1=0;
  //enable timer 0 overflow interrupt
  TIMSK |= (1<<TOIE1);
  //enable interrupts
  sei();
}

void loop() {
  //check for increments
  //at system clock speed 1MHz ~3.8 overflows of counter equals 1 second
  //230/3.8 equals 1 minute,
  if(cntr >= 230) 
  {
    cntr=0;
    ++minutes;
  }
  if(minutes == 60)
  {
    minutes = 0;
    ++hours;
  }
  if(hours == 24)
  {
    hours = 0;
    ++days;
  }
  seconds = cntr/3.8;
  
  //print result to screen
  oled.setCursor(0,3);
  oled.print(seconds);
  oled.print("s:");
  oled.print(minutes);
  oled.print("m:");
  oled.print(hours);
  oled.print("h:");
  oled.print(days);
  oled.print("d:");
  oled.print(cntr);
  oled.print("c");
  oled.print("       ");
}

//isr to increment counter whenever timer overflows
ISR (TIM1_OVF_vect)
{
  ++cntr;
}

Simply, tell us what do you want to display on the OLED screen and what does ATtiny85 do here.

Yes.

The error told you where it was already defined. And it's not a library, it's in the core you're using. It even told you which file, and which function.

And you're already using register level programming and interrupts? Curious.

I want to display the elapsed time in seconds, minutes, hours and days

The timer1 overflow ISR increments a counter, and the main loop looks at that and calculates how many seconds have passed. when 60 seconds has passed it will increment the minute variable, then same of for hours and days.

Then it’ll print the elapsed time to the screen.

yess, I got that far but wasn’t sure what that meant and whether I could use it or not. I can’t tell when the core is using it for? It just looks like a definition for the macro?

This is where it took me in iotnx5.h:

/* Timer/Counter1 Overflow */
#define TIM1_OVF_vect_num		4
#define TIM1_OVF_vect			_VECTOR(4)
#define TIMER1_OVF_vect_num		4
#define TIMER1_OVF_vect			_VECTOR(4)
#define SIG_OVERFLOW1			_VECTOR(4)

aah I guess I meant I’m new to using microcontrollers like the ATtiny on their own instead of arduino boards. My mistake.

I have compiled your sketch of post #1 without error excluding this line #include <PinChangeInterrupt.h>. Try it.

#include <TinyWireM.h>
#include <Tiny4kOLED.h>
//#include <PinChangeInterrupt.h>


//timer overflow counter
volatile uint8_t cntr = 0;
//elapsed time variables
volatile uint8_t seconds = 0;
volatile uint8_t minutes = 0;
volatile uint8_t hours = 0;
volatile uint8_t days = 0;


void setup() {
  // initialise OLED
  oled.begin(128, 64, sizeof(tiny4koled_init_128x64r), tiny4koled_init_128x64r);
  //OLED font size
  oled.setFont(FONT8X16);
  //Clear OLED
  oled.on();
  oled.clear();

  /*
    //initialise timer 0
    //Set all control register bits to 0
    TCCR0A=0x00;
    TCCR0B=0x00;
    //Set prescaler to 1024
    TCCR0B |= (1<<CS00) | (1<<CS01);
    //start timer from 0
    TCNT0=0;
    //enable timer 0 overflow interrupt
    TIMSK |= (1<<TOIE0);
  */

  //initialise timer 1
  //Set all control register bits to 0
  TCCR1 = 0x00;
  //TCCR0B=0x00;
  //Set prescaler to 1024
  TCCR1 |= (1 << CS13) | (1 << CS11) | (1 << CS10);
  //start timer from 0
  TCNT1 = 0;
  //enable timer 0 overflow interrupt
  TIMSK |= (1 << TOIE1);
  //enable interrupts
  sei();
}

void loop() {
  //check for increments
  //at system clock speed 1MHz ~3.8 overflows of counter equals 1 second
  //230/3.8 equals 1 minute,
  if (cntr >= 230)
  {
    cntr = 0;
    ++minutes;
  }
  if (minutes == 60)
  {
    minutes = 0;
    ++hours;
  }
  if (hours == 24)
  {
    hours = 0;
    ++days;
  }
  seconds = cntr / 3.8;

  //print result to screen
  oled.setCursor(0, 3);
  oled.print(seconds);
  oled.print("s:");
  oled.print(minutes);
  oled.print("m:");
  oled.print(hours);
  oled.print("h:");
  oled.print(days);
  oled.print("d:");
  oled.print(cntr);
  oled.print("c");
  oled.print("       ");
}

//isr to increment counter whenever timer overflows
ISR (TIM1_OVF_vect)
{
  ++cntr;
}

weird. I still get the error. It might be because I’m using the ATtiny as a board, instead of the arduino uno? I’m using DIY ATtiny → ATtiny 85 in the board manager.

I have used the same ATtinyCore

Are there any C/C++ APIs to access the registers of ATtiny85?

Once again:

It's in the core file Tone.cpp, in the function _noTone. It couldn't be clearer.

I have no idea what core you're using (because you haven't said) so I can't pull up the file itself to show it to you. You'll have to look on your own.

Good luck.

Switching to ATtinyCore instead of DIY ATtiny did it! No idea why but I’m not complaining

weirdly it works even with the PinChangeInterrupt library for me. Hopefully I’ll still be able to use that.

You don't need that Library,

aah this is only half the project. I’ll be using a button and rotary encoder which needs that library, so I needed to make sure that wasn’t using the timer either.

You don't need a separate timer for this. It is an exact thing that millis() doing.