Setting up multiple timers with AVR - c

I am trying to set up two timer interrupt routines with Teensy 2.0 Microcontroller (which is based on ATMEGA32U4 8 bit AVR 16 MHz) for independent control of two servo motors
After much trial - I was able to set one up on pin 7 of port C, but
How do I set up the second ISR to be initialized and called independently of the first?
Do I need to setup the second timer and, if so, what would such code look like?
Here is the setup code:
int main(void)
{
DDRE = 0xFF;
TCCR1A |= 1 << WGM12; // Configure timer 1 for CTC mode
TCCR1B = (1<<WGM12) | (1<<CS11) ;
OCR1A = 1000; // initial
TIMSK1 |= 1 << OCIE1A; // Output Compare A Match Interrupt Enable
sei(); // enable interrupts
// ...code that sets pulseWidth based on app logic variable.
// Not showing as its not important
}
ISR(TIMER1_COMPA_vect)
{
if (0 == pulseWidth)
{
return;
}
static uint8_t state = 0;
int dutyTotal = 20*1000;
if (0 == state)
{
PORTC |= 0b10000000;
OCR1A = pulseWidth;
state = 1;
}
else if (1 == state)
{
PORTC &= 0b01111111;
OCR1A = dutyTotal - pulseWidth;
state = 0;
}
}

While it's difficult to give a definitive answer without knowing more about your application (e.g. what kind of servo/motor, - I'm guessing model RC type with 1-2ms pule?) there are two approaches to solving the problem:
Firstly, In your code you seem to be manually generating a PWM signal by toggling PC7. You could add another output by increasing your number of states - you need one more than the number of servos to give the gap which sets the pulse repetition frequency. This is a common technique when you need to drive a lot of servos, since most RC servos don't care about pulse phasing or frequency (within limits), only the pulse width, so you can generate a bunch of different pulses one after the other on different outputs while only using one timer like this (in a sort of pseudo-code state diagram):
State 0:
Turn on output 1
Set timer TOP to pulse duration 1.
Go to state 1:
State 1:
Turn off output 1
Turn on output 2
Set timer TOP to pulse duration 1.
Go to state 2:
State 2:
Turn off output 2
Set timer TOP to pulse duration 3.
Go to state 0:
"Pulse duration 3" sets the PRF (pulse repetition frequency). If you want get fancy,
you can set this to 1/f-pd1-pd2, to give a constant frequency.
[ "TOP" is AVR-speak for the thing that sets the wrap (overflow) rate of the timer. See data sheet. ]
Secondly, there is a much easier way if you're only using two servos - use the hardware PWM functionality of the timer. The AVR timers have a built-in PWM function to do the pin-toggling for you. Timer1 on the mega32 has two PWM output pins, which could work great for your two servos and you then don't (necessarily) need an interrupt handler at all.
This is also the right solution if you are PWM driving motors directly (e.g. through an H-Bridge.)
To do this, you need to put the timer into PWM mode and enable the OC1A and OC1B output pins, e.g.
/*
* Set fast PWM mode on OC1A and OC1B with ICR1 as TOP
* (Mode 14)
*/
TCCR1A = (1 << WGM11) | (1 << COM1B1) | (1 << COM1A1);
TCCR1B = (3 << WGM12);
/*
* Clock source internal, pre-scale by 8
* (i.e. count rate = 2MHz for 16MHz crystal)
*/
TCCR1B |= (1 << CS11);
/*
* Set counter TOP value to set pulse repetition frequency.
* E.g. 50Hz (good for RC servos):
* 2e6/50 = 40000. N.B. This must be less than 65535.
* We count from t down to 0 so subtract 1 for true freq.
*/
ICR1 = 40000-1;
/* Enable OC1A and OC1B PWM output */
DDRB |= (1 << PB5) | (1 << PB6);
/* Uncomment to enable TIMER1_OVF_vect interrupts at 50Hz */
/* TIMSK1 = (1 << TOV1); */
/*
* Set both servos to centre (1.5ms pulse).
* Value for OCR1x is 2000 per ms then subtract one.
*/
OCR1A = 3000-1;
OCR1B = 3000-1;
Disclaimer - this code fragment compiles but I have not checked it on an actual device so you may need to double-check the register values. See the full datasheet at http://www.atmel.com/Images/doc7766.pdf
Also, you perhaps have some typos in your code, bit WGM12 doesn't exist in TCC1A (you've actually set bit 3, which is FOC1A - "force compare", see datasheet.) Also, you are writing DDRE to enable outputs on port E but toggling a pin on port C.

