Go Down

Topic: Help setting up fast PWM by registers (solved) (Read 1 time) previous topic - next topic

loggerin

Apr 20, 2011, 05:47 am Last Edit: Apr 20, 2011, 08:04 am by loggerin Reason: 1
   I've been trying to set up my own PWM code for better timings and to learn about the hardware under Arduino but i can't seem to get it to work. I've read the section of the manual about timers and PWM so many times i could probably recite it from memory and have all the timers are working fine but PWM output just refuses to work. I'm trying to set up fast PWM and (for now) dim the LED on pin 13 (timer0) though I would rather it have it on timer2. I've been staring at the code for three days now and tried every combination of bits i could think of but nothing i try works, so i believe I'm missing something vital somewhere.

If someone could please look at my code and point out what I'm doing wrong i would be grateful. You would probably prevent me from going prematurely bald as well.
Code: [Select]

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


//////////
// constants
///////////////////
 #define PWM_OUT  OCR0A
 #define pin_out  13


//////////
// global variables
///////////////////
 // hold current value of PWM_OUT
 byte DUTY = 0;


//////////
// arduino setup
///////////////////
 void setup() {
   // setup interupt/pwm code
     // enable pwm pin
     pinMode(pin_out, OUTPUT);

     // set fast pwm mode, clear on match
     //TCCR0A = 0b10000011;
     //TCCR0B = 0b00001100;
     TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00);
     TCCR0B = _BV(WGM02);
   
     // set timer0 prescaler to 64
     // 1/ (16000000 / 64) = 1/250000
     TCCR0B |= _BV(CS02);

     // Timer0 match A Interrupt Enable
     TIMSK0 = _BV(OCIE0A);
     
     // turn on global interupts
     sei();
     
     // set initial value of OCR0A(TOP)
     DUTY = 50;
     PWM_OUT = DUTY;
     
   // setup testing
   Serial.begin(9600);
 }

//////////
// arduino main loop
///////////////////
 void loop(){
   //PWM_OUT = DUTY;
   //delay(100);
   //DUTY++;
 }


//////////
// interupt code
///////////////////
 ISR(TIMER0_COMPA_vect) {
   Serial.println("hi");
 }

Coding Badly


Do you have an ATmega328 or ATmega168 based board?

Quote
I'm trying to set up fast PWM and (for now) dim the LED on pin 13 (timer0)


Timer 0 is already set to Fast PWM.  Pin 13 is not capable of PWM.

loggerin

#2
Apr 20, 2011, 06:42 am Last Edit: Apr 20, 2011, 06:45 am by loggerin Reason: 1
I'm have an older Arduino mega running a 1280.

For the mega you can run PWM on pin 13(its mapped to pin 26 on the atmega). It describes it in the documentation and I tested it with an analogWrite. I should be able to run PWM on pins 2-13.

Just in case I moved everything to timer2(pin 10) and it still doesn't work. Testing it with a voltmeter it reads the same voltage for a duty of 0 and 255.

Coding Badly

Quote
void setup() {
   // setup interupt/pwm code
     // enable pwm pin
     pinMode(pin_out, OUTPUT);

     // set fast pwm mode, clear on match
     //TCCR0A = 0b10000011;
     //TCCR0B = 0b00001100;
     TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00);
     TCCR0B = 0;  // Start with mode 3.  Mode 7 is not orthogonal.
   
     // set timer0 prescaler to 64 256
     // 1/ (16000000 / 64 256) = 1/250000
     TCCR0B |= _BV(CS02);

     // Timer0 match A Interrupt Enable
     TIMSK0 = 0;  // Once you have a PWM output then add interrupts to the mix.
     
     // turn on global interupts
     // sei();  // This line of code is useless.  Remove it.
     
     // set initial value of OCR0A(TOP)
     DUTY = 50;
     PWM_OUT = DUTY;
     
   // setup testing
   Serial.begin(9600);
 }

loggerin

Thank you, I have something to build on that actually works now. By far better than a cobbled together script from who knows how many tutorials I read and a semi incomprehensible manual.

Coding Badly


Go Up