今回はADCを動かしてみます。
この記事は JTAG でデバッグすることを前提にして書いています。
環境構築については こちら をご覧になってください。
投稿時の開発環境を記しておきます。
PC:
Windows10 OS
開発ボード :
ESP32-DevKitCーVE
(Soc : ESP32-D0WD-V3)
デバッガー(H/W):
FT2232D
デバッガー (S/W) :
Visual Studio Code + PlatformIO + ESP-IDF Framework
ADCとは
アナログ・ディジタル・コンバーターの略で、アナログ電圧をディジタル値に変換する機能です。
プロジェクトをつくる
使っていたプロジェクトを開いていたら、File – Close Folder して閉じておきます。
その後にVSCodeからPlatformIOをOpenします。
以下の内容でプロジェクトを新規に作成します。
Name : ESP32E-ADC
Board : Espressif ESP32 Dev Module
Framework : Eresspsif IoT Development Framework
Name : ESP32E の “E” は Framework (Espressif IoT Development Framework)の頭文字を示しています。
(後から見てわかるように、ESP-IDFを使うことを明示しています)

platformio.ini に以下の3行を追加して、 Ctrl + s で保存しておきます。
COM[4]の4の部分はデバイスマネージャーのポート(COMとLPT)で Silicon Labs CP210x から始まるCOMの番号を記述します。
debug_tool = minimodule
upload_port = COM[4]
monitor_speed = 115200
ADCのAPIリファレンスとサンプル
ADCのAPIは こちら を参照してください。
サンプルプログラムは こちら を参考にしました。
PlatformIOで Eresspsif IoT Development Framework を選択したことにより、以下のローカルフォルダからも参照可能なはずです。
C:\Users\xxxxx\.platformio\packages\framework-espidf\examples\peripherals\adc\single_read\adc
(xxxxxは皆さまのユーザー名)
電源電圧を測定する
設定することで-11dBのアッテネーターが使えるようなのですが、これを使っても電源電圧は測定できないようです。
基準電圧(Vref)が1100mV程度ということなので、抵抗で分割した電圧を入力し、マイコン内部のアッテネーターは使わないことにしました。
Vrefは一定ではないようで、調べていたら esp_adc_cal_characterize() という関数で Vrefを得ることができるようなので試してみました。
マイコンへの入力電圧が1100mVを超えない程度に(手持ちの)抵抗は以下の定数を使いました。

コーディングする
main.c を以下のようにコーディングします。
#include
#include
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#include "esp_log.h"
static const char *TAG = "adc";
#define DEFAULT_VREF 1100 // (1)デフォルトのリファレンス電圧 [mV]
static esp_adc_cal_characteristics_t *adc_chars; // (2)情報を格納するための構造体へのポインタ
static void check_efuse(void) // (3)efuseを確認するための関数
{
//Check if TP is burned into eFuse
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
ESP_LOGI(TAG, "eFuse Two Point: Supported\n");
} else {
ESP_LOGI(TAG, "eFuse Two Point: NOT supported\n");
}
//Check Vref is burned into eFuse
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
ESP_LOGI(TAG, "eFuse Vref: Supported\n");
} else {
ESP_LOGI(TAG, "eFuse Vref: NOT Supported\n");
}
}
void app_main(void)
{
//Check if Two Point or Vref are burned into eFuse
check_efuse();
adc1_config_width(ADC_WIDTH_BIT_12); // (4)ADCの分解能を設定する
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_0); // (5)ADCのチャンネルとアッテネーターを設定する
//Characterize ADC
adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t)); // (6)構造体のメモリ確保
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_0, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars); // (7)情報を取得する
int vref = adc_chars->vref; // (8)リファレンス電圧を得る
while (true)
{
int val = adc1_get_raw(ADC1_CHANNEL_0); // (9)0-4095の値を読む
int devidedVoltage = val * vref / 4095; // (10)分圧された電圧を得る
int powerSupplyVoltage = 5.7 * devidedVoltage; // (11)分圧された電圧から電源電圧を得る
ESP_LOGI(TAG, "devidedVoltage: %d powerSupplyVoltage: %d mV\r\n", devidedVoltage, powerSupplyVoltage); // (12)ログに出力する
vTaskDelay(pdMS_TO_TICKS(1000)); // (13)時間待ち
}
}
ビルドして実行する
ビルド後、エラーがないことを確認して F5キーを押して app_main() にカーソルが来るまで待ちます。
その後、Monitor を起動し、F5キーを押してプログラムを実行します。
以下のように値が表示されれば成功です。

check_efuse()は計測とは無関係ですが、確認するために使ってみました。
こちらの環境では以下の通りでした。
eFuse Two Point: NOT supported
eFuse Vref: Supported
マイコンのADCは「大体これくらいの値」を測定できれば良いと思っているので、まあ合格です。。