Halzephron, thank you so much for your answer. I dont have the high enough reputation to mark your answer, hopefully someone else will.
Details below:
You are absolutely right about being able to use a single IRS to control a number of servos - embarrassing I did not think of that, but given how well your simpler solution worked - I'll just use that.
... Also, you are writing DDRE to enable outputs on port E but toggling a pin on port C.
Thanks, I commented out that line, and it works the same - (so I dont need to enable output at all?)
Bit WGM12 doesn't exist in TCC1A (you've actually set bit 3, which is FOC1A - "force compare", see datasheet.)
I removed that too, but leaving the rest of my code unchanged - it results in servos moving slower, with way less torque and jittering as they do, even after arriving at desired position. Servo makes a weird "shaky" noise (frequency ~10-20, I'd say) and the arm it trembling, so for the reasons I don't understand - setting this bit seems necessary.
I suspected that a timer per motor is highly inelegant, and so I really like your second approach (built - in timer-generated PWM),
... This is also the right solution if you are PWM driving motors directly (e.g. through an H-Bridge.)
Very curious, why? I.e. what's the difference between using this method vs, say, timer-generated PWM.
In your code, I had to change below line to get 50HZ, otherwise I was getting 25HZ before (verified with a scope)
ICR1 = 20000-1; // was 40000 - 1;
One other thing I noticed with scope was that the timer-generated PWM code I have - produces less "rectangular" shape than the PWM code snippet you attached. It takes about 0.5 milliseconds for the signal to drop off to 0 with my code, and its absolutely instantaneous with yours (which is great). This solved another problem I had been bashing my head against: I could get analog servos to work fine with my code (IRS-generated PWM), but any digital servo I tried - just did not move, as if it was broken. I guess the shape of the signal is critical for digital servos, I never read this anywhere. Or maybe its something else I dont know.
As a side note, another weirdness I spent a bunch of time on - I uncommented the TIMSK1 = (1 << TOV1); line, thinking I always needed it - but what happened, my main function would get frozen, blocked forever upon first call to delay_ms(...) not sure what it is - but keeping it commented out unblocks my main loop (where I read the servo positin values from the USB HID using Teensy's sample code)
Again, many thanks for the help.

Related

STM32F0 - Multiple interrupts from one Timer?

I'm trying to figure out if there is a way of using any of the timers to generate interrupts at more than one delay time.
E.G. I want to be able to start a timer, then have it cause interrupts at say 20us, 50us, 100us, 300us.
I can see that its perfectly possibly (and easy) to have timers cause an interrupt when the end of the count has elapsed (using HAL) but having trouble working out if I can do what I want using only one timer.
I notice some timers are 4 channel but not sure if they can be set as required.
I guess my fall back is to use one timer for each (but ideally I would like to keep other timers in case they are needed for other tasks).
I've read the docs but having trouble understanding if the device can be configured as I want it to.
The easiest way - is to change the timer period (write a different value to the ARR register, use __HAL_TIM_SET_AUTORELOAD macro if you prefer HAL) in each interrupt. This way every other period could be different.
Just keep in mind ARR buffering, or Auto-reload preload, see ARPE bit decription in TIMx_CR1. if it is enabled - the new value of ARR will be taken in account only after the next update event.
You can have more than one interrupt generated during one cycle. You need to use output compare registers and enable their interrupts.
In the timer interrupt handler routine you will need to check what has triggered the interrupt.
There are multiple ways you can achieve it. One a little blunt and simple, another one slightly more complicated, but once set up, very effective and quick to process.
Approach number 1, a little limited, but also a little simpler: use capture/compare (in this case, compare specifically) to trigger an interrupt. Since timers have up to 4 capture/compare values, you can have up to 4 interrupts. You will have to check which exactly interrupt fired tho in the handler. Which specifically compare value, I mean.
Approach number 2, more flexible, more precise, but a bit more hassle to set up: master-slave timers. You can have one timer (including basic) be the clock source for the other timers ("tick" on the rising edge of master slave setting). For example, master timer ticks at 10kHz, and its slave timer uses its output as a clock source and ticks to, say, 50. Or 100. You can have multiple slaves. Depending on what timer's interrupt fires, you know right away how much time exactly passed, no need to check values in compare register or anything.
Mixed method: slave timers can have capture/compare too by the way, if you're into that. You can create huge timer chains if you want to.
You have a dozen timers in your MCU, you can probably spare 1 or 2 more for this purpose. Once you get it working, should make your life very easy.
This is how I set up a timer that is a slave, but also a master to another timer. TMR is TIM3 with TIM1 as a master:
/*
* CR1 reset value = 0x00000000
* ARR is not buffered
* upcounter (default)
* update request source: only overflow/underflow
*
* */
TMR->CR1 = 0x00; //reset
TMR->CR1 |= TIM_CR1_URS;
/*
* 108MHz Clock, 64000 prescaler -> 2kHz Timer Clock
* Reload value 6, Period = 6/2000s = 3ms
* */
TMR->PSC = (108000U / 2U) - 1U; //APB1 is 54MHz, timer is 2x APB1 Freq, so now the timer is at 2kHz; 16-bit value!!! 65535 max!
TMR->ARR = 6U - 1U; //6 ticks at 2kHz is 3ms
TMR->CNT = 0x00; //start value
TMR->EGR |= TIM_EGR_UG; //force update event and load all values into registers
TMR->SR &= ~TIM_SR_UIF; //force clear update event
/*
* SMCR Slave Mode Control Register reset value = 0x00000000
* Trigger Selection - ITR0 (TIM1 as Master for TIM3)
* Slave Mode Selection - Trigger Mode - The counter starts at a rising edge of the trigger TRGI (but it is not
* reset). Only the start of the counter is controlled (0b0110)
*/
TMR->SMCR = 0x00; //reset
TMR->SMCR |= (0x00 << TIM_SMCR_TS_Pos) | (0x00 << 16U) | (0x06 << TIM_SMCR_SMS_Pos);
/*
* CR2 reset value = 0x00000000
* Master Mode Selection 1: OC1REF Triggers TRGO to start another timer
* Master Mode Selection 2: reset
* Compare value: 4 (output LOW: CNT = 0, 1, 2, 3; output HIGH CNT = 4, 5)
* Duty cycle: 33.33%
* Output compare 1 mode - PWM mode 2 (0b0111)
*
* */
TMR->CR2 = 0x00; //reset
TMR->CR2 |= (0x04 << TIM_CR2_MMS_Pos); //OC1REF as TRGO
TMR->CCR1 = 4U;
TMR->CCMR1 = 0x00;
TMR->CCMR1 |= (0x07 << TIM_CCMR1_OC1M_Pos);
/*
* Capture Compare Enable Register
* Polarity: default - active high
* Capture Compare Output Enable
* */
TMR->CCER = 0x00; //reset
TMR->CCER |= TIM_CCER_CC1E;
The rest of my example/training project, including screenshots of waveform, are here: Github Chained Timers Demo. There you will find TIM1 to be the master, TIM3 its slave and the master of TIM5, and so on. Timers are connected in different master-slave modes.

speed up the AVR ISR

I am wondering if it is possible to speed up the ISR without changing the prescaler.
I have a timer with 2 compare registers A and B.
COMPA is used for a PWM output from around 22% up to 100%. This has a fixed frequency and I am not allowed to change it at least not much.
Now I would like to use the COMPB with around 4 times the speed but with a fixed duty cycle of 50%.
If I set the OCIE0B bit in TIMSK0 for the attiny13 can I do the following to speed things up?
Or am I misunderstanding something here?
ISR(TIM0_COMPB_vect){
switch (timing){
case 0:
OCR0B = 63;
PORTB ^= (1 << PB3);
timing = 1;
break;
case 1:
OCR0B = 127;
PORTB ^= (1 << PB3);
timing = 2;
break;
case 2:
OCR0B = 191;
PORTB ^= (1 << PB3);
timing = 3;
break;
case 3:
OCR0B = 255;
PORTB ^= (1 << PB3);
timing = 0;
break;
}
}
Any help appreciated.
Thanx :D
You can do this very efficiently by creatively using the Normal Mode.
The trick is to set the prescaller to get a clock period that is double what you want the variable-duty PWM signal to run at. So if, for example, you want that to PWM at 1Mhz, set the prescaller to 2Mhz.
Assume the variable duty cycle PWM is on pin A and the fixed 50% 4x clock signal is on pin B. (You can also swap these and and also update the code everything will still work)
Enable interrupts for "On compare match B" and "Overflow".
Force pin A high with a force compare match. (Alternately you can skip this step and instead use the inverse of the desired duty cycle in step 7)
Set the COM bits for 'A' to Toggle on match.
Leave the COM bits for B to off. Assumes you have DDR set for this pin to be normal GPIO.
Set the OCR for B to 128.
Set the WGM timer mode to 0 - "Normal Mode".
Set the OCR for A whatever you want the variable duty cycle to be. Note that you might need to special case here for extreme values of 0 and/or 255 depending on what you want to have happen (just turn the pin ON of OFF with GPIO).
You can repeat step 6 anytime you want to change the duty cycle of A and it will update on the next TOP.
Once you do these steps, the A pin will output the desired duty cycle at 1/2 the prescaller clock and the B will output 50% duty at 2x the prescaller clock (which is the desired 4x of the A period).
Here is the ISR code (note that I am not sure what the TOV vector is called in the attiny13 headers [it is sometimes different across AVRs] so you might have to edit the TIM0_OVF_vect name)...
ISR(TIM0_COMPB_vect,TIM0_OVF_vect){
PINB |= (1 << PB3); // Compiles to a single cycle SBI
}
See how this works?
Note that setting a bit in the PIN register actually toggles the PORT bit. This is a quirk of the AVR GPIOs that is documented in the datasheets.
Hopefully this is fast enough. If you really want to squeeze every last cycle out, you can even potentially save the 2 cycles of the RJMP from the interrupt vector by putting the single SBI instruction that the ISR compiles down to directly into the interrupt vector table with a trailing RETI, but this is more complicated!
Focusing solely on the C code aspects, then this can be trivially optimized as:
ISR(TIM0_COMPB_vect)
{
static const uint8_t OCR[4] = {63,127,191,255};
OCR0B = OCR[timing];
PORTB ^= 1u << PB3;
timing++;
if(timing==4)
timing=0;
}
Disassembled on gcc AVR -O3 (with all variables/registers volatile) this brings down the amount of instructions from ~50 to ~20, so it's about twice as fast and takes less memory.
If you just want the fastest equivalent version of the supplied code, then here it is...
ISR(TIM0_COMPB_vect){
OCR0B += 64;
PINB |= (1 << PB3);
}
OCR0B will overflow every 4 passes, which is defined behavior. Probably wise to initialize OCR0B to some non-zero number like 1 to avoid edge cases.
This avoids all variables and memory access - only register access.
Avoids all compares and braches.
The PINB method of toggling the pin compiles down to a single SBI instruction rather than a PUSH, load, XOR, store, POP sequence.
...but again, none of this matters if it does not work and unless you are using one of the two "immediate OCR update" modes, then updating OCR in the middle of a timer cycle will have no effect.

Erroneous Pulsetrain Timing

I am having some trouble with a timer on my Arduino atmega328p-pu with 16MHz clock.
I have a really simply program with only one timer, two ISRs, and one pin.
The program does the following:
Iterates through the bits of 'sequence' and sets pin4 high or low respectively. However it doesnt set the bit high for the entire period, only 1/12 of it. What you see below is a single timer that counts up from 0 to 340. There is ISRB at 28, and then ISRA happens at 340, then it loops (that is what CTC mode does, loops after ISRA). ISRB always turns off the pin, and ISRA handles whether or not the pin should be high.
Now then the problem. All the timing works for each bit, but for some reason the loopover event causes the pulse spacing to SHORTEN. Yes shorten, not widen (which if anything was what I would expect because of extra clock cycles for executing the loop event).
it makes waveforms that look like this.
_|_|_|_|_ _ _ _ _|_|_|_||_|_|_|_ _ _ _
You can see that the problem resides in the junction between two packets, but the rest of the timing is good. I cant seem to track down why.
#include <stdint.h>
uint32_t sequence =0b111100001111; // example data sequence
uint8_t packetlength = 12;
uint8_t index = 0;
void setup(){
DDRD = 0xFF; // all port D as input
bitSet(DDRD, 4); // board pin 4 output
bitSet(PORTD, 4); // start high
// initialize timer1
TCCR1A = 0; // zeros timer control register
TCCR1B = 0;
TCNT1 = 0; // sets timer counter to 0
OCR1A = 340; // compare match register 340*62.5ns = 21.25us
OCR1B = 28; // 28*62.5ns = 1.75us
TIMSK1 = 0;
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS10); // CS10 no prescaler (use CS12 for 256 prescaler for testing)
TIMSK1 |= (1 << OCIE1A); // enable timer compare A interrupt
TIMSK1 |= (1 << OCIE1B); // enable timer compare B interrupt
}
ISR(TIMER1_COMPA_vect){ // controls bit repeat rate
if (bitRead(sequence,index) == 1){
bitSet(PORTD, 4); //set high
}
index ++;
if (index == packetlength){ //loop over when end reached.
index = 0;
}
}
ISR(TIMER1_COMPB_vect){ // controls duty cycle
bitClear(PORTD, 4); // set low
}
void loop(){
//nothing
}
Edit: April 5. Scope photos demonstrating inter pulsetrain period shortening.
The important measurement value is BX-AX
Normal. 340 + 6 calculation clock cycles (best estimate from scope)
Bad. Timer only counting 284 cycles before interrupt is firing.
Also Bad, but not a huge problem. This pulse is far to wide to be reasonably explained by the clock cycles needed set the bit low. It appears to take 17, I would expect 3.
I do not see why you should expect precise timing at the bit output. Interrupts begin after a delay once requested which will vary depending on instruction execution time for each instruction being run in whatever is being interrupted. I suspect (without seeing evidence in your report of the problem) that the variation you see is identical to instruction execution time variation.
If you want precise hardware output timing, you must either use never-interrupted programmed I/O or use the various flip-bit-upon-timer-compare features of the uP's hardware peripheral set. The ISR can be used to set things up for the next compare, but not to directly flip output bits.
Once you've figured out how to setup the action to be performed by the hardware upon comparitor matches, it will be simpler to do it all in a single ISR. That service routine can arrange for both the conditional bit set and the following unconditional bit clear. You probably want the ISR to run during the lengthier part of the cycle so that latency in the actual running of your [a] ISR code does not cause the setup to be too late.
[a. In addition to your ISR code, the programming environment is causing some context save a restore to wrap what you wrote. This can add execution cycles that might not be expected. Auto-generated context save/restore often is extravagant about tucking away state so that naive programmers are not puzzled by strange foreground-background interactions. ]

How to get millisecond resolution from DS3231 RTC

How to get accurate milliseconds?
I need to calculate the delay of sending data from Arduino A to Arduino B. I tried to use DS3231 but I cannot get milliseconds. What should I do to get accurate milliseconds from DS3231?
The comment above is correct, but using millis() when you have a dedicated realtime clock makes no sense. I'll provide you with better instructions.
First thing in any hardware interfacing project is a close reading of the datasheet. The DS3231 datasheeet reveals that there are five possible frequencies of sub-second outputs (see page 13):
32 KHz
1 KHz
1.024 KHz
4.096 KHz
8.192 KHz
These last four options are achieved by various combinations of the RS1 and RS2 control bits.
So, for example, to get exact milliseconds, you'd target option 2, 1KHz. You set RS1 = 0 and RS2 = 0 (see page 13 of the datasheet you provided) and INTCN = 0 (page 9). Then you'd need an ISR to capture interrupts from the !INT/SQW pin of the device to a digital input pin on your Arduino.
volatile uint16_t milliseconds; // volatile important here since we're changing this variable inside an interrupt service routine:
ISR(INT0_vect) // or whatever pin/interrupt you choose
{
++milliseconds;
if(milliseconds == 999) // roll over to zero
milliseconds = 0;
}
OR:
const int RTCpin = 3; // use any digital pin you need.
void setup()
{
pinmode(RTCpin, INPUT);
// Global Enable INT0 interrupt
GICR |= ( 1 < < INT0);
// Signal change triggers interrupt
MCUCR |= ( 1 << ISC00);
MCUCR |= ( 0 << ISC01);
}
If these commands in setup() don't work on your Arduino, google 'Arduino external interrupt INT0'. I've shown you two ways, one with Arduino code and one in C.
Once you have this ISR working and pin3 of the DS3231 connected to a digital input pin of your choosing, that pin will be activated at 1KHz, or every millisecond. Perfect!
// down in main program now you have access to milliseconds, you might want to start off by setting:
// When 1-second RTC changes seconds:
milliseconds = 0; // So you can measure milliseconds since last second.
That's all there is to it. All you need to learn now is how to set the command register using I2C commands and you're all set.
The C code example gains 1ms every second. Should be:
{
if (milliseconds == 999) // roll over to zero
milliseconds = 0;
else
++milliseconds;
}

How to control a motor with atmega 32 pwm

I have been for some time on how to control a motor (control its speed) with fast pwm mode with my atmega32. I need to use the 8-bit Timer0, because i have other uses for the other counters. I think I know how to inialise the timer for this task:
void initial_io (void){
DDRC = 0xFF;
DDRB = 0xFF;
PORTA = (1<<PA4)|(1<<PA5);
TCCR0 = (1<<WGM01)|(1<<WGM00); // PWM mode : Fast PWM.
TCCR0 = (1<<CS02)|(1<<CS00); // PWM clock = CPU_Clock/1024
}
But then comes the problem. I simply don't know what to do next, what to do on my main.
My exact project is to drive a remote controlled car with acceleration. So when I ask from the car to go forward it must accelerate from stop to maximum speed whith fixed acceleration. I don't know any Assembly, so if you can help me please do it in C. Any help will be much appreciated.
Well, I guess you're okay with all port B and C pins being outputs. Also, you shouldn't need to do anything in assembly on AVR. The assembly-only stuff is available as macros in avr-libc.
Setup
First off, you're setting up TCCR0 wrong. You have to set all the bits at once, or you have to use a read-modify-write operation (usually TCCR0 |= _BV(bit_num); to set a bit or TCCR0 &= ~_BV(bit_num); to clear it). (_BV(N) is an avr-libc macro that's more legible than the (1<<N) stuff you're using, but does the same thing.) Also, you're missing the polarity of your PWM output, set by the COM00 and COM01 bits. Right now you have them (implicitly) disabled PWM output (OC0 disconnected).
So I'm going to assume you want a positive-going PWM, i.e. larger PWM input values result in larger high-output duty cycles. This means COM01 needs to be set and COM00 needs to be cleared. (See pp. 80-81 of the ATmega32(L) data sheet.) This results in the setup line:
TCCR0 = _BV(WGM01) | _BV(WGM00) // PWM mode: Fast PWM.
| _BV(COM01) // PWM polarity: active high
| _BV(CS02) | _BV(CS00); // PWM clock: CPU_Clock / 1024
Duty Cycle
Now we get to the actual duty cycle generation. Timer 0 is pretty stupid, and hard wires its BOTTOM to 0 and TOP to 0xFF. This means that each PWM period is PWM_Clock / 256, and since you set PWM_Clock to CPU_Clock / 1024, the period is CPU_Clock / 262144, which is about 33 ms for an 8 MHz CPU clock. So each PWM clock, this counter counts up from 0 to 255, then loops back to 0 and repeats.
The actual PWM is generated by the OC circuit per Table 40. For the COM0* setting we have, it says:
Clear OC0 on compare match, set OC0 at BOTTOM
What this means is that each time the counter counts up, it compares the count value to the OCR0 register, and if they match it drives the OC0 output pin to GND. When the counter wraps around to 0, it drives the pin to VCC.
So to set the duty cycle, you just write a value corresponding to that duty cycle into OCR0:
OCR0 = 0; // 0% duty cycle: always GND.
OCR0 = 64; // 25% duty cycle
OCR0 = 128; // 50% duty cycle
OCR0 = 172; // 67% duty cycle
OCR0 = 255; // 100% duty cycle; always VCC. See below.
That last case is there to resolve a common problem with PWM: the number of possible duty cycle settings is always one more than the number of count steps. In this case, there are 256 steps, and if the output could be VCC for 0, 1, 2, … 256 of those steps, that gives 257 options. So rather than prevent either the 0% or 100% case, they make the one-shy-of-100% case disappear. Note 1 on Table 40 says:
A special case occurs when OCR0 equals TOP and COM01 is set. In this case, the compare match is ignored, but the set or clear is done at BOTTOM.
One more thing: if you write to OCR0 in the middle of a PWM cycle, it just waits until the next cycle.
Simulating Acceleration
Now to get the "constant acceleration" you want, you need to have some kind of standard time base. The TOV0 (timer 0 overflow) interrupt might work, or you could use another of the timers or some kind of external reference. You'll use this standard time base to know when to update OCR0.
Constant acceleration just means that the speed changes linearly with time. Taking this a step further, it means that for each update event, you need to change the speed by a constant amount. This is probably nothing more than saturation arithmetic:
#define kAccelStep 4
void accelerate_step() {
uint8_t x = OCR0;
if(x < (255 - kAccelStep))
OCR0 = x + kAccelStep;
else
OCR0 = 255;
}
Just do something like this for each time step and you'll get constant acceleration. A similar algorithm can be used for deceleration, and you could even use fancier algorithms to simulate nonlinear functions or to compensate for the fact that the motor does not instantly go to the PWM-specified speed.
As you seem to be a beginner on AVR programming, I suggest you go the easy way: start with Arduino.
The Arduino environment offers simple functions so you don't need to manipulate the processor registers directly. For instance, to control a PWM output, you simply have to call analogWrite() (documentation here)
Here is a tutorial to hook up a motor to an Arduino.
Here is a tutorial to program a ATMega32 from Arduino IDE

Resources