1
0
mirror of https://github.com/hybridgroup/gobot.git synced 2025-05-11 19:29:20 +08:00
hybridgroup.gobot/platforms/firmata/firmata_adaptor.go

172 lines
4.1 KiB
Go
Raw Normal View History

2014-04-27 19:56:18 -07:00
package firmata
import (
"fmt"
"strconv"
2014-07-14 13:34:46 -07:00
"time"
"github.com/hybridgroup/gobot"
"github.com/tarm/goserial"
)
type FirmataAdaptor struct {
gobot.Adaptor
2014-07-13 13:54:41 -07:00
board *board
i2cAddress byte
2014-04-27 19:56:18 -07:00
connect func(*FirmataAdaptor)
}
2014-10-17 12:42:07 -05:00
// NewFirmataAdaptor returns a new firmata adaptor with specified name
// Generates a connect function that opens serial communication in specified port
2014-04-30 08:10:44 -07:00
func NewFirmataAdaptor(name, port string) *FirmataAdaptor {
2014-04-27 19:56:18 -07:00
return &FirmataAdaptor{
2014-06-23 20:33:59 -07:00
Adaptor: *gobot.NewAdaptor(
name,
"FirmataAdaptor",
port,
2014-06-23 20:33:59 -07:00
),
2014-04-27 19:56:18 -07:00
connect: func(f *FirmataAdaptor) {
sp, err := serial.OpenPort(&serial.Config{Name: f.Port(), Baud: 57600})
2014-04-27 19:56:18 -07:00
if err != nil {
panic(err)
}
2014-07-13 13:54:41 -07:00
f.board = newBoard(sp)
2014-04-27 19:56:18 -07:00
},
}
}
2014-10-17 12:42:07 -05:00
// Connect returns true if connection to board is succesfull
2014-04-27 19:56:18 -07:00
func (f *FirmataAdaptor) Connect() bool {
f.connect(f)
2014-07-13 13:54:41 -07:00
f.board.connect()
f.SetConnected(true)
return true
}
2014-10-17 12:42:07 -05:00
// close finishes connection to serial port
// Prints error message on error
2014-04-27 19:56:18 -07:00
func (f *FirmataAdaptor) Disconnect() bool {
2014-07-13 13:54:41 -07:00
err := f.board.serial.Close()
if err != nil {
fmt.Println(err)
}
return true
}
2014-10-17 12:42:07 -05:00
// Finalize disconnects firmata adaptor
2014-04-27 19:56:18 -07:00
func (f *FirmataAdaptor) Finalize() bool { return f.Disconnect() }
2014-10-17 12:42:07 -05:00
// InitServo (not yet implemented)
2014-04-27 19:56:18 -07:00
func (f *FirmataAdaptor) InitServo() {}
2014-10-17 12:42:07 -05:00
// ServoWrite sets angle form 0 to 360 to specified servo pin
2014-04-27 19:56:18 -07:00
func (f *FirmataAdaptor) ServoWrite(pin string, angle byte) {
p, _ := strconv.Atoi(pin)
2014-07-13 13:54:41 -07:00
f.board.setPinMode(byte(p), servo)
f.board.analogWrite(byte(p), angle)
}
2014-10-17 12:42:07 -05:00
// PwmWrite writes analog value to specified pin
2014-04-27 19:56:18 -07:00
func (f *FirmataAdaptor) PwmWrite(pin string, level byte) {
p, _ := strconv.Atoi(pin)
2014-07-13 13:54:41 -07:00
f.board.setPinMode(byte(p), pwm)
f.board.analogWrite(byte(p), level)
}
2014-10-17 12:42:07 -05:00
// DigitalWrite writes digital values to specified pin
2014-04-27 19:56:18 -07:00
func (f *FirmataAdaptor) DigitalWrite(pin string, level byte) {
p, _ := strconv.Atoi(pin)
2014-07-13 13:54:41 -07:00
f.board.setPinMode(byte(p), output)
f.board.digitalWrite(byte(p), level)
}
2014-10-17 12:42:07 -05:00
// DigitalRead retrieves digital value from specified pin
// Returns -1 if response from board is timed out
2014-04-27 19:56:18 -07:00
func (f *FirmataAdaptor) DigitalRead(pin string) int {
2014-07-13 13:54:41 -07:00
ret := make(chan int)
2014-07-14 13:34:46 -07:00
p, _ := strconv.Atoi(pin)
2014-07-13 13:54:41 -07:00
f.board.setPinMode(byte(p), input)
f.board.togglePinReporting(byte(p), high, reportDigital)
f.board.readAndProcess()
2014-07-13 20:27:38 -07:00
gobot.Once(f.board.events[fmt.Sprintf("digital_read_%v", pin)], func(data interface{}) {
2014-07-13 13:54:41 -07:00
ret <- int(data.([]byte)[0])
})
2014-07-14 13:34:46 -07:00
select {
case data := <-ret:
return data
case <-time.After(10 * time.Millisecond):
}
return -1
}
2014-10-17 12:42:07 -05:00
// AnalogRead retrieves value from analog pin.
// NOTE pins are numbered A0-A5, which translate to digital pins 14-19
2014-04-27 19:56:18 -07:00
func (f *FirmataAdaptor) AnalogRead(pin string) int {
2014-07-13 13:54:41 -07:00
ret := make(chan int)
p, _ := strconv.Atoi(pin)
2014-04-27 19:56:18 -07:00
p = f.digitalPin(p)
2014-07-13 13:54:41 -07:00
f.board.setPinMode(byte(p), analog)
f.board.togglePinReporting(byte(p), high, reportAnalog)
f.board.readAndProcess()
2014-07-13 20:27:38 -07:00
gobot.Once(f.board.events[fmt.Sprintf("analog_read_%v", pin)], func(data interface{}) {
2014-07-13 13:54:41 -07:00
b := data.([]byte)
ret <- int(uint(b[0])<<24 | uint(b[1])<<16 | uint(b[2])<<8 | uint(b[3]))
})
2014-07-14 13:34:46 -07:00
select {
case data := <-ret:
return data
case <-time.After(10 * time.Millisecond):
}
return -1
}
2014-10-17 12:42:07 -05:00
// AnalogWrite writes value to ananlog pin
2014-06-09 14:28:48 -07:00
func (f *FirmataAdaptor) AnalogWrite(pin string, level byte) {
f.PwmWrite(pin, level)
}
2014-10-17 12:42:07 -05:00
// digitalPin converts pin number to digital mapping
2014-04-27 19:56:18 -07:00
func (f *FirmataAdaptor) digitalPin(pin int) int {
return pin + 14
}
2014-10-17 12:42:07 -05:00
// I2cStart initializes board with i2c configuration
2014-04-27 19:56:18 -07:00
func (f *FirmataAdaptor) I2cStart(address byte) {
f.i2cAddress = address
2014-07-13 13:54:41 -07:00
f.board.i2cConfig([]byte{0})
}
2014-10-17 12:42:07 -05:00
// I2cRead reads from I2c specified size
// Returns empty byte array if response is timed out
2014-06-06 18:58:04 -07:00
func (f *FirmataAdaptor) I2cRead(size uint) []byte {
2014-07-13 13:54:41 -07:00
ret := make(chan []byte)
f.board.i2cReadRequest(f.i2cAddress, size)
2014-07-13 13:54:41 -07:00
f.board.readAndProcess()
2014-07-13 20:27:38 -07:00
gobot.Once(f.board.events["i2c_reply"], func(data interface{}) {
ret <- data.(map[string][]byte)["data"]
2014-07-13 13:54:41 -07:00
})
2014-07-14 13:34:46 -07:00
select {
case data := <-ret:
return data
case <-time.After(10 * time.Millisecond):
}
return []byte{}
}
2014-10-17 12:42:07 -05:00
// I2cWrite retrieves i2c data
2014-06-06 18:58:04 -07:00
func (f *FirmataAdaptor) I2cWrite(data []byte) {
2014-07-13 13:54:41 -07:00
f.board.i2cWriteRequest(f.i2cAddress, data)
}