-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add AnalogActuatorDriver, analog temperature sensor, driver for PCF85…
…91 (with 400kbit stabilization), driver for YL-40
- Loading branch information
1 parent
6347285
commit 3b3ad4d
Showing
18 changed files
with
2,088 additions
and
149 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package aio | ||
|
||
import ( | ||
"strconv" | ||
|
||
"gobot.io/x/gobot" | ||
) | ||
|
||
// AnalogActuatorDriver represents an analog actuator | ||
type AnalogActuatorDriver struct { | ||
name string | ||
pin string | ||
connection AnalogWriter | ||
gobot.Eventer | ||
gobot.Commander | ||
scale func(input float64) (value int) | ||
lastValue float64 | ||
lastRawValue int | ||
} | ||
|
||
// NewAnalogActuatorDriver returns a new AnalogActuatorDriver given by an AnalogWriter and pin. | ||
// The driver supports customizable scaling from given float64 value to written int. | ||
// The default scaling is 1:1. An adjustable linear scaler is provided by the driver. | ||
// | ||
// Adds the following API Commands: | ||
// "Write" - See AnalogActuator.Write | ||
// "RawWrite" - See AnalogActuator.RawWrite | ||
func NewAnalogActuatorDriver(a AnalogWriter, pin string) *AnalogActuatorDriver { | ||
d := &AnalogActuatorDriver{ | ||
name: gobot.DefaultName("AnalogActuator"), | ||
connection: a, | ||
pin: pin, | ||
Commander: gobot.NewCommander(), | ||
scale: func(input float64) (value int) { return int(input) }, | ||
} | ||
|
||
d.AddCommand("Write", func(params map[string]interface{}) interface{} { | ||
val, err := strconv.ParseFloat(params["val"].(string), 64) | ||
if err != nil { | ||
return err | ||
} | ||
return d.Write(val) | ||
}) | ||
|
||
d.AddCommand("RawWrite", func(params map[string]interface{}) interface{} { | ||
val, _ := strconv.Atoi(params["val"].(string)) | ||
return d.RawWrite(val) | ||
}) | ||
|
||
return d | ||
} | ||
|
||
// Start starts driver | ||
func (a *AnalogActuatorDriver) Start() (err error) { return } | ||
|
||
// Halt is for halt | ||
func (a *AnalogActuatorDriver) Halt() (err error) { return } | ||
|
||
// Name returns the drivers name | ||
func (a *AnalogActuatorDriver) Name() string { return a.name } | ||
|
||
// SetName sets the drivers name | ||
func (a *AnalogActuatorDriver) SetName(n string) { a.name = n } | ||
|
||
// Pin returns the drivers pin | ||
func (a *AnalogActuatorDriver) Pin() string { return a.pin } | ||
|
||
// Connection returns the drivers Connection | ||
func (a *AnalogActuatorDriver) Connection() gobot.Connection { return a.connection.(gobot.Connection) } | ||
|
||
// RawWrite write the given raw value to the actuator | ||
func (a *AnalogActuatorDriver) RawWrite(val int) (err error) { | ||
a.lastRawValue = val | ||
return a.connection.AnalogWrite(a.Pin(), val) | ||
} | ||
|
||
// SetScaler substitute the default 1:1 return value function by a new scaling function | ||
func (a *AnalogActuatorDriver) SetScaler(scaler func(float64) int) { | ||
a.scale = scaler | ||
} | ||
|
||
// Write writes the given value to the actuator | ||
func (a *AnalogActuatorDriver) Write(val float64) (err error) { | ||
a.lastValue = val | ||
rawValue := a.scale(val) | ||
return a.RawWrite(rawValue) | ||
} | ||
|
||
// RawValue returns the last written raw value | ||
func (a *AnalogActuatorDriver) RawValue() (val int) { | ||
return a.lastRawValue | ||
} | ||
|
||
// Value returns the last written value | ||
func (a *AnalogActuatorDriver) Value() (val float64) { | ||
return a.lastValue | ||
} | ||
|
||
func AnalogActuatorLinearScaler(fromMin, fromMax float64, toMin, toMax int) func(input float64) (value int) { | ||
m := float64(toMax-toMin) / (fromMax - fromMin) | ||
n := float64(toMin) - m*fromMin | ||
return func(input float64) (value int) { | ||
if input <= fromMin { | ||
return toMin | ||
} | ||
if input >= fromMax { | ||
return toMax | ||
} | ||
return int(input*m + n) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package aio | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
|
||
"gobot.io/x/gobot/gobottest" | ||
) | ||
|
||
func TestAnalogActuatorDriver(t *testing.T) { | ||
a := newAioTestAdaptor() | ||
d := NewAnalogActuatorDriver(a, "47") | ||
|
||
gobottest.Refute(t, d.Connection(), nil) | ||
gobottest.Assert(t, d.Pin(), "47") | ||
|
||
err := d.RawWrite(100) | ||
gobottest.Assert(t, err, nil) | ||
gobottest.Assert(t, len(a.written), 1) | ||
gobottest.Assert(t, a.written[0], 100) | ||
|
||
err = d.Write(247.0) | ||
gobottest.Assert(t, err, nil) | ||
gobottest.Assert(t, len(a.written), 2) | ||
gobottest.Assert(t, a.written[1], 247) | ||
gobottest.Assert(t, d.RawValue(), 247) | ||
gobottest.Assert(t, d.Value(), 247.0) | ||
} | ||
|
||
func TestAnalogActuatorDriverWithScaler(t *testing.T) { | ||
// commands | ||
a := newAioTestAdaptor() | ||
d := NewAnalogActuatorDriver(a, "7") | ||
d.SetScaler(func(input float64) int { return int((input + 3) / 2.5) }) | ||
|
||
err := d.Command("RawWrite")(map[string]interface{}{"val": "100"}) | ||
gobottest.Assert(t, err, nil) | ||
gobottest.Assert(t, len(a.written), 1) | ||
gobottest.Assert(t, a.written[0], 100) | ||
|
||
err = d.Command("Write")(map[string]interface{}{"val": "247.0"}) | ||
gobottest.Assert(t, err, nil) | ||
gobottest.Assert(t, len(a.written), 2) | ||
gobottest.Assert(t, a.written[1], 100) | ||
} | ||
|
||
func TestAnalogActuatorDriverLinearScaler(t *testing.T) { | ||
var tests = map[string]struct { | ||
fromMin float64 | ||
fromMax float64 | ||
input float64 | ||
want int | ||
}{ | ||
"byte_range_min": {fromMin: 0, fromMax: 255, input: 0, want: 0}, | ||
"byte_range_max": {fromMin: 0, fromMax: 255, input: 255, want: 255}, | ||
"signed_percent_range_min": {fromMin: -100, fromMax: 100, input: -100, want: 0}, | ||
"signed_percent_range_mid": {fromMin: -100, fromMax: 100, input: 0, want: 127}, | ||
"signed_percent_range_max": {fromMin: -100, fromMax: 100, input: 100, want: 255}, | ||
"voltage_range_min": {fromMin: 0, fromMax: 5.1, input: 0, want: 0}, | ||
"voltage_range_nearmin": {fromMin: 0, fromMax: 5.1, input: 0.02, want: 1}, | ||
"voltage_range_mid": {fromMin: 0, fromMax: 5.1, input: 2.55, want: 127}, | ||
"voltage_range_nearmax": {fromMin: 0, fromMax: 5.1, input: 5.08, want: 254}, | ||
"voltage_range_max": {fromMin: 0, fromMax: 5.1, input: 5.1, want: 255}, | ||
"upscale": {fromMin: 0, fromMax: 24, input: 12, want: 127}, | ||
"below_min": {fromMin: -10, fromMax: 10, input: -11, want: 0}, | ||
"exceed_max": {fromMin: 0, fromMax: 20, input: 21, want: 255}, | ||
} | ||
a := newAioTestAdaptor() | ||
d := NewAnalogActuatorDriver(a, "7") | ||
|
||
for name, tt := range tests { | ||
t.Run(name, func(t *testing.T) { | ||
// arrange | ||
d.SetScaler(AnalogActuatorLinearScaler(tt.fromMin, tt.fromMax, 0, 255)) | ||
a.written = []int{} // reset previous write | ||
// act | ||
err := d.Write(tt.input) | ||
// assert | ||
gobottest.Assert(t, err, nil) | ||
gobottest.Assert(t, len(a.written), 1) | ||
gobottest.Assert(t, a.written[0], tt.want) | ||
}) | ||
} | ||
} | ||
|
||
func TestAnalogActuatorDriverStart(t *testing.T) { | ||
d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") | ||
gobottest.Assert(t, d.Start(), nil) | ||
} | ||
|
||
func TestAnalogActuatorDriverHalt(t *testing.T) { | ||
d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") | ||
gobottest.Assert(t, d.Halt(), nil) | ||
} | ||
|
||
func TestAnalogActuatorDriverDefaultName(t *testing.T) { | ||
d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") | ||
gobottest.Assert(t, strings.HasPrefix(d.Name(), "AnalogActuator"), true) | ||
} | ||
|
||
func TestAnalogActuatorDriverSetName(t *testing.T) { | ||
d := NewAnalogActuatorDriver(newAioTestAdaptor(), "1") | ||
d.SetName("mybot") | ||
gobottest.Assert(t, d.Name(), "mybot") | ||
} |
Oops, something went wrong.