@@ -10,7 +10,7 @@ import (
1010)
1111
1212// InputType defines how an ADC samples the input signal. A single-ended input
13- // samples its input in the range from the ground (0V) to Vref, or the refence
13+ // samples its input in the range from the ground (0V) to Vref, that is the reference
1414// input. A 10-bits ADC with a reference input of 5V has a precision of (5 -
1515// 0) / 1024 = 0.0049V = 4.9mV on single-ended inputs.
1616//
@@ -24,18 +24,45 @@ type InputType int
2424const (
2525 // SingleEnded configures the inputs of an ADC as single-ended.
2626 SingleEnded InputType = 0
27+
2728 // PseudoDifferential configures the inputs of an ADC as pseudo-differential.
2829 PseudoDifferential InputType = 1
2930)
3031
3132// ADC is the interface that wraps a Read method.
3233//
33- // Read returns the voltage of a channel of the ADC .
34+ // Read queries the channel of an ADC and returns it's voltage .
3435type ADC interface {
3536 Read (channel int ) (float64 , error )
3637}
3738
39+ // MCP3004 is 10-bits ADC with 4 single-ended or 2 pseudo-differential inputs.
40+ // Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21295C.pdf
41+ type MCP3004 struct {
42+ Conn * spi.Device
43+
44+ // Vref is the voltage on the reference input of the ADC.
45+ Vref float64
46+
47+ InputType InputType
48+ }
49+
50+ // Read returns the voltage of a channel.
51+ func (m MCP3004 ) Read (channel int ) (float64 , error ) {
52+ if channel < 0 || channel > 4 {
53+ return 0 , fmt .Errorf ("channel %d is invalid, ADC has only 4 channels" , channel )
54+ }
55+
56+ raw , err := read10 (m .Conn , channel , m .InputType )
57+ if err != nil {
58+ return 0 , err
59+ }
60+
61+ return (m .Vref / 1024 ) * float64 (raw ), nil
62+ }
63+
3864// MCP3008 is 10-bits ADC with 8 single-ended or 4 pseudo-differential inputs.
65+ // Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21295C.pdf
3966type MCP3008 struct {
4067 Conn * spi.Device
4168
@@ -47,12 +74,26 @@ type MCP3008 struct {
4774
4875// Read returns the voltage of a channel.
4976func (m MCP3008 ) Read (channel int ) (float64 , error ) {
77+ if channel < 0 || channel > 7 {
78+ return 0 , fmt .Errorf ("channel %d is invalid, ADC has only 8 channels" , channel )
79+ }
80+
81+ raw , err := read10 (m .Conn , channel , m .InputType )
82+ if err != nil {
83+ return 0 , err
84+ }
85+
86+ return (m .Vref / 1024 ) * float64 (raw ), nil
87+ }
88+
89+ // read10 reads a 10 bits value from an channel of an ADC.
90+ func read10 (conn * spi.Device , channel int , inputType InputType ) (int , error ) {
5091 var cmd int
5192
5293 // The first bit after the start bit will determine if the conversion
5394 // is done using single-ended or differential input mode. 0 means
5495 // differential, 1 means single-ended.
55- if m . InputType == SingleEnded {
96+ if inputType == SingleEnded {
5697 cmd = 1
5798 }
5899 // The bit is then shifted 3 times and the number is incremented with
@@ -77,7 +118,7 @@ func (m MCP3008) Read(channel int) (float64, error) {
77118 // bytes we read 3 bytes.
78119 in := make ([]byte , 3 )
79120
80- if err := m . Conn .Tx (out , in ); err != nil {
121+ if err := conn .Tx (out , in ); err != nil {
81122 return 0 , fmt .Errorf ("failed to read channel %d: %v" , channel , err )
82123 }
83124
@@ -100,7 +141,113 @@ func (m MCP3008) Read(channel int) (float64, error) {
100141 // 00000010 10110111
101142 //
102143 // 00000010 10110111 is 696 in base10.
103- output := float64 (int (in [1 ]& 3 )<< 8 + int (in [2 ]))
144+ return int (in [1 ]& 3 )<< 8 + int (in [2 ]), nil
145+ }
146+
147+ // MCP3204 is 12-bits ADC with 4 single-ended or 2 pseudo-differential inputs.
148+ // Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21298e.pdf
149+ type MCP3204 struct {
150+ Conn * spi.Device
104151
105- return (m .Vref / 1024 ) * output , nil
152+ // Vref is the voltage on the reference input of the ADC.
153+ Vref float64
154+
155+ InputType InputType
156+ }
157+
158+ // Read returns the voltage of a channel.
159+ func (m MCP3204 ) Read (channel int ) (float64 , error ) {
160+ if channel < 0 || channel > 4 {
161+ return 0 , fmt .Errorf ("channel %d is invalid, ADC has only 4 channels" , channel )
162+ }
163+
164+ raw , err := read12 (m .Conn , channel , m .InputType )
165+ if err != nil {
166+ return 0 , err
167+ }
168+
169+ return (m .Vref / 4096 ) * float64 (raw ), nil
170+ }
171+
172+ // MCP3208 is 12-bits ADC with 8 single-ended or 4 pseudo-differential inputs.
173+ // Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21298e.pdf
174+ type MCP3208 struct {
175+ Conn * spi.Device
176+
177+ // Vref is the voltage on the reference input of the ADC.
178+ Vref float64
179+
180+ InputType InputType
181+ }
182+
183+ // Read returns the voltage of a channel.
184+ func (m MCP3208 ) Read (channel int ) (float64 , error ) {
185+ if channel < 0 || channel > 8 {
186+ return 0 , fmt .Errorf ("channel %d is invalid, ADC has only 8 channels" , channel )
187+ }
188+
189+ raw , err := read12 (m .Conn , channel , m .InputType )
190+ if err != nil {
191+ return 0 , err
192+ }
193+
194+ return (m .Vref / 4096 ) * float64 (raw ), nil
195+ }
196+
197+ // read12 reads a 12 bits value from an channel of an ADC.
198+ func read12 (conn * spi.Device , channel int , inputType InputType ) (int , error ) {
199+ // The start bit.
200+ cmd := 1
201+ cmd = cmd << 1
202+
203+ // The first bit after the start bit will determine if the conversion
204+ // is done using single-ended or differential input mode. 0 means
205+ // differential, 1 means single-ended.
206+ if inputType == SingleEnded {
207+ cmd = 1
208+ }
209+ // The bit is then shifted 3 times and the number is incremented with
210+ // a 3 bits channel.
211+ cmd = cmd << 3
212+ cmd += channel
213+
214+ // The result is shifted 6 times.
215+ //
216+ // x x x x x 1 1 1 1 1 x x x x x x
217+ // | | | | | ------- 3 bits for selecting channel
218+ // | |---------------- 1 bit defining single-ended or pseudo-differential input mode
219+ // |------------------ 1 start bit
220+ cmd = cmd << 6
221+
222+ // The data is is in the first 2 bytes, the third byte is an empty byte.
223+ out := []byte {byte (cmd >> 8 ), byte (cmd & 0xFF ), 0 }
224+
225+ // For every byte send the SPI master reads a byte. Because we send 3
226+ // bytes we read 3 bytes.
227+ in := make ([]byte , 3 )
228+
229+ if err := conn .Tx (out , in ); err != nil {
230+ return 0 , fmt .Errorf ("failed to read channel %d: %v" , channel , err )
231+ }
232+
233+ // The 12-bits measurement is at the end of the 3 byte response.
234+ //
235+ // 11111111 11101100 10110111
236+ // ^^^^ ^^^^^^^^
237+ // To get the base10 value of the channel the second byte is masked
238+ // with 15:
239+ //
240+ // 11101100
241+ // 00001111
242+ // -------- &
243+ // 00001100
244+ //
245+ // The byte is shifted 8 bits and the last byte is added:
246+ // 00001100 00000000
247+ // 10110111
248+ // -------- +
249+ // 00001100 10110111
250+ //
251+ // 00001100 10110111 is 3255 in base10.
252+ return int (in [1 ]& 0xF )<< 8 + int (in [2 ]), nil
106253}
0 commit comments