ev3go / ev3dev Goto Github PK
View Code? Open in Web Editor NEWev3dev is a simple interface to the Lego Mindstorms ev3 robotics platform
License: Other
ev3dev is a simple interface to the Lego Mindstorms ev3 robotics platform
License: Other
I'm developing code on OS X and the package does not compile locally because of the unix.Poll dependency. This is generally not an issue because of cross compilation, but code completion and other local tools do not work correctly.
There should be a build tag for the code that uses the unix dependency in a separate file, so it has a bogus implementation for other platforms.
I got that working and will push a PR soon.
The BuWizz battery is a promising device that allows control of LEGO motors and other power functions by Bluetooth. It can be controlled (currently) via an app available for ios and android.
The developers claim that the communication protocol will be opened. However, there is little indication that this is happening. When it does, add a package that allows a BT-enabled EV3 device to control paired BuWizz bricks.
I know I can set flags to configure target architecture for a compiled app.
I want to develop on my main Mac machine, then compile and transfer compiled files into the brick.
What options should I use to compile for EV3 on a Mac?
It seems I missed an attribute: fw_version
for sensors.
The code for fbdev handling in ev3 and evb are essentially identical. This code should be moved to ev3dev (back again) in a way that only keeps the device-specific code in the ev3 and evb packages.
I'm writing something with the mindsensors 9dof and sensor initialisation fails with failed to find sensor: ev3dev: failed to read sensor0 commands attribute /sys/class/lego-sensor/sensor0/commands: read /sys/class/lego-sensor/sensor0/commands: operation not supported at ev3dev.go:533 github.com/ev3go/ev3dev.attributeOf
because reading from commands
returns ENOTSUP
(I had had this in tests previously - probably because I noticed this).
To avoid this, allow ENOTSUP
failure to be ignored on initialisation.
See http://ddemidov.github.io/ev3dev-lang-python/#ev3dev.PowerSupply for python example.
The ev3go/ev3dev package was easy to start with errors.New
and fmt.Errorf
, but it makes mechanical error handling difficult. So add three (?) error interface types and relevant implementations:
type ValidValuer interface {
ValidValues() []string
}
type ValidRanger interface {
ValidRange() (min, max int)
}
type ValidDurationRanger interface {
ValidDurationRange() (min, max time.Duration)
}
type NegativeDuration time.Duration
func (d NegativeDuration) Error() string {
if d >= 0 {
panic(fmt.Sprintf("ev3dev: invalid negative duration: %v", d))
}
return fmt.Sprintf("ev3dev: invalid duration: %v (must be positive)", time.Duration(d))
}
func (d NegativeDuration) ValidDurationRange() (min, max time.Duration) {
if d >= 0 {
panic(fmt.Sprintf("ev3dev: invalid negative duration: %v", d))
}
return 0, MaxInt64
}
See #50 (comment)
Add StopActions (string, error)
, StopActions() ([]string, error)
and SetStopAction(action string) *Steerer
. StopAction
and StopActions
will error if the returned values do not match.
New to go1.8.1; go1.7.4 passes.
WARNING: DATA RACE
Write at 0x00c4200de1e1 by goroutine 32:
github.com/ev3go/ev3dev_test.(*sensorDirect).Truncate()
/home/daniel/src/github.com/ev3go/ev3dev/sensor_test.go:333 +0x1a6
github.com/ev3go/sisyphus.(*RW).Setattr()
/home/daniel/src/github.com/ev3go/sisyphus/rw_node.go:194 +0x13a
bazil.org/fuse/fs.(*Server).handleRequest()
/home/daniel/src/bazil.org/fuse/fs/serve.go:945 +0x3e2d
bazil.org/fuse/fs.(*Server).serve()
/home/daniel/src/bazil.org/fuse/fs/serve.go:878 +0x5e5
bazil.org/fuse/fs.(*Server).Serve.func1()
/home/daniel/src/bazil.org/fuse/fs/serve.go:425 +0x7f
Previous read at 0x00c4200de1e1 by goroutine 16:
reflect.typedmemmove()
/home/daniel/go/src/runtime/mbarrier.go:253 +0x0
reflect.packEface()
/home/daniel/go/src/reflect/value.go:112 +0x11c
reflect.valueInterface()
/home/daniel/go/src/reflect/value.go:955 +0x18c
reflect.deepValueEqual()
/home/daniel/go/src/reflect/deepequal.go:132 +0x3a6
reflect.deepValueEqual()
/home/daniel/go/src/reflect/deepequal.go:84 +0xaf0
reflect.DeepEqual()
/home/daniel/go/src/reflect/deepequal.go:190 +0x2bb
github.com/ev3go/ev3dev_test.TestSensor.func7()
/home/daniel/src/github.com/ev3go/ev3dev/sensor_test.go:875 +0x57d
testing.tRunner()
/home/daniel/go/src/testing/testing.go:657 +0x107
Goroutine 32 (running) created at:
bazil.org/fuse/fs.(*Server).Serve()
/home/daniel/src/bazil.org/fuse/fs/serve.go:426 +0x695
github.com/ev3go/sisyphus.Serve.func1()
/home/daniel/src/github.com/ev3go/sisyphus/sisyphus.go:47 +0x68
Goroutine 16 (running) created at:
testing.(*T).Run()
/home/daniel/go/src/testing/testing.go:697 +0x543
github.com/ev3go/ev3dev_test.TestSensor()
/home/daniel/src/github.com/ev3go/ev3dev/sensor_test.go:902 +0x12da
testing.tRunner()
/home/daniel/go/src/testing/testing.go:657 +0x107
See http://www.ev3dev.org/docs/tutorials/using-ev3-buttons/ for docs.
go test -race
is very noisy.
Hi there
What do you think about a higher level api?
I felt like leaning go and stared to port my python linefollower to go.
I got to this: https://github.com/vogtp/ev3bot
Not yet a linefollower and probably horrible go code...
... but it might be a starting point for a high level api.
have fun
Patrick
It would be nice to have sound support. Tone/beep is easy to implement using the Linux input subsystem (evdev). Since we don't want to use cgo, we would have to call an external process (e.g. aplay
for PCM playback.
How do you plan on handling breaking driver changes in ev3dev-stretch? For example, port names and LED names have changed.
Similar to #53, sensors have sysfs attributes that never change and could be cached.
address
, commands
, driver_name
, fw_version
, modes
.
Additionally, some values only change when the mode changes. It is fairly safe to make the assumption that no one will change the mode outside of your program (but technically, not a 100% guarantee). These values could be cached when the mode is set.
bin_data_format
, decimals
, mode
, num_values
, units
I am new to both EV3 and Go. I just wanted to play a bit with motor control (large motor on outB). While it was easily in Python...
#!/usr/bin/env python3
from time import sleep
from ev3dev.ev3 import *
motor_left = LargeMotor('outB')
motor_left.run_direct(duty_cycle_sp=100)
sleep(0.5)
motor_left.run_direct(duty_cycle_sp=0)
The same went shockingly difficult in Go...
package main
import (
"time"
"github.com/ev3go/ev3dev"
)
func main() {
const driver = "lego-ev3-l-motor"
m, err := ev3dev.TachoMotorFor("outB", driver)
if err != nil {
panic(err)
}
err = m.Command("reset").Err()
if err != nil {
panic(err)
}
err = m.SetPolarity("normal").Err()
if err != nil {
panic(err)
}
maxSpeed, err := m.MaxSpeed()
if err != nil {
panic(err)
}
err = m.SetSpeedSetpoint(maxSpeed).Err()
if err != nil {
panic(err)
}
err = m.Command("run-forever").Err()
if err != nil {
panic(err)
}
time.Sleep(500 * time.Millisecond)
err = m.Command("stop").Err()
if err != nil {
panic(err)
}
}
I can write a Python run_direct
-like function in Go, of course. But I wonder whether there is such a function, that I could use out-of-the-box.
First of all, thanks for all the work done so far on this great library.
Are there any plans to publish a tagged version, like discribed here https://go.dev/blog/publishing-go-modules?
If each device type holds an err error
field and has an Err() error
method, then setters can return the device pointer. Attribute reader and writer methods would return early if the err
field if non-nil, so a call to Err
should reset the err
field to nil.
This depends on providing some basic read/write VFS functionality for mocking the sysfs (golang.org/x/tools/godoc/vfs would work but is read only).
This adds functionality that is specified in the ev3dev.org API for the base device class.
func IsConnected(d Device) (bool, error)
provides the capacity to query whether the Device
is still connected (the API specification actually caches this AFAICS, so this is a difference, but I think determining the value at call time is more sensible).
I'm inexperienced in go, so I thought I would share my first ev3go program and see what you think.
package main
import (
"log"
"strconv"
"image/color"
"os/exec"
"github.com/ev3go/ev3"
"github.com/ev3go/ev3dev"
)
const (
top = 30
bottom = 100
left = 70
right = 110
)
func main() {
// configure the LEGO EV3 IR sensor on input port 1 in IR-SEEK mode
irSensor, err := ev3dev.SensorFor("in1", "lego-ev3-ir")
if err != nil {
log.Fatal(err)
}
irSensor.SetMode("IR-SEEK")
// configure LEGO EV3 Large motor in output port A
motor, err := ev3dev.TachoMotorFor("outA", "lego-ev3-l-motor")
if err != nil {
log.Fatal(err)
}
// init poller so we can monitor buttons
buttonPoller := ev3dev.ButtonPoller{}
// init the LCD so we can draw stuff
ev3.LCD.Init(true)
defer ev3.LCD.Close()
motor.Command("run-direct")
beaconPresent := false
for {
// read the channel 1 heading value from the IR sensor
v0, _ := irSensor.Value(0)
heading, _ := strconv.Atoi(v0)
// motor rotation is in the same direction as heading, so this will
// cause the motor to rotate towards the beacon
motor.SetDutyCycleSetpoint(heading)
v1, _ := irSensor.Value(1)
distance, _ := strconv.Atoi(v1)
// sound feedback when beacon is in or out of range
if beaconPresent && distance == -128 {
beaconPresent = false
exec.Command("beep", "-f", "400", "-n", "-f", "200").Start()
} else if !beaconPresent && distance != -128 {
beaconPresent = true
exec.Command("beep", "-f", "200", "-n", "-f", "400").Start()
}
// Draw a bar graph to indicate how far away the beacon is. The closer
// the beacon, the taller the graph.
for x := left; x < right; x++ {
for y := top; y < bottom; y++ {
if y > top+distance {
ev3.LCD.Set(x, y, color.Black)
} else {
ev3.LCD.Set(x, y, color.White)
}
}
}
// check for button presses
b, err := buttonPoller.Poll()
if err != nil {
log.Fatal(err)
}
if (b & ev3dev.Back) == ev3dev.Back {
// exit the program
break
}
if (b & ev3dev.Middle) == ev3dev.Middle {
speak := exec.Command("espeak", "--stdout", "-a", "200", "-s", "100",
"Don't press that button")
play := exec.Command("aplay", "-q")
play.Stdin, _ = speak.StdoutPipe()
speak.Start()
play.Start()
}
}
}
This was going to go into the testing PR, but that has been going on too long.
While we can make things race free from the perspective of the code, there are still possibilities for physical racing. We should not allow this, so make it impossible to hold more than one Device
to any single physical port, with flexibility for the LegoPort
type which should not prevent other device types from attaching to the port they are controlling.
Is there a documentation section on how to use EV3 Go bindings?
This is just a matter of style, but I would rather see setpoint written as "Setpoint" instead of "SetPoint" in identifier names. I consider it a single word.
There is ad hoc evdev implementation in ev3dev. This may want to be expanded in the future. A third party evdev package does already exist, but it is cgo dependent which makes its use in this context difficult; compiling programs for controlling and ev3 will either be done using cross compilation which precludes cgo, or will be done on the ev3 itself which will be slow. So if an evdev package is implemented it needs to be pure Go.
I have encountered an install issue that has raised this error
go get -v github.com/ev3go/ev3dev
github.com/ev3go/ev3dev
# github.com/ev3go/ev3dev
C:\Users\<USERNAME>\go\pkg\mod\github.com\ev3go\[email protected]\evdev.go:39:32: not enough arguments in call to syscall.Syscall
C:\Users\<USERNAME>\go\pkg\mod\github.com\ev3go\[email protected]\evdev.go:39:33: undefined: syscall.SYS_IOCTL
C:\Users\<USERNAME>\go\pkg\mod\github.com\ev3go\[email protected]\lcd.go:79:17: undefined: syscall.Mmap
C:\Users\<USERNAME>\go\pkg\mod\github.com\ev3go\[email protected]\lcd.go:79:62: undefined: syscall.PROT_READ
C:\Users\<USERNAME>\go\pkg\mod\github.com\ev3go\[email protected]\lcd.go:79:80: undefined: syscall.PROT_WRITE
C:\Users\<USERNAME>\go\pkg\mod\github.com\ev3go\[email protected]\lcd.go:79:100: undefined: syscall.MAP_SHARED
C:\Users\<USERNAME>\go\pkg\mod\github.com\ev3go\[email protected]\lcd.go:103:9: undefined: syscall.Munmap
Package level action variables deserve locks, but removing them made fluent API easier to design.
Blocked on #8.
I recently tried Go on the EV3 because I hoped it would have better performance compared to Python.
In a while loop, the robot repeatedly retrieves a sensor value (in this case, from mindsensors.com Line Leader) and thus waits until it changes to a specific value.
I converted the corresponding Python code to Go, but I noticed Go is actually seven times slower in retrieving those sensor values. Below are the two test programs I wrote to compare the performance.
ll = Sensor("in2")
ll.mode = "PID-ALL"
debug_print("Starting")
start = time.perf_counter()
for _ in range(1000):
value = ll.value(2)
if value == -1:
# is on black line; the program would normally end the loop here
pass
end = time.perf_counter()-start
debug_print(end)
Output (example): 0.9874834319999763
func main() {
ll, err := ev3dev.SensorFor("ev3-ports:in2:i2c1", "ms-line-leader")
if err != nil {
log.Fatal(err)
}
ll.SetMode("PID-ALL")
log.Println("Starting")
start := time.Now()
for i := 0; i < 1000; i++ {
value, err := ll.Value(2)
if err != nil {
log.Fatal(err)
}
if value == "-1" {
// is on black line
}
}
end := time.Since(start)
log.Println(end)
}
Output (example): 6.850100872s
While Python takes about 1 second on my EV3 for the loop, Go takes about 7 seconds.
The question I'm asking myself is: Am I doing something wrong here? Because I usually would expect Go to be faster, and indeed the startup time is much lower.
If not: Why is Go seven times slower? I couldn't find any major difference between how the python ev3dev2
module and the Go github.com/ev3go/ev3dev
package retrieve sensor values.
PS: I think ~143 checks per second with Go are more than enough, but I'm opening this issue because I'm curious to find out what causes this. As you might have guessed, I've got little to no experience with Go.
Add functions Find(dst Device, driver string) error
and FindAfter(d, dst Device, driver string) error
that find a device of the given Device
types such that the driver name matches the device driver.
The approach is to iterate over the dst.Path()
contents and check the driver name against driver
, returning the first match in the case of Find
or the first match after d.String()
in the directory list for FindAfter
. The resulting found device is placed in dst
by reflection (or a private setID
method is added to Device
) and its err
field is set to nil.
If d
is nil in FindAfter
searching starts from the first directory slot associated with dst
(equivalent to Find
). If it is not nil, it's concrete type must match the concrete type of dst
or an error is returned.
Only ev3go/ev3/ev3dev
devices are supported; use of others will return a meaningful error.
http://docs.ev3dev.org/projects/lego-linux-drivers/en/ev3dev-stretch/brickpi3.html
Inputs: spi0.1:SX:DEVICE
where X is in {1-4}.
Outputs: spi0.1:MY:DEVICE
where Y is in {A-D}.
Hi,
I was wondering how the Mindsensors Sensor Multiplexer could be used in this language, including:
Thanks in advance
Add it if it does.
Add an ev3 package and start with high-level LED control.
Sketch:
type LED struct { ... }
func NewLED(s Side) *LED
func (l *LED) Color() (color.Color, error)
func (l *LED) SetColor(color.Color) *LED
func (l *LED) Trigger() (Trigger, error)
func (l *LED) SetTrigger(Trigger) *LED
func (l *LED) Pattern([]time.Duration) *LED
func (l *LED) Stream(<-chan time.Duration) *LEDStream
func (l *LED) Err() error
type Side byte
const (
Left Side = 1 << iota
Right
}
type Trigger string
const (
None Trigger = "none"
MMC0 ... etc
Timer
Heartbeat
DefaultOn
Transient
BatteryChargingOrFull
BatteryCharging
BatteryFull
BatteryChargingBlinkFullSolid
RFKill0
)
type LEDStream struct { ... }
func (l *LEDStream) Waiter() <-chan error
See ##50 (comment).
address
AddressOf
provides thiscommands
count_per_rot
count_per_m
full_travel_count
driver_name
max_speed
stop_actions
Hello,
I am having some trouble making the example run.
What I did on my computer:
go get github.com/ev3go/ev3dev/examples/demo
go build github.com/ev3go/ev3dev/examples/demo
scp demo [email protected]:/home/robot
What I did on the robot:
./demo
.robot@ev3dev:~$ ./demo
unexpected fault address 0xa6c92000
fatal error: fault
[signal SIGBUS: bus error code=0x2 addr=0xa6c92000 pc=0x63dd4]
goroutine 1 [running]:
runtime.throw(0xe8bd5, 0x5)
/usr/local/go/src/runtime/panic.go:608 +0x5c fp=0x424668 sp=0x424654 pc=0x38990
runtime.sigpanic()
/usr/local/go/src/runtime/signal_unix.go:387 +0x214 fp=0x42468c sp=0x424668 pc=0x4bfb0
runtime.memclrNoHeapPointers(0xa6c91000, 0x16400)
/usr/local/go/src/runtime/memclr_arm.s:68 +0x58 fp=0x424690 sp=0x424690 pc=0x63dd4
github.com/ev3go/ev3dev.(*lcd).frameBuffer(0x472000, 0xf0b01, 0x472018, 0x66)
/home/lionel/Documents/projects/go/src/github.com/ev3go/ev3dev/lcd.go:85 +0x1c0 fp=0x4246cc sp=0x424690 pc=0xb8774
github.com/ev3go/ev3dev.(*lcd).Init(0x472000, 0x1, 0x0, 0x0)
/home/lionel/Documents/projects/go/src/github.com/ev3go/ev3dev/lcd.go:60 +0x10c fp=0x4246e4 sp=0x4246cc pc=0xb8578
main.main()
/home/lionel/Documents/projects/go/src/github.com/ev3go/ev3dev/examples/demo/demo.go:26 +0x38 fp=0x4247c4 sp=0x4246e4 pc=0xbb970
runtime.main()
/usr/local/go/src/runtime/proc.go:201 +0x204 fp=0x4247e4 sp=0x4247c4 pc=0x3a584
runtime.goexit()
/usr/local/go/src/runtime/asm_arm.s:867 +0x4 fp=0x4247e4 sp=0x4247e4 pc=0x636d8
I compiled a simple hello world program to make sure the problem was not from the compilation and it worked perfectly.
Could you help me please?
Note: I am using the jessie version ev3dev-jessie-ev3-generic-2017-09-14
Polling and waiting are essentially high-level functions and so might be a better fit for ev3. The ev3dev Button type would then just return the /dev/input
file corresponding to the button event, being a string type and defaulting to /dev/input/by-path/platform-gpio-keys.0-event
when zero.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.