Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TinyGoでIoTを始めよう

irieda
April 20, 2019

 TinyGoでIoTを始めよう

TinyGoというGo言語サブセットを使って
PC-OSの無い環境の組み込み開発を始める方法の紹介。

irieda

April 20, 2019
Tweet

More Decks by irieda

Other Decks in Technology

Transcript

  1. TinyGoͰIoTΛ࢝ΊΑ͏

    View Slide

  2. ͓લ୭Αʁ
    ϝΧτϩιϑτ԰
    Pythonista -> Gopher
    झຯͰGoʹ޲͔ͳ͍෼໺ͷ։୓
    Goྺ͸̒೥ऑ͘Β͍
    αΠτ:
    ձࣾ: 144Lab(2017/07/01 ͔Β৽໊ࣾ)
    HN: @nobonobo
    http://golang.rdy.jp/

    View Slide

  3. ૊ΈࠐΈ։ൃͬͯʁ

    View Slide

  4. ૊ΈࠐΈͱݴͬͯ΋ʁ
    େผͯ͠
    PC޲͚OSͷ্Ͱ૊ΈࠐΈ
    PC޲͚OSແ͠Ͱ૊ΈࠐΈ
    ʢ૊ΈࠐΈ޲͚OS·ͨ͸OSແ͠ʣ
    ͱ͍͏̎छྨ͕͋Γ·͢ɻ

    View Slide

  5. PC޲͚OSͷ্Ͱ૊ΈࠐΈ
    PCʹ͍ۙখܕϘʔυʢRaspberryPiͳͲʣͰ
    Linux΍Windows10ͷ্ʹ
    ΞϓϦΛ࣮૷͢ΔελΠϧ
    ͕ૉ੖Β͍͠
    ͨͩ͠ɺిݯ֬อ͕ඞਢ
    Ϟϊͷબ୒ࢶ͸࣮࣭̎୒
    RaspberryPiܥ
    ߴՁͳϘʔυͷྨ
    https://gobot.io

    View Slide

  6. PC޲͚OSແ͠Ͱ૊ΈࠐΈ
    Goͷෆಘҙ෼໺
    Goͷཪํͷػೳηοτ͕OSʹґଘ
    goroutineͷεέδϡʔϥ΍GCͳͲ
    OSͷແ͍؀ڥʹҠ২͢Δίετ͕ߴ͍
    ௿ϨΠϠͷI/Oࢧԉػೳ͕΋ͱ΋ͱແ͍
    PCͱҧ͍෺ཧతʹଟ༷͗͢Δ؀ڥ

    View Slide

  7. ૊ΈࠐΈ։ൃͷੈք
    ιϑτ΢ΣΞͷ஌͕ࣝٻΊΒΕΔ
    ௿ϨΠϠʔͷ஌ࣝ΋ٻΊΒΕΔ
    ϋʔυ΢ΣΞͷ஌ࣝ΋গ͠ٻΊΒΕΔ
    ։ൃ؀ڥΛ੔͑Δͷʹίετ͕͔͔Δ
    ૊ΈࠐΈ is Hard!

    View Slide

  8. ͦͯ͠ɾɾɾ
    C/C++͕σϑΝΫτελϯμʔυ
    C͚ͩͳΒ·ͩ͠΋C++͸πϥΠ
    ॲཧͷ࣮ମΛӅ͢ͷ্͕ख͗͢Δ
    ࠔ೉ͳґଘղܾ
    include஍ࠈͱIFDEF஍ࠈ
    ΦʔόʔϩʔυʹςϯϓϨʔτ
    ૊ΈࠐΈ is Hard!

    View Slide

  9. C/C++ͷ୅ΘΓʹGoͳΒʁ
    ϦʔμϏϦςΟ࠷ߴʂ
    ΤϥʔΛపఈͯ͠νΣοΫ͢ΔจԽʂ
    undefined-behavierʹ೰·͞Εͳ͍ʂ
    ґଘղܾʹgo-get͕࢖͑Δʂ
    ૊ΈࠐΈ͕গ͠਎ۙʹͳΔ͔΋ʁʂ

    View Slide

  10. ͱ͍͏Θ͚Ͱ
    TinyGoͰ͢Αʂʂ

    View Slide

  11. ઌ݄ϗοςϯτϦೖΓ
    https://tech.144lab.com/entry/tinygo

    View Slide

  12. λʔήοτྫ

    View Slide

  13. micro:bit
    ରԠ։ൃπʔϧͷ਺͕τοϓΫϥε
    ϒϩοΫํࣜͰখֶੜ΋ϓϩάϥϛϯάOK
    ϒϩοΫʹ๞͖ͨΒJS,TS΁
    ArduinoͰ΋PythonͰ΋Ruby,Jacvascript,LuaͳͲͳͲ
    ϓϩ޲͚SEGGER Embedded StudioͰ΋OK

    View Slide

  14. circuit playground express
    ౥ࡌΪϛοΫ਺͕τοϓΫϥε
    ϑϧΧϥʔ֊ௐ͖ͭLED̍̌ݸ
    εϐʔΧʔʹϚΠΫ
    ޫྔηϯαɺԹ౓ɾ࣪౓ηϯα
    ̒࣠ʢՃ଎౓ɾ֯଎౓ʣηϯα
    IRϦϞίϯૹड৴
    λονηϯγϯά
    UART/USB/SPI/I2C/etc...

    View Slide

  15. ࣮ࡍʹ͍ΖΜͳίʔυΛ
    ίϯύΠϧͯ͜͠ΕΒͰ
    ಈ͔ͯ͠Έ·͠ΐ͏ʂ

    View Slide

  16. TinyGoͷ࢖͍ํ
    dockerϕʔε͕ࠓ͸ΦεεϝͰ͢ɻ
    ʢdevϒϥϯνϏϧυ͸େม ˍ ߴස౓Ͱґଘ͸มߋ͞Ε
    Δʣ
    $ docker run -it --rm tinygo/tinygo tinygo version
    tinygo version 0.4.1 linux/amd64

    View Slide

  17. ͨ·ʹΞοϓσʔτͯ͠Έ·͠ΐ͏
    $ docker pull tinygo/tinygo:latest
    latest: Pulling from tinygo/tinygo
    Digest: sha256:821ad71e7d9b3fe46a84a5818e52d3d3596e0d8f3855f8407b917a37371b2b23
    Status: Image is up to date for tinygo/tinygo:latest

    View Slide

  18. sample̍
    ͍ΘΏΔLνΧʢ૊ΈࠐΈͰͷHelloWorldʣ
    package main
    import (
    "machine"
    "time"
    )
    func main() {
    led := machine.GPIO{machine.LED}
    led.Configure(machine.GPIOConfig{Mode: machine.GPIO_OUTPUT})
    for {
    led.Low()
    time.Sleep(time.Millisecond * 500)
    led.High()
    time.Sleep(time.Millisecond * 500)
    }
    }

    View Slide

  19. Ϗϧυ
    output.uf2 --Drag&Drop--> CIRCUITPYσόΠε
    ͜Ε͚ͩͰλʔήοτʹॻ͖ࠐ·ΕΔ
    $ go mod init github.com/nobonobo/examples/sample1
    $ PACKAGE_PATH = github.com/nobonobo/examples/sample1
    $ PROJECT_PATH = /go/src/$PACKAGE_PATH
    $ docker run -it --rm $PWD:$PROJECT_PATH -w $PROJECT_PATH \
    tinygo/tinygo tinygo build -target=circuitplay-express -o output.uf2 .

    View Slide

  20. TinyGoͷఏڙόε࣮૷(1)
    ڞ௨Ͱఏڙ͢Δόε
    GPIO(൚༻ೖग़ྗϐϯ)
    ADCʢΞφϩάܭଌʣ
    PWMʢαʔϘɺύϫʔίϯτϩʔϧ޲͚ʣ
    UARTʢPCͱͷ࿈ܞ༻ʣ
    SPIʢখ͞ͳσόΠεͱͷ࿈ܞ༻ʣ
    I2Cʢখ͞ͳσόΠεͱͷ࿈ܞ༻ʣ

    View Slide

  21. TinyGoͷఏڙόε࣮૷(2)
    Ұ෦ͷλʔήοτ
    DACʢΞφϩάిѹൃੜʣ

    View Slide

  22. ΞʔΩςΫνϟผͷఏڙػೳ
    ϨδελΞΫηε
    ΠϯϥΠϯΞηϯϒϥ
    λΠϚʔɺUARTϋϯυϦϯά
    ΄ͱΜͲͷλʔήοτͰ
    ʮprintlnʯͰ
    γϦΞϧϙʔτʹσόοάϩάΛग़ྗͰ͖Δɻ

    View Slide

  23. पลσόΠεผυϥΠόʔ
    Device Name Interface Type
    SPI
    I2C
    I2C
    I2C
    GPIO
    UART
    I2C
    I2C
    I2C
    GPIO
    https://github.com/tinygo-org/drivers
    APA102 RGB LED
    BH1750 ambient light sensor
    BlinkM RGB LED
    BMP180 barometer
    "Easystepper" stepper motor controller
    ESP8266/ESP32 AT Command set for WiFi/TCP/UDP
    MAG3110 magnetometer
    MMA8653 accelerometer
    MPU6050 accelerometer/gyroscope
    WS2812 RGB LED

    View Slide

  24. ֎෦ύοέʔδͱdocker
    ґଘ͢ΔύοέʔδΛ௥Ճ͍ͨ͠ʂʂ
    ͋ΕʁdockerϕʔεͩͱͲ͏͢Δʁʂ
    ͦ͜Ͱgo modͰ͢Α
    $ export GO111MODULE=on
    $ go mod github.com/..../sample1
    $ go get github.com/tinygo-org/drivers/ws2812
    $ go mod vendor

    View Slide

  25. ͢Δͱʁ
    vendor/
    github.com/
    tinygo-org/
    drivers/
    ws2812/
    main.go
    ͖ͬࣔͨ͞͠dockerίϚϯυͰίϯςφ಺͔Β
    ws2812ύοέʔδ͕ࢀরՄೳʹͳΔɻ

    View Slide

  26. LEDετϦοϓυϥΠόΛ࡞Δ
    package main
    import (
    "device/arm"
    "image/color"
    "machine"
    "github.com/tinygo-org/drivers/ws2812"
    )
    // NeopixelDriver represents a connection to a NeoPixel
    type NeopixelDriver struct {
    pin machine.GPIO
    device ws2812.Device
    pixelCount int
    pixels []color.RGBA
    }
    // NewNeopixelDriver returns a new NeopixelDriver

    View Slide

  27. ͦͯ͠ಈ͔ͯ͠ΈΔ
    package main
    import (
    "image/color"
    "machine"
    "time"
    )
    const NUM_PIXELS = 10
    func main() {
    neo := NewNeopixelDriver(machine.GPIO{machine.NEOPIXELS}, NUM_PIXELS)
    n := 0
    var pows = []uint8{255, 127, 63, 31, 15, 7, 3, 1, 0, 0}
    for {
    for i := 0; i < NUM_PIXELS; i++ {
    pow := pows[NUM_PIXELS-1-i]
    neo.SetPixel((n+i)%NUM_PIXELS, color.RGBA{R: pow, G: pow, B: pow})
    }

    View Slide

  28. DEMO
    ໨͕ʔɾɾ໨͕ʔʂʂ

    View Slide

  29. ໌Δ͞ʹԠͯ͡LEDΛ౮͢
    package main
    import (
    "image/color"
    "machine"
    "time"
    )
    const NUM_PIXELS = 10
    func main() {
    machine.InitADC()
    sensor := machine.ADC{machine.A8}
    sensor.Configure()
    neo := NewNeopixelDriver(machine.GPIO{machine.NEOPIXELS}, NUM_PIXELS)
    for {
    for i := 0; i < NUM_PIXELS; i++ {
    pow := uint8(sensor.Get() / 256)
    neo.SetPixel(i, color.RGBA{R: pow, G: pow, B: pow})

    View Slide

  30. DEMO

    View Slide

  31. GoͬΆ͘ॻ͘
    package main
    import (
    "image/color"
    "machine"
    "time"
    )
    const NUM_PIXELS = 10

    View Slide

  32. Ϙλϯ؂ࢹؔ਺
    func observer(event chan int) {
    btnA := machine.GPIO{machine.BUTTONA}
    btnA.Configure(machine.GPIOConfig{Mode: machine.GPIO_INPUT_PULLDOWN})
    btnB := machine.GPIO{machine.BUTTONB}
    btnB.Configure(machine.GPIOConfig{Mode: machine.GPIO_INPUT_PULLDOWN})
    next := make([]bool, 2)
    prev := make([]bool, 2)
    prev[0], prev[1] = btnA.Get(), btnB.Get()
    for {
    time.Sleep(20 * time.Millisecond)
    next[0], next[1] = btnA.Get(), btnB.Get()
    for i := range next {
    if !prev[i] && next[i] {
    event }
    }
    prev[0], prev[1] = next[0], next[1]
    }
    }

    View Slide

  33. ϨϯμϦϯάؔ਺
    func renderer(ch chan *NeopixelDriver) {
    for {
    v := v.Show()
    }
    }

    View Slide

  34. mainؔ਺
    func main() {
    events := make(chan int)
    go observer(events) // Ϙλϯ؂ࢹλεΫىಈ
    ɹneo := NewNeopixelDriver(machine.GPIO{machine.NEOPIXELS}, NUM_PIXELS)
    ch := make(chan *NeopixelDriver)
    go renderer(ch) // ϨϯμϥʔλεΫىಈ
    prev, next := 0, 0
    neo.SetPixel(prev, color.RGBA{R: 10, G: 10, B: 10})
    ch for {
    select {
    case v := switch v {
    case 0:
    println("buttonA pressed")
    next++
    if next >= NUM_PIXELS {

    View Slide

  35. DEMO

    View Slide

  36. ·ͱΊ
    ฒߦॲཧ͕௒ॻ͖΍͍͢ʂ
    ݱঢ়ͷ௿ϨΠϠ֦ுखஈ
    ΠϯϥΠΞηϯϒϥ
    SVCall
    CGOαϙʔτ΍ߴϨϕϧαϙʔτ͕ෆ଍
    TinyGoͷϏϧυͰ͸go-mod͸·ͩ࢖͑ͳ͍
    ͕ɺdockerͱͷซ༻ͰͳΜͱ͔ͳΔ

    View Slide

  37. ࠓޙͷൃల

    View Slide

  38. ׆ൃͳ׆ಈ
    BLEϥΠϒϥϦରԠ
    CGOαϙʔτ
    Ճ଎౓ηϯαͳͲͷυϥΠόʔ
    ESPγϦʔζͷαϙʔτ

    View Slide

  39. ݱঢ়ͷωοτػೳ
    ҎԼͷΞΠςϜΛ࢖͏͜ͱͰ࣮ݱՄೳ
    ESP8266 or ESP32 ͱ͍͏֨҆Wi-Fiػೳ෇͖ϚΠίϯ
    driversʹ͋Δ
    ࠓճͷλʔήοτΛESPϞδϡʔϧͱUARTͱ͍͏̎৴߸
    Λͭͳ͙
    TCP/UDP௨৴͕ՄೳʹͳΔ
    ESP8266/ESP32 AT Command set for
    WiFi/TCP/UDP

    View Slide

  40. ࠓޙͷωοτ઀ଓ
    LINE ThingsͷΑ͏ʹࠓ΍୭΋͕࣋ͭεϚϗΛ
    BLEtoΠϯλʔωοτͷϋϒʹͪ͠Ό͏ΞΠσΟΞ΋
    LoRaɺNB-IoTϞδϡʔϧ΋΅ͪ΅ͪೖखՄೳʹͳΓͭͭ
    ͋Γ·͢

    View Slide

  41. WebAssemblyग़ྗ
    ຊՈΑΓ΋ޮ཰తͳ੒ՌΛग़ͤΔ
    syscall/jsαϙʔτͳͲ΋࢝·ͬͯΔ

    View Slide

  42. IoT։ൃ͸ͲΜͲΜ਎ۙʹ
    ͳ͖ͬͯͯ·͢Αʂ

    View Slide

  43. ͓ΘΓ

    View Slide