google-site-verification: google3bd66dd162ef54c7.html

Arduinoで作るパルスジェネレーターの改良(ソフト入れ替え)

 前回の記事でvabenecosi さんが作られた高精度版のパルスジェネレーターのソフトの動作確認が完了しましたが、今回はこれを以前私が作ったハードに組み込みます。

 まずは回路図から、

▼高精度版パルスジェネレーターの回路図(クリックで別窓に拡大)
Arduinoで作ったパルスジェネレーターの回路図
 これは、vabenecosi さんが 簡易パルスジェネレータの製作(ハード編) で公開されている修正内容を私の回路図に反映させたものです。(水魚堂さんのBsch3V用のファイルも置いておきます。回路図(bsch3v用ファイル)

【変更点】
 1) Timer1を使うために、出力ピンとロータリーエンコーダーのピンアサインを変更
 2) 周波数調整用にTC1追加、C3容量変更(22→10pF)
 3) R6、C7追加

▼基板
基板
 トリマコンデンサの調整ネジがGND側になるように取り付けます。

▼配線面
配線面
 青色の線が今回修正した部分です。

▼基板を本体へ取り付け
取付完了
 ファームはv4r7を入れました。

▼周波数調整穴
周波数調整穴
 ケースの底に穴を開けてトリマコンデンサが調整できるようにしました。freq.ADJ.と書いておくと、なんだかかっこいいです。

 なお、トリマの調整範囲を調べると、パルス幅100μsに設定した状態で下記の結果でした。
 TC1最大 : 100.0008μs ( +8ppm)
 TC1最小 : 99.9898μs ( -102ppm)
 調整可能な範囲がマイナス気味なので、C3の容量をもう少し大きくしておいた方が良かったかも知れません。なおこの結果は私が使った部品と配線方法に強く依存しているはずなので、参考程度にお考え下さい。また、前の記事で「あちゃんでいい」のを使って大きな誤差が出ていましたが、その時とは違う水晶発振子を使っています。

▼精度確認の様子
周波数微調整と精度確認
 パルス幅10msに設定してユニバーサルカウンタで精度を確認している様子です。 

 測定に使ったユニバーサルカウンタ(アドバンテスト TR5822)は上に乗っているルビジウムオシレーターで校正しています。またこのルビジウムはGPSと比較して誤差を補正しているので測定の確度は大丈夫だと思います。

◆まとめ
 以前私が作った物は、ジッタが大きくてパルスジェネレーターとしてははなはだ頼りない物だったのですが、今回 vabenecosi さんが作られたソフトに入れ替えることで、見違えるように高精度のパルスジェネレーターに変身しました。すばらしいソフトを公開してくださっている vabenecosi さんに感謝します。

 改良版のソフトを使うことでパルスの周波数は500kHzまで出せるようになりました。このあたりの周波数の信号が出せると、受信機のマーカーとして使うことが出来ます。ちなみに旧ソフトでは12.5kHzが限界、しかもジッタまみれです。
 出力端子にアンテナ代わりにミノムシクリップの線でもつないでおいて、受信機で受信すれば正確な周波数間隔でキャリアを確認出来て面白いです。変調かけるともっと面白そうですが、遊びすぎでしょうね。

Arduinoで作るパルスジェネレーターの高精度化ソフト

 アキバ通いと旅のサイトの vabenecosi さんが、以前私が作ったパルスジェネレーターの高精度版のソフトを作られました。

▼以前作ったパルスジェネレーター
以前作ったArduinoで動くパルスジェネレーター

 高精度版ソフトに関する vabenecosi さんの記事はいくつかに別れていますが、下記URLとその周辺の記事で詳しく解説されています。
 最初の記事はこちら→ 簡易パルスジェネレータの製作(速報版)
 ソフト解説がこちら→ 簡易パルスジェネレータの製作(ソフト編)

 詳しくは vabenecosi さんの記事を参照していただくとして、改良のポイントとしては、
 私のプログラムではタイマー割り込みのキャッチボールでパルスを発生させていたのに対し、vabenecosi さんのプログラムではCPUに内蔵されているタイマー (timer1) でパルスを発生させています。

 私のやり方では、タイマー割り込みの処理時間がオーバーヘッドになるため、周期1ms以下では誤差が目立ってきます。またArduinoの環境の制約から、時間の粒度が4μsと粗いため最小パルス幅は40μsまでしか設定できませんでした。一方で、vebenecosi さんのプログラムではハードウェアタイマーを使っているので、小さなパルス幅まで正確なタイミングでパルスの発生が可能になっています。

 ということで、公開されているプログラムを動かしてみました。

▼まずは Arduino UNOで動かしてみた
Arduino UNO でテスト
 上は液晶シールドで、その下にArduino UNO があります。

 この状態でとりあえずソフトのテストは出来ます。でも、Arduino UNO のクロックオシレーターはセラロックなので周波数精度が悪く、ユニバーサルカウンタでパルスを測定しても中途半端な値が出て気持ち悪いです。

 そこで、水晶オシレーターで動く「あちゃんでいいの」で動くように組み替えました。

▼あちゃんでいいのでテスト
あちゃんでいいのでテスト
 現時点で3種類のファームが公開されているので、それぞれ3つのCPUに焼いてテストしているところです。

