{"id":1534,"date":"2019-02-01T11:24:18","date_gmt":"2019-02-01T11:24:18","guid":{"rendered":"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/?p=1534"},"modified":"2019-03-14T15:06:20","modified_gmt":"2019-03-14T15:06:20","slug":"opis-algorytmu-pd","status":"publish","type":"post","link":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/?p=1534","title":{"rendered":"Opis algorytmu PD"},"content":{"rendered":"<p>Z tego wpisu dowiesz si\u0119:<\/p>\n<ul>\n<li>Jak p\u0142ynnie pod\u0105\u017ca\u0107 za lini\u0105?<\/li>\n<li>Jak przetwarza\u0107 sygna\u0142y z czujnik\u00f3w by sterowa\u0107 szybko\u015bci\u0105 poszczeg\u00f3lnych silnik\u00f3w?<\/li>\n<li>Co to jest tzw. &#8222;p\u0119tla zwrotna&#8221;?<\/li>\n<\/ul>\n<p>A wszystko po to, by oprogramowa\u0107 Line Followera (w skr\u00f3cie LF)!<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-1564\" src=\"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_6781-300x169.jpg\" alt=\"\" width=\"300\" height=\"169\" srcset=\"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_6781-300x169.jpg 300w, https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_6781-768x432.jpg 768w, https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/01\/DSC_6781-1024x576.jpg 1024w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p><span style=\"font-weight: 400;\"><strong>Regulator PD<\/strong> to \u201cuci\u0119ta\u201d wersja regulatora PID (ang. Proportional-Integral-Derivative). Pos\u0142u\u017cy nam on do p\u0142ynnego sterowania linefollower\u2019em. Regulator ten posiada 3 cz\u0142ony:<br \/>\n<\/span><span style=\"font-weight: 400;\">liniowy (P),<br \/>\n<\/span><span style=\"font-weight: 400;\">ca\u0142kowy (I),<br \/>\nr\u00f3\u017cniczkowy (D). <\/span><\/p>\n<p><span style=\"font-weight: 400;\"><strong>Cz\u0142on P<\/strong> odpowiada za to, jak szybko silniki LF\u2019a b\u0119d\u0105 si\u0119 obraca\u0107 na podstawie po\u0142o\u017cenia linii. Je\u017celi linia b\u0119dzie po prawej stronie czujnika to robot \u201cwie\u201d, \u017ce musi skr\u0119ci\u0107 w tym kierunku i zmniejszy szybko\u015b\u0107 prawego silnika (lub zwi\u0119kszy pr\u0119dko\u015b\u0107 lewego, ale z regu\u0142y lepiej zastosowa\u0107 to pierwsze rozwi\u0105zanie). Jednak sama zale\u017cno\u015b\u0107 liniowa nie wystarcza, \u017ceby p\u0142ynnie pod\u0105\u017ca\u0107 za lini\u0105 (chyba, \u017ce bardzo powoli). \u017beby \u201cprzewidzie\u0107\u201d zmiany w kierunku ruchu i odpowiednio na nie zareagowa\u0107 przydaje si\u0119 nam <strong>cz\u0142on D regulatora<\/strong>. Jest to prosta r\u00f3\u017cnica pomi\u0119dzy poprzedni\u0105 a aktualn\u0105 pozycj\u0105 linii. W przypadku prostej linii r\u00f3\u017cnica b\u0119dzie nieznaczna, a podczas nag\u0142ej zmiany kierunku robot szybciej zmieni szybko\u015b\u0107 silnik\u00f3w. <strong>Cz\u0142on I<\/strong> pomijamy, bo nie jest on zbyt wa\u017cny w przypadku linefollower\u2019\u00f3w (z do\u015bwiadczenia).<br \/>\n<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Mo\u017ce i jest to na pocz\u0105tek troch\u0119 skomplikowane, ale implementacja jest bardzo prosta i nie wymaga zbyt wiele pisania:<\/span><span style=\"font-weight: 400;\"><br \/>\n<\/span><\/p>\n<pre class=\"lang:default decode:true\">error_P = pozycja_linii * KP; \/\/ zale\u017cno\u015b\u0107 liniowa\r\nerror_D = (pozycja_linii - poprzednia_pozycja_linii) * KD; \/\/ r\u00f3\u017cnica pomi\u0119dzy pomiarami\r\nError = error_P + error_D; \/\/ suma cz\u0142on\u00f3w regulatora\r\npoprzednia_pozycja_linii = pozycja_linii;<\/pre>\n<p><span style=\"font-weight: 400;\">Uzyskany w ten spos\u00f3b Error mo\u017cemy bezpo\u015brednio wykorzysta\u0107 do ustawienia pr\u0119dko\u015bci silnik\u00f3w. Wsp\u00f3\u0142czynniki KP i KD okre\u015blaj\u0105 jaki wp\u0142yw maj\u0105 poszczeg\u00f3lne cz\u0142ony na ruch LF\u2019a i b\u0119d\u0105 si\u0119 znacz\u0105co r\u00f3\u017cni\u0107 w zale\u017cno\u015bci od algorytmu wykrywania pozycji linii czy samej budowy robota (np. pozycji czujnika). W\u0142a\u015bnie w konkretnych warto\u015bciach KP, KD <strong>le\u017cy sekret<\/strong> dzia\u0142ania dobrego regulatora PID. \u017beby uzyska\u0107 p\u0142ynny ruch trzeba si\u0119 troch\u0119 \u201cpobawi\u0107\u201d z tymi wsp\u00f3\u0142czynnikami i znale\u017a\u0107 najlepsze warto\u015bci. Mo\u017cna znale\u017a\u0107 wiele metod strojenia takiego regulatora (np. Metoda Zieglera-Nicholsa), jednak w tym przypadku najpro\u015bciej jest to zrobi\u0107 r\u0119cznie czyli metoda pr\u00f3b i b\u0142\u0119d\u00f3w, eksperymentalnie zmieniaj\u0105c KP i KD i sprawdzaj\u0105c na torze jak to wp\u0142ywa na ruch LF.<br \/>\n<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Na pocz\u0105tku ustawiamy KD = 0, i szukamy najmniejszego KP, \u017ceby robot przy ma\u0142ej pr\u0119dko\u015bci w miar\u0119 dobrze pod\u0105\u017ca\u0142 po prostej linii lub lekkim \u0142uku. Po znalezieniu odpowiedniego KP mo\u017cemy stopniowo zwi\u0119ksza\u0107 wsp\u00f3\u0142czynnik KD i pr\u0119dko\u015b\u0107, do uzyskania p\u0142ynnego ruchu. Jako, \u017ce r\u00f3\u017cnice w pomiarach s\u0105 stosunkowo ma\u0142e w por\u00f3wnaniu do po\u0142o\u017cenia linii, cz\u0119sto nast\u0119puje zale\u017cno\u015b\u0107: KD &gt; KP.<\/span><\/p>\n<p><b>Okre\u015blanie pozycji linii, wsp\u00f3lne dzia\u0142anie 5-ciu czujnik\u00f3w<\/b><\/p>\n<p>Jak przy pomocy wielu czujek jednoznacznie okre\u015bli\u0107, gdzie znajduje si\u0119 linia? Ka\u017cda czujka zwraca tylko informacj\u0119 o ilo\u015bci odbitego \u015bwiat\u0142a (warto\u015bci od 0 do 1023). Mo\u017cna by zastosowa\u0107 algorytm kt\u00f3ry wybiera jedn\u0105 pozycj\u0119 z najwi\u0119ksz\u0105 warto\u015bci\u0105 ale prowadzi on tylko do niep\u0142ynnego ruchu. Powinni\u015bmy zastosowa\u0107 bardziej precyzyjny algorytm wykrywania linii ze \u015bredni\u0105 wa\u017con\u0105.<\/p>\n<p>Ka\u017cdemu czujnikowi przypisujemy wagi, na kt\u00f3rych postawie b\u0119dziemy okre\u015bla\u0107 pozycj\u0119 (np. -2000, -1000, 0, 1000, 2000 dla kolejnych czujek). Nast\u0119pnie czytamy warto\u015bci z czujnik\u00f3w, mno\u017cymy je razy wag\u0119 i sumujemy. Na koniec dzielimy otrzyman\u0105 warto\u015b\u0107 przez sum\u0119 warto\u015bci z czujek. W ten spos\u00f3b dok\u0142adn\u0105 informacj\u0119 nawet kiedy linia znajduje si\u0119 na granicy dw\u00f3ch czujnik\u00f3w.<\/p>\n<pre class=\"lang:default decode:true\">pozycja = (cz1*waga1+cz2*waga2+cz3*waga3+cz4*waga4+cz5*waga5)\/(cz1+cz2+cz3+cz4+cz5)<\/pre>\n<p>W przypadku zastosowania wag: -2000, -1000, 0, 1000, 2000 dla kolejnych czujnik\u00f3w, po przeliczeniu \u015bredniej wa\u017conej otrzymamy jedn\u0105 warto\u015b\u0107 od -2000 do 2000 (dla -2000 linia znajduje si\u0119 po lewej stronie, dla 0 &#8211; na \u015brodku, a dla 2000 &#8211; po prawej).<\/p>\n<p><b><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-1572 alignnone\" src=\"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/02\/line_pos-300x161.png\" alt=\"\" width=\"573\" height=\"307\" srcset=\"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/02\/line_pos-300x161.png 300w, https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/02\/line_pos.png 627w\" sizes=\"auto, (max-width: 573px) 100vw, 573px\" \/><\/b><\/p>\n<p><b>Sterowanie pr\u0119dko\u015bci\u0105 silnik\u00f3w <\/b><\/p>\n<p>Jak wykorzysta\u0107 wcze\u015bniej otrzymany Error do sterowania pr\u0119dko\u015bci\u0105 silnik\u00f3w? Do ustawienia pr\u0119dko\u015bci pojedynczego silnika u\u017cywamy sygna\u0142u PWN. B\u0119dziemy t\u0105 warto\u015b\u0107 zmienia\u0107 w zale\u017cno\u015bci od uzyskanego Error\u2019a.<\/p>\n<p>Je\u017celi warto\u015b\u0107 Error\u2019a jest ujemna to w naszym przypadku pozycja linii znajduje si\u0119 po lewej stronie LF\u2019a. Aby skorygowa\u0107 ruch b\u0119dziemy zmniejsza\u0107 pr\u0119dko\u015b\u0107 lewego silnika. Analogicznie post\u0119pujemy w przypadku dodatniej warto\u015bci:<\/p>\n<pre class=\"lang:default decode:true\">if(Error &gt; 0){\r\npwn1=maxSpeed; \/\/maxSpeed to wczesniej ustalona maksymalna warto\u015b\u0107 PWN LF\u2019a\r\npwn2=maxSpeed-Error;\r\n} else {\r\npwn1=maxSpeed+Error;\r\npwn2=maxSpeed;<\/pre>\n<p>Warto pami\u0119ta\u0107, \u017ce Error mo\u017ce by\u0107 znacznie wi\u0119kszy od warto\u015bci maxSpeed. Je\u017celi warto\u015b\u0107 nowego pwn1 lub pwn2 jest mniejsza od 0 to musimy j\u0105 ustawi\u0107 na 0 (pwn powinien wynosi\u0107 od 0 do 255). Po tych wszystkich operacjach uzyskujemy pwn\u2019y do sterowania silnikami.<\/p>\n<p>M\u00f3j LF w akcji:<\/p>\n<div style=\"width: 720px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-1534-1\" width=\"720\" height=\"405\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/02\/MOV_6780.mp4?_=1\" \/><a href=\"http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/02\/MOV_6780.mp4\">http:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/wp-content\/uploads\/sites\/6\/2019\/02\/MOV_6780.mp4<\/a><\/video><\/div>\n<p style=\"text-align: right;\">(c) Bytler, 2019<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Z tego wpisu dowiesz si\u0119: Jak p\u0142ynnie pod\u0105\u017ca\u0107 za lini\u0105? Jak przetwarza\u0107 sygna\u0142y z czujnik\u00f3w by sterowa\u0107 szybko\u015bci\u0105 poszczeg\u00f3lnych silnik\u00f3w? Co to jest tzw. &#8222;p\u0119tla zwrotna&#8221;? A wszystko po to, by oprogramowa\u0107 Line Followera (w skr\u00f3cie LF)! Regulator PD to \u201cuci\u0119ta\u201d wersja regulatora PID (ang. Proportional-Integral-Derivative). Pos\u0142u\u017cy nam on do p\u0142ynnego sterowania linefollower\u2019em. Regulator ten [&hellip;]<\/p>\n","protected":false},"author":24,"featured_media":1564,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[52],"tags":[274,273,277,275,276,40],"class_list":{"0":"post-1534","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","6":"hentry","7":"category-fibot","8":"tag-lf","9":"tag-line-folower","10":"tag-petla","11":"tag-pid","12":"tag-regulator","13":"tag-tcrt5000","15":"post-with-thumbnail","16":"post-with-thumbnail-large"},"_links":{"self":[{"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/posts\/1534","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/users\/24"}],"replies":[{"embeddable":true,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1534"}],"version-history":[{"count":9,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/posts\/1534\/revisions"}],"predecessor-version":[{"id":2284,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/posts\/1534\/revisions\/2284"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=\/wp\/v2\/media\/1564"}],"wp:attachment":[{"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1534"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1534"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/physics.uwb.edu.pl\/wf\/fi-bot\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1534"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}