-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathanalog_reader.go
110 lines (91 loc) · 2.94 KB
/
analog_reader.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package europi
import (
"machine"
"math"
)
const (
// Calibrated[Min|Max]AI was calculated using the EuroPi calibration program:
// https://github.com/Allen-Synthesis/EuroPi/blob/main/software/programming_instructions.md#calibrate-the-module
CalibratedMinAI = 300
CalibratedMaxAI = 44009
DefaultSamples = 1000
)
func init() {
machine.InitADC()
}
// AnalogReader is an interface for common analog read methods for knobs and cv input.
type AnalogReader interface {
Samples(samples uint16)
ReadVoltage() float32
Percent() float32
Range(steps uint16) uint16
}
// A struct for handling the reading of analogue control voltage.
// The analogue input allows you to 'read' CV from anywhere between 0 and 12V.
type AnalogInput struct {
machine.ADC
samples uint16
}
// NewAI creates a new AnalogInput.
func NewAI(pin machine.Pin) *AnalogInput {
adc := machine.ADC{Pin: pin}
adc.Configure(machine.ADCConfig{})
return &AnalogInput{ADC: adc, samples: DefaultSamples}
}
// Samples sets the number of reads for an more accurate average read.
func (a *AnalogInput) Samples(samples uint16) {
a.samples = samples
}
// Percent return the percentage of the input's current relative range as a float between 0.0 and 1.0.
func (a *AnalogInput) Percent() float32 {
return float32(a.read()) / CalibratedMaxAI
}
// ReadVoltage return the current read voltage between 0.0 and 10.0 volts.
func (a *AnalogInput) ReadVoltage() float32 {
return a.Percent() * MaxVoltage
}
// Range return a value between 0 and the given steps (not inclusive) based on the range of the analog input.
func (a *AnalogInput) Range(steps uint16) uint16 {
return uint16(a.Percent() * float32(steps))
}
func (a *AnalogInput) read() uint16 {
var sum int
for i := 0; i < int(a.samples); i++ {
sum += Clamp(int(a.Get())-CalibratedMinAI, 0, CalibratedMaxAI)
}
return uint16(sum / int(a.samples))
}
// A struct for handling the reading of knob voltage and position.
type Knob struct {
machine.ADC
samples uint16
}
// NewKnob creates a new Knob struct.
func NewKnob(pin machine.Pin) *Knob {
adc := machine.ADC{Pin: pin}
adc.Configure(machine.ADCConfig{})
return &Knob{ADC: adc, samples: DefaultSamples}
}
// Samples sets the number of reads for an more accurate average read.
func (k *Knob) Samples(samples uint16) {
k.samples = samples
}
// Percent return the percentage of the knob's current relative range as a float between 0.0 and 1.0.
func (k *Knob) Percent() float32 {
return 1 - float32(k.read())/math.MaxUint16
}
// ReadVoltage return the current read voltage between 0.0 and 10.0 volts.
func (k *Knob) ReadVoltage() float32 {
return k.Percent() * MaxVoltage
}
// Range return a value between 0 and the given steps (not inclusive) based on the range of the knob's position.
func (k *Knob) Range(steps uint16) uint16 {
return uint16(k.Percent() * float32(steps))
}
func (k *Knob) read() uint16 {
var sum int
for i := 0; i < int(k.samples); i++ {
sum += int(k.Get())
}
return uint16(sum / int(k.samples))
}