どんどん行きましょう。お次はアナログ関係。
結論から言うと、かなり簡単です。まあ SDK 使ってるんですからそりゃそうだけど。
ADC
アナログ値を読み取るやつです。若干面倒ですが...
ソースコードと説明
ご覧の通り。スッキリと書けます。なんとなく FreeRTOS 使ってみました。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "sdkconfig.h"
void vAdc(void *pvParameters) {
adc_gpio_init(ADC_UNIT_1, ADC_CHANNEL_0);
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_11);
while(1) {
printf("%d\n", adc1_get_raw(ADC1_CHANNEL_0));
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void app_main(void) {
xTaskCreatePinnedToCore(vAdc, "ADC", 1024 * 2, NULL, 1, NULL, 1);
}
説明することは Attenuation と入力電圧範囲でしょうか。ドキュメンテーションによると、次のことが書かれています。
- 0 dB attenuation (ADC_ATTEN_DB_0) gives full-scale voltage 1.1 V
- 2.5 dB attenuation (ADC_ATTEN_DB_2_5) gives full-scale voltage 1.5 V
- 6 dB attenuation (ADC_ATTEN_DB_6) gives full-scale voltage 2.2 V
- 11 dB attenuation (ADC_ATTEN_DB_11) gives full-scale voltage 3.9 V (see note below)
つまり、上で書いた ADC_ATTEN_DB_11
が上に対応しているわけです。この場合は入力電圧が 3.9V まで変換されるというわけ。だから電圧値として換算するなら、今回は 3.9 を乗じればいいです。
更に補足として、ドキュメンテーションには推奨電圧範囲(suggested range) が書かれていました。特のこの範囲の特性が良いようです(線形性という点で?)。使用するアプリケーションに応じてここらへんは調節しましょう。
+----------+------------+--------------------------+
| SoC | attenuation| suggested range (mV) |
+==========+============+==========================+
| | 0 | 100 ~ 950 |
| +------------+--------------------------+
| | 2.5 | 100 ~ 1250 |
| ESP32 +------------+--------------------------+
| | 6 | 150 ~ 1750 |
| +------------+--------------------------+
| | 11 | 150 ~ 2450 |
+----------+------------+--------------------------+
| | 0 | 100 ~ 800 |
| +------------+--------------------------+
| | 2.5 | 100 ~ 1100 |
| ESP32-S2 +------------+--------------------------+
| | 6 | 150 ~ 1350 |
| +------------+--------------------------+
| | 11 | 150 ~ 2600 |
+----------+------------+--------------------------+
DAC
お次は DAC です。
LEDボヤァのコード
地味に面白い cw の機能があります。まずは通常の LED ボヤァをどうぞ。説明することはマジでない。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/dac.h"
#include "sdkconfig.h"
void vDacIncr(void *pvParameters) {
dac_output_enable(DAC_CHANNEL_1);
uint8_t voltage = 0;
while(1) {
dac_output_voltage(DAC_CHANNEL_1, voltage += 16);
vTaskDelay(10);
}
}
void app_main(void) {
xTaskCreatePinnedToCore(vDacIncr, "DAC with Increment", 1024 * 2, NULL, 1, NULL, 1);
}
CWジェネレータ
この機能は cos 波形を自動的に生成する機能です。関係ないけど、無線免許を持っている自分からしたら CW ってモールス信号だと思いましたね。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/dac.h"
#include "sdkconfig.h"
void vDacCwGen(void *pvParameters) {
dac_cw_config_t config = {
.en_ch = DAC_CHANNEL_1,
.scale = DAC_CW_SCALE_1,
.phase = DAC_CW_PHASE_0,
.freq = 130,
/* .offset = 0 */
.offset = 1
};
dac_output_enable(DAC_CHANNEL_1);
dac_cw_generator_config(&config);
dac_cw_generator_enable();
while(1) {
vTaskDelay(1);
}
}
void app_main(void) {
xTaskCreatePinnedToCore(vDacCwGen, "DAC with CW Generator", 1024 * 2, NULL, 1, NULL, 1);
}
地味な注意点は offset
です。別に DC オフセットは必要じゃなかったので 0 でいいのかなあと思いましたが、なんかこれじゃあダメでした。良くわからん(ひょっとして ESP-IDF のバグ?)。
一度有効化したら何も操作は要りません。