Skocz do zawartości

LineFollower kąt prosty


Szuszy

Pomocna odpowiedź

Mam ten sam problem, tylko nie koniecznie podczas kąta prostego ale podczas ostrego zakrętu.

Chodzi mi o program na If'ach, 8 czujników(2 na linii podczas jazdy prosto), Atmega32.

                                                'pomijając typ i taktowanie
Config Porta = Input                             'do 8 pinów portu a podczepione są czujniki(od lewej pina.0 -> pina.1 -> pina.2 ->...)
Confug Portb= Output
Config Portc = Input
Config Portd = Output
Do
    If Pina.4 = 0 And Pina.5 = 0 Then           'jeżeli środkowe czujniki=0
    Pinb.3 = 1 And Pinb.4 = 1 And               'silnik l=1
    Pind.6 = 1 And Pind.7 = 1                   'silnik p=1

    If Pina.0 = 1 And Pina.1 = 1 And Pina.2 = 1
    And Pina.3 = 1 And Pina.4 = 0 And Pina.5 = 0
    And Pina.6 = 0 And Pina.7 = 0 Then
    Pinb.3 = 1 And Pinb.4 = 1                   'silnik l=1
    And Pind.6 = 0 And Pind.7 = 0               'silnik p=0 
        'Jeszcze dużo różnych wersji...  :roll: 
 End If
Loop Until Pinc.0 = 1                            'dopóki przycisk nie wciśnięty
Link do komentarza
Share on other sites

Przecież koledzy wyżej napisali.

Musi to wyglądać tak:

1.Masz zmienną ostatnipomiar;

