-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathADCDACPi.py
148 lines (127 loc) · 4.96 KB
/
ADCDACPi.py
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python
"""
================================================
ABElectronics ADCDAC Pi Analogue to Digital / Digital to Analogue Converter
================================================
Based on the Microchip MCP3202 and MCP4822
"""
from __future__ import absolute_import, division, print_function, \
unicode_literals
try:
import spidev
except ImportError:
raise ImportError(
"spidev not found.")
class ADCDACPi:
"""
Based on the Microchip MCP3202 and MCP4822
"""
# variables
__adcrefvoltage = 3.3 # reference voltage for the ADC chip.
# Define SPI bus and init
spiADC = spidev.SpiDev()
spiADC.open(0, 1)
spiADC.max_speed_hz = (900000)
spiDAC = spidev.SpiDev()
spiDAC.open(0, 0)
spiDAC.max_speed_hz = (20000000)
dactx = [0, 0]
# Max DAC output voltage. Depends on gain factor
# The following table is in the form <gain factor>:<max voltage>
__dacMaxOutput__ = {
1: 2.048, # This is Vref
2: 3.3 # This is the voltage of the 3.3V rail
}
# public methods
def __init__(self, gain_factor=1):
"""Class Constructor
gain_factor -- Set the DAC's gain factor. The value should
be 1 or 2. Gain factor is used to determine output voltage
from the formula: Vout = G * Vref * D/4096
Where G is gain factor, Vref (for this chip) is 2.048 and
D is the 12-bit digital value
"""
if (gain_factor != 1) and (gain_factor != 2):
raise ValueError('DAC __init__: Invalid gain factor. \
Must be 1 or 2')
else:
self.gain = gain_factor
self.maxdacvoltage = self.__dacMaxOutput__[self.gain]
def read_adc_voltage(self, channel, mode):
"""
Read the voltage from the selected channel on the ADC
Channel = 1 or 2
"""
if (channel > 2) or (channel < 1):
raise ValueError('read_adc_voltage: channel out of range')
if (mode > 1) or (mode < 0):
raise ValueError('read_adc_voltage: mode out of range')
raw = self.read_adc_raw(channel, mode)
voltage = (self.__adcrefvoltage / 4096) * raw
return voltage
def read_adc_raw(self, channel, mode):
"""
Read the raw value from the selected channel on the ADC
Channel = 1 or 2
"""
if (channel > 2) or (channel < 1):
raise ValueError('read_adc_voltage: channel out of range')
if (mode > 1) or (mode < 0):
raise ValueError('read_adc_voltage: mode out of range')
if mode == 0:
raw = self.spiADC.xfer2([1, (1 + channel) << 6, 0])
ret = ((raw[1] & 0x0F) << 8) + (raw[2])
if mode == 1:
if channel == 1:
raw = self.spiADC.xfer2([1, 0x00, 0])
else:
raw = self.spiADC.xfer2([1, 0x40, 0])
ret = ((raw[1]) << 8) + (raw[2])
return ret
def set_adc_refvoltage(self, voltage):
"""
set the reference voltage for the analogue to digital converter.
The ADC uses the raspberry pi 3.3V power as a voltage reference so
using this method to set the reference to match the
exact output voltage from the 3.3V regulator will increase the
accuracy of the ADC readings.
"""
if (voltage >= 0.0) and (voltage <= 7.0):
self.__adcrefvoltage = voltage
else:
raise ValueError('set_adc_refvoltage: reference voltage \
out of range')
return
def set_dac_voltage(self, channel, voltage):
"""
set the voltage for the selected channel on the DAC
voltage can be between 0 and 2.047 volts
"""
if (channel > 2) or (channel < 1):
raise ValueError('set_dac_voltage: DAC channel needs to be 1 or 2')
if (voltage >= 0.0) and (voltage < self.maxdacvoltage):
rawval = (voltage / 2.048) * 4096 / self.gain
self.set_dac_raw(channel, int(rawval))
else:
raise ValueError('set_dac_voltage: voltage out of range')
return
def set_dac_raw(self, channel, value):
"""
Set the raw value from the selected channel on the DAC
Channel = 1 or 2
Value between 0 and 4095
"""
if (channel > 2) or (channel < 1):
raise ValueError('set_dac_voltage: DAC channel needs to be 1 or 2')
if (value < 0) and (value > 4095):
raise ValueError('set_dac_voltage: value out of range')
self.dactx[1] = (value & 0xff)
if self.gain == 1:
self.dactx[0] = (((value >> 8) & 0xff) | (channel - 1) << 7 |
1 << 5 | 1 << 4)
else:
self.dactx[0] = (((value >> 8) & 0xff) | (channel - 1) << 7 |
1 << 4)
# Write to device
self.spiDAC.xfer2(self.dactx)
return