diff --git a/Makefile b/Makefile index aeb59b6af..bb9c1a192 100644 --- a/Makefile +++ b/Makefile @@ -241,6 +241,9 @@ endif @md5sum ./build/test.uf2 tinygo build -size short -o ./build/test.uf2 -target=circuitplay-express ./examples/makeybutton/main.go @md5sum ./build/test.uf2 + tinygo build -size short -o ./build/test.hex -target=arduino ./examples/bts7960/main.go + @md5sum ./build/test.hex + # rwildcard is a recursive version of $(wildcard) # https://blog.jgc.org/2011/07/gnu-make-recursive-wildcard-function.html diff --git a/README.md b/README.md index 45a01501d..3758479df 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ The following 81 devices are supported. | [4x4 Membrane Keypad](https://cdn.sparkfun.com/assets/f/f/a/5/0/DS-16038.pdf) | GPIO | | [L293x motor driver](https://www.ti.com/lit/ds/symlink/l293d.pdf) | GPIO/PWM | | [L9110x motor driver](https://www.elecrow.com/download/datasheet-l9110.pdf) | GPIO/PWM | +| [BTS7960 motor driver](https://www.handsontec.com/dataspecs/module/BTS7960%20Motor%20Driver.pdf) | GPIO/PWM | | [LIS2MDL magnetometer](https://www.st.com/resource/en/datasheet/lis2mdl.pdf) | I2C | | [LIS3DH accelerometer](https://www.st.com/resource/en/datasheet/lis3dh.pdf) | I2C | | [LPS22HB MEMS nano pressure sensor](https://www.st.com/resource/en/datasheet/dm00140895.pdf) | I2C | diff --git a/bts7960/bts7960.go b/bts7960/bts7960.go new file mode 100644 index 000000000..db9264612 --- /dev/null +++ b/bts7960/bts7960.go @@ -0,0 +1,86 @@ +package bts7960 + +import ( + "time" + + "machine" +) + +// PWM is the interface necessary for controlling the bts 7960 motor. +type PWM interface { + Channel(pin machine.Pin) (channel uint8, err error) + Top() uint32 + Set(channel uint8, value uint32) +} + +// Device is the bts7960 device +type Device struct { + lEn machine.Pin + rEn machine.Pin + lPwm machine.Pin + rPwm machine.Pin + rPwmCh, lPwmCh uint8 + pwm PWM +} + +// New returns a new motor driver. +func New(lEn, rEn, lPwm, rPwm machine.Pin, pwm PWM) *Device { + return &Device{lEn: lEn, rEn: rEn, lPwm: lPwm, rPwm: rPwm, pwm: pwm} +} + +// Configure configures the Device. +func (d *Device) Configure() error { + d.rPwm.Configure(machine.PinConfig{Mode: machine.PinOutput}) + d.lPwm.Configure(machine.PinConfig{Mode: machine.PinOutput}) + d.lEn.Configure(machine.PinConfig{Mode: machine.PinOutput}) + d.rEn.Configure(machine.PinConfig{Mode: machine.PinOutput}) + + var err error + d.lPwmCh, err = d.pwm.Channel(d.lPwm) + if err != nil { + println("failed to configure lpwn: " + err.Error()) + return err + } + + d.rPwmCh, err = d.pwm.Channel(d.rPwm) + if err != nil { + println("failed to configure rpwn: " + err.Error()) + return err + } + + d.Stop() + + return nil +} + +// Enable enables the motor driver +func (d *Device) Enable() { + d.lEn.High() + d.rEn.High() +} + +// Disable disabled the motor driver +func (d *Device) Disable() { + d.lEn.Low() + d.rEn.Low() +} + +// Stop stops the motor +func (d *Device) Stop() { + d.pwm.Set(d.lPwmCh, 0) + d.pwm.Set(d.rPwmCh, 0) +} + +// Left turns motor left. +func (d *Device) Left(speed uint32) { + d.pwm.Set(d.rPwmCh, 0) + time.Sleep(time.Microsecond * 100) + d.pwm.Set(d.lPwmCh, d.pwm.Top()*speed/100) +} + +// Right turns motor right. +func (d *Device) Right(speed uint32) { + d.pwm.Set(d.lPwmCh, 0) + time.Sleep(time.Microsecond * 100) + d.pwm.Set(d.rPwmCh, d.pwm.Top()*speed/100) +} diff --git a/examples/bts7960/main.go b/examples/bts7960/main.go new file mode 100644 index 000000000..d71d27145 --- /dev/null +++ b/examples/bts7960/main.go @@ -0,0 +1,45 @@ +package main + +import ( + "machine" + "time" + + "tinygo.org/x/drivers/bts7960" +) + +// Configuration for the Arduino Uno. +// Please change the PWM and pin if you want to try this example on a different +// board. +var ( + pwm = machine.Timer0 + + rEn = machine.D2 + lEn = machine.D3 + + rPwm = machine.PD5 + lPwm = machine.PD6 +) + +func main() { + if err := pwm.Configure(machine.PWMConfig{}); err != nil { + println(err.Error()) + return + } + + bts := bts7960.New(lEn, rEn, lPwm, rPwm, pwm) + err := bts.Configure() + if err != nil { + println("cannot configure bts: " + err.Error()) + return + } + + println("rotating left") + bts.Left(50) + + println("rotating left") + bts.Right(50) + + for { + time.Sleep(time.Second) + } +}