2.Badasz stan pinów odpowiadających za czujniki (robisz z nich jedną zmienną typu obecnypomiar = pina.4<<7 + pina.5<<6 itd (ustawiasz czujniki od lewej do prawej na poszczególnych bitach. Nie wiem czy bascom ma <

3.Teraz sprawdzasz czy po odczytaniu czujników zmienna obecnypomiar==0. Jak tak to ignorujesz jej wartość. Jak jest rózna od zera to ostatnipomiar=obecnypomiar.

4.Dokonujesz analizy gdzie skręcać według zmiennej ostatnipomiar.

W tej sposób jak ostatnim "ruchem" robota będzie widzenie linii po prawej stronie to robot będzie podążał w prawo tak długo aż ponownie na nią nie trafi itd.

Jedna jednak uwaga, że taki algorytm aż prosi się o regulator PID, który jest bardzo dobrze opisany i ogólnie prosty do użycia.

Link do komentarza
Share on other sites

Mam identyczny problem. Tylko troche mój program różni się od kolegów wyżej. Robot jeździ jak ta lala po obłych trasach nawet szybko, ale jak natknie się na ostrzejszy zakręt lub kąt prosty to przestrzela. Robi ruch, a w zasadzie takie wzdrygnięcie w lewo/prawo, po czym pojedzie dalej prosto. Starałem się go zaprogramować tak, żeby na trasę wrócił w ten sposób:

Jeśli widzi 3 czujnikami (kąt prosty) to skręć, ale jeśli żaden czujnik nie widzi to skręć w odpowiednią stronę dopóki czujnik środkowy nie znajdzie się na linii.

Średnio znam się na Bascomie, więc próbowałem to robić na niezliczoną już ilość sposobów, m.in. tak:

Do
  Gosub Pomiar

  If C1 > Reakcja And C2 > Reakcja And C3 > Reakcja And C4 > Reakcja And C5 > Reakcja Then
  Gosub Prosto

  Elseif C1 > Reakcja And C2 > Reakcja And C3 > Reakcja Then
  Gosub Lewo_sk

  ...

Loop

...

Lewo_sk:
Do
Pwm1a = 0
Pwm1b = 220
Loop Until C3 < Reakcja ' Reakcja to odpowiednia stała zadeklarowana wcześniej, tutaj 550
Return

...

Niestety to i wiele innych sposobów nie działa...

Procek to mega8 wykręcona na 8MHz na wewnętrznym oscylatorze. Czujniki w ilości 5 szt. ustawione w linii prostej co już wydaje mi się sporym błędem konstrukcyjnym. Robot w założeniu ma jeździć z prędkością 0,6-0,7 [m/s], ale coś czarno to widze. Jestem pod wrażeniem tego jak kąty proste pokonuje robot Zajwaq kolegi Zaja.

Bardzo bym prosił o jakąś podpowiedź, bo moje nerwy już tego powoli nie wytrzymują. Siedze nad tym programem już chyba z tydzień i dalej nie działa jak trzeba...

Link do komentarza
Share on other sites

Problemy macie przez to w jaki sposób wykrywacie położenie robota. Radzę zainteresować się case'ami. Poniżej wklejam większość kodu na jakim jeździłem Feniksem, na zawodach rok temu 😉

Teraz robię to całkiem inaczej, bo to co używałem jest z mojego punkty widzenia w tej chwili jakąś masakrą i pomyłką, ale skoro utknęliście tylko na if'ach to i tak powinno Wam to pomóc 😉

Wykroiłem tylko zbędne kawałki kodu i deklaracje. Procedury sterujące silnikami działały tak, że gdy w nawisie była wartość >0 to silnik był sterowany na jazdę do przodu z zadaną prędkością, w przeciwnym wypadku kręcił się on do tyłu z odpowiednią prędkością.

Do
  'Odczytywanie stanów z czujników
  Czujniki(1) = Getadc(4)
  Czujniki(2) = Getadc(0)
  Czujniki(3) = Getadc(1)
  Czujniki(4) = Getadc(2)
  Czujniki(5) = Getadc(3)
  Czujniki(6) = Getadc(5)
  Czujniki(7) = Getadc(6)
  Czujniki(8) = Getadc(7)

  'Ustawianie flagi linii
  If Czujniki(1) > Granica Then Set Flagalinii.0 Else Reset Flagalinii.0
  If Czujniki(2) > Granica Then Set Flagalinii.7 Else Reset Flagalinii.7
  If Czujniki(3) > Granica Then Set Flagalinii.6 Else Reset Flagalinii.6
  If Czujniki(4) > Granica Then Set Flagalinii.5 Else Reset Flagalinii.5
  If Czujniki(5) > Granica Then Set Flagalinii.4 Else Reset Flagalinii.4
  If Czujniki(6) > Granica Then Set Flagalinii.3 Else Reset Flagalinii.3
  If Czujniki(7) > Granica Then Set Flagalinii.2 Else Reset Flagalinii.2
  If Czujniki(8) > Granica Then Set Flagalinii.1 Else Reset Flagalinii.1


  If Flagalinii = 0 Then

     If Last >= 32 Then       'Jeśli ostatnio widziana była po lewej
        Call P_silnik(255)
        Call L_silnik( -120)
     End If

     If Last < 31 Then       'Jeśli ostatnio widziana była po prawej
        Call P_silnik( -120)
        Call L_silnik(255)
     End If

  Else       'Jeśli Robot na linii
     Last = Flagalinii       'Zapisz aktualny stan czujników do kopii

  Select Case Flagalinii
   Case &B10000000
     Call P_silnik(255)
     Call L_silnik( -100)
   Case &B11000000
     Call P_silnik(255)
     Call L_silnik( -70)
   Case &B01000000
     Call P_silnik(250)
     Call L_silnik( -60)
   Case &B01100000
     Call P_silnik(250)
     Call L_silnik(50)
   Case &B00100000
     Call P_silnik(240)
     Call L_silnik(100)
   Case &B00110000
     Call P_silnik(230)
     Call L_silnik(220)

   Case &B00010000
     Call P_silnik(250)
     Call L_silnik(250)

   Case &B00011000
     Call P_silnik(220)
     Call L_silnik(230)
   Case &B00001000
     Call P_silnik(100)
     Call L_silnik(240)
   Case &B00001100
     Call P_silnik(50)
     Call L_silnik(250)
   Case &B00000100
     Call P_silnik( -60)
     Call L_silnik(250)
   Case &B00000110
     Call P_silnik( -70)
     Call L_silnik(255)
   Case &B00000010
     Call P_silnik( -100)
     Call L_silnik(255)



   Case &B00010001
     Call P_silnik(255)
     Call L_silnik(255)
   Case Else       'Jeśli stan czujników nie rozpoznany

   If Flagalinii <> 0 Then       'Jeśli pod czujnikami jest "coś"
     If Flagalinii >= 32 Then       'Jeśli "to coś" jest bardziej po lewej
        Call P_silnik(255)
        Call L_silnik( -180)
        Waitms 5
     End If

     If Flagalinii < 31 Then       'Jeśli to "to coś" jest bardziej po prawej
        Call P_silnik( -180)
        Call L_silnik(255)
        Waitms 5
     End If
   End If       'Koniec wykrywnia nieznanego wzorou pod czujnikami

  End Select

End If
Loop

End       'koniec programu głównego

Raz jeszcze podkreślam, że powyższy kod nie jest żadnym ideałem i raczej proponowałbym traktować go jako ciekawostkę, bo nie warto się na nim wzorować. Sam sposób określania pozycji robota jest już na Diodzie dobrze opisany w kilku tematach 😉

  • Lubię! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

LineFollower kąt prosty

To akurat proste pytanie, jeżeli musisz skręcić o 90° to odpowiednim silnikiem robisz całą moc wstecz, a jego kolegą całą moc do przodu, wtedy obrócisz się w miejscu jak czołg.

Chodzi tu o program. Co zrobić żeby LF wykonał poprzednią czynność "gdy straci linie" podczas zakrętu

Zbudować algorytm oparty o kolejkowanie poleceń. znaczy sie chodzi o to żeby w jakieś tablicy działającej jak kolejka FIFO pamiętać ostatnie wykonaną czynność np 100 poleceń, aby w razie potrzeby można się do niej wrócić (oczywiści po odwróceniu jej).

Inna metoda to po utracie linii zatrzymać się i spróbować zrobić pełne koło (ale nie w miejscu), o kierunku obrotu na jaki wskazują ostatnio wykonane czynności, wtedy istnieje prawdopodobieństwo że w promieniu tego koła znajdzie się ponownie szukana linia toru przejazdu.

Link do komentarza
Share on other sites

To akurat proste pytanie, jeżeli musisz skręcić o 90° to odpowiednim silnikiem robisz całą moc wstecz, a jego kolegą całą moc do przodu, wtedy obrócisz się w miejscu jak czołg.

Problemem tutaj jest wykrycie tego kąta prostego, bo nie można tego łatwo w if'ach samych zapisać - mówię to z praktyki.

Zbudować algorytm oparty o kolejkowanie poleceń. znaczy sie chodzi o to żeby w jakieś tablicy działającej jak kolejka FIFO pamiętać ostatnie wykonaną czynność np 100 poleceń, aby w razie potrzeby można się do niej wrócić (oczywiści po odwróceniu jej).

W FTL całkowicie wystarcza zapamiętanie ostatniego poprawnego odczytu. Tak jak mam w tym moim kodzie, aktualna flaga staje się poprzednią na końcu pętli tylko, gdy ta nowo zmierzona nie jest pusta - bo taka i tak nam nic nie pomoże.

Link do komentarza
Share on other sites

Problemem tutaj jest wykrycie tego kąta prostego, bo nie można tego łatwo w if'ach samych zapisać - mówię to z praktyki.

Zgadzam się w pełni. Druga lekcja programowania w mojej szkole (chodziłem do liceum informatycznego gdzie był przedmiot JIMP "Języki i metody programowania").

Jeden IF jest czasami niezbędny. Dwa to już dużo. 10 to grzech ciężki programisty.

Ogólnie takie rzeczy lepiej robić na tablicach, które działają jako macierze do transkodowania danych wejściowych na wyjściowe.

'*    Mega8 Line Fllower Logic matrix Beta test    *' 
'* Ogólna idea sterowania za pomocą tablicy wzorca *' 
$regfile = "m8def.dat" 

Config Portc = Input 
Config Portb = Output 
Config Portd = Output 

Dim Czujniki As Byte 
Dim Temp As Byte 

Set Portb.1 
Set Portb.2 
Do 
 Czujniki = Portc            'odczytujemy czujniki 
 Shift Czujniki , Left , 3   ' składamy to do kupy, aby zadresowac pamięć wzorca 
 Czujniki = Czujniki And &B00000111  'korekta aby nie zaadresować przypadkiem czegoś więcej niż chcemy. 
 Readeeprom Temp , Czujniki  'odczytujemy dane sterujace z tablicy wzorca 
 Portc = Temp                ' i wysyłamy do mostka sterujacego silnikiem. 
 Waitms 5                    ' chwila zwłoki, niech też silnik zdąży ruszyć z miejsca 
Loop 
' Pamieć wzorca sterujacego. 
$eeprom 
Data &B00000010               'poz 1 z 8 np. ostro w lewo 
Data &B00000010               'poz 2 z 8 
Data &B00001010               'poz 3 z 8 itd do 8. 

Zero IFów, przy czym jest to idea bez PWMa, ale tablica może równie dobrze przechowywać dane dla lewego i prawego PWMa.

Link do komentarza
Share on other sites

Dzięki za podpowiedzi, już jest lepiej, ale dalej nie jestem zadowolony z efektu. Spróbuję oprzeć swój program o switch-casy, może rzeczywiście będzie lepiej. Metoda wprowadzenia zmiennej przez KD rzeczywiście się sprawdza. Problemem może być u mnie także wariujący prawy skrajny czujnik, który to po najechaniu na linie każe skręcać raz w prawo, ale niestety częściej w... lewo i wtedy robot ucieka mi z trasy. Mam jeszcze kilka w zapasie, to wymienię.

Link do komentarza
Share on other sites

Przemyślę całą sprawę.

Jak ustawić i zapisać że przy jakiejś wartości poszczególnych czujników PWM dla poszczególnych silników będzie takie jak chcemy? To (tak mi się wydaję) zły zapis:

Case &B10000000
     Call P_silnik(255)
     Call L_silnik( -100) 
Link do komentarza
Share on other sites

To nie jest zły zapis, tylko Treker nie podał całego kodu, a pętlę główną programu.

A powiedzcie ile macie tych czujników 6, 8 więcej ???

__________

Komentarz dodany przez: Treker

TrEker 😋

A no faktycznie już poprawiłem.

Link do komentarza
Share on other sites

Teraz to najczęściej spotyka się roboty z czujnikami w ilości 8-16, ale gdy ktoś chce się za to zabrać na poważnie to zostaje już tylko PID, w którym nie ma takich problemów jak z if'ami i case'ami 😉 Trzeba tylko dobrze dobrać nastawy PID'a.

Link do komentarza
Share on other sites

Przecież to zwykła procedura...

U mnie za jeden silnik odpowiada taka konstrukcja:

'Prawy silnik do przodu

Sub P_silnik(byval Szybkosc As Integer)
  If Szybkosc > 0 Then
  In1 = 1
  In2 = 0
  Pwm1a = Szybkosc
  End If

  If Szybkosc < 0 Then
  In1 = 0
  In2 = 1
  Szybkosc = Abs(szybkosc)
  Pwm1a = Szybkosc
  End If

  If Szybkosc = 0 Then
  In1 = 0
  In2 = 0
  Pwm1a = 0
  End If
End Sub

Tak, wiem że można to napisać na jednym if'ie mniej 😉

Link do komentarza
Share on other sites

Mam takie pytanie przepisałem program użytkownika szuszy tak by było na Atmega8 i jest jak kompiluję wyskakuje error a nawet kilka teraz spróbowałem skompilować oryginalną wersję i też wyskakuje error. Pomoże ktoś?

$regfile = "m8def.dat"                                      ' Typ procesora ( ATMEGA 8 )
$crystal = 1000000                                          'Taktowanie procesora ( 1Mhz )

Config Portc = Output
Config Portd = Input

Portc = &B0000000
Portd = &B00000000


Motor_lp Alias Portc.0
Motor_lt Alias Portc.1
Motor_pp Alias Portc.2
Motor_pt Alias Portc.3
Sensor_prawy Alias Pind.0
Sensor_srodkowy Alias Pind.1
Sensor_lewy Alias Pind.2


Do
  If Sensor_lewy = 0 And Sensor_srodkowy = 1 And Sensor_prawy = 0 Then       'go along
     Gosub Go

   Elseif Sensor_lewy = 0 And Sensor_srodkowy = 1 And Sensor_prawy = 1 Then       'turn left
     Zmienna = 0
     Gosub Lewt

   Elseif Sensor_lewy = 0 And Sensor_srodkowy = 0 And Sensor_prawy = 1 Then       'turn left
     Gosub Lewt


   Elseif Sensor_lewy = 1 And Sensor_srodkowy = 1 And Sensor_prawy = 0 Then       'turn right
     Zmienna = 1
     Gosub Righ

   Elseif Sensor_lewy = 1 And Sensor_srodkowy = 0 And Sensor_prawy = 0 Then       'turn right
     Gosub Righ

    Elseif Sensor_lewy = 0 And Sensor_srodkowy = 0 And Sensor_prawy = 0 Then
     If Zmienna = 1 Then
     Gosub Righ
     Else
     Gosub Lewt



  End If
Loop


Go:
Motor_lt = 1
Motor_pt = 1
Return
Lewt:
Motor_lt = 0
Motor_pt = 1

Return
Righ:
Motor_lt = 1
Motor_pt = 0

Return
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.