jeol-t330a/succbone/succd/adc.go

62 lines
1.3 KiB
Go

package main
import (
"fmt"
"math"
"os"
"strconv"
"strings"
"time"
)
// adc is an abstract ADC-based analog input.
type adc interface {
// Read returns the ADC value in volts.
Read() (float32, error)
}
// bbADC implements adc using a BeagleBone's built-in ADC.
type bbADC struct {
path string
}
// newBBADC returns a BeagleBone ADC for a given channel number.
func newBBADC(num int) (*bbADC, error) {
path := fmt.Sprintf("/sys/bus/iio/devices/iio:device0/in_voltage%d_raw", num)
if _, err := os.Stat(path); err != nil {
return nil, fmt.Errorf("could not access: %w", err)
}
return &bbADC{
path: path,
}, nil
}
func (b *bbADC) Read() (float32, error) {
by, err := os.ReadFile(b.path)
if err != nil {
return 0, err
}
d := strings.TrimSpace(string(by))
v, err := strconv.ParseUint(d, 10, 64)
if err != nil {
return 0, err
}
// The ADC Vref/Vdd is at 1.8V and is 10-bit (0-4095).
vadc := float32(v) * 1.8 / 4096.0
// The ADC is connected through a resistor divider.
r1 := float32(1000.0)
r2 := float32(4698.0)
vin := vadc / (r1 / (r1 + r2))
return vin, nil
}
// fakeADC implements an adc that outputs a sine wave. This is used for testing.
type fakeADC struct {
}
func (b *fakeADC) Read() (float32, error) {
t := float64(time.Now().UnixMilli()) / 1000
v := (math.Sin(t/10)+1)*(6.5/2) + 2
return float32(v), nil
}