« Raspberry Pi 4でscipyをimport | トップページ | デジタルフィルターの実験 »

2021年3月 5日 (金)

ADCのサンプリングレート

アナログ出力に対してADCをかけて波形サンプリングをしたい。サンプリングレートはどの程度になるのか以下の2パターンを実験してみた。

  • PicoのADCを使ってサンプリングして、PicoからUARTでRaspberry Piにデータを取り込む
  • ADC IC MCP3208を使ってSPIでRaspberry Piにデータを取り込む

結果

PicoのADCをUARTでサンプリングした場合の最小周期は1300us(800Hz)程度
MCP3208をSPIでサンプリングした場合の最小周期は50us(20KHz)程度

結論

ナイキスト周波数を100Hzとすればいずれの方法でもサンプリングは可能。

 

PicoのADCをUARTにて

PicoのUART0(1ピン、2ピン)をPiのUART(8ピン、10ピン)に接続した。

以下のMicroPythonをPicoで実行。

import machine
import utime

uart = machine.UART(1,115200)
sensor_temp = machine.ADC(4)
conversion_factor = 3.3 / 65535

count = 0
ptime = utime.ticks_ms()
while True:
reading = sensor_temp.read_u16() * conversion_factor

temperature = 27 - (reading - 0.706) / 0.001721
ctime = utime.ticks_us()
count += 1
output = "{}/{}\n".format(count, (ctime - ptime))
if (count % 1000) == 0:
   print(output)
uart.write(output)
ptime = ctime

 

以下のPythonコードをRaspberry Pi 4Bにて実行した。

import time
import serial


s = serial.Serial("/dev/serial0",115200, timeout=3)
s.reset_input_buffer()
count = 0

try:
   while True:

      line =s.readline()
      line = line.decode('utf-8')
      count += 1
      if (count % 1000) == 0:
         print("{}".format(line))


except KeyboardInterrupt:
   pass

結果は以下。1000回に1回、カウント数とループ一回当たりの時間をコンソール出力している。

Adc0

 

MCP3208をSPIにて

MCP3208をRaspberry Pi 4BのSPIに接続している。PythonコードはBlue Backs Raspberry Piで学ぶ電子回路に掲載されているものを使っている。


import RPi.GPIO as GPIO
import time

# MCP3208からSPI通信で12ビットのデジタル値を取得。0から7の8チャンネル使用可
def readadc(adcnum, clockpin, mosipin, misopin, cspin):
   if adcnum > 7 or adcnum < 0:
      return -1
   GPIO.output(cspin, GPIO.HIGH)
   GPIO.output(clockpin, GPIO.LOW)
   GPIO.output(cspin, GPIO.LOW)

   commandout = adcnum
   commandout |= 0x18 # スタートビット+シングルエンドビット
   commandout <<= 3 # LSBから8ビット目を送信するようにする   

   for i in range(5):
# LSBから数えて8ビット目から4ビット目までを送信
      if commandout & 0x80:
         GPIO.output(mosipin, GPIO.HIGH)
      else:
         GPIO.output(mosipin, GPIO.LOW)
      commandout <<= 1
      GPIO.output(clockpin, GPIO.HIGH)
      GPIO.output(clockpin, GPIO.LOW)
   adcout = 0
# 13ビット読む(ヌルビット+12ビットデータ)
   for i in range(13):
      GPIO.output(clockpin, GPIO.HIGH)
      GPIO.output(clockpin, GPIO.LOW)
      adcout <<= 1
      if i>0 and GPIO.input(misopin)==GPIO.HIGH:
         adcout |= 0x1
   GPIO.output(cspin, GPIO.HIGH)
   return adcout

GPIO.setmode(GPIO.BCM)
# ピンの名前を変数として定義
SPICLK = 11
SPIMOSI = 10
SPIMISO = 9
SPICS = 8
# SPI通信用の入出力を定義
GPIO.setup(SPICLK, GPIO.OUT)
GPIO.setup(SPIMOSI, GPIO.OUT)
GPIO.setup(SPIMISO, GPIO.IN)
GPIO.setup(SPICS, GPIO.OUT)

ptime = time.time()
count = 0
try:
   while True:
      inputVal0 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS)
      ctime=time.time()
      if (count % 1000) == 0:
         print("{}/{}".format(inputVal0, ctime-ptime))
      ptime=ctime
      count += 1

except KeyboardInterrupt:
   pass

GPIO.cleanup()

結果は以下の通り。1000回に1回、ADC値とループ時間をコンソール出力している。5掛ける10のマイナス5乗で50us。

Adc1

以上。

« Raspberry Pi 4でscipyをimport | トップページ | デジタルフィルターの実験 »

ラズパイ日記」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

« Raspberry Pi 4でscipyをimport | トップページ | デジタルフィルターの実験 »