ATtiny85 interrupt not working as I would expect them to

I've been trying to drive a servo off the ATtiny85 using interrupts and I'm not having much luck. I've distilled the code down the the absolute minimum, I believe that the code should produce an asymmetric waveform but it doesn't, something strange is happening and the OCR0A registry doesn't seem to react to new values that I assign in the switch cases.... Help!

int state =1;

void setup() {
 
     pinMode(0, OUTPUT);
 
          // Enable Output Compare Match Interrupt
          TIMSK |= (1 << OCIE0A);

           //set the compare value to any number larger than 0
          OCR0A = 255;

          //reset the Timer Counter Control Register to its reset value
            TCCR0B = 0;

           //set counter0 prescaler to 64
            //our FCLK is 8mhz so this makes each timer tick be 8 microseconds long

          TCCR0B &= ~(1<< CS02); //clear
            TCCR0B |=  (1<< CS01); //set
            TCCR0B |=  (1<< CS00); //set
 

}

void loop() {
//nada
}

ISR(TIMER0_COMPA_vect)
{
switch (state)
    {  
    case 1:
        PORTB|=   B00000001; //set pin high
        TCNT0  = 0;//reset the counter to 0
                   OCR0A = 200;
        //update our state
        state = 2;
        break;

    case 2:
                PORTB &= ~B00000001; //set pin low
        //set the compare value to the additional amount of timer ticks the pulse should last
        //update our state
          OCR0A = 50;
        TCNT0  = 0;//reset the counter to 0
        state = 1;
        break;
        
    }//end switch

}

I think you have to start the timer in CTC mode, see table 11.5 in the datasheet

TCCR0A |=(1<<WGM01); //Start timer 1 in CTC mode Table 11.5

Thanks very much for the reply, I didn't have that bit set but it doesn't seem to make any difference...

Hmm it works for me.
I just tried this on a t85, the ISR gets called every 2,04 ms

volatile int state =1;

void setup() {
  pinMode(0, OUTPUT);
  cli();
  TCCR0B = 0;
  TCCR0A = 0;
  TCCR0A |=(1<<WGM01); //Start timer 1 in CTC mode Table 11.5 
  TIMSK |= (1 << OCIE0A); //Enable CTC interrupt see 13.3.6
   OCR0A = 255; //CTC Compare value
  TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler =64 Table 11.6

sei();
}

void loop() {
  //nada
}

ISR(TIMER0_COMPA_vect){
  state=!state;
  if (state==1){
    PORTB |=(1<<PB0);  //high
  }
  else{
    PORTB &= ~(1<<PB0);   // low 
  }

}

Thanks again for the reply.

I get this error when I run that code:

avrdude: verification error, first mismatch at byte 0x0180
0x1f != 0x0f
avrdude: verification error; content mismatch

Also, I'm trying to change the compare register each time I enter the ISR so that I can replicate a servo drive waveform, my original clip of code has 200 and 50 assigned alternatively to the OCR0A register but the pin doesn't seem to be spending the prescribed time in those states.

I get this error when I run that code:

That error is from uploading the code, not the compilation.

Also, I'm trying to change the compare register each time I enter the ISR

I know my example was just to check that your timer setup was working as expected.

Do you have some way of checking that you get the results you are expecting (like a LogicAnalyzer or Scope )?

I do have a O'Scope to see how long the pin spends up and down, that's how I go to the point where I know the output wave form isn't asymmetric as I'd expect, its completely symmetric, transitions are on a time that lines up with the smallest value I put in for the OCR0A registry leading me to believe that I'm not changing the OCR0A in the ISR.

What should I do to get your code to upload?

Thanks again for the help.

Can you upload other sketches ?

There is nothing special about my sketch, atleast I don't think so.

Note that if you have something connected to the programming pins (for example your Scope) it may cause errors.

I am using this tiny core:

https://code.google.com/p/arduino-tiny/

If I use your ISR routine I get the below result with my LogicAnalyzer

Here we go

t85.png

I was able to get your code to load after a removed the scope probe, thanks for the tip!

Your scope shot shows exactly what I'm expecting, but it's not what I'm getting. I checked and I'm using the same core.

So I'm still not sure why I get this:
http://postimg.org/image/8p6236pj7/
When I load this code:

int state =1;

void setup() {
 
     pinMode(0, OUTPUT);
 
          // Enable Output Compare Match Interrupt
          TIMSK |= (1 << OCIE0A);
          TCCR0A |=(1<<WGM01); //Start timer 1 in CTC mode Table 11.5
           
           //set the compare value to any number larger than 0
          OCR0A = 255;

          //reset the Timer Counter Control Register to its reset value
            TCCR0B = 0;

           //set counter0 prescaler to 64
            //our FCLK is 8mhz so this makes each timer tick be 8 microseconds long

          TCCR0B &= ~(1<< CS02); //clear
            TCCR0B |=  (1<< CS01); //set
            TCCR0B |=  (1<< CS00); //set
 

}

void loop() {
}

ISR(TIMER0_COMPA_vect)
{
switch (state)
    {  
    case 1:
        PORTB|=   B00000001; //set pin high
        TCNT0  = 0;//reset the counter to 0
                   OCR0A = 200;

        //update our state
        state = 2;
        break;

    case 2:
                PORTB &= ~B00000001; //set pin low
        //set the compare value to the additional amount of timer ticks the pulse should last
        //update our state
          OCR0A = 50;

        TCNT0  = 0;//reset the counter to 0
        state = 1;
        break;
        
    }//end switch

}

Any more ideas?

Well I was able to mod your code and get the effect I was looking for, so thanks!

I'm still not clear why it wasn't working the way I'd like but here is what seems to be working now:

volatile int state =1;

void setup() {
  pinMode(0, OUTPUT);
  cli();
  TCCR0B = 0;
  TCCR0A = 0;
  TCCR0A |=(1<<WGM01); //Start timer 1 in CTC mode Table 11.5 
  TIMSK |= (1 << OCIE0A); //Enable CTC interrupt see 13.3.6
   OCR0A = 255; //CTC Compare value
  TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler =64 Table 11.6

sei();
}

void loop() {
  //nada
}

ISR(TIMER0_COMPA_vect){
  state=!state;
  if (state==1){
    PORTB |=(1<<PB0);  //high
       OCR0A = 50; //CTC Compare value
  }
  else{
       OCR0A = 255; //CTC Compare value
    PORTB &= ~(1<<PB0);   // low 
  }

}

I did bit more modification to Erni's code, I'm trying bring in the servopos variable into the ISR and it doesn't seem to want to go.

I get a static waveform When I run this code, when I'm expecting a varying duration pulse:

volatile int state =1;
volatile byte servopos =60;

void setup() {
  pinMode(0, OUTPUT);
  cli();
  TCCR0B = 0;
  TCCR0A = 0;
  TCCR0A |=(1<<WGM01); //Start timer 1 in CTC mode Table 11.5 
  TIMSK |= (1 << OCIE0A); //Enable CTC interrupt see 13.3.6
   OCR0A = 255; //CTC Compare value
  TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler =64 Table 11.6

sei();
}

void loop() {
  

  delay(100);
  
  cli();
    servopos++;
  if(servopos=125) servopos=0;
  sei();
  

  //nada
}

ISR(TIMER0_COMPA_vect){

  state=!state;
  if (state==1){
    PORTB |=(1<<PB0);  //high
    OCR0A = 130+servopos;//byte(reg); //CTC Compare value
  }
  else{
       OCR0A = 255; //CTC Compare value
    PORTB &= ~(1<<PB0);   // low 

  }

}

What should I be doing beyond volatile labeling the variables I want to access in the main and ISR sections what else and I supposed to do?

That is strange.
When I try your latest sketch I get a assymetric waveform (about 1.04 High and 2.04 low).

