Skip to content

Commit cb1f952

Browse files
authored
megapi: use serialport adaptor and move driver to drivers/serial (hybridgroup#1062)
1 parent e2b710b commit cb1f952

File tree

10 files changed

+190
-210
lines changed

10 files changed

+190
-210
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ the `gobot/drivers/serial` package:
391391
- [UART](https://en.wikipedia.org/wiki/Serial_port) <=> [Drivers](https://github.com/hybridgroup/gobot/tree/master/drivers/serial)
392392
- Sphero: Sphero
393393
- Neurosky: MindWave
394+
- MegaPi: MotorDriver
394395

395396
Support for devices that use Serial Peripheral Interface (SPI) have
396397
a shared set of drivers provided using the `gobot/drivers/spi` package:

drivers/MIGRATION.md

+32-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ import(
115115
116116
### Neurosky adaptor split off
117117
118-
The Neurosky adaptor now us the generic serial adaptor. The driver part was moved. With this, the imports needs to be
118+
The Neurosky adaptor now use the generic serial adaptor. The driver part was moved. With this, the imports needs to be
119119
adjusted. In addition all events now have a suffix "Event", see below.
120120
121121
```go
@@ -148,6 +148,37 @@ import(
148148
...
149149
```
150150
151+
### MegaPi adaptor split off
152+
153+
The MegaPi adaptor now use the generic serial adaptor. The driver part was moved. With this, the imports needs to be
154+
adjusted.
155+
156+
```go
157+
// old
158+
import(
159+
...
160+
"gobot.io/x/gobot/v2/platforms/megapi"
161+
...
162+
)
163+
164+
...
165+
megaPiAdaptor := megapi.NewAdaptor("/dev/ttyS0")
166+
motor := megapi.NewMotorDriver(megaPiAdaptor, 1)
167+
...
168+
169+
// new
170+
import(
171+
...
172+
"gobot.io/x/gobot/v2/drivers/serial/megapi"
173+
"gobot.io/x/gobot/v2/platforms/serialport"
174+
...
175+
)
176+
...
177+
adaptor := serialport.NewAdaptor("/dev/ttyS0", serialport.WithName("MegaPi"))
178+
motor := megapi.NewMotorDriver(adaptor, 1)
179+
...
180+
```
181+
151182
## Switch from version 2.2.0 (gpio drivers affected)
152183
153184
### gpio.ButtonDriver, gpio.PIRMotionDriver: substitute parameter "v time.duration"

drivers/serial/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ Gobot has a extensible system for connecting to hardware devices. The following
1414

1515
- Sphero: Sphero
1616
- Neurosky: MindWave
17+
- MegaPi: MotorDriver

drivers/serial/megapi/motor_driver.go

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package megapi
2+
3+
import (
4+
"bytes"
5+
"encoding/binary"
6+
"log"
7+
"sync"
8+
"time"
9+
10+
"gobot.io/x/gobot/v2"
11+
"gobot.io/x/gobot/v2/drivers/serial"
12+
)
13+
14+
var _ gobot.Driver = (*MotorDriver)(nil)
15+
16+
type megapiMotorSerialAdaptor interface {
17+
gobot.Adaptor
18+
serial.SerialWriter
19+
}
20+
21+
// MotorDriver represents a motor
22+
type MotorDriver struct {
23+
*serial.Driver
24+
port byte
25+
halted bool
26+
writeBytesChannel chan []byte
27+
finalizeChannel chan struct{}
28+
syncRoot *sync.Mutex
29+
}
30+
31+
// NewMotorDriver creates a new MotorDriver at the given port
32+
func NewMotorDriver(a megapiMotorSerialAdaptor, port byte, opts ...serial.OptionApplier) *MotorDriver {
33+
d := &MotorDriver{
34+
port: port,
35+
halted: true,
36+
syncRoot: &sync.Mutex{},
37+
writeBytesChannel: make(chan []byte),
38+
finalizeChannel: make(chan struct{}),
39+
}
40+
d.Driver = serial.NewDriver(a, "MegaPiMotor", d.initialize, d.shutdown, opts...)
41+
42+
return d
43+
}
44+
45+
// Speed sets the motors speed to the specified value
46+
func (d *MotorDriver) Speed(speed int16) error {
47+
d.syncRoot.Lock()
48+
defer d.syncRoot.Unlock()
49+
50+
if d.halted {
51+
return nil
52+
}
53+
return d.speedHelper(speed)
54+
}
55+
56+
// initialize implements the Driver interface
57+
func (d *MotorDriver) initialize() error {
58+
d.syncRoot.Lock()
59+
defer d.syncRoot.Unlock()
60+
61+
// sleeping is required to give the board a chance to reset after connection is done
62+
time.Sleep(2 * time.Second)
63+
64+
// kick off thread to send bytes to the board
65+
go func() {
66+
for {
67+
select {
68+
case bytes := <-d.writeBytesChannel:
69+
if _, err := d.adaptor().SerialWrite(bytes); err != nil {
70+
panic(err)
71+
}
72+
time.Sleep(10 * time.Millisecond)
73+
case <-d.finalizeChannel:
74+
d.finalizeChannel <- struct{}{}
75+
return
76+
default:
77+
time.Sleep(10 * time.Millisecond)
78+
}
79+
}
80+
}()
81+
82+
d.halted = false
83+
return d.speedHelper(0)
84+
}
85+
86+
// Halt terminates the Driver interface
87+
func (d *MotorDriver) shutdown() error {
88+
d.syncRoot.Lock()
89+
defer d.syncRoot.Unlock()
90+
91+
d.finalizeChannel <- struct{}{}
92+
<-d.finalizeChannel
93+
94+
d.halted = true
95+
return d.speedHelper(0)
96+
}
97+
98+
// there is some sort of bug on the hardware such that you cannot
99+
// send the exact same speed to 2 different motors consecutively
100+
// hence we ensure we always alternate speeds
101+
func (d *MotorDriver) speedHelper(speed int16) error {
102+
if err := d.sendSpeed(speed - 1); err != nil {
103+
return err
104+
}
105+
return d.sendSpeed(speed)
106+
}
107+
108+
// sendSpeed sets the motors speed to the specified value
109+
func (d *MotorDriver) sendSpeed(speed int16) error {
110+
bufOut := new(bytes.Buffer)
111+
112+
// byte sequence: 0xff, 0x55, id, action, device, port
113+
bufOut.Write([]byte{0xff, 0x55, 0x6, 0x0, 0x2, 0xa, d.port})
114+
if err := binary.Write(bufOut, binary.LittleEndian, speed); err != nil {
115+
return err
116+
}
117+
bufOut.Write([]byte{0xa})
118+
d.writeBytesChannel <- bufOut.Bytes()
119+
120+
return nil
121+
}
122+
123+
func (d *MotorDriver) adaptor() megapiMotorSerialAdaptor {
124+
if a, ok := d.Connection().(megapiMotorSerialAdaptor); ok {
125+
return a
126+
}
127+
128+
log.Printf("%s has no MegaPi serial connector\n", d.Name())
129+
return nil
130+
}

examples/megapi_motor.go examples/serialport_megapi_motor.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ import (
1111
"time"
1212

1313
"gobot.io/x/gobot/v2"
14-
"gobot.io/x/gobot/v2/platforms/megapi"
14+
"gobot.io/x/gobot/v2/drivers/serial/megapi"
15+
"gobot.io/x/gobot/v2/platforms/serialport"
1516
)
1617

1718
func main() {
1819
// use "/dev/ttyUSB0" if connecting with USB cable
1920
// use "/dev/ttyAMA0" on devices older than Raspberry Pi 3 Model B
20-
megaPiAdaptor := megapi.NewAdaptor("/dev/ttyS0")
21-
motor := megapi.NewMotorDriver(megaPiAdaptor, 1)
21+
adaptor := serialport.NewAdaptor("/dev/ttyS0", serialport.WithName("MegaPi"))
22+
motor := megapi.NewMotorDriver(adaptor, 1)
2223

2324
work := func() {
2425
speed := int16(0)
@@ -36,7 +37,7 @@ func main() {
3637
}
3738

3839
robot := gobot.NewRobot("megaPiBot",
39-
[]gobot.Connection{megaPiAdaptor},
40+
[]gobot.Connection{adaptor},
4041
[]gobot.Device{motor},
4142
work,
4243
)

platforms/megapi/README.md

+10-7
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,19 @@ Please refer to the main [README.md](https://github.com/hybridgroup/gobot/blob/r
1515
package main
1616

1717
import (
18-
"gobot.io/x/gobot/v2"
19-
"gobot.io/x/gobot/v2/platforms/megapi"
18+
"fmt"
2019
"time"
20+
21+
"gobot.io/x/gobot/v2"
22+
"gobot.io/x/gobot/v2/drivers/serial/megapi"
23+
"gobot.io/x/gobot/v2/platforms/serialport"
2124
)
2225

2326
func main() {
2427
// use "/dev/ttyUSB0" if connecting with USB cable
2528
// use "/dev/ttyAMA0" on devices older than Raspberry Pi 3 Model B
26-
megaPiAdaptor := megapi.NewAdaptor("/dev/ttyS0")
27-
motor := megapi.NewMotorDriver(megaPiAdaptor, 1)
29+
adaptor := serialport.NewAdaptor("/dev/ttyS0", serialport.WithName("MegaPi"))
30+
motor := megapi.NewMotorDriver(adaptor, 1)
2831

2932
work := func() {
3033
speed := int16(0)
@@ -40,13 +43,13 @@ func main() {
4043
}
4144

4245
robot := gobot.NewRobot("megaPiBot",
43-
[]gobot.Connection{megaPiAdaptor},
46+
[]gobot.Connection{adaptor},
4447
[]gobot.Device{motor},
4548
work,
4649
)
4750

4851
if err := robot.Start(); err != nil {
49-
panic(err)
50-
}
52+
panic(err)
53+
}
5154
}
5255
```

platforms/megapi/megapi_adaptor.go

-88
This file was deleted.

0 commit comments

Comments
 (0)