2013-11-28 3 views
1

Мне нужно создать робот сумо. У меня есть линейный датчик, который не может пересекать красную линию или черную линию. Робот начинается на белой поверхности. Я не знаю значений, которые я получаю от АЦП. Есть ли способ сказать роботу не пересекать линию?Неизвестная калибровка значения датчика

Я думал сохранить среднее значение из трех первых значений, а затем сравнить их с показаниями.

Вот мой код

#ifndef F_CPU 
#define F_CPU 1000000 // 1 Mhz 
#endif 


#include <avr/io.h> 
#include <inttypes.h> 
#include <util/delay.h> 
//The maximal possible delay is 262.14 ms/F_CPU in MHz. = 262 ms = 0.262s 
#include <stdlib.h> 

/*-----#Functions#-----*/ 

/*-----#Motor#-----*/ 
void motors_init(); 
void M1_forward(unsigned char pwm); 
void Moveforward(unsigned char pwm); 
void Movebackward(unsigned char pwm); 
void Moveleft(unsigned char pwm); 
void Moveright(unsigned char pwm); 

/*-----#ADC#-----*/ 
void InitADC(); 
uint16_t ReadADC(uint8_t ch); 
uint16_t sensor_average(uint8_t ch); 


/*-----#Other#-----*/ 
void delay_ms(unsigned int time_ms); 



/*-----#Global Variables#-----*/ 
uint16_t valueAnalSensor1; 
uint16_t valueAnalSensor2; 
uint16_t linesensor; 


int main() 
{ 
    DDRD = 0xFF;   //PD as output 
    PORTD= 0x00;   //keep all LEDs off 
    motors_init(); 
    InitADC(); 

    linesensor = sensor_average(1); 
    valueAnalSensor1 = sensor_average(2); 
    valueAnalSensor2 = sensor_average(3); 



      PORTD ^= _BV(PD4);  //turn LED off 
      delay_ms(500); //wait for half second 
      PORTD ^= _BV(PD4);  //turn LED off 
      delay_ms(500); //wait for half second 
      PORTD ^= _BV(PD4);  //turn LED off 
      delay_ms(500); //wait for half second 
      PORTD ^= _BV(PD4);  //turn LED off 
      delay_ms(500); //wait for half second 

      delay_ms(500); 
      Moveforward(10); 
      delay_ms(500); 
      delay_ms(500); 
      delay_ms(500); 
      delay_ms(500); 
      Movebackward(255); 
      delay_ms(500); 
      delay_ms(500); 
      delay_ms(500); 
      delay_ms(500); 
      Moveleft(10); 
      delay_ms(500); 
      delay_ms(500); 
      delay_ms(500); 
      delay_ms(500); 
      delay_ms(500); 
      Moveright(2); 
      delay_ms(500); 
      delay_ms(500); 
      delay_ms(500); 
      delay_ms(500); 
      delay_ms(500); 

    while(1) 
    { 
      PORTD ^= _BV(PD4);  //turn LED off 
      delay_ms(100); //wait for half second 
      PORTD ^= _BV(PD4);  //turn LED off 
      delay_ms(100); //wait for half second 
      PORTD ^= _BV(PD4);  //turn LED off 
      delay_ms(100); //wait for half second 
      PORTD ^= _BV(PD4);  //turn LED off 
      delay_ms(100); //wait for half second 


     //adc_result=ReadADC(0);   // Read Analog value from channel-0 
     Moveforward(255); 

     //delay_ms(500); 
     //Moveforward(255); // Full speed 

     /* 
     */ 
     //check_line_sensor(); 
     //check_analog_sensor(); 

    } 
} 

void check_line_sensor() 
{ 
    uint16_t currentValue; 
    currentValue = ReadADC(1); 

    if(currentValue < linesensor); 
    //TODO: backup motors AND TURN AND move forward 
} 

void check_analog_sensor() 
{ 
    uint16_t currentValue; 
    currentValue = ReadADC(1); 

    if(currentValue < valueAnalSensor1); 
    { 
     while(ReadADC(1) > linesensor) 
     { 
      Moveforward(255); 
      delay_ms(5000); 
     } 
    } 
} 


uint16_t sensor_average(uint8_t ch) 
{ 
    uint16_t adcvalue; 
    adcvalue = ReadADC(ch); 
    delay_ms(1000); 
    adcvalue = adcvalue + ReadADC(ch); 
    delay_ms(1000); 
    adcvalue = adcvalue + ReadADC(ch); 
    adcvalue = adcvalue/3; 

    return adcvalue; 
} 


void motors_init() 
{ 
    // configure for inverted PWM output on motor control pins: 
    // set OCxx on compare match, clear on timer overflow 
     DDRD = 0xFF;   //PD as output 
     PORTD= 0x00;   //keep all LEDs off 


    TCCR2 |= (1 << COM21); 
    // set none-inverting mode 

    TCCR2 |= (1 << WGM21) | (1 << WGM20); 
    // set fast PWM Mode 

    //TCCR2 |= (1 << CS21); // No need for a prescalar 
    // set prescaler to 8 and starts PWM 



    // initialize all PWMs to 0% duty cycle (braking) 
    OCR1A = OCR1B = 0; 

} 
// Motor Control Functions -- pwm is an 8-bit value 
// (i.e. ranges from 0 to 255) 


void Moveforward(unsigned char pwm) 
{ 
    PORTB|=((1<<PB2)|(1<<PB1)); 
    PORTD|=(1<<PD3); //Set BIT PD3 
    PORTD&=~(1<<PD2); //Clear BIT PD2 
    PORTD|=(1<<PD1); //Set BIT PD1 
    PORTD&=~(1<<PD0); //Clear BIT PD0 
    OCR1A = pwm; 
    OCR1B = pwm; 
} 

void Movebackward(unsigned char pwm) 
{ 
    PORTB|=((1<<PB2)|(1<<PB1)); 
    PORTD&=~(1<<PD3); 
    PORTD|=(1<<PD2); 
    PORTD&=~(1<<PD1); 
    PORTD|=(1<<PD0); 
    OCR1A = pwm; 
    OCR1B = pwm; 
} 

void Moveleft(unsigned char pwm) 
{ 
    PORTB|=((1<<PB2)|(1<<PB1)); 
    PORTD&=~(1<<PD3); 
    PORTD|=(1<<PD2); 
    PORTD&=~(1<<PD1); 
    PORTD&=~(1<<PD0); 
    OCR1A = pwm; 
    OCR1B = pwm; 
} 

void Moveright(unsigned char pwm) 
{ 
    PORTB|=((1<<PB2)|(1<<PB1)); 
    PORTD&=~(1<<PD3); 
    PORTD&=~(1<<PD2); 
    PORTD&=~(1<<PD1); 
    PORTD|=(1<<PD0); 
    OCR1A = pwm; 
    OCR1B = pwm; 
} 




void InitADC() 
{ 
    //TODO: RECHECK THIS! 
    ADMUX=(0<<REFS1)|(1<<REFS0);       // For Aref=internal; 
    ADCSRA=(1<<ADEN)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); //Rrescalar div factor =8 
} 

uint16_t ReadADC(uint8_t ch) 
{ 
    ch &= 0b00000111; 
    ADMUX= (ADMUX & 0xF8)|ch; 

    //Start Single conversion 
    ADCSRA|=(1<<ADSC); 

    while(ADCSRA & (1<<ADSC)); 

    return(ADC); 
} 

void delay_ms(unsigned int time_ms) 
{ 

    unsigned int i; 

    for (i = 0; i < time_ms; i++) 
    _delay_ms(1); 
} 
+0

Много вопросов ... Какова точность АЦП? Белое значение АЦП? Красное значение АЦП? Черное значение АЦП? Вам нужно получить базовый уровень. –

+0

Это то, что я не знаю. ADC - 8-битная точность. –

+0

Я просто знаю, что робот начнет белую поверхность. Я думал о сохранении этого значения и использовании его в качестве сравнения. –

ответ

0

Вы, кажется, не так много вариантов, чтобы взаимодействовать с оборудованием (например, дисплей, ключи и т.д.) ... так что если вы не в состоянии измерить значение АЦП на процессоре штифтом с помощью вольтметра, когда датчик перемещается от белого до черного или красного цвета, вы можете написать небольшую процедуру калибровки, которая

  • считывает значения АЦП
  • сдвигает значение с помощью одного из светодиодов так что вы можете прочитать его битком до конца
  • blink еще один светодиод включен-выключен в синхронизации, чтобы обеспечить вам удар, поэтому вы не пропустите нулевое значение (в качестве альтернативы вы можете выводить очень маленькие импульсы двигателя, чтобы получить слышимую обратную связь)
  • пока это делается, приостановите все (реальных) действий двигателя

EDIT: , и там, вероятно, может быть информационный лист датчика тоже?!?

Смежные вопросы