學 Go 玩創客,TinyGo 初體驗(2):以 Arduino Uno/Nano 控制腳位數位與類比輸出入

Photo by Ross Findon on Unsplash

Go 參考資料

由於 Go 仍然很新,所以台灣買不到書可參考。網路上有些關於 Go 語言的資訊,我個人參考的是下面這兩個:

  1. A Tour of Go(可線上當場執行範例)

材料準備

在看本篇之前,你會需要:

  1. 400 孔麵包板。
  2. 公公頭杜邦線若干,或者用其他杜邦線加 2.54mm 排針代替。
  3. 5mm 或類似大小的 LED 燈數個。
  4. 220 歐姆及 10 K 歐姆電阻數個。
  5. 按壓按鈕及光敏電阻。
Photo by Robin Glauser on Unsplash

回頭看 Blinky 範例

上一篇我們用範例程式令 Arduino Uno 內建的 LED 燈閃爍,這裡我們再來看一次程式:

package main

import (
"machine"
"time"
)

func main() {
led := machine.LED
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
for {
led.Low()
time.Sleep(time.Millisecond * 500)
led.High()
time.Sleep(time.Millisecond * 500)
}
}
led := machine.LED
var led machine.Pin = machine.LED
var led machine.Pin = machine.D13
Photo by Danielle MacInnes on Unsplash
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
type PinConfig struct {
Mode PinMode
}
type PinMode uint8

const (
PinInput PinMode = iota // 0
PinInputPullup // 1
PinOutput // 2
)
led.Configure(machine.PinConfig{2)
led.Set(true) // High
led.Set(false) // Low
const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)
time.Sleep(time.Millisecond * 500)
Photo by AbsolutVision on Unsplash
package mainimport (
"machine"
"time"
)
func main() {machine.Pin(13).Configure(machine.PinConfig{Mode: machine.PinOutput})for {
machine.D13.High()
time.Sleep(time.Millisecond * 500)
machine.D13.Low()
time.Sleep(time.Millisecond * 500)
}
}

數位輸出

接下來要開始接線了,這回我們改用 Uno/Nano 的 2 號腳位來控制一顆外接 LED 燈。同時,我們將嘗試用個不太一樣的程式版本來控制它。

package mainimport (
"machine"
"time"
)
func main() { led := machine.D2
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
for {
led.Set(!led.Get())
delay(500)
}
}
func delay(t uint32) {
time.Sleep(time.Duration(1000000 * t))
}
func delay(t uint16) {    time.Sleep(time.Duration(1000000 * uint32(t)))}

數位輸出 — — 陣列版

剛才只是 1 顆燈的範例,假如現在改成一排燈(腳位 2 至 8),我們希望它能來回閃動呢?這時我們可以使用陣列來處理之。

package mainimport (
"machine"
"time"
)
func main() { leds := []machine.Pin{
machine.D2,
machine.D3,
machine.D4,
machine.D5,
machine.D6,
machine.D7,
machine.D8,
}
for i := 0; i < len(leds); i++ {
leds[i].Configure(machine.PinConfig{Mode: machine.PinOutput}})
}
for { for i := 0; i < len(leds); i++ {
leds[i].High()
delay(75)
leds[i].Low()
}
for i := len(leds) - 1; i >= 0; i-- {
leds[i].High()
delay(75)
leds[i].Low()
}
}
}
func delay(t uint16) {
time.Sleep(time.Duration(1000000 * uint32(t)))
}
Photo by Lawrence Hookham on Unsplash
package mainimport (
"machine"
"time"
)
func main() { delay := func(t uint16) {
time.Sleep(time.Duration(1000000 * uint32(t)))
}
leds := []machine.Pin{
machine.D2,
machine.D3,
machine.D4,
machine.D5,
machine.D6,
machine.D7,
machine.D8,
}
for _, led := range leds {
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
}
index, delta := 0, 1 for { for i, led := range leds {
led.Set(i == index)
}
index += delta if index == 0 || index == len(leds)-1 {
delta *= -1
}
delay(75) }
}

數位輸入

看完數位輸出,接著看類比輸入。我們將偵測一個按鈕(腳位 2)提供的數位信號(高電位/低電位),並用這信號來控制 LED 燈(腳位 9)。

package mainimport (
"machine"
"time"
)
func main() { button := machine.D2
button.Configure(machine.PinConfig{Mode: machine.PinInput})
led := machine.D9
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
for {
led.Set(!button.Get())
time.Sleep(time.Millisecond * 100)
}
}

使用內部上拉電阻的數位輸入

以上接線還可以進一步簡化,改用板子本身的內建上拉電阻來接按鈕。(Uno 擁有介於 20K 至 50K 歐姆的內部上拉電阻:)

    button := machine.D2
button.Configure(machine.PinConfig{Mode: machine.PinInputPullup})

類比輸出

這裡我們直接沿用前一個範例的接線,但只用到 LED 燈。

package mainimport (
"machine"
"time"
)
func main() { machine.InitPWM()
led := machine.PWM{machine.D9}
led.Configure()
duty, delta := 0, 1024 for { led.Set(uint16(duty))
duty += delta
if duty < 0 || duty > 65535 {
delta *= -1
duty += delta
}
time.Sleep(time.Millisecond * 25)
}
}
Photo by Dil on Unsplash

類比輸入

最後來看類比輸入,也就是讀取類比信號或介於 0–5V 間的電壓值。

mackage mainimport (
"machine"
"time"
)
func main() {machine.InitADC()
ldr := machine.ADC{machine.ADC0}
ldr.Configure()
led := machine.Pin(machine.D9)
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
for {
print(ldr.Get())
if ldr.Get() > 40000 {
led.Set(true)
} else {
led.Set(false)
}

time.Sleep(time.Millisecond * 100)
}
}
led.Set(ldr.Get() > 40000)

尾聲

在本篇我們看了 Arduino Uno 基本的腳位輸出入功能,並藉此了解 Go 語言的一些特性。不過這還不是終點;在後續的篇幅中,筆者會帶大家看看 TinyGo 能做的更多事情,例如使用驅動程式來控制更多的外部模組,以及使用幾種其他不同的控制板。

Photo by Bethany Legg on Unsplash

Former translator, after-hours Maker, sunny-day analog film shooter. Currently a junior tech-book editor based in Taiwan. https://krantasblog.blogspot.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store