회원가입 ID/PW 찾기
AA
아크마님이 만드신 라인트레이서를 보고 구현해 봤는데...

스위치를 없애고 adc값을 받아 lcd에 표시해주고 모터를 구동할려고 하고 있습니다.

아크마님이 주신 소스를 보고 아무리 소스수정을 해도 머가 먼지 잘모르겠습니다...

어느부분을 지워야할지 잘모르겠네요.........

대충이라도 조금 알려주세요 A포트: 발광 B포트: LCD D포트: 모터 F포트: 수광

AVR128 사용중입니다....간단하게라도 좀 알려주세요

 #include <mega128.h>

// Alphanumeric LCD Module functions
#asm
   .equ __lcd_port=0x18 ;PORTB
#endasm
#include <lcd.h>  
#include <delay.h>
#include <stdio.h>
#include <stdlib.h>
#include "acc.h"
#include "handle.h"
 

#define TRUE  1
#define FALSE  0
  
#define TIMER0_32PRESCALE_VALUE 2   // (1/16MHz)*32*1000000

#define SENSOR_ON_TIME   40  // 40us 후에 센서를 끔.
#define SENSOR_OFF_TIME  70  // 트리거 신호의 주기 = 240us


#define FULL_STEP   3/*2상*/  /* 1-2상여자 = 7 */
#define ZERO    0
#define RIGHT  1
#define LEFT  2
#define BOTH  3   

#define FORWARD  0x03  /* 모터 방향 설정 bit1=왼쪽, bit0=오른쪽 */

#define MOTOR_PORT    PORTD

#define SPEED_LIMIT  300
#define SPEED_START  0

#define motor_disable()  MOTOR_PORT = 0x00
#define enable()            #asm("sei") 
#define disable()           #asm("cli") 


#define sen_on()  PORTA=0x18
#define sen_off()  PORTA=0x00


#define SENSOR_MODE_ON  1
#define SENSOR_MODE_OFF  2

#define SENSOR_ADJUST   50   

#define LEFT2  1
#define LEFT1   2
#define LEFT0   3

#define RIGHT2  6
#define RIGHT1  5
#define RIGHT0  4

#define LIGHT 0
#define COMPARE 1
#define MODE LIGHT
 
#define HANDLE_RATE_CUR  70
#define HANDLE_RATE_OLD     30

typedef  unsigned char byte;
typedef  unsigned int word;
typedef  unsigned long dword;

        
byte mode; 
byte buzzer_flag;  
 
// sensor part
 
byte sensor_mode; 
word sensor_input[6];
word sensor_border; // 비교기식일때 on/off 경계선
int sensor_adjust; // 광량식일때 좌우 대칭 센서 보정
byte sensor_cnt=0;


// motor part
const byte r_phase_table[] = {0x50, 0x60, 0xA0, 0x90};
const byte l_phase_table[] = {0x05, 0x06, 0x0A, 0x09};  

byte step_status;    // 주행 방향
word speed_limit; // 최고 제한속도
word time_r,time_l; // 타이머 주기
word acc_index;
byte l_phase_index, r_phase_index; // 상 인덱스
 
// adjust
int handle_adjust=0; 
long handle_adjust_cur=0;
long handle_adjust_old=150;
int handle_gain=4;
  
// general part
byte lcd_buf[16];

word i,j;

void port_init(void)
{     
 // External SRAM page configuration:
 //              -              / 0000h - 7FFFh
 // Lower page wait state(s): None
 // Upper page wait state(s): None
 // MCUCR=0x80;// set PC7 as output. PC7 is A15 and is used to enable nCE of SRAM.
 // XMCRA=0x00;
 
 MCUCR=0x00;// set PC7 as output. PC7 is A15 and is used to enable nCE of SRAM.
 XMCRA=0x00;
 
 DDRA = 0x18;
 DDRB = 0xff; // lcd, dummy led
 DDRD = 0xff; // step motor output 
 DDRE = 0x08;    // joystick switch input, buzzer output(PORTE3)
 DDRF = 0x00; // sensor input
 
 
 SFIOR=0x00;
}
 
