2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ESP32のSPI接続でMCP3208から高速AD変換を試してみました。

Last updated at Posted at 2020-05-07

#ESP32のSPI接続でMCP3208からAD変換実験

##初めてQiitaへ投稿
初めて投稿させて頂きます。既出極まりない内容ですが、自分用のメモとしての初投稿です。ご容赦願います。

##ESP32のSPI設定
HSPIを使用し、端子設定はごく一般的なSPI設定です。

  • CLK 32
  • MISO 33
  • MOSI 25
  • SS 26 (chip select) Low Active

SPIクロック:4MHzで設定
SPIモード:Mode0 : POL=0,PHA=0  (0,0)モード・・・データを立ち上がりエッジでサンプリング、立下りでシフトするモード

AD終了後、即時次のADを呼んだ時にどのくらいのレートでESP32から読めるのかを確認してみました。また、その時の波形も併せて載せておきます。

sample.ino
#include <SPI.h>

#define SPI1_CLK  32
#define SPI1_MISO 33
#define SPI1_MOSI 25
#define SPI1_SS   26

#define SPI_CLK 4000000

SPIClass SPI1(HSPI);
SPISettings spiSettings = SPISettings(SPI_CLK, SPI_MSBFIRST, SPI_MODE0);//0,0

void setup() {
  Serial.begin(115200);
  SPI1.begin(SPI1_CLK, SPI1_MISO, SPI1_MOSI, SPI1_SS);
  pinMode(SPI1_SS, OUTPUT);
  pinMode(SPI1_CLK, OUTPUT);
  pinMode(SPI1_MISO, INPUT);
  pinMode(SPI1_MOSI, OUTPUT);
  digitalWrite(SPI1_SS, HIGH) ;
  SPI1.beginTransaction(spiSettings);
}

void loop() {
  byte channel = 0;
  Serial.println(adc_read(0));
  //delay(1);
}

int adc_read(uint8_t channel) {
  digitalWrite(SPI1_SS, LOW);
  SPI1.transfer(0x06 | channel>>2);//bit7-3:dummy, bit2:start, bit1:single,bit0:D2
  uint8_t dh = SPI1.transfer((channel & 0x03) << 6);//D1,D0,X,Null,B11-B8
  uint8_t dl = SPI1.transfer(0x00);//B7-B0
  digitalWrite(SPI1_SS, HIGH);
  return ((dh & 0xF) << 8 | dl); //get 12bits data
}

##MCP3208へのアナログ入力
アナログ入力としては、可変抵抗で 0Vから3.3Vまで振った場合、デジタル出力は12ビットなので、0~4095になります。ただし、0V近辺および3.3V近辺では既にクリッピングされた感じでした。正確には測定していません。

##波形1 クロックとMISOの波形
MCP3208のデータシートでは、5bitでチャンネル指定、1bitのダミーと1bitのNullのあと、12bitのAD出力データがMSB firstで通信される事になるため、全部で19bitのクロックが必要になります。(下記仕様の波形から、SPIモードは 0,0と確認)
図1.png

ただ、ESP32の標準SPIライブラリでは、バイト単位での送受信に限られるため、頭に5bitのダミーのデータ(0)を入れて、全部で24bit(3バイト)にして通信することになります。19bitで送信する方法は調査不足かもしれません。

(ちなみに、ESP8266では、通常のSPIライブラリでは無いライブラリを用いて、19bitで通信することは出来ました。そのライブラリをESP32で試しては居ません。https://github.com/MetalPhreak/ESP8266_SPI_Driver 中のspi_transaction()関数を利用)

6bit目にStartビットとして'H'を送るまでのクロックは無視されるので、通信的には問題なしです。
MOSIの1バイト目で、Start bitと、Single指定と、Channel番号のD2を指定しています。Channel番号の下位ビットは2バイト目のbit7,bit6で送っています。データ送信と受信はSPIの場合は同時です。。

下記が3バイト(24bit)のCLKと、MISO信号です。2バイト目のbit3-0と3バイト目のb7-0がAD変換結果の12bitデータとなります。
esp32-mcp3208-clk-miso.png

##波形2 Delay無しで回した時の サンプリング周期の確認
AD終了後、すぐ次のループに入る処理を行った場合、サンプリング間の周期は、約520usec(サンプリング周期は 1.9kHz)になりました。Delay無しで繰り返しているにも関わらず、以前ESP8266で取った時の272us(Serial.printlnあり)より遅い理由は分かりません。クロック速度はESP8266の時も 4MHzでしたのでクロックの差は無し。Dummyのクロック5発分は、ESP8266の時には不要だったので、今回の方が少し不利ですが、それ以上の差がある。ライブラリの違いかもしれません。
2a.png
ちなみに、Serial.printlnを止めれば、短縮されますが、波形を取り忘れました(汗)

##Arduino IDEのシリアルプロッタでのAD出力確認
少しDelayを入れて(波形を取りやすくするために10msを入れました)、 Analog入力を0V~3.3Vの可変VRを動かして、AD結果を波形にしたものがこれです。電圧が0手前、3.3V手前の時に、AD結果として既にクリップされていますが、正確な電圧範囲は測定していません。
3.png

とりあえず、Qiita初投稿はここまでです。
次はこの値を Bluetoothで送り、別のESP32で受信した値でサーボモーターを回す予定です。

2
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?