Позволяем Arduino управлять нашим браузером

Проект в котором мы рассмотрим новую возможность браузера Google Chrome по связи с Ардуино и последовательными устройствами.

О проекте

Недавно Google Chrome добавил функциональность для связи с последовательными устройствами из браузера, что позволит в дальнейшем легко реализовывать интерактивные проекты.

Возможность комбинировать Arduino или физические вычисления с браузерными технологиями может дать дизайнерам и техническим специалистам возможности для более быстрого и дешевого прототипирования потрясающих приложений.

В прошлом Arduino обычно подключалась к Processing для создания интерактивных проектов, продуктов или услуг. Хотя это все еще широко используемый способ подключения Arduino к компьютеру, подключение к браузеру может предоставить более широкий спектр возможностей и требует меньше настроек.

Однако, до недавнего времени, подключение Arduino к веб-браузеру было все еще сложной задачей (веб-сокеты и сервер на устройстве), но теперь, с введением последовательного API, вы можете подключиться к любому последовательному устройству из браузера одним нажатием кнопки.

Одним из огромных преимуществ является то, что программное обеспечение, которое запускается в браузере, легко распространять и запускать на различных устройствах и операционных системах.

Эта система должна работать с любым Arduino, имеющим последовательное соединение с компьютером. На данный момент только Google Chrome поддерживает веб-последовательный порт, если включены экспериментальные функции веб-платформы, но надеемся, что такие возможности смогут появиться и в других браузерах.

Компоненты

Для реализации этого небольшого проекта контроля Ардуино через браузер нам понадобятся всего лишь:

  1. Плата Arduino
  2. USB кабель

Примеры использования

В своей диссертации о будущем изучения Arduino, Arduino Action, я использовал этот последовательный веб-протокол для установления связи между Arduino и экосистемой телефонов.

Этот проект был создан для опытного прототипирования с Илзе Поуэльс, Себастьяном де Кабо Португал и Кэролайн Вегнер.

В этом прототипе мы использовали связь Bluetooth, но если бы мы знали про webSerial, то это было бы более оптимальным решением.

Камера подключалась к ноутбуку, на котором работал P5.js (ниде) для запуска PoseNet (распознает вашу позу с помощью компьютерного зрения) и Key Nearest Neighbor (модель машинного обучения, которую можно обучить отличать одни позы от других).

Скрипт JS

Скрипт P5.js ниже:

<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/addons/p5.sound.min.js"></script>
    <link rel="stylesheet" type="text/css" href="style.css">
    <meta charset="utf-8" />

  </head>
  <body>
    <div id="serialControls">
    <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>
    </div>
<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.
*/

var val1 = 0;
var val2 = 0;
    //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, serialReader;
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() {
    disconnect()
    //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;

        serialReader = 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"
        }
        if (e == "TypeError: Failed to execute 'requestPort' on 'Serial': 1 argument required, but only 0 present."){
        e += "\n Use Google Chrome and enable-experimental-web-platform-features"
        }
      if (e == "NetworkError: Failed to open serial port."){
      e +="Try unplugging the Arduino and connect again"
      }
        disconnect()
        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 (serialReader) {
        await serialReader.cancel();
        await inputDone.catch(() => { });
        serialReader = 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 serialReader.read();
        if (done === true){
            break;
        }
        //When recieved something add it to the big textarea
        receiveText.value += value;
      
        serialString = receiveText.value;
        //Scroll to the bottom of the text field
        var patt = new RegExp(/([0-9]{1,6}), ([0-9]{1,6})\n/m);
  var res = patt.exec(serialString);
  if(res != null){
      serialString = serialString.replace(patt,"");//"["+res[1]+", "+res[2]+"]");
  val1 = res[1]
  val2 = res[2]
  }
   receiveText.value = serialString
        receiveText.scrollTop = receiveText.scrollHeight;
    
}
}
    </script>

    <script src="sketch.js"></script>
  </body>
</html>

Как это работает

Установите последнюю версию Google Chrome.

Включите:

“enable-experimental-web-platform-features”

для этого идем сюда:

chrome://flags/#enable-experimental-web-platform-features

Вы должны теперь иметь возможность общаться с помощью браузера с вашим Arduino.

Можете проверить это на:

https://geertroumen.com/projectHub/serial_terminal.html

либо загрузите некоторый код в Arduino для отправки данных, либо проверить индикаторы RX / TX при отправке сообщений, чтобы убедиться, что он работает.

Если вы хотите попробовать это самостоятельно в P5.js (см.выше), перейдите к этому скетчу и загрузите скетч Arduino:

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);
}

Объяснение Javascript

В браузере используется язык сценариев JavaScript, именно здесь вы можете брать значения из Arduino и делать с ними все; он также может отправлять значения обратно в Arduino и использовать другие периферийные устройства, такие как мышь, клавиатура, камера, микрофон и т. д.

Наиболее важными функциями в коде javascript для подключения к Arduino являются функции записи и чтения. В этом примере writeToStream() является эквивалентом Serial.print для компьютера.

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;
    }
}

В этом случае значение каждого пакета байтов добавляется в поле recieveText.

Вот один простой пример того, как вы можете использовать кнопку для отправки определенного символа или строки в 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)

Итоговое видео

Итоговое видео от автора (англ.) ниже:

В этом видео автор показал как Arduino можно подключить через последовательный API к браузеру Chrome.

Когда Arduino был запущен, то у меня были проблемы с поиском последовательного порта в интерфейсе последовательного API; просто выключите Arduino, подключите и отключите плату, и вы сможете её найти.

Иногда соединение было нестабильным, если я не мог подключиться; отключите Arduino, обновите страницу, нажмите «Подключиться», подключите Arduino и подключитесь к нему.

Исходя из опыта такой метод кажется наиболее надежным.

31 августа 2020 в 15:32
Опубликовано: | Оригинал
Уроки,

Добавить комментарий

Ваш E-mail не будет никому виден. Обязательные поля отмечены *