attiny85 and TimerOne.h

hi guys im working on a project with one led matrix and 2 shift registers.Since i use 3 ports on my arduino(latch, data, clock) i was thinking to trasfer my code to an ATTiny85 .
im using this code

// 8*8 led matrix 2 shifters 
#include <TimerOne.h>

//Pin connected to Pin 12 of 74HC595 (Latch)
int latchPin = 8;
//Pin connected to Pin 11 of 74HC595 (Clock)
int clockPin = 12;
//Pin connected to Pin 14 of 74HC595 (Data)
int dataPin = 11;
uint8_t led[8];
long counter1 = 0;
long counter2 = 0;
void setup() {
//set pins to output
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
led[0] = B11111111;
led[1] = B10000001;
led[2] = B10111101;
led[3] = B10100101;
led[4] = B10100101;
led[5] = B10111101;
led[6] = B10000001;
led[7] = B11111111;
Timer1.initialize(10000);
Timer1.attachInterrupt(screenUpdate);
}
void loop() {
counter1++;
if (counter1 >=100000) {counter2++;}
if (counter2 >= 10000) {
counter1 = 0;
counter2 = 0;
for (int i=0; i<8; i++) {
led[i]= ~led[i];
}
}
}
void screenUpdate() {
uint8_t row = B00000001;
for (byte k = 0; k < 9; k++) {
// Open up the latch ready to receive data!
digitalWrite(latchPin, LOW);
shiftIt(~row );
shiftIt(led[k] ); // LED array
// Close the latch, sending the data in the registers out to the
//matrix
digitalWrite(latchPin, HIGH);
row = row << 1;
}
}
void shiftIt(byte dataOut) {
// Shift out 8 bits LSB first,
// on rising edge of clock
boolean pinState;
//clear shift register read for sending data
digitalWrite(dataPin, LOW);
// for each bit in dataOut send out a bit
for (int i=0; i<8; i++) {
//set clockPin to LOW prior to sending bit
digitalWrite(clockPin, LOW);
// if the value of DataOut and (logical AND) a bitmask
// are true, set pinState to 1 (HIGH)
if ( dataOut & (1<<i) ) {
pinState = HIGH;
}
else {pinState = LOW;
}
//sets dataPin to HIGH or LOW depending on pinState
digitalWrite(dataPin, pinState);
//send bit out on rising edge of clock
digitalWrite(clockPin, HIGH);
digitalWrite(dataPin, LOW);
}
//stop shifting
digitalWrite(clockPin, LOW);
}

If i compile it for my duemillanove , no problem, but for my attiny85 i get this error.

attiny85 timer one.ccp tccr1b not declared in this scope

What can i do ?Thanks for your time...

So, it seems that the TimerOne library is not suported by attiny85...
Is there any code for driving med matrix without the use of TimerOne library?
PLEASE respond...

You are using Timer1 to call the screenUpdate function every 10ms, correct? Are you using Arduino Tiny to program the 't85 or something else?

thank you for responding.
Yes this is corrrect.
No im using the arduino duemillanove as isp to program them.

Are you programming from the Arduino IDE? What are you selecting from the Tools > Board menu? The standard Arduino IDE will program an ATmega328 or ATmega168. You'll need something like Arduino Tiny to program an ATtiny85.

I have been programming my ATTiny from an Ard Uno using this approach: http://hlt.media.mit.edu/?p=1229

im using the same method

I believe the HLT core uses Counter/Timer0 for millis(). Not sure if they use Timer1. If not, or if it's used for something you don't use or care about, you should be able to appropriate it.

.... not sure how to do that.... Could you pleaaaase help me?

ok i've been strangling with the code (im a complete newbie...)

//Pin connected to Pin 12 of 74HC595 (Latch)
int latchPin = 0;
//Pin connected to Pin 11 of 74HC595 (Clock)
int clockPin = 1;
//Pin connected to Pin 14 of 74HC595 (Data)
int dataPin = 2;
uint8_t led[8];
long counter1 = 0;
long counter2 = 0;
//unsigned long  time;
long previousMillis = 0; 
long interval = 10000;

void setup() {
//set pins to output
pinMode(latchPin, OUTPUT);
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
led[0] = B11111111;
led[1] = B10000001;
led[2] = B10111101;
led[3] = B10100101;
led[4] = B10100101;
led[5] = B10111101;
led[6] = B10000001;
led[7] = B11111111;
//Timer1.initialize(10000);
//Timer1.attachInterrupt(screenUpdate);
}
void loop() {
     

    
counter1++;
if (counter1 >=100000) {counter2++;}
if (counter2 >= 10000) {
counter1 = 0;
counter2 = 0;
for (int i=0; i<8; i++) {
led[i]= ~led[i];
}

}
unsigned long currentMillis = micros(); 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
    screenUpdate();
}
delay(500);
}
void screenUpdate() {


uint8_t row = B00000001;
for (byte k = 0; k < 9; k++) {
// Open up the latch ready to receive data!
digitalWrite(latchPin, LOW);
shiftIt(~row );
shiftIt(led[k] ); // LED array
// Close the latch, sending the data in the registers out to the
//matrix
digitalWrite(latchPin, HIGH);
row = row << 1;
}
}

void shiftIt(byte dataOut) {
// Shift out 8 bits LSB first,
// on rising edge of clock
boolean pinState;
//clear shift register read for sending data
digitalWrite(dataPin, LOW);
// for each bit in dataOut send out a bit
for (int i=0; i<8; i++) {
//set clockPin to LOW prior to sending bit
digitalWrite(clockPin, LOW);
// if the value of DataOut and (logical AND) a bitmask
// are true, set pinState to 1 (HIGH)
if ( dataOut & (1<<i) ) {
pinState = HIGH;
}
else {pinState = LOW;
}
//sets dataPin to HIGH or LOW depending on pinState
digitalWrite(dataPin, pinState);
//send bit out on rising edge of clock
digitalWrite(clockPin, HIGH);
digitalWrite(dataPin, LOW);
}
//stop shifting
digitalWrite(clockPin, LOW);

}

but what it does is a very quick flickering .... But i believe is a start... :blush:

EDIT: So news...
If i upload the code to my arduino and use it works.
If i upload it to the ATtiny85 there goes the flickering again... So i suppose is has to do with the internal clock... Is there any way to fix this?

pyrforos:
.... not sure how to do that.... Could you pleaaaase help me?

I'll give it a shot, what's your clock frequency?

thank you
I believe is 8MHz(or 1???)

Well if you haven't changed the fuses from the factory setting, then it's using the internal 8MHz RC oscillator divided by eight, so the CPU clock is 1MHz.

I wrote this using WinAVR. I don't currently have the HLT core installed, but I did test it with Arduino Tiny and it worked (although I imagine it stepped all over its millis() function in the process, ha!). I think it should work with HLT, but I recommend you try it standalone first. Just copy the entire code below into a new sketch, wire an LED to pin 3 (on the DIP package, I assume you're using a DIP?) and see if it blinks on for a second, then off for a second.

If that works, then you only need about the last 30 lines of code as indicated by the comments, try adding those into your sketch. In your setup() function, replace "Timer1.initialize(10000);" and "Timer1.attachInterrupt(screenUpdate);" with "setupTimer1(screenUpdate);".

This is pretty much quick-and-dirty code for a very specific purpose, based on how I understood the requirement. Let me know how (if) it works for you!

//Example for Arduino forum.
//Use ATtiny85 Timer/Counter1 to call a function every 10ms.
//In setup(), call setupTimer1() and pass it the name of your function which will
//run as part of the interrupt service routine (ISR) every 10ms. This function must take no
//arguments, return nothing, and should run as quickly as possible. The delay() and millis()
//functions will not work while the ISR is running and so should be avoided.
//Works with 1MHz or 8MHz system clock (others may be possible, but I got lazy).
//
//In this example, the myISR() function simply turns an LED on for a second, then off for a second.
//Connect the LED to DIP pin 3 (PB4).
//
//Jack Christensen 18Oct2011
//
//Scotchware License: If we meet some day, and you think this is worth it, you can buy me a scotch.

#include <avr/io.h>
#include <avr/interrupt.h>

//function prototypes
void setupTimer1(void (*isrPointer)(void));
void setup(void);
void loop(void);
void myISR(void);

#define LED PORTB4                  //connect LED to this pin

#ifndef ARDUINO                     //main() function not required in Arduino environment
int main(void) {
    setup();
    for(;;) {loop();}
    return 0;
}
#endif

void setup(void) {
    DDRB |= _BV(LED);               //set the LED pin as an output
    setupTimer1(myISR);             //set timer1 up to call myISR every 10ms
}

void loop(void) {
}

void myISR() {                      //this function will be called every 10ms
    static uint8_t myCounter;

    if (++myCounter == 100) {       //has a second elapsed?
        myCounter = 0;
        PINB |= _BV(LED);           //toggle the LED
    }
}

//Copy code from here down, AND uncomment the following line and move it near the top of your sketch BEFORE the setup() function.
//void setupTimer1(void (*isrPointer)(void));        //function prototype for setupTimer1()
void (*userISR)(void);              //pointer to the user's ISR

void setupTimer1(void (*isrPointer)(void)) {
    userISR = isrPointer;           //save the pointer to the user's ISR
    //set timer1 up to generate an interrupt every millisecond
    TCCR1 |= _BV(CTC1);             //clear timer1 when it matches the value in OCR1C
    TIMSK |= _BV(OCIE1A);           //enable interrupt when OCR1A matches the timer value
    sei();                          //enable global interrupts
    OCR1A = 124;                    //set the match value for interrupt
    OCR1C = 124;                    //and the same match value to clear the timer
#if F_CPU == 1000000                //1MHz system clock
    TCCR1 |= _BV(CS12);             //set prescaler to divide by 8 (this starts the timer)
#elif F_CPU == 8000000              //8MHz system clock
    TCCR1 |= _BV(CS12) | _BV(CS11) | _BV(CS10);    //set prescaler to divide by 64 (this starts the timer)
#else
    Clock must be 1MHz or 8MHz!     //Error, only 1MHz or 8MHz clock (F_CPU) supported.
#endif
}

ISR(TIMER1_COMPA_vect) {            //handles the Timer1 Compare Match A interrupt
    static uint8_t interruptCount;

    if (++interruptCount == 10) {   //have there been 10 interrupts? (i.e. 10ms)
        interruptCount = 0;         //yes, reset the counter
        userISR();                  //and call the user's ISR
    }
}

a veryy big thanks mate!(LOL Scotchware License XD XD)

