Witam, stworzyłem swojego pierwszego LF'a i jestem w trakcie pisania kodu. Początkowo będzie on sterowany w prostych pętlach "if", a w miarę rozwoju będę chciał dojść do napisania regulatora PD.
Aktualnie mam problem z odpowiednim wysterowaniem silników, w kodzie który napisałem nie dostaje oczekiwanych efektów.
Silniki zachowują się w następujący sposób:
1. Gdy czujniki nie wykrywają lini silniki dostają maksymalne obroty
2. Gdy wykryta jest linia na którymkolwiek czujniku obroty są identyczne, chociaż w kodzie wypełnienie się różni dla kolejnych par lub pojedynczych czujników.
Niestety nie mogę znaleźć gdzie leży błąd, dlatego też poprosił bym o pomoc z waszej strony.
Kod wygląda następująco:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define MOTOR_LEWY_PRZOD PORTD // |= (1<<PD2)
#define MOTOR_PRAWY_PRZOD PORTD // |= (1<<PD7)
#define MOTOR_LEWY_TYL PORTD // |= (1<<PD3)
#define MOTOR_PRAWY_TYL PORTB // |= (1<<PB0)
#define MOTOR_LEWY_PWM OCR1B //PB2
#define MOTOR_PRAWY_PWM OCR1A //PB1
void PWM(int LEWY, int PRAWY)
{
if(LEWY>=0)
{
if (LEWY>255)
LEWY=255;
MOTOR_LEWY_PRZOD |= (1<<PD2);
MOTOR_LEWY_TYL |= (0<<PD3);
}
if (PRAWY>=0) //PRZÓD
{
if (PRAWY>255)
PRAWY=255;
MOTOR_PRAWY_PRZOD |= (1<<PD7);
MOTOR_PRAWY_TYL |= (0<<PB0);
}
if(LEWY<0)
{
if (LEWY<-255)
LEWY=-255;
MOTOR_LEWY_PRZOD |= (0<<PD2);
MOTOR_LEWY_TYL |= (1<<PD3);
}
if (PRAWY<0) //TYŁ
{
if (PRAWY<-255)
PRAWY=-255;
MOTOR_PRAWY_PRZOD |= (0<<PD7);
MOTOR_PRAWY_TYL |= (1<<PB0);
}
MOTOR_LEWY_PWM = abs(LEWY);
MOTOR_PRAWY_PWM = abs(PRAWY);
}
int czujniki[6]={0,0,0,0,0,0};
void odczyt_adc()
{
for(int i=0; i<6; i++)
{
ADMUX &= 0b11100000; //zerowanie bitów mux
ADMUX |= i; //tab_czujnikow[i]; //wybór kanału przetwornika
ADCSRA |= (1<<ADSC); //uruchomienie pomiaru
while (ADCSRA & (ADSC==1)) {}; //oczekiwanie na zakonczenie pomiaru
if(ADCH>200) //porownanie wyniku
{czujniki[i]=1;} //wpisanie wyniku do tablicy
else
{czujniki[i]=0;}
}
}
int main(void)
{
//------------------------------------- ADC oraz kierunki pinów dla ADC ---------------------------------------
ADMUX |= (0<<REFS0) | (0<<REFS1); //AREF, Internal Vref turned off
ADMUX |= (1<<ADLAR); //wyrównanie do lewej, 8 bitowy wynik konwersji
ADCSRA |= (1<<ADEN) | (1<<ADPS0) | (1<<ADPS1) | (1<<ADPS2); //uruchomienie adc, prescaler 128 = 128khz
PORTC |= (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5);
DDRC |= (0<<PC0) | (0<<PC1) | (0<<PC2) | (0<<PC3) | (0<<PC4) | (0<<PC5);
PINC |= (1<<PC0) | (1<<PC1) | (1<<PC2) | (1<<PC3) | (1<<PC4) | (1<<PC5);
//--------------------- TIMER1 DLA PWM LEWY/PRAWY oraz kierunki pinów sterowania silnikami --------------------
TCCR1A |= (1<<COM1A1) | (1<<COM1B1) | (1<<WGM10); //Set OC0A on Compare Match, clear OC0A at BOTTOM (inverting mode), fast pwm 8-bit counter
TCCR1B |= (1<<WGM12) | (1<<CS11); //fast pwm 8 bit counter, prescaler = 8
DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2); //USTAWIENIE PB0/1/2 JAKO WYJSCIA (kierynek prawy/pwm lewy/pwm prawy)
DDRD |= (1<<PD2) | (1<<PD3) | (1<<PD7); //USTAWIENIE PD2/3/7 JAKO WYJSCIA (kierunek lewy/kierunek lewy/kierunek prawy)
while (1)
{
odczyt_adc();
if (czujniki[0]==1 && czujniki[1]==0) //tylko 0
{
PWM(100,0);
}
if (czujniki[0]==1 && czujniki[1]==1) //0 i 1
{
PWM(150,0);
}
if (czujniki[0]==0 && czujniki[1]==1 && czujniki[2]==0) //tylko 1
{
PWM(175,0);
}
if (czujniki[1]==1 && czujniki[2]==1) //1 i 2
{
PWM(200,0);
}
if (czujniki[1]==0 && czujniki[2]==1 && czujniki[3]==0) //tylko 2
{
PWM(225,0);
}
if (czujniki[2]==1 && czujniki[3]==1) //2 i 3
{
PWM(250,250);
}
if (czujniki[2]==0 && czujniki[3]==1 && czujniki[4]==0) //tylko 3
{
PWM(0,225);
}
if (czujniki[3]==1 && czujniki[4]==1) //3 i 4
{
PWM(0,200);
}
if (czujniki[3]==0 && czujniki[4]==1 && czujniki[5]==0) //tylko 4
{
PWM(0,175);
}
if (czujniki[4]==1 && czujniki[5]==1) //4 i 5
{
PWM(0,150);
}
if (czujniki[5]==1 && czujniki[4]==0) //tylko 5
{
PWM(0,100);
}
}
}
Z góry dziękuję za udzieloną pomoc.
EDIT: Do odmierzania czasu używam zewnętrznego kwarcu 16mhz.
Ustawienie fuse bitów:
-U lfuse:w:0xf7:m -U hfuse:w:0xd9:m -U efuse:w:0xff:m
Czyli:
Full swing crystal, 16K CK, 14CK +65 ms [CKSEL = 0111, SUT = 111]
EDIT2: w symulatorze zauważyłem, że nie zmieniają mi się kanały na ADC