Edited at

Arduino Unoでtinygoをやってみた


はじめに

知人の手伝いで行った同人ハードウェアフェスの立ち話でtinygoなるものを聞きました。

golangをLLVMでCに変換してBluePill(STM32F103)や micro:bitなどnrfシリーズで動作するとか!

https://github.com/tinygo-org/tinygo

https://tinygo.org/

Screenshot from 2019-02-12 00-34-49.png

emgoというのもBluePillやnrfシリーズに対応してて、以前ちょっと触ってみたのですがご無沙汰なので、こっちをArduino Unoで試したいと思います。

https://github.com/ziutek/emgo


環境構築

公式ページの手順に従い必要なものを入れます。

https://tinygo.org/getting-started/requirements/

以下2つが必要になります。


  • Go 1.11+

  • LLVM 7 (for example, from apt.llvm.org

$ go version

go version go1.11 linux/amd64

go はもともと入っていたのでLLVMを入れます。

※ちなみにOSはUbuntu 18.04でやってます。

http://apt.llvm.org/

$ wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -

$ sudo apt-get update
$ sudo apt-get install clang-7 lldb-7 lld-7
$ sudo apt-get install libllvm-7-ocaml-dev libllvm7 llvm-7 llvm-7-dev llvm-7-doc llvm-7-examples llvm-7-runtime

Arduinoで試してみるので以下を入れます


  • binutils (avr-objcopy) for flashing.

  • GCC (avr-gcc) for linking object files.

  • libc (avr-libc), which is not installed on Debian as a dependency of avr-gcc.

  • avrdude for flashing to an Arduino.

$ sudo apt-get install gcc-avr binutils-avr avr-libc

$ sudo apt-get install avrdude

必要なものがそろったらtinygoをセットアップします。

$ go get -u github.com/tinygo-org/tinygo

# github.com/tinygo-org/tinygo/loader
/go/src/github.com/tinygo-org/tinygo/loader/libclang.go:16:10: fatal error: clang-c/Index.h: No such file or directory
#include <clang-c/Index.h> // if this fails, install libclang-7-dev
^~~~~~~~~~~~~~~~~
compilation terminated.

失敗しました。メッセージの通りにlibclang-7-devを入れて再チャレンジ

$ sudo apt-get install libclang-7-dev

$ go get -u github.com/tinygo-org/tinygo
$ go install github.com/tinygo-org/tinygo
$ which tinygo
/go/bin/tinygo

インストールできました。

Home > Getting Started > Usage をやってみます。

/tinygo/srcに移動して、tinygo run examples/testを打ってみます。

$ tinygo run examples/test/

Hello world from Go!
The answer is: 42
5 ** 2 = 25
3 + 12 = 15
fib(11) = 89
sumrange(100) = 5050
strlen foo: 3
map length: 2
map read: answer = 42
answer = 42
foo = 3
map length: 1
map read: data = 3
data = 3
len/cap foo: 4 4
len/cap bar: 3 5
len/cap foo[1:2]: 1 3
foo[3]: 5
sum foo: 12
copy foo -> bar: 3
sum bar: 7
thing: foo
is int: 5
is byte: 120
is string: foo
is Thing: foo
is *Thing: foo
is *Thing: foo
is Doubler: 6
Stringer.String(): foo
Stringer.(*Thing).String(): foo
hello from function pointer: 5
deferring...
...run as defer 2
...run as defer 1
bound method: foo
thing inside closure: foo
inside fp closure: foo 3
lower to upper char: h -> H

tiny-goがあるフォルダに移動して、make gen-deviceを実行します。

$ cd /go/src/github.com/tinygo-org/tinygo

$ make gen-device
./tools/gen-device-avr.py lib/avr/packs/atmega src/device/avr/
lib/avr/packs/atmega/AT90CAN128.atdf
lib/avr/packs/atmega/AT90CAN32.atdf
lib/avr/packs/atmega/AT90CAN64.atdf
lib/avr/packs/atmega/AT90PWM1.atdf

省略

src/device/stm32/stm32l1xx.go
src/device/stm32/stm32l4x1.go
src/device/stm32/stm32l4x3.go
src/device/stm32/stm32w108.go
src/device/stm32/stm32l4x2.go
src/device/stm32/stm32l4x5.go
$


サンプル実行

サンプルを実行してみます。

$ tinygo flash -target=arduino examples/blinky1


avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "/tmp/tinygo130840926/main.hex"
avrdude: input file /tmp/tinygo130840926/main.hex auto detected as Intel Hex
avrdude: writing flash (698 bytes):

Writing | ################################################## | 100% 0.12s

avrdude: 698 bytes of flash written
avrdude: verifying flash memory against /tmp/tinygo130840926/main.hex:
avrdude: load data flash data from input file /tmp/tinygo130840926/main.hex:
avrdude: input file /tmp/tinygo130840926/main.hex auto detected as Intel Hex
avrdude: input file /tmp/tinygo130840926/main.hex contains 698 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.10s

avrdude: verifying ...
avrdude: 698 bytes of flash verified

avrdude done. Thank you.

おおお!!

GoのコードがArduinoに書き込まれました!!!

秒数を変えると点滅の速度が変わりました。


blinky1.go

package main

// This is the most minimal blinky example and should run almost everywhere.

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 * 300)

led.High()
time.Sleep(time.Millisecond * 300)
}
}


image.png

Goでマイコンを動かすのは新鮮ですね :heart_eyes: