0

I am trying to push the MCP3008 to its limits and sample as many samples as possible from a single channel per second. I am also not trying to have to write any C or assembly code, and keep it all as much as possible in python.

My approach so far has been rather naive, I imported python libraries which instantiate SPI and MCP3008 classes, so my python can read from the MCP3008. All I did was call the function set_clock_hz to the max when I instantiated the class. The idea was that I can max out the clock on the MCP and sample as high a frequency as possible

Below is my code.

# Simple example of reading the MCP3008 analog input channels and printing
# them all out.
import time
# Import SPI library (for hardware SPI) and MCP3008 library.
import Adafruit_GPIO.SPI as SPI
import Adafruit_MCP3008
import csv
# Software SPI configuration:
#CLK  = 18
#MISO = 23
#MOSI = 24
#CS   = 25
#mcp = Adafruit_MCP3008.MCP3008(clk=CLK, cs=CS, miso=MISO, mosi=MOSI)

# Hardware SPI configuration:
SPI_PORT   = 0
SPI_DEVICE = 0
mcp = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE, 50000)) #50000 max speed in hz


print('Reading MCP3008 values, press Ctrl-C to quit...')
# Print nice channel column headers.

# Main program loop.

#Run for one second
t_end = time.time() + 1
arr = []

while time.time() < t_end:  
# The read_adc function will get the value of the specified channel (0-7).
    value = mcp.read_adc(7)
    arr.append(value)

#Write results
with open('highFreqMeas.csv', "w") as output:
    writer = csv.writer(output, delimiter=",", lineterminator='\n')
    for i in arr:
        writer.writerow([i])

#Read results to see how many samples in second
with open('highFreqMeas.csv', "r") as infile:
    reader = csv.reader(infile, delimiter=",", lineterminator='\n')
    reader = list(reader)
    print len(reader)

1 Answers1

1

It's not clear if you are bit banging SPI or not (i.e. using software SPI). If you are then stop doing that and use hardware SPI via the Python spidev module.

You have the constant 50000 in your code. That is no where near the maximum SPI bit rate for the MCP3008. The datasheet suggests it can always support at least 1.35 MHz for SPI, i.e. 1350000 bits per second.

joan
  • 71,024
  • 5
  • 73
  • 106
  • I am using hardware SPI. Okay, so if I set the max to 1,350,000 bps, and only record from one channel, and each channel is 10 bit, I can record 135,000 samples per second? – Tuomas Talvitie Oct 20 '19 at 10:32
  • 1
    Why not try and see? However there are lots of overheads and I think the Linux SPI driver maxes out at about 25k transactions per second. I would guess a maximum of circa 15k per second from Python. – joan Oct 20 '19 at 10:59
  • good idea! So I assume that a single bit is transferred by a single Hz ? Is this the right way of thinking about it? – Tuomas Talvitie Oct 21 '19 at 07:47
  • 1
    A bit is transferred per clock, and there will be Hz clocks per second. Note that normally 3 bytes are used to transfer a reading from the MCP3008, therefore 24 bits per reading. – joan Oct 21 '19 at 08:12
  • Ah I like the analogy there! I am following up until the part about 'readings.' Does 1 reading = 21 bits? Sorry if I am not following. – Tuomas Talvitie Oct 21 '19 at 11:47
  • 24 bits are normally transferred to get the reading from the MCP3008. The 10 bit ADC reading forms part of that 24 bits. You need to look at the datasheet for the MCP3008. – joan Oct 21 '19 at 12:15
  • hey @joan just a follow up, I actually got over 25k samples per second finally! With python and using hardware SPI! – Tuomas Talvitie Dec 12 '19 at 20:21
  • @TuomasTalvitie That's very good, and more than I would have expected from Python. Which model Pi? – joan Dec 13 '19 at 00:14
  • its a model 3, which (From reading other sources) has a max linus SPI transfer rate of around 70k per second. Someone claimed to get up to 200k. But I do not have an official source on these numbers yet. – Tuomas Talvitie Dec 13 '19 at 19:42
  • Could you post the code that gave you 25 ksps in the end? – Martin R Mar 31 '20 at 18:48