Go Down

Topic: Interrupts and delay() (Read 481 times) previous topic - next topic

Peppel


Hi, I recently started to to program the attiny85 using the following core from HLT:
http://highlowtech.org/?p=1695

As far as I know it does not support the tone() function so, in an attempt to make my own I created the following sketch:

Code: [Select]
void setup()
{
  pinMode(0, OUTPUT);
}

void loop()
{
  myTone(500);
  delay(1000);
  myNoTone();
  delay(1000);
}

ISR(TIMER1_COMPA_vect)
{
   PORTB ^= (1 << PORTB0);
}


void myTone(int freq)
{
  float period = 1.00/(float)freq;
  float ticks = (125000.00*(float)period)/2.00;
  int over = ticks/255;
  TCCR1 = (1 << CTC1) | (1 << CS12); // divide by 8 prescaler
 
 
  OCR1A = ticks; //
  OCR1C = ticks; //
  TIMSK = (1 << OCIE1A) | (1<<TOIE1);
 
  sei();
}

void myNoTone()
{
TCCR1 = 0;
TCNT1 = 0;
}


Everything works fine, however, when running the sketch the delays between the tones aren,t 1000ms
If someone knows why this happens, please let me know. Thanks.

Robin2


Everything works fine, however, when running the sketch the delays between the tones aren,t 1000ms
If someone knows why this happens, please let me know. Thanks.


So how long is the delay instead of the expected 1000ms?

And is it always the same length?

...R


Peppel

The delays last the same, aprox. 1/2 of a second.

When I tried with the gcc-avr _delay_ms() It worked fine

Robin2

What does this do
Code: [Select]
PORTB ^= (1 << PORTB0);

I can never get my head around that notation. Can you express the RHS as a binary value?

I'm wondering if bits are mangled in PORTB that should not be mangled.

...R

Jack Christensen

#4
Aug 04, 2014, 07:27 pm Last Edit: Aug 04, 2014, 07:33 pm by Jack Christensen Reason: 1

What does this do
Code: [Select]
PORTB ^= (1 << PORTB0);

I can never get my head around that notation. Can you express the RHS as a binary value?

I'm wondering if bits are mangled in PORTB that should not be mangled.

...R


Toggles bit zero in PORTB, i.e. PORTB = PORTB ^ 0x01;

Shouldn't mangle any other bits.

Common idiom, worth mastering.

PS: But it is not an atomic operation, so if not executed with interrupts inhibited (as it is here by virtue of being in an ISR), it could cause unintended results.
MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Peppel

PORTB is the register that stores pin outputs.
The LSB of PORTB is PORTB0 (pin 5)

PORTB =                                 00000000
(1 << PORTB0) =                     00000001
PORTB XOR (1 << PORTB0) =  00000001
It's just using a XOR mask to toggle pin 5, it has nothing to do with
timing or delays.

Robin2

#6
Aug 04, 2014, 10:05 pm Last Edit: Aug 04, 2014, 10:09 pm by Robin2 Reason: 1

Toggles bit zero in PORTB, i.e. PORTB = PORTB ^ 0x01;


This is much easier to understand and   PORTB = PORTB ^ 0b00000001; is even better.

And I guess the toggled bit is what is creating the tone.

So what is interfering with delay() ?

Can you add a little code to toggle the on board LED after every delay and ( A ) check the time against the flashing LED and ( B ) comment out the calls to myTone() and myNoTone() and see does that restore the delay() to its proper duration?

Might try it myself tomorrow.

...R

bperrybap



What does this do
Code: [Select]
PORTB ^= (1 << PORTB0);

I can never get my head around that notation. Can you express the RHS as a binary value?

I'm wondering if bits are mangled in PORTB that should not be mangled.

...R


Toggles bit zero in PORTB, i.e. PORTB = PORTB ^ 0x01;

Shouldn't mangle any other bits.

Common idiom, worth mastering.

PS: But it is not an atomic operation, so if not executed with interrupts inhibited (as it is here by virtue of being in an ISR), it could cause unintended results.


But there is a different way to toggle a pin.
You can write to the PINx register.

Code: [Select]
PINB = (1 << PORTB0);
That will Toggle the pin atomically using the PINxn h/w toggle functionality.

--- bill

Peppel

Quote
Can you add a little code to toggle the on board LED after every delay and ( A ) check the time against the flashing LED and ( B ) comment out the calls to myTone() and myNoTone() and see does that restore the delay() to its proper duration?


I connected a LED to pin 6 of the attiny (PB1) and tried the following sketch:

Code: [Select]
#include <avr/delay.h>

void setup()
{
DDRB = (1 << PORTB0) | (1 << PORTB1);
PORTB = 0;

}

void loop()
{
  myTone(500);
  PORTB ^= (1 << PORTB1);
  delay(1000);
  myNoTone();
  PORTB ^= (1 << PORTB1);
  delay(1000);
}

ISR(TIMER1_COMPA_vect)
{
   PORTB ^= (1 << PORTB0);
}


void myTone(int freq)
{
  float period = 1.00/(float)freq;
  float ticks = (125000.00*(float)period)/2.00;
  int over = ticks/255;
  TCCR1 = (1 << CTC1) | (1 << CS12); // divide by 8 prescaler
 
 
  OCR1A = ticks; //
  OCR1C = ticks; //
  TIMSK = (1 << OCIE1A) | (1<<TOIE1);
 
  sei();
}

void myNoTone()
{
TCCR1 = 0;
TCNT1 = 0;
}


the delays were still less than 1000ms, when I removed the tone functions the delays were normal.

Probably the interrupts are messing up with the delay()?

Coding Badly

As far as I know it does not support the tone() function...


This core does...
http://code.google.com/p/arduino-tiny/

Peppel


I finally solved my problem.

Because TIMSK is the only register in my sketch that affects timer1 and timer0 (delay timer) I replaced:

Code: [Select]
TIMSK = (1 << OCIE1A) | (1<<TOIE1);

with:

Code: [Select]
TIMSK |= (1 << OCIE1A) | (1<<TOIE1);

Note that OR operation.
Maybe when setting TIMSK I was also changing the timer0 settings??

Anyway, thanks to all.  :)

Robin2

That's the sort of problem I had in mind when I said
Code: [Select]
I'm wondering if bits are mangled in PORTB that should not be mangled.
I just wasn't looking in the right place.

...R

Go Up