Let Arduino Control Your Browser © GPL3+

Recently Google Chrome added the functionality to communicate with serial devices from the browser. Build interactive experiences easily!

  • 8,545 views
  • 2 comments
  • 14 respects

Components and supplies

Ph a000066 iso (1) ztbmubhmho
Arduino UNO
This should work with any Arduino (or Serial device)
×1
Adafruit industries ada62 image 75px
USB-A to B Cable
×1

About this project

The ability to combine Arduino or physical computing with browser technologies can give designers and technologists superpowers to prototype awesome experiences faster; easier and cheaper.

In the past, Arduino was usually connected to Processing te generate interactive art, products or services. While this is still a widely used way to connect Arduino to a computer, connecting to a browser can give a wider range of opportunities and requires less installation.

Connecting Arduino to a web browser was however still a pain to create (websockets and a server on the device) but now with the introduction of the Serial API you can connect to any Serial device from the browser with the click of a button.

One huge benefit is that software that runs in the browser is easy to share and execute on various devices and operating systems. This system should work with any Arduino that has a serial connection to the computer. Right now only Google Chrome supports web serial if experimental web platform features are enabled, but more browsers might follow.

In this video, I show how Arduino can be connected through the Serial API to the Chrome browser. The P5 sketch can be found here.

Examples of use

In my thesis on the future of learning Arduino, Arduino Action, I used this web Serial protocol to establish a connection between the Arduino and the ecosystem of phones.

This project was for experience prototyping with Ilse Pouwels , Sebastian de Cabo Portugal and Carolyn Wegner

In this prototype we did use Bluetooth communication, but if we would have known webSerial than that would have been a more optimal solution. The Camera is connected to a laptop on which P5.js runs to run a poseNet (that recognizes your pose using computer vision) and Key Nearest Neighbour (a Machine Learning model that can be trained to distinguish certain poses from others).

Steps to make it work

  • Get the latest version of Google Chrome
  • Enable “enable-experimental-web-platform-features” go to chrome://flags/#enable-experimental-web-platform-features
  • You should be able to communicate using the browser with your Arduino; you can test this at https://geertroumen.com/projectHub/serial_terminal.html (You can either upload some code to the Arduino to send data or check RX/TX lights when sending messages to confirm that it is working).
  • If you want to try it yourself in P5.js go to this sketch and upload the Arduino sketch in this project to the Arduino.

Javascript Explained

In the browser the scripting language used is JavaScript, this is where you can take the values from the Arduino and do all kinds of things with it; it can also send values back to the Arduino and use other peripherals like the mouse, keyboard, camera, microphone etc.

The most important functions in the javascript code for connecting with the Arduino are the write and read function. In this example "writeToStream()" is the equivalent of Serial.print for the computer.

writeToStream("Hello")

The equivalent for the Serial.read is reader.read()

async function readLoop() {
    while (true) {
        const { value, done } = await reader.read();
        receiveText.value += value;
    }
}

In this case the value of each package of bytes is added to the recieveText field.

Here is one simple example of how you could use a button to send a specific character or string to the Arduino:

//find the element with the HTML tag id="commandButton"
commandButton = document.getElementById("commandButton")
//make a function that does the desired action
function commandFunction(){
     //Add a check to see if there is an output stream
     if (outputStream) {
         //if there is an ouput stream
         //send an A to the Arduino 
         writeToStream("A")
     }else{
         //if not
         //alert the user that there is no connection
         alert("no connection")
    }
} 
//Couple the button to the commandFunction when clicked
commandButton.addEventListener("click",commandFunction)

Troubleshooting

  • If Arduino is running I had some issues with finding the Serial port in the Serial API interface; just turn Arduino off, plug the Arduino in and out and you should be able to find it.
  • Sometimes the connection is flaky if you can't connect; unplug the Arduino, refresh the page, click connect, plug in the Arduino and connect to it. This seems to be the most solid way (out of experience).

Read more

Let us know below what you make ;)

Code

Simple code on the Arduino to turn on and off an LED with the WebSerial interfaceArduino
When an "A" is sent the light will go on, when a "B" is sent the light will go off, in the meantime it sends the analog Values to the browser
void setup() {
// put your setup code here, to run once:
    pinMode(13,OUTPUT);
    Serial.begin(9600);
}

void loop() {
// put your main code here, to run repeatedly:
    while(Serial.available()){
        char data = Serial.read();
        switch(data){
            case 'A':
                digitalWrite(13, HIGH);
                //do this when A is sent from the USB-host/computer
            break;
            case 'B':
            digitalWrite(13, LOW);
                //do this when B is sent from the USB-host/computer
            break;
            case 'Q':
                //Send the current value on analogPin 0 to the USB-host/computer
                Serial.write(map(analogRead(0),0,1023,0,255));
            break;
        }
    }
    Serial.print(analogRead(0));
    Serial.print(", ");
    Serial.println(analogRead(1));
    delay(100);
}
WebSerial browser codeHTML
This is example code that connects Google Chrome via webSerial to your Arduino
<html>
    <button id="connectButton">Connect</button><span id="statusBar">Disconnected</span><br />
    <input id="sendText" type="text" /><input id="sendButton" type="button" value="send" /><br />
    <textarea readonly id="receiveText" ></textarea>

