Мне нужно создать робот сумо. У меня есть линейный датчик, который не может пересекать красную линию или черную линию. Робот начинается на белой поверхности. Я не знаю значений, которые я получаю от АЦП. Есть ли способ сказать роботу не пересекать линию?Неизвестная калибровка значения датчика
Я думал сохранить среднее значение из трех первых значений, а затем сравнить их с показаниями.
Вот мой код
#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);
}
Много вопросов ... Какова точность АЦП? Белое значение АЦП? Красное значение АЦП? Черное значение АЦП? Вам нужно получить базовый уровень. –
Это то, что я не знаю. ADC - 8-битная точность. –
Я просто знаю, что робот начнет белую поверхность. Я думал о сохранении этого значения и использовании его в качестве сравнения. –