{"id":9548,"date":"2022-05-31T07:52:53","date_gmt":"2022-05-31T11:52:53","guid":{"rendered":"https:\/\/itp.nyu.edu\/physcomp\/?page_id=9548"},"modified":"2022-08-26T17:53:24","modified_gmt":"2022-08-26T21:53:24","slug":"p5-serialport-and-p5-webserial-compared","status":"publish","type":"page","link":"https:\/\/itp.nyu.edu\/physcomp\/lessons\/p5-serialport-and-p5-webserial-compared\/","title":{"rendered":"p5.serialport and p5.webserial Compared"},"content":{"rendered":"\n<p>Asynchronous serial communication is not part of the core of p5.js, nor is it part of the core for web browsers. To read serial in a p5.js sketch, or in a web page in general, you need some help. One approach is to open a separate application that connects to the serial port and offers a webSocket connection to the browser. This is the approach that the p5.serialport library and the p5.serialcontrol app take. Another approach is to use the browser API called <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Web_Serial_API\">WebSerial<\/a>. This is the approach that the p5.webserial library takes. <\/p>\n\n\n\n<p>The difference between them is best illustrated by Figures 1 and 2 below. With p5.seriaport, you must open another application on your computer, <a href=\"https:\/\/github.com\/p5-serial\/p5.serialcontrol\/releases\">p5.serialcontrol<\/a>, to communicate with the serial port. It is this application that handles serial communication, not the p5.js sketch in the browser. This can be more complicated for beginning users. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><a href=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/socket-serial-connection-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"3757\" height=\"1057\" src=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/socket-serial-connection-2.png\" alt=\"Diagram of three rectangles connected by arrows. The rectangle on the right represents your p5.js sketch, running in a browser. Your sketch implements the p5.serialport library. Your sketch connects to p5 serial control, the middle rectangle, via a webSocket. The p5 serial control application runs on your laptop. It connects to a serial port on your computer and listens for webSocket connections from your p5.js sketch. It passes whatever comes in the serial port through to the webSocket and vice versa. The third rectangle is your Arduino, connected to p5 serial control via the serial port.\" class=\"wp-image-6549\" srcset=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/socket-serial-connection-2.png 3757w, https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/socket-serial-connection-2-768x216.png 768w, https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/socket-serial-connection-2-1280x360.png 1280w\" sizes=\"(max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/a><figcaption><em>Figure 1. Diagram of the connection from the serial port to p5.js through p5.serialcontrol<\/em><\/figcaption><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/serial-connection.png\" alt=\"Diagram of two rectangles connected by arrows. The rectangle on the right represents your p5.js sketch, running in a browser. Your sketch implements the p5.webserial library. The browser connects to a serial port on your computer. It passes whatever comes in the serial port through to the webSocket and vice versa. The second rectangle is your Arduino, connected via the serial port.\" class=\"wp-image-9673\" width=\"329\" height=\"171\"\/><figcaption><a href=\"https:\/\/itp.nyu.edu\/physcomp\/wp-content\/uploads\/socket-serial-connection-2.png\"><\/a><em>Figure 2. Diagram of the connection from the serial port to p5.js through p5.webserial<\/em><\/figcaption><\/figure><\/div>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>p5.serialport\/p5.serialcontrol:<\/th><th>p5.webserial:<\/th><\/tr><\/thead><tbody><tr><td><strong>advantages:<\/strong><br>* works in all browsers.<br>* Allows your browser to connect to the serial port of a remote computer, if that computer is running a web server program.<br>* Supports opening multiple serial ports at the same time<\/td><td><strong>advantages:<\/strong><br>* connection is direct to the browser, making it easier for beginners to learn<br><br><br><br><\/td><\/tr><tr><td><strong>disadvantages:<\/strong><br>* requires a third application (p5.serialcontrol), making it more difficult for beginners to learn<\/td><td><strong>disadvantages:<\/strong><br>* only works in Chrome and Edge browsers<br>* No connection to remote computers<br>* Not sure if it supports a second serial port.<\/td><\/tr><\/tbody><\/table><figcaption>Table 1. Comparing p5.seriaport to p5.webserial<\/figcaption><\/figure>\n\n\n\n<p>The APIs of p5.serialport and p5.webserial are similar, so it&#8217;s pretty straightforward to convert between them.<\/p>\n\n\n\n<p> The code below is a typical p5.serialport setup. You make an instance of the p5.serialport library with the port name, then you make callback functions for the primary tasks:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\nlet serial;          \/\/ variable to hold an instance of the serialport library\nlet portName = &#039;\/dev\/cu.usbmodem1421&#039;;  \/\/ fill in your serial port name here\n \nfunction setup() {\n  serial = new p5.SerialPort();       \/\/ make a new instance of the serialport library\n  serial.on(&#039;list&#039;, printList);  \/\/ set a callback function for the serialport list event\n  serial.on(&#039;connected&#039;, serverConnected); \/\/ callback for connecting to the server\n  serial.on(&#039;open&#039;, portOpen);        \/\/ callback for the port opening\n  serial.on(&#039;data&#039;, serialEvent);     \/\/ callback for when new data arrives\n  serial.on(&#039;error&#039;, serialError);    \/\/ callback for errors\n  serial.on(&#039;close&#039;, portClose);      \/\/ callback for the port closing\n \n  serial.list();                      \/\/ list the serial ports\n  serial.open(portName);              \/\/ open a serial port\n}\n<\/pre><\/div>\n\n\n<p><meta charset=\"utf-8\"> The code below is a typical p5.webserial setup. You check t see if WebSerial is available, and then you make an instance of the p5.webserial library, then you look for ports using <code>getPorts()<\/code>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n\/\/ variable to hold an instance of the p5.webserial library:\nconst serial = new p5.WebSerial();\n \/\/ port chooser button:\nlet portButton;\n\/\/ variable for incoming serial data:\nlet inData;\n \nfunction setup() {\n   \/\/ check to see if serial is available:\n   if (!navigator.serial) {\n    alert(&quot;WebSerial is not supported in this browser. Try Chrome or MS Edge.&quot;);\n  }\n  \/\/ check for any ports that are available:\n  serial.getPorts();\n  \/\/ setup function continues below:\n<\/pre><\/div>\n\n\n<p>Unlike with p5.serialport, you don&#8217;t pass in the port name. Instead, the user chooses the port with a pop-up menu:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n  \/\/ if there&#039;s no port chosen, choose one:\n  serial.on(&quot;noport&quot;, makePortButton);\n  \/\/ open whatever port is available:\n  serial.on(&quot;portavailable&quot;, openPort);\n  \/\/ setup function continues below:\n<\/pre><\/div>\n\n\n<p>Then you make callback functions for the primary tasks. These are similar to p5.serialport&#8217;s callbacks:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n   \/\/ handle serial errors:\n  serial.on(&quot;requesterror&quot;, portError);\n  \/\/ handle any incoming serial data:\n  serial.on(&quot;data&quot;, serialEvent);\n  serial.on(&quot;close&quot;, makePortButton)\n  \/\/ setup function continues below:\n<\/pre><\/div>\n\n\n<p>You also add listeners for when the USB serial port enumerates or de-enumerates. This way, if you unplug your serial device or reset it, your program automatically reopens it when it&#8217;s available:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\n  \n  \/\/ add serial connect\/disconnect listeners from WebSerial API:\n  navigator.serial.addEventListener(&quot;connect&quot;, portConnect);\n  navigator.serial.addEventListener(&quot;disconnect&quot;, portDisconnect);\n} \/\/ end of setup function\n<\/pre><\/div>\n\n\n<p>The functions in each API are similar too: <\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><thead><tr><th>p5.serialport functions <strong>(from the library&#8217;s <\/strong><a href=\"https:\/\/p5-serial.github.io\/index.html\">guide<\/a><strong>)<\/strong><\/th><th>p5.webserial functions (from the library&#8217;s <a href=\"https:\/\/github.com\/yoonbuck\/p5.WebSerial\/wiki\/Guide#reading-from-the-serial-port\">guide<\/a>)<\/th><\/tr><\/thead><tbody><tr><td><code>read()<\/code> returns a single byte of data (first in the buffer)<\/td><td><strong><code>read()<\/code><\/strong>&nbsp;\u2014 reads a single byte from the queue (returns a number)<\/td><\/tr><tr><td><br><code>readChar()<\/code> returns a single char, e,g, &#8216;A&#8217;, &#8216;a&#8217;<\/td><td><strong><code>readChar()<\/code><\/strong>&nbsp;\u2014 reads a single byte from the queue as a character (returns a string)<\/td><\/tr><tr><td><br><code>readBytes()<\/code> returns all of the data available as an array of bytes<\/td><td><strong><code>readBytes()<\/code><\/strong>&nbsp;\u2014&nbsp;reads all data currently available in the queue as a&nbsp;<code>Uint8Array<\/code>.<\/td><\/tr><tr><td><code>readBytesUntil(charToFind)<\/code> returns all of the data available until <code><code>charToFind<\/code><\/code> is encountered<\/td><td><strong><code>readBytesUntil(charToFind)<\/code><\/strong>&nbsp;\u2014 reads bytes until a character is found (returns a&nbsp;<code>Uint8Array<\/code>)<\/td><\/tr><tr><td><br><code>readString() <\/code>returns all of the data available as a string<\/td><td><\/td><\/tr><tr><td><code>readStringUntil(charToFind)<\/code> returns all of the data available as a string until <meta charset=\"utf-8\"> <code><code>charToFind<\/code><\/code> is encountered<\/td><td><strong><code>readStringUntil(stringToFind)<\/code><\/strong>&nbsp;\u2014 reads out a string until a certain substring is found (returns a string)<\/td><\/tr><tr><td><code>last() <\/code>returns the last byte of data from the buffer<\/td><td><\/td><\/tr><tr><td><br><code>lastChar()<\/code> returns the last byte of data from the buffer as a char<\/td><td><\/td><\/tr><tr><td><\/td><td><strong><code>readLine()<\/code><\/strong>&nbsp;\u2014&nbsp;read a string until a line ending is found (returns a string)<\/td><\/tr><tr><td><code>write()<\/code> &#8211; sends most any JS data type out the port.<\/td><td><code>write()<\/code> &#8211; sends most any JS data type out the port.<\/td><\/tr><tr><td><\/td><td><code>print()<\/code>&#8211; sends string data out the serial port<\/td><\/tr><tr><td><\/td><td><code>println()<\/code> &#8211; sends string data out the serial port, along with a newline character.<\/td><\/tr><\/tbody><\/table><figcaption>Table 2. Comparison of p5.serialport and p5.webserial APIs<\/figcaption><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Both p5.serialport and p5.webserial will do the job of getting bytes from a serial device like an Arduino or other microcontroller to p5.js and vice versa. Which you use depends on what you need. p5.webserial is great if you&#8217;re connected directly to the browser&#8217;s computer via USB. For most serial applications, this is the way to go.  Alternately, p5.serialport offers the advantage that you can run p5.serialcontrol app on your browser&#8217;s computer or on another computer on the same network. That way, a browser on your phone or tablet can communicate to the serial device via the computer running p5.serialcontrol. <\/p>\n\n\n\n<p>This site contains lab examples for both <a href=\"https:\/\/itp.nyu.edu\/physcomp\/labs\/#p5js_serialport_library\">p5.serialport<\/a> and <a href=\"https:\/\/itp.nyu.edu\/physcomp\/labs\/#p5js_webserial_library\">p5.webserial<\/a> for your convenience. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Asynchronous serial communication is not part of the core of p5.js, nor is it part of the core for web browsers. To read serial in a p5.js sketch, or in a web page in general, you need some help. One approach is to open a separate application that connects to the serial port and offers &hellip; <a href=\"https:\/\/itp.nyu.edu\/physcomp\/lessons\/p5-serialport-and-p5-webserial-compared\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;p5.serialport and p5.webserial Compared&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"parent":13,"menu_order":10,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"categories":[42,52,31,79,78,26,9],"tags":[],"class_list":["post-9548","page","type-page","status-publish","hentry","category-asynchronous-serial","category-lesson","category-p5-js","category-p5-serialport","category-p5-webserial","category-programming","category-serial-communication"],"_links":{"self":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages\/9548"}],"collection":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/comments?post=9548"}],"version-history":[{"count":17,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages\/9548\/revisions"}],"predecessor-version":[{"id":10255,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages\/9548\/revisions\/10255"}],"up":[{"embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/pages\/13"}],"wp:attachment":[{"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/media?parent=9548"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/categories?post=9548"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itp.nyu.edu\/physcomp\/wp-json\/wp\/v2\/tags?post=9548"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}