<script type="text/javascript">
/*
This code is highly based on the webSerial tutorial by Google:
https://codelabs.developers.google.com/codelabs/web-serial/#0

The intention is to get you started with using webSerial for your Arduino project.




*/


    //Define the elements
let sendText = document.getElementById("sendText");
let sendButton = document.getElementById("sendButton");
let receiveText = document.getElementById("receiveText");
let connectButton = document.getElementById("connectButton");
let statusBar = document.getElementById("statusBar");

//Couple the elements to the Events
connectButton.addEventListener("click", clickConnect)
sendButton.addEventListener("click", clickSend)

//When the connectButton is pressed
async function clickConnect() {
    if (port) {
        //if already connected, disconnect
        disconnect();

    } else {
        //otherwise connect
        await connect();
    }
}

//Define outputstream, inputstream and port so they can be used throughout the sketch
var outputStream, inputStream, port;
navigator.serial.addEventListener('connect', e => {
    statusBar.innerText = `Connected to ${e.port}`;
    connectButton.innerText = "Disconnect"
  });
  
  navigator.serial.addEventListener('disconnect', e => {
    statusBar.innerText = `Disconnected`;
    connectButton.innerText = "Connect"
  });
//Connect to the Arduino
async function connect() {

    //Optional filter to only see relevant boards
    const filter = {
        usbVendorId: 0x2341 // Arduino SA
    };

    //Try to connect to the Serial port
    try {
        port = await navigator.serial.requestPort(/*{ filters: [filter] }*/);
        // Continue connecting to |port|.

        // - Wait for the port to open.
        await port.open({ baudrate: 9600 });

        statusBar.innerText = "Connected";
        connectButton.innerText = "Disconnect"
        let decoder = new TextDecoderStream();
        inputDone = port.readable.pipeTo(decoder.writable);
        inputStream = decoder.readable;

        const encoder = new TextEncoderStream();
        outputDone = encoder.readable.pipeTo(port.writable);
        outputStream = encoder.writable;

        reader = inputStream.getReader();
        readLoop();
    } catch (e) {

        //If the pipeTo error appears; clarify the problem by giving suggestions.
        if (e == "TypeError: Cannot read property 'pipeTo' of undefined") {
            e += "\n Use Google Chrome and enable-experimental-web-platform-features"
        }
        connectButton.innerText = "Connect"
        statusBar.innerText = e;
    }
}
//Write to the Serial port
async function writeToStream(line) {
    const writer = outputStream.getWriter();
    writer.write(line);
    writer.releaseLock();
}

//Disconnect from the Serial port
async function disconnect() {

    if (reader) {
        await reader.cancel();
        await inputDone.catch(() => { });
        reader = null;
        inputDone = null;
    }
    if (outputStream) {
        await outputStream.getWriter().close();
        await outputDone;
        outputStream = null;
        outputDone = null;
    }
    statusBar.innerText = "Disconnected";
    connectButton.innerText = "Connect"
    //Close the port.
    await port.close();
    port = null;
}

//When the send button is pressed
function clickSend() {
    //send the message
    writeToStream(sendText.value)
    //and clear the input field, so it's clear it has been sent
    sendText.value = "";

}

//Read the incoming data
async function readLoop() {
    while (true) {
        const { value, done } = await reader.read();
        if (done === true){
            break;
        }
        //When recieved something add it to the big textarea
        receiveText.value += value;
        //Scroll to the bottom of the text field
        receiveText.scrollTop = receiveText.scrollHeight;
    
}
    </script>
</html>

Comments

Similar projects you might like

Control an LED with the Remote Control

Project showcase by Nicholas_N

  • 39,964 views
  • 17 comments
  • 28 respects

Servo Control with TV Remote Control

Project showcase by eldo85

  • 23,439 views
  • 8 comments
  • 46 respects

How To Control Arduino From Mobile Phone

Project showcase by lubosrusnak

  • 23,659 views
  • 0 comments
  • 15 respects

Control Home Appliances Through Web Or Mobile

Project tutorial by Team Gadget Programmers

  • 17,655 views
  • 5 comments
  • 29 respects

ESP01 Webserver to Control Your Arduino UNO, Mega or Nano

Project tutorial by adamsstephen

  • 13,719 views
  • 3 comments
  • 17 respects
Add projectSign up / Login