Serial http://robotic-controls.com/ en Tkinter with Serial http://robotic-controls.com/learn/python-guis/tkinter-serial <span>Tkinter with Serial</span> <div class="field field--name-field-topics field--type-entity-reference field--label-inline"> <div class="field--label">Topics</div> <div class="field--items"> <div class="field--item"><a href="/topics/python" hreflang="en">Python</a></div> <div class="field--item"><a href="/topics/serial" hreflang="en">Serial</a></div> <div class="field--item"><a href="/topics/gui" hreflang="en">GUI</a></div> </div> </div> <span><span lang="" about="/users/evan-boldt" typeof="schema:Person" property="schema:name" datatype="">Evan Boldt</span></span> <span>Fri, 05/03/2013 - 23:46</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>Introduction</h3> <p><a href="http://robotic-controls.com/sites/default/files/images/tkinterSerialRead.png" title="A short Python script to display text from serial (for example, an Arduino) to a TkInter window widget while overcoming the issue of pySerials default blocking behavior"><img alt="A short Python script to display text from serial (for example, an Arduino) to a TkInter window widget while overcoming the issue of pySerials default blocking behavior" class="image-medium soft float-right" data-entity-type="" data-entity-uuid="" height="220" src="/sites/default/files/styles/medium/public/images/tkinterSerialRead.png" style="clear: right;" width="112" /></a>To use Python as a graphical interface for an Arduino powered robot, programmatically read the USB with the <a href="http://pyserial.sourceforge.net/">pySerial </a>library. However, waiting for input from pySerial's Serial object is blocking, which means that it will prevent your GUI from being responsive. The process cannot update buttons or react to input because it is busy waiting for the serial to say something.</p> <p>The first key is to use the root<strong>.after(milliseconds)</strong> method to run a non-blocking version of read in the tkinter main loop. Keep in mind that when TkInter gets to the root<strong>.mainloop()</strong> method, it is running its own while loop. It needs the things in there to run every now and then in order to make the interface respond to interactions. If you are running your own infinite loop anywhere in the code, the GUI will freeze up. Alternatively, you could write your own infinite loop, and call root<strong>.update()</strong> yourself occasionally. Both methods achieve basically the same goal of updating the GUI.</p> <p>However, the real issue is making sure that reading from serial is non-blocking. Normally, the Serial.read() and Serial.readline() will hold up the whole program until it has enough information to give. For example, a Serial.readline() won't print anything until there is a whole line to return, which in some cases might be never! Even using the after() and update() methods will still not allow the UI to be updated in this case, since the function never ends. This problem can be avoided with the timeout=0 option when enitializing the Serial object, which will cause it to return nothing unless something is already waiting in the Serial object's buffer.<!--break--></p> <h3>Code</h3> <pre class="code-scroll-tall"> from serial import * from Tkinter import * serialPort = "/dev/ttyACM0" baudRate = 9600 ser = Serial(serialPort , baudRate, timeout=0, writeTimeout=0) #ensure non-blocking #make a TkInter Window root = Tk() root.wm_title("Reading Serial") # make a scrollbar scrollbar = Scrollbar(root) scrollbar.pack(side=RIGHT, fill=Y) # make a text box to put the serial output log = Text ( root, width=30, height=30, takefocus=0) log.pack() # attach text box to scrollbar log.config(yscrollcommand=scrollbar.set) scrollbar.config(command=log.yview) #make our own buffer #useful for parsing commands #Serial.readline seems unreliable at times too serBuffer = "" def readSerial(): while True: c = ser.read() # attempt to read a character from Serial #was anything read? if len(c) == 0: break # get the buffer from outside of this function global serBuffer # check if character is a delimeter if c == '\r': c = '' # don't want returns. chuck it if c == '\n': serBuffer += "\n" # add the newline to the buffer #add the line to the TOP of the log log.insert('0.0', serBuffer) serBuffer = "" # empty the buffer else: serBuffer += c # add to the buffer root.after(10, readSerial) # check serial again soon # after initializing serial, an arduino may need a bit of time to reset root.after(100, readSerial) root.mainloop()</pre> </div> <section> </section> <div class="field field--name-field-disqus field--type-disqus-comment field--label-above"> <div class="field--label">Disqus</div> <div class="field--item"><drupal-render-placeholder callback="Drupal\disqus\Element\Disqus::displayDisqusComments" arguments="0=Tkinter%20with%20Serial&amp;1=http%3A//robotic-controls.com/learn/python-guis/tkinter-serial&amp;2=node/61" token="6P7FJOWfand5LXop6xB9c5m_Q9jN7CQpogsHM4HIJQY"></drupal-render-placeholder></div> </div> Sat, 04 May 2013 04:46:07 +0000 Evan Boldt 61 at http://robotic-controls.com http://robotic-controls.com/learn/python-guis/tkinter-serial#comments Reading Numbers From Serial http://robotic-controls.com/learn/arduino/reading-numbers-serial <span>Reading Numbers From Serial</span> <div class="field field--name-field-topics field--type-entity-reference field--label-inline"> <div class="field--label">Topics</div> <div class="field--items"> <div class="field--item"><a href="/topics/programming" hreflang="en">Programming</a></div> <div class="field--item"><a href="/topics/serial" hreflang="en">Serial</a></div> <div class="field--item"><a href="/topics/arduino" hreflang="en">Arduino</a></div> <div class="field--item"><a href="/topics/c" hreflang="en">C++</a></div> </div> </div> <span><span lang="" about="/users/evan-boldt" typeof="schema:Person" property="schema:name" datatype="">Evan Boldt</span></span> <span>Sun, 02/17/2013 - 17:32</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>Introduction</h3> <p>Reading numbers from serial on an Arduino is needed surprisingly commonly. Exactly what is happening might be kind of hard to figure out.</p> <h4 style="color: #333333;">Serial</h4> <p>Serial communication is digital, which means all data is transmitted in 1's and 0's. Typically, serial communication is done using <a title="ASCII Table" href="http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters">ASCII letters</a>. This means that, to send a number to the Arduino, the data sent is not the binary version of the number in base 2 (as an integer), but instead a sequence of characters for each digit in base 10 (which is human-readable). It is not an efficient use of bandwidth, but bandwidth is not usually a problem with Arduinos connect by USB.<!--break--></p> <h3>Arduino Code</h3> <pre>char commandLetter; // the delineator / command chooser char numStr[4]; // the number characters and null long speed; // the number stored as a long integer void serialEvent() { // Parse the string input once enough characters are available if(Serial.available() &gt;= 4) { commandLetter = Serial.read(); //dump the buffer if the first character was not a letter if ( ! isalpha( commandLetter ) { // dump until a letter is found or nothing remains while(( ! isalpha( Serial.peak() ) &amp;&amp; Serial.available()) { Serial.read(); // throw out the letter } //not enough letters left, quit if ( Serial.available() &lt; 3 ) { return; } } // read the characters from the buffer into a character array for( int i = 0; i &lt; 3; ++i ) { numStr[i] = Serial.read(); } //terminate the string with a null prevents atol reading too far numStr[i] = '\0'; //read character array until non-number, convert to long int speed = atol(numStr); Serial.println(speed); } } </pre> <h3>Code Explanation</h3> <h4>serialEvent</h4> <p>serialEvent is a function that is called by Arduino before each loop. So, you can separate out your serial handling from the rest of your code. You could also put the contents of this function in the loop() function and it would be similar.</p> <h4>Fixed-Width</h4> <p>Commands need to be delineated in some way. Fixed-width commands are convenient on Arduino because the Serial.available function tells you how many characters are waiting. It is also possible to delineate by special characters. An extremely common and simple version of this is a Comma Separated Value file. However, since it is simplest to use C strings, the character arrays which the serial is read into is necessarily fixed-width anyway. To get around this issue, a vector or linked list could be used, so the serial string can dynamically grow and shrink.</p> <h4>Command Differentiation</h4> <p>In many cases, a robot takes multiple kinds of inputs. For example, there might be multiple speeds, or a direction, or some kind of trigger. Prefixing each command with a unique letter can make it easy to differentiate what the following string is supposed to do.</p> <h4>C Strings</h4> <p>C strings are arrays of char data types. They must be terminated by a NULL character '\textbackslash 0'. Without the NULL character at the end, there is no way for any function to know how long the string is. For example, a print function would print the string and then a bunch of garbage characters until it gets to a NULL or the end of the memory available. In this case, it's less likely for that to happen since we are only using atol, which will only read until there is a non-numeric character. A non-numeric byte is more likely to randomly be at the end of the string than a NULL character.</p> <table style="float: right; margin: 0 0 5px 9px;"><caption>ASCII Table</caption> <thead> <tr> <td>Decimal</td> <td>Character</td> </tr> </thead> <tbody> <tr> <td>48</td> <td>'0'</td> </tr> <tr> <td>49</td> <td>'1'</td> </tr> <tr> <td>50</td> <td>'2'</td> </tr> <tr> <td>51</td> <td>'3'</td> </tr> <tr> <td>52</td> <td>'4'</td> </tr> <tr> <td>53</td> <td>'5'</td> </tr> <tr> <td>54</td> <td>'6'</td> </tr> <tr> <td>55</td> <td>'7'</td> </tr> <tr> <td>56</td> <td>'8'</td> </tr> <tr> <td>57</td> <td>'9'</td> </tr> </tbody> </table> <h4>Char to Integer</h4> <p>Converting a single character to a number takes advantage of how characters are stored, which is typically in a format called ASCII. Think of a char of ASCII like an integer data type. Except that when printed, it is not a decimal number. The number in the int is translated into a letter on the screen according to a table. For example, the decimal number 97 is translated into the letter 'a'. Each letter is really stored as a 'number'. I'm showing it as a decimal (base 10) number, but it is really stored in binary (base 2). The C++ compile takes care of translating our base 10 decimal numbers into base 2 binary.</p> <p>Here is how to take advantage of this:</p> <pre>int number = (int)charInput - (int)48;<br>// or:<br>int number = charInput - '0';</pre> <p>Since ASCII stores the letters sequentially, starting at 0, just subtract the value where 0 begins from each of the characters to convert it to its numeric form. This works regardless of the base of the character storage. So, it converts the ASCII character representing the number in base 10 into an integer in base 2.</p> <h4>Char Array (C-string) to Long Integer</h4> <p>Now, each of the letters from right to left need to be multiplied by a power of 10. Here is the basic idea of what atol does:</p> <pre>char charArray[5] = "5432"; // double quotes adds the \0 at the end long longnum = 0; //the converted number long exp = 1; //start with 10^0 int index = 0; //the current place in the array //find the end of the string - when character is not a number while ( isdigit( charArray[idx] ) ) { ++idx; } //begin base multiplication and number conversion while( idx &gt;= 0 ) { //convert digit character to a long long currentDigit = (long) charArray[idx] - (long)48 currentDigit *= exponent; //number multiplied by 10^(len-idx) exponent *= 10; // next number to left is another power of ten longnum += currentDigit;<br> --idx; } </pre></div> <section> </section> <div class="field field--name-field-disqus field--type-disqus-comment field--label-above"> <div class="field--label">Disqus</div> <div class="field--item"><drupal-render-placeholder callback="Drupal\disqus\Element\Disqus::displayDisqusComments" arguments="0=Reading%20Numbers%20From%20Serial&amp;1=http%3A//robotic-controls.com/learn/arduino/reading-numbers-serial&amp;2=node/46" token="AamYQ_Fw1AKGTpr2Y2iiSevIULq7FgC26yL7S2kFZ_Q"></drupal-render-placeholder></div> </div> Sun, 17 Feb 2013 23:32:48 +0000 Evan Boldt 46 at http://robotic-controls.com Python Web UI with Tornado http://robotic-controls.com/learn/python-guis/python-web-ui-tornado <span>Python Web UI with Tornado</span> <div class="field field--name-field-topics field--type-entity-reference field--label-inline"> <div class="field--label">Topics</div> <div class="field--items"> <div class="field--item"><a href="/topics/python" hreflang="en">Python</a></div> <div class="field--item"><a href="/topics/web" hreflang="en">Web</a></div> <div class="field--item"><a href="/topics/serial" hreflang="en">Serial</a></div> <div class="field--item"><a href="/topics/gui" hreflang="en">GUI</a></div> </div> </div> <span><span lang="" about="/users/evan-boldt" typeof="schema:Person" property="schema:name" datatype="">Evan Boldt</span></span> <span>Fri, 02/08/2013 - 12:10</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>Introduction</h3> <p>So, you want a GUI for your robot. Sure, you could make a nice GUI in <a href="/learn/basics-gui">Python with Tkinter</a>, but there are some really good reasons to try it as a website instead:</p> <ul> <li>A web GUI can be accessed from almost any location</li> <li>A well-designed web GUI can be used on almost any device like a tablet or a phone</li> <li>HTML, CSS, and Javascript are well documented, powerful, and very flexible</li> <li>HTML can be easily made to look very nice</li> </ul> <p>There are some drawbacks to implementing your GUI as a website though:</p> <ul> <li>It is only able to start communication one-way (browser to server, server responds)</li> <ul> <li>Great for buttons and other input</li> <li>Requres continuous <a href="http://en.wikipedia.org/wiki/Polling_(computer_science)">polling</a> or a <a href="http://en.wikipedia.org/wiki/Comet_(programming)">commet</a> to get data to be pushed to the browser</li> </ul> <li>It adds another "layer" of complexity to your code</li> <ul> <li>Several different languages (C++ on Arduino, Python Server, and HTML+CSS+Javascript in browser)</li> <li>The server has to relay information from the browser to the robot</li> </ul> </ul> <p><!--break--></p> <h3>Installing Python Tornado</h3> <p>I used the <a href="http://www.tornadoweb.org/">Tornado</a> web server for my projects. It is better than just using CGI, since the environment is always loaded while the server is running instead of loading it every time a request is made. CGI would be problematic then, since serial.begin would be run every time a request was made, which simply wouldn't work since the Arduino would also restart all the time.</p> <p>On Ubuntu, the installation is as easy as:</p> <pre>sudo apt-get install python-tornado python-serial</pre> <h3>Using Tornado with the Serial Library</h3> <p>So one of the challenges with this is that reading serial input in python is usually <a href="http://en.wikipedia.org/wiki/Blocking_(computing)">blocking</a>, so the webserver becomes unresponsive to browsers' requests while waiting for serial input.</p> <pre class="code-scroll-tall">#! /usr/bin/python2.7 import os import json import tornado.ioloop import tornado.web from serial import * tornadoPort = 8888 cwd = os.getcwd() # used by static file server # Make a Serial object serialPort = '/dev/ttyACM0' serialBaud = 9600 ser = Serial( serialPort, serialBaud, timeout=0, writeTimeout=0 ) # gets serial input in a non-blocking way serialPending = '' def checkSerial(): try: s = ser.read( ser.inWaiting() ) except: print("Error reading from %s " % serialPort ) return if len(s): serialPending += s paseSerial() #called whenever there is new input to check serialHistory = '' mostRecentLine = '' def parseSerial(): split = serialPending.split("\r\n") if len( split ) &gt; 1: for line in split[0:-1]: print( line ) #do some stuff with the line, if necessary #example: mostRecentLine = line # in this example, status will show the most recent line serialHistory += line pending = split[-1] # send the index file class IndexHandler(tornado.web.RequestHandler): def get(self, url = '/'): self.render('index.html') def post(self, url ='/'): self.render('index.html') # handle commands sent from the web browser class CommandHandler(tornado.web.RequestHandler): #both GET and POST requests have the same responses def get(self, url = '/'): print "get" self.handleRequest() def post(self, url = '/'): print 'post' self.handleRequest() # handle both GET and POST requests with the same function def handleRequest( self ): # is op to decide what kind of command is being sent op = self.get_argument('op',None) #received a "checkup" operation command from the browser: if op == "checkup": #make a dictionary status = {"server": True, "mostRecentSerial": mostRecentLine } #turn it to JSON and send it to the browser self.write( json.dumps(status) ) #operation was not one of the ones that we know how to handle else: print op print self.request raise tornado.web.HTTPError(404, "Missing argument 'op' or not recognized") # adds event handlers for commands and file requests application = tornado.web.Application([ #all commands are sent to http://*:port/com #each command is differentiated by the "op" (operation) JSON parameter (r"/(com.*)", CommandHandler ), (r"/", IndexHandler), (r"/(index\.html)", tornado.web.StaticFileHandler,{"path": cwd}), (r"/(.*\.png)", tornado.web.StaticFileHandler,{"path": cwd }), (r"/(.*\.jpg)", tornado.web.StaticFileHandler,{"path": cwd }), (r"/(.*\.js)", tornado.web.StaticFileHandler,{"path": cwd }), (r"/(.*\.css)", tornado.web.StaticFileHandler,{"path": cwd }), ]) if __name__ == "__main__": #tell tornado to run checkSerial every 10ms serial_loop = tornado.ioloop.PeriodicCallback(checkSerial, 10) serial_loop.start() #start tornado application.listen(tornadoPort) print("Starting server on port number %i..." % tornadoPort ) print("Open at http://127.0.0.1:%i/index.html" % tornadoPort ) tornado.ioloop.IOLoop.instance().start()</pre> <h3>Setting up the Browser</h3> <p>To make it easy to send requests to the server, it's really a good idea to use <a href="http://jquery.com/">jquery</a>, and the easiest way to use jquery is to use the Google API for it. To add jquery to the webpage, just add this script:</p> <pre>&lt;script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"&gt;&lt;/script&gt;&nbsp;</pre> <p>So to start, we'll just have a simple webpage that has a div. When the div is clicked, jquery will ask the status of the tornado webserver.</p> <pre class="code-scroll-tall">&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;Python Tornado Test Page&lt;/title&gt; &lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"&gt;&lt;/script&gt; &lt;script&gt; function serverResponded( data ) { /* log the event data, so you can see what's going on. Shows up in the console on your browser. (Chrome: Tools &gt; Developer Tools &gt; Console) */ console.log( data ); // check the server status, and report it on the screen if ( data.server === true ) { $('#status .value').html("OK"); } else { $('#status .value').html("NOT OK"); } // add the last serial to the div on the screen $('#serial .value').html( data.mostRecentSerial ); } $(document).ready( function() { /* handle the click event on the clickme */ $('#clickme').click( function() { params = { op: "checkup" }; $.getJSON( 'http://localhost:8888/com' , params, serverResponded ); }); }); &lt;/script&gt; &lt;/head&gt; &lt;body&gt; &lt;div id="clickme" style="cursor: pointer;"&gt;CLICK ME&lt;/div&gt; &lt;div id="status"&gt; Server Status: &lt;span class="value"&gt;?&lt;/span&gt; &lt;/div&gt; &lt;div id="serial"&gt; Last Serial Input: &lt;span class="value"&gt;&lt;/span&gt; &lt;/div&gt; &lt;/body&gt;</pre></div> <section> </section> <div class="field field--name-field-disqus field--type-disqus-comment field--label-above"> <div class="field--label">Disqus</div> <div class="field--item"><drupal-render-placeholder callback="Drupal\disqus\Element\Disqus::displayDisqusComments" arguments="0=Python%20Web%20UI%20with%20Tornado&amp;1=http%3A//robotic-controls.com/learn/python-guis/python-web-ui-tornado&amp;2=node/30" token="VfM7nfmxI2ZJp3EN7vuSIF0xbhHRc5YYB88m5cGkX9U"></drupal-render-placeholder></div> </div> Fri, 08 Feb 2013 18:10:44 +0000 Evan Boldt 30 at http://robotic-controls.com http://robotic-controls.com/learn/python-guis/python-web-ui-tornado#comments Arduino to Arduino Serial Communication http://robotic-controls.com/learn/arduino/arduino-arduino-serial-communication <span>Arduino to Arduino Serial Communication</span> <div class="field field--name-field-topics field--type-entity-reference field--label-inline"> <div class="field--label">Topics</div> <div class="field--items"> <div class="field--item"><a href="/topics/arduino" hreflang="en">Arduino</a></div> <div class="field--item"><a href="/topics/serial" hreflang="en">Serial</a></div> </div> </div> <span><span lang="" about="/users/jenn-case" typeof="schema:Person" property="schema:name" datatype="">Jenn Case</span></span> <span>Wed, 02/06/2013 - 13:10</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>Introduction</h3> <p>It is possible to chain Arduinos together in such a way as to get communication between the two. Having Arduino-Arduino communication can be useful for many projects, such as having one Arduino to run motors and having another sense the surroundings and then relay commands to the other Arduino. This can be done in several methods, using I2C and Serial, to list a few.</p> <p>This tutorial will focus on Arduino-Arduino communication through the serial ports (RX and TX).</p> <p><!--break--></p> <h3>Schematic</h3> <p>The schematic below shows how to connect the two Arduinos together. This shows two Unos, but if a Mega is used, it can be connected to any of the Serial ports on the Mega as long as that is accounted for in the code.</p> <p><a href="/sites/default/files/learn/Arduino-ArduinoSerial.png"><img src="/sites/default/files/styles/large/public/learn/Arduino-ArduinoSerial.png" alt="" width="480" height="209" style="display: block; margin-left: auto; margin-right: auto;" class="image-large soft"></a></p> <p>There has to be a common ground between the two or else it will not function properly. Also, note that TX goes to RX and RX goes to TX.</p> <h3>Coding</h3> <p>When sending things through serial, everything is sent in bytes. These bytes are then read one byte at a time by the other Arduino. When it is just characters being sent through the serial, it is relatively easy to convert from characters to bytes. However, if there are both characters and numbers are going through, this can lead to messing up the data because a number and a character can have the same byte value, but that does not make them the same. Numbers are also tricky because they may not actually fit in the byte.</p> <h4>Simple Code</h4> <p>The easiest way to get around this is to try to avoid using characters and numbers at the same time. This can be done by sending one character across, each with a different meaning. A good example of this comes from the Arduino <a href="http://arduino.cc/en/Tutorial/PhysicalPixel">Physical Pixel</a> tutorial.</p> <p>Upload the Physical Pixel code, which can be found in the Arduino IDE under: File &gt;&gt; Examples &gt;&gt; Communication, onto one Arduino.</p> <p>On the other Arduino, upload:</p> <pre>void setup() {<br> Serial.begin(9600);<br>}<br><br>void loop() {<br> Serial.print('H');<br> delay(1000);<br> Serial.print('L');<br> delay(1000);<br>}</pre> <p>When this is run, the LED attached to Pin 13 on the Arduino with the Physical Pixel code should flash on and off at a frequency of 0.5 Hz. To make sure this is actually the code doing that, the delays can always be changed in the above code.</p> <p>In this code the job of 'H' was to turn an LED on and the job of 'L' was to turn the LED off. This can easily be applicable to getting various characters triggering more reactions.</p> <p>However, depending on the application, this may not be enough and more drastic code may be required.</p> <h4>Complex Code</h4> <p>For sending data from one Arduino to another in a form that cannot be simplified, there are other options. One option is to turn everything sent from the Sender Arduino into characters and then have the Receiver Arduino read in the characters. The data is actually sent as bytes, but the Arduino can convert from characters to bytes and vice versa.</p> <h4>Sender Code</h4> <p>The sender code changes characters into bytes and, if necessary, it changes number values into characters before turning it into bytes. Below is a sample of the Sender code:</p> <pre>//Sender Code<br><br>char str[4];<br><br>void setup() {<br> Serial.begin(9600);<br>}<br><br>void loop() {<br> int value=1234; //this would be much more exciting if it was a sensor value<br> <br> itoa(value, str, 10); //Turn value into a character array<br> Serial.write(str, 4);<br>}</pre> <h4>Receiver Code</h4> <p>The receiver will then receive the byte array from the other Arduino and interpret it there. Below is the code for the receiver. Note that this code is intended for a Mega since it will interpret the data received from the other Arduino and then print to the Serial Monitor what it received so that the user can check it. This debugging can be avoided by using an Uno and then printing what was found onto an LCD screen that uses I2C communication.</p> <pre>//Receiver Code<br><br>char str[4];<br><br>void setup() {<br> Serial.begin(9600);<br> Serial1.begin(9600);<br>}<br><br>void loop() {<br> int i=0;<br><br> if (Serial1.available()) {<br> delay(100); //allows all serial sent to be received together<br> while(Serial1.available() &amp;&amp; i&lt;4) {<br> str[i++] = Serial1.read();<br> }<br> str[i++]='\0';<br> }<br><br> if(i&gt;0) {<br> Serial.println(str,4);<br> }<br>}</pre> <p>There is one flaw with this program as it is now. It results in only a character array, so if the integers were desired, they are lost without further work on the data.</p> <p>Further tutorials have been made to show how this data may be manipulated by <a href="http://robotic-controls.com/learn/arduino/splitting-string">splitting strings</a> or getting <a href="http://robotic-controls.com/learn/arduino/character-array-float">floats from the character arrays</a>.</p></div> <section> </section> <div class="field field--name-field-disqus field--type-disqus-comment field--label-above"> <div class="field--label">Disqus</div> <div class="field--item"><drupal-render-placeholder callback="Drupal\disqus\Element\Disqus::displayDisqusComments" arguments="0=Arduino%20to%20Arduino%20Serial%20Communication&amp;1=http%3A//robotic-controls.com/learn/arduino/arduino-arduino-serial-communication&amp;2=node/13" token="57gyC9d_soVMwUsSL2dhw3TureDDjY3-N8np8lM4a-k"></drupal-render-placeholder></div> </div> Wed, 06 Feb 2013 19:10:03 +0000 Jenn Case 13 at http://robotic-controls.com http://robotic-controls.com/learn/arduino/arduino-arduino-serial-communication#comments Serial Commands http://robotic-controls.com/learn/arduino/serial-commands <span>Serial Commands</span> <div class="field field--name-field-topics field--type-entity-reference field--label-inline"> <div class="field--label">Topics</div> <div class="field--items"> <div class="field--item"><a href="/topics/arduino" hreflang="en">Arduino</a></div> <div class="field--item"><a href="/topics/python" hreflang="en">Python</a></div> <div class="field--item"><a href="/topics/serial" hreflang="en">Serial</a></div> <div class="field--item"><a href="/topics/c" hreflang="en">C++</a></div> </div> </div> <span><span lang="" about="/users/evan-boldt" typeof="schema:Person" property="schema:name" datatype="">Evan Boldt</span></span> <span>Wed, 01/30/2013 - 17:11</span> <div class="field field--name-body field--type-text-with-summary field--label-hidden field--item"><h3>Introduction</h3><p>Serial communication through USB can be used to communicate between a host computer (like a laptop, or <a href="http://www.raspberrypi.org/faqs">Raspberry Pi</a>), and an Arduino. Doing so allows:</p><ul><li>Use of the faster hardware of the host computer for calculations</li><li>Synchronization of multiple Arduinos</li><li>Use of other information provided by the host computer, like internet connections or larger data files</li><li>Creation of a graphical interface using the host's display or web server</li></ul><h3><!--break-->Communication</h3><p>Communication is easy. Arduino and Python have simple methods for establishing serial communication.</p><h4>Arduino</h4><pre>void setup() { Serial.begin(9600); //Initialize serial communication at 9600 baud } void loop() { Serial.println('hello'); } </pre><h4>Python</h4><pre>from <a href="http://pyserial.sourceforge.net/pyserial_api.html">serial</a> import * ser = Serial( "/dev/ttyACM0" , 9600 ) while 1: print ser.readline() </pre><h3>Incomplete Messages</h3><p>One of the most difficult issues with this sort of serial communication is ensuring that commands are received in entirety. If you send "1000" from Python, and want Arduino to read it as shown below, Arduino might read "10" and then in another loop() right afterward read "00".</p><pre>char incoming[11] = " "; int i = 0; while (Serial.available() &gt; 0) { <span class="comment">// read the incoming byte:</span> char[i] = Serial.read(); i++; } <span class="comment">//Convert the incoming string into an integer!</span> int newNumber = atoi(incoming); </pre><h3>Fixed Length Packets</h3><p>One way to solve this in an efficient manner is to use a fixed length for commands and wait until there are enough bytes waiting in the buffer. The downside is that no commands may be issued with a length longer than the fixed length, and requires remaining length be wasted.</p><h4>Python</h4><pre>ser.write('%10d' % 1000 ) <span class="comment">#pad the number so it is 10 characters long</span> </pre><p>Now just add a condition so that no reading is done unless a full command is waiting in the serial buffer.</p><h4>Arduino</h4><pre>if ( Serial.available() &gt;= 10 ) { char incoming[11] = " "; int i = 0; while (Serial.available() &gt; 0) { <span class="comment">// read the incoming byte:</span> char[i] = Serial.read(); i++; } <span class="comment">//Convert the incoming string into an integer!</span> newNumber = atoi(incoming); } </pre><h3>Delineation</h3><p>Another way to solve this problem is to delineate commands by placing a special character at the end of each command to signify that the command is complete. The problem with this way is that the length of the incoming string is unknown, and a long or improperly formed command could overflow a fixed length array. To overcome this limitation, a dynamic class is usually used. The <a href="http://arduino.cc/en/Reference/StringObject">String object</a> is a good solution as it can be easily converted back into a character array. Maintaining data types with C++ strings can quickly become confusing, and it is extremely important that the delineation character is never used in the command. There are some special command characters in <a href="http://en.wikipedia.org/wiki/ASCII">ASCII</a> that would be good choices.</p><h3>Multiple Command Types</h3><p>You can send different commands over the same communication line by attaching a prefix to the command. For example, speed and position could be sent as "p000001000" and "s000000200" to tell the Arduino to go to position 1000 at a speed of 200.</p><h4>Python</h4><pre>ser.write('p%9d' % 1000 ) <span class="comment">#send position, padded to 9 (plus 1 command char)</span> ser.write('s%9d' % 200 ) <span class="comment"> #send speed, padded to 9 (plus 1 command char)</span> </pre><h4>Arduino</h4><pre>int position, speed; if ( Serial.available() &gt;= 10 ) { <span class="comment">//read the first character as the command</span> char command = Serial.read(); char incoming[10] = " "; int i = 0; <span class="comment&gt;//Do not read too much - the next command could already be waiting&lt;/span&gt; while (Serial.available() &gt; 0 &amp;&amp; i &lt; 10) { &lt;span class=">// read the incoming byte:</span> char[i] = Serial.read(); i++; } <span class="comment">//Convert the incoming string into an integer, based on command</span> if ( command == 'p' ) { position = atoi(incoming); } else if ( command == 's' ) { speed = atoi(incoming); } else { <span class="comment">//The command was not one of the recognized characters</span> Serial.println("COMMAND ERROR - Not recognized"); } } </pre><p>Now that your communication is established, it is up to you to figure out what to do with the data on either end.</p></div> <section> </section> <div class="field field--name-field-disqus field--type-disqus-comment field--label-above"> <div class="field--label">Disqus</div> <div class="field--item"><drupal-render-placeholder callback="Drupal\disqus\Element\Disqus::displayDisqusComments" arguments="0=Serial%20Commands&amp;1=http%3A//robotic-controls.com/learn/arduino/serial-commands&amp;2=node/5" token="H7xXTDBsymtv9UPU84bhe-Uzt2VuMbLXOt-zt8P1wkk"></drupal-render-placeholder></div> </div> Wed, 30 Jan 2013 23:11:35 +0000 Evan Boldt 5 at http://robotic-controls.com