TinyGoとWasmについて簡単にまとめてみた

はじめに

この記事はVoicyアドベントカレンダー24日目の記事です。

こんにちは、ミック ( @mickbare )です。 Voicyではバックエンドの開発を担当しています。

最近、噂のWasm(WebAssembly)とTinyGoについて、概要と導入について簡単にまとめました。

Wasm?(WebAssembly)

Webブラウザなどで利用できるバイナリー形式のアセンブリ風言語です。 Google ChromeのV8など、Wasmを解釈できる仮想マシンVM)上で動作させます。 VMと言っても、JVMなどと同じような形式で、いわゆるバイトコードインタプリタを介して実行されます。

登場は比較的新しく、FlashやActive X, Java Appletなどのブラウザプラグインの一種という位置づけです。 そもそもはJSの高速化の文脈で登場しているため、JavaScriptと連携して動作させられるように設計されています。

ただし、Wasm自体はバイナリとそのバイナリを動かす仮想マシンの仕様でありブラウザに依存しません。 そこで近年はWASIという仕様が策定されるなどブラウザ外で動かすための活動が活発です。

ブロックチェーン上で動かしたり、コンテナの代わりにKubernetes上で動かす話もあるようです。

TinyGo?

TinyGoはGolangマイコン向けのバイナリーをビルドするためのコンパイラとランタイムの実装です。 ランタイムを小さくすることで、記憶容量に限りがあるマイコン向けにビルドサイズを小さくし、また標準のコンパイラではサポートされていないマイコンの命令セットもサポートします。 同じくビルドサイズが小さくなるWasmと相性が良いです。 Goの公式もTinyGoの使用を推奨しています。 現状TinyGoはAVR(Arudino)やARM(Respberry Pi)などで動かせるようになっています。

マイコン向けにカスタムしただけなので記述自体はGoとほぼ変わりません。 既存のコンパイラの一部分を抜き出したり拡張したものをサブセット(部分集合)と呼んだりします。

TinyGoを試してみる

TinyGoのインストール、ドキュメントまわり、サンプルコードなどをまとめました。

TinyGo のインストール

公式のドキュメントに従ってインストールしてください。 ※TinyGo の実行には Goが必要なので事前にインストールが必要です。

https://tinygo.org/getting-started/ - https://tinygo.org/getting-started/install/linux/ - https://tinygo.org/getting-started/install/macos/ - https://tinygo.org/getting-started/install/windows/ - https://tinygo.org/getting-started/install/using-docker/

主要なドキュメントとか

tinygo で使用するmachine packageのドキュメント https://tinygo.org/docs/reference/microcontrollers/machine/

tinygoでサポートされているデバイスの仕様 https://tinygo.org/docs/reference/devices/

githubのexample https://github.com/tinygo-org/drivers/tree/v0.18.0/examples

最初はdocmentやexampleなどコードベースで動かし方を確認するのが良いと思います。

TinyGo Playground

Go Playgroundと同じく、公式からブラウザ上の実行環境が公開されています。 https://play.tinygo.org/

Arudinoとか買わなきゃ!の前にこちらで軽く遊んでみて感じを掴むのも良いかもしれません。 デバイス制御についてあれこれかくとTinyGoではなくマイコン開発の話になってしまうので、 とりあえず、クリスマスイルミネーション仕様で適当にギラギラ光らせてみたCircuit Playground ExpressのLチカコードだけ置いてみます。

ちなみに、Circuit Playground ExpressはいろんなセンサやLEDを搭載した半田付け不要のオールインワンな開発基盤です。 TinyGo Playgroundのデバイスリスの中ではリッチなLチカができそうだったのでピックアップしました。

www.switch-science.com

package main

import (
    "image/color"
    "machine"
    "time"
    "tinygo.org/x/drivers/ws2812"

)
var (
    led = machine.LED
    neo = machine.NEOPIXELS //WS2812
    table = [10]color.RGBA{
        color.RGBA{ R:0xE6, G:0x00, B: 0x12 },
        color.RGBA{ R:0xF3, G:0x98, B: 0x00 },
        color.RGBA{ R:0xFF, G:0xF1, B: 0x00 },
        color.RGBA{ R:0x00, G:0x99, B: 0x44 },
        color.RGBA{ R:0x00, G:0x68, B: 0xB7 },
        color.RGBA{ R:0x1D, G:0x20, B: 0x88 },
        color.RGBA{ R:0x92, G:0x07, B: 0x83 },
        color.RGBA{ R:0xFF, G:0x00, B: 0x00 },
        color.RGBA{ R:0x00, G:0xFF, B: 0x00 },
        color.RGBA{ R:0x00, G:0x00, B: 0xFF },
    }
)



func main() {

    led.Configure(machine.PinConfig{Mode: machine.PinOutput})
    neo.Configure(machine.PinConfig{Mode: machine.PinOutput})

    ws := ws2812.New(neo)

    var leds [10]color.RGBA
    offset := 0
    for {
        for i := 0; i < len(leds); i++ {
            index := (i + offset) % len(leds)   
            leds[i] = table[index]
        }
        offset++

        ws.WriteColors(leds[:])

        time.Sleep(100 * time.Millisecond)
    }
}

Circuit Playground ExpressにRGB LEDが10個ついてるので、 コード自体は、カラーテーブルを用意してリングバッファで色の配置をくるくる動かしてるだけです。

終わりに

Go Conference 2021 Authmn TinyGo WorkshopがTinyGoをめちゃくちゃ詳しく解説していて入門に打ってつけなので、Playgroundで遊んでみたりしてなんか良さそうだなと思った方はぜひこちらも確認してみてください! https://gocon.jp/2021autumn/sessions/workshop_a/

次回は、@awakot_56さんです!