/*
=== Fast PWM on OC0A (PB0): ===
1. Set Timer0 to Fast PWM
2. Enable output on OC0A (PB0)
3. Control brightness (or motor control) with OCR0A
8000000 = F_CPU
8 = prescaler
256 = 8-bit counter
PWM freq. = 8000000 / (8 * 256) = 3906.25 Hz
=== What's Going On ===
1. Fast PWM Mode: Timer0 counts 0 → 255 repeatedly.
2. OCR0A & OCR0B:
a. When TCNT0 == OCR0x, the corresponding pin transitions.
b. In non-inverting mode, pin is cleared on match, set at bottom (0).
3. Duty cycle = OCR0x / 255
If OCR0A is 200:
Duty cycle = (200 / 255) x 100 = 78.43%
*/
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <TinyDebug.h>
// Motor connected to PB1 (OC0B)
#define MOTOR_PIN PB1 // OC0B
void pwm_init(void) {
DDRB |= (1 << MOTOR_PIN); // Set PB1 (OC0B) as output
// === Timer0 Setup: Fast PWM, Non-inverting mode on OC0A ===
// Clear OC0B on compare match, set at BOTTOM (non-inverting mode)
TCCR0A |= (1 << COM0B1); // Non-inverting PWM on OC0B (PB1)
// WGM01 + WGM00 = Mode 3 → Fast PWM mode
TCCR0A |= (1 << WGM00) | (1 << WGM01); // Fast PWM mode (Mode 3)
// Set prescaler to clk/64 → PWM freq = 8MHz / (256 * 64) ≈ 488 Hz
TCCR0B |= (1 << CS01) | (1 << CS00);
// Start with motor off
OCR0B = 0;
}
int main(void) {
pwm_init();
// Sweep motor speed up and down
while (1) {
OCR0B = 1;
_delay_ms(1000);
OCR0B = 254;
_delay_ms(1000);
/*
// Speed up
for (uint8_t speed = 0; speed <= 255; speed++) {
OCR0B = speed;
_delay_ms(10);
}
// Slow down
for (uint8_t speed = 255; speed > 0; speed--) {
OCR0B = speed;
_delay_ms(10);
}
*/
}
}