jl7gmnのblog

yahooブログから移行してきました。アマチュア無線を中心としたブログです。

測定器

愛知タワー風速値表示追加その3

愛知タワー付属の風速計へつながっているインプット情報のカウント入力、リセット入力、電源、COMMONの各端子からCMOS IC 4024の7Stage Binary Ripple Counterへのカウント入力と4024の論理にあわせる為、リセット信号は1石のスィッチングトランジスタの反転回路を通して繋ぎます。回路図とパターン作製ができたので、このバイナリー出力の7ビットをESP32DevKitCに繫ぐインターフェース部を別基板で作製するための回路図を作製しました。スケッチは回路図での端子を決めてから検討してゆく事になります。単に入力の7ビットバイナリーデータのデコードです。単純に必要なものは入力の7ビットを繋ぐポート、電源、1.8inch TFT液晶ディスプレーを繋ぐポートがあれば事足ります。今は使いませんが、余分なシリアルポート端子も回路には入れてあります。

1.8 inch TFT液晶ディスプレーは、今まで使った実績がある物なので、過去の他の実績のある回路と同じ端子接続で使うことができます。スケッチ上のTFT設定は過去使ったものがそのまま使える利点があります。(検討が不要)実は回路図のTFT液晶部分や電源、シリアル端子部は前の他の回路をそのままそっくり流用です。使わないところを消して、必要な箇所を部品を置いて繫いでゆくやり方です。
AnemometerValueDisplay

カウンターからの7ビットの出力を受ける入力ポートも、過去同じ様な用途で使った実績がありますから、安心してスケッチできます。Hi!
回路図も作製できたので、ついでにパターンも作製してしまいました。回路が単純な引き回しなので、100X80mm基板は、スカスカです。

AnemometerValueDisplayPCB

今回は2枚基板の接続の合理的な端子の接続は全く考慮していません。基板を2階建てにした設計も必要かもしれません。今は検討段階での試作です。

さてスケッチを開始しましょうか?

つづく?

愛知タワー風速値表示追加その2

風速値表示回路のパターン作製でのジャンパー処理が必要でしたので、回路図を修正し若干のパターン修正を行ないました。当初LEDはピンヘッドジャックに差す予定でパターンを作製していましたが、ジャックを省き、確認時使うパターンということで入れてあります。確認時のみ使うだけで良く、風速値表示はESP32DevKitCに繋ぐTFTカラー液晶で数値として表示されるため特に問題がなければ部品としては取り付けしない予定です。

修正回路図:どうしても繋がらない箇所をジャンパーワイヤーを使いパターン
を修正しました。
修正パターン

※ちょっとしたeagle操作!
当初CMOSの電源とグランドの接続パターンがピン配線できなかったのですが、ちゃんと機能がありました。今までは、専用のICは使わないでソケットで配線していました。ないわけがないのはわかっていましたが、探すのが面倒でソケットで足りていました。Hi!知ってしまえば、やはり専用のICを使うと便利です。(ピンを調べなくても、回路図に出てきます。)
invoke
invokeでICをクリックして電源を選択すると回路図に表示されランドとしてパターン配線出来る様になりました。

実際に修正した最終ボトムパターンです。100X80mmの基板サイズに十分入ります。
修正パターンボトム

切削待ち基板が既に1枚あるので、コレを合わせて2枚になりました。
EAGLE CADは最初のparts選びが一番最初に悩むところかと思います。習うより慣れろという言葉が本当に当てはまると思います。部品のパーツも秋月の部品もありますからとても助かります。ESP32もあります。回路図でよく使うGND ,+12Vとかレギュレータ、コンデンサ、抵抗、インダクタンス、ピンヘッド、(ピンジャック代用)取り付け穴、LED、各ICソケット、ジャンパー、トランジスタ、ダイオード、基本的なパーツを押さえて於けば、一通り回路図がかけると思います。片面基板が対象ですので、EAGLE CAD では回路図ができてしまえば、後は部品を選んで基板上に置いて、ボトムパターンにてランド間を繫いでゆく手順です。特に最初によく使うパターン太さとドリル穴を選んで、一覧にパターン幅がなければ、手入力で数値を入れます。私はよく2mm幅を使いますが、この2mmは手入力になります。パターンをICの中を通したりする時はパターン幅を1.5mm幅とか、1mm幅とかに変えてます。ドリル穴径はディスクリートパーツリードが入る0.9Φにしています。ICソケットも0.9Φでokです。これらを設定してからパタ−ン化してゆきます。片面基板は、なれるとサッサと回路図を横にして、繫いでゆき、行き詰まったところで、ジャンパーを使います。全配線分が終了したら、微調整を行なう段取りです。(パターンの太さや、ランド補強、基板取り付け穴追加等)調整が終わったら、ベターアース化でパターン設計は終了です。後は切削マシーン用にガーバーデータ(パターン用とドリル用、切り抜き用)を作製です。コレぐらいの回路だと1日かからないで簡単に出来る様になります。当面はDIPタイプのICとディスクリートL,C,Rでいいのではないかと思っています。すすんでいる人はICもSOPとかチップL,C,Rで、基板業者にたのんでいますね。綺麗に出来上がるようですね。作ることが好きでやっていますので、簡単なのが私には向いていると思っています。今の所はブレッドボードでの実験で使った部品をまるまるそのまま使うやり方で行なっています。超アナログですが、一番楽しい所、醍醐味は回路を考えボードで確認している時です。Hi!

つづく?

愛知タワー風速値表示追加その1

タワーには風速カウンター表示部がユニットでついていますが、他のところへカウンターを新たに追加したくて、久々にゲート回路を組んでみる事にしました。タワーのUPボタン、DOWNボタン、停止ボタンの高さ表示ユニット近くにおいてある風速値のカウンターです。同じ仕様の物を購入するのが一番手っ取り早いですが、調べて見ると、パルスカウントをするだけなので、ゲートICを選べばできそうな内容です。元のカウンター部分には一切手を入れないでのパルス信号と電源だけパラレルに繋ぐやり方です。本来ならば元々のカウンターの接続線を延長して行う方法が別の場所へ設置する方法もありますが、高さ表示ユニット部はそのままにしておきたいのです。こういう理由からいま付いているカウンターと同じ動作をするカウント表示回路を作製します。

まず最初に調べたのは、信号線2本です。電源は単に電圧+12VとGNDなので特に問題ありません。風速回転のパルス信号線の動作です。
信号線は回転している風速部から回転に合わせて矩形パルスが来ています。正論理信号です。
もう一つの信号線はタイマー信号線です。Nomally+で10secで”L”信号がパルス状に来ています。
上記の信号線より、10秒間のタイマー”H"状態の時に正パルス信号をカウントする仕様です。ここで考えなければいけない事は、カウントを幾つまでカウント出来る様にするかを決めなければなりません。コレはタワーの下に付いているコントロールボックスに、アラームを鳴らしタワーをダウンさせる回転数を設置するユニットがあります。私の設定は経験上かなりの風が吹いているよりも前の風速値38にしてあります。早めにタワーを下げるためです。この38という設定値を十分に範囲内カウントするには6ビットのカウンターで事足りますが、ゲートICのカウンターから見るとCMOS 4024で対応できそうです。
カウントは0から127までです。実績的にカウント表示で今まで100を超えたことはありませんのでコレにしました。他にも1セグメント表示回路も付いている4026もありましたが、セグメント表示でなくTFT液晶ディスプレーにしたいので使いません。(また、2桁だと2個もゲートが必要です。Hi!)
インターフェースとなる回路図です。
anemometer-circuit

表示ユニット端子に繋がっている線を5本繋ぎます。(電源とGND,タイマー信号線、パルス信号線、COMMON)
テストで使用したOSCは矩形波ですが±信号でしたので、パルス入力にはダイオードをいれてあります。
実際の接続時は信号を繫いでみて、はずすか確認します。タイマー信号の”L”パルスはプッシュSWでGNDに落とす様にしてシミュレーションしています。4024のリセットは”H"パルスでかかるので信号と同じ動作で”L”となる様にタクトSWでGNDに落とした時にSWトランジスタで反転させてリセット信号としています。

カウンターがOSCの低周波矩形波信号周波数で表示カウントアップしていくだけの動画です。
バイナリー出力です。(各LED出力7ポートの重みは、それぞれ1,2,4,8,16,32,64です。)




回路図にもあるように信号出力はバイナリーの7ポート出力です。信号が出ているのが分かるように発光ダイオードを付けています。パルス発生間隔が風速によって違う場合と同じようにOSCで矩形波の周波数を1Hzから7Hzぐらいの間で上げ下げすると実際の風速と同じ様にゆらぎカウントしてくれています。
またタイマーはタクトSWでGNDレベルに適当におおよそ10sec過ぎた当たりで疑似パルスとしてチョンと押すと全出力が消えリセットがかかった後にまた1からカウント始めます。
目で出力信号が見える様にパルスカウンター出力には、発光LEDを繋ぐため4050のバッファーを入れています。今回は単にゲートICのパルスカウントを準備し、インターフェースを付けただけです。

この後の予定としては、ソフトウェア設計が大半となります。
7ビットのバイナリーの信号出力分の入力ポートを用意して、スケッチで全ポートを読み取りし、カウント値を液晶に表示する様にするスケッチです。ArduinoNanoかESP32DevKitCのどちらかをつかいたいと思います。現在は信号線のワイヤーが5本繋がり表示する仕様で進めていますが、完成後はUDPを使ったサーバー化をおこない、風速値を別のESP32DevKitCに表示できる展開にしてクライアントのWiFi信号が届く範囲でUDP通信での風速値をリアルタイム表示させる拡張も考えたいと思います。となるとやはりESP32DevKitCを使わないとできないですね!

つづく?

ESP32DevKitCでの周波数カウンタその1

ある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);

ほか,修正箇所として、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();

 #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 ();  //発振器の周波数をリセットする
  }
}

***********************************************
上記のスケッチでは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

上記のカウントした周波数の誤差は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です)。

わたしのコメントです。★手持ちのLCDのボードアドレス:0x27

しかし、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は色々できて、やはりいいですね。

つづく?

MS-9160 測定システムのオークション購入

日頃から、Arduinoの実験回路をブレッドボードにて組み上げてゆき、最後にレギュレータでの電源回路も組み入れAC-DCアダプターを繫いでテストを行なっていましたが、案外と電源回路をわざわざ作るという事が結構な手間となっていました。また各部の電圧はデジタルマルチメータ、周波数は周波数カウンタをいちいち用意設置しての測定を行なっていました。丁度このような測定システムが一式まとまった装置がないかと思いオークションを探していた所、目的のシステムが出品されていましたので、即参戦しました。ところが、このようなシステムを必要としている方は誰もいなく、難なく無事落札できました。

■MS−9160フロントパネルサイド
MS-9160-FRONT

■MS-9160バックサイド
MS-9160-BACK
■付属品
MS-9160付属品

■取扱説明書
MS-9160-OP-MANUAL

早速届いてテーブルの上に設置しました。
この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回路図

5V-2A

■15V-1A回路図
15V-1A

■0-30V-3A回路図
0-30V-3A

先ずは、電源を入れて実際にジェネレータでサイン波を発生させてオシロスコープに表示させて周波数の精度を見てみました。アナログダイヤルなので結構ズレがあるのかと思いましたが、目盛り精度はほどほどにいいようです。先ずは電源を入れっぱなしにして各測定器で問題がないかを確認してみました。
一日中入れっぱなしです。一日では特になにもありませんでした。ところが数日して、周波数カウンターが電源を入れてもセグメントの点灯がありません。しかも少し焦げ臭い匂いがしました。ケースのネジを外して中身を確認しました。どうも電源の入り口のチョークインダクタンスの一つが焼焦げていました。少し形状からすると耐電力が足りない超小型のインダクタンスを使っていて電流が増加してずっと流れている時に熱を出して切れた様です。実際セグメントは結構点灯させていたので、流れる電流が多かったのでしょう。早速他のところにも同じサイズのインダクタンスが使われていましたので、手持ちの少し耐電力のあるインダクタンスに交換し復帰しました。

■左が交換取り付けしたインダクタンス、右が焦げたインダクタンス

交換インダクタンス

■焦げたL2インダクタンスをカットした基板
(PCBは外さず、そのままでカット)
カウンターインダクタンス

■新しいインダクタンスを取り付けた基板
カウンター交換インダクタンス

焦げ焼けたインダクタンスを新しいインダクタンスに交換して元通り
にカウンターは復帰しました。セグメントが点灯している状態での
インダクタンスの熱があるか触って確認しましたが、熱は全く感じら
れません。以上でOKとしてケースを元に戻し修理完了です。
思うに、全部のセグメントLEDが点灯する状態時の電流には耐えられ
ない部品の為、焦げたのだと思われます。
(設計ミスだったと思われます。)
数日数時間点けっぱなしでも特に問題はない状態です。ところが今度
はマルチメータの電源が入らなくなってしまいました。またケースを
開けないといけないかと思ったのですが、どうもマルチメータは積層
9Vの乾電池動作の様です。後ろのボックスを外して電池を交換です。
引っ張り出して他のマルチメータで電圧を計ったら2.7Vしかありませ
んでした。これを新品の9V積層電池に交換して、難なく電源が入りました。
(中華製で2019年の8月まで有効のスタンプがありました。)
届いて良く動作してたと思います。おそらく5年位は使われていたの
ではないかと思われます。
問題な点が全部出尽くした感じなので、これから実験用として便利に
使ってゆきたいと思います。
念願の新しいテスト用測定システムが運用開始となりました。

つづく?


アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

QRコード
QRコード
アーカイブ
  • ライブドアブログ