rendered paste body/********************************************************************************
*
* 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 <avr/io.h>
#include <delay.h>
// 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;