void tlcd_init(void)
{
 // LCD module initialization
 lcd_init(8);  
 lcd_gotoxy(0,0);
 lcd_putsf("tracer");
 lcd_gotoxy(0,1);
 lcd_putsf("akma 1.1");      
}
    
  
byte adc_on = FALSE;                       
#define ADC_VREF_TYPE 0x40
//ADC initialize
// Conversion time: 1uS
void adc_init(void)
{
 ADCSRA = 0x00; //disable adc
  ADMUX = 0x00; //select adc input 0
  ACSR  = 0x80;
  //ADCSRA = 0x89;   // 1us 검은색 수광은 이것도 되는데..
  ADCSRA = 0x8E; // 이러케 하면 adc가 먼저 win
 
  for(i=0;i<6;i++)
 {
  sensor_input[i]=0;
    }
}
void display_handle()
{

   sprintf(lcd_buf, "handle");
   lcd_gotoxy(0,0);
      lcd_puts(lcd_buf);
 
   sprintf(lcd_buf, "%8d", handle_adjust);
      lcd_gotoxy(0,1);
      lcd_puts(lcd_buf);
         delay_ms(1000);

}
 
void display_sensor()
{
  for(i=0;i<8;i+=2)
  { 
   sprintf(lcd_buf, "%d : %4d", i, sensor_input[i]);
   lcd_gotoxy(0,0);
      lcd_puts(lcd_buf);
 
   sprintf(lcd_buf, "%d : %4d",i+1, sensor_input[i+1]);
      lcd_gotoxy(0,1);
      lcd_puts(lcd_buf);
         delay_ms(1000);
  }
}

void display_sensor_compare()

 if( sensor_input[LEFT2] > sensor_border)
  {  
    lcd_buf[0] = '1';
 }else
 {
   lcd_buf[0] = '0';
 }
 
 if( sensor_input[LEFT1] > sensor_border)
 {  
    lcd_buf[1] = '1';
 }else
 {
   lcd_buf[1] = '0';
 }
 
 if( sensor_input[LEFT0] > sensor_border)
 {  
    lcd_buf[2] = '1';
 }else
 {
   lcd_buf[2] = '0';
 } 
 
     if( sensor_input[RIGHT0] > sensor_border)
 {  
    lcd_buf[3] = '1';
 }else
 {
   lcd_buf[3] = '0';
 } 
 
 if( sensor_input[RIGHT1] > sensor_border)
 {  
    lcd_buf[4] = '1';
 }else
 {
   lcd_buf[4] = '0';
 } 

 if( sensor_input[RIGHT2] > sensor_border)
 {  
    lcd_buf[5] = '1';
 }else
 {
   lcd_buf[5] = '0';
 } 
 
 lcd_gotoxy(0,1);
 lcd_puts(lcd_buf);
      
 sprintf(lcd_buf, "compare ");
 lcd_gotoxy(0,0);
 lcd_puts(lcd_buf);
  
 delay_ms(500);
 
}
 
 
// 광량식
void auto_detect()
{  
 long sensor_temp = 0;
                             
   TCNT0 = 0xff; 
 TCCR0 = 0x03; //start timer, prescale 32   
 TIMSK = 0x01; //timer 0 interupt
 enable(); // interrupt enable
 
   for(i=0;i<2;i++)
   {
     delay_ms(50);   // 센서값을 읽을 시간을 벌어줌 
  sensor_temp = (long)sensor_temp + (long)(sensor_input[1]+sensor_input[2]+sensor_input[3]-sensor_input[4]-sensor_input[5]-sensor_input[6]);
    } 
        
    sensor_adjust = (int)(sensor_temp/2);
 
 lcd_gotoxy(0,0);
 lcd_putsf("auto    ");
 
 lcd_gotoxy(0,1);
 lcd_putsf("detect  ");
 delay_ms(200);
 
 
 sprintf(lcd_buf, "adjust ");
  lcd_gotoxy(0,0);
  lcd_puts(lcd_buf);
   
 sprintf(lcd_buf, "%8d", sensor_adjust);
  lcd_gotoxy(0,1);
  lcd_puts(lcd_buf);
  delay_ms(300); 
  
   sensor_adjust = -20;//(int)(sensor_temp/10);
  
}      

