{"id":566,"date":"2014-08-22T17:53:28","date_gmt":"2014-08-22T16:53:28","guid":{"rendered":"http:\/\/ofalcao.pt\/blog\/?p=566"},"modified":"2014-08-22T17:53:28","modified_gmt":"2014-08-22T16:53:28","slug":"ad4m4st0r-o-codigo","status":"publish","type":"post","link":"https:\/\/ofalcao.pt\/blog\/2014\/ad4m4st0r-o-codigo","title":{"rendered":"AD4M4ST0R &#8211; o c\u00f3digo"},"content":{"rendered":"<div class=\"seriesmeta\">This post is part 4 of 9 of \u00a0<a href=\"https:\/\/ofalcao.pt\/blog\/series\/ad4m4st0r-um-rover-lego\" class=\"series-122\" title=\"AD4M4ST0R - um rover LEGO\">AD4M4ST0R - um rover LEGO<\/a><\/div><p>Para terminar a apresenta\u00e7\u00e3o do AD4M4ST0R faltava apenas o c\u00f3digo.<\/p>\n<p>O programa principal \u00e9 um script escrito em python &#8216;joy.py&#8217; que lida com o gamepad e os motores. O controlo da webcam e do buzzer \u00e9 delegado em dois bash scripts (&#8216;saycheese.sh&#8217; e &#8216;beep.sh&#8217;).<\/p>\n<p>O programa principal, &#8220;joy.py&#8217;:<\/p>\n<pre>import sys, traceback, os\nos.environ['SDL_VIDEODRIVER'] = 'dummy'\n\n# from math import sqrt\nfrom math import log10\nfrom subprocess import call\nfrom time import sleep\nfrom pygame import joystick, event, display\n\n### botoes ###\nB_TRIANG = 0\nB_CIRC = 1\nB_CROSS = 2\nB_SQUARE = 3\nB_LTRIG2 = 4\nB_RTRIG2 = 5\nB_LTRIG = 6\nB_RTRIG = 7\nB_SELECT = 8\nB_LJOY = 10\nB_RJOY = 11\nB_START = 9\n\n\ndef main():\n\u00a0\u00a0\u00a0 try:\n\u00a0\u00a0 \u00a0display.init();\n\u00a0\u00a0 \u00a0joystick.init();\n\u00a0\u00a0 \u00a0js=joystick.Joystick(0);\n\u00a0\u00a0 \u00a0js.init();\n\n\u00a0\u00a0 \u00a0### arranca em modo Joystick ###\n\u00a0\u00a0 \u00a0control_by_JOY=True;\n\n\u00a0\u00a0 \u00a0num_axes=js.get_numaxes();\n\u00a0\u00a0 \u00a0num_buttons=js.get_numbuttons();\n\u00a0\u00a0 \u00a0num_hats=js.get_numhats();\n\n\u00a0\u00a0 \u00a0### sabemos a priori que tem 4 axes, 13 buttons e 1 hat\n\n\u00a0\u00a0 \u00a0### inicializa motores com Duty Cycle=0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 call(\"echo 0 &gt; \/sys\/class\/tacho-motor\/tacho-motor0\/duty_cycle_sp\", shell=True);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 call(\"echo 0 &gt; \/sys\/class\/tacho-motor\/tacho-motor1\/duty_cycle_sp\", shell=True);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 call(\"echo 1 &gt; \/sys\/class\/tacho-motor\/tacho-motor0\/run\", shell=True);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 call(\"echo 1 &gt; \/sys\/class\/tacho-motor\/tacho-motor1\/run\", shell=True);\n\n\u00a0\u00a0 \u00a0flag=False;\n\n\u00a0\u00a0 \u00a0while True:\n\u00a0\u00a0 \u00a0\u00a0 x=y=motor_direito=motor_esquerdo=0.0;\n\u00a0\u00a0 \u00a0\u00a0 event.pump();\n\n\u00a0\u00a0 \u00a0\u00a0 button_mode=js.get_button(B_SELECT);\n\u00a0\u00a0 \u00a0\u00a0 button_shot=js.get_button(B_SQUARE);\n\n\u00a0\u00a0 \u00a0\u00a0 if button_mode ==1:\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 call(\".\/beep.sh\" , shell=True);\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 if control_by_JOY==True:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 control_by_JOY=False;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 print 'Control Mode=HAT';\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 else:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 control_by_JOY=True;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 print 'Control Mode=JOYSTICK';\n\n\u00a0\u00a0 \u00a0\u00a0 if button_shot==1:\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0print 'Cheese!!!';\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0call(\"\/root\/saycheese.sh\", shell=True);\n\n\n\u00a0\u00a0 \u00a0\u00a0 ### eixo dos joysticks entre -1 e +1\n\u00a0 \u00a0\u00a0 \u00a0\u00a0 ### x=axis2 , y=-axis3\n\u00a0\u00a0 \u00a0\u00a0 ### ignorar valores abaixo de 0.1 (dead zone)\n\u00a0\u00a0 \u00a0\u00a0 ### aplicar log10(100x) aos restantes (para dar enfase aos mais baixos)\n\u00a0\u00a0 \u00a0\u00a0 ### o resultado e' 0 ou 1 a 2 por isso\n\u00a0\u00a0 \u00a0\u00a0 ###\u00a0\u00a0 \u00a0multiplicar por 25 da' valores Duty Cycle nulos ou entre 25 e 50\n\n\u00a0\u00a0 \u00a0\u00a0 if control_by_JOY==True:\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # Control by Right Joystick, Axis 2 e 3\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 axis2=js.get_axis(2);\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 axis3=js.get_axis(3);\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 if axis2&gt;0:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if axis2&lt;0.1:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 x=0;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 x=log10(axis2*100);\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 elif axis2&lt;0:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if axis2&gt;-0.1:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 x=0;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 x=-log10(-axis2*100);\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 if axis3&gt;0:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if axis3&lt;0.1:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 y=0;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 y=-log10(axis3*100);\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 elif axis3&lt;0:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if axis3&gt;-0.1:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 y=0;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 y=log10(-axis3*100);\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 else:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 y=0;\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 if y&lt;&gt;0:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if x&lt;0:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_direito=50*y\/2;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # rodar para a esquerda =&gt; reduzir motor esquerdo\n\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_esquerdo=motor_direito*(1+x\/3);\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_esquerdo=50*y\/2;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # rodar para a direita =&gt; reduzir motor direito\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_direito=motor_esquerdo*(1-x\/3);\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0 elif x&lt;&gt;0:\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # y=0, apenas roda\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_esquerdo=25*x;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_direito=-motor_esquerdo;\n\n\u00a0 \u00a0\u00a0 \u00a0\u00a0 else:\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 # Control by HAT keys\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 hat=js.get_hat(0);\n\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 if hat==(0,1):\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ### anda em frente ###\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_direito=50;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_esquerdo=50;\n\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 elif hat==(1,0):\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ### roda para a direita ###\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_esquerdo=50;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_direito=-50;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 elif hat==(0,-1):\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ### recua ###\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_direito=-50;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_esquerdo=-50;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 elif hat==(-1,0):\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ### roda para a esquerda ###\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_esquerdo=-50;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_direito=50;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 elif hat==(1,1):\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ### frente e roda para a direita ###\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_esquerdo=50;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_direito=25;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 elif hat==(-1,1):\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ### frente e roda para a esquerda ###\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_esquerdo=25;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_direito=50;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 elif hat==(-1,-1):\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ### recua e roda para a esquerda ###\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_esquerdo=-50;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_direito=-25;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0 elif hat==(1,-1):\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ### recua e roda para a direita ###\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_esquerdo=-25;\n\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 motor_direito=-50;\n\n\u00a0\u00a0\u00a0 \u00a0\u00a0 comando_motordir = \"echo \" + repr(motor_direito) + \" &gt; \/sys\/class\/tacho-motor\/tacho-motor0\/duty_cycle_sp\";\n\u00a0\u00a0 \u00a0\u00a0  comando_motoresq = \"echo \" + repr(motor_esquerdo) + \" &gt; \/sys\/class\/tacho-motor\/tacho-motor1\/duty_cycle_sp\";\n\n \u00a0\u00a0 \u00a0\u00a0 call(comando_motordir, shell=True);\n\u00a0\u00a0 \u00a0\u00a0  call(comando_motoresq, shell=True);\n\n\u00a0\u00a0 \u00a0# end while\n\n\u00a0\u00a0\u00a0 except (KeyboardInterrupt, SystemExit):\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 print \"Exiting...\";\n\u00a0\u00a0\u00a0 except Exception:\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 traceback.print_exc(file=sys.stdout);\n\n\u00a0\u00a0\u00a0 call(\"echo 0 &gt; \/sys\/class\/tacho-motor\/tacho-motor0\/duty_cycle_sp\", shell=True);\n\u00a0\u00a0\u00a0 call(\"echo 0 &gt; \/sys\/class\/tacho-motor\/tacho-motor1\/duty_cycle_sp\", shell=True);\n\u00a0\u00a0\u00a0 call(\"echo 0 &gt; \/sys\/class\/tacho-motor\/tacho-motor0\/run\", shell=True);\n\u00a0\u00a0\u00a0 call(\"echo 0 &gt; \/sys\/class\/tacho-motor\/tacho-motor1\/run\", shell=True);\n\n\u00a0\u00a0\u00a0 js.quit();\n\u00a0\u00a0\u00a0 joystick.quit();\n\u00a0\u00a0\u00a0 display.quit();\n\u00a0\u00a0\u00a0 sys.exit(0);\n\nif __name__ == \"__main__\":\n\u00a0\u00a0\u00a0 main()<\/pre>\n<p>O controlo da webcam, &#8216;saycheese.sh&#8217;:<\/p>\n<pre>#!\/bin\/sh\nfilename=$(date +\"%d-%m-%y_%Hh%Mm%Ss\")\nfswebcam -d \/dev\/video0 -p MJPEG -r 640x480 -q -D 1 -S 3 -s brightness=10 -s contrast=20\u00a0 $filename.jpg<\/pre>\n<p>O controlo do buzzer, &#8216;beep.sh&#8217;:<\/p>\n<pre>#!\/bin\/bash\necho -en \"\u000007\" &gt; \/dev\/tty1<\/pre>\n<p>A quem o considerar \u00fatil, esteja \u00e0 vontade para utilizar \/ feel free to use as you wish.<\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"seriesmeta\">This post is part 4  of 9 of \u00a0<a href=\"https:\/\/ofalcao.pt\/blog\/series\/ad4m4st0r-um-rover-lego\" class=\"series-122\" title=\"AD4M4ST0R - um rover LEGO\">AD4M4ST0R - um rover LEGO<\/a><\/div><p>Para terminar a apresenta\u00e7\u00e3o do AD4M4ST0R faltava apenas o c\u00f3digo. O programa principal \u00e9 um script escrito em python &#8216;joy.py&#8217; que lida com o gamepad e os motores. O controlo da webcam e do buzzer \u00e9 delegado em dois bash scripts (&#8216;saycheese.sh&#8217; e &#8216;beep.sh&#8217;). O programa principal, &#8220;joy.py&#8217;: import sys, traceback, os os.environ[&#8216;SDL_VIDEODRIVER&#8217;] = &#8216;dummy&#8217; &hellip; <a href=\"https:\/\/ofalcao.pt\/blog\/2014\/ad4m4st0r-o-codigo\" class=\"more-link\">Continuar a ler<span class=\"screen-reader-text\"> &#8220;AD4M4ST0R &#8211; o c\u00f3digo&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[13,18,19],"tags":[36,45,223],"series":[122],"class_list":["post-566","post","type-post","status-publish","format-standard","hentry","category-ev3dev","category-lego","category-lego-mindstorms","tag-bash","tag-codigo","tag-python","series-ad4m4st0r-um-rover-lego"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2Mhyv-98","_links":{"self":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/566","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/comments?post=566"}],"version-history":[{"count":0,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/566\/revisions"}],"wp:attachment":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/media?parent=566"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/categories?post=566"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/tags?post=566"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/series?post=566"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}