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/DA | G | 使用 |
---|---|---|
ADC2_1 | 0 | (E-Inkで使用) |
ADC2_2 | 2 | (ブザーで使用) |
ADC2_0 | 4 | (E-Inkで使用) |
ADC2_5 | 12 | (電源制御で使用) |
ADC2_4 | 13 | 裏右pin (RxDで使用) |
ADC2_6 | 14 | 裏左pin (TxDで使用) |
ADC2_3 | 15 | (E-Inkで使用) |
ADC2_8 | 25 | 裏左と上pin |
ADC2_9 | 26 | 裏左と上pin |
ADC2_7 | 27 | (onスイッチで使用) |
ADC1_4 | 32 | GROVE(I2C) |
ADC1_5 | 33 | GROVE(I2C) |
ADC1_6 | 34 | 裏右pin (MISOで使用) |
ADC1_7 | 35 | (MOSからのfeedback?で使用) |
ADC1_0 | 36 | 裏左と上pin |
ADC1_1 | 37 | (ボタン上回しで使用) |
ADC1_2 | 38 | (ボタン押すで使用) |
ADC1_3 | 39 | (ボタン下回しで使用) |
DAC1 | 25 | ADC2で同じpin |
DAC2 | 26 | ADC2と同じpin |
ピンの配置
正面を手前に見て、上面
ch1 | ch2 | ch3 | |||||
i | 3 | B | G25 | G36 | G26 | o | G |
裏面のMI-BUS
G23 | G25 | (ch1) | |
ch8 | G34 | G26 | (ch3) |
G18 | G36 | (ch2) | |
G21 | G22 | ||
ch7 | G13 | G14 | ch6 |
RST | 3V3 | ||
5Vi | 5Vo | GND | BAT |
下面のGROVE
G33 | G32 | 5V | GND |
ch5 | ch4 |
chと線色
線とchのpinは以下の様に決めました。ch | G | 線色 |
---|---|---|
1 | 25 | 青 |
2 | 36 | 赤 |
3 | 26 | 橙 |
4 | 32 | 黄 |
5 | 33 | 緑 |
6 | 14 | 青 |
7 | 13 | 赤 |
8 | 34 | 橙 |
3.3V | 3V3 | 白 |
GND | GND | 黒 |
測定回路
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.30 | 3.27 | +30 | 3.30 |
1 | 2.91 | 2.90 | +10 | 2.93 |
2 | 2.52 | 2.54 | -20 | 2.57 |
3 | 2.17 | 2.17 | 0 | 2.20 |
4 | 1.79 | 1.81 | -20 | 1.83 |
5 | 1.42 | 1.45 | -30 | 1.47 |
6 | 1.09 | 1.08 | +10 | 1.10 |
7 | 0.72 | 0.72 | 0 | 0.73 |
8 | 0.34 | 0.36 | -20 | 0.37 |
- | 0.00 | 0.00 | 0 | 0.00 |
参考
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秒待つ
}