簡體   English   中英

如何以高頻讀取和累積傳感器值,而無需不斷寫入磁盤(RPi 2 b+、MCP3304、Python)

[英]How to read & accumulate sensor values at high frequency, without constantly writing to disk (RPi 2 b+, MCP3304, Python)

我正在嘗試使用Raspberry Pi 2 B+ 型通過MCP3304 (5v VDD)以 ~ 10kHz 的速率連續三次(讀數之間為 0.1 ms,或 10 ksps) 基於外部刺激每秒一次,對這些值求平均值,然后將它們與當前日期時間一起寫入文本文件。 光電二極管只是將數據讀出到放大器,然后放大器饋入 MCP3304,MCP3304 通過 SPI 將數據饋入 RPi。 (本質上:RPi 接收數字輸入,通過 MCP3304 和在線信號放大器觸發來自光電二極管的三個連續樣本。這三個樣本存儲在內存中,取平均值,然后與日期時間戳一起寫入磁盤到現有的 CSV文本文件。)這一切都在 Python 2.7 上。

就目前而言,我使用以下代碼( SensorRead() )獲得 < 1kHz 的采樣。 我對 Python 非常陌生(並且在這方面使用傳感器和 RPis!),並且認為我設置我的課程以獲取三個單獨的連續 ADC 樣本的方式以及可能我的寫入磁盤設置可能會減慢我的速度下來。 但是,我似乎無法找到更好的方法。 編輯 1:我通過 Python 從 RPi GPIO 對最大采樣率進行了大量研究,它似乎遠高於 ADC 對 ~ 1MHz 或 ~ 1000 ksps(例如12 )的限制。 Edit2:也許 100 ksps 的 ADC 最大采樣率實際上是指可以讀取多少位而不是每秒可以獲取多少個完整的 12 位樣本?

是的。 就是這樣。 MCP3304 可以達到 100ksps,但 Python 讀取速率接近 30ksps,當在 MCP3304 每次迭代讀取的 24 位之間拆分時,接近 1ksps



我的兩個問題:
1) 是否有更好的方法來接近 MCP3304 規格表中宣傳的完整 100 ksps? 此鏈接建議每次我想獲取單個樣本時調用 WiringPi 可能會導致一些相當大的延遲。

2) 有沒有可能,對於初學者/中等水平的 Python 技能,我可以在內存中進行所有這些采樣和每秒平均,並且只寫入磁盤,例如,每分鍾一次? 編輯:您能否指出一些相關鏈接/資源的方向?

謝謝!

注 1:代碼是“線程化的”,因為還有一些其他功能同時運行。 注 2:我也在同時讀取 ADC 上的差分通道,因此 MCP3304 命令中的“差分 = 真”

'''
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 得到了一些很好的結果,正如我編寫的這個測試代碼所示,以量化我讀取 ADC 的速度 我還最終編寫了自己的函數來從 MCP3304 中讀取數據——一旦一切都干凈了,我將鏈接到它——我能夠在 Cython 中進一步優化。

關於你的問題的一點。 每秒三個樣本是 3Hz 而非 100kHz 的速率。 在我看來,您想要的是三個相距 10us 的樣本。

1) 使用運行 Linux 的 Pi 在 MCP3304 上的 10us 采樣周期? 很可能不是。 做一些搜索。 例如,參見https://raspberrypi.stackexchange.com/questions/45386/microphone-via-spi ,其中一個答案說他們使用 C 代碼實現了 33us(33ksps)並避免了 SPI 驅動程序。 此外,我懷疑您會發現 Linux 進程切換和其他線程妨礙並影響采樣率,特別是如果它們也在讀取 ADC。 如果您有一個專用的非 Linux 處理器來讀取 ADC,用 C 或匯編語言編程,將三個樣本提供給 Pi,那么這可能更有可能。 如果您使用並行 ADC,即不使用類似 SPI 的串行通信,則更容易。 另見http://www.hertaville.com/interface-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 上是難以實現的,但求平均值和寫入絕對是可能的。

不過,我有一個解決您的問題的方法:如果實際上您對三個樣本所做的只是對它們求平均值,為什么不在輸入引腳之前添加一個老式低通模擬濾波器,然后只取一個樣本. Hey presto,無需硬實時 ADC,無需擔心其他進程或內核中斷!

我們最近針對不同頻率下讀取輸入的准確性對 PIGPIO 和 RPi.GPIO 進行了基准測試。 該測試是在 Raspberry Pi 3b 上進行的。

我建議使用 PIGPIO 以獲得更好的結果。 在我們的測試中,讀取精度高於 99% 的庫的最大讀取頻率為 20 KHz,而 Rpi.GPIO 庫的最大讀取頻率為 5KHz

您可以在此帖子中找到確切的測試設置和完整結果: https : //atman-iot.com/blog/raspberry-pi-benchmark/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM