{"id":121,"date":"2012-03-08T01:37:07","date_gmt":"2012-03-08T06:37:07","guid":{"rendered":"http:\/\/sunapi386.ca\/wordpress\/?p=121"},"modified":"2013-03-05T11:19:29","modified_gmt":"2013-03-05T16:19:29","slug":"serial-programming-python-tutorial","status":"publish","type":"post","link":"https:\/\/sunapi386.ca\/wordpress\/serial-programming-python-tutorial\/","title":{"rendered":"Python Tutorial to serial programming"},"content":{"rendered":"<h2><strong>Python Tutorial<\/strong><\/h2>\n<blockquote><p>Edit Jan 29 2013: This site has gained some significant traffic, according to google. If you search &#8220;pyserial tutorial&#8221; this page is 3rd up. So hence I will edit and make it a bit more understandable, seems like there is actually a need for this!<\/p><\/blockquote>\n<p>This tutorial describes the process of connecting to a spectrometer over serial port, and writing a python program to automate collection of data. Normally we would need to enter in the wavelength and\u00a0acquire\u00a0the (transmittance\/absorbency\/concentration) result manually. Since the spectrometer has a serial port, we can write a program that automates this process. In order for python to be able to talk to the spectrometer, we need to get pySerial, which extends Python&#8217;s capabilities to include interacting with a serial port.<\/p>\n<p><em>In this python tutorial, I will explain how to:<\/em><\/p>\n<ol>\n<li>How to configure Python and pySerial<\/li>\n<li>Verify serial port communication, with a spectrometer device<\/li>\n<li>Write some functioning code in Python and use the spectrometer<\/li>\n<\/ol>\n<p><!--more--><\/p>\n<h2><strong>Part 1: Setup Python and pySerial<\/strong><\/h2>\n<p>This part mostly involves installing Python and pySerial, which the latest versions can be downloaded from their respective google searches.<\/p>\n<p>The installation process for both of these tools are relatively trivial. Especially Python.<\/p>\n<p>For pySerial, you&#8217;re looking for a file that&#8217;s something like\u00a0<em>pyserial-2.6.tar.gz<\/em>. That can be grabbed from <a href=\"http:\/\/pyserial.sourceforge.net\/pyserial.html\">here<\/a>.\u00a0So after you&#8217;ve downloaded and extracted the folder to\u00a0<em>C:\\Python32\\Lib\\site-packages,\u00a0<\/em>go to the folder with <em>cmd.exe<\/em> to where\u00a0<em>setup.py<\/em> is located, and type\u00a0<em>python setup.py install<\/em>. That&#8217;s it. If I manage to lose you on the way, see their official documentation <a href=\"http:\/\/pyserial.sourceforge.net\/pyserial.html#installation \">here<\/a>.<\/p>\n<figure id=\"attachment_349\" aria-describedby=\"caption-attachment-349\" style=\"width: 960px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2012\/03\/work.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-349\" alt=\"My spectrometer setup\" src=\"https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2012\/03\/work.jpg\" width=\"960\" height=\"720\" srcset=\"https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2012\/03\/work.jpg 960w, https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2012\/03\/work-300x225.jpg 300w, https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2012\/03\/work-400x300.jpg 400w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" \/><\/a><figcaption id=\"caption-attachment-349\" class=\"wp-caption-text\">My spectrometer setup<\/figcaption><\/figure>\n<h2>Part 2: Communicating with your device via serial port.<\/h2>\n<p>Obviously I&#8217;m assuming you have some sort of a USB to serial device, or a serial port built in. The USB to serial device I used was from Texas Instrument, and it requires their\u00a0proprietary\u00a0driver to setup. I&#8217;ll assume you can figure the driver installation part on your own.<\/p>\n<p>Now you need to know two things:<\/p>\n<ol>\n<li><em>What kind of commands your serial device supports.<\/em> This depends on what device you&#8217;re using, so I&#8217;ll assume you can find proper documentation &#8211; for something among the line of a bunch of commands and their operands. Oh and make sure you know what the baud rate is! Otherwise you can&#8217;t establish communication no matter what.<\/li>\n<li><em>What kind of API calls can accomplish that.\u00a0\u00a0<\/em>All the API interface documentation for pySerial can be located\u00a0<a href=\"http:\/\/pyserial.sourceforge.net\/pyserial_api.html\">here<\/a>.<\/li>\n<\/ol>\n<p>Now we need verify communication works. I will post one code example from my programming below, in part 3. It is what I used to verify that my setup works correctly. There is additional code examples\u00a0<a href=\"http:\/\/pyserial.sourceforge.net\/examples.html#wxpython-examples\">here<\/a>\u00a0on the official pySerial documentation page.<\/p>\n<p><strong style=\"color: #000000;\">Part 3: Code in Python<\/strong><\/p>\n<figure id=\"attachment_150\" aria-describedby=\"caption-attachment-150\" style=\"width: 810px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2012\/03\/e1.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-150\" title=\"eclipse\" alt=\"\" src=\"https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2012\/03\/e1.jpg\" width=\"810\" height=\"900\" srcset=\"https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2012\/03\/e1.jpg 810w, https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2012\/03\/e1-270x300.jpg 270w\" sizes=\"auto, (max-width: 810px) 100vw, 810px\" \/><\/a><figcaption id=\"caption-attachment-150\" class=\"wp-caption-text\">Picture of my python develop environment in eclipse.<\/figcaption><\/figure>\n<p>This code is not available on <a href=\"https:\/\/github.com\/sunapi386\">my github<\/a>. I was not using version control when I developed this. Though I should have. I will do a step by step analysis of my code and guide you through what each part is doing. This is the code I have written (with thanks to <a href=\"https:\/\/github.com\/christophebiocca\">Christophe Biocca<\/a> for his help!):<\/p>\n<pre><code>## API calls ##\r\nimport serial\r\nimport io\r\nimport time<\/code><\/pre>\n<pre>## Creates an object, Spectrometer ##\r\nclass Spectrometer():<\/pre>\n<pre># Parameters\r\nbaud = 1200\r\nbyte = 17 # 17 bytes ## potential problem here##<\/pre>\n<pre>def __init__( self, port = 2 ):\r\nself.port = port\r\nself.isOpen = False\r\nreturn<\/pre>\n<pre>## Open and initize the serial port ##\r\ndef start( self ):\r\nif not self.isOpen :\r\nself.ser = serial.Serial()\r\nself.ser.baudrate = self.baud\r\nself.ser.port = self.port\r\nself.ser.timeout = 2\r\nself.ser.open()\r\nprint( \"Opened port.\" )\r\nself.sio = io.TextIOWrapper( io.BufferedRWPair( self.ser, self.ser ) ) # TextWrapper\r\nself.isOpen = True\r\nreturn<\/pre>\n<pre># Loop readings to a list\r\ndef aquire ( self, start, jump, end, progress = None ):\r\ntry:\r\nprint( \"{0} to {1} with jump {2}\".format ( start, jump, end ) )\r\nresult = []\r\nself.w( \"GTO {0}\".format( start ) )\r\ntime.sleep( 4 )\r\nfor wavelength in range( start, end + jump, jump ):\r\ncurrent_pos = ( wavelength - start ) \/ ( end - start )\r\nif progress:\r\nprogress.set( current_pos )\r\ncommand = \"GTO {0}\".format( wavelength )\r\nself.w( command )\r\nself.w( \"SND\" )\r\noutput = self.r( 17 )\r\nwhile output == b\"\":\r\nself.w( \"SND\" )\r\noutput = self.r( 17 )\r\nresult.append( output.decode( 'ascii' ).strip().split( ' ' ) )\r\nprint()\r\nself.w( \"BEP\" )\r\nfinally:\r\nself.close()\r\nreturn result<\/pre>\n<pre>## Write ##\r\ndef w( self, command ):\r\nself.start()\r\ntime.sleep( 0.1 )\r\nself.sio.write( command + str( \"\\n\" ) )\r\nself.sio.flush()\r\nprint( \"{0:10}{1}\".format( \"Sent:\", command ) )\r\nreturn<\/pre>\n<pre>## Read ##\r\ndef r( self, byte ):\r\nself.start()\r\nread = self.ser.read( byte )\r\nprint( \"{0:10}{1}\".format( \"Read:\", read ) )\r\nreturn read<\/pre>\n<pre>## Helper function for make_reading to call the wavelength ##\r\ndef measure ( self, wavelength ):\r\ncommand = \"GTO \" + str( wavelength )\r\nself.w( command )\r\nstring = self.r( 17 )\r\nreturn string<\/pre>\n<pre>## Unused. Spectrometer has mode of Absorbance, Concentration, Transmittance. ##\r\ndef set_mode( self, mode ):\r\nself.w( mode )\r\nreturn<\/pre>\n<pre>## Close the serial port ##\r\ndef close( self ):\r\nself.ser.close()\r\nself.isOpen = False\r\nprint( \"Closed port.\" )\r\nreturn<\/pre>\n<p>This is more or less the main object code that you&#8217;d need to interact with a spectrometer and all its functions. Very poorly documented, I apologize. Anyhow, hopefully you see enough from this Python and pySerial tutorial to get started.<\/p>\n<p>Oh and by the way, I wrote a GUI with TKInter that simply is a box which prompts the user for a starting, jump amount, and ending wavelength. Actual range is 350 to 900 nm. I won&#8217;t be posting this code for sake of relevancy to the topic on hand.<\/p>\n<p>But here&#8217;s what the simple interface looks like:<\/p>\n<p><a href=\"https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2012\/03\/e2.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-151\" title=\"GUI\" alt=\"\" src=\"https:\/\/sunapi386.ca\/wordpress\/wp-content\/uploads\/2012\/03\/e2.jpg\" width=\"178\" height=\"127\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>It also outputs the measurements to a CSV file which can then be imported to a data analysis software package like Excel or R to analyze.<\/p>\n<p>Thank you for reading and I hope you have found it useful.<\/p>\n<p>Jason Sun<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Python Tutorial Edit Jan 29 2013: This site has gained some significant traffic, according to google. If you search &#8220;pyserial tutorial&#8221; this page is 3rd up. So hence I will edit and make it a bit more understandable, seems like there is actually a need for this! This tutorial describes the process of connecting to &hellip; <a href=\"https:\/\/sunapi386.ca\/wordpress\/serial-programming-python-tutorial\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Python Tutorial to serial programming<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[15,18,17,16,19],"class_list":["post-121","post","type-post","status-publish","format-standard","hentry","category-hack2600","tag-programming","tag-pyserial","tag-python","tag-serial","tag-spectrometer"],"_links":{"self":[{"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/posts\/121","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/comments?post=121"}],"version-history":[{"count":13,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/posts\/121\/revisions"}],"predecessor-version":[{"id":126,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/posts\/121\/revisions\/126"}],"wp:attachment":[{"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/media?parent=121"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/categories?post=121"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sunapi386.ca\/wordpress\/wp-json\/wp\/v2\/tags?post=121"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}