Attiny 861 timer problem - TCWORLD core

Hi, i´m trying to set up timer1 with my 861 but it messes with millis() somehow.

I´snt timer0 being used for millis ?

boolean flip = 0;

ISR(TIMER1_COMPA_vect){//timer1 interrupt 2Hz toggles pin 13 (LED)
  flip = 1;
}

void setup() {
  // put your setup code here, to run once:
  TCCR1A = 0 ;// disable PWM mode
  TCCR1B = _BV(CS13) | _BV(CS12) | _BV(CS11) | _BV(CS10);
  OCR1C = 245;
  
  TCNT1  = 0;
  TIMSK = _BV(OCIE1A);
  sei();
}

void loop() {
  // put your main code here, to run repeatedly: 
  if (flip){
  
  // do something
  }
  
}

I wanted a 2HZ timer with CTC mode, so it´s easy to handle.

given that the Attiny861 isn't supported by the standard Arduino core, you will have to be more specific as to which core you are using.

I tried using the TCWORLD core (GitHub - TCWORLD/ATTinyCore: ATTiny Core for Arduino 1.0+ - You will need to add 8mhz internal osc manually in boards.txt) since i´m getting too many compiler errors with Tinycore2 (native lcd library). Some tests resulted in timer 0 and 1 counting.
I´m using Attiny 861A.

Aren´t they all using the cores released by Atmel ?

They are all variants of each other and of the Arduino core which is a modified version of wiring.

I don't know why I didn't add an 8MHz variant of the 861, I will update the core to add one soon.
(Could you post the entry you added to the boards.txt file so I can add it to the core :slight_smile: )

The core should be using Timer0 for the millis() function as per the pins_arduino.h file.

#define TIMER_TO_USE_FOR_MILLIS                   0

This is your problem (just noticed it):

TIMSK = _BV(OCIE1A);

For the 861, TIMSK is a shared register for both timer 0 and timer 1. You should be doing this:

TIMSK |= _BV(OCIE1A);

Otherwise you disable the millis interrupt.

There are still some things which bother me :

  1. OCR1C is not 0 after startup its 0xFF

  2. I found a formula which is easy to use:
    prescaler / frequency = timer interrupt interval in seconds
    16384 / 8000000 = 0,002048 * 244 = 0,499712 which should equal to 2hz
    But when i set 244 its like a seconds, using 123 nears half a second.
    Will using DTPS (in TCCR1B) give me any advantage /difference ?

  3. I want to measure current and integrate Wh and Ah so i need to be as exact as i can in terms of timecounting .
    Your trick worked but i can feel that its a bit less than a second/half a second.
    Would you suggest using an external oscillator or try to measure the frequency and adapt it in time calculations ?
    Can i use Tinytuner for that (don´t really know what it´s doing).

Since i need to reduce code size as hell to get it all onto the tiny (lcd in 4 bit mode and 2 buttons, session saving/displaying, setup to set values digitwise for control and calibration) .
So far pretty much everything except the power analyzer itself with autogain and some displaypages with logic needs to be implemented and im about 5kb size now, and i really don´t want to cut out any of the features i have implemented.
I look for solutions which keep code size smallest.

Thanks, you already helped me alot !

OCR1C will be 255 after startup. This is because there is an init() function which is called before setup() which initialises all the timers in an 8bit PWM mode (hence the 255) - this is so that analogWrite() works as expected. If you don't need the PWM pins, then there is no problems with changing the timers.

_BV(n) is the same as (1<<n). It simply creates a bit mask. e.g.:

_BV(0) == 0b00000001
_BV(1) == 0b00000010
_BV(2) == 0b00000100

etc.

The "|=" bit does the bitwise or of what is in the register already with the mask you have created and saves it back to the register. If you just use an "=" operator it simply assigns the bitmask to the register which means that the bit you want is a 1, but all others in the register are written to 0. This clears the timer 0 interrupt enable bit amongst others.

Regarding the frequency, it will have half of what you think it is because the timer counts from 0 to 243, then toggles the pin, then counts from 0 to 243, then toggles the pin. This means that for a pin to go high to low to high again takes twice as long as you think. It is like doing this:

