とりあえず1PIN単位で動くものだけ調べてみました。
※(2019/08/30)ごめんなさい、嘘書いてありました。アナログのpinMode()設定が違っていたので入力値がおかしかったみたいです。
最新情報はM5StickC非公式日本語リファレンスを確認おねがいします。
PIN配置

GROVEのVOUTは5Vでした。しなしながらIO32とIO33のアナログ入力は3.3Vまでなので、アナログのGROVEセンサーとかをつなげると物によってはちゃんと動かない気がします。
PIN設定
| PIN | IO | Map | Function |
| IO26 | I/O | Extended IO port | GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1 |
| IO36(SENSOR_VP) | I | Extended IO port | GPIO36, ADC1_CH0, RTC_GPIO0 |
| IO0 | I/O | Microphone
SCL Extended IO port | ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1, EMAC_TX_CLK |
| IO32 | I/O | GROVE SDA | 32K_XP (32.768 kHz crystal oscillator input), ADC1_CH4, TOUCH9, RTC_GPIO9 |
| IO33 | I/O | GROVE SCL | 32K_XN (32.768 kHz crystal oscillator output), ADC1_CH5, TOUCH8, RTC_GPIO8 |
外部からアクセスができる上記5PINが調査対象です。
調査結果
| PIN | digitalRead() | analogRead() | touchRead() | dacWrite() | digitalWrite() | ledcWrite() |
| IO26 | ○ | ○ | NG | ○ | ○ | ○ |
| IO36 | ○ | ○ | NG | NG | NG | NG |
| IO0 | ○ | NG | NG | NG | ○ | ○ |
| IO32 | ○ | ○ | 33 | NG | ○ | ○ |
| IO33 | ○ | ○ | 32 | NG | ○ | ○ |
IO26はADC2_CH9に繋がっているのに、Wi-fi使っていない場合でもアナログ入力できませんでした。上側にあるポートからはアナログ入力できなそうですね。
タッチセンサーがまた微妙で、ESP32のデータシートがおそらく間違っていて、内部的に逆に接続されている気がします。
調査方法
digitalRead() デジタル入力 0(1.65V未満) or 1(1.65V以上)
#include <M5StickC.h>
int PIN = 32;
void setup() {
M5.begin();
pinMode( PIN, INPUT);
}
void loop() {
Serial.printf("%04d\n", digitalRead(PIN) );
delay(500);
}
上記コードのPIN変数を変えていって実験しました。digitalRead()はどのポートでも利用できます。
analogRead() アナログ入力 0(0V)-4095(3.3V)
#include <M5StickC.h>
int PIN = 32;
void setup() {
M5.begin();
pinMode(PIN, ANALOG);
}
void loop() {
Serial.printf("%04d\n", analogRead(PIN) );
delay(500);
}
アナログ入力はIO0が正しく取得できません。内部的にプルアップされている関係で、0と4095のどちらかの数値になります。
touchRead() 静電容量取得 0に近いほうがタッチ
#include <M5StickC.h>
int PIN = 32;
boolean touched = false;
int threshold = 16;
void gotTouch() {
touched = true;
}
void setup() {
M5.begin();
pinMode( PIN, INPUT);
touchAttachInterrupt(PIN, gotTouch, threshold);
}
void loop() {
if (touched) {
Serial.println("touch!");
touched = false;
}
Serial.printf("%4d\n", touchRead(PIN) );
delay(500);
}
touchRead()は触ると数値が小さくなるので、触らないときの数字と、触って下がったときの数字の中間か、やや低い値をthresholdに設定してください。
タッチは初めて実験してみましたが、混乱しました。IO32とIO33の結果が逆でした。
コードを見ても、データシートも見ても問題ないはずだったので、他のESP32 Devボードで実験してみたら、やっぱり逆です。
たぶんデータシートが間違っていますね。
typedef struct {
uint8_t reg; /*!< GPIO register offset from DR_REG_IO_MUX_BASE */
int8_t rtc; /*!< RTC GPIO number (-1 if not RTC GPIO pin) */
int8_t adc; /*!< ADC Channel number (-1 if not ADC pin) */
int8_t touch; /*!< Touch Channel number (-1 if not Touch pin) */
} esp32_gpioMux_t;
こんな構造体があって、ArduinoではGPIOを管理していました。
| PIN | reg | rtc | adc | touch |
| 0 | 0x44 | 11 | 11 | 1 |
| 1 | 0x88 | -1 | -1 | -1 |
| 2 | 0x40 | 12 | 12 | 2 |
| 3 | 0x84 | -1 | -1 | -1 |
| 4 | 0x48 | 10 | 10 | 0 |
| 5 | 0x6c | -1 | -1 | -1 |
| 6 | 0x60 | -1 | -1 | -1 |
| 7 | 0x64 | -1 | -1 | -1 |
| 8 | 0x68 | -1 | -1 | -1 |
| 9 | 0x54 | -1 | -1 | -1 |
| 10 | 0x58 | -1 | -1 | -1 |
| 11 | 0x5c | -1 | -1 | -1 |
| 12 | 0x34 | 15 | 15 | 5 |
| 13 | 0x38 | 14 | 14 | 4 |
| 14 | 0x30 | 16 | 16 | 6 |
| 15 | 0x3c | 13 | 13 | 3 |
| 16 | 0x4c | -1 | -1 | -1 |
| 17 | 0x50 | -1 | -1 | -1 |
| 18 | 0x70 | -1 | -1 | -1 |
| 19 | 0x74 | -1 | -1 | -1 |
| 20 | 0x78 | -1 | -1 | -1 |
| 21 | 0x7c | -1 | -1 | -1 |
| 22 | 0x80 | -1 | -1 | -1 |
| 23 | 0x8c | -1 | -1 | -1 |
| 24 | 0 | -1 | -1 | -1 |
| 25 | 0x24 | 6 | 18 | -1 |
| 26 | 0x28 | 7 | 19 | -1 |
| 27 | 0x2c | 17 | 17 | 7 |
| 28 | 0 | -1 | -1 | -1 |
| 29 | 0 | -1 | -1 | -1 |
| 30 | 0 | -1 | -1 | -1 |
| 31 | 0 | -1 | -1 | -1 |
| 32 | 0x1c | 9 | 4 | 9 |
| 33 | 0x20 | 8 | 5 | 8 |
| 34 | 0x14 | 4 | 6 | -1 |
| 35 | 0x18 | 5 | 7 | -1 |
| 36 | 0x04 | 0 | 0 | -1 |
| 37 | 0x08 | 1 | 1 | -1 |
| 38 | 0x0c | 2 | 2 | -1 |
| 39 | 0x10 | 3 | 3 | -1 |
こんな感じのマトリクスで、内部レジスタのアドレスとか番号が並んでいます。
| PIN | reg | rtc | adc | touch |
| 32 | 0x1c | 9 | 4 | 9 |
| 33 | 0x20 | 8 | 5 | 8 |
該当部分だけ抜きですと、RTCとTouchとかはPIN番号大きい方から割り当てていますが、ADCは逆です。Touchもデータシート上は上記の記述ですが、実際の実装はIO32がT8でIO33がT9になっていると思われます。
ここ以外のいろんな場所でも逆に定義されているので、ライブラリは修正されない気もします。
一応商品としてはありますので、使うときにはIO32を取得してください。
dacWrite() アナログ出力 0(0V)-255(3.3V)
#include <M5StickC.h>
int PIN = 26;
void setup() {
M5.begin();
pinMode(PIN, OUTPUT);
}
void loop() {
dacWrite(PIN, 0);
delay(500);
dacWrite(PIN, 128);
delay(500);
dacWrite(PIN, 255);
delay(500);
}
dacWrite()はIO26でしか使えません。(内部的にはIO25でも可能)

