{"id":710,"date":"2015-11-19T20:54:37","date_gmt":"2015-11-19T19:54:37","guid":{"rendered":"http:\/\/heppg.de\/ikg\/wordpress\/?p=710"},"modified":"2017-01-22T19:36:08","modified_gmt":"2017-01-22T18:36:08","slug":"gpio-comparison","status":"publish","type":"post","link":"https:\/\/heppg.de\/ikg\/wordpress\/?p=710","title":{"rendered":"gpioServer and scratchClient performance comparison for stepper driving signals"},"content":{"rendered":"<p>GPIO performance on raspberry pi is an often discussed topic.<\/p>\n<p>New scratch uses a build in gpioServer, other options are scratchClient.<br \/>\nEspecially stepper motors need quite high pulse rate, so I have set up a test harness for a small stepper with 2ms step width. The scenario are<\/p>\n<ul>\n<li>a DMA pulse driven approach<\/li>\n<li>a python program<\/li>\n<li>scratch, using scratchClient<\/li>\n<li>scratch, using GPIOserver<\/li>\n<\/ul>\n<p>The main focus is on performance of scratch to GPIO.<br \/>\nFor scratchClient, some bottleneck analysis is performed.<\/p>\n<h3>DMA created pulses<\/h3>\n<p>As expected, DMA pulse widths are precise. The glitch on third line is due to a limitation in my modified RPIO.PWM-library which does not yet allow impulse roll over. The interval time printed on the image is for four steps and precise 8ms.<\/p>\n<p><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/dma.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-720\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/dma.png\" alt=\"dma\" width=\"253\" height=\"100\" \/><\/a><\/p>\n<p><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/impulse.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-711 size-full\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/impulse.png\" alt=\"dma-impulse\" width=\"740\" height=\"212\" \/><\/a><\/p>\n<p>This DMA approach is listed for reference only, as it is not easily controllable from scratch. It is either on or off, but number of pulses can&#8217;t be determined.<\/p>\n<h3>python created pulses<\/h3>\n<p>python code is also pretty good. Pulse with is exceeding the expected 8ms by 0.5ms, which could quite easily compensated by some more advanced time handling.<\/p>\n<p><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/python1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-721\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/python1.png\" alt=\"python\" width=\"253\" height=\"100\" \/><\/a><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/python.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-712 size-full\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/python.png\" alt=\"python\" width=\"744\" height=\"213\" \/><\/a><\/p>\n<h3>scratch and scratchClient<\/h3>\n<p>The scratchClient approach is expected to be slower. Time scale is changed for this chart and the result is 326ms for 4 steps, which is 40 times slower than python or DMA.<\/p>\n<p><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/scratch_variables_scratchClient.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-726\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/scratch_variables_scratchClient.png\" alt=\"scratch_variables_scratchClient\" width=\"475\" height=\"100\" \/><\/a><\/p>\n<p><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/scratchclient.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-713\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/scratchclient.png\" alt=\"scratchclient\" width=\"756\" height=\"211\" \/><\/a><\/p>\n<h3>scratch with gpioserver<\/h3>\n<p>GPIOserver, build in into scratch, is finally at 101ms, three times faster than scratch with scratchClient, only 12 times slower than python. The assymmetric pulses are due to to &#8216;forever loop&#8217;, I suppose.<\/p>\n<p><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/scratch_gpioserver.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-723\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/scratch_gpioserver.png\" alt=\"scratch_gpioserver\" width=\"383\" height=\"100\" \/><\/a><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/gpioserver1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-718 size-full\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/gpioserver1.png\" alt=\"gpioserver\" width=\"740\" height=\"211\" \/><\/a><\/p>\n<p>All of the measurements have been taken on a RPI2, Model B, raspbian &#8216;jessie&#8217;, scratch is 2015-11-11.<br \/>\nPython is 2.7, the DMA code is a modified RPIO.PWM, adjusted for PI2.<\/p>\n<h3>scratchClient bottleneck analysis<\/h3>\n<p>The result for scratchClient was unexpectedly bad. So I have set up some tests to find out where the bottleneck is located.<\/p>\n<p><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/scratch_broadcast_scratchClient.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-724\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/scratch_broadcast_scratchClient.png\" alt=\"scratch_broadcast_scratchClient\" width=\"475\" height=\"100\" \/><\/a><\/p>\n<p>First approach was to change the variable based communication to the stepper module by an event based &#8216;broadcast&#8217;. This approach resulted in 101ms cycle time, a good match to the result from GPIOserver.<\/p>\n<p>Second approach was to write a small python code which simulates scratch: a socket server for port 42001, sending out sensor updates like &#8220;sensor-update &#8220;br0.0&#8221; 0 &#8220;.<\/p>\n<p><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/python_variables_scratchClient1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-725\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/python_variables_scratchClient1.png\" alt=\"python_variables_scratchClient\" width=\"475\" height=\"100\" \/><\/a><\/p>\n<p><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/python_scratchclient.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-728\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2015\/11\/python_scratchclient.png\" alt=\"python_scratchclient\" width=\"741\" height=\"211\" \/><\/a><\/p>\n<p>The delay time was 2ms, and the result from this is a cycle time of 9ms. Pretty close to the pure python approach.<br \/>\nFrom these results it is clear that the bottleneck is on scratch side. Looks as if scratch variable access and sending them out is three times slower than sending out broadcasts from scratch.<br \/>\nSocket communication imposes some overhead, but is not limiting performance.<\/p>\n<p>See also <a href=\"http:\/\/heppg.de\/ikg\/wordpress\/?p=884\">scratch performance 2, gpioserver reaction time<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>GPIO performance on raspberry pi is an often discussed topic. New scratch uses a build in gpioServer, other options are scratchClient. Especially stepper motors need quite high pulse rate, so I have set up a test harness for a small stepper with 2ms step width. The scenario are a DMA pulse driven approach a python [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,3],"tags":[],"class_list":["post-710","post","type-post","status-publish","format-standard","hentry","category-scratch","category-scratchclient"],"_links":{"self":[{"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/710","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=710"}],"version-history":[{"count":9,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/710\/revisions"}],"predecessor-version":[{"id":889,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/710\/revisions\/889"}],"wp:attachment":[{"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=710"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=710"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=710"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}