我正在尝试使用Raspberry Pi 2 Model B+通过MCP3304(5v VDD)以~10kHz的速率连续三次(每次读取之间0.1 ms,或每秒10 ksps的速率)从光电二极管读取有关红外强度的模拟数据(基于外部刺激),取这些值的平均值,然后将它们与当前日期时间一起写入文本文件光电二极管只是将数据读出到放大器,然后放大器将数据馈送到mcp3304,mcp3304通过spi将数据馈送到rpi。(实质上:RPi接收数字输入,通过MCP3304和串联信号放大器从光电二极管触发三个连续采样这三个样本存储在内存中,平均值,然后写入到一个现有的CSV文本文件的DATE时间戳磁盘。)这一切都在Python 2.7。
现在,我得到了一个1,2)时的限制。edit2:也许adc最大采样率100ksps实际上是指每秒可以读取多少位,而不是完整的12位采样数?
是的。就这样。mcp3304可以达到100ksps,但python的读取速率更接近30ksps,在每次迭代的24位mcp3304读取之间进行分割时,这个速率更接近1ksps
我的两个问题是:1)有没有更好的方法来接近MCP3304规格表中公布的100 ksp的完整值?This link建议每次我想采集一个样本时调用wiringpi可能会导致相当大的延迟。

2)对于初级/中等水平的Python技能,我是否有可能在内存中执行所有这些采样和每秒平均值,并且每分钟只向磁盘写入一次编辑:你能告诉我一些相关链接/资源的方向吗?
谢谢!
注1:代码是“线程化的”,因为还有一些其他函数同时运行。
注2:我还同时读取ADC上的差分通道,因此MCP3304命令中的“differential=true”

'''
FILENAME = "~/output_file_location/and/name.txt"
adc_channel_pd = pin of the ADC from which analog signal is taken
stimulus_in_pin = the the pin that receives the alert to begin sampling
stimulus_LED_alert_pin = pin that goes "high" to illuminate an LED every time the stimulus_in_pin is triggered
Vref = the reference voltage for the ADC (3.3v; VDD = 5V)

'''

# import packages
import wiringpi2 as wiringpi
import time
from gpiozero import MCP3304
import threading
import datetime

# Define important objects
Vref = 3.3
adc_channel_pd = 7
stimulus_in_pin = 32
stimulus_LED_alert_pin = 16

# establish GPIO reading structure
wiringpi.wiringPiSetupPhys()

# set appropriate pin inputs and outputs (0 = input, 1 = output)
wiringpi.pinMode(stimulus_in_pin, 0)
wiringpi.pinMode(stimulus_LED_alert_pin, 1)

# create a class to take 3 PD readings, then average them, immediately upon stimulus
class SensorRead(threading.Thread):
    def __init__(self):
        super(SensorRead, self).__init__()
        self.daemon = True
        self.start()
    def run(self):
        for i in itertools.count():
            if (wiringpi.digitalRead(stimulus_in_pin) == True):
                val_ir_1 = MCP3304(adc_channel_pd, True).value * Vref)
                val_ir_2 = MCP3304(adc_channel_pd, True).value * Vref)
                val_ir_3 = MCP3304(adc_channel_pd, True).value * Vref)
                voltage_ir = round(  (float( (sum([val_ir_1,val_ir_2,val_ir_3])) / 3)) , 9)
                dt_ir = '%s' % datetime.datetime.now()
                f = open(FILENAME, "a")
                f.write("IR Sensor," + dt_ir + "," + str(voltage_ir) + "\n")
                f.close()
                # print to terminal so I can verify output in real time
                print "IR Sensor:", dt_ir,",",voltage_ir
                # blink ir light on board for visual verification of stimulus in real time
                wiringpi.digitalWrite(stimulus_LED_alert_pin, 1)
                time.sleep(0.5)
                wiringpi.digitalWrite(stimulus_LED_alert_pin, 0)
                # sleep to avoid noise post LED firings
                time.sleep(0.5)

# run class
SensorRead()

编辑:我用cython得到了一些很好的结果,如this test-code I wrote to quantify how fast I could read my ADC所示。最后,我还编写了自己的函数来读取MCP3304——一旦它完全清除,我将链接到它——我可以在Cython中进一步优化它。

最佳答案

关于你的问题有一点。每秒三个样本的频率是3Hz而不是100kHz对我来说,你想要的是三个相隔10美元的样品。
1)使用运行Linux的PI的MCP3304上的10us采样周期?很可能不是。做些搜索例如,请参见https://raspberrypi.stackexchange.com/questions/45386/microphone-via-spi其中一个答案说,他们使用c代码并避免使用spi驱动程序实现了33us(33ksps)。另外,我怀疑您会发现Linux进程切换和其他线程妨碍并影响采样率,特别是当它们同时读取ADC时。如果您有一个专用的非linux处理器来读取adc(用c语言或汇编语言编程),并将三个样本馈送给pi,那么这可能更为可能。如果使用并行ADC(即不使用类似SPI的串行通信),则更容易。另请参见http://www.hertaville.com/interfacing-an-spi-adc-mcp3008-chip-to-the-raspberry-pi-using-c.htmlhttps://www.raspberrypi.org/forums/viewtopic.php?f=93&t=83069
2)虽然使用MCP3304在10us周期的采样在Pi上很难实现,但平均和写入绝对是可能的。
不过,我有一个解决问题的方法:如果你要对三个样本进行平均化,为什么不在输入端之前添加一个老式的低通模拟滤波器,然后只取一个样本。嘿,普雷斯托,不需要硬实时ADC,不需要担心其他进程,或内核中断!

关于python - 如何在不不断写入磁盘的情况下高频读取和累积传感器值(RPi 2 b +,MCP3304,Python),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38045783/

10-12 14:15
查看更多