Arduino Stack Exchange is a question and answer site for developers of open-source hardware and software that is compatible with Arduino. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

still pretty new to AVR programming, I don't really understand what's going wrong here, and I don't know really how to solve it...

The Concept:

Play a sine wav saved as a char array in PROGMEM through a 8bit DAC connected to PORTC pins on the arduino mega.

This Works:

//file just defines an array and a size 
#include "sine440.h"
int i = 0;
void setup() {
  DDRC = B11111111;  
}

void loop() {
  PORTC = pgm_read_byte(&sine[i++]);
  if(i >= sine_size){
    i = i - sine_size;
  }

  delayMicroseconds(60);
}

The above code produces a sine wav of about 440hz, exactly what I wanted. Now, I'd like to move this into an interrupt routine, as follows:

This Doesn't Work

#include "sine440.h"
int i = 0;
void setup() {
  DDRC = B11111111;
  TCCR5B = (1 << WGM52) | (1 << CS50 );
  OCR5A =  16000000/16000;
  TIMSK5 = (1 << OCIE5A);
}

ISR(TIMER5_COMPA_vect){
  PORTC = pgm_read_byte(&sine[i++]);
  if(i >= sine_size){
    i = i - sine_size;
  }
}

void loop() {

}

The above code produces a sine wave of 1721hz. I know that this means it's iterating through the array too fast, but I don't know how to change it. In order for it to produce 440hz, it needs to be preforming 16000 iterations per second, which is what I believe OCR5A = 16000000/16000; does. BUT it doesn't appear that changing the value of OCR5A does anything at all. Giving it the max value of 65,535 still produces 1721hz sine wav...

So what am I doing wrong here? How do I change the speed of this timer interrupt?

share|improve this question
3  
Try setting TCCR5A = 0 explicitly, maybe arduino has WGM51 or WGM50 set at startup for some reason. – BrettAM Jun 11 at 23:34
up vote 2 down vote accepted

I second BrettAM's comment. The Arduino IDE sets most of all the timers up for PWM, I had to comment out a section once to use my own ISR with Timer 3 on a 32u4 because no matter where or how I set it the CTC interrupt never went. The WGM50 and CS51 are set at the start of the Arduino files basically, so that messes with you settings.

What you will need to do is go into the Arduino core files. This is $install_path/arduino-1.x.x/hardware/arduino/avr/cores/arduino/ under that directory you need to find wiring.c thus file contains all the set up of the timers for PWM and the millis() or micros().

Go to line 342, located there is this:

#if defined(TCCR5B) && defined(CS51) && defined(WGM50)

  sbi(TCCR5B, CS51);           //set ter 5 prescale factor to 64
  sbi(TCCR5B, CS50);
  sbi(TCCR5A, WGM50);         // put timer 5 in 8-bit phase correct pwm mode

#endif

What you can do here is place another #if defined() macro around this resulting in:

#if !defined(doNotSetTimer5)
  #if defined(TCCR5B) && defined(CS51) && defined(WGM50)

    sbi(TCCR5B, CS51);           //set ter 5 prescale factor to 64
    sbi(TCCR5B, CS50);
    sbi(TCCR5A, WGM50);         // put timer 5 in 8-bit phase correct pwm mode

  #endif
#endif

Now when you want to use your custom settings, you will put the following at the top of your ino file:

#define doNotSetTimer5
#include <wiring.c>

That does not block the Arduino environment from setting up Timer 5 when compiled with other code but only when you want to use custom settings(changed because of @Gerbens suggestion). When you change these settings you will loose PWM on 3 pins: 44 45 46. But be able to make use of setting your own PWM up or a CTC ISR().

This doesn't mess anything else and is the easiest way to do it.

share|improve this answer
1  
Wouldn't it be better to use a !defined(...), as to not break existing code? Something like #if !defined(doNotSetTimer5). That way you need to set the flag only if you want the no-standard settings. – Gerben Jun 12 at 14:04
    
@Gerben that's a good point, I will change it to that rather then. Will be more compatible with stuff. +1 – RSM Jun 12 at 15:42
    
Hey, thanks. I actually found a thread yesterday before seeing BretAm's comment that addressed this issue with a different timer. So i tried it out and it worked. But this did a great job in explaining WHY it was happening. – Dave Jun 12 at 20:50
    
@Dave pleasure, maybe just add that link as a comment here or something to have another way too. – RSM Jun 13 at 6:15

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.