Pages: [1]   Go Down
Author Topic: Interrupts and delay()  (Read 282 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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:
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.
Logged

UK
Offline Offline
Tesla Member
***
Karma: 135
Posts: 7657
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

UK
Offline Offline
Tesla Member
***
Karma: 135
Posts: 7657
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What does this do
Code:
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
Logged

Grand Blanc, MI, USA
Offline Offline
Faraday Member
**
Karma: 95
Posts: 4091
CODE is a mass noun and should not be used in the plural or with an indefinite article.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

What does this do
Code:
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.
« Last Edit: August 04, 2014, 12:33:02 pm by Jack Christensen » Logged

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

UK
Offline Offline
Tesla Member
***
Karma: 135
Posts: 7657
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
« Last Edit: August 04, 2014, 03:09:43 pm by Robin2 » Logged

Dallas, TX USA
Offline Offline
Faraday Member
**
Karma: 70
Posts: 2738
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What does this do
Code:
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:
PINB = (1 << PORTB0);
That will Toggle the pin atomically using the PINxn h/w toggle functionality.

--- bill
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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()?
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 209
Posts: 13024
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


I finally solved my problem.

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

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

with:

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

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

Anyway, thanks to all.  smiley
Logged

UK
Offline Offline
Tesla Member
***
Karma: 135
Posts: 7657
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

...R
Logged

Pages: [1]   Go Up
Jump to: