제가 프로그램 소스를 구했는데 중간 중간에 주석이 있지만 잘 이해가 안되서요~
atmega8을 사용해 짠 4족로봇 소스인데 이 소스를 atmega128로 바꿀려구요
계속해봐도 잘 모르겠어요..
도와주세요~
// 천천히 전진, 좌,우 회전.
// 좌우 회전 방법 개선
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#define U08 unsigned char
#define U16 unsigned int
#define S16 signed int
#define OFF 0
#define ON 1
#define LEG_FORWARD (3000) //한쪽 두개의 다리를 넓게 벌릴때 사용되는 각도
#define LEG_BACKWARD (7500) // " " " 좁게 만들때
#define LEG_UP (2500)
#define LEG_DOWN (-0)
#define ROBOT_SPEED (U08)(3) //robot 패턴 변화시간 *100ms : 작을수록 빠름.
#define SERVO_DIFF (S16)(ROBOT_SPEED * 100 / 20) //각 패턴당 움직이는 시간(ms) / 서보 한 펄스 시간(ms)
#define ROBOT_FW 1
#define ROBOT_BW 2
#define ROBOT_LE 3
#define ROBOT_RI 4
#define ROBOT_DIR_LAST 5
#define ROBOT_STOP 0
void SERVO_ONOFF(num, onoff);
void LED_ONOFF(num, onoff);
void RobotPatternChange(void);
U08 gu08DelayTime = 0;
U08 gu08RobotDirec = 0;
U08 gu08RobotSpeed = 5;
U16 u16_ServoTargetAngle[8] = {0,}; //서보 목표 각도
U16 u16_ServoPresentAngle[8] = {0,}; //서보 현재 각도
U16 gu16ServoActualAngle[8] = {0,}; //실제 서보 각도
S16 gs16ServoAngleDiff[8]; //서보각도 변화량
// 1 2 3 4 //회전 관절
const U16ServoCenterValue[8] = { 0x5dc0 - 900, 0x5dc0 - 700 , 0x5dc0 - 300 , 0x5dc0 + 200,
// 5 6 7 8 //상하 관절
0x5dc0 - 500, 0x5dc0 + 300, 0x5dc0 -200, 0x5dc0 + 800 };
const S16_MovingAngleData[][8] = {
// 1 2 3 4 5 6 7 8
/////// 전진
{LEG_FORWARD, -LEG_FORWARD, LEG_BACKWARD, -LEG_BACKWARD, 0, 0, 0, 0}, //정지1: 1,2번 쪽 넓게
{LEG_FORWARD, -LEG_FORWARD, LEG_BACKWARD, -LEG_BACKWARD, -LEG_DOWN, LEG_UP, -LEG_DOWN, LEG_UP}, //다리 들고
{LEG_BACKWARD, -LEG_BACKWARD, LEG_FORWARD, -LEG_FORWARD, -LEG_DOWN, LEG_UP, -LEG_DOWN, LEG_UP}, //다리 돌리고
{LEG_BACKWARD, -LEG_BACKWARD, LEG_FORWARD, -LEG_FORWARD, 0, 0, 0, 0}, //3,4번 다리로 넓게 내리고
{LEG_BACKWARD, -LEG_BACKWARD, LEG_FORWARD, -LEG_FORWARD, -LEG_UP, LEG_DOWN, -LEG_UP, LEG_DOWN},
{LEG_FORWARD, -LEG_FORWARD, LEG_BACKWARD, -LEG_BACKWARD, -LEG_UP, LEG_DOWN, -LEG_UP, LEG_DOWN},
/////// 회전(좌 ?)
{LEG_FORWARD, -LEG_FORWARD, LEG_FORWARD, -LEG_FORWARD, 0, 0, 0, 0}, //정지1: 4발 넓게
{LEG_FORWARD, -LEG_FORWARD, LEG_FORWARD, -LEG_FORWARD, -LEG_UP, 0, -LEG_UP, 0}, //다리 들고
{-LEG_FORWARD, -LEG_FORWARD, -LEG_FORWARD, -LEG_FORWARD, -LEG_UP, 0, -LEG_UP, 0}, //
{-LEG_FORWARD, -LEG_FORWARD, -LEG_FORWARD, -LEG_FORWARD, 0, 0, 0, 0}, //3,4번 다리로 넓게 내리고
{-LEG_FORWARD, -LEG_FORWARD, -LEG_FORWARD, -LEG_FORWARD, 0, LEG_UP, 0, LEG_UP},
{LEG_FORWARD, -LEG_FORWARD, LEG_FORWARD, -LEG_FORWARD, 0, LEG_UP, 0, LEG_UP},
//////// 회전 (우 ?)
{LEG_FORWARD, -LEG_FORWARD, LEG_FORWARD, -LEG_FORWARD, 0, 0, 0, 0}, //정지1: 4발 넓게
{LEG_FORWARD, -LEG_FORWARD, LEG_FORWARD, -LEG_FORWARD, 0, LEG_UP, 0, LEG_UP}, //다리 들고
{LEG_FORWARD, LEG_FORWARD, LEG_FORWARD, LEG_FORWARD, 0, LEG_UP, 0, LEG_UP}, //
{LEG_FORWARD, LEG_FORWARD, LEG_FORWARD, LEG_FORWARD, 0, 0, 0, 0}, //3,4번 다리로 넓게 내리고
{LEG_FORWARD, LEG_FORWARD, LEG_FORWARD, LEG_FORWARD, -LEG_UP, 0, -LEG_UP, 0},
{LEG_FORWARD, -LEG_FORWARD, LEG_FORWARD, -LEG_FORWARD, -LEG_UP, 0, -LEG_UP, 0},
{3840, -3840, 4800, -4800, 0, 0, 0, 0},
{3840, -3840, 4800, -4800, 0, 0, 0, 0},
// {5760, 5760, 3840, -3840, 0, 0, 0, 0},
// {5760, 5760, 3840, -3840, 0, 0, 0, 0},
// {5760, 5760, 3840, -3840, 0, 0, 0, 0}
};
U08 u08_WalkingPattern = 0;
U08 u08_ServoIndex = 0;
U08 u08_1msCnt = 0;
U08 u08_100msCnt = 0;
U08 u08_1secCnt = 0;
U08 num=0;
void t1msTask()
{
if (gu08DelayTime > 0)
{
gu08DelayTime--;
}
};
void t2msTask(){};
void t10msTask(){};
void t100msTask()
{
gu08RobotSpeed--;
if (0 == gu08RobotSpeed)
{
RobotPatternChange();
gu08RobotSpeed = ROBOT_SPEED;
}
};
void t1secTask(){};
void RobotPatternChange(void)
{
U08 i, temp;
u08_1secCnt ++;
U16 su16TempPresentAngle;
U16 su16TempTargetAngle;
LED_ONOFF(u08_1secCnt%8,OFF);
if(u08_1secCnt%8>=1) LED_ONOFF(u08_1secCnt%8-1,ON);
if(ROBOT_FW == gu08RobotDirec)
{
for (i=0; i<8; i++)
{
u16_ServoPresentAngle[i] = u16_ServoTargetAngle[i]; //기존 목표값을 현재값으로
u16_ServoTargetAngle[i] = U16ServoCenterValue[i] + S16_MovingAngleData[u08_WalkingPattern][i];
//다음 다리 각도값 : 서보모터 중앙값 + 다리이동 변화량.
gs16ServoAngleDiff[i] = ((S16)u16_ServoTargetAngle[i] - (S16)u16_ServoPresentAngle[i]) / SERVO_DIFF; //서보모터 변화량 계산
gu16ServoActualAngle[i] = u16_ServoPresentAngle[i]; //서보 실제값을 현재 시작 서보 각도값으로.
}
}
else if(ROBOT_BW == gu08RobotDirec)
{
for (i=0; i<8; i++)
{
u16_ServoPresentAngle[i] = u16_ServoTargetAngle[i]; //기존 목표값을 현재값으로
u16_ServoTargetAngle[i] = U16ServoCenterValue[i] + S16_MovingAngleData[5-u08_WalkingPattern][i];
//다음 다리 각도값 : 서보모터 중앙값 + 다리이동 변화량.
gs16ServoAngleDiff[i] = ((S16)u16_ServoTargetAngle[i] - (S16)u16_ServoPresentAngle[i]) / SERVO_DIFF; //서보모터 변화량 계산
gu16ServoActualAngle[i] = u16_ServoPresentAngle[i]; //서보 실제값을 현재 시작 서보 각도값으로.
}
}
else if(ROBOT_LE == gu08RobotDirec)
{
temp = u08_WalkingPattern + 6;
for (i=0; i<8; i++)
{
u16_ServoPresentAngle[i] = u16_ServoTargetAngle[i]; //기존 목표값을 현재값으로
u16_ServoTargetAngle[i] = U16ServoCenterValue[i] + S16_MovingAngleData[temp][i];
//다음 다리 각도값 : 서보모터 중앙값 + 다리이동 변화량.
gs16ServoAngleDiff[i] = ((S16)u16_ServoTargetAngle[i] - (S16)u16_ServoPresentAngle[i]) / SERVO_DIFF; //서보모터 변화량 계산
gu16ServoActualAngle[i] = u16_ServoPresentAngle[i]; //서보 실제값을 현재 시작 서보 각도값으로.
}
}
else if(ROBOT_RI == gu08RobotDirec)
{
temp = u08_WalkingPattern + 12;
for (i=0; i<8; i++)
{
u16_ServoPresentAngle[i] = u16_ServoTargetAngle[i]; //기존 목표값을 현재값으로
u16_ServoTargetAngle[i] = U16ServoCenterValue[i] + S16_MovingAngleData[temp][i];
//다음 다리 각도값 : 서보모터 중앙값 + 다리이동 변화량.
gs16ServoAngleDiff[i] = ((S16)u16_ServoTargetAngle[i] - (S16)u16_ServoPresentAngle[i]) / SERVO_DIFF; //서보모터 변화량 계산
gu16ServoActualAngle[i] = u16_ServoPresentAngle[i]; //서보 실제값을 현재 시작 서보 각도값으로.
}
}
else //보행 패턴이 없는 경우 : 변화량을 0 으로
{
for (i=0; i<8; i++)
{
gs16ServoAngleDiff[i] = 0;
}
}
if ( ROBOT_STOP != gu08RobotDirec)
{
u08_WalkingPattern++;
if(u08_WalkingPattern >= 6) u08_WalkingPattern = 0;
}
};
int main(void)
{
unsigned int i,j,k,l;
u08_1secCnt = 0; //for test
TIMSK = 0x11; //Timer 0 overflow int enable | Timer1 Output compare
TCCR0 = 0x03; //64 prescaler
TCNT0 = 0x06; //for 1ms
TCCR1A = 0x00; // Normal mode
TCCR1B = 0x01; // None prescaler
GICR = 0x40; // INT 0 enable
MCUCR = 0x02; // INT 0 Falling edge Ext int
DDRA = 0xf0; //PA4-7 : LED
DDRC = 0xc3; //PC0,1,6,7 : LED
PORTA = 0xf0; //LED all off
PORTC = 0xc3; //LED all off
DDRD = 0xf0; //Servo
DDRB = 0xf0;
PORTD = 0x00;
PORTB = 0x00;
// OCR1A = 0x5dc0 //test 1.5ms
// 1.5ms : 0x5dc0 0.9ms : 0x3840 2.1ms : 0x8340
for (i=0; i<8; i++)
{
u16_ServoPresentAngle[i] = U16ServoCenterValue[i];
u16_ServoTargetAngle[i] = U16ServoCenterValue[i];
gu16ServoActualAngle[i] = U16ServoCenterValue[i];
}
u08_ServoIndex = 0;
TCNT1 = 0;
// TCCR1B = 0x04; // 256 prescaler
// TCNT1 = 0x0bdc; // 1sec for test.
sei();
while(1)
{
num++;
}
return 0;
}
void SERVO_ONOFF(num, onoff)
{
if(onoff == OFF)
{
if(num==0) PORTB &= ~_BV(4);
else if(num==1) PORTB &= ~_BV(5);
else if(num==2) PORTB &= ~_BV(6);
else if(num==3) PORTB &= ~_BV(7);
else if(num==4) PORTD &= ~_BV(4);
else if(num==5) PORTD &= ~_BV(5);
else if(num==6) PORTD &= ~_BV(6);
else if(num==7) PORTD &= ~_BV(7);
}
else if(onoff == ON)
{
if(num==0) PORTB |= _BV(4);
else if(num==1) PORTB |= _BV(5);
else if(num==2) PORTB |= _BV(6);
else if(num==3) PORTB |= _BV(7);
else if(num==4) PORTD |= _BV(4);
else if(num==5) PORTD |= _BV(5);
else if(num==6) PORTD |= _BV(6);
else if(num==7) PORTD |= _BV(7);
}
}
void LED_ONOFF(num,onoff)
{
if(onoff == OFF)
{
if(num==0) PORTC &= ~_BV(0);
else if(num==1) PORTC &= ~_BV(1);
else if(num==2) PORTC &= ~_BV(6);
else if(num==3) PORTC &= ~_BV(7);
else if(num==4) PORTA &= ~_BV(4);
else if(num==5) PORTA &= ~_BV(5);
else if(num==6) PORTA &= ~_BV(6);
else if(num==7) PORTA &= ~_BV(7);
}
else if(onoff == ON)
{
if(num==0) PORTC |= _BV(0);
else if(num==1) PORTC |= _BV(1);
else if(num==2) PORTC |= _BV(6);
else if(num==3) PORTC |= _BV(7);
else if(num==4) PORTA |= _BV(4);
else if(num==5) PORTA |= _BV(5);
else if(num==6) PORTA |= _BV(6);
else if(num==7) PORTA |= _BV(7);
}
}
ISR (TIMER1_COMPA_vect) //서보 모터 제어용
{
TCNT1 = 0;
U08 temp;
u08_ServoIndex ++;
if(u08_ServoIndex == 16 ) //서보 인덱스 계산 8개의 서보가 각각 ON/OFF되므로 16
{
u08_ServoIndex = 0;
}
temp = u08_ServoIndex/2;
if(u08_ServoIndex % 2 == 0) //짝수이면 펄스 ON
{
SERVO_ONOFF(temp, ON);
OCR1A = gu16ServoActualAngle[temp];
}
else //홀수 일때는 펄스의 한 주기 길이가 2.5ms가 되도록 OFF 출력
{
SERVO_ONOFF(temp, OFF);
OCR1A = 0x9c40 - gu16ServoActualAngle[temp];
gu16ServoActualAngle[temp] += gs16ServoAngleDiff[temp]; //0x9c40이 2.5ms 시간임.
}
}
ISR (INT0_vect)
{
if ( 0 != gu08DelayTime) return;
gu08RobotDirec++;
gu08DelayTime = 200;
if (gu08RobotDirec >= ROBOT_DIR_LAST)
{
gu08RobotDirec = ROBOT_STOP;
}
}
ISR (TIMER0_OVF_vect) //Tick Timer??
{
TCNT0 = 0x06;
u08_1msCnt++;
t1msTask();
if(u08_1msCnt % 2 == 0) t2msTask();
if(u08_1msCnt % 10 == 0) t10msTask();
if(u08_1msCnt % 100 == 0)
{
t100msTask();
u08_100msCnt++;
u08_1msCnt = 0;
}
if(u08_100msCnt % 5 == 0)
{
// t500msTask();
}
if(u08_100msCnt == 10)
{
t1secTask();
u08_100msCnt =0;
}
if(u08_100msCnt % 100 == 0)
{
//t10secTask();
u08_100msCnt = 0;
}
return 0;
}
ㅡㅡ;;;