//비교식
void auto_detect_compare()
{  
 long sensor_temp = 0;
                             
   TCNT0 = 0xff; 
 TCCR0 = 0x03; //start timer, prescale 32   
 TIMSK = 0x01; //timer 0 interupt
 enable(); // interrupt enable
 
   for(i=0;i<10;i++)
   {
     delay_ms(100);   // 센서값을 읽을 시간을 벌어줌 
  for(j=1;j<7;j++)    // 1,2,3센서(white) vs 4,5,6센서(black)
      sensor_temp += sensor_input[j];
    } 
   
    sensor_border = (word)((float)sensor_temp/(float)60 /* 6x10 */);
      
 lcd_gotoxy(0,0);
 lcd_putsf("auto    ");
 
 lcd_gotoxy(0,1);
 lcd_putsf("detect  ");
 delay_ms(200);
 
 
 sprintf(lcd_buf, "border ");
  lcd_gotoxy(0,0);
  lcd_puts(lcd_buf);
   
 sprintf(lcd_buf, "%8d", sensor_border);
  lcd_gotoxy(0,1);
  lcd_puts(lcd_buf);
  delay_ms(1000); 
}
 

void system_init(void)
{
 disable();       

 port_init();
 //센서를 보호하기 위해 부팅하자마자 바로 꺼준다..점등식으로만 써야하므로..
 sen_off();
 //시끄러우니 일단 끄자..

 tlcd_init();
 motor_disable();  
 adc_init();
 delay_ms(1); 
 sensor_mode = SENSOR_MODE_OFF;
 
 enable();  
}    


void start_motor(void)
{
    disable();
  
 step_status = BOTH;
 
 l_phase_index = r_phase_index = 0;
 speed_limit = SPEED_LIMIT; 
 acc_index = SPEED_START; 

 OCR1AH = (acc_tbl[acc_index]>>8)&0xff;   // register high byte
 OCR1AL = acc_tbl[acc_index]&0xff;       // register low byte
 
 OCR3AH = (acc_tbl[acc_index]>>8)&0xff;   // register high byte
 OCR3AL = acc_tbl[acc_index]&0xff;       // register low byte
 
 TCCR1B = 0x09;          //clock/1
 TCCR3B = 0x09;          //clock/1
     
 TIMSK = 0x11;
 ETIMSK = 0x10;
 
 enable();
}  
   
void beep(void)
{
 buzzer_flag =1;
 delay_ms(100);
 buzzer_flag =0;
 delay_ms(100);
}
 


void cal_trim(void)
{
  handle_adjust_cur =(long)( (((long)handle_adjust_old*(long)HANDLE_RATE_OLD) + (long)(sensor_input[1]+sensor_input[2]+sensor_input[3]-sensor_input[4]-sensor_input[5]-sensor_input[6]-sensor_adjust)*(long)HANDLE_RATE_CUR ) / (long)100);
    handle_adjust_old = handle_adjust_cur;
   handle_adjust=(int)(handle_adjust_cur*(int)handle_gain);
  
   //범위를 넘으면 시스템이 죽으므로 처리
  if(handle_adjust > 60)
   handle_adjust = 60;
 
  if(handle_adjust < -60)
   handle_adjust = -60;     

}  

void cal_trim_compare(void)
{
  if( sensor_input[LEFT2] > sensor_border)
  {  
    handle_adjust = 12;
 }
 else if( sensor_input[RIGHT2] > sensor_border)
 {
   handle_adjust = 12;
 }
 else if( sensor_input[LEFT1] > sensor_border)
 {
   handle_adjust = 8;
 }
 else if( sensor_input[RIGHT1] > sensor_border)
 {
     handle_adjust = -8;
 } 
 else if( sensor_input[LEFT0] > sensor_border)
 {
  handle_adjust = 4;
 }
 else if( sensor_input[RIGHT0] > sensor_border)
 {
  handle_adjust = -4;
 }else
 {
  handle_adjust = 1;
 }
 
 handle_adjust= (word)((float)handle_adjust * (float)handle_gain); 
      
}


void cal_speed(void)
{    
        // 가속 테이블은 140을 기준으로 141~~ 속도를 느리게
        // 0~139는 속도를 빠르게 해준다..   
 step_status = ZERO;
 acc_index++;
 if (acc_index > speed_limit) acc_index = speed_limit;    
 time_l=(word)((acc_tbl[acc_index]*handle[140+handle_adjust])>>8);   
 time_r=(word)((acc_tbl[acc_index]*handle[140-handle_adjust])>>8);
}               