IO26からの出力にLEDと抵抗に接続してものをオシロスコープで測定した結果です。若干電圧低下していますが、概ね255で3.3V程度、128でその半分の電圧が出力されています。
digitalWrite() デジタル出力 LOW(0V) or HIGH(3.3V)
#include <M5StickC.h>
int PIN = 32;
void setup() {
M5.begin();
pinMode(PIN, OUTPUT);
}
void loop() {
digitalWrite(PIN, HIGH);
delay(500);
digitalWrite(PIN, LOW);
delay(500);
}
IO36はIOがInputのみなので、出力には使えませんが、それ以外のPINでは使えました。
ledcWrite() PWM出力
#include <M5StickC.h>
int PIN = 32;
int PWMCH = 0;
void setup() {
M5.begin();
pinMode(PIN, OUTPUT);
ledcSetup(PWMCH, 12000, 8);
ledcAttachPin(PIN, PWMCH);
}
void loop() {
ledcWrite(PWMCH, 0); // 0%(0.0V)
delay(500);
ledcWrite(PWMCH, 128); // 50%(1.7V)
delay(500);
ledcWrite(PWMCH, 256); // 100%(3.3V)
delay(500);
}
PWMはdigitalWrite()で出力を定期的にON/OFFさせることで、擬似的なdacWrite()に似た動きになります。PWMは4PIN同時に利用することが可能で、細かい設定はledcSetup()で行っています。サンプルは周波数が 12KHz で分解能が8ビット(0-256)になっています。
8ビットの場合、256分割してそのうち何個を出力するかの指定なので、出力しないの0と全部出力するの256までの257段階で制御が可能です。

上記はキャプチャ用に周波数50Hzに落として実験しましたが、上記のように128(50%)を指定するとONとOFFが交互にきて、平均すると半分の電圧相当になります。
LEDの明るさ調整とかであればdacWrite()でなくて、PWM制御で十分明るさが変わります。
まとめ
GROVEの電源が5Vなんで、ちょっと注意が必要そうですね。あと本家だといろいろな拡張HATが開発されているようですので、楽しみです。
今後はI2Cとか2PIN以上必要な通信を調べていきたいと思います。



コメント
素晴らしいレポートありがとうございます