Skocz do zawartości

programek

Użytkownicy
  • Zawartość

    5
  • Rejestracja

  • Ostatnio

Reputacja

0 Neutralna

O programek

  • Ranga
    2/10

Informacje

  • Płeć
    Mężczyzna
  • Lokalizacja
    Kraków
  1. Troche nie wiem jak się za to zabrać :/
  2. tego warunku:if(aktualna_pozycja ==0) nie dałem ponieważ nie planowałem przerw w trasie. wartość adc 850 dobrałem metodą prób i błędów. Dzisiaj rano chciałem zrobić test i wywaliłem wszystko z pętli głównej i dałem to: pomiar_czujnik(1); if ( (linia-100) < wynik && wynik < (linia + 100) ) c1 = 1; else c1 = 0; pomiar_czujnik(2); if ( (linia-100) < wynik && wynik < (linia + 100) ) c2 = 1; else c2 = 0; pomiar_czujnik(3); if ( (linia-100) < wynik && wynik < (linia + 100) ) c3 = 1; else c3 = 0; pomiar_czujnik(4); if ( (linia-100) < wynik && wynik < (linia + 100) ) c4 = 1; else c4 = 0; pomiar_czujnik(5); if ( (linia-100) < wynik && wynik < (linia + 100) ) c5 = 1; else c5 = 0; pomiar_czujnik(6); if ( (linia-100) < wynik && wynik < (linia + 100) ) c6 = 1; else c6 = 0; pomiar_czujnik(7); if ( (linia-100) < wynik && wynik < (linia + 100) ) c7 = 1; else c7 = 0; pomiar_czujnik(8); if ( (linia-100) < wynik && wynik < (linia + 100) ) c8 = 1; else c8 = 0; lcd_cls(); lcd_locate(0,0); lcd_int(c1); lcd_int(c2); lcd_int(c3); lcd_int(c4); lcd_int(c5); lcd_int(c6); lcd_int(c7); lcd_int(c8); Na LCD miałem 8 cyfr ( każda od innego czujnika ). Wgrałem program do avr położyłem roota na podłodze i miałem osiem zer, następnie położyłem na lini tak że taśma była ustawiona równolegle to linijki z czujnikami. Teoretycznie powinno pojawić się osiem jedynek, ale było ich tylko 6 ( dwa środkowe czujniki tak jakby nie wykrywały linii ). Zmieniłem wartość 850 na #define linia 750 i już ładnie działało. Na płytce mam złącze do UARTA ( koło gniazda KANDA ). Jak pierwszy raz chwyciłem w ręce avr to używałem winavr, ale nie polecam. Potem dowiedziałem się o istnieniu ECLIPSA i bardzo mi się on spodobał Jest fajny, łatwy w obsłudze i wygodnie się w nim programuje Wieczorem będę testował
  3. Zrobiłem tak jak napisałeś: /* * main.c * * Created on: 30 sty 2015 * Author: Dominik */ #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include "LCD/lcd44780.h" #include "ADC/adc.h" #define IN1 (1<<PC6) #define IN2 (1<<PC7) #define IN3 (1<<PC5) #define IN4 (1<<PC4) #define MUX_A (1<<PA1) #define MUX_B (1<<PA0) #define SET_A PORTA |= MUX_A #define CLR_A PORTA &= ~ MUX_A; #define SET_B PORTA |= MUX_B #define CLR_B PORTA &= ~ MUX_B; #define MUX_X (1<<PA3) #define MUX_Y (1<<PA2) //#define KEY (1<<PC3) #define linia 850 void silnik_L ( uint8_t kierunek, uint8_t predkosc ); void silnik_R ( uint8_t kierunek, uint8_t predkosc ); void pomiar_czujnik ( uint8_t czujnik ); void napiecie_lipol ( void ); uint16_t wynik=0; uint8_t predkosc = 45; int main(void) { // PORTC |= KEY; // podciągamy klawisz do VCC DDRC |= IN1| IN2 | IN3 | IN4; // wyjscia do sterowania silnikami DDRD |= (1<<PD4) | (1<<PD5); // wyjscia PWM DDRA |= MUX_A | MUX_B; // wejscia adresowe ( multiplekser ) - jako wyjscia lcd_init(); // inicjalizaja lcd lcd_cls(); lcd_str("start..."); _delay_ms(500); // inicjalizacja ADC ADCSRA |= (1<<ADEN); // włącz ADC ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // preskaler = 128 ADMUX |= REF_VCC; // ustawiamy wewn. źr odn. VCC // ustawienia TIMER1 w Fast PWM TCCR1A |= (1<<WGM10)|(1<<WGM11); // Fast PWM 10-bitowy TCCR1B |= (1<<WGM12); // Fast PWM 10-bitowy TCCR1A |= (1<<COM1B1)|(1<<COM1A1); // OC1A,OC1B are cleared on TOP TCCR1B |= (1<<CS10); // preskaler = 1 accu1_vol.ref_adc = 780; // zmierzona wartość ADC ( 7,4 V ) accu1_vol.ref_v = 742; // wartość mierzonego napięcia ( 7,4 V ) napiecie_lipol(); // sprawdzanie napiecia akumulatora _delay_ms ( 2000 ); lcd_cls(); uint8_t zmienna; uint8_t wartosc; float aktualna_pozycja; float roznica = 0; while(1) { zmienna = 0; wartosc = 0; aktualna_pozycja=0; roznica=0; for( uint8_t i = 1; i <9; i++ ) { pomiar_czujnik(i); if ( (linia-100) < wynik && wynik < (linia + 100) ) { zmienna++; wartosc += i-5; } } if (zmienna>0) // jesli linia jest pod ktoryms z czujnikow { aktualna_pozycja = wartosc / zmienna; roznica = (0 - aktualna_pozycja) * 12; silnik_L(0,predkosc-roznica); silnik_R(0,predkosc+roznica); } else // jesli robot wyjechal z trazy { if(aktualna_pozycja < 0) { silnik_L(0,predkosc - 20); silnik_R(0,predkosc + 20); } if(aktualna_pozycja > 0) { silnik_L(0,predkosc + 20); silnik_R(0,predkosc - 20); } } } } /* * przod => kierunek = 0 * tyl => kierunek = 1 * * predkosc w % */ void silnik_L ( uint8_t kierunek, uint8_t predkosc ) { if ( kierunek == 0 ) { PORTC |= IN3; PORTC &= ~IN4; } else if ( kierunek == 1 ) { PORTC |= IN4; PORTC &= ~IN3; } OCR1A = (1023 / 100) * predkosc; } void silnik_R ( uint8_t kierunek, uint8_t predkosc ) { if ( kierunek == 0 ) { PORTC |= IN2; PORTC &= ~IN1; } else if ( kierunek == 1 ) { PORTC |= IN1; PORTC &= ~IN2; } OCR1B = (1023 / 100) * predkosc; } void pomiar_czujnik ( uint8_t czujnik ) { switch ( czujnik ) { case 1: CLR_A; SET_B; break; // case 2: CLR_A; CLR_B; break; // case 3: SET_A; SET_B; break; // Y case 4: SET_A; CLR_B; break; // case 5: CLR_A; SET_B; break; // case 6: SET_A; CLR_B; break; // X case 7: CLR_A; CLR_B; break; // case 8: SET_A; SET_B; break; // } _delay_us(500); wynik = 0; if ( czujnik > 0 && czujnik < 5 ) wynik = pomiar( PA2 ); // dokonujemy pomiaru na PA2 if ( czujnik > 4 && czujnik < 9 ) wynik = pomiar( PA3 ); // dokonujemy pomiaru na PA3 } void napiecie_lipol ( void ) { uint16_t wynik=0; lcd_locate(0,0); lcd_str("Napiecie"); wynik = pomiar( PA7 ); // dokonujemy pomiaru na kanale PA7 get_vol( wynik, &accu1_vol ); // zamiana ADC na napięcie lcd_locate(1,1); lcd_str( accu1_vol.v1 ); // jednostki i dziesiątki zmierzonego napięcia lcd_str( "." ); lcd_str( accu1_vol.v2 ); // część ułamkowa zmierzonego napięcia lcd_str( " V "); } Robot jeździ trochę lepiej ale nadal przy małej prędkości często zjeżdża z trasy. Co jeszcze mogę zmienić? Filmik: LineFollower
  4. Jak na razie to w programie zmieniłem tylko tego delay'a, poprawiłem pętlę for i zamieniłem to: aktualna_pozycja = wartosc / zmienna; na to if (zmienna>0) aktualna_pozycja = wartosc / zmienna; Nie rozumiem tylko o co chodzi koledze booby, mógłbyś napisać trochę jaśniej? (jestem początkujący) Zauważyłem jeszcze jedno dziwne zachowanie u robota (sorry za obrazek, ale chciałem coś na szybko namalować): Załóżmy że czarna linia, to taśma po której jeździ robot, a zielone kropki to czujniki. Kilka razy trafił mi się taki przypadek, że robot skrócił sb zakręt ( czyli pojechał tak jak jest zaznaczona strzałka ) i gdy dojeżdża do czarnej linii to reaguje czujnik najbardziej wysunięty na prawo, czyli lewy silnik przyśpiesza, a prawy zwalnia co skutkuje tym że robot całkowicie odbija z trasy... :/
  5. Witam wszystkich Jest to mój pierwszy post na tym forum. Od jakiegoś czasu próbuje zaprogramować robota ( line follower ) Tu jest schemat i pcb: Napisałem taki program: main.c /* * main.c * * Created on: 30 sty 2015 * Author: Dominik */ #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include "LCD/lcd44780.h" #include "ADC/adc.h" #define IN1 (1<<PC6) #define IN2 (1<<PC7) #define IN3 (1<<PC5) #define IN4 (1<<PC4) #define MUX_A (1<<PA1) #define MUX_B (1<<PA0) #define SET_A PORTA |= MUX_A #define CLR_A PORTA &= ~ MUX_A; #define SET_B PORTA |= MUX_B #define CLR_B PORTA &= ~ MUX_B; #define MUX_X (1<<PA3) #define MUX_Y (1<<PA2) //#define KEY (1<<PC3) #define linia 850 void silnik_L ( uint8_t kierunek, uint8_t predkosc ); void silnik_R ( uint8_t kierunek, uint8_t predkosc ); void pomiar_czujnik ( uint8_t czujnik ); void napiecie_lipol ( void ); uint16_t wynik=0; uint8_t predkosc = 45; int main(void) { // PORTC |= KEY; // podciągamy klawisz do VCC DDRC |= IN1| IN2 | IN3 | IN4; // wyjscia do sterowania silnikami DDRD |= (1<<PD4) | (1<<PD5); // wyjscia PWM DDRA |= MUX_A | MUX_B; // wejscia adresowe ( multiplekser ) - jako wyjscia lcd_init(); // inicjalizaja lcd lcd_cls(); lcd_str("start..."); _delay_ms(500); // inicjalizacja ADC ADCSRA |= (1<<ADEN); // włącz ADC ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // preskaler = 128 ADMUX |= REF_VCC; // ustawiamy wewn. źr odn. VCC // ustawienia TIMER1 w Fast PWM TCCR1A |= (1<<WGM10)|(1<<WGM11); // Fast PWM 10-bitowy TCCR1B |= (1<<WGM12); // Fast PWM 10-bitowy TCCR1A |= (1<<COM1B1)|(1<<COM1A1); // OC1A,OC1B are cleared on TOP TCCR1B |= (1<<CS10); // preskaler = 1 accu1_vol.ref_adc = 780; // zmierzona wartość ADC ( 7,42 V ) accu1_vol.ref_v = 742; // wartość mierzonego napięcia ( 7,42 V ) napiecie_lipol(); // sprawdzanie napiecia akumulatora _delay_ms ( 2000 ); lcd_cls(); uint8_t zmienna; uint8_t wartosc; float aktualna_pozycja; float roznica = 0; while(1) { zmienna = 0; wartosc = 0; aktualna_pozycja=0; roznica=0; for( uint8_t i = 1; i <10; i++ ) { pomiar_czujnik(i); if ( (linia-100) < wynik && wynik < (linia + 100) ) { zmienna++; wartosc += i; } } aktualna_pozycja = wartosc / zmienna; if(aktualna_pozycja>20)aktualna_pozycja=0; // gdy wsszystkie czujniki sa nad biala roznica = (4.5 - aktualna_pozycja) * 12; // powierzchnia to zmienna aktualna poz. //ma wartosc 255 wiec ja zeruje if(aktualna_pozycja==0) roznica = 0; silnik_L(0,predkosc-roznica); silnik_R(0,predkosc+roznica); } } /* * przod => kierunek = 0 * tyl => kierunek = 1 * * predkosc w % */ void silnik_L ( uint8_t kierunek, uint8_t predkosc ) { if ( kierunek == 0 ) { PORTC |= IN3; PORTC &= ~IN4; } else if ( kierunek == 1 ) { PORTC |= IN4; PORTC &= ~IN3; } OCR1A = (1023 / 100) * predkosc; } void silnik_R ( uint8_t kierunek, uint8_t predkosc ) { if ( kierunek == 0 ) { PORTC |= IN2; PORTC &= ~IN1; } else if ( kierunek == 1 ) { PORTC |= IN1; PORTC &= ~IN2; } OCR1B = (1023 / 100) * predkosc; } void pomiar_czujnik ( uint8_t czujnik ) { switch ( czujnik ) { case 1: CLR_A; SET_B; break; // case 2: CLR_A; CLR_B; break; // case 3: SET_A; SET_B; break; // Y case 4: SET_A; CLR_B; break; // case 5: CLR_A; SET_B; break; // case 6: SET_A; CLR_B; break; // X case 7: CLR_A; CLR_B; break; // case 8: SET_A; SET_B; break; // } _delay_ms(1); wynik=0; if ( czujnik > 0 && czujnik < 5 ) wynik = pomiar( PA2 ); // dokonujemy pomiaru na PA2 if ( czujnik > 4 && czujnik < 9 ) wynik = pomiar( PA3 ); // dokonujemy pomiaru na PA3 } void napiecie_lipol ( void ) { uint16_t wynik=0; lcd_locate(0,0); lcd_str("Napiecie"); wynik = pomiar( PA7 ); // dokonujemy pomiaru na kanale PA7 get_vol( wynik, &accu1_vol ); // zamiana ADC na napięcie lcd_locate(1,1); lcd_str( accu1_vol.v1 ); // jednostki i dziesiątki zmierzonego napięcia lcd_str( "." ); lcd_str( accu1_vol.v2 ); // część ułamkowa zmierzonego napięcia lcd_str( " V "); } adc.c /* * adc.c * * Created on: 9 lut 2015 * Author: Dominik */ #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <stdlib.h> #include "adc.h" uint16_t min=1024, max, diff; // pomiar napięcia uint16_t pomiar( uint8_t kanal ) { ADMUX = (ADMUX & 0b11111000) | kanal; ADCSRA |= (1<<ADSC); // start konwersji while( ADCSRA & (1<<ADSC) ); return ADCW; } // zamiana ADC na napięcie void get_vol( uint16_t adc, TVOL * voltage ) { voltage->adc_mid = adc; uint16_t wynik = ( adc * (uint32_t)voltage->ref_v ) / voltage->ref_adc; div_t divmod = div(wynik, 100); itoa( divmod.quot, voltage->v1, 10 ); itoa( divmod.rem, voltage->v2, 10); if( divmod.rem < 10 ) { voltage->v2[0]='0'; voltage->v2[1]=divmod.rem+'0'; } voltage->v1[2]=0; voltage->v2[2]=0; } adc.h /* * adc.h * * Created on: 9 lut 2015 * Author: Dominik */ #ifndef ADC_ADC_H_ #define ADC_ADC_H_ // definicje bitów odpowiedzialnych za wybór źródła odniesienia #define REF_256 (1<<REFS1)|(1<<REFS0) #define REF_VCC (1<<REFS0) // typ strukturalny na potrzeby przeliczania napięć z ADC do stringów // v1 - część przed przecinkiem // v2 - część po przecinku typedef struct { uint16_t adc_mid; // uśredniona wartość ADC uint16_t ref_adc; // środkowy zakres wartości ADC odpowiadającej zmierzonemu niżej napięciu uint16_t ref_v; // środkowy zakres napięcia * 100 (czyli np dla 6,5V ---> 650) char v1[3]; char v2[3]; } TVOL; TVOL accu1_vol; uint16_t pomiar( uint8_t kanal ); void get_vol( uint16_t adc, TVOL * voltage ); #endif /* ADC_ADC_H_ */ Wgrałem kod do robota, ustawiłem na trasie. Robot przejeżdża 1 lub 3/4 okrążenia :/ Nie wiem czy za wolno dokonje pomiarów, czy za słabo reaguje na moment gdy robot zaczyna zjeżdżać z trasy. Proszę o pomoc.... Tak jak pisałem, siedzę już kilka dni nad kodem i nic mi nie wychodzi. Tu jest filmik jak to działa: https://www.youtube.com/watch?v=YD71L31Z6So&feature=youtu.be Z góry dzięki za pomoc
×
×
  • Utwórz nowe...