▼周波数カウンタの値と比較
周波数精度の確認
 この写真はパルス周期 100μsに設定した状態です。ユニバーサルカウンタの測定結果は、99.9849μsなので、誤差は0.015%しかありません。私の作ったプログラムでは誤差が0.8%もあったので、すばらしく改善されています。ちなみに、この誤差はあちゃんでいいのの基板の水晶の周波数精度が原因です。
 それと、ユニバーサルカウンタの値は1LSBがちらちら」と変化するだけなので品質の高い波形が出ていると思います。ちなみに、私が作った割込み方式だと、下3桁くらいは値がフラフラしていました。

◆まとめ
 いろいろ条件を変えて試してみましたが、素晴らしい精度でパルスが出ていることが確認出来ました。ということで、この記事の最初の写真の私のパルスジェネレーターのプログラムは、vabenecosi さんの書かれたものに入れ替える予定です。すばらしいプログラムを書いてくださったvabenecosi さんに感謝します。

 あと、ソフトは v3 v4 v5 の3種類が公開されていますが、私はv4系で行こうかと思います。理由はvabenecosi さんのブログに書くのが正しい作法かと。

 それとソフトの入れ替えのためにはハードの配線も少し変更しないといけません。せっかく精度の高いパルスが出せるので、周波数を微調整出来るように、トリマを追加するのも悪くないかなと思います。このあたりは進展があったらまた記事で紹介したいと思います。

Timer1とFlexiTimer2を使ったバーストパルス発生の実験

 Arduinoを使ったパルスジェネレーターを最近作りましたが、まだまだメモリーに余裕があります。これを遊ばせておくのはもったいないので、もう少し機能を追加したいと思います。

 機能追加の候補としては、バーストパルス発生、サーボテスト信号発生、ストロボスコープ信号の発生です。

 このうちで厄介そうなのはバーストパルスの発生です。現在のパルスジェネレーターは、パルスのONとOFFの時間をTimer1割り込みの値を交互に切り替えることで、タイミングを作っています。(下図参照)

▼パルスの発生原理
ノーマルパルス
 この方法は単純で判り易いのですが、毎回タイマーの設定をやり直さないといけないのでオーバーヘッドが発生するのが難点です。

 この方法のままでバーストパルスを発生させると、オーバーヘッドが累積するため大きな誤差になることが予想されます。この問題を解決するために、もう一つ別のタイマー割り込みを使うことにします。

▼タイマー割り込みを二つ使ったバーストパルスの発生
バーストパルス
 この図のように、バーストの発生周期はFlexiTimer2で、バーストそのものの周期はTimer1で発生させてやれば、タイミング誤差の少ないパルス発生が出来るはずです。

 実はこれをやりたくてFlexiTimer2の使い方を調べていたのですが、制約条件はいろいろあるものの、なんとか思い通りに動かせるようになりました。そこで、早速Timer1と組み合わせてバーストパルスの発生のテストを行ってみました。動作の原理は、上の図の通りです。

▼バーストパルス発生のテストプログラム
/* FlexiTimer2とTimer1の同時使用テスト
* インターバルはFlexiTimer2で、バーストのON/OFF時間はTimerOneで発生
* 2016/3/28 ラジオペンチ
*/

#include <FlexiTimer2.h>
#include <TimerOne.h>
#include <LiquidCrystal.h>

#define led_pin 13

volatile int burstN;
volatile boolean sigFlag;

unsigned long MI; // メインインターバル
unsigned long BI; // バーストインターバル(周期の半分の値をセット
int BPN; // バーストパルス数

void setup() {
pinMode(led_pin, OUTPUT);
pinMode(14, OUTPUT);
MI = 50; // 50*60μs= 3ms
BI = 30;
BPN = 10;
IntervalSet(MI);
}

void loop() {
}

void IntervalSet(unsigned long t) { // メインインターバル設定
FlexiTimer2::stop();
FlexiTimer2::set(t, 0.00006, IRQ_FT2); // 注:40usだとジッタが大きいかも
FlexiTimer2::start();
}

void IRQ_FT2() { // FlexiTimer2の割込み処理
sigFlag = false; // 開始位相はネガ
burstN = BPN; // バーストパルス数設定
Timer1.initialize(BI); // Timer1にバーストインターバルセット
digitalWrite(14, HIGH); // バースト同期パルス発生
Timer1.attachInterrupt(IRQ_timer1); // Timer1割込み開始
digitalWrite(14, LOW);
}

void IRQ_timer1() { // TimerOneの割込み処理
sigFlag = ! sigFlag; // 極性反転して
digitalWrite(13, sigFlag); // ポートへ出力
if (sigFlag == false) { // LOWになっていた場合は
burstN--; // カウンタをデクリメント
if (burstN == 0) {
Timer1.stop(); // Timer1割込み停止
}
}
}
3ms周期で、10発のバーストパルス(デユーテーイ50%、周期60μs)を発生させるプログラムになっています。

▼波形
バースト波形
 横軸は0.5ms/div. 波形の上はバーストパルスで、下は同期信号です。バースト周期3msで10発のパルスが発生しています。

 ということで、何とかバーストパルスが発生できるようになりました。

 記事の最初に書いたサーボテスト信号などは簡単なプログラムを書くだけで作れるはずです。ただ問題は、これらの機能を、どうやって既存のパルスジェネレーターに組み込むかです。

 複数の機能を簡単なボタン層背で使えるようにしないといけませんが、プログラムを組むのが面倒です。さて、どうしたものやら。
カレンダー
06 | 2018/07 | 08
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード