Skip to content

Commit 3a723a4

Browse files
committed
numato board
1 parent 20ac1c5 commit 3a723a4

File tree

8 files changed

+350
-245
lines changed

8 files changed

+350
-245
lines changed

components/board/mcp3008helper/mcp3008.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ func (mar *MCP3008AnalogReader) Read(ctx context.Context, extra map[string]inter
6060
// garbage and might be non-zero.
6161
val := 0x03FF & ((int(rx[1]) << 8) | int(rx[2]))
6262

63-
64-
//TODO: wtf is the analog range for this
63+
//TODO: wtf is the analog range for this
6564
return val, board.AnalogRange{}, nil
6665
}
6766

components/board/numato/board.go

+44-12
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ type numatoBoard struct {
118118
sent map[string]bool
119119
sentMu sync.Mutex
120120
workers rdkutils.StoppableWorkers
121+
122+
productID int
121123
}
122124

123125
func (b *numatoBoard) addToSent(msg string) {
@@ -355,6 +357,7 @@ type analog struct {
355357
pin string
356358
}
357359

360+
// analog Read returns the analog value with the range and step size in mV/bit.
358361
func (a *analog) Read(ctx context.Context, extra map[string]interface{}) (int, board.AnalogRange, error) {
359362
res, err := a.b.doSendReceive(ctx, fmt.Sprintf("adc read %s", a.pin))
360363
if err != nil {
@@ -364,8 +367,34 @@ func (a *analog) Read(ctx context.Context, extra map[string]interface{}) (int, b
364367
if err != nil {
365368
return 0, board.AnalogRange{}, err
366369
}
367-
368-
return reading, board.AnalogRange{Min: 0, Max: 0, StepSize: 0}, nil
370+
var max float32 = 0.0
371+
var stepSize float32 = 0.0
372+
switch a.b.productID {
373+
case 0x805:
374+
// 128 channel usb numato has 12 bit resolution
375+
max = 3.3
376+
stepSize = max / 4096
377+
case 0x802:
378+
// 32 channel usb numato has 10 bit resolution
379+
max = 3.3
380+
stepSize = max / 1024
381+
case 0x800:
382+
// 8 and 16 pin usb versions have the same product ID but different voltage ranges
383+
// both have 10 bit resolution
384+
if a.b.pins == 8 {
385+
max = 5.0
386+
} else if a.b.pins == 16 {
387+
max = 3.3
388+
}
389+
stepSize = max / 1024
390+
case 0xC05:
391+
// 1 channel usb relay module numato - 10 bit resolution
392+
max = 5.0
393+
stepSize = max / 1024
394+
default:
395+
}
396+
stepSize *= 1000
397+
return reading, board.AnalogRange{Min: 0, Max: max, StepSize: stepSize}, nil
369398
}
370399

371400
func (a *analog) Write(ctx context.Context, value int, extra map[string]interface{}) error {
@@ -390,10 +419,10 @@ func connect(ctx context.Context, name resource.Name, conf *Config, logger loggi
390419
path = devs[0].Path
391420
}
392421

393-
// Find the numato board product id
394-
products := usb.Search(usb.NewSearchFilter("AppleUSBACMData", "usbmodem"), func(vendorID, productID int) bool {
395-
return true
396-
})
422+
// Find the numato board's productid
423+
var products []usb.Description
424+
products = getSerialDevices()
425+
397426
var productID int
398427
for _, product := range products {
399428
if product.ID.Vendor != 0x2a19 {
@@ -402,6 +431,10 @@ func connect(ctx context.Context, name resource.Name, conf *Config, logger loggi
402431
productID = product.ID.Product
403432
}
404433

434+
if productID != 0x805|0x802|0x800|0x0C05 {
435+
logger.Warnf("analog range and step size is not supported for numato with product id %d", productID)
436+
}
437+
405438
options := goserial.OpenOptions{
406439
PortName: path,
407440
BaudRate: 19200,
@@ -414,12 +447,12 @@ func connect(ctx context.Context, name resource.Name, conf *Config, logger loggi
414447
if err != nil {
415448
return nil, err
416449
}
417-
418450
b := &numatoBoard{
419-
Named: name.AsNamed(),
420-
pins: pins,
421-
port: device,
422-
logger: logger,
451+
Named: name.AsNamed(),
452+
pins: pins,
453+
port: device,
454+
logger: logger,
455+
productID: productID,
423456
}
424457

425458
b.analogs = map[string]*pinwrappers.AnalogSmoother{}
@@ -437,6 +470,5 @@ func connect(ctx context.Context, name resource.Name, conf *Config, logger loggi
437470
return nil, multierr.Combine(b.Close(ctx), err)
438471
}
439472
b.logger.CDebugw(ctx, "numato startup", "version", ver)
440-
441473
return b, nil
442474
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//go:build darwin
2+
3+
package numato
4+
5+
import "go.viam.com/utils/usb"
6+
7+
func getSerialDevices() []usb.Description {
8+
return usb.Search(usb.NewSearchFilter("AppleUSBACMData", "usbmodem"), func(vendorID, productID int) bool {
9+
return true
10+
})
11+
}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//go:build linux
2+
3+
package numato
4+
5+
import "go.viam.com/utils/usb"
6+
7+
func getSerialDevices() []usb.Description {
8+
return usb.Search(usb.SearchFilter{}, func(vendorID, productID int) bool {
9+
return true
10+
})
11+
}

components/board/pinwrappers/analogs.go

+9-5
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type AnalogSmoother struct {
2626
lastError atomic.Pointer[errValue]
2727
logger logging.Logger
2828
workers utils.StoppableWorkers
29+
analogRange board.AnalogRange
2930
}
3031

3132
// SmoothAnalogReader wraps the given reader in a smoother.
@@ -65,16 +66,14 @@ func (as *AnalogSmoother) Read(ctx context.Context, extra map[string]interface{}
6566
avg := as.data.Average()
6667
lastErr := as.lastError.Load()
6768
if lastErr == nil {
68-
///TODO: figure out range ??
69-
return avg, board.AnalogRange{}, nil
69+
return avg, as.analogRange, nil
7070
}
7171
//nolint:forcetypeassert
7272
if lastErr.present {
73-
return avg, board.AnalogRange{}, lastErr.err
73+
return avg, as.analogRange, lastErr.err
7474
}
7575

76-
//TODO: range here
77-
return avg, board.AnalogRange{}, nil
76+
return avg, as.analogRange, nil
7877
}
7978

8079
// Start begins the smoothing routine that reads from the underlying
@@ -107,6 +106,11 @@ func (as *AnalogSmoother) Start() {
107106
}
108107

109108
as.workers = utils.NewStoppableWorkers(func(ctx context.Context) {
109+
// Store the analog reader range and step size
110+
_, analogRange, err := as.Raw.Read(ctx, nil)
111+
as.lastError.Store(&errValue{err != nil, err})
112+
as.analogRange = analogRange
113+
110114
for {
111115
select {
112116
case <-ctx.Done():

components/board/server.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,10 @@ func (s *serviceServer) ReadAnalogReader(
148148
if err != nil {
149149
return nil, err
150150
}
151-
return &pb.ReadAnalogReaderResponse{Value: int32(val),
152-
MinRange: analogRange.Min, MaxRange: analogRange.Max, StepSize: analogRange.StepSize}, nil
151+
return &pb.ReadAnalogReaderResponse{
152+
Value: int32(val),
153+
MinRange: analogRange.Min, MaxRange: analogRange.Max, StepSize: analogRange.StepSize,
154+
}, nil
153155
}
154156

155157
// WriteAnalog writes the analog value to the analog writer pin of the underlying robot.

0 commit comments

Comments
 (0)