-
Notifications
You must be signed in to change notification settings - Fork 3
/
mcp3008.py
125 lines (99 loc) · 3.5 KB
/
mcp3008.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
"""
Here is a growing collection of libraries and example python scripts for controlling a variety of Adafruit electronics with a Raspberry Pi
In progress!
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
Written by Limor Fried, Kevin Townsend and Mikey Sklar for Adafruit Industries. BSD license, all text above must be included in any redistribution
To download, we suggest logging into your Pi with Internet accessibility and typing: git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git
Refactored into a class structure and pluggable access objects added by Eric Stein. Modifications BSD as well.
"""
import RPi.GPIO as GPIO
import threading
# change these as desired - they're the pins connected from the
# SPI port on the ADC to the Cobbler
SPICLK = 18
SPIMISO = 23
SPIMOSI = 24
SPICS = 25
class Pin(object) :
def read(self) :
raise NotImplemented
class TMP36(Pin) :
F = 0
C = 1
K = 2
"""
Choose a scale if you don't want C. K and F also available as constants in the class scope.
"""
def __init__(self, temp_scale=None) :
if temp_scale is None :
temp_scale = self.C
self.temp_scale = temp_scale
@classmethod
def c2f(self, c) :
# convert celsius to fahrenheit
return ( c * 9.0 / 5.0 ) + 32
@classmethod
def c2k(self, c) :
# celsius to kelvin
return c + 273.15
def setup_mcp3008(self, mcp, channel_number) :
self.mcp = mcp
self.channel_number = channel_number
def read(self) :
millivolts = self.mcp.readadc(self.channel_number)
c = ((millivolts - 100.0) / 10.0) - 40.0
if self.temp_scale == TMP36.C :
return c
elif self.temp_scale == TMP36.F :
return TMP36.c2f(c)
elif self.temp_scale == TMP36.K :
return TMP36.c2k(c)
class MCP3008(object) :
SPI_LOCK = threading.Lock()
def __init__(self, mv_aref) :
self.mv_aref = mv_aref
self.channels = [None] * 8
# set up the SPI interface pins
GPIO.setmode(GPIO.BCM)
GPIO.setup(SPIMOSI, GPIO.OUT)
GPIO.setup(SPIMISO, GPIO.IN)
GPIO.setup(SPICLK, GPIO.OUT)
GPIO.setup(SPICS, GPIO.OUT)
# read SPI data from MCP3008 chip, 8 possible adc's (0 thru 7)
def _readadc(self, adcnum, clockpin=SPICLK, mosipin=SPIMOSI, misopin=SPIMISO, cspin=SPICS):
if ((adcnum > 7) or (adcnum < 0)):
return -1
GPIO.output(cspin, True)
GPIO.output(clockpin, False) # start clock low
GPIO.output(cspin, False) # bring CS low
commandout = adcnum
commandout |= 0x18 # start bit + single-ended bit
commandout <<= 3 # we only need to send 5 bits here
for i in range(5):
if (commandout & 0x80):
GPIO.output(mosipin, True)
else:
GPIO.output(mosipin, False)
commandout <<= 1
GPIO.output(clockpin, True)
GPIO.output(clockpin, False)
adcout = 0
# read in one empty bit, one null bit and 10 ADC bits
for i in range(12):
GPIO.output(clockpin, True)
GPIO.output(clockpin, False)
adcout <<= 1
if (GPIO.input(misopin)):
adcout |= 0x1
GPIO.output(cspin, True)
adcout /= 2 # first bit is 'null' so drop it
return adcout * ( self.mv_aref / 1024.0)
def readadc(self, *args, **kwargs) :
self.SPI_LOCK.acquire(True)
try :
return self._readadc(*args, **kwargs)
finally :
self.SPI_LOCK.release()
def setup_channel(self, channel_number, pinobject) :
pinobject.setup_mcp3008(self, channel_number)
self.channels[channel_number] = pinobject