-
Notifications
You must be signed in to change notification settings - Fork 0
/
MCP3201Photometer.py
138 lines (105 loc) · 4.61 KB
/
MCP3201Photometer.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
#!/usr/bin/python3.4
# -*- coding: utf-8 -*-
from time import sleep
import csv
import spidev
import pigpio
pi = pigpio.pi()
actionSwitch = 17
pi.set_mode(actionSwitch, pigpio.INPUT)
pi.set_pull_up_down(actionSwitch, pigpio.PUD_DOWN)
# uses the "spidev" package ('sudo pip3 install spidev')
# check dtparam=spi=on --> in /boot/config.txt or (set via 'sudo raspi-config')
class MCP3201(object):
"""
Functions for reading the MCP3201 12-bit A/D converter using the SPI bus either in MSB- or LSB-mode
"""
def __init__(self, SPI_BUS, CE_PIN):
"""
initializes the device, takes SPI bus address (which is always 0 on newer Raspberry models)
and sets the channel to either CE0 = 0 (GPIO pin BCM 8) or CE1 = 1 (GPIO pin BCM 7)
"""
if SPI_BUS not in [0, 1]:
raise ValueError('wrong SPI-bus: {0} setting (use 0 or 1)!'.format(SPI_BUS))
if CE_PIN not in [0, 1]:
raise ValueError('wrong CE-setting: {0} setting (use 0 for CE0 or 1 for CE1)!'.format(CE_PIN))
self._spi = spidev.SpiDev()
self._spi.open(SPI_BUS, CE_PIN)
self._spi.max_speed_hz = 976000
pass
def readADC_MSB(self):
"""
Reads 2 bytes (byte_0 and byte_1) and converts the output code from the MSB-mode:
byte_0 holds two ?? bits, the null bit, and the 5 MSB bits (B11-B07),
byte_1 holds the remaning 7 MBS bits (B06-B00) and B01 from the LSB-mode, which has to be removed.
"""
bytes_received = self._spi.xfer2([0x00, 0x00])
MSB_1 = bytes_received[1]
MSB_1 = MSB_1 >> 1 # shift right 1 bit to remove B01 from the LSB mode
MSB_0 = bytes_received[0] & 0b00011111 # mask the 2 unknown bits and the null bit
MSB_0 = MSB_0 << 7 # shift left 7 bits (i.e. the first MSB 5 bits of 12 bits)
return MSB_0 + MSB_1
def readADC_LSB(self):
"""
Reads 4 bytes (byte_0 - byte_3) and converts the output code from LSB format mode:
byte 1 holds B00 (shared by MSB- and LSB-modes) and B01,
byte_2 holds the next 8 LSB bits (B03-B09), and
byte 3, holds the remaining 2 LSB bits (B10-B11).
"""
bytes_received = self._spi.xfer2([0x00, 0x00, 0x00, 0x00])
LSB_0 = bytes_received[1] & 0b00000011 # mask the first 6 bits from the MSB mode
LSB_0 = bin(LSB_0)[2:].zfill(2) # converts to binary, cuts the "0b", include leading 0s
LSB_1 = bytes_received[2]
LSB_1 = bin(LSB_1)[2:].zfill(8) # see above, include leading 0s (8 digits!)
LSB_2 = bytes_received[3]
LSB_2 = bin(LSB_2)[2:].zfill(8)
LSB_2 = LSB_2[0:2] # keep the first two digits
LSB = LSB_0 + LSB_1 + LSB_2 # concatenate the three parts to the 12-digits string
LSB = LSB[::-1] # invert the resulting string
return int(LSB, base=2)
def convert_to_voltage(self, adc_output, VREF=3.3):
"""
Calculates analogue voltage from the digital output code (ranging from 0-4095)
VREF could be adjusted here (standard uses the 3V3 rail from the Rpi)
"""
return adc_output * (VREF / (2 ** 12 - 1))
if __name__ == '__main__':
SPI_bus = 0
CE = 0
MCP3201 = MCP3201(SPI_bus, CE)
#menu
fileName1 = raw_input('Please enter file name?:\n')
pollFrequencyFactor = 0.1
adcRunningTotal = 0
adcRunningVoltage = 0
#the infinite loop where the values are read and written to csv
#while True:
#n = 0#for while loop
with open(('/home/pi/Documents/CSF/'+fileName1+'.csv'), 'a+') as f:
writer = csv.writer(f, delimiter=",", lineterminator="\n")
writer.writerow(['Time/s', 'Value', 'Voltage'])
try:
while True:
n=0
while (pi.read(actionSwitch)==True):
for i in range(1000):
ADC_output_code = MCP3201.readADC_MSB()
adcRunningTotal = adcRunningTotal + ADC_output_code
adcRunningVoltage = adcRunningVoltage + MCP3201.convert_to_voltage(ADC_output_code)
sleep(0.0001)
ADC_output_code = adcRunningTotal/1000
ADC_voltage = adcRunningVoltage/1000
writer.writerow([n, ADC_output_code, ADC_voltage])
n = n + pollFrequencyFactor
adcRunningTotal = 0
adcRunningVoltage = 0
#output = interp(output, [0, 1023], [0, 100])
#print(output)
#sleep(0.05) #values are displayed every 50ms
except (KeyboardInterrupt):
print('\n', "Exit on Ctrl-C: Good bye!")
except:
print("Other error or exception occurred!")
raise
finally:
print()