#include #include #include #define F_CPU 9600000UL // 9.6 MHz #include #define PWM PB0 #define TX PB2 /* * Do all the startup-time peripheral initializations. */ static void init(void) { //IO DDRB = _BV(PWM)|_BV(TX); //PWM output and serial TX PORTB |= _BV(TX); //Timer in Fast PWM mode TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00); TCCR0B = _BV(CS01); //PWM base frequency is 4.7KHz //ADC ADMUX = _BV(MUX1); ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1); } /* * Software UART half bit delay routine */ void uart_delay() { _delay_us(52); //52us 19200 baud } void putchar(uint8_t c) { //start bit PORTB &= ~_BV(TX); uart_delay(); //clock out data uint8_t i; for (i=0; i<8; i++) { if (c & 0x1) PORTB |= _BV(TX); else PORTB &= ~_BV(TX); c = c>>1; uart_delay(); } //stop PORTB |= _BV(TX); uart_delay(); } uint16_t sample() { ADCSRA |= _BV(ADSC); //start conversion loop_until_bit_is_set(ADCSRA, ADSC); uint16_t result = ADC; return result; } void main(void) { init(); uint8_t setpoint = 20; //initial duty cycle OCR0A = 0; while (1) { //run the motor _delay_ms(10); //turn off the PWM TCCR0A &= ~_BV(COM0A1); PORTB &= ~_BV(PWM); //wait for things to settle _delay_ms(1); //take a sample average uint8_t value = (sample()>>2); value += (sample()>>2); _delay_us(10); value += (sample()>>2); _delay_us(10); value += (sample()>>2); _delay_us(10); value += (sample()>>2); value = value>>2; putchar(value); int8_t error = value-setpoint; OCR0A += (error>>4); //turn on the PWM TCCR0A |= _BV(COM0A1); } }