Adding godocs to firmata package
This commit is contained in:
parent
bf7bc97c3a
commit
58c15eb116
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
|
||||
This package provides the adaptor for microcontrollers such as Arduino that support the [Firmata](http://firmata.org/wiki/Main_Page) protocol
|
||||
|
||||
Installing:
|
||||
|
||||
go get github.com/hybridgroup/gobot && go install github.com/hybridgroup/gobot/platforms/firmata
|
||||
|
||||
## Example
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/hybridgroup/gobot"
|
||||
"github.com/hybridgroup/gobot/platforms/firmata"
|
||||
"github.com/hybridgroup/gobot/platforms/gpio"
|
||||
)
|
||||
|
||||
func main() {
|
||||
gbot := gobot.NewGobot()
|
||||
|
||||
firmataAdaptor := firmata.NewFirmataAdaptor("arduino", "/dev/ttyACM0")
|
||||
led := gpio.NewLedDriver(firmataAdaptor, "led", "13")
|
||||
|
||||
work := func() {
|
||||
gobot.Every(1*time.Second, func() {
|
||||
led.Toggle()
|
||||
})
|
||||
}
|
||||
|
||||
robot := gobot.NewRobot("bot",
|
||||
[]gobot.Connection{firmataAdaptor},
|
||||
[]gobot.Device{led},
|
||||
work,
|
||||
)
|
||||
|
||||
gbot.AddRobot(robot)
|
||||
|
||||
gbot.Start()
|
||||
}
|
||||
|
||||
For further information refer to firmata readme:
|
||||
https://github.com/hybridgroup/gobot/blob/master/platforms/firmata/README.md
|
||||
*/
|
||||
package firmata
|
|
@ -69,6 +69,10 @@ type pin struct {
|
|||
analogChannel byte
|
||||
}
|
||||
|
||||
// newBoard creates a new board connected in specified serial port.
|
||||
// Adds following events: "firmware_query", "capability_query",
|
||||
// "analog_mapping_query", "report_version", "i2c_reply",
|
||||
// "string_data", "firmware_query"
|
||||
func newBoard(sp io.ReadWriteCloser) *board {
|
||||
board := &board{
|
||||
majorVersion: 0,
|
||||
|
@ -88,7 +92,6 @@ func newBoard(sp io.ReadWriteCloser) *board {
|
|||
"analog_mapping_query",
|
||||
"report_version",
|
||||
"i2c_reply",
|
||||
"analog_mapping_query",
|
||||
"string_data",
|
||||
"firmware_query",
|
||||
} {
|
||||
|
@ -98,6 +101,8 @@ func newBoard(sp io.ReadWriteCloser) *board {
|
|||
return board
|
||||
}
|
||||
|
||||
// connect starts connection to board.
|
||||
// Queries report version until connected
|
||||
func (b *board) connect() {
|
||||
if b.connected == false {
|
||||
b.reset()
|
||||
|
@ -114,6 +119,8 @@ func (b *board) connect() {
|
|||
}
|
||||
}
|
||||
|
||||
// initBoard initializes board by listening for "firware_query", "capability_query"
|
||||
// and "analog_mapping_query" events
|
||||
func (b *board) initBoard() {
|
||||
gobot.Once(b.events["firmware_query"], func(data interface{}) {
|
||||
b.queryCapabilities()
|
||||
|
@ -130,19 +137,23 @@ func (b *board) initBoard() {
|
|||
})
|
||||
}
|
||||
|
||||
// readAndProcess reads from serial port and parses data.
|
||||
func (b *board) readAndProcess() {
|
||||
b.process(b.read())
|
||||
}
|
||||
|
||||
// reset writes system reset bytes.
|
||||
func (b *board) reset() {
|
||||
b.write([]byte{systemReset})
|
||||
}
|
||||
|
||||
// setPinMode writes pin mode bytes for specified pin.
|
||||
func (b *board) setPinMode(pin byte, mode byte) {
|
||||
b.pins[pin].mode = mode
|
||||
b.write([]byte{pinMode, pin, mode})
|
||||
}
|
||||
|
||||
// digitalWrite is used to send a digital value to a specified pin.
|
||||
func (b *board) digitalWrite(pin byte, value byte) {
|
||||
port := byte(math.Floor(float64(pin) / 8))
|
||||
portValue := byte(0)
|
||||
|
@ -157,48 +168,54 @@ func (b *board) digitalWrite(pin byte, value byte) {
|
|||
b.write([]byte{digitalMessage | port, portValue & 0x7F, (portValue >> 7) & 0x7F})
|
||||
}
|
||||
|
||||
// analogWrite writes value to specified pin
|
||||
func (b *board) analogWrite(pin byte, value byte) {
|
||||
b.pins[pin].value = int(value)
|
||||
b.write([]byte{analogMessage | pin, value & 0x7F, (value >> 7) & 0x7F})
|
||||
}
|
||||
|
||||
// version returns board version following MAYOR.minor convention.
|
||||
func (b *board) version() string {
|
||||
return fmt.Sprintf("%v.%v", b.majorVersion, b.minorVersion)
|
||||
}
|
||||
|
||||
func (b *board) reportVersion() {
|
||||
b.write([]byte{reportVersion})
|
||||
}
|
||||
|
||||
// queryFirmware writes bytes to query firmware from board.
|
||||
func (b *board) queryFirmware() {
|
||||
b.write([]byte{startSysex, firmwareQuery, endSysex})
|
||||
}
|
||||
|
||||
// queryPinState writes bytes to retrieve pin state
|
||||
func (b *board) queryPinState(pin byte) {
|
||||
b.write([]byte{startSysex, pinStateQuery, pin, endSysex})
|
||||
}
|
||||
|
||||
// queryReportVersion sends query for report version
|
||||
func (b *board) queryReportVersion() {
|
||||
b.write([]byte{reportVersion})
|
||||
}
|
||||
|
||||
// queryCapabilities is used to retrieve board capabilities.
|
||||
func (b *board) queryCapabilities() {
|
||||
b.write([]byte{startSysex, capabilityQuery, endSysex})
|
||||
}
|
||||
|
||||
// queryAnalogMapping returns analog mapping for board.
|
||||
func (b *board) queryAnalogMapping() {
|
||||
b.write([]byte{startSysex, analogMappingQuery, endSysex})
|
||||
}
|
||||
|
||||
// togglePinReporting is used to change pin reporting mode.
|
||||
func (b *board) togglePinReporting(pin byte, state byte, mode byte) {
|
||||
b.write([]byte{mode | pin, state})
|
||||
}
|
||||
|
||||
// i2cReadRequest reads from slaveAddress.
|
||||
func (b *board) i2cReadRequest(slaveAddress byte, numBytes uint) {
|
||||
b.write([]byte{startSysex, i2CRequest, slaveAddress, (i2CModeRead << 3),
|
||||
byte(numBytes & 0x7F), byte(((numBytes >> 7) & 0x7F)), endSysex})
|
||||
}
|
||||
|
||||
// i2cWriteRequest writes to slaveAddress.
|
||||
func (b *board) i2cWriteRequest(slaveAddress byte, data []byte) {
|
||||
ret := []byte{startSysex, i2CRequest, slaveAddress, (i2CModeWrite << 3)}
|
||||
for _, val := range data {
|
||||
|
@ -209,6 +226,7 @@ func (b *board) i2cWriteRequest(slaveAddress byte, data []byte) {
|
|||
b.write(ret)
|
||||
}
|
||||
|
||||
// i2xConfig returns i2c configuration.
|
||||
func (b *board) i2cConfig(data []byte) {
|
||||
ret := []byte{startSysex, i2CConfig}
|
||||
for _, val := range data {
|
||||
|
@ -219,16 +237,24 @@ func (b *board) i2cConfig(data []byte) {
|
|||
b.write(ret)
|
||||
}
|
||||
|
||||
// write is used to send commands to serial port
|
||||
func (b *board) write(commands []byte) {
|
||||
b.serial.Write(commands[:])
|
||||
}
|
||||
|
||||
// read returns buffer reading from serial port (1024 bytes)
|
||||
func (b *board) read() []byte {
|
||||
buf := make([]byte, 1024)
|
||||
b.serial.Read(buf)
|
||||
return buf
|
||||
}
|
||||
|
||||
// process uses incoming data and executes actions depending on what is received.
|
||||
// The following messages are processed: reportVersion, AnalogMessageRangeStart,
|
||||
// digitalMessageRangeStart.
|
||||
// And the following responses: capability, analog mapping, pin state,
|
||||
// i2c, firmwareQuery, string data.
|
||||
// If neither of those messages is received, then data is treated as "bad_byte"
|
||||
func (b *board) process(data []byte) {
|
||||
buf := bytes.NewBuffer(data)
|
||||
for {
|
||||
|
|
|
@ -16,6 +16,8 @@ type FirmataAdaptor struct {
|
|||
connect func(*FirmataAdaptor)
|
||||
}
|
||||
|
||||
// NewFirmataAdaptor returns a new firmata adaptor with specified name
|
||||
// Generates a connect function that opens serial communication in specified port
|
||||
func NewFirmataAdaptor(name, port string) *FirmataAdaptor {
|
||||
return &FirmataAdaptor{
|
||||
Adaptor: *gobot.NewAdaptor(
|
||||
|
@ -33,6 +35,7 @@ func NewFirmataAdaptor(name, port string) *FirmataAdaptor {
|
|||
}
|
||||
}
|
||||
|
||||
// Connect returns true if connection to board is succesfull
|
||||
func (f *FirmataAdaptor) Connect() bool {
|
||||
f.connect(f)
|
||||
f.board.connect()
|
||||
|
@ -40,6 +43,8 @@ func (f *FirmataAdaptor) Connect() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// close finishes connection to serial port
|
||||
// Prints error message on error
|
||||
func (f *FirmataAdaptor) Disconnect() bool {
|
||||
err := f.board.serial.Close()
|
||||
if err != nil {
|
||||
|
@ -47,9 +52,14 @@ func (f *FirmataAdaptor) Disconnect() bool {
|
|||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Finalize disconnects firmata adaptor
|
||||
func (f *FirmataAdaptor) Finalize() bool { return f.Disconnect() }
|
||||
|
||||
// InitServo (not yet implemented)
|
||||
func (f *FirmataAdaptor) InitServo() {}
|
||||
|
||||
// ServoWrite sets angle form 0 to 360 to specified servo pin
|
||||
func (f *FirmataAdaptor) ServoWrite(pin string, angle byte) {
|
||||
p, _ := strconv.Atoi(pin)
|
||||
|
||||
|
@ -57,6 +67,7 @@ func (f *FirmataAdaptor) ServoWrite(pin string, angle byte) {
|
|||
f.board.analogWrite(byte(p), angle)
|
||||
}
|
||||
|
||||
// PwmWrite writes analog value to specified pin
|
||||
func (f *FirmataAdaptor) PwmWrite(pin string, level byte) {
|
||||
p, _ := strconv.Atoi(pin)
|
||||
|
||||
|
@ -64,6 +75,7 @@ func (f *FirmataAdaptor) PwmWrite(pin string, level byte) {
|
|||
f.board.analogWrite(byte(p), level)
|
||||
}
|
||||
|
||||
// DigitalWrite writes digital values to specified pin
|
||||
func (f *FirmataAdaptor) DigitalWrite(pin string, level byte) {
|
||||
p, _ := strconv.Atoi(pin)
|
||||
|
||||
|
@ -71,6 +83,8 @@ func (f *FirmataAdaptor) DigitalWrite(pin string, level byte) {
|
|||
f.board.digitalWrite(byte(p), level)
|
||||
}
|
||||
|
||||
// DigitalRead retrieves digital value from specified pin
|
||||
// Returns -1 if response from board is timed out
|
||||
func (f *FirmataAdaptor) DigitalRead(pin string) int {
|
||||
ret := make(chan int)
|
||||
|
||||
|
@ -91,6 +105,7 @@ func (f *FirmataAdaptor) DigitalRead(pin string) int {
|
|||
return -1
|
||||
}
|
||||
|
||||
// AnalogRead retrieves value from analog pin.
|
||||
// NOTE pins are numbered A0-A5, which translate to digital pins 14-19
|
||||
func (f *FirmataAdaptor) AnalogRead(pin string) int {
|
||||
ret := make(chan int)
|
||||
|
@ -114,19 +129,24 @@ func (f *FirmataAdaptor) AnalogRead(pin string) int {
|
|||
return -1
|
||||
}
|
||||
|
||||
// AnalogWrite writes value to ananlog pin
|
||||
func (f *FirmataAdaptor) AnalogWrite(pin string, level byte) {
|
||||
f.PwmWrite(pin, level)
|
||||
}
|
||||
|
||||
// digitalPin converts pin number to digital mapping
|
||||
func (f *FirmataAdaptor) digitalPin(pin int) int {
|
||||
return pin + 14
|
||||
}
|
||||
|
||||
// I2cStart initializes board with i2c configuration
|
||||
func (f *FirmataAdaptor) I2cStart(address byte) {
|
||||
f.i2cAddress = address
|
||||
f.board.i2cConfig([]byte{0})
|
||||
}
|
||||
|
||||
// I2cRead reads from I2c specified size
|
||||
// Returns empty byte array if response is timed out
|
||||
func (f *FirmataAdaptor) I2cRead(size uint) []byte {
|
||||
ret := make(chan []byte)
|
||||
f.board.i2cReadRequest(f.i2cAddress, size)
|
||||
|
@ -145,6 +165,7 @@ func (f *FirmataAdaptor) I2cRead(size uint) []byte {
|
|||
return []byte{}
|
||||
}
|
||||
|
||||
// I2cWrite retrieves i2c data
|
||||
func (f *FirmataAdaptor) I2cWrite(data []byte) {
|
||||
f.board.i2cWriteRequest(f.i2cAddress, data)
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ func initTestFirmata() *board {
|
|||
func TestReportVersion(t *testing.T) {
|
||||
b := initTestFirmata()
|
||||
//test if functions executes
|
||||
b.reportVersion()
|
||||
b.queryReportVersion()
|
||||
}
|
||||
|
||||
func TestQueryFirmware(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue