I am reading an MCP3008 ADC using pigpio, I've abstracted the script below.
I have also found a slightly different construction or parsing of the three SPI command bytes and reconstruction of the ADC values in this Adafruit_MCP3008 script.
In my implementation (based on @joan's comments) I treat the three command bytes as they are shown in the MCP3008 chip documentation literally. First byte is only 0x01
for example. The Adafruit implementation stuffs all instruction bits into the first byte, leaving the 2nd and 3rd bytes as 0x00
.
I think I can understand how that works, it's just a 1 bit frame change, and so the returned ADC value is strung out over all three returned bytes instead of only the last two for my implementation.
Is there likely to be any advantages or disadvantages to either implementation, or are they for all practical purposes identical and interchangeable (except perhaps for a small difference in speed due to python differences)?
For channels 4-7 here are the three bytes for each, the results are the same:
my implementation
['0b1', '0b11000000', '0b0']
['0b1', '0b11010000', '0b0']
['0b1', '0b11100000', '0b0']
['0b1', '0b11110000', '0b0']
[0, 339, 678, 1021]
implementation of Adafruit_MCP3008
['0b11100000', '0b0', '0b0']
['0b11101000', '0b0', '0b0']
['0b11110000', '0b0', '0b0']
['0b11111000', '0b0', '0b0']
[0, 339, 678, 1021]
my implementation
def _digitize_quick(self, channels=None):
if channels == None:
channels = range(8)
values = []
for i_channel in channels:
three_bytes = [1, (8+i_channel)<<4, 0]
print [bin(x) for x in three_bytes]
cnt, rawdata = self.pi.bb_spi_xfer(self.CSbar, three_bytes) # http://abyz.me.uk/rpi/pigpio/python.html
adc_value = ((rawdata[1]<<8) | rawdata[2]) # & 0x3FF left off for debugging
values.append(adc_value)
return values
implementation of Adafruit_MCP3008
def _digitize_alt(self, channels=None):
"""from https://github.com/adafruit/Adafruit_Python_MCP3008/blob/master/Adafruit_MCP3008/MCP3008.py"""
if channels == None:
channels = range(8)
results = []
for i_channel in channels:
command = 0b11 << 6 # Start bit, single channel read
command |= (i_channel & 0x07) << 3 # Channel number (in 3 bits)
# Note the bottom 3 bits of command are 0, this is to account for the
# extra clock to do the conversion, and the low null bit returned at
# the start of the response.
three_bytes = [command, 0x0, 0x0]
print [bin(x) for x in three_bytes]
cnt, resp = self.pi.bb_spi_xfer(self.CSbar, three_bytes)
result = (resp[0] & 0x01) << 9
result |= (resp[1] & 0xFF) << 1
result |= (resp[2] & 0x80) >> 7
results.append(result & 0x3FF)
return results