delay(500);
digitalWrite(pin,HIGH);
delay(500);
digitalWrite(pin,LOW);

and expecting to get a 2Hz signal - it will actually be 1Hz.

You also have to remember that to get the time in seconds you multiply by (OCR1C+1), not OCR1C. So if you want a value of 244, then you need to set OCR1C = 243.

To get 2Hz, you should use OCR1C=121 as:
OCR1C = (( 0.25 [seconds] * 8000000 [clocks per second]) / 16384 [clocks per period])-1 = 121

Yeah i realized that with = and |= but i couldn´t edit before you began posting your reply :grin:

Well how is millis calculated anyways and is it affected by wrong calibrated frequency of the internal osci ?
Since timer0 can only uses 2 8 bit register (TCNT0L/H) i dont quite get how to get an unsigned long out of it.

Sorry for all theese questions but they have been bothering me quite a while and i haven´t found clear answers (maybe due to wrong search terms).

Timer0 only has one register - TCNT0 - its an 8bit timer.

Essentially the timer isn't used to store millis(), a separate unsigned long variable is. The timer is set in a freerunning mode whereby after each 4 times it overflows (0.25 milliseconds each) it increments the variable that millis() returns.

If the internal oscillator is wrong, the millis() function will also be wrong by the same amount. It should never, even with a crystal, be used for time critical events or long term timekeeping (RTC should be used for the latter).

(Could you post the entry you added to the boards.txt file so I can add it to the core smiley )

attiny861at8.name=ATtiny861 @ 8 MHz (internal oscillator; BOD disabled)
attiny861at8.upload.using=arduino:arduinoisp
attiny861at8.upload.maximum_size=8192
attiny861at8.bootloader.low_fuses=0xE2
attiny861at8.bootloader.high_fuses=0xDF
attiny861at8.bootloader.extended_fuses=0xFF
attiny861at8.bootloader.path=empty
attiny861at8.bootloader.file=empty861at8.hex

attiny861at8.build.mcu=attiny861
attiny861at8.build.f_cpu=8000000L
attiny861at8.build.core=tiny
attiny861at8.build.variant=tinyX61

Sorry, didn´t have a lot of time this week.

The upload seems to be very slow (above 6kb), so i added following line :
attiny861at8.upload.protocol=arduinoattiny861at8.upload.speed=19200

Seems like this is the already used baud rate, at least avrdude is saying that.

There are a few more things which I´m having trouble with using your core:
The Bin bit in ADCSRB is bit 7 not 2, but i guess thats because BIN is defined in arduino e.g. Serial.print(x, BIN)

When i try to burn the 8mhz bootloader i get :

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0xff != 0x01
avrdude: verification error; content mismatch

I would like to use this lcd library https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads, but i´m getting errors :

In the same Directory
LiquidCrystal\LCD.cpp.o:(.rodata._ZTV3LCD+0xe): undefined reference to `__cxa_pure_virtual'
When putting it in documents\libraries
C:\Users\Master\Documents\Arduino\libraries\LiquidCrystal\I2CIO.cpp: In member function 'int I2CIO::begin(uint8_t)':
C:\Users\Master\Documents\Arduino\libraries\LiquidCrystal\I2CIO.cpp:61: error: 'Wire' was not declared in this scope
C:\Users\Master\Documents\Arduino\libraries\LiquidCrystal\I2CIO.cpp: In member function 'uint8_t I2CIO::read()':
C:\Users\Master\Documents\Arduino\libraries\LiquidCrystal\I2CIO.cpp:117: error: 'Wire' was not declared in this scope
C:\Users\Master\Documents\Arduino\libraries\LiquidCrystal\I2CIO.cpp: In member function 'int I2CIO::write(uint8_t)':
C:\Users\Master\Documents\Arduino\libraries\LiquidCrystal\I2CIO.cpp:140: error: 'Wire' was not declared in this scope

The standard library works but i miss the moveCursorRight () method, or is there any secret trick to get the same result without printing anything?

I´m still testing alot, will post more when problems occur.