The only explanation I can think of is that the tiny is autoresetting.
The usual advise to solve this is to connect a 10kOhm resistor from reset to Vcc, and a 0.1 uF capacitor from ground to Vcc as close to the chip as possible.

BTW if it is a servo signal to control a standard rc servo that you are trying to make, then
there are servo libraris for the t85.

So you're not seeing the pulse change duration as the main loop changes the servopos value either?

I've tried to get the servo library referred to below to work but had no luck, so I pulled apart the library and tried to reverse engineer it... and that's where I am now.

http://www.cunningturtle.com/attiny4585-servo-library/

I only need to control one servo... this doesn't seem like it should be that difficult.

I'll try the cap and resistor on pin one and see what happens.

I'm also wondering if using another IDE would make any difference, like using WINAVR...

Thanks again for all the help.

You could try this library, it worked for me

http://forum.arduino.cc

OK, I tried to get that library to work and I get this error:

In file included from TinyServoExample.ino:39:0:
C:\Users\Bill\Documents\Arduino\libraries\TinyServo/TinyServo.h:77:4: error: #error TinyServo library does not support this processor.
   #error TinyServo library does not support this processor.

I can't say I understand why, it's pretty straightforward that the ATtiny85 is supported, I look through the logic tree in TinyServo.h and I think that the 85 should be covered.

I'm running at 8 MHz, in which case it's recommended that I force the timer to timer 1 but I'm not really sure how to do that, I found the file core_build_options.h but wasn't sure what to change. I tried 1 MHz but that didn't change the error...

I just retried the library and it works as I remember.
I didn't change the Timer

My test sketch that sweeps a servo connected to pin 3

// tylernt@gmail.com's ATTiny Hardware Timer Assisted Servo Library v1.0 20-Nov-13
#include <TinyServo.h>
const byte SERVOS = 1; 
const byte servoPin[SERVOS] = { 3}; 

#define SERVO 0

void setup() {
  setupServos();
}

void loop() {
  delay(1000);
  for (byte i = 0; i <= 180; i++)
  {
    moveServo(SERVO, i);
    delay(50);
  }
}

I got the same "processor not supported error" with your code. I'm guessing that there must be something in the 1.63 version on the IDE I'm using that is difference in the naming of processors.

Maybe, I have tried it both in 1.6.5 and 1.05, so maybe it is time to upgrade (or downgrade :o )

I once made som servocode for the ATtiny13, and changed it for the t85.

You could give it a try:

volatile unsigned int count =0;
volatile unsigned int pw =150;

void setup() {
  pinMode(3, OUTPUT);
  cli();
  TIFR = (1 << TOV0);           // clear interrupt flag table 11.9.8
  TCNT0=0;
  TCCR0B = 0;
  TCCR0A = 0;
  TCCR0A |=(1<<WGM01); //Start timer 0 in CTC mode Table 11.5 
  TIMSK |= (1 << OCIE0A); //Enable CTC interrupt see 13.3.6
  TCCR0B |= (1 << CS00) ; // Prescaler Table 11.6
  OCR0A = 1; //CTC Compare value
  sei();
}

void loop() {
  for(int x=50;x<=170;x++){
    pw=x;
    delay(50);
  }

  for(int x=170;x>=50;x--){
    pw=x;
    delay(50);
  }

}

ISR(TIMER0_COMPA_vect){
  count++;
  if (count<=pw){
    PORTB |=(1<<PB3);  //high
  }
  else{
    PORTB &= ~(1<<PB3);   // low 
  }
  if (count>=(2000-pw)){
    count=0;
  }

}

Wow, Thanks for posting that.

I tried your code and didn't see any change in the pulse length, screen shot is here:

http://postimg.org/image/8ssha8ccx/

So, I think, for whatever reason variables aren't making it between the main loop and the ISR.

I also tried the 10k from Vcc to reset and 0.1 uF from reset to ground

http://postimg.org/image/xh1o93l3z/
to no avail.

I'm out of ideas...