我必须创建一个相扑机器人。我有一个线传感器,它不能穿过红线也不能穿过黑线。机器人从白色表面开始。我不知道我从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);
}
答案 0 :(得分:0)
您似乎没有太多选项可以与您的硬件进行交互(如显示器,按键等)...所以如果您无法使用电压表测量处理器引脚上的ADC值从白色移动到黑色或红色,您可以编写一个小的校准程序
编辑: 并且可能还有传感器的数据表?!?