/******************************************************************************** * * Compiler: AVR-GCC * * This little program needs a little cleaning. It outputs two PWM channels for * standard motors (PB3 AND PD7), and 2 remote-control style pwm channels * for the ATMega16. Each motor should be continuously moving, so plug them * in and test them. Use this program as a basis to build bigger programs.. * * * The chip (ATMega8, 16 or 32): * * +------\_/-----+ * (XCK) PB0 | 1 40 | PA0 XCK=USART extern clock in / out * PB1 | 2 39 | PA1 * PB2 | 3 38 | PA2 * <-motor1 PB3 | 4 37 | PA3 * PB4 | 5 36 | PA4 * (MOSI) PB5 | 6 35 | PA5 * (MISO) PB6 | 7 34 | PA6 * (SCK) PB7 | 8 33 | PA7 * RESET | 9 32 | AREF * VCC | 10 31 | GND * GND | 11 30 | AVCC * XTAL2 | 12 29 | PC7 * XTAL1 | 13 28 | PC6 * USART PD0 | 14 27 | PC5 * USART PD1 | 15 26 | PC4 * PD2 | 16 25 | PC3 * PD3 | 17 24 | PC2 * <-servoB PD4 | 18 23 | PC1 * <-servoA PD5 | 19 22 | PC0 * PD6 | 20 21 | PD7 motor2-> * +--------------+ * * * ********************************************************************************/ #include #include // some constants to keep track of what directions things are moving: #define UP 1 #define DOWN -1 // to help make code more transparent: #define TRUE 1 #define FALSE 0 /******************************************************************************** * INIT_CHIP ********************************************************************************/ void init_chip(void) { // init stuff for the 8 bit timers: //TCCR1 = 0x72; // set phase correct PWM for timer 0 //OCR1 = 128; // set starting duty cycle for timer 0 - pin PB3 TCCR2 = 0x72; // set phase correct PWM for timer 2 OCR2 = 128; // set starting duty cycle for timer 2 - pin PD7 // init stuff for the 16 bit timer TCCR1A = 0xA2; // 0xFX versus 0xAX to invert waveform TCCR1B = 0x19; // 0x19 for 20ms prescaler ICR1 = 20000; // TOP value of counter set at 20ms (base freq = 50Hz) OCR1A = 1500; // Starting duty cycle (1500=center) motor A - pin PD5 OCR1B = 1500; // Starting duty cycle (1500=center) motor B - pin PD4 // set output pins DDRD = 0xB0; // set output bits (OCR 1A 1B & motor 2 compare) DDRB = 0x08; // set output motor 1 } /******************************************************************************** * MAIN ********************************************************************************/ void main (void) { uint16_t pw_A = 1500; // duty cycle for servo A uint16_t pw_B = 1500; // duty cycle for servo B uint8_t pw_1 = 127; // duty cycle for motor 1 uint8_t pw_2 = 127; // duty cycle for motor 2 int8_t directionA = UP; int8_t directionB = DOWN; int8_t direction1 = UP; int8_t direction2 = DOWN; uint8_t speedA = 2; uint8_t speedB = 3; uint8_t speed1 = 1; uint8_t speed2 = 1; init_chip(); // initializes registers and pin stuff _delay_loop_2(5000); // wait 5ms for stuff to turn on while (TRUE){ //check if pulse width changes need to switch directions: if(pw_A >= 2000) directionA = DOWN; if(pw_A <= 1000) directionA = UP; if(pw_B >= 2000) directionB = DOWN; if(pw_B <= 1000) directionB = UP; if(pw_1 >= 245) direction1 = DOWN; if(pw_1 <= 10) direction1 = UP; if(pw_2 >= 245) direction2 = DOWN; if(pw_2 <= 10) direction2 = UP; pw_A += (directionA * speedA); pw_B += (directionB * speedB); pw_1 += (direction1 * speed1); pw_2 += (direction2 * speed2); OCR1A = pw_A; // replace output compare registers OCR1B = pw_B; // with the new pulse widths //OCR1 = pw_1; OCR2 = pw_2; _delay_loop_2(500); // delay some number of microseconds } } // ************************* 16 Bit timer reference ******************************* // // TCCR1A bits: // | | | = 0xA2 // COM1A1 - COM1A0 - COM1B1 - COM1B0 - FOC1A - FOC1B - WGM11 - WGM10 // // TCCR1B bits: // | | | = 0x19 // ICNC1 - ICES1 - - - WGM13 - WGM12 - CS12 - CS11 - CS10 // // WGM - turn bits 11 12 & 13 on for fast PWM where ICR1 defines TOP // COM - in fast PWM mode, A1 & B1 on. A0 & B0 off and on toggles wave invert // FOC1A, FOC1B - set these bits for channel A and channel B, respectively // CS - prescaling 0-5: none - 1 - 8 - 64 - 256; // // OCR1AH & OCR1AL (to specify high and low bytes - may be needed) // ************************* 8 Bit timer reference ******************************* // // TCCR0 bits: // 1 1 1 1 1 = 0x73 // FOC0 - WGM00 - COM01 - COM00 - WGM01 - CS02 - CS01 - CS00 // // // // WGM - turn bits 11 12 & 13 on for fast PWM where ICR1 defines TOP // COM - in fast PWM mode, A1 & B1 on. A0 & B0 off and on toggles wave invert // FOC - always 0 for pwm // CS - prescaling 0-5: none - 1 - 8 - 64 - 256;