{"id":942,"date":"2016-08-12T16:04:59","date_gmt":"2016-08-12T15:04:59","guid":{"rendered":"http:\/\/ofalcao.pt\/blog\/?p=942"},"modified":"2016-08-12T16:04:59","modified_gmt":"2016-08-12T15:04:59","slug":"ev3dev-using-irlink-with-python","status":"publish","type":"post","link":"https:\/\/ofalcao.pt\/blog\/2016\/ev3dev-using-irlink-with-python","title":{"rendered":"ev3dev &#8211; using IRLink with python"},"content":{"rendered":"<p>I got myself a <a href=\"http:\/\/www.hitechnic.com\/cgi-bin\/commerce.cgi?preadd=action&amp;key=nil1046\">HiTechnic IRLink<\/a> sensor.<\/p>\n<p>As of today (August 2016) ev3dev already recognizes the IRLink as a nxt-i2c sensor but there&#8217;s no language support for it. David Lechner <a href=\"https:\/\/github.com\/ev3dev\/ev3dev\/issues\/719\">suggested me<\/a> using the &#8220;direct&#8221; attribute to communicate directly with the IRLink at I2C level.<\/p>\n<p>Last time I wrote something mildly related to I2C was about 20 years ago for a Microchip PIC project but well&#8230; why not?<\/p>\n<p>So after lots of trial and error, reading several times the <a href=\"http:\/\/www.philohome.com\/pf\/LEGO_Power_Functions_RC_v120.pdf\">LEGO Power Functions RC Protocol<\/a> and shamelessly copying code from Mike Hatton (&#8220;Parax&#8221;), Xander Soldaat and Lawrie Griffiths I found on GitHub, RobotC forum and LeJOS forum I fanally managed to control a PF motor in ComboPWM mode.<\/p>\n<p>In the following video, I&#8217;m increasing the motor speed (all 7 steps) then decreasing it again until it stops:<\/p>\n<div class=\"jetpack-video-wrapper\"><iframe loading=\"lazy\" title=\"ev3dev - using IRLink with python\" width=\"840\" height=\"473\" src=\"https:\/\/www.youtube.com\/embed\/EjuZp0i1FB8?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>This is the python script running in the EV3:<\/p>\n<pre>#!\/usr\/bin\/python\r\n\r\n#\r\n# based mainly on RobotC code from Mike Hatton (\"Parax\") and Xander Soldaat\r\n# but also on LeJOS code from Lawrie Griffiths\r\n#\r\n\r\n# assumes IRLink at Input 1 as sensor0\r\n\r\nimport sys\r\nfrom time import sleep\r\n\r\n# channel: 0..3\r\n# motorA, motorB: 0..7\r\n\r\nchannel = 0\r\nfor motorA in (1,1,2,2,3,3,4,4,5,5,6,6,7,7,6,6,5,5,4,4,3,3,2,2,1,1,0,0):\r\n\r\n\u00a0 motorB = motorA\r\n\r\n\u00a0 iBufferSize=2\r\n\u00a0 iBuffer = bytearray(iBufferSize)\r\n\r\n\u00a0 iBuffer[0] = ((0x04 | channel) &lt;&lt; 4) | motorB\r\n\u00a0 iBuffer[1] = motorA &lt;&lt; 4\r\n\u00a0 check = 0xF ^ (0x04 | channel) ^ motorB ^ motorA\r\n\u00a0 iBuffer[1] = iBuffer[1] | check\r\n\r\n\u00a0 oBufferSize=14\r\n\u00a0 oBuffer = bytearray(oBufferSize)\r\n\r\n\u00a0 # clear all positions\r\n\u00a0 for i in range (0,oBufferSize):\r\n\u00a0\u00a0\u00a0 oBuffer[i]=0\r\n\r\n\u00a0 oBuffer[0]=0x80\u00a0\u00a0\u00a0 # Start Bit\r\n\r\n\u00a0 oBufferIdx = 0\r\n\r\n\u00a0 for iBufferByte in range (0,2):\r\n\u00a0\u00a0\u00a0 for iBufferIdx in range (0,8):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 oBuffer[1 + (oBufferIdx \/ 8)] |= (0x80 &gt;&gt; (oBufferIdx % 8) )\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 if ( ( ( iBuffer[iBufferByte] ) &amp; (0x80 &gt;&gt; (iBufferIdx % 8) ) ) != 0 ) :\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 oBufferIdx = oBufferIdx + 6\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 else:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 oBufferIdx = oBufferIdx + 3\r\n\r\n# Stop bit\r\n\u00a0 oBuffer[1+ (oBufferIdx \/ 8)] |= (0x80 &gt;&gt; (oBufferIdx % 8) )\r\n\r\n\u00a0 tailIdx = 1 + (oBufferIdx \/ 8) + 1\r\n\r\n\u00a0 # Tail\r\n\r\n\r\n\u00a0 if (tailIdx == 10):\r\n\u00a0\u00a0\u00a0 oBuffer[tailIdx]= 0x10 # IRLink message payload length\r\n\u00a0\u00a0\u00a0 register = 0x43\r\n\u00a0 else:\r\n\u00a0\u00a0\u00a0 oBuffer[tailIdx]= 0x11\r\n\u00a0\u00a0\u00a0 register = 0x42\r\n\r\n\u00a0 oBuffer[tailIdx+1]= 0x02 # IRLink in Power Functions Mode\r\n\u00a0 oBuffer[tailIdx+2]= 0x01 # IRLInk Start transmission \r\n\r\n\r\n# clear IRLink (not sure if correct but seems to improve)\r\n\r\n\u00a0 fd = open(\"\/sys\/class\/lego-sensor\/sensor0\/direct\", 'wb',0)\r\n\u00a0 fd.seek(0x41)\r\n\u00a0 fd.write(chr(0x46))\r\n\u00a0 fd.write(chr(0x44))\r\n\u00a0 fd.write(chr(0x4C))\r\n\u00a0 fd.write(chr(0x50))\r\n\u00a0 fd.close()\r\n\u00a0 sleep(0.1)\r\n\r\n\u00a0 for i in range(0,5):\r\n\u00a0\u00a0\u00a0 fd = open(\"\/sys\/class\/lego-sensor\/sensor0\/direct\", 'wb',0)\r\n\u00a0\u00a0\u00a0 fd.seek(register)\r\n\u00a0\u00a0\u00a0 for oBufferIdx in range (0,oBufferSize):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 fd.write(chr(oBuffer[oBufferIdx]))\r\n\u00a0\u00a0\u00a0 fd.close()\r\n\r\n\u00a0\u00a0\u00a0 # Power Functions timings (for a 5-command burst)\r\n\u00a0\u00a0\u00a0 if (i==1):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 sleep(0.064)\r\n\u00a0\u00a0\u00a0 elif (i==5):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 sleep(0.096)\r\n\u00a0\u00a0\u00a0 else:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 sleep(0.080)<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I got myself a HiTechnic IRLink sensor. As of today (August 2016) ev3dev already recognizes the IRLink as a nxt-i2c sensor but there&#8217;s no language support for it. David Lechner suggested me using the &#8220;direct&#8221; attribute to communicate directly with the IRLink at I2C level. Last time I wrote something mildly related to I2C was &hellip; <a href=\"https:\/\/ofalcao.pt\/blog\/2016\/ev3dev-using-irlink-with-python\" class=\"more-link\">Continuar a ler<span class=\"screen-reader-text\"> &#8220;ev3dev &#8211; using IRLink with python&#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":[157,13,18,154,158,19,98],"tags":[274,149],"series":[],"class_list":["post-942","post","type-post","status-publish","format-standard","hentry","category-ev3dev-en","category-ev3dev","category-lego","category-lego-en","category-lego-mindstorms-en","category-lego-mindstorms","category-python","tag-irlink","tag-power-functions-en"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2Mhyv-fc","_links":{"self":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/942","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=942"}],"version-history":[{"count":0,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/posts\/942\/revisions"}],"wp:attachment":[{"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/media?parent=942"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/categories?post=942"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/tags?post=942"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/ofalcao.pt\/blog\/wp-json\/wp\/v2\/series?post=942"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}