试图通过SPI(MCP3304,MCP3204或MCP3008)在RPi 2 b +上读取带有Cython的ADC?

问题描述:

我想读取连接到RPi 2 b+MCP3304(5V VDD,3.3V Vref,主通道= 7,差分通道= 6)的差分电压值,尽可能接近MCP3304的最大采样率100ksps。优选地,每100μs(> 10ksps)我会得到> 1个样本。试图通过SPI(MCP3304,MCP3204或MCP3008)在RPi 2 b +上读取带有Cython的ADC?

一种用户recently suggested I try porting my code to C for some speed gains。我对C非常陌生,所以我认为我会给Cython一枪,但似乎无法弄清楚如何利用基于C的速度增益。

我的猜测是,我需要写一个.pyx文件,其中包括通过SPI访问ADC的比特/字节比我目前使用 Python包的更原始的手段(蟒包裹gpiozero包)。 1)这看起来是否正确,如果是的话,可能会有人2)请帮助我理解如何以适当的方式处理MCP3304的位/字节,从而产生从Cython获得的速度增益?我已经看过MCP3008的C教程,但无法适应此代码以适应MCP3304规格表中列出的时序;尽管我可能可以修改Cython特定的MCP3008(或其他ADC)教程以适应MCP3304。

这是我写的一个小小的.pyx循环,用于测试我读取电压值的速度。 (定时读取25,000个样本需要多长时间)。它比在Python中直接运行速度快9%。

# Load packages 
import time 
from gpiozero import MCP3304 


# create a class to ping PD every ms for 1 minute 
def pd_ping(): 
    cdef char *FILENAME = "testfile.txt" 
    cdef double v 
    # cdef int adc_channel_pd = 7 
    cdef size_t i 

    # send message to user re: expected timing 
    print "Runing for ", 25000 , "iterations. Fingers crossed!" 

    print time.clock() 

    s = [] 
    for i in range(25000): 
     v = MCP3304(channel = 7, diff = True).value * 3.3 
     # concatenate 
     s.append(str(v)) 

    print "donezo" , time.clock() 

    # write to file 
    out = '\n'.join(s) 
    f = open(FILENAME, "w") 
    f.write(out) 

大概没有必要为每个迭代的MCP3304对象。从浮点到字符串的转换可能会延迟。

s = [] 
mcp = MCP3304(channel = 7, diff = True) 
for i in range(25000): 
    v = mcp.value * 3.3 
    s.append(v) 

out = '\n'.join('{:.2f}'.format(v) for v in s) + '\n' 

如果乘以3.3并非绝对必要在这一点上,它可以稍后再进行。

+0

不可思议!这个改进的性能稍微超过了10倍(从大约33秒到2秒),谢谢! – drewbles

+0

注意:如果对于后代很重要,我也将乘法除去3.3,并将{:.2f}增加到{:.17f}以获得尽可能多的信息。谢谢! – drewbles

+0

后续,任何想法如何我可以声明(通过“cdef”)列表“s”?我想知道如果这可能会获得我更多的速度改善 – drewbles