Well it blinks but for about 9 or 10 sec ,but if i chanche the value of

   if (++myCounter == 100) {       //has a second elapsed?

to
  if (++myCounter == 10) {       //has a second elapsed? is seems to be working :slight_smile: for the blinky

im sorry, doesn't work on the project... i tried to play with the values but with no success...

Is it maybe blinking every 8 seconds? Maybe it thinks the clock is 8MHz when it's actually 1MHz. Comment out the lines indicated below, this will hard-code it for a 1MHz clock.

//#if F_CPU == 1000000                //1MHz system clock
    TCCR1 |= _BV(CS12);             //set prescaler to divide by 8 (this starts the timer)
//#elif F_CPU == 8000000              //8MHz system clock
//    TCCR1 |= _BV(CS12) | _BV(CS11) | _BV(CS10);    //set prescaler to divide by 64 (this starts the timer)
//#else
//    Clock must be 1MHz or 8MHz!     //Error, only 1MHz or 8MHz clock (F_CPU) supported.
//#endif

it works but the flickering stays... its like the update function is actually enough slow to mess up your eyes

Thinking some more on this.

From what you've said, I suspect you are telling the IDE (via Tools > Board) that you have an ATtiny85 @ 8MHz, but in fact it's running at 1MHz. Have you reset the fuses from their factory default values? Can you use AVRDUDE to read out the fuse bytes? What are their values? The factory defaults are Low Fuse=0x62, High Fuse=0xDF, Extended Fuse=0xFF. If you will change the Low Fuse to 0xE2, that will change the clock to 8MHz, which will work better for you I think.

Choosing different clock frequencies via Tools > Board in the IDE does not change the clock frequency in the hardware, it just tells the compiler what speed the clock is set to. So obviously the two need to match.

Then also be sure to uncomment these lines in the code, despite my previous post:

#if F_CPU == 1000000                //1MHz system clock
    TCCR1 |= _BV(CS12);             //set prescaler to divide by 8 (this starts the timer)
#elif F_CPU == 8000000              //8MHz system clock
    TCCR1 |= _BV(CS12) | _BV(CS11) | _BV(CS10);    //set prescaler to divide by 64 (this starts the timer)
#else
    Clock must be 1MHz or 8MHz!     //Error, only 1MHz or 8MHz clock (F_CPU) supported.
#endif

sorry for the delay...
No i did not touch any of the fuses... i don't know how to...
im on linux so i cant use avrdude, only arduino IDE, and the only option in boards is the name of the chip am using.

Not sure about Linux, but on Windows, avrdude is installed as part of the Arduino IDE, under hardware\tools\avr\bin.

But, lacking that, you could also change the clock prescaler on the fly! I should look at HLT again, maybe it assumes an 8MHz clock. Let's proceed on that assumption, and also factory fuse settings. Enter these as the first two lines in setup() to set the clock to 8MHz:

    CLKPR = 0x80;    //set the Clock Prescaler Change Enable bit
    CLKPR = 0x00;    //set the Clock Prescaler to divide by one

I installed HLT, and all of the entries in the boards.txt file have 1MHz clocks. I added one with 8MHz as below (also modified the name on the existing one to be clear it's 1MHz).

# modified the next line only
attiny85usbtinyisp.name=ATtiny85 @ 1MHz (w/ USB Tiny ISP)
attiny85usbtinyisp.upload.using=arduino:usbtinyisp
attiny85usbtinyisp.upload.maximum_size=8192
attiny85usbtinyisp.build.mcu=attiny85
attiny85usbtinyisp.build.f_cpu=1000000L
attiny85usbtinyisp.build.core=attiny45_85

# new entry
attiny85usbtinyisp8.name=ATtiny85 @ 8 MHz (w/ USB Tiny ISP)
attiny85usbtinyisp8.upload.using=arduino:usbtinyisp
attiny85usbtinyisp8.upload.maximum_size=8192
attiny85usbtinyisp8.build.mcu=attiny85
attiny85usbtinyisp8.build.f_cpu=8000000L
attiny85usbtinyisp8.build.core=attiny45_85

HOWEVER, something is funny with my demo code. It works when the 8MHz board is selected via Tools > Boards, but when using the 1MHz entry, the LED only blinks every eight seconds. Haven't figured out why yet, but I think you observed the same thing earlier. The same code works as expected at 1MHz with WinAVR or Arduino Tiny. Anyhoo, add an 8MHz entry to boards.txt, and try the code below, the LED should blink every second.

//Example for Arduino forum.
//Use ATtiny85 Timer/Counter1 to call a function every 10ms.
//In setup(), call setupTimer1() and pass it the name of your function which will
//run as part of the interrupt service routine (ISR) every 10ms. This function must take no
//arguments, return nothing, and should run as quickly as possible. The delay() and millis()
//functions will not work while the ISR is running and so should be avoided.
//Works with 1MHz or 8MHz system clock (others may be possible, but I got lazy).
//
//In this example, the myISR() function simply turns an LED on for a second, then off for a second.
//Connect the LED to DIP pin 3 (PB4).
//
//Jack Christensen 18Oct2011
//
//Scotchware License: If we meet some day, and you think this is worth it, you can buy me a scotch.

#include <avr/io.h>
#include <avr/interrupt.h>

//function prototypes
void setupTimer1(void (*isrPointer)(void));
void setup(void);
void loop(void);
void myISR(void);

#define LED PORTB4                  //connect LED to this pin

#ifndef ARDUINO                     //main() function not required in Arduino environment
int main(void) {
    setup();
    for(;;) {loop();}
    return 0;
}
#endif

void setup(void) {
#if F_CPU == 8000000                //8MHz system clock
    CLKPR = 0x80;                   //set the Clock Prescaler Change Enable bit
    CLKPR = 0x00;                   //set the Clock Prescaler to divide by one (8Mhz assuming factory default fuses)
#endif
    DDRB |= _BV(LED);               //set the LED pin as an output
    setupTimer1(myISR);             //set timer1 up to call myISR every 10ms
}

void loop(void) {
}

void myISR() {                      //this function will be called every 10ms
    static uint8_t myCounter;
    
    if (++myCounter == 100) {       //has a second elapsed?
        myCounter = 0;
        PINB |= _BV(LED);           //toggle the LED
    }
}

//Copy code from here down, AND uncomment the following line and move it near the top of your sketch BEFORE the setup() function.
//void setupTimer1(void (*isrPointer)(void));        //function prototype for setupTimer1()
void (*userISR)(void);              //pointer to the user's ISR

void setupTimer1(void (*isrPointer)(void)) {
    userISR = isrPointer;           //save the pointer to the user's ISR
    //set timer1 up to generate an interrupt every millisecond
    TCCR1 |= _BV(CTC1);             //clear timer1 when it matches the value in OCR1C
    TIMSK |= _BV(OCIE1A);           //enable interrupt when OCR1A matches the timer value
    sei();                          //enable global interrupts
    OCR1A = 124;                    //set the match value for interrupt
    OCR1C = 124;                    //and the same match value to clear the timer
#if F_CPU == 1000000                //1MHz system clock
    TCCR1 |= _BV(CS12);             //set prescaler to divide by 8 (this starts the timer)
#elif F_CPU == 8000000              //8MHz system clock
    TCCR1 |= _BV(CS12) | _BV(CS11) | _BV(CS10);    //set prescaler to divide by 64 (this starts the timer)
#else
#error Only 1MHz or 8MHz clock (F_CPU) supported!
#endif
}

ISR(TIMER1_COMPA_vect) {            //handles the Timer1 Compare Match A interrupt
    static uint8_t interruptCount;
    
    if (++interruptCount == 10) {   //have there been 10 interrupts? (i.e. 10ms)
        interruptCount = 0;         //yes, reset the counter
        userISR();                  //and call the user's ISR
    }
}