// left motor phase
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
 l_phase_index--;
 l_phase_index &= FULL_STEP;
   
   MOTOR_PORT =  r_phase_table[r_phase_index] | l_phase_table[l_phase_index] ;
   
   step_status |= LEFT;
 
  if(step_status == BOTH)
   {  

  #if(MODE==LIGHT)
     cal_trim();
  #elseif(MODE==COMPARE)
    cal_trim_compare();
   #endif
   
     cal_speed();
    
    }
              
  OCR1AH = ( time_l >> 8 ) & 0xff;
 OCR1AL = time_l & 0xff; 
}

// right motor phase
interrupt [TIM3_COMPA] void timer3_compa_isr(void)
{
   r_phase_index++;
 r_phase_index &= FULL_STEP;
 
    MOTOR_PORT =  r_phase_table[r_phase_index] | l_phase_table[l_phase_index] ;
 
 step_status |= RIGHT;
  if(step_status == BOTH)
    {
  #if(MODE==LIGHT)
     cal_trim();
  #elseif(MODE==COMPARE)
    cal_trim_compare();
   #endif
       
     cal_speed();
    }
   
  OCR3AH = ( time_r >> 8 ) & 0xff;
 OCR3AL = time_r & 0xff;  
}

  
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{    
    sensor_input[sensor_cnt]= ADCW; 
 sensor_cnt++;
 if(sensor_cnt>=8) sensor_cnt=0;
 ADMUX =  sensor_cnt; // adc cheannel select               
}
  
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{    
 TCCR0 = 0x00; 
 if(sensor_mode == SENSOR_MODE_OFF)
 {
         ADCSRA|=0x40; //하얀색 수광용
         sen_on();
       sensor_mode = SENSOR_MODE_ON;
       TCNT0 = (byte)(0xff -  (SENSOR_ON_TIME/TIMER0_32PRESCALE_VALUE));   
      TCCR0 = 0x03; //start timer     
    
 }else if(sensor_mode ==  SENSOR_MODE_ON)
 {       
   //ADCSRA|=0x40; //검정색 수광용
      sen_off();
     
      sensor_mode = SENSOR_MODE_OFF;  
        TCNT0 = (byte)(0xff -  (SENSOR_OFF_TIME/TIMER0_32PRESCALE_VALUE));  
         TCCR0 = 0x03; //start timer          
 }else if(sensor_mode== (SENSOR_MODE_OFF+1))   
  {
            lcd_gotoxy(0,1);
         lcd_putsf("SENSOR");
         disable();
 }
              
}

// Timer 2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{


}
      

void main(void)
{       
 system_init(); 
 #if(MODE==LIGHT)
    auto_detect();
 #elseif(MODE==COMPARE)
   auto_detect_compare(); 
  #endif
  
   start_motor();  

 enable(); // interrupt enable
 
 while (1)
 { 

          //display_handle();
         //display_sensor();
        //display_sensor_compare();
 }  
}


댓글 2
  • No Profile
    스위치를 쓰는 소스가 맞나요?
     DDRE = 0x08;    // joystick switch input, buzzer output(PORTE3)
    이 소스가 조이스틱 스위치로부터 입력을 받도록 io를 설정하는겁니다.
    스위치 입력은 구현이 안되어있네요.
    그냥 스위치 안달고 사용하시면 되비다.
  • No Profile

하드웨어 설계 및 개발에 대하여 개발자들이 자유롭게 토론하는 공간입니다.
- Q&A, 자유주재 토론, 관련 정보 공유
- 분야 : 마이크로프로세서 응용, 전기/전자(아날로그/디지털) 회로 설계, C/C++ 프로그래밍, 펌웨어,
         PCB Artwork, 트러블슈팅 등 하드웨어 설계에 관한 전반인 내용
※ 게시글에 맞는 분류를 선택하여 글을 작성해 주시면 쾌적한 사이트 운영에 많은 도움이 됩니다.
※ 하드웨어 인사이트는 회원들간의 거래정보를 게재할 뿐이지, 그 어떤 책임과 의무도 가지지 않습니다.

search
  • 사랑은 너무 어려 양심이 무엇인지 모른다. 그러나 양심이 사랑에서 태어나는 것을 누가 모르는가?
    - 셰익스피어
  • * 납포인트 정보 *
  • 글 작성 : 3
  • 댓글 작성 : 1
  • 내 글이 추천받음 : 1
저작권법에 위배되는 콘텐츠는 등록 불가하며, 저작물에 대한 권리는 저작자에게 있습니다.
Copyright 2006-2021 © hardwareis.com, All rights reserved.