{"id":780,"date":"2014-11-06T15:32:01","date_gmt":"2014-11-06T15:19:14","guid":{"rendered":"http:\/\/ofalcao.pt\/blog\/?p=780"},"modified":"2014-11-06T15:34:22","modified_gmt":"2014-11-06T15:34:22","slug":"controlo-de-sbrick-com-wiimote","status":"publish","type":"post","link":"https:\/\/ofalcao.pt\/blog\/2014\/controlo-de-sbrick-com-wiimote","title":{"rendered":"Controlo de SBrick com wiimote"},"content":{"rendered":"<p>Descobri que \u00e9 muito f\u00e1cil usar um wiimote em Linux por isso na sequ\u00eancia de &#8216;<a href=\"http:\/\/ofalcao.pt\/blog\/2014\/sbrick-controlo-remoto-com-um-gamepad\">SBrick &#8211; controlo remoto com um gamepad<\/a>&#8216; segue agora como controlar o SBrick com um wiimote (na verdade um clone barato, um <a href=\"https:\/\/www.worten.pt\/acessorio-wii-n-play-comando-remote-plus-preto.html\">N-Play Remote Plus<\/a>, comprado fora de horas numa Worten &#8211; infelizmente n\u00e3o havia a vers\u00e3o com Motion Plus).<\/p>\n<p>O wiimote usa Bluetooth, apesar de n\u00e3o seguir estritamente as normas. Se tivermos bluetooth no nosso PC podemos confirmar que estamos em condi\u00e7\u00f5es de utilizar o wiimote carregando em simult\u00e2neo nos bot\u00f5es &#8216;1&#8217; e &#8216;2&#8217; do wiimote para que este fique vis\u00edvel durante uns segundos:<\/p>\n<pre>$ hcitool -i hci0 scan\r\nScanning ...\r\n\u00a0\u00a0 \u00a004:02:16:01:1C:E7\u00a0\u00a0 \u00a0Nintendo RVL-CNT-01<\/pre>\n<p>Como n\u00e3o segue as normas n\u00e3o \u00e9 poss\u00edvel emparelhar com ele mas existem ferramentas para isso como o <a href=\"http:\/\/abstrakraft.org\/cwiid\/\">cwiid<\/a>. Como vou usar pyhton fui buscar a library correspondente:<\/p>\n<pre>$ sudo apt-get install python-cwiid<\/pre>\n<p>existem v\u00e1rios exemplos b\u00e1sicos que n\u00e3o vou apresentar aqui, sigo directamente para o resultado final:<\/p>\n<div class=\"jetpack-video-wrapper\"><iframe loading=\"lazy\" title=\"Vengit SBrick controlled with a Wiimote\" width=\"840\" height=\"473\" src=\"https:\/\/www.youtube.com\/embed\/aVT57uZQ6IQ?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/div>\n<p>&nbsp;<\/p>\n<p>O script utilizado no video acima:<\/p>\n<pre># apt-get install python-cwiid\r\nimport cwiid\r\nfrom time import sleep\r\nfrom subprocess import call\r\nfrom math import log10\r\n\r\n# macros for the SBrick\r\nDRIVE_A=\"gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0102\"\r\nDRIVE_B=\"gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0103\"\r\nCOAST_A=\"gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=01020000\"\r\nCOAST_B=\"gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=01030000\"\r\nBREAK_A=\"gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0002\"\r\nBREAK_B=\"gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0003\"\r\n\r\n\r\n# connecting to the wiimote. This allows several attempts\r\n# as first few often fail.\r\n\r\nprint 'Press 1+2 on your Wiimote now...'\r\nwm = None\r\ni=1\r\nwhile not wm:\r\n\u00a0\u00a0 \u00a0try:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0wm=cwiid.Wiimote()\r\n\u00a0\u00a0 \u00a0except RuntimeError:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (i&gt;5):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0print(\"cannot create connection\")\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0quit()\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0print \"Error opening wiimote connection\"\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0print \"attempt \" + str(i)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0i +=1\r\n\r\n#set wiimote to report button presses and accelerometer state\r\nwm.rpt_mode = cwiid.RPT_BTN | cwiid.RPT_ACC\r\n\r\n#turn on all led and ruble to show connected\r\nwm.led=15\r\nwm.rumble=True\r\nsleep(0.5)\r\nwm.rumble=False\r\nwm.led=0\r\nsleep(1.5)\r\n\r\n# roll = accelerometer[0], standby ~125\r\n# pitch = accelerometer[1], standby ~125\r\n\r\nwhile True:\r\n\u00a0\u00a0 \u00a0buttons = wm.state['buttons']\r\n\r\n\u00a0\u00a0 \u00a0#only pay attention when button '1' pressed\r\n\u00a0\u00a0 \u00a0if (buttons &amp; cwiid.BTN_1):\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0roll=(wm.state['acc'][0]-125)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pitch=(wm.state['acc'][1]-125)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (roll&lt;0):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (roll&lt;-4):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (roll&lt;-25):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0roll=-100\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0roll=-50*log10(-4*roll)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0roll=0\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (roll&gt;0):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (roll&gt;4):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (roll&gt;25):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0roll=100\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0roll=50*log10(4*roll)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0roll=0\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (pitch&gt;0):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (pitch&gt;4):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (pitch&gt;25):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pitch=100\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pitch=50*log10(4*pitch)\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pitch=0\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (pitch&lt;0):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if (pitch&lt;-4):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if(pitch&lt;-25):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pitch=-100\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pitch=-50*log10(-4*pitch)\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pitch=0\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if ((pitch&lt;&gt;0)or(roll&lt;&gt;0)):\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0roll=2.5*roll\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0pitch=2.5*pitch\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if(pitch&lt;&gt;0):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if(roll&gt;0):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0# turn right\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0motor_L=pitch\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0motor_R=-pitch-roll\/2\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0# turn left\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0motor_R=-pitch\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0motor_L=pitch+roll\/2\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0elif(roll&lt;&gt;0):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0#just rotate\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0motor_R=motor_L=roll;\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0# does nothing\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0motor_R=motor_L=0\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if((motor_R&lt;&gt;0)or(motor_L&lt;&gt;0)):\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if(motor_R&lt;0):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0duty=str(hex(int(-motor_R)))\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0command_A=DRIVE_A+\"00\"+duty[2:]\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0duty=str(hex(int(motor_R)))\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0command_A=DRIVE_A+\"01\"+duty[2:]\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0if(motor_L&lt;0):\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0duty=str(hex(int(-motor_L)))\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0command_B=DRIVE_B+\"00\"+duty[2:]\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0duty=str(hex(int(motor_L)))\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0command_B=DRIVE_B+\"01\"+duty[2:]\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0#send motors commands to SBrick\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0call(command_A, shell=True);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0call(command_B, shell=True);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0sleep(0.1)\r\n\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0#send COAST commands to SBrick\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0call(COAST_A, shell=True);\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0call(COAST_B, shell=True);\r\n\r\n\u00a0\u00a0 \u00a0else:\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0# inactive\r\n\u00a0\u00a0 \u00a0\u00a0\u00a0 \u00a0sleep(0.01)<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Descobri que \u00e9 muito f\u00e1cil usar um wiimote em Linux por isso na sequ\u00eancia de &#8216;SBrick &#8211; controlo remoto com um gamepad&#8216; segue agora como controlar o SBrick com um wiimote (na verdade um clone barato, um N-Play Remote Plus, comprado fora de horas numa Worten &#8211; infelizmente n\u00e3o havia a vers\u00e3o com Motion Plus). &hellip; <a href=\"https:\/\/ofalcao.pt\/blog\/2014\/controlo-de-sbrick-com-wiimote\" class=\"more-link\">Continuar a ler<span class=\"screen-reader-text\"> &#8220;Controlo de SBrick com wiimote&#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":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[16,18,20,26],"tags":[162,163,164,165,166,167],"series":[],"class_list":["post-780","post","type-post","status-publish","format-standard","hentry","category-geek","category-lego","category-linux","category-ubuntu","tag-ble-pt","tag-bluetooth-pt","tag-power-functions-pt","tag-python-pt","tag-sbrick-pt","tag-wiimote-pt"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2Mhyv-cA","_links":{"self":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/780","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=780"}],"version-history":[{"count":0,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/780\/revisions"}],"wp:attachment":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/media?parent=780"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/categories?post=780"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/tags?post=780"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/series?post=780"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}