未知的传感器值校准

时间:2013-11-28 04:35:09

标签: c algorithm avr atmel

我必须创建一个相扑机器人。我有一个线传感器,它不能穿过红线也不能穿过黑线。机器人从白色表面开始。我不知道我从ADC得到的值。有没有办法告诉机器人不要越过一条线?

我想存储3个第一个值的平均值,然后将它们与读数进行比较。

这是我的代码

#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);
}

1 个答案:

答案 0 :(得分:0)

您似乎没有太多选项可以与您的硬件进行交互(如显示器,按键等)...所以如果您无法使用电压表测量处理器引脚上的ADC值从白色移动到黑色或红色,您可以编写一个小的校准程序

  • 读取ADC值
  • 通过其中一个LED移动值,以便您可以逐位读取
  • 同步闪烁另一个LED开关以提供节拍,因此您不会错过零(或者您可以输出非常小的电机脉冲以获得声音反馈)
  • 完成此操作后,暂停所有(实际)电机动作

编辑: 并且可能还有传感器的数据表?!?