ESP32-S3のPCNTをPlatformIO版ESP-IDF V5で使う

カテゴリー: ESP32  タグ:

ESP-IDFのAPIはV4.4からV5へのバージョンアップで大幅に仕様が変わったらしいです。PCNTも含まれ、記述や関数名が変わっています。参考はここ

ところが、PlatformIOでESP32-S3をESP-IDF V5.1.1で開発してみると、新しい仕様のPCNTが使えない。無理やり「pulse_cnt.h」「pulse_cnt.c」を組み込んでも当然ながらframeworkにhalのドライバが存在しないのでリンカが通らない。なにより小手先の対策はESP-IDFのバージョンを変えるとフレームワークも一新されるので得策ではありません。

今回はレガシィ記述でPCNTを使うことにしました。その覚書です。

2023/1/4 文章修正と内容訂正しました。

古いPrograminng Manualを探して導入

公式ホームページからのリンクはたどれませんが、旧版のマニュアルページが残っていました。V3.3.6のPrograminng Manualを参考にレガシーPCNTを導入します。

2023/1/4 訂正

よくよく確認したら、公式ページからたどれるV4.4.3のページのPCNTはレガシー記述のマニュアルでした。現在このページには「Download PDF」のリンクが存在するので、できるうちにPDFマニュアルもDLしておきました。PCNT以外のペリフェラルもこういった事例が存在するかもしれませんので、保険です。

ここからexsampleもたどれます。

ポートからパルスを入力して、シリアルモニターにRPM表示

以下は、レガシー記述でPCNTをセットするプログラムです。

ポート41からのパルスを1秒ごとにシリアルモニターにrpm表示で出力するだけの動作プログラムの抜粋です。

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/pcnt.h"

void init_PCNT(void) {
		 pcnt_config = {
		.pulse_gpio_num = (gpio_num_t)41,	// port41
		.ctrl_gpio_num = -1,				// 制御信号使わない
		.channel = PCNT_CHANNEL_0,			// ch0
		.unit = unit,						// unit0
		.pos_mode = PCNT_COUNT_INC,			// 立上りエッジでアップ
		.neg_mode = PCNT_COUNT_DIS,			// 立下りエッジは機能しない
		.lctrl_mode = PCNT_MODE_KEEP,		// 制御信号L設定変更なし
		.hctrl_mode = PCNT_MODE_KEEP,		// 制御信号H設定変更なし
		.counter_h_lim = 3000,
		.counter_l_lim = 0,
	};
	pcnt_unit_config(&pcnt_config);
	pcnt_set_filter_value(unit, 100);
	pcnt_filter_enable(unit);
	pcnt_counter_pause(unit);
	pcnt_counter_clear(unit);
	pcnt_counter_resume(unit);
}

void pcntTestTask(void *pvParameters) {
	int16_t cntval;

	init_PCNT();
	while (1) {
		pcnt_get_counter_value(unit, &cntval);
		pcnt_counter_clear(unit);
		printf("%d\r\n", cntval*60/32);
		vTaskDelay(1000);
	}
}

抜粋なので抜けてますが、ポート41は入力に設定しておきます。メインで「pcntTestTask()」を起動しています。あとRTOSのTickは1000Hzにしてあります。表示を32で割っているのは、たまたま確認したベンチが一回転32パルスだっただけです。

コンパイラは難なく通り、実機で動作OKでした。SGから2,133.333Hzを入力し、vTaskDelayで1秒を単純に区切ってみただけですが表示は4,000(タイミングによっては3999)rpmと正確に出ました。

お気軽にコメントをどうぞ。

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)