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 }