無線ブログ集
メイン | 簡易ヘッドライン |
リンク 単体表示
jl7gmnのblog (2024/3/11 19:35:35)
現在データベースには 147 件のデータが登録されています。
ESP32DevKitCでの周波数カウンタその1
(2023/1/11 3:06:55)
あるWebページからのきっかけで、ESP32DevkitC対応のカウンタをためしてみたくなり、ESP32DevKitCでの周波数カウンタのサンプルをWebで探したところ、説明がポルトガル語ですが、ありました。ESPを楽しむ上ではとても良いサンプルだと思います。割り込みを使った安定動作するカウンタです。入力波形が矩形波である程度きれいな場合は1Hz桁の変動だけありますが精度よく動作してくれるようです。
早速、サンプル作製と詳細な動作説明がありましたのでWebアプリを使いポルトガル語を和訳してみました。和訳はフリーのWebアプリを使いました。和訳説明は最後に添付します。
因みにこの周波数カウンタでは校正確認用のOSCも内蔵されています。内蔵OSCを1Hzから最大40MHzまで変えてみて実際に40MHzまでカウントできました。
ブログは次のurlです。
ブログサンプルの回路図通りに液晶を準備し、接続します。
周波数入力はGPIO34
OSC出力はGPIO33
端子接続GPIO32とGPIO35
LCD GNDはGND
LCD VCCは+5V
LCD SDAはGPIO21
LCD SCLはGPIO22
内蔵OSC発振周波数を使っての確認時は周波数入力GPIO34とOSC出力GPIO33を繋ぎます。
【主な変更箇所】
サンプルで使用してる液晶LCDは16x2のI2C接続ですが、ブログのLCDのスケッチでは手持ちのLCDと違う為表示は動作しませんので、手持ち用の実績のある1602AのLCDのスケッチに書き直してます。アドレスは手持ちで確認してある0x27です。自分のLCDに合わせてアドレスは事前確認必要です。
オリジナルスケッチ
#include <LiqudCrystal_PCF8574.h>
LiquidCrystal_PCF8574 lcd(0x3F);
手持ちのLCDのスケッチへ変更
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
LiquidCrystal_I2C lcd(0x27,16,2);
ほか,修正箇所として、LCDの種類切り替えは削除してます。
動作の保証はあくまでも私の手持ち部品での動作確認を行なった内容なのでありませんし、しません。
下記に全スケッチ(和訳コメントあり)を示します。
***********************************************
// file:FREQ-COUNTER-2023JAN10-001.ino
// Modefy by JL7GMN
// ESP32DivKitC-FREQ-Counter
// ----ORIGINAL-------------------------------------------------
// BLOG Eletrogate
// ESP32 Frequencimetro
// ESP32 DevKit 38 pinos + LCD
// https://blog.eletrogate.com/esp32-frequencimetro-de-precisao
// Rui Viana e Gustavo Murta agosto/2020
// -------------------------------------------------------------
#include "stdio.h" // Biblioteca STDIO //stdioライブラリ
#include "driver/ledc.h" // Biblioteca ESP32 LEDC //ESP32 LEDCライブラリ
#include "driver/pcnt.h" // Biblioteca ESP32 PCNT //ESP32 PCNTライブラリ
#include "soc/pcnt_struct.h"
#define LCD_ON //LCDを使用する場合はLCD_ONを、使用しない場合はLCD_OFFを設定する。
#define LCD_I2C_OFF //I2C LCDを使用する場合はLCD_I2C_ONを、使用しない場合はLCD_I2C_OFFを設定する。
//-------------------------------------------------------------
#define I2C_SDA 21 //液晶ディスプレイ i2c SDA - Gpio_21
#define I2C_SCL 22 //液晶ディスプレイ i2c SDA - Gpio_22
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
//--------------------------------------------------------------
#define PCNT_COUNT_UNIT PCNT_UNIT_0 //ESP32 パルスカウンター PCNT ユニット 0
#define PCNT_COUNT_CHANNEL PCNT_CHANNEL_0 //ESP32 パルスカウンター PCNT チャンネル 0
#define PCNT_INPUT_SIG_IO GPIO_NUM_34 //周波数計入力 - GPIO 34
#define LEDC_HS_CH0_GPIO GPIO_NUM_33 //LEDC出力 - パルスジェネレータ - GPIO_33
#define PCNT_INPUT_CTRL_IO GPIO_NUM_35 //PCNT制御端子 - HIGH=カウントアップ、LOW=カウントダウン
#define OUTPUT_CONTROL_GPIO GPIO_NUM_32 //タイマ出力 - カウントを制御する - GPIO_32
#define PCNT_H_LIM_VAL overflow //カウント上限値
#define IN_BOARD_LED GPIO_NUM_2 //ESP32 ネイティブLED - GPIO 2
bool flag = true; //カウント終了インジケーター - 印刷を再開する
uint32_t overflow = 20000; //PCNTカウンタオーバーフローの最大値
int16_t pulses = 0; //カウントされたパルス数
uint32_t multPulses = 0; //カウンタオーバーフロー回数 PCNT
uint32_t janela = 1000000; //パルスカウントのための1秒間のサンプリング時間 999990
//uint32_t oscilador = 12543; //発振器の初期周波数 - 12543 Hz -> 1MHz
uint32_t oscilador = 1000000;//resol:3 1,000,008Hz (1MHz)
uint32_t mDuty = 0; //ロードサイクルの計算値
uint32_t resolucao = 0; //解像度の計算値
float frequencia = 0; //周波数計算用変数
char buf[32]; //スコアを記録するためのバッファー
esp_timer_create_args_t create_args; //ESP-Timerの引数
esp_timer_handle_t timer_handle; //ESP-Timerインスタンス
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; //同期用変数型portMUX_TYPE
//----------------------------------------------------------------------------------------
void setup()
{
Serial.begin(115200); //シリアル115200Bpsの初期化
//Serial.println(" Digite uma frequencia - 1 a 40 MHz"); // Print na console
lcd.init();
lcd.backlight();
lcd.clear();
// Modefy by JL7GMN
// ESP32DivKitC-FREQ-Counter
// ----ORIGINAL-------------------------------------------------
// BLOG Eletrogate
// ESP32 Frequencimetro
// ESP32 DevKit 38 pinos + LCD
// https://blog.eletrogate.com/esp32-frequencimetro-de-precisao
// Rui Viana e Gustavo Murta agosto/2020
// -------------------------------------------------------------
#include "stdio.h" // Biblioteca STDIO //stdioライブラリ
#include "driver/ledc.h" // Biblioteca ESP32 LEDC //ESP32 LEDCライブラリ
#include "driver/pcnt.h" // Biblioteca ESP32 PCNT //ESP32 PCNTライブラリ
#include "soc/pcnt_struct.h"
#define LCD_ON //LCDを使用する場合はLCD_ONを、使用しない場合はLCD_OFFを設定する。
#define LCD_I2C_OFF //I2C LCDを使用する場合はLCD_I2C_ONを、使用しない場合はLCD_I2C_OFFを設定する。
//-------------------------------------------------------------
#define I2C_SDA 21 //液晶ディスプレイ i2c SDA - Gpio_21
#define I2C_SCL 22 //液晶ディスプレイ i2c SDA - Gpio_22
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
//--------------------------------------------------------------
#define PCNT_COUNT_UNIT PCNT_UNIT_0 //ESP32 パルスカウンター PCNT ユニット 0
#define PCNT_COUNT_CHANNEL PCNT_CHANNEL_0 //ESP32 パルスカウンター PCNT チャンネル 0
#define PCNT_INPUT_SIG_IO GPIO_NUM_34 //周波数計入力 - GPIO 34
#define LEDC_HS_CH0_GPIO GPIO_NUM_33 //LEDC出力 - パルスジェネレータ - GPIO_33
#define PCNT_INPUT_CTRL_IO GPIO_NUM_35 //PCNT制御端子 - HIGH=カウントアップ、LOW=カウントダウン
#define OUTPUT_CONTROL_GPIO GPIO_NUM_32 //タイマ出力 - カウントを制御する - GPIO_32
#define PCNT_H_LIM_VAL overflow //カウント上限値
#define IN_BOARD_LED GPIO_NUM_2 //ESP32 ネイティブLED - GPIO 2
bool flag = true; //カウント終了インジケーター - 印刷を再開する
uint32_t overflow = 20000; //PCNTカウンタオーバーフローの最大値
int16_t pulses = 0; //カウントされたパルス数
uint32_t multPulses = 0; //カウンタオーバーフロー回数 PCNT
uint32_t janela = 1000000; //パルスカウントのための1秒間のサンプリング時間 999990
//uint32_t oscilador = 12543; //発振器の初期周波数 - 12543 Hz -> 1MHz
uint32_t oscilador = 1000000;//resol:3 1,000,008Hz (1MHz)
uint32_t mDuty = 0; //ロードサイクルの計算値
uint32_t resolucao = 0; //解像度の計算値
float frequencia = 0; //周波数計算用変数
char buf[32]; //スコアを記録するためのバッファー
esp_timer_create_args_t create_args; //ESP-Timerの引数
esp_timer_handle_t timer_handle; //ESP-Timerインスタンス
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; //同期用変数型portMUX_TYPE
//----------------------------------------------------------------------------------------
void setup()
{
Serial.begin(115200); //シリアル115200Bpsの初期化
//Serial.println(" Digite uma frequencia - 1 a 40 MHz"); // Print na console
lcd.init();
lcd.backlight();
lcd.clear();
#if defined
LCD_ON //
LCDまたはI2C LCDを使用している場合
lcd.begin(16, 2); // LCD初期化 16列2行
//lcd.print(" Frequencia:"); //LCDに周波数("FREQUENCY:")文字を表示
lcd.print(" FREQUENCY:"); //Change Portugal to English
#endif
Serial.println(" Input Frequency 1 to 40 MHz"); // Print message for input freq
inicializa_frequencimetro(); // 周波数メーターの初期化
}
//----------------------------------------------------------------------------
void inicializa_oscilador () //パルスジェネレータの初期化
{
resolucao = (log (80000000 / oscilador) / log(2)) / 2 ; //発振器の解を計算する
if (resolucao < 1) resolucao = 1; // 最小分解能
Serial.print("resolucao :");
Serial.println(resolucao); // Print //SERIAL MONITOR PRINT
mDuty = (pow(2, resolucao)) / 2; //ロードサイクル計算 パルスの50%
// Serial.println(mDuty); //SERIAL MONITOR PRINT mDuty
ledc_timer_config_t ledc_timer = {}; //LEDC タイマー設定のインストール
ledc_timer.duty_resolution = ledc_timer_bit_t(resolucao); //解像度を設定する
ledc_timer.freq_hz = oscilador; //発振周波数を設定
ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE; //高速動作モード
ledc_timer.timer_num = LEDC_TIMER_0; //LEDC タイマー0を使用
ledc_timer_config(&ledc_timer); //LEDCタイマーを設定
ledc_channel_config_t ledc_channel = {}; //LEDCのチャンネル構成をインスタンス化します。
ledc_channel.channel = LEDC_CHANNEL_0; //チャンネル0を設定する
ledc_channel.duty = mDuty; //充電サイクルを設定する
ledc_channel.gpio_num = LEDC_HS_CH0_GPIO; //LEDC出力のGPIO設定 - 発振器
ledc_channel.intr_type = LEDC_INTR_DISABLE; //LEDC割り込み禁止
ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE; //高速チャンネル動作モード
ledc_channel.timer_sel = LEDC_TIMER_0; //LEDC タイマー0を選択
ledc_channel_config(&ledc_channel); //LEDCチャンネルを設定
}
//----------------------------------------------------------------------------------
static void IRAM_ATTR pcnt_intr_handler(void *arg) //オーバーフローカウンタカウント
{
portENTER_CRITICAL_ISR(&timerMux); //それ以上の割り込みをブロック
multPulses++; //オーバーフローカウンタをインクリメント
PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT); //インタラプションインジケーターワイパー
portEXIT_CRITICAL_ISR(&timerMux); //新しい割り込みをリリース
}
//----------------------------------------------------------------------------------
void inicializa_contador(void) //パルスカウンタの初期化
{
pcnt_config_t pcnt_config = { }; //インスタンスPCNT設定
pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_IO; //GPIOをパルス入力に設定
pcnt_config.ctrl_gpio_num = PCNT_INPUT_CTRL_IO; //カウント制御用GPIOの設定
pcnt_config.unit = PCNT_COUNT_UNIT; //カウントユニット PCNT - 0
pcnt_config.channel = PCNT_COUNT_CHANNEL; //カウントチャネル PCNT - 0
pcnt_config.counter_h_lim = PCNT_H_LIM_VAL; //最大カウント数 20000
pcnt_config.pos_mode = PCNT_COUNT_INC; //パルスの立ち上がりでカウントアップ
pcnt_config.neg_mode = PCNT_COUNT_INC; //パルスの立ち下がりでカウントを増加させる
pcnt_config.lctrl_mode = PCNT_MODE_DISABLE; //PCNT - lctrlモード無効
pcnt_config.hctrl_mode = PCNT_MODE_KEEP; //PCNT - hctrlモード - HIGHならカウントアップ
pcnt_unit_config(&pcnt_config); //PCNTカウンターの設定
pcnt_counter_pause(PCNT_COUNT_UNIT); //PCNTカウンターを一時停止
pcnt_counter_clear(PCNT_COUNT_UNIT); //PCNTカウンターを0にリセット
pcnt_event_enable(PCNT_COUNT_UNIT, PCNT_EVT_H_LIM); //カウント上限値の設定
pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL);//PCNT割り込みルーチンの設定
pcnt_intr_enable(PCNT_COUNT_UNIT); //PCNT割り込みの有効化
pcnt_counter_resume(PCNT_COUNT_UNIT); //PCNTカウンターのカウントをリセットする
}
//----------------------------------------------------------------------------------
void tempo_controle(void *p) //パルス読み出し終了時間
{
gpio_set_level(OUTPUT_CONTROL_GPIO, 0); //PCNTコントロール - メーター用
pcnt_get_counter_value(PCNT_COUNT_UNIT, &pulses);//PCNTにカウントされた値を取得
flag = true; //制御の中断が発生したことを通知
}
//---------------------------------------------------------------------------------
void inicializa_frequencimetro()
{
inicializa_oscilador (); //発振器でパルスの発生を開始する。
inicializa_contador(); //PCNTパルスカウンタの初期化
gpio_pad_select_gpio(OUTPUT_CONTROL_GPIO); //制御ポートを設定する
gpio_set_direction(OUTPUT_CONTROL_GPIO, GPIO_MODE_OUTPUT); //制御ポートを出力に設定
create_args.callback = tempo_controle; //制御時間のインスタンス化
esp_timer_create(&create_args, &timer_handle); //タイマーのパラメータを作成する
gpio_set_direction(IN_BOARD_LED, GPIO_MODE_OUTPUT); //ポートLEDを出力
gpio_matrix_in(PCNT_INPUT_SIG_IO, SIG_IN_FUNC226_IDX, false); //パルス入力を指示する
gpio_matrix_out(IN_BOARD_LED, SIG_IN_FUNC226_IDX, false, false);//ESP32のLEDの場合
}
//----------------------------------------------------------------------------------------
//ドットを含む32ビット長数値の書式設定
char *ultos_recursive(unsigned long val, char *s, unsigned radix, int pos)
{
int c;
if (val >= radix)
s = ultos_recursive(val / radix, s, radix, pos + 1);
c = val % radix;
c += (c < 10 ? '0' : 'a' - 10);
*s++ = c;
//if (pos % 3 == 0) *s++ = '.';
if (pos % 3 == 0) *s++ = ',';
return s;
}
//----------------------------------------------------------------------------------------
//ドットを含む32ビット長数値の書式設定
char *ltos(long val, char *s, int radix)
{
if (radix < 2 || radix > 36) {
s[0] = 0;
} else {
char *p = s;
if (radix == 10 && val < 0) {
val = -val;
*p++ = '-';
}
p = ultos_recursive(val, p, radix, 0) - 1;
*p = 0;
}
return s;
}
//---------------------------------------------------------------------------------
void loop()
{
if (flag == true) //カウントダウンが終了した場合
{
flag = false; //COUNTDOWN NOT FINISH FLAG SETTING
frequencia = (pulses + (multPulses * overflow)) / 2 ; //PCNTでカウントされたパルスの合計を計算する
//printf("Frequencia : %s", (ltos(frequencia, buf, 10))); // Print frequencia com pontos
printf("FREQUENCY : %s", (ltos(frequencia, buf, 10))); // Print frequencia com pontos
printf(" Hz \n"); // Print unidade Hz
//#if defined LCD_ON || defined LCD_I2C_ON //LCDまたはI2C LCDを使用する場合
#if defined LCD_ON
lcd.setCursor(2, 1); //カーソルを1行目の2番目に位置させる
lcd.print((ltos(frequencia, buf, 10))); //LCDに表示される周波数プリント頻度
lcd.print(" Hz "); //LCDにHz単位を表示
#endif
multPulses = 0; //オーバーフローカウンターのクリア
delay (100); // Delay 100 ms あらゆる用途に対応できるdelaytimer
// Espaco para qualquer função
pcnt_counter_clear(PCNT_COUNT_UNIT); //PCNTカウンターをゼロにリセット
esp_timer_start_once(timer_handle, janela); //1秒タイムカウンター開始
gpio_set_level(OUTPUT_CONTROL_GPIO, 1); //制御ポート - パルスカウントを有効にする
}
String inputString = ""; //データ入力用クリア文字列 初期化
oscilador = 0; //周波数値をゼロにリセット
while (Serial.available()) //シリアルでデータを持っている間
{
char inChar = (char)Serial.read(); //1 バイトの読み出し。
inputString += inChar; //文字列を追加
if (inChar == '\n') //ENTERを押した場合
{
oscilador = inputString.toInt(); //文字列を整数に変換する
inputString = ""; //文字列を消去する
}
}
if (oscilador != 0) //何らかの値が入力されている場合
{
inicializa_oscilador (); //発振器の周波数をリセットする
}
}
lcd.begin(16, 2); // LCD初期化 16列2行
//lcd.print(" Frequencia:"); //LCDに周波数("FREQUENCY:")文字を表示
lcd.print(" FREQUENCY:"); //Change Portugal to English
#endif
Serial.println(" Input Frequency 1 to 40 MHz"); // Print message for input freq
inicializa_frequencimetro(); // 周波数メーターの初期化
}
//----------------------------------------------------------------------------
void inicializa_oscilador () //パルスジェネレータの初期化
{
resolucao = (log (80000000 / oscilador) / log(2)) / 2 ; //発振器の解を計算する
if (resolucao < 1) resolucao = 1; // 最小分解能
Serial.print("resolucao :");
Serial.println(resolucao); // Print //SERIAL MONITOR PRINT
mDuty = (pow(2, resolucao)) / 2; //ロードサイクル計算 パルスの50%
// Serial.println(mDuty); //SERIAL MONITOR PRINT mDuty
ledc_timer_config_t ledc_timer = {}; //LEDC タイマー設定のインストール
ledc_timer.duty_resolution = ledc_timer_bit_t(resolucao); //解像度を設定する
ledc_timer.freq_hz = oscilador; //発振周波数を設定
ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE; //高速動作モード
ledc_timer.timer_num = LEDC_TIMER_0; //LEDC タイマー0を使用
ledc_timer_config(&ledc_timer); //LEDCタイマーを設定
ledc_channel_config_t ledc_channel = {}; //LEDCのチャンネル構成をインスタンス化します。
ledc_channel.channel = LEDC_CHANNEL_0; //チャンネル0を設定する
ledc_channel.duty = mDuty; //充電サイクルを設定する
ledc_channel.gpio_num = LEDC_HS_CH0_GPIO; //LEDC出力のGPIO設定 - 発振器
ledc_channel.intr_type = LEDC_INTR_DISABLE; //LEDC割り込み禁止
ledc_channel.speed_mode = LEDC_HIGH_SPEED_MODE; //高速チャンネル動作モード
ledc_channel.timer_sel = LEDC_TIMER_0; //LEDC タイマー0を選択
ledc_channel_config(&ledc_channel); //LEDCチャンネルを設定
}
//----------------------------------------------------------------------------------
static void IRAM_ATTR pcnt_intr_handler(void *arg) //オーバーフローカウンタカウント
{
portENTER_CRITICAL_ISR(&timerMux); //それ以上の割り込みをブロック
multPulses++; //オーバーフローカウンタをインクリメント
PCNT.int_clr.val = BIT(PCNT_COUNT_UNIT); //インタラプションインジケーターワイパー
portEXIT_CRITICAL_ISR(&timerMux); //新しい割り込みをリリース
}
//----------------------------------------------------------------------------------
void inicializa_contador(void) //パルスカウンタの初期化
{
pcnt_config_t pcnt_config = { }; //インスタンスPCNT設定
pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_IO; //GPIOをパルス入力に設定
pcnt_config.ctrl_gpio_num = PCNT_INPUT_CTRL_IO; //カウント制御用GPIOの設定
pcnt_config.unit = PCNT_COUNT_UNIT; //カウントユニット PCNT - 0
pcnt_config.channel = PCNT_COUNT_CHANNEL; //カウントチャネル PCNT - 0
pcnt_config.counter_h_lim = PCNT_H_LIM_VAL; //最大カウント数 20000
pcnt_config.pos_mode = PCNT_COUNT_INC; //パルスの立ち上がりでカウントアップ
pcnt_config.neg_mode = PCNT_COUNT_INC; //パルスの立ち下がりでカウントを増加させる
pcnt_config.lctrl_mode = PCNT_MODE_DISABLE; //PCNT - lctrlモード無効
pcnt_config.hctrl_mode = PCNT_MODE_KEEP; //PCNT - hctrlモード - HIGHならカウントアップ
pcnt_unit_config(&pcnt_config); //PCNTカウンターの設定
pcnt_counter_pause(PCNT_COUNT_UNIT); //PCNTカウンターを一時停止
pcnt_counter_clear(PCNT_COUNT_UNIT); //PCNTカウンターを0にリセット
pcnt_event_enable(PCNT_COUNT_UNIT, PCNT_EVT_H_LIM); //カウント上限値の設定
pcnt_isr_register(pcnt_intr_handler, NULL, 0, NULL);//PCNT割り込みルーチンの設定
pcnt_intr_enable(PCNT_COUNT_UNIT); //PCNT割り込みの有効化
pcnt_counter_resume(PCNT_COUNT_UNIT); //PCNTカウンターのカウントをリセットする
}
//----------------------------------------------------------------------------------
void tempo_controle(void *p) //パルス読み出し終了時間
{
gpio_set_level(OUTPUT_CONTROL_GPIO, 0); //PCNTコントロール - メーター用
pcnt_get_counter_value(PCNT_COUNT_UNIT, &pulses);//PCNTにカウントされた値を取得
flag = true; //制御の中断が発生したことを通知
}
//---------------------------------------------------------------------------------
void inicializa_frequencimetro()
{
inicializa_oscilador (); //発振器でパルスの発生を開始する。
inicializa_contador(); //PCNTパルスカウンタの初期化
gpio_pad_select_gpio(OUTPUT_CONTROL_GPIO); //制御ポートを設定する
gpio_set_direction(OUTPUT_CONTROL_GPIO, GPIO_MODE_OUTPUT); //制御ポートを出力に設定
create_args.callback = tempo_controle; //制御時間のインスタンス化
esp_timer_create(&create_args, &timer_handle); //タイマーのパラメータを作成する
gpio_set_direction(IN_BOARD_LED, GPIO_MODE_OUTPUT); //ポートLEDを出力
gpio_matrix_in(PCNT_INPUT_SIG_IO, SIG_IN_FUNC226_IDX, false); //パルス入力を指示する
gpio_matrix_out(IN_BOARD_LED, SIG_IN_FUNC226_IDX, false, false);//ESP32のLEDの場合
}
//----------------------------------------------------------------------------------------
//ドットを含む32ビット長数値の書式設定
char *ultos_recursive(unsigned long val, char *s, unsigned radix, int pos)
{
int c;
if (val >= radix)
s = ultos_recursive(val / radix, s, radix, pos + 1);
c = val % radix;
c += (c < 10 ? '0' : 'a' - 10);
*s++ = c;
//if (pos % 3 == 0) *s++ = '.';
if (pos % 3 == 0) *s++ = ',';
return s;
}
//----------------------------------------------------------------------------------------
//ドットを含む32ビット長数値の書式設定
char *ltos(long val, char *s, int radix)
{
if (radix < 2 || radix > 36) {
s[0] = 0;
} else {
char *p = s;
if (radix == 10 && val < 0) {
val = -val;
*p++ = '-';
}
p = ultos_recursive(val, p, radix, 0) - 1;
*p = 0;
}
return s;
}
//---------------------------------------------------------------------------------
void loop()
{
if (flag == true) //カウントダウンが終了した場合
{
flag = false; //COUNTDOWN NOT FINISH FLAG SETTING
frequencia = (pulses + (multPulses * overflow)) / 2 ; //PCNTでカウントされたパルスの合計を計算する
//printf("Frequencia : %s", (ltos(frequencia, buf, 10))); // Print frequencia com pontos
printf("FREQUENCY : %s", (ltos(frequencia, buf, 10))); // Print frequencia com pontos
printf(" Hz \n"); // Print unidade Hz
//#if defined LCD_ON || defined LCD_I2C_ON //LCDまたはI2C LCDを使用する場合
#if defined LCD_ON
lcd.setCursor(2, 1); //カーソルを1行目の2番目に位置させる
lcd.print((ltos(frequencia, buf, 10))); //LCDに表示される周波数プリント頻度
lcd.print(" Hz "); //LCDにHz単位を表示
#endif
multPulses = 0; //オーバーフローカウンターのクリア
delay (100); // Delay 100 ms あらゆる用途に対応できるdelaytimer
// Espaco para qualquer função
pcnt_counter_clear(PCNT_COUNT_UNIT); //PCNTカウンターをゼロにリセット
esp_timer_start_once(timer_handle, janela); //1秒タイムカウンター開始
gpio_set_level(OUTPUT_CONTROL_GPIO, 1); //制御ポート - パルスカウントを有効にする
}
String inputString = ""; //データ入力用クリア文字列 初期化
oscilador = 0; //周波数値をゼロにリセット
while (Serial.available()) //シリアルでデータを持っている間
{
char inChar = (char)Serial.read(); //1 バイトの読み出し。
inputString += inChar; //文字列を追加
if (inChar == '\n') //ENTERを押した場合
{
oscilador = inputString.toInt(); //文字列を整数に変換する
inputString = ""; //文字列を消去する
}
}
if (oscilador != 0) //何らかの値が入力されている場合
{
inicializa_oscilador (); //発振器の周波数をリセットする
}
}
***********************************************
上記のスケッチではOSC出力は12.543KHzを1MHzに変更して動作確認できています。
OSCは最大40MHzまでカウント動作しました。各周波数でのカウンタ動作確認時のスケッチと周波数を示します。*の表示桁はバラツキ動作がある桁です。
(一部resol値記載がありますが、個人的に分解能変数を知りたくて調べた時の値です。)
//uint32_t
oscilador = 12543; //発振器の初期周波数 - 12543 Hz -> 10MHz
//uint32_t oscilador = 1; //1Hz
//uint32_t oscilador = 10; //10Hz
//uint32_t oscilador = 50; //50Hz
//uint32_t oscilador = 100; //100Hz
//uint32_t oscilador = 500; //resol:8 500Hz
//uint32_t oscilador = 1000; //1,000Hz
//uint32_t oscilador = 5000; //5,000Hz
//uint32_t oscilador = 10000;//resol:6 10,000Hz
//uint32_t oscilador = 12500;//resol:6 12,500Hz
//uint32_t oscilador = 20000;//resol:5 20,000Hz
//uint32_t oscilador = 50000;//resol:5 50,000Hz
//uint32_t oscilador = 60000;//resol:5 60,000Hz
//uint32_t oscilador = 70000;//resol:5 70,007Hz
//uint32_t oscilador = 80000;//resol:4 80,000Hz
//uint32_t oscilador = 90000;//resol:4 90,002Hz
//uint32_t oscilador = 100000;//resol:4 100,000Hz
//uint32_t oscilador = 200000;//resol:4 200,002Hz
//uint32_t oscilador = 300000;//resol:4 300,049Hz
//uint32_t oscilador = 400000;//resol:3 400,004Hz
//uint32_t oscilador = 500000;//resol:3 500,005Hz
//uint32_t oscilador = 600000;//resol:3 600,099Hz
//uint32_t oscilador = 700000;//resol:3 700,033Hz
//uint32_t oscilador = 800000;//resol:3 800,007Hz
//uint32_t oscilador = 900000;//resol:3 900,149Hz
uint32_t oscilador = 1000000;//resol:3 1,000,008Hz (1MHz)
//uint32_t oscilador = 5000000;//resol:2 5,000,050Hz
//uint32_t oscilador = 10000000;//resol:1 10,000,099Hz
//uint32_t oscilador = 15000000;//resol:1 15,014,80*Hz
//uint32_t oscilador = 20000000;//20,000,184Hz
//uint32_t oscilador = 25000000;//25,036,9**Hz
//uint32_t oscilador = 30000000;//30,029,59*Hz
//uint32_t oscilador = 35000000;//35,068,8**Hz
//uint32_t oscilador = 40000000;//40,000,352Hz
//uint32_t oscilador = 10; //10Hz
//uint32_t oscilador = 50; //50Hz
//uint32_t oscilador = 100; //100Hz
//uint32_t oscilador = 500; //resol:8 500Hz
//uint32_t oscilador = 1000; //1,000Hz
//uint32_t oscilador = 5000; //5,000Hz
//uint32_t oscilador = 10000;//resol:6 10,000Hz
//uint32_t oscilador = 12500;//resol:6 12,500Hz
//uint32_t oscilador = 20000;//resol:5 20,000Hz
//uint32_t oscilador = 50000;//resol:5 50,000Hz
//uint32_t oscilador = 60000;//resol:5 60,000Hz
//uint32_t oscilador = 70000;//resol:5 70,007Hz
//uint32_t oscilador = 80000;//resol:4 80,000Hz
//uint32_t oscilador = 90000;//resol:4 90,002Hz
//uint32_t oscilador = 100000;//resol:4 100,000Hz
//uint32_t oscilador = 200000;//resol:4 200,002Hz
//uint32_t oscilador = 300000;//resol:4 300,049Hz
//uint32_t oscilador = 400000;//resol:3 400,004Hz
//uint32_t oscilador = 500000;//resol:3 500,005Hz
//uint32_t oscilador = 600000;//resol:3 600,099Hz
//uint32_t oscilador = 700000;//resol:3 700,033Hz
//uint32_t oscilador = 800000;//resol:3 800,007Hz
//uint32_t oscilador = 900000;//resol:3 900,149Hz
uint32_t oscilador = 1000000;//resol:3 1,000,008Hz (1MHz)
//uint32_t oscilador = 5000000;//resol:2 5,000,050Hz
//uint32_t oscilador = 10000000;//resol:1 10,000,099Hz
//uint32_t oscilador = 15000000;//resol:1 15,014,80*Hz
//uint32_t oscilador = 20000000;//20,000,184Hz
//uint32_t oscilador = 25000000;//25,036,9**Hz
//uint32_t oscilador = 30000000;//30,029,59*Hz
//uint32_t oscilador = 35000000;//35,068,8**Hz
//uint32_t oscilador = 40000000;//40,000,352Hz
上記のカウントした周波数の誤差はOSC出力波形が歪をおこしている事が原因の様でした。オシロスコープでの波形確認は大切です。Hi!
カウンタ入力に波形成形回路やレベルアンプを追加すると精度良く使用出来ると思われます。ちなみにサンプリングは1secです。また直接のカウンタ入力への正弦波入力では精度は取れません。波形成形回路を入れることで精度良くなると思われます。波形成形回路を追加する時には、カウント確認ポートとしてGPIO2のポートが動作している時に反転出力が出ますのでレベルの調整とかの時に使えます。(カウント時の出力ポートです。)
一部周波数の入力のスケッチ部もありますが、確認してません。
*********************************************
【動作説明の和訳】おかしな訳部分は適当に修正理解お願いします。(アプリでの和訳です。)
■PULSE COUNT
CONTROLLER
PCNTパルスカウンタモジュールは、入力信号の立ち上がりや立ち下がりのエッジ数をカウントするように設計されています。独立した8つのユニットを搭載しているのです 各PCNTユニットは、16ビットカウンタと、立ち上がりまたは立ち下がりカウントを有効にすることができる2つのチャンネルを備えています。各チャンネルには、カウントするパルスの入力と、カウントの有効/無効を切り替えるコントロールポートがあります。 また、各PCNTユニットには、カウンターの設定に使用するレジスタがあります。これらのカウンタは、最大カウンタ値、最小カウンタ値、あるカウンタ値など、選択されたいくつかのパラメータに従って割り込みを発生させるようにプログラムすることができます。今回のケースでは、ESP32で割り込みを発生させるために、カウンタの最大値を使用します。
■TIMER
ESP32には、4つの汎用タイマが内蔵されています。これらはいずれも16ビットのプリスケーラ(分周器)と64ビットのカウンタをベースとした汎用的な64ビットタイマである。
ESP32には2つのタイマモジュールがあり、それぞれ2つのタイマが搭載されています。タイマーの特徴は以下の通りです。
- 2~65536の16ビットプリスケーラです。
- 64ビットのタイムベースカウンターです。
- タイムベースカウンターのアップ/ダウン:カウントの増減を設定可能。
- タイムベースカウンターの停止と再開。
- アラームで自動充電。
- ソフトウェア制御による瞬時充電。
- レベル、パルスエッジ割り込み発生。
各タイマは,APBクロック(APB_CLK,通常80MHz)を基本クロックとして使用します。このクロックを16ビットのプリスケーラで分周し、タイムベースパルスを生成します。このパルスは,構成によってタイムベースカウンタのインクリメントまたはデクリメントに使用することができます。
■高分解能タイマー Temporizador de alta resolução (High Resolution Timer)
ESPRESSIFは、ハードウェアタイマーをより正確かつ高速に制御できるように、ESP32タイマー用のAPI(Application Programming Interface)セットを作成しました。 esp_timerのAPIセットは、シングルおよびピリオディックタイマー、マイクロ秒の分解能と64ビット範囲を提供します。内部的には、esp_timerは64ビットハードウェアタイマーを使用します。このプロジェクトでは、PCNTのパルスカウントを計時するためにesp_timerが使用されています。周波数計測の単位はヘルツで、1秒あたりのパルス数に換算されるため、1秒ごとにPCNTカウンターに入るパルスのカウントが行われる。
■LEDC
LEDCまたはLED_PWMコントローラは、主にLEDの輝度を制御するために設計されていますが、他の目的のためにPWM信号を生成するために使用することも可能です。16個のチャンネルを持ち、独立したパルスを生成してカラーRGB LEDデバイスを駆動することができます。LED_PWMコントローラは、高速PWM8チャンネル、低速PWM8チャンネルを搭載しています。これらのチャンネルは,80MhzのAPB_CLKクロックを使用し,分周器,カウンタ,コンパレータの応用で,周波数とDuty Cycleを調整したパルスを発生させることが可能である。このPWM LEDコントローラのすべての設定は,いくつかの内部レジスタを介して行われます。
■動作原理
周波数計は5つのパーツに分かれています。
1. パルスカウンターです。
2. カウントタイム制御。
3. プログラマブル信号発生器(1Hz~40Mhz)。
4. その他の機能用スペース。
5. 結果のプリントアウト。
1. パルスカウンタはPCNTカウンタモジュールを使用します。PCNTの設定には、以下のパラメータを使用します。
・ゲートウェイ
・入力チャンネルになります。
・制御ポート
・パルスの立ち上がりに応じてカウントされます。
・カウントは、立下りパルスで行います。
・高水準で制御して初めてカウントされる。
・最大カウント数制限
2. カウントタイム制御はesp-timerを使用します。esp-timerは以下のパラメータを持ちます。
・時間制御を行います。
3. 周波数メーターのテスト用周波数発生器は、ledcを使用しています。ledcは以下のパラメータを持つ。
・出力ポートになります。
・lcdチャンネル。
・周波数を使用します。
・ledcの解像度です。
・デューティサイクル
■周波数計の仕組み
・周波数計は、1秒の時間の間にパルスを数えることが基本です。
まず、LEDC発振器とPCNTカウンタの設定と初期化を行います。 そして、esp-timer、カウンターの制御ポートを出力として、カウンターの入力ポートをESP32ボードのLedに接続します。
・LEDC発振器は発振器変数で設定された12.543KHzの周波数の発生を開始します。
この周波数を選んだのは、周波数メーターの精度が分かるようにするためです。この発振器初期化機能では、周波数値に応じて分解能とデューティサイクルが既に自動計算されています。 デューティサイクルとは、生成されたパルスのHIGH部分とLOW部分の比率のことです。例えば、今回のプログラムでは、このDutyは50%、つまりHIGH部分の幅はパルスの全周期の半分となる。
パルスのカウントには、PCNTカウンターを使用した。32,768パルスの制限値があるため、このプログラムでは20,000の値を最大値として設定した。カウント時間中に20,000パルスを超えた場合、オーバーフローレジスタが発生します。 オーバーフローが発生するたびに、変数multPulsesにカウントされます。
カウント制御ポート(GPIO 35)がハイレベルになると、パルス入力ポート(GPIO 34)から入力されるパルスをカウントするようにカウンタを解放します。制御パルスの立ち上がりと立ち下がりの両方でパルスをカウントし、平均的なカウントを向上させます。この2つのカウントを2で割ると頻度が算出される。
・カウント時間は、esp-timerで設定します。
可変窓から1秒に設定されています。タイマーの1パルスが1マイクロ秒に相当するので、100万パルスをカウントすると1秒の周波数サンプリングが完了します。
割り込みに対応した2つの機能がプログラム上で定義されています。最初の関数IRAM_ATTR pcntは、PCNTカウンタが満杯になるたびに、オーバーフローカウンタをインクリメントします。もう一つの関数time_controlは、esp-timerの時間切れ後、PCNTカウンターのレジスタに含まれる値を取得します。
1秒経過後、PCNTカウンタレジスタが読み出され、カウント終了を示すFlagがtrueに変更されます。プログラムループでは、Flagがtrueであることがわかると、周波数値が計算される。 オーバーフロー回数に20,000を乗じ、残りパルス数に加算します。この和を2で割ると、カウントが2回行われるため(制御パルスの立ち上がりと立ち下がりでパルスをカウント)、2回目のカウントが行われます。
ディスプレイの周波数を読みやすくするために、ultosとltosという機能を使って、3桁ごとにドットを挿入しています。この周波数は、LCDディスプレイに表示される以外に、Arduino IDEのシリアルコンソールにも送信されます。周波数サンプリング後、レジスタをリセットし、時刻とパルスカウントを再開します。
また、Arduino IDEのシリアルコンソールを使用して、テスト用に発振器の周波数を変更することも可能です。入力フィールドに1Hz~40MHzの値を入力し、ENTERを押します。
発振器のパルス出力はGPIO33ピンに設定されていますので、このパルス出力をGPIO34の周波数メータ入力に接続して、テストを行う必要があります。ただし、外部信号の周波数測定では、この接続を外してください。ESP32は3.3Vの電圧信号で動作するため、それ以外の電圧レベルの信号を測定したい場合は、入力ポートにロジックレベルコンバータ 3.3V-5V Bidirectional - 4 Channelを使用することを推奨します。内部ではGPIOマトリックスを使って、周波数計からの入力パルスをESP32のネイティブLEDに導き、周波数に応じてLEDを点滅させるようにしています。
■■使用したライブラリ■■
このプロジェクトで使用したArduino IDEのバージョンはV 1.8.12ですが、コードの非互換性を避けるため、バージョンが古い場合は更新してください。
2023年1月10日(火曜日)現在【【Arduino IDE 2.0.3】】
ESP32 Boardで使用するためのArduino IDEの設定がまだの場合は、以下のリンク先のチュートリアルの手順に従ってください。この設定は、プロジェクトが正常に動作するために必要不可欠です。 ESP32 BoardがTutorialと異なる場合は、Arduino IDEで設定を変更してください。
今回使用したArduino IDEのESP32ファームウェアのバージョンはV 1.0.4です。もし古い場合は、何らかの不具合を避けるために、プログラムをコンパイルする前にアップデートしてください。必要であれば、Board Managerを使用して更新します。
I2Cインターフェース(PCF8574)の液晶ディスプレイを使用するには、LiquidCrystal_PCF8574ライブラリのインストールが必要です。Arduino IDEのLibrary Managerを使用してインストールします。
また、パラレルLCDディスプレイ(4ビット)を使用する場合は、Arduino IDEのライブラリマネージャでLiquidCrystalライブラリもインストールしてください。
■回路図 Diagramas dos circuitos:
I2Cインターフェース搭載ディスプレイ(PCF8574)の構成図(画像を拡大するには、別のタブで開いてください。)
ディスプレイの裏に接続されているI2C Interfaceボード(PCF8574)のポテンショメーターで、ディスプレイの明るさを調整することを忘れないでください。ジャンパーは接続したままにしてください。
■ESP32 周波数メーターのプログラム。
表示選択指示
Arduino IDEコンパイラは、プログラムコンパイラのディレクティブを使用して、LCDディスプレイの種類を有効にしたり選択したりすることができます。
LCD並列使用 - LCD_ONまたはLCD_OFFに変更してください。
#define LCD_OFF ou #define LCD_ON // ON se for usar esse display
I2C LCDの使用 - LCD_I2C_ONまたはLCD_I2C_OFFに変更します。
#define LCD_I2C_ON ou #define LCD_I2C_OFF // ON se for usar esse display
OB:LCDのI2Cインターフェースのアドレスが分からない場合は、ESP32 I2C Scannerを使って調べてください:(私のボードのアドレスは0x3Fです)。
PCNTパルスカウンタモジュールは、入力信号の立ち上がりや立ち下がりのエッジ数をカウントするように設計されています。独立した8つのユニットを搭載しているのです 各PCNTユニットは、16ビットカウンタと、立ち上がりまたは立ち下がりカウントを有効にすることができる2つのチャンネルを備えています。各チャンネルには、カウントするパルスの入力と、カウントの有効/無効を切り替えるコントロールポートがあります。 また、各PCNTユニットには、カウンターの設定に使用するレジスタがあります。これらのカウンタは、最大カウンタ値、最小カウンタ値、あるカウンタ値など、選択されたいくつかのパラメータに従って割り込みを発生させるようにプログラムすることができます。今回のケースでは、ESP32で割り込みを発生させるために、カウンタの最大値を使用します。
■TIMER
ESP32には、4つの汎用タイマが内蔵されています。これらはいずれも16ビットのプリスケーラ(分周器)と64ビットのカウンタをベースとした汎用的な64ビットタイマである。
ESP32には2つのタイマモジュールがあり、それぞれ2つのタイマが搭載されています。タイマーの特徴は以下の通りです。
- 2~65536の16ビットプリスケーラです。
- 64ビットのタイムベースカウンターです。
- タイムベースカウンターのアップ/ダウン:カウントの増減を設定可能。
- タイムベースカウンターの停止と再開。
- アラームで自動充電。
- ソフトウェア制御による瞬時充電。
- レベル、パルスエッジ割り込み発生。
各タイマは,APBクロック(APB_CLK,通常80MHz)を基本クロックとして使用します。このクロックを16ビットのプリスケーラで分周し、タイムベースパルスを生成します。このパルスは,構成によってタイムベースカウンタのインクリメントまたはデクリメントに使用することができます。
■高分解能タイマー Temporizador de alta resolução (High Resolution Timer)
ESPRESSIFは、ハードウェアタイマーをより正確かつ高速に制御できるように、ESP32タイマー用のAPI(Application Programming Interface)セットを作成しました。 esp_timerのAPIセットは、シングルおよびピリオディックタイマー、マイクロ秒の分解能と64ビット範囲を提供します。内部的には、esp_timerは64ビットハードウェアタイマーを使用します。このプロジェクトでは、PCNTのパルスカウントを計時するためにesp_timerが使用されています。周波数計測の単位はヘルツで、1秒あたりのパルス数に換算されるため、1秒ごとにPCNTカウンターに入るパルスのカウントが行われる。
■LEDC
LEDCまたはLED_PWMコントローラは、主にLEDの輝度を制御するために設計されていますが、他の目的のためにPWM信号を生成するために使用することも可能です。16個のチャンネルを持ち、独立したパルスを生成してカラーRGB LEDデバイスを駆動することができます。LED_PWMコントローラは、高速PWM8チャンネル、低速PWM8チャンネルを搭載しています。これらのチャンネルは,80MhzのAPB_CLKクロックを使用し,分周器,カウンタ,コンパレータの応用で,周波数とDuty Cycleを調整したパルスを発生させることが可能である。このPWM LEDコントローラのすべての設定は,いくつかの内部レジスタを介して行われます。
■動作原理
周波数計は5つのパーツに分かれています。
1. パルスカウンターです。
2. カウントタイム制御。
3. プログラマブル信号発生器(1Hz~40Mhz)。
4. その他の機能用スペース。
5. 結果のプリントアウト。
1. パルスカウンタはPCNTカウンタモジュールを使用します。PCNTの設定には、以下のパラメータを使用します。
・ゲートウェイ
・入力チャンネルになります。
・制御ポート
・パルスの立ち上がりに応じてカウントされます。
・カウントは、立下りパルスで行います。
・高水準で制御して初めてカウントされる。
・最大カウント数制限
2. カウントタイム制御はesp-timerを使用します。esp-timerは以下のパラメータを持ちます。
・時間制御を行います。
3. 周波数メーターのテスト用周波数発生器は、ledcを使用しています。ledcは以下のパラメータを持つ。
・出力ポートになります。
・lcdチャンネル。
・周波数を使用します。
・ledcの解像度です。
・デューティサイクル
■周波数計の仕組み
・周波数計は、1秒の時間の間にパルスを数えることが基本です。
まず、LEDC発振器とPCNTカウンタの設定と初期化を行います。 そして、esp-timer、カウンターの制御ポートを出力として、カウンターの入力ポートをESP32ボードのLedに接続します。
・LEDC発振器は発振器変数で設定された12.543KHzの周波数の発生を開始します。
この周波数を選んだのは、周波数メーターの精度が分かるようにするためです。この発振器初期化機能では、周波数値に応じて分解能とデューティサイクルが既に自動計算されています。 デューティサイクルとは、生成されたパルスのHIGH部分とLOW部分の比率のことです。例えば、今回のプログラムでは、このDutyは50%、つまりHIGH部分の幅はパルスの全周期の半分となる。
パルスのカウントには、PCNTカウンターを使用した。32,768パルスの制限値があるため、このプログラムでは20,000の値を最大値として設定した。カウント時間中に20,000パルスを超えた場合、オーバーフローレジスタが発生します。 オーバーフローが発生するたびに、変数multPulsesにカウントされます。
カウント制御ポート(GPIO 35)がハイレベルになると、パルス入力ポート(GPIO 34)から入力されるパルスをカウントするようにカウンタを解放します。制御パルスの立ち上がりと立ち下がりの両方でパルスをカウントし、平均的なカウントを向上させます。この2つのカウントを2で割ると頻度が算出される。
・カウント時間は、esp-timerで設定します。
可変窓から1秒に設定されています。タイマーの1パルスが1マイクロ秒に相当するので、100万パルスをカウントすると1秒の周波数サンプリングが完了します。
割り込みに対応した2つの機能がプログラム上で定義されています。最初の関数IRAM_ATTR pcntは、PCNTカウンタが満杯になるたびに、オーバーフローカウンタをインクリメントします。もう一つの関数time_controlは、esp-timerの時間切れ後、PCNTカウンターのレジスタに含まれる値を取得します。
1秒経過後、PCNTカウンタレジスタが読み出され、カウント終了を示すFlagがtrueに変更されます。プログラムループでは、Flagがtrueであることがわかると、周波数値が計算される。 オーバーフロー回数に20,000を乗じ、残りパルス数に加算します。この和を2で割ると、カウントが2回行われるため(制御パルスの立ち上がりと立ち下がりでパルスをカウント)、2回目のカウントが行われます。
ディスプレイの周波数を読みやすくするために、ultosとltosという機能を使って、3桁ごとにドットを挿入しています。この周波数は、LCDディスプレイに表示される以外に、Arduino IDEのシリアルコンソールにも送信されます。周波数サンプリング後、レジスタをリセットし、時刻とパルスカウントを再開します。
また、Arduino IDEのシリアルコンソールを使用して、テスト用に発振器の周波数を変更することも可能です。入力フィールドに1Hz~40MHzの値を入力し、ENTERを押します。
発振器のパルス出力はGPIO33ピンに設定されていますので、このパルス出力をGPIO34の周波数メータ入力に接続して、テストを行う必要があります。ただし、外部信号の周波数測定では、この接続を外してください。ESP32は3.3Vの電圧信号で動作するため、それ以外の電圧レベルの信号を測定したい場合は、入力ポートにロジックレベルコンバータ 3.3V-5V Bidirectional - 4 Channelを使用することを推奨します。内部ではGPIOマトリックスを使って、周波数計からの入力パルスをESP32のネイティブLEDに導き、周波数に応じてLEDを点滅させるようにしています。
■■使用したライブラリ■■
このプロジェクトで使用したArduino IDEのバージョンはV 1.8.12ですが、コードの非互換性を避けるため、バージョンが古い場合は更新してください。
2023年1月10日(火曜日)現在【【Arduino IDE 2.0.3】】
ESP32 Boardで使用するためのArduino IDEの設定がまだの場合は、以下のリンク先のチュートリアルの手順に従ってください。この設定は、プロジェクトが正常に動作するために必要不可欠です。 ESP32 BoardがTutorialと異なる場合は、Arduino IDEで設定を変更してください。
今回使用したArduino IDEのESP32ファームウェアのバージョンはV 1.0.4です。もし古い場合は、何らかの不具合を避けるために、プログラムをコンパイルする前にアップデートしてください。必要であれば、Board Managerを使用して更新します。
I2Cインターフェース(PCF8574)の液晶ディスプレイを使用するには、LiquidCrystal_PCF8574ライブラリのインストールが必要です。Arduino IDEのLibrary Managerを使用してインストールします。
また、パラレルLCDディスプレイ(4ビット)を使用する場合は、Arduino IDEのライブラリマネージャでLiquidCrystalライブラリもインストールしてください。
■回路図 Diagramas dos circuitos:
I2Cインターフェース搭載ディスプレイ(PCF8574)の構成図(画像を拡大するには、別のタブで開いてください。)
ディスプレイの裏に接続されているI2C Interfaceボード(PCF8574)のポテンショメーターで、ディスプレイの明るさを調整することを忘れないでください。ジャンパーは接続したままにしてください。
■ESP32 周波数メーターのプログラム。
表示選択指示
Arduino IDEコンパイラは、プログラムコンパイラのディレクティブを使用して、LCDディスプレイの種類を有効にしたり選択したりすることができます。
LCD並列使用 - LCD_ONまたはLCD_OFFに変更してください。
#define LCD_OFF ou #define LCD_ON // ON se for usar esse display
I2C LCDの使用 - LCD_I2C_ONまたはLCD_I2C_OFFに変更します。
#define LCD_I2C_ON ou #define LCD_I2C_OFF // ON se for usar esse display
OB:LCDのI2Cインターフェースのアドレスが分からない場合は、ESP32 I2C Scannerを使って調べてください:(私のボードのアドレスは0x3Fです)。
わたしのコメントです。★手持ちのLCDのボードアドレス:0x27
しかし、LCDディスプレイを使いたくない場合は、Arduino IDEのSerial Consoleで周波数の測定値を表示することができます。また、同じコンソールから、1Hzから40MHzの値の間で希望の試験周波数を入力することができます。とてもクールです。この方法で、プロジェクトが正しく組み立てられたことを確認し、周波数メーターをテストすることができます。
■周波数計の校正。
この設計のさらなる利点は、周波数測定の校正を可能にすることです。ESP32で通常表示される測定値は、非常に満足のいくものです。基準として使用される精密な周波数メーターを使用すると、プログラム内の変数ウィンドウの値を調整することができます。この値を変更することで、得られた精度よりもさらに高い精度を得ることができます。オシロスコープの周波数測定機能を使った周波数計のテストでは、ウィンドウの値を変えて、なんとかオシロスコープと同じ値を得ることができたんだ!」。
どちらのタイプの液晶ディスプレイも搭載しないことにした場合、周波数の測定値を確認するために
Arduino IDEシリアルコンソール
. コンソールスピードは、次のように設定します。
115200 Bps
. 周波数計の試験周波数を変更するには、入力フィールドに1Hz~40MHzの値を入力し、Enterキーを押します。ヘルツ(Hz)の単位は入力する必要がありません。しかし、このテストを行うには、次のことを忘れないでください。
周波数メータ入力 (GPIO34)
Oscilador (GPIO33)の出力に接続する必要があります。
しかし、LCDディスプレイを使いたくない場合は、Arduino IDEのSerial Consoleで周波数の測定値を表示することができます。また、同じコンソールから、1Hzから40MHzの値の間で希望の試験周波数を入力することができます。とてもクールです。この方法で、プロジェクトが正しく組み立てられたことを確認し、周波数メーターをテストすることができます。
■周波数計の校正。
この設計のさらなる利点は、周波数測定の校正を可能にすることです。ESP32で通常表示される測定値は、非常に満足のいくものです。基準として使用される精密な周波数メーターを使用すると、プログラム内の変数ウィンドウの値を調整することができます。この値を変更することで、得られた精度よりもさらに高い精度を得ることができます。オシロスコープの周波数測定機能を使った周波数計のテストでは、ウィンドウの値を変えて、なんとかオシロスコープと同じ値を得ることができたんだ!」。
どちらのタイプの液晶ディスプレイも搭載しないことにした場合、周波数の測定値を確認するために
Arduino IDEシリアルコンソール
. コンソールスピードは、次のように設定します。
115200 Bps
. 周波数計の試験周波数を変更するには、入力フィールドに1Hz~40MHzの値を入力し、Enterキーを押します。ヘルツ(Hz)の単位は入力する必要がありません。しかし、このテストを行うには、次のことを忘れないでください。
周波数メータ入力 (GPIO34)
Oscilador (GPIO33)の出力に接続する必要があります。
*********************************************
参考文献やWeb情報、他は割愛してます。
サンプリング時間変更や、TFT液晶への変更もできますね!
5MHz、6MHzのVFOの周波数などの利用でも100Hz桁も精度良く動作しているので十分使えると思います。
ESP32DevKitCは色々できて、やはりいいですね。
つづく?
FT-2000DをICOMチューナーに繋ぐ自動制御その1
(2022/12/11 23:17:28)
普段無線をする時にFT-2000Dの内蔵チュナーと外付けのICOMのIC-AT100を使いアンテナのマッチングをとっていますが、IC-AT100はICOMの独特のバンド設定方式でYAESU方式と異なる為、全面のバンドSWを手動で切り替えて使用しています。毎回各バンドを行き来する際は本当に面倒です。以前は切り替えを忘れて、SWを焦がしたこともありました。このような手動から開放されたくて、色々と回路を検討していましたが、およそ頭の中では、大丈夫となりましたので、回路を実験しながら組立ててゆきたいと思います。簡単に概略を説明すると、無線器からは、リニアとかをコントロールする時に繋ぐBAND出力(BCD)コード出力が出てるので、これを使います。
回路の心臓部はやはりESP32DevKitCと電圧変換回路です。ESP32DevKitCのデジタル入力ポートにBCDデータ(D0,D1,D2,D3)を入力し、バンド検出コードルーチンで該当するバンドにてD/Aコンバーター出力(0から3V)を出します。この電圧をOPアンプでの電圧フォロワー回路にてICOMのバンド電圧に変換して自動でAT100が制御出来るという塩梅です。D/A出力設定値を調整することが主になるかと思います。上手くいくかはこれからやってみてということになります。OPアンプも12Vを供給して最大8V出力ですので(1.8/1.9MHz検出電圧7V〜8V)RAIL
TO
RAILタイプの高電圧タイプを注文してあります。秋月通販で一昨日発送でしたので、本日届くと思います。主に確認するのはOPアンプ回路での電圧変換回路動作になります。
ESP32DevKitCには本当のアナログDC出力をするポートが2つあることが分かりました。PWMのようなパワー制御のDUTY比設定での平均電圧ではありません。これらのポートの一つを使って単純にD/A出力を0V〜3V(実際最大電圧:3.234V)を出力するだけの簡単なコーディングですから既に確認済みです。
コードは単純に下記になります。(GPIO25ポートとGPIO26ポートがアナログ出力D/A対応)
setupでpinMode(25,OUTPUT);ピンの出力ポートとしての設定をします。
loopルーチン内で、下記の出力コードにて25ピンに電圧が出力されます。
dacWrite(25,255);
//255設定で3.2347V
dacWrite(25,0); //0設定で0.0792V
約3.1555Vの幅です。
8bitで設定範囲は0から255までです。PWMの256とは設定範囲が異なる様です。
文献を確認した所、IC-AT100のバンド毎の中心電圧と検出範囲は下記の様です。
IC-AT100は50MHzは対応していません。ICOMのリニアアンプ用等を使用する際の設定電圧になると思います。
1.8/1.9MHz :7.5V(7.0〜8.0V)
3.5MHz :6.25V(6.0〜6.5V)
7MHz :5.25V(5.0〜5.5V)
14MHz
:4.25V(4.0〜4.5V)
18/21MHz :3.25V(3.0〜3.5V)
24/28MHz :2.25V(2.0〜2.5V)
10MHz :0.6V(0〜1.2V)
50MHz
:1.6V(1.2〜2.0V) ;AT-100は未対応
上記の電圧になるかをESP32のコードdacWrite(25,***)でカットアンドトライ設定で確認します。7.5Vと0.6Vが上手く出れば成功と言うことになります。文章では簡単ですが、OPアンプの回路が上手く動作してくれるかにかかっています。パーツが届いたら回路をブレッドボードに組んでゆきます。
待ち遠しい今でもあります。Hi !
つづく?
FT-2000DをICOMチューナーに繋ぐ自動制御その2
(2022/12/11 23:16:21)
上記のグラフより8ビットのD/A出力での0−3V(実際は1.23V〜3.12V)
続きを読む
昨日、パーツが届いたので、早速OPアンプの電圧変換回路をブレッドボードに組んでみました。
回路は、ネットの知恵袋での検索で、質問者に対する回答の回路に、いいのがありましたので、そのまま使ってみる事にしました。
■使用する実験回路
OPアンプICは2個入りのJRCの7062Dを使用しました。1個で回路が出来上がります。
本来の入力電圧範囲は0.0V〜3.2Vですが、回路は1-5Vを0-10Vに変換する回路なので目的とは違う感じですが、これが実は思うに都合よく動作してくれると思ったからです。それは、電源投入時の初期時のポート出力電圧でのバンド開始点が必ず10MHzを設定して、それから目的の設定バンドへ切り替わり動作するというルーチン動作に出来ると思ったからです。多少検出電圧がでたとしても、ICOMの仕様で、必ず0〜1.2Vの範囲の電圧では10MHzになります。その後にFT-2000DのBAND-DATAで設定されたバンドに切り替わるという流れです。
なお、参照した回路図でので電源電圧は12Vですが、今回は9V電源電圧で行なっています。出力の最大が1.8/1.9MHz時が中心7.5V
(範囲7.0〜8.0V)なので最大で8V出力です。RAIL to
RAILのOPアンプなので電源電圧最大近辺まで出力するということで9Vにしています。ただ、マニュアルを見直したらFT−2000DのBAND-DATA出力端子には13Vの出力があるので、OPアンプ供給電源用13Vでやり直す必要があります。ESP32DevKitCには13Vを5Vレギュレータを通して供給します。他に回路用の電源を別途用意せず、FT-2000DのBAND-DATAソケットから回路全部の電源を供給することにします。
13V電圧変更については先ずは間違いなく動作する電圧が発生できるかの確認なので、見直しはあとにすることにします。
13V電圧変更については先ずは間違いなく動作する電圧が発生できるかの確認なので、見直しはあとにすることにします。
実験ボード(安かったので今回新たに2つ購入した内の1つです。)
早速今回のテスト回路で使いました。
ICOMのバンド設定電圧をグラフに書いてバンド幅の電圧とバンド同士の
区間電圧幅も前もって確認してあります。結構バンドとバンドの間は
電圧差幅がもうけられています。不感(不設定)地帯?
このグラフをみているとゆとり幅電圧区間(不感地帯)があったのが
50MHzが後から付け足してなくなってしまっている経過が分かります。
(24/28MHZと10MHzとの間に無理やり設定した感じです。)
(50MHzがない状態でゆとり幅電圧区間があった24/28MHz,10MHzは
50MHzに対してゆとり幅電圧区間が無しになってしまってます。)
ESP32DevKitCのD/Aコンバーターの出力を設定するN値(0〜255)を
手動で入力してバンドの区間中心電圧になるN値を最初に求めました。
また各中心値N時の出力電圧、OPアンプの電圧変換出力電圧を測定
してみました。わかりやすいようにX軸はN値、Y軸はOPアンプ回路の
出力電圧でグラフにしてみました。(周波数帯も記載)
黄色の50MHzはICOM
IC-AT100ではないので実際は使いません。
FT-2000DではアンテナAをICOM IC-AT100に繋ぎ1.8MHzから29MHzまでの
利用となります。50MHzはIC-AT100が対応してないので、アンテナ切り替え
のBで使う方法で運用することになります。
■各バンドのD/A設定値Nに対する出力電圧
N値に対してとてもリニアに出力電圧が変換出力出来ています。
上記のグラフより8ビットのD/A出力での0−3V(実際は1.23V〜3.12V)
がOPアンプ電圧変換回路で0-8V(実際は0.00V(N=0〜96)〜7.92V(N=255))に
変換出来ています。
D/AでのN値での出力(Δは中止値との差分電圧)
(OPアンプの入力電圧)は以下の通りでした。
N OUTPUT 周波数帯
247 ----- 7.51V (Δ+0.01V)-------
1.8/1.9MHz
222 ----- 6.26V (Δ+0.01V)------- 3.5MHz
202 ----- 5.25V (Δ±0.00V)------- 7MHz
181 -----
4.24V (Δ-0.01V)------- 14MHz
161 ----- 3.23V (Δ-0.02V)------- 18/21MHz
142 ----- 2.27V (Δ+0.02V)------- 24/28MHz
129 ----- 1.60V (Δ±0.00V)------- 50MHz
108 ----- 0.58V (Δ-0.02V)------- 10MHz
96以下 - 0.00V
(---------- )------- 10MHz
設定Nでの出力の差は大きくても±0.02でした。素晴らしいと思います。
入力電圧値は特に気にせずN対出力の関係を重視しています。
なおバンド間でゆとり幅のない50MHzと隣接してる箇所は
以下の通りでした。参考データです。Hi!
(実際使うIC-AT100では50MHzがないので隣接は無しです。)
■10MHzの設定電圧1.20V上限の上下N値と出力電圧
N
OUTPUT 周波数帯
121 ----- 1.23V(Δ+0.03V)------- 50MHz
120 ----- 1.18V (Δ-0.02V)------- 10MHz
■24/28MHzの設定電圧2.00V下限の上下N値と電圧
N
OUTPUT 周波数帯
137 ----- 2.02V (Δ+0.02V)------- 24/28MHz
136 ----- 1.97V (Δ−0.03V)------- 50MHz
後先になりましたが、各バンドの区間電圧範囲(仕様)です。
1.8/1.9MHz (7.00V〜8.00V) 中心 7.50V
3.5MHz (6.00V〜6.50V) 中心 6.25V
7MHz
(5.00V〜5.50V) 中心 5.25V
14MHz (4.00V〜4.50V) 中心 4.25V
18/21MHz (3.00V〜3.50V) 中心 3.25V
24/28MHz (2.00V〜2.50V) 中心 2.25V
50MHz (1.20V〜2.00V) 中心 1.60V
10MHz (0.00V〜1.20V)
中心 0.60V
D/Aコンバーターの分解能が不足するかと思いましたが、全く
問題ない電圧に設定できています。
また、参考回路には記載してありませんが、LPFをOPアンプ出力側に入れて
平滑化してあります。コレはとても重要で、オシロでの出力波形を見ると
リップル的に波形が時々変化がみられます。D/A出力電圧は設定Nに対しての
出力変化は±0.005V以下です。
OPアンプ出力にLPFを入れての電圧変化は大きいときで±0.02Vです。リニアに
倍率がかかるので大きくなっています。ただし、この変化幅電圧は設定区間の
N値巻算ではN≒±1以下と微小です。
上記の変化幅を大きくN±1として見積もりし、実際の7MHzではどうかを
みてみました。検出区間のN値は下記となっています。
下限5.00V N値=197
中心5.25V N値=202
上限5.50V N値=207
中心電圧のN値に対しN±5が7MHz区間検出幅です。
電圧の変動は大きく見積もっての±1カウントですからこれ以上には
なりません。
上記より検出範囲区間でのゆとりNの値は間違いなく±4カウント幅あります。
まだまだ検討することが沢山ありますが今回のテスト回路での実験はD/Aコンバーターを使い目的の電圧設定ができたという点で成功ということにします。
今回の実験でICOMチューナーのバンド設定電圧が準備できたことにして、次はFT-2000DのBAND-DATA出力4BIT(D3,D2,D1,D0)を入力して周波数帯を検出するルーチンをコーディングしてゆきます。簡単なIF文のAND処理でD/Aを既にスケッチしたESP32DevKitCで追加コーディングしてゆく予定です。
つづく?
続きを読む
FT-2000DをICOMチューナーに繋ぐ自動制御その3
(2022/12/11 23:14:31)
OPアンプの電圧回路の入力1〜5Vを0〜10Vになる回路でテストしてきましたが、ESP32DevKitCのポートを使う場合は、出力される電圧は5Vではなく3Vとなるので、出力範囲も1〜3Vだと2Vの範囲内での出力調整となりますが、やはり0−1Vの区間を0V出力として使うのはなにか機能を使っていない様な、気持ち悪いのでやはり0〜3Vを0〜8Vに変換するように回路定数を変更しました。実は定数変更をする前にOPアンプ単体での入力電圧0〜3Vを同じように0〜8Vに変換する回路を組む事で足りるのではないかと思い実験してみましたが、入力0Vの時の出力が完全に0Vにならないオフセットの問題があり断念しました。単電源で回路を作製し、オフセットの端子付きOPアンプで試したのですが、0V入力時、オフセットVRで完全に出力を0.0000Vにすることは出来ませんでした。他対策方法の出力の補正に関しては発生する電圧の0V入力時の出力の電圧をプログラムで、出力から差し引くという補正方法があるらしいのですが、リアルタイムでの対応ではなく手間もかかる上、目的が違うので、単電源のOPアンプでは、簡単には出来ないと判断し、最初の回路の定数変更での0V〜3Vを0V〜8Vに変換する方向で検討し直す事にしています。入力0V時の出力を完全に0.0000Vにすることも可能でしたので、最初の回路をそのまま使うことにしました。
回路定数の変更は下記値で対応できました。
Vcc=13V
R2=470Ω
R6=50kΩ 上記の回路の定数R2とR6を変更すると1〜5Vの入力電圧Vinは0〜5Vにアジャスト
出来るようになります。
実施のESP32DevKitCのD/A出力電圧はD/Aoutputは完全にN =
0で0.0933Vと完全に0Vにはなっていませんが、OPアンプの電圧変換回路の定数変更後は完全に0.0000Vに調整出来る様になり目的の特性にする事ができます。
D/A設定値 : D/Aoutput : Vout
N = 0時 : 0.0933V : 0.0000V
N =
250時 : 3.0463V : 7.5115V
確認時の電圧であり、最終のバンド設定電圧時とは(N値設定)異なっています。
Nの最大は255ですが、ICOMのバンド1.8/1.9MHz時の7.5Vは、仮にN=250でセットできる様に上側にゆとり幅をもたせ、VR2で調整です。勿論
N = 0時の出力0.0000VはVR1でオフセット調整と同じ様に最初に合わせておきます。
一番上の7.5Vをアジャストした後は、他のバンドの電圧となる
D/AのN値を探します。出力が目的のバンドの電圧になるN値を各バンド全部探しD/Aの設定値として記録します。
各バンドの設定電圧となるD/A設定用のN値でのOPアンプ出力は下記となりました。
BAND 検出電圧 : D/A N値 OPアンプ出力
1.8/1.9MHz 7.50V
: N=248 7.4999V
3.5MHz 6.25V :
N=208 6.2577V
7.0MHz 5.25V :
N=174 5.2450V
14.0MHz 4.25V : N=142
4.2518V
18/21MHz 3.25V : N=109 3.2456V
24/28MHz
2.25V : N=77 2.2537V
50MHz 1.60V : N=55 ---------V
10.0MHz 0.60V : N=23 0.6127V
本当のYAESUのBAND-DATAでの順番は下記の対応です。スケッチは各バンド検出時にD/Aに出力させるN値を設定してゆく様にコーディングしてゆきます。
DATA: BAND D/A Set N value
0
:10MHz N=0 (Output 0.0000V)
1 :1.8/1.9MHz N=248
2 :3.5MHz N=208
3 :7.0MHz N=174
4
:10MHz N=23
5
:14MHz N=142
6
:18MHz N=109
7
:21MHz N=109
8
:24MHz N=77
9 :28/29MHz
N=77
---------------------------------------
10 :50MHz N=55
(50MHzは疑似回路のSWが0から9までなので、10はBAND疑似SWで設定できませんので測定しません。スケッチではコーディングして対応する様にしてはあります。)
■試験回路
FT-2000DのBAND-DATA出力D3,D2,D1,D0に対する表示になります。(まだ疑似SWでの実験で、実際のBAND-DATAに繋いではいません。Hi!)
■SW0 BAND-DATA : 0,0,0,0 ; D3,D2,D1,D0
■SW1
BAND-DATA : 0,0,0,1 ; D3,D2,D1,D0
■SW2 BAND-DATA : 0,0,1,0 ; D3,D2,D1,D0
■SW3
BAND-DATA : 0,0,1,1 ; D3,D2,D1,D0
■SW4 BAND-DATA : 0,1,0,0 ; D3,D2,D1,D0
■SW5
BAND-DATA : 0,1,0,1 ; D3,D2,D1,D0
■SW6 BAND-DATA : 0,1,1,0 ; D3,D2,D1,D0
■SW8 BAND-DATA : 1,0,0,0 ; D3,D2,D1,D0
■SW9
BAND-DATA : 1,0,0,1 ; D3,D2,D1,D0
ICOMのチューナーではバンドが2バンドの同じ表示になる設定が数カ所ありますが、BAND-DATA値での対応として表示上で分かるようにMHzを付けて入力されているバンドが識別出来るようにしておきました。
■BAND-DATAが18MHzの場合18.0に単位MHzが付きます。
ACTIVE!
18.0 MHz
21.0
■BAND-DATAが21MHzの場合21.0に単位MHzが付きます。
ACTIVE!
18.0
21.0 MHz
24/28MHzも入力された設定側バンドに単位MHzが付くのは同じです。
あとFT-2000DのBAND-DATA端子には+13Vが①端子に出ていますので、ESP32DevKitC用の+5Vはここからレギュレータで取るように+5Vのレギュレータ回路の追加も行ないます。ステップBYステップで、FT-2000DのBCD接続での動作確認、次にIC-AT100で疑似SWでバンド自動設定確認し、最後に全体での確認をしてゆきたいと思います。
つづく?
FT-2000DをICOMチューナーに繋ぐ自動制御その5
(2022/12/11 23:13:05)
気が向いたので、EAGLE
CADでパターンを作製してみました。今回は抵抗が結構本数あるので、ジャンパー無しでの対応でできそうです。それから今回は基板作製してから、結構回路変更があったりと、急な回路変更等にも対応出来る様に未使用のポートにもピン端子を付けてみました。空き端子を使った機能追加や、ポート変更対応も出来上がった基板にても容易に対応できる様になります。
基板サイズはEAGLE CADでフリーで使用出来るサイズ 100X80mmです。基板はFR4を使います。
■未使用ポート引き出しピンヘッド追加した回路図
四角い枠がピンヘッド端子です。回路図上での引き出しでパターン上に
ランドを作製するためです。パターン上でESP32の下のピンヘッドは
は取り付けできません。引き出しランドとして使用することになります。
それ以外はピンを取り付けします。
■作製パターン(ボトムパターン)
パターンができましたが、切削マシーンを片付けてしまっているので、準備しないといけません。テーブルの上には、先に購入した実験用セットがあり、簡単には動かせません。切削マシーンを置くスペースがありません。少し考えないといけません。どこに設置しましょうか?他愛のない事で悩んでいます。
IC-AT100、AT-150でもレベル用ICに使う8Vのリファレンス電圧が必要でしたが、間に合わせでアジャストタイプのレギュレータを使用していましたが、8Vのレギュレータパーツが入手できましたので、確認してみました。リファレンス用ということでピッタリと8.0Vでないといけないと思っていましたが、レギュレータ自体の出力電圧は計ってみると7.8V台です。不良かと思いましたが仕様を見てみると最小7.7V、最大が8.3Vと結構幅があるのでビックリです。実際交換して使ってみましたが、特に問題は無い様でした。
つづく?
FT-2000DをICOMチューナーに繋ぐ自動制御その6
(2022/12/11 23:12:23)
ICOMのアンテナチューナーの接続端子を確認していて、インターフェース回路上での変更が必要なことが分かりました。内容は、+13Vの電源供給ラインがAC電源供給タイプのIC-AT100は不要で、電源供給必要なAT-150の場合のみFT-2000DのBAND-DATAから供給するという内容です。インターフェース回路上にショートピンヘッド(3P)で対応する様にパターンを修正します。パターン上のピンショートでも、あとから切り替えSWを外付けのどちらでも対応可能です。
■JP30(3P)でAT-150のときのみショートピンで13V供給になります。IC-AT100のときはIC-AT100の内蔵電源供給されているので端子からの13V供給は不要です。3PはオープンでIC-AT100です。
回路図はAT-150時の状態です。
■13Vライン修正パターン箇所
■ボトム全体のパターン(近くの部品のパターンレイアウトを若干修正しています。)
■最終GND
ベタアース処理(Polygon ,Ratsnest処理)
■ポリゴン、Ratsnest処理完了後のボトムパターン
■ポリゴン、Ratsnest処理完了後のボトムパターン
パターンの外周は必ずアースパターンとなるようにパターン作製しています。
パターンを切削する前にICOMのチューナーの電源供給の違いに気がつき、修正できホットしています。
焦らずステップバイステップです。それぞれの全端子の仕様確認も怠ってはいけませんね!
あとの修正はないかと思いますが、もう少し冷静に確認してみます。
問題なければ、切削のマシーン設置の準備です。
つづく?
FT-2000DをICOMチューナーに繋ぐ自動制御その4
(2022/12/11 14:54:50)
FT-2000DのBAND-DATAの4BITデータを使い現在の周波数をESP32DevKitCで判別し対応する周波数帯に対応する電圧を出力するため、更にD/A変換を使いOPアンプでの電圧変換しICOMのチューナーのバンド自動選択用の電圧を得ています。BCDの周波数判別、そしてA/D出力電圧発生の動作確認は特に大した問題もありませんでした。次のステップとしてはチューナーに繫いでの動作確認です。チューナーの回路図をみていて肝心のリファレンス電圧の+8Vの用意をしていない事が分かり急遽、購入してあった可変式の電圧レギュレータを+8Vにアジャストし、確認回路とをIC-AT100に接続し確認してみることにしました。
結果は動作OKです。上手く動作してくれました。BCDコードSWで作製した仮のFT-2000DのBAND-DATAですが、100%動作してくれています。チュナーを運用中、途中で止まったり、バンドが変わったりしないか、同じバンド7MHzに設定したままで放置試験をしています。4、5時間点けっぱなしでしたが、何も起こらずOKの様です。
今も、継続して設定しっぱなしの確認続けています。
上手く動作してくれましたので、現状の回路図をEAGLE CADで纏めました。
'2022/dec/09回路図間違い修正差替
回路図上ではピンヘッドで別々に記載したターミナルとしていますが、実際はまとまりが1つのコネクタになります。
(FT-2000D BAND-DATAの記載のピンヘッドと、チューナー側のAT-100 AT-150の記載のピンヘッド)
AT-100の接続用コネクタは変わった形状をしています。専用コネクタが準備できてないので、配線の引き出し場所とか検討が必要。AT-150はコネクタがあるので問題なし。FT-2000DのBAND-DATA用コネクタもあるので問題なし。
今回作製の回路と各機器はFT-2000Dのバンドデータ様コネクタ1つとチュナー側のコネクタの2つだけでの接続です。回路とチュナーの電源供給はFT-2000Dからでの構想です。電流が足りるかも実際の接続で確認します。
'2022/dec/09回路図間違い修正差替
パターンの作製は後で行なう予定でいます。
毎回思いますが、回路部品も少なく、とてもシンプルになっています、8ピンのOPアンプ回路とコネクタと電源用のレギュレータが目立つ位です。ソフトウェアのウェイトがかなりしめていると言えます。スケッチ自体に時間がかかっていますから実際そうです。
インターフェース回路はESP32DevKitCでのD/A出力とOPアンプでの電圧変換回路構成です。使ったD/A出力はArduinoNano,UNOにはありませんから、D/A出力機能のあるESP32DevKitCはいろんな事に対応できる素晴らしいCPUだと思います。Hi!
つづく?
USBアイソレーター高周波回り込み対策
(2022/11/26 20:30:13)
アマチュア無線の7MHzの周波数帯での高周波の回り込みによるパソコンのアプリの異常動作が現在あり過去色々と対策を行なってきましたが、完全な解決策となったものはまだありません。パッチンコアは確かに高い周波数帯では100%と言えるほと効果があり問題はありません。ただし、すべてのアマチュアバンドの周波数帯で効果があるとは、やはり言えない状態です。低い周波数ほど減衰が取れない事が大きな理由で、私の場合は、7MHzで四苦八苦しておりました。減衰の大きな最近対策導入したコモンモード用のラインフィルターでかなり効果がありましたが、完全に回り込みがなくなったわけではなく、たまにでたりがあります。HAMRADIO
DELUXEアプリでパソコンと2台の無線機をシンクロ動作させて使っています。シンクロ動作はシリアル通信用インターフェースを使い2台の無線機をシリアル通信制御するのですが、片方の無線機に繋がったアプリが時折通信が寸断するのが問題です。
今回はPCのノイズ対策等で効果があると言うUSBアイソレーターなるものを2台のシリアル通信インタフェースに入れ試してみる為、ネットで注文しました。なお、ここに行き着くまでに、USBインタフェースを繋がない状態ではPCは何も問題が起きないと、確認できています。シリアルインターフェースを通してのPCへの回り込みというところまでルート(回り込み原因元)が確認出来ていましたので、少し掛けでもありますが若干の期待をして2個注文してみました。注文はアマゾンでしましたが、配送は中華からでした。
■注文したUSBアイソレーター
■中華から届いた状態で、例のごとく部品用のパッケージで、エアー
■確認開始
最初は、USBアイソレータがシリアル通信速度に対して使えるかを、ハムログ
に繫いで単体動作確認です。FT-2000Dの通信速度で問題なければ、FT-1000MP
はかなり通信速度が遅いので調べるまでもなく動く想定です。結果は、FT-2000D
では今までと同じ様にハムログで正常に周波数読み取りをしてくれました。
FT-1000MPは動く想定で次の確認です。次にUSBアイソレータをFT-1000MPの
シリアルインターフェースに挿してUSBポートへ繫いでHAMRADIO DELUXEでの
シンクロ動作確認です。先ずは電波の回り込みの確認の前の今まで通り正常動作
するかの確認が最初です。Hi!
■拡張USB
ポートに2台の無線機のシリアルインターフェースがUSBアイソレータ
を挿して繋いだ状態です。白色のUSBケーブルはキーボード用です。
USBポート接続してます。
■FT-2000D側のシリアルインターフェースもUSBアイソレーターを挿して
USBポートに繋ぎます。
回り込み確認前のHAMRADIO DELUXEでのシンクロ通信もハムログもすべて
いままで通り動作してくれました。まずは一安心です。
丁度、風が強くタワーを伸ばせないアンテナが低い状態で、7MHzでアイソレ
ーター効果があるのか確認をしてみることにしました。SWRが1.7ぐらいある
アンテナを繫いでですから条件は悪く、インターフェアンスが起きやすい状態
です。今までは、アンテナが低い状態では、回り込みでFT-2000Dの送信側の
シリアル通信アプリがフリーズして止まってしまってましたが、USBアイソ
レータを両方のシリアルインターフェースに挿入して使用した状態では、全く
問題無しでシンクロ動作してくれました。嬉しい限りです。先ずは小さくガッツ
ポーズです。次はより条件の厳しいキャリア連続送信での確認をします。何の
問題もなくアプリは正常動作継続してくれました。
効果がでた雄一の理由として、回り込みの箇所が特定出来ていた事と、アイソ
レーターでの完全な回り込み箇所の高周波を分離する仕様通りの効果が機能した
事だと思われます。
これで、シリアル通信からの回り込みが完全に止まり解決ということになりました。
安いアイソレーターなので、当初、ダメかもと思っていましたが、アイソレーター
としてしっかり動作してくれました。通信インタフェースでのアプリが止まる様
な回り込みの問題がある方は、パッチンコアも使いながら対策として是非USB
アイソレータを入れてインタフェースとPCを繋ぎ分離して使う方法を試してみて
もらいたいですね。100%解決できると思います。コレほどまでに効果があるとは
USBアイソレーターに驚きました。サイズもとても小さなアイソレーターICなの
で高周波は筒抜けかと思っていましたが、とんでもないです。しっかり分離して
くれています。
いま、FT-2000Dのバンド出力を使ってアイコムのアンテナチューナーを自動で
バンド切り替えする回路を検討していますが、各バンドを識別し、バンド毎に
A/D出力を出しOPアンプで電圧変換しICOMのバンド制御電圧を作るのですが
この出力へのノイズ重畳が少し気になっています。このノイズがパソコンの
USBポートからきていることが確認できています。パソコンのノイズがある為に
折角A/D出力で電圧を調整しても、別の電源を繋いだ実際の動作時の電圧値に
違いが出ます。ノイズありでの調整では意味がないということです。ここで
USBアイソレータをつかって見ることで、制御信号のみ通しノイズは分離し通さ
ないという効果があるかを確認してみようと思っています。
(ノイズレベルは実用上は問題ないレベルかもしれません。電圧に違いが出る
ことが何かスッキリしません。私の気質、気持ちの問題なのかもしれませんが。!)
そういえば、思い当たる節として時折コンパイルエラーが起きていたことがあり
ます。USBのノイズが影響していた可能性も否めませんね。やはりオシロスコープ
での信号、出力波形確認は必要です。Arduinoのシリアル通信はこんなノイズが
重畳したUSB電源でもコンパイルしてくれてるのはたまたま上手く、いっている
だけなのかもしれません。
使いみちは結構あるので、USBアイソレータは予備で2個位追加購入しておこう
かと思います。
つづく?
MS-9160 測定システムのオークション購入
(2022/11/13 21:06:26)
日頃から、Arduinoの実験回路をブレッドボードにて組み上げてゆき、最後にレギュレータでの電源回路も組み入れAC-DCアダプターを繫いでテストを行なっていましたが、案外と電源回路をわざわざ作るという事が結構な手間となっていました。また各部の電圧はデジタルマルチメータ、周波数は周波数カウンタをいちいち用意設置しての測定を行なっていました。丁度このような測定システムが一式まとまった装置がないかと思いオークションを探していた所、目的のシステムが出品されていましたので、即参戦しました。ところが、このようなシステムを必要としている方は誰もいなく、難なく無事落札できました。
■MS−9160フロントパネルサイド
■MS-9160バックサイド
■付属品
■取扱説明書
早速届いてテーブルの上に設置しました。
このUNIVERSAL
SYSTEMは発振器(ジェネレータ)、周波数カウンター、デジタルマルチメータ、電源が1つに纏められたオールインワンの測定システムになります。
ジェネレータは矩形波、三角波、サイン波、TTLパルスが選べ、周波数としては1Hz〜10MHzまでの範囲で発生可能です。また波形の形も色々とコントロールできるすぐれた機能もついています。
内蔵されたカウンターは1Hzから2.7GHzまでをACH,BCHの2つのチャンネルで対応していて周波数範囲も広く十分実用的に計測出来るものです。3BANDハンディ無線器の周波数の50MHz,144MHz,430MHzを計測してみましたが精度良く表示してくれました。
マルチメータも実験確認用としても十分使用できるレンジ範囲です。容量とインダクタンスも測定出来ます。またRS-232Cのシリアルインターフェースコネクタもありシリアル通信でのコントロールも対応している様です。
電源は、固定で+5V(2A) 、+15V(1A)、可変で0〜30V(3A)でとても実験にはうれしい電圧端子が用意済みです。
ネットで調べた所、全部の回路図もありました。(723を使った電源回路)
■5V-2A回路図
■15V-1A回路図
■0-30V-3A回路図
先ずは、電源を入れて実際にジェネレータでサイン波を発生させてオシロスコープに表示させて周波数の精度を見てみました。アナログダイヤルなので結構ズレがあるのかと思いましたが、目盛り精度はほどほどにいいようです。先ずは電源を入れっぱなしにして各測定器で問題がないかを確認してみました。
一日中入れっぱなしです。一日では特になにもありませんでした。ところが数日して、周波数カウンターが電源を入れてもセグメントの点灯がありません。しかも少し焦げ臭い匂いがしました。ケースのネジを外して中身を確認しました。どうも電源の入り口のチョークインダクタンスの一つが焼焦げていました。少し形状からすると耐電力が足りない超小型のインダクタンスを使っていて電流が増加してずっと流れている時に熱を出して切れた様です。実際セグメントは結構点灯させていたので、流れる電流が多かったのでしょう。早速他のところにも同じサイズのインダクタンスが使われていましたので、手持ちの少し耐電力のあるインダクタンスに交換し復帰しました。
■左が交換取り付けしたインダクタンス、右が焦げたインダクタンス
■焦げたL2インダクタンスをカットした基板
(PCBは外さず、そのままでカット)
■新しいインダクタンスを取り付けた基板
焦げ焼けたインダクタンスを新しいインダクタンスに交換して元通り
にカウンターは復帰しました。セグメントが点灯している状態での
インダクタンスの熱があるか触って確認しましたが、熱は全く感じら
れません。以上でOKとしてケースを元に戻し修理完了です。
思うに、全部のセグメントLEDが点灯する状態時の電流には耐えられ
ない部品の為、焦げたのだと思われます。
(設計ミスだったと思われます。)
数日数時間点けっぱなしでも特に問題はない状態です。ところが今度
はマルチメータの電源が入らなくなってしまいました。またケースを
開けないといけないかと思ったのですが、どうもマルチメータは積層
9Vの乾電池動作の様です。後ろのボックスを外して電池を交換です。
引っ張り出して他のマルチメータで電圧を計ったら2.7Vしかありませ
んでした。これを新品の9V積層電池に交換して、難なく電源が入りました。
(中華製で2019年の8月まで有効のスタンプがありました。)
届いて良く動作してたと思います。おそらく5年位は使われていたの
ではないかと思われます。
問題な点が全部出尽くした感じなので、これから実験用として便利に
使ってゆきたいと思います。
念願の新しいテスト用測定システムが運用開始となりました。
つづく?
MODEL 1200FXローテーターその30
(2022/11/10 2:10:50)
ローテーターの停止方法をPMW方式を使って低速化設定する事で、いったりきたりの収束動作はなくなりました。低速動作は高速回転から低速にすることで惰性回転で減速しながら停止の動作です。設定角度を±1よりオーバーランしても単独の低速回転からのスタートでは回転しません。うまい具合になっています。
以下実際の動作をESP32DevKitCサーバーとESP32DevKitCクライアント、そしてクライアントとしてのスマフォでの動作確認をしてみました。角度の送信はスマフォからもESP32DevKitCクライアントのどちらでも可能です。今回はESP32DevKitCクライアントはESP32DevKitCサーバーからの現在角度と設定角度を受信します。ESP32DevKitCサーバーはスマフォクライアントからの設定角度を受けて1200FXローテーターを回転させています。なお、家庭に設定のルーターのWiFiは使っていません。ESP32DevKitCの個人設定サーバーWiFiでのUDP通信で行なっています。スマフォも個人サーバーに繫いでのUDP通信です。
(ESP32DevKitCサーバーに個人で設定したSSIDと任意パスワードで自分のサーバーが出来上がります。これに繫いでます。)
■スマフォからの0°から360°のUDP通信データ送信でのローテーターのCW方向回転です。
左側がクライアント、右側がサーバーです。サーバーはローテーター制御しています。
■スマフォからの360°から0°のUDP通信データ送信でのローテーターCCW方向回転です。
スマフォからでもESP32DevKitCクライアントからでもローテーターをコントロールすることが出来、現在の角度もクライアント側で表示しますのでとても便利になりました。スマフォでも現在の角度データを受け取り表示しますがスマフォアプリではデータ処理が1バイトのデータ表示のみで値255までは現在角度を表示しますが、値256以上のデータでは正式な角度表示はなりません。ESP32DevKitCでの行なった1バイト以上の時の数値処理が必要です。
(スマフォでのUDPデータの基本送出は1バイトですから、温度表示は−側が少し厄介で工夫がいると思いますが0°から100°までは問題なくスマフォで受取正常に表示しますね。角度は残念ながら0°から255°までということです。256°から360°は正常に表示されません。)
角度設定して、スマフォでも正常な現在角度の表示になるように0から999の3桁までの数値がそのまま表示出来るデコード処理付きスマフォアプリを作っていただくと実用なりますね。どなたか開発していただけたら嬉しいですね!だれかアンドロイドスマフォ用に開発してくれませんでしょうか?
スマフォの携帯性の良さはやはり群を抜いてますから、スマフォが使えると超便利でありがたいですが!
そういえば、スマフォアプリも開発出来るQtなんかもありましたね?
NC制御の切削用アプリのCandleはQtで開発されたアプリでしたが、Qt上だけでしか当時動かす事が出来ませんでした。コレをLinuX上のアイコンで動作させる為、Qtのコンパイルでお世話になったことをふと思い出しました。
つづく?
execution time : 0.098 sec