Проект в котором мы рассмотрим новую возможность браузера Google Chrome по связи с Ардуино и последовательными устройствами.
О проекте
Недавно Google Chrome добавил функциональность для связи с последовательными устройствами из браузера, что позволит в дальнейшем легко реализовывать интерактивные проекты.
Возможность комбинировать Arduino или физические вычисления с браузерными технологиями может дать дизайнерам и техническим специалистам возможности для более быстрого и дешевого прототипирования потрясающих приложений.
В прошлом Arduino обычно подключалась к Processing для создания интерактивных проектов, продуктов или услуг. Хотя это все еще широко используемый способ подключения Arduino к компьютеру, подключение к браузеру может предоставить более широкий спектр возможностей и требует меньше настроек.
Однако, до недавнего времени, подключение Arduino к веб-браузеру было все еще сложной задачей (веб-сокеты и сервер на устройстве), но теперь, с введением последовательного API, вы можете подключиться к любому последовательному устройству из браузера одним нажатием кнопки.
Одним из огромных преимуществ является то, что программное обеспечение, которое запускается в браузере, легко распространять и запускать на различных устройствах и операционных системах.
Эта система должна работать с любым Arduino, имеющим последовательное соединение с компьютером. На данный момент только Google Chrome поддерживает веб-последовательный порт, если включены экспериментальные функции веб-платформы, но надеемся, что такие возможности смогут появиться и в других браузерах.
Компоненты
Для реализации этого небольшого проекта контроля Ардуино через браузер нам понадобятся всего лишь:
- Плата Arduino
- 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 и подключитесь к нему.
Исходя из опыта такой метод кажется наиболее надежным.