undefined

bokuweb.me

chrome拡張で”あーるえすにーさんにーしー”通信をやってみる

はじめに

今回は若干組み込みよりですが、使用する言語はCoffeeScriptです。 htmlやcss、JavaScriptなどブラウザで動作する技術を使用し、組み込み機器と通信しよう!という試みです。

あーるえすにーさんにーしー?

RS-232C(あーるえすにーさんにーしー)です。

http://ja.wikipedia.org/wiki/RS-232

モデム等と通信するために設計された通信方式です。古いPCには必ずといっていいほどついていましたが(D-SUB 9pin(でぃーさぶきゅーぴん)ってやつですね)、今や、ついている機種のほうが少ないと思います。ただ、組み込み業界ではまだまだ現役です。

PCについていない場合、以下のような変換をケーブルを使うのが一般的じゃないでしょうか。この変換を使用することでUSB通信がRS-232Cレベルの通信に変換されます。PCから見るともともと実装されているポートは「COMポート」、USB等で拡張したポートは「仮想COMポート」という扱いになります。

iBUFFALO USBシリアルケーブル(USBtypeA to D-sub9ピン)1.0m ブラックスケルトン BSUSRC0610BS

iBUFFALO USBシリアルケーブル(USBtypeA to D-sub9ピン)1.0m ブラックスケルトン BSUSRC0610BS

こんなのを買ってUSBに接続します。

RS-232Cは約-3V~-15Vを『1』、約+3V~+15Vを『0』とする負論理の規格です。大抵の場合、RS-232Cドライバ・レシーバというICによって+5Vや+3.3Vのレベルに変換されマイコンに接続されます。

今回どんなの作るの?

味気ないですが、COMポートを選択し、『send』を押すことで固定データ[0x01, 0x02, 0x03, 0x04, 0x05]がCOMポートの送信ラインから送信されるというサンプルです。送信ラインをそのまま受信ラインに直結(ループバック)させることで送信データ[0x01, 0x02, 0x03, 0x04, 0x05]がそのまま受信できることを確認できると思います。

f:id:bokuweb:20150203211054j:plain

chrome拡張を作る

chrome拡張にはCOMポートにアクセスする機能が用意されています。 この機能を使うことでchrome上から通信ができます。

用意するファイル

  • manifest.json
  • window.html
  • icon.png
  • background.js
  • jquery-1.11.2.js
  • chromeserial.js(chromeserial.coffee)
  • app.js(app.coffee)

manifest.json

この拡張がどういうものかを定義します。 ここで"serial"を許可しておかないと通信はできません。

{
  "name": "chrome_serial_sample",          // app名
  "description": "chrome_serial_sample",   // 説明
  "version": "1.0",                        // バージョン
  "manifest_version": 2,                   // マニフェストバージョン
  "app": {
    "background": {
      "scripts": ["js/background.js"]      // backgroundで動作するJSの指定
    }
  },
  "icons": { "128": "icon.png" },  // iconのサイズと指定
  "permissions": [
     "serial"                      // serial使用許可
  ]

window.html

COMポートの選択や送信ボタンなどをhtmlでwindow.htmlに書いていきます。今回は味気ないですがcssで装飾できるので見た目は好きなようにできます。

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
        <title>serialsample</title>
    </head>
    <body>
        <span>COMポートの選択</span>
        <select value="" id="ports" ></select>
        <a href="#" id="com-open">open</a>
        <a href="#" id="com-close">close</a>
        <a href="#" id="send">send</a>

        <!-- Load JS here for greater good =============================-->
        <script src="js/jquery-1.11.2.min.js"></script>
        <script src="js/chromeserial.js"></script>
        <script src="js/app.js"></script>
    </body>
</html>

icon.png

好きなものを用意してください。

background.js

windowサイズ等を指定します。 いじる必要はあまりないかと思います。 ほぼサンプルのまま。

chrome.app.runtime.onLaunched.addListener(function(){
  chrome.app.window.create('window.html', {
    'bounds': {
      'width': 500,
      'height': 400
    }
  });
});
  • chromeserial.js(chromeserial.coffee)

chrome.serialのラッパーです。chrome.serialを使うにはひと手間いるのでclass化してその中で処理しています。

class @Serial

    connectionId = null

    constructor: (parms) ->
        for name, value of parms
            @[name] = value
        @getPorts()

    getPorts: ->
        chrome.serial.getDevices (ports) =>
            for i,value of ports
                port = value.path
                @select.appendChild new Option port, port
      return

    startConnection: ->
        portName = @select.childNodes[@select.selectedIndex].value
        config =
            bitrate : @bitrate
            dataBits : @dataBits
            parityBit : @parityBit
            stopBits : @stopBits

        chrome.serial.connect portName, config, (openInfo) ->
            connectionId = openInfo.connectionId
            console.log "connectionId = " + connectionId
            return
        return

    endConnection: ->
        chrome.serial.disconnect connectionId, (result) ->

    startRecieve: ->
        console.log "recieve start!!"
        chrome.serial.onReceive.addListener @getData

    getData: (readInfo) =>
        data = new Uint8Array readInfo.data
        @recieveCallback(data)

    sendData: (message) ->
    buffer = new ArrayBuffer(message.length)
    array = new Uint8Array(buffer)
    for value, i in message
        array[i] = value
    chrome.serial.send connectionId, buffer, (sendInfo) =>
        @sendCallback sendInfo
  • app.js(app.coffee)

アプリケーション部分です。 $comOpenButtonがクリックされるとCOMポートをオープンし、受信を開始します。 $sendButtonがクリックされたときに["0x01, 0x02, 0x03, 0x04, 0x05"]を送信しています。 受信が来たらrecieveCallback内でconsoleに受信データを表示しています。 受信したひとは送信ラインと受信ラインを直結(ループバック)してください。

D-SUB9pinのピンアサインはこうなってます。

f:id:bokuweb:20150203211259j:plain

2pinが受信データ、3pinが送信データです。他にもごちゃごちゃありますが基本的には送信データ、受信データ、GNDの3本あれば通信できます。

$comOpenButton = $('#com-open')
$comCloseButton = $('#com-close')
$sendButton = $('#send')

$comOpenButton.click (event) ->
  serial.startConnection()
  serial.startRecieve()

$comCloseButton.click (event) ->
  serial.endConnection()

$sendButton.click (event) ->
  message = ["0x01, 0x02, 0x03, 0x04, 0x05"]
  serial.sendData(message)

recieveCallback = (data) ->
  console.log "recieve data!!"
  console.log data

sentCallback  = (info) ->
  console.log "send!!"

serialConfig =
  select : document.getElementById 'ports' # ポート名を表示するselect要素ID名
  bitrate : 9600                           # ボーレート
  dataBits : "eight"                       # データ数
  parityBit : "no"                         # パリティビット
  stopBits : "one"                         # ストップビット
  recieveCallback : recieveCallback        # データ受信完了時コールバック関数
  sendCallback : sentCallback              # データ送信完了時コールバック関数

serial = new Serial serialConfig

デモ

chrome -> 『設定』 -> 『拡張機能』で『デベロッパーモード』をチェック

f:id:bokuweb:20150203211431j:plain

f:id:bokuweb:20150203211446j:plain

『パッケージ化されていない拡張機能を読み込む』でサンプルの入ったディレクトリを選択

f:id:bokuweb:20150203211512j:plain

『起動』でwindowが立ち上がる

f:id:bokuweb:20150203211527j:plain

『open』を押してCOMポートをオープン consoleに接続idと受信開始メッセージが表示される

f:id:bokuweb:20150203211547j:plain

『send』を押すとデータ送信される。 ループバックしている場合じゃ以下のように送信データが受信されます。

f:id:bokuweb:20150203211629j:plain

これなにがいいの?

  • htmlとjavascriptをちょっと知ってるよ!って組み込み技術者がPC側のシミュレータなどを簡単に作れる
  • jQueryなど既存のJSライブラリを使える。(リッチな表現が簡単にできる)
  • 以前紹介したc3.jsなどを使えば組み込み基板からのデータをリッチなチャートにできる

簡単にリッチなチャートが作れるC3.jsを使ってみた - ぼくのかんがえたさいきょうのうぇぶさーびす

ってとこかと思います。c3.jsとかhighchart.jsとか使うと綺麗なチャートがさくっとできちゃうんでteratermとかでセンサーデータ眺めてる人にこういうの作ってあげると「うおっ!」てなるかもしれません。

リポジトリ

bokuweb/chrome_serial_sample · GitHub