15.CoreInk単体でAD8ch


15.CoreInk単体でAD8ch

M5Stack CoreInk (https://docs.m5stack.com/en/core/coreink?id=tutorialampquick-start) の CPUは、ESP32-PICO-D4 (https://www.espressif.com/sites/default/files/documentation/esp32-pico-d4_datasheet_en.pdf) です。
ESP32でADCは18chありますが、CoreInkにpinが出ているのは、G13-14/25-26/32-34/36の8pinです。
AD/DAG使用
ADC2_10(E-Inkで使用)
ADC2_22(ブザーで使用)
ADC2_04(E-Inkで使用)
ADC2_512(電源制御で使用)
ADC2_413裏右pin (RxDで使用)
ADC2_614裏左pin (TxDで使用)
ADC2_315(E-Inkで使用)
ADC2_825裏左と上pin
ADC2_926裏左と上pin
ADC2_727(onスイッチで使用)
ADC1_432GROVE(I2C)
ADC1_533GROVE(I2C)
ADC1_634裏右pin (MISOで使用)
ADC1_735(MOSからのfeedback?で使用)
ADC1_036裏左と上pin
ADC1_137(ボタン上回しで使用)
ADC1_238(ボタン押すで使用)
ADC1_339(ボタン下回しで使用)
DAC125ADC2で同じpin
DAC226ADC2と同じpin

ピンの配置

正面を手前に見て、

上面

ch1ch2ch3
i3BG25G36G26oG
* ここで、i=5Vin, o=5Vout, 3=3V3, B=BATとします。

裏面のMI-BUS

G23G25(ch1)
ch8G34G26(ch3)
G18G36(ch2)
G21G22
ch7G13G14ch6
RST3V3
5Vi5Vo
GNDBAT
上面の3pinとMI-BUSの3pinは同一ピンが出ています。

下面のGROVE

G33G325VGND
ch5ch4

chと線色

線とchのpinは以下の様に決めました。
chG線色
125
236
326
432
533
614
713
834
3.3V3V3
GNDGND
手持ちの線色が少ないのでダブっています。

測定回路

10kΩ±1%の抵抗9本と0.1uF±10%のコンデンサ8個が必要です。

V-ADC特性の測定

必要な物
・10kΩの可変抵抗 (I=3.3/10k=0.33mA消費)
・テスター M-6000M (METEX)
6Vレンジで誤差±0.7%+2dgts=±(6*0.7/100+0.001*2)=±44mV
3.3VとGND間に10kΩの可変抵抗を接続し、可変端子をG25で測定しました。可変端子とGND間には0.1uFを接続しています。テスターでは4桁の電圧表示は安定していますが、CoreInkのADC値はふらふらしています。
測定データからエクセルのグラフを作りました。測定範囲が0.14V~3.12Vとわかります。左側の直線部分と右側の曲線部分の2つに分けて、エクセルの機能で近似曲線式を出しました。

AD値と電圧値の値が極端に違い、そのままでは式内の定数の有効桁数が1桁しか得られなかったので、できた式の有効桁数を見ながらAD値を1桁ずつ下げていきました。最終的には、
  • ADC=AD/10000とし、
  • V=0V (AD=0 or 1の場合)
  • V=3.3V (AD=4094 or 4095の場合)
  • V=8.4019*ADC+0.1428 (AD=0~2639の場合)
  • V=-13.602xADC^2+14.252xADC-0.4457 (AD=2640~4095の場合)

測定結果

ch測定
(V)
テスター
(V)

(mV)
計算
(V)
3.303.27+303.30
12.912.90+102.93
22.522.54-202.57
32.172.1702.20
41.791.81-201.83
51.421.45-301.47
61.091.08+101.10
70.720.7200.73
80.340.36-200.37
0.000.0000.00
テスター電圧でAD値を校正すれば、今回の測定では±30mVの精度に入っています。しかし、AD値はふらふらしているので、もっと精度をあげるには、平均値を算出する必要があります。

参考

SPI

Serial Peripheral Interface (シリアル・ペリフェラル・インタフェース)
・SCK (Serial Clock) クロックout
・MISO (Master In Slave Out) 信号out
・MOSI (Master Out Slave In) 信号in
・SS (Slave Select) in
* 同じ基板内など、近距離で直結したデバイスに使用

I2C

アイ・アイ・シー
・SDA (シリアルデータ)
・SCL (シリアルクロック)
* 2線とも、プルアップ抵抗を通じて電源電圧に接続
* 同じ基板内など、近距離で直結したデバイスに使用

UART

Universal Asynchronous Receiver Transmitter
・RxD (Recieve Data) 受信データ
・TxD (SD, Transmit Data, Send Data) 送信データ
・GND
* マイコン間通信に使用
* 非同期シリアル通信

ADCについて

ESP32PICOD4 Datasheet

ADCの表記無し。

ESP32 Series Datasheet

p23の 4.1.2 アナログ-デジタルコンバーター
ESP32は12ビットSARADCを統合し、18チャネル(アナログ対応ピン)での測定をサポートします。 ULPコプロセッサーESP32では、スリープモードで動作しているときに電圧を測定するようにも設計されているため、低消費電力。CPUは、しきい値設定および他のトリガーを介してウェイクアップできます。適切な設定により、ADCは最大18ピンの電圧を測定するように構成できます。表7に、ADCの特性を示します。

表7:ADCの特性

DNL(微分非直線性):–7~7LSB (RTCコントローラー;外部100nF(104)コンデンサに接続されたADCにて)

INL(積分非直線性):–12~12LSB (DC信号入力;周囲温度25℃;Wi-Fi&BTオフにて)

サンプリングレート
RTCコントローラーは、200ksps以下
DIGコントローラーは、2Msps以下

ノート:
•atten=3で、測定結果が3000を超える場合(約2450mVの電圧)、ADCの精度は上記の表に記載されているよりも悪化します。
•より良いDNL結果を得るために、ユーザーはフィルターを使用して複数のサンプリングテストを行うか、平均値を計算できます。

デフォルトでは、チップ間で測定結果に±6%の違いがあります。SP-IDFはADC1のメソッドのいくつかのキャリブレーションを提供します。eFuse Vref値(ADC基準電圧)を使用したキャリブレーション後の結果を表8に示します。精度を高めるために、ユーザーは、ESP-IDFで提供されている他のキャリブレーション方法を適用するか、独自の方法を実装できます。

表8:ADCキャリブレーション結果

トータルエラー
-60~60mV (Atten=3, 150~2450mVの測定範囲)
-40~40mV (Atten=2, 150〜1750mVの測定範囲)
-30~30mV (Atten=1, 100~1250mVの測定範囲)
-23~23mV (Atten=0, 100〜950mVの測定範囲)

ESP-IDF Programming Guide

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html#adc-calibration
一部を翻訳すると
概要
ESP32は、2つの12ビットSAR(逐次比較レジスタ)ADCを統合し、合計18の測定チャネル(アナログ対応ピン)をサポートします。これらのチャネルがサポートされています。

ADC1:GPIO32-39の8チャンネル
ADC2:GPIO0,2,4,12-15,25-27の10チャネル

ノイズの最小化
ESP32 ADCはノイズに敏感である可能性があり、ADCの読み取り値に大きな不一致が生じます。ノイズを最小限に抑えるために、ユーザーは使用中のADC入力パッドに0.1µFのコンデンサを接続する場合があります。マルチサンプリングを使用して、ノイズの影響をさらに軽減することもできます。

ADCキャリブレーション
esp_adc_cal/include/esp_adc_cal.h APIは、チップ間のADC基準電圧(VREF)の変動による測定された電圧の差を補正する機能を提供します。設計によると、ADCリファレンス電圧は1100mVですが、実際のリファレンス電圧は、さまざまなESP32間で1000mVから1200mVの範囲になります。

ADC基準電圧の比較
ADC電圧曲線に対する異なる基準電圧の影響を示すグラフ
(Vin=約0.1VでADC=0であり、基準電圧によりVin=1.8~2.0V以上はADC=約4100で一定になっている)

このAPIを使用してADCの読み取り値を修正するには、特定の減衰でADCの1つを特性評価して、ADC基準電圧の差を考慮した特性曲線(ADC-電圧曲線)を取得する必要があります。特性曲線はの形式であり、ADCの読み取り値をmV単位の電圧に変換するために使用されます。特性曲線の計算は、eFuseに保存するか、ユーザーが提供できるキャリブレーション値に基づいています。y = coeff_a * x + coeff_b

スケッチ


// CoreInk アナログ8ch入力
#include <M5CoreInk.h>                 // M5Stack CoreInk使用
Ink_Sprite InkPageSprite(&M5.M5Ink);   // 定義
int pin[8] = {25, 36, 26, 32, 33, 14, 13, 34}; //ch1~8のpin番号
int AD[8] = {0, 0, 0, 0, 0, 0, 0, 0};  // AD読取初期値
float V[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // 電圧算出初期値(V)
int ADmax = 4095;                      // ADの最大値 12bit 2^12-1
float ADC;                             // =float(AD[i])/10000
float Vmax = 3.3;     // CPU電圧 電圧最大値 3300mV/4095=0.8mVきざみ
int i;                                 // chのループ用
int dy = 15, upy;                      // 行刻み,上の行
char strBuff[64];                      // 表示用64文字の配列

void inkSet() {                       // お決まり
  M5.begin();               // E-Ink,RTC,I2C,ブザーを初期化
  if (!M5.M5Ink.isInit()) {           // 初期化出来なければ
    Serial.println("エラー Ink Init"); // シリアルモニタに表示
    while (1) delay(100);             // ずっと待つ
  }
  M5.M5Ink.clear();                   // 画像クリア
  delay(1000);                        // 1秒待つ
  InkPageSprite.creatSprite(0, 0, 200, 200, false);
  // 画像領域を作成し、画面ドライバーから画像データバフを取得しない
}

void setup() {
  inkSet();                   // CoreInkの設定
  for (i = 0; i < 8; i++) {   // ch1-8
    pinMode(pin[i], ANALOG);  // アナログpinとする
  }
}
void loop() {
  Serial.println("");            // シリアルモニタ改行
  upy = 10;                      // 1行目のy
  for (i = 0; i < 8; i++) {      // ch1~8
    AD[i] = analogRead(pin[i]);  // アナログ入力
    ADC = float(AD[i]) / 10000;  // 有効桁を増やすため
    if (AD[i] < 2) {             // ADC=0,1の場合
      V[i] = 0.0;                // 0Vとする
    } else if (AD[i] > 4093) {   // ADC=4094,4095の場合
      V[i] = 3.3;                // 3.3Vとする
    } else if (AD[i] <= 2639) {  // ADC=2-2639の場合
      V[i] = ADC * 8.4019 + 0.1428;  // 直線
    } else {                     // ADC=2640-4093の場合
      V[i] = ADC * ADC * (-13.602) + ADC * 14.252 - 0.4457;//曲線
    }
    Serial.printf("%1d:%4.2f(%04d ", i + 1, V[i], AD[i]); //電圧,AD表示
    sprintf(strBuff, "V%1d= %5.3fV (ADC= %04d)", i + 1, V[i], AD[i]);//文字列を作る
    InkPageSprite.drawString(10, upy, strBuff);  // (x,y)に文字列を描く
    upy = upy + dy;                              // 次の行のy
  }
  InkPageSprite.pushSprite();  // 画面更新
  delay(15000);                // 15秒待つ
}