1.はじめに
今までAruduinoやルネサス系のマイコンを利用してC言語でプログラムを書くことが多かったのですが、最近の言語を学習したいと思い、Micropythonに取り組んでいました。MicroPythonは結構色々な人が取り組んでネット上での資料も多くあったので、私がやっていることが少しでも利用できる人がいたら良いと思い、またGo言語にも少し興味があったのでTinyGoに取り組んでみることにしました。
2. ハードウェアについて
今回はとりあえず手元にあった9軸センサモジュールのAE-BMX055とSeeed XIAOを使って製作しました。Seeed XIAOはTinyGoをサポートしているので開発しやすいと思います。
下の図は今回の製作した回路図です。
3.プログラムについて
AE-BMX055はI2Cを使用するので、TinyGo Driversをインストールして開発しました。
プログラムはTinyGo Driversを利用してI2Cで加速度、角速度、地磁気のデータを取得しています。
下のプログラムはAE-BMX055の制御関係のプログラムです。
package bmx055
import (
"time"
"tinygo.org/x/drivers"
)
type bmx055_data struct {
// Acc
XAcc float64
YAcc float64
ZAcc float64
// Gyaro
XGyro float64
YGyro float64
ZGyro float64
// Mag
XMag int32
YMag int32
ZMag int32
}
type Device struct {
bus drivers.I2C
AccAddress uint8
GyroAddress uint8
MagAddress uint8
Dat bmx055_data
}
func New(bus drivers.I2C) Device {
return Device{
bus: bus,
AccAddress: ACCAddress,
GyroAddress: GyroAddress,
MagAddress: MagAddress,
}
}
/* Init*/
func (d *Device) Configture() {
/* Acc*/
_ = d.bus.WriteRegister(d.AccAddress, AccPmuRangeReg, []byte{0x03})
_ = d.bus.WriteRegister(d.AccAddress, AccPmuBwReg, []byte{0x08})
_ = d.bus.WriteRegister(d.AccAddress, AccPmuLpwReg, []byte{0x00})
time.Sleep(100 * time.Millisecond)
/* Gyro*/
_ = d.bus.WriteRegister(d.GyroAddress, GyroRangeReg, []byte{0x04})
_ = d.bus.WriteRegister(d.GyroAddress, GyroBwReg, []byte{0x07})
_ = d.bus.WriteRegister(d.GyroAddress, GyroLpm1Reg, []byte{0x00})
time.Sleep(100 * time.Millisecond)
/* Mag */
_ = d.bus.WriteRegister(d.MagAddress, MagPowCtlReg, []byte{0x83})
time.Sleep(100 * time.Millisecond)
_ = d.bus.WriteRegister(d.MagAddress, MagPowCtlReg, []byte{0x01})
time.Sleep(100 * time.Millisecond)
_ = d.bus.WriteRegister(d.MagAddress, MagAdvOpOutputReg, []byte{0x00})
_ = d.bus.WriteRegister(d.MagAddress, MagAxesReg, []byte{0x84})
_ = d.bus.WriteRegister(d.MagAddress, MagRepXyReg, []byte{0x04})
_ = d.bus.WriteRegister(d.MagAddress, MagRepZReg, []byte{0x16})
}
//isConnected
func (d *Device) IsConnected() bool {
data := make([]byte, 1)
_ = d.bus.ReadRegister(d.AccAddress, BGW_CHIPID, data)
return data[0] == 0xfa
}
/* Get Acceralater Data Function */
func (d *Device) GetAcc() error {
data := make([]byte, 6)
err := d.bus.ReadRegister(d.AccAddress, AccDataStartReg, data)
if err != nil {
println(err)
return err
}
// Get ACC Data
x := int32(uint16(data[1])*256|uint16(data[0]&0xf0)) >> 4
if x > 2047 {
x -= 4096
}
y := int32(uint16(data[3])*256|uint16(data[2]&0xf0)) >> 4
if y > 2047 {
y -= 4096
}
z := int32(uint16(data[5])*256|uint16(data[4]&0xf0)) >> 4
if z > 2047 {
z -= 4096
}
d.Dat.XAcc = float64(x) * 0.0196
d.Dat.YAcc = float64(y) * 0.0196
d.Dat.ZAcc = float64(z) * 0.0196
return nil
}
/* Get Gyro Data Function */
func (d *Device) GetGyro() error {
data := make([]byte, 6)
err := d.bus.ReadRegister(d.GyroAddress, GyroDataStartReg, data)
if err != nil {
println(err)
return err
}
// Get Gyro Data
x := int32(uint16(data[1])<<8 | uint16(data[0]))
if x > 32767 {
x -= 65536
}
y := int32(uint16(data[3])<<8 | uint16(data[2]))
if y > 32767 {
y -= 65536
}
z := int32(uint16(data[5])<<8 | uint16(data[4]))
if z > 32767 {
z -= 65536
}
//
d.Dat.XGyro = float64(x) * 0.0038
d.Dat.YGyro = float64(y) * 0.0038
d.Dat.ZGyro = float64(z) * 0.0038
return nil
}
/* Get Magnetic Filed Data Function */
func (d *Device) GetMag() error {
data := make([]byte, 6)
err := d.bus.ReadRegister(d.MagAddress, MagDataStartReg, data)
if err != nil {
println(err)
return err
}
// Get ACC Data
d.Dat.XMag = int32(uint16(data[1])<<8|uint16(data[0]&0xf8)) / 8
if d.Dat.XMag > 4095 {
d.Dat.XMag -= 8192
}
d.Dat.YMag = int32(uint16(data[3])<<8|uint16(data[2]&0xf8)) / 8
if d.Dat.YMag > 4095 {
d.Dat.YMag -= 8192
}
d.Dat.ZMag = int32(uint16(data[5])<<8|uint16(data[4]&0xfe)) / 2
if d.Dat.ZMag > 16383 {
d.Dat.ZMag -= 32768
}
return nil
}
下のプログラムは動作確認用のプログラムです。
package bmx055
import (
"fmt"
"machine"
"time"
)
func main() {
var err error
machine.I2C0.Configure(machine.I2CConfig{})
d := New(machine.I2C0)
conected := d.IsConnected()
// BMX055 is Conenect ?
if !conected {
// Not Connected
println("Not Connected!")
for {
}
}
// Initilaize For BMX055
d.Configture()
for {
/* Get Accelerometer Data */
err = d.GetGyro()
if err == nil {
fmt.Printf("Gyro : x=%5.2f y=%5.2f z=%5.2f\n", d.Dat.XGyro, d.Dat.YGyro, d.Dat.ZGyro)
}
/* Get Gyro Data */
err = d.GetAcc()
if err == nil {
fmt.Printf("Acc : x=%5.2f y=%5.2f z=%5.2f\n", d.Dat.XAcc, d.Dat.YAcc, d.Dat.ZAcc)
}
/* Get Geomagnetic sensor Data*/
err = d.GetMag()
if err == nil {
fmt.Printf("Mag : x=%4d y=%4d z=%4d\n", d.Dat.XMag, d.Dat.YMag, d.Dat.ZMag)
}
fmt.Println()
time.Sleep(100 * time.Millisecond)
}
}
4. 動作の様子
下の図のようにシリアルポート経由で角速度、加速度、地磁気のデータが出力されます。
5. 最後に
今回のTinyGoのプログラムを作ってみて、Go言語の楽しさがわかってきました。Go言語をやり始めて3週間ぐらいですが、何とか本などを見ながら、サンプルプログラムを作ることができました。まだまだ、未完成ですがとりあえずはデータを取得できるので何かに活用できると思います。
もし、良かったらここに公開していますので、自由に使ってください。
次は色々なセンサを組み合わせて実際に役立つものをに取り組みたいと思います。