PIC12F1822内蔵DACによる
低周波信号発生器の実験的製作
↑PIC16F1823とPIC12F1822
PIC16F688と12F683とのピン配置は同じで、後継種と思われる。
ソフトウエアも互換性が、概ね保たれている。
2015年2月追記
PIC12F1822/16F1823データシート日本語版
PIC12F1822_16F1823_JP.pdf
デバイスファイルの更新
PK2DeviceFile.dat
秋月では、PIC16F18xx、16F19xxシリーズの種類が増えてきました。
当局では使用頻度の高い、8ピンPIC12F683はPIC12F1822、14ピンはPIC16F688はPIC16F1823と対応している様です。
実際マニュアルを眺めてみると・・・ (^_^;)
なんとD/Aコンバータを始め、新設機能や命令等、既存機能も含めて大幅に性能アップしています。
おまけに安くなっている・・・ (^O^)/
こりゃ~使わにゃ損ゝと言う事で、まずは使ってみようと言う事になりましたが・・・
マニュアルのページ数も大幅アップで、怒涛の436ページ (*_*;
今回は新設のDACを、とりあえず使ってみる事を目標に、プログラム実験してみます。
PIC12F683やPIC16F688から移行した場合のPIC12F1822とのプログラミング上での相違点・変更点は、ソースファイルのコメント欄になるべく記載しています。
そちらを参照して頂いた方が直接的で解りやすいと思います。
参考文献(2015年02月変更しました)
PIC12F1822/16F1823データシート Microchip
補足事項
プログラミングにあたって、MPLAB IDEはVer8.91にバージョンアップしています。
PICKIT2書込みソフトはVer2.61、デバイスファイルはver1.62.14に更新しています。
この更新しないとPIC12F1822/16F1823への書き込みはできません。
ライタは秋月のPICKIT2互換ボードを、今まで通りそのまま使用しています。
後閑哲也氏の「PIC16F1ファミリ活用ガイドブック」 (技術評論社)が発売されました。
当局も「お~っ」と思い購入し、読んでみましたが・・・
なんとこの本には、アッセンブラ プログラミングの解説がありません。
アッセンブラから入門したい各局様は、以前のガイドブックが良いと思われます。
追加モジュールの詳細は(注1)で対処OKと思われます。
ただ、MPLAB X IDEの解説がありますので、XC8等から入門する分には良い本と思います。
PICを無線工作に応用する場合は、少なくとも部分的にアッセンブラは必要と思いますけど。
追記 2015年2月
PIC12F1822/16F1823データシート日本語版がMicrochip社HPに公開されていました。
当局では使用頻度の高い、8ピンPIC12F683はPIC12F1822、14ピンはPIC16F688はPIC16F1823と対応している様です。
実際マニュアルを眺めてみると・・・ (^_^;)
なんとD/Aコンバータを始め、新設機能や命令等、既存機能も含めて大幅に性能アップしています。
おまけに安くなっている・・・ (^O^)/
こりゃ~使わにゃ損ゝと言う事で、まずは使ってみようと言う事になりましたが・・・
マニュアルのページ数も大幅アップで、怒涛の436ページ (*_*;
今回は新設のDACを、とりあえず使ってみる事を目標に、プログラム実験してみます。
PIC12F683やPIC16F688から移行した場合のPIC12F1822とのプログラミング上での相違点・変更点は、ソースファイルのコメント欄になるべく記載しています。
そちらを参照して頂いた方が直接的で解りやすいと思います。
参考文献(2015年02月変更しました)
PIC12F1822/16F1823データシート Microchip
補足事項
プログラミングにあたって、MPLAB IDEはVer8.91にバージョンアップしています。
PICKIT2書込みソフトはVer2.61、デバイスファイルはver1.62.14に更新しています。
この更新しないとPIC12F1822/16F1823への書き込みはできません。
ライタは秋月のPICKIT2互換ボードを、今まで通りそのまま使用しています。
後閑哲也氏の「PIC16F1ファミリ活用ガイドブック」 (技術評論社)が発売されました。
当局も「お~っ」と思い購入し、読んでみましたが・・・
なんとこの本には、アッセンブラ プログラミングの解説がありません。
アッセンブラから入門したい各局様は、以前のガイドブックが良いと思われます。
追加モジュールの詳細は(注1)で対処OKと思われます。
ただ、MPLAB X IDEの解説がありますので、XC8等から入門する分には良い本と思います。
PICを無線工作に応用する場合は、少なくとも部分的にアッセンブラは必要と思いますけど。
追記 2015年2月
PIC12F1822/16F1823データシート日本語版がMicrochip社HPに公開されていました。
PIC駄資料室その1へGO!
PIC12F683/16F688を踏まえて、PIC12F1822/16F1823のプログラミングをしてみて気が付いた事等。
タイマ0をウエイトとして使用するに当たって、TMR0とプリスケーラの設定表等。
このページに書き切れないので、別ページに収納しました。
PIC12F683/16F688を踏まえて、PIC12F1822/16F1823のプログラミングをしてみて気が付いた事等。
タイマ0をウエイトとして使用するに当たって、TMR0とプリスケーラの設定表等。
このページに書き切れないので、別ページに収納しました。
今回の主菜、D/Aコンバータ・モジュールの初調理
ハードウエア
今回初登場(当局比)の内蔵モジュールです。
これは外部ピンへ出力できるので、色々応用が利きそうです。
その外部ピン出力インピーダンスが高いので、基本的に電圧フォロアが必要です。
DACのビット数が少ないため、いびつな出力波形になりそうです・・・
どのみち、サイン波にするには、フィルタ回路で誤魔化す必要がありそうです。
DAC出力ルーチン
5ビットのDACですので、0~1FHの出力電圧段階となります。
このルーチンは、呼ばれるごとにDACへのデータ出力が順次変化します。
データは00H~1FHまでの範疇で1周期33個分を用意、それを繰り返します。
実際は32回呼び出される事で、1周期となります。
「時間」の進行は、このサブルーチンが呼び出された回数と間隔です。
つまり生成周波数は、一定時間に呼び出される回数で決まります。
時間軸(X軸):
波形1周期を32分割し、その位置とY軸データは決められています。
電圧軸(Y軸):
X軸の現在位置に対応した、データテーブルからの電圧データをDACレジスタに出力する。
データテーブル
一応SIN(1/32・2π)・Yを計算してみましたが、Y軸解像度が少な過ぎます。
で、実際DAC動作波形をオシロで見ながら、近似の妥協値を決めました。
データは33個用意しないと波形がいびつになります。
ここでは当局の技術不足で、CALL,RETURNすべて込で16サイクルも消費します。
よって、Fosc=32MHZでは2.0usの時間を消費します。
今回使用するその他PIC内外モジュール
内部発振器モジュール
今回はクロックは正確さを要求しないので、内部発振としました。
早い方が良いので、最高速のFosc=32MHZを使用しました。
以前のPIC内部発振は8MHZだったので4倍高速となりました。
FVR
せっかく存在するので使ってみた程度
DAC出力を5VのVDDまでフルスイングすると、OPアンプが対応しない事もあります。
約2Vに設定しましたが、思ったより正確です。
A/Dコンバータ
ボリウムで、ぐりぐりと周波数が可変できれば気持ち良さそう・・・
しかし、入力コンデンサの充電時間がどうにも長いかな・・・
タイマ0
DAC出力間隔、すなわちX軸進行時間を決めるタイマとして使うかな
ウエイトとしてもプログラムとは別に動作しているので、便利
LM358
外付けの電圧フォロアとして、とりあえず1/2を使いました
DAC出力とは、単純に直接接続しています。
予備実験では残り1/2をLPFにしてみた所、高域ではきれいな波形になりました。
しかし、低域でのギザギザにあまり効果が無かった・・・
ハードウエア
今回初登場(当局比)の内蔵モジュールです。
これは外部ピンへ出力できるので、色々応用が利きそうです。
その外部ピン出力インピーダンスが高いので、基本的に電圧フォロアが必要です。
DACのビット数が少ないため、いびつな出力波形になりそうです・・・
どのみち、サイン波にするには、フィルタ回路で誤魔化す必要がありそうです。
DAC出力ルーチン
5ビットのDACですので、0~1FHの出力電圧段階となります。
このルーチンは、呼ばれるごとにDACへのデータ出力が順次変化します。
データは00H~1FHまでの範疇で1周期33個分を用意、それを繰り返します。
実際は32回呼び出される事で、1周期となります。
「時間」の進行は、このサブルーチンが呼び出された回数と間隔です。
つまり生成周波数は、一定時間に呼び出される回数で決まります。
時間軸(X軸):
波形1周期を32分割し、その位置とY軸データは決められています。
電圧軸(Y軸):
X軸の現在位置に対応した、データテーブルからの電圧データをDACレジスタに出力する。
データテーブル
一応SIN(1/32・2π)・Yを計算してみましたが、Y軸解像度が少な過ぎます。
で、実際DAC動作波形をオシロで見ながら、近似の妥協値を決めました。
データは33個用意しないと波形がいびつになります。
ここでは当局の技術不足で、CALL,RETURNすべて込で16サイクルも消費します。
よって、Fosc=32MHZでは2.0usの時間を消費します。
今回使用するその他PIC内外モジュール
内部発振器モジュール
今回はクロックは正確さを要求しないので、内部発振としました。
早い方が良いので、最高速のFosc=32MHZを使用しました。
以前のPIC内部発振は8MHZだったので4倍高速となりました。
FVR
せっかく存在するので使ってみた程度
DAC出力を5VのVDDまでフルスイングすると、OPアンプが対応しない事もあります。
約2Vに設定しましたが、思ったより正確です。
A/Dコンバータ
ボリウムで、ぐりぐりと周波数が可変できれば気持ち良さそう・・・
しかし、入力コンデンサの充電時間がどうにも長いかな・・・
タイマ0
DAC出力間隔、すなわちX軸進行時間を決めるタイマとして使うかな
ウエイトとしてもプログラムとは別に動作しているので、便利
LM358
外付けの電圧フォロアとして、とりあえず1/2を使いました
DAC出力とは、単純に直接接続しています。
予備実験では残り1/2をLPFにしてみた所、高域ではきれいな波形になりました。
しかし、低域でのギザギザにあまり効果が無かった・・・
↑ 実験回路①
↑ スカスカの穴あき基板
RCローパスフィルタは配線されています。
カットオフ周波数は約5KHZです。
実験回路①
DAC処理を割込みルーチンに含む方法
PIC12F1822のソースプログラム
12f1822_dac01.asm
注意
ダウンロードしてMPLAB_IDEのエディタで見て下さい。
NOTE PADではTABがうまく配列しません。
よって、とでも見ずらいです
まずは実験回路①だ~
例によって超簡単な(手抜きとも言う)回路を作ります。
それからの、各種実験プログラム作成で~す。
8ピンDIPソケット2個+CR類の基板となりました。
回路図(と言う程の物でもないですが)は左記です。
ただの実験基板なので、電圧フォロアは無くても実験可能です。
しかし、基板がスカスカで寂しいので付けました・・・
ソケットも大量に在庫していますしね。
実験基板が出来れば、それに合わせてプログラムを作るだけです。
もちろん、ブレッドボードでDACルーチンの基本動作実験を事前に行っています。
実験基板なので、RCフィルタは不要です。
Rf=33KΩ、Cf=0.001uFでカットオフ周波数が約5KHZとなります。
このフィルタの挿入で波形のギザギザが結構丸くなります。
カットオフ周波数近辺では少し減衰しますが、サイン波に近くなります。
プログラム構想(と言う程の物でも無いですが・・・)
DAC処理と時間待ち処理と時間待ちデータ変更処理の3点が主なプログラムです。
まずはPIC1個で処理する、簡単実験回路対応と言う事が前提です。
大まかにメインループと割込み処理の2本立てを考えてみました。
DAC処理を、そのどちらに持ってくるかで、各処理方法が別れます。
方法①DAC処理を割込みルーチンに持ってきた
ボリウムぐりぐりで周波数可変したい、と言う単純な要求で作成しました。
メインループはADC処理をしているだけとなります。
タイマ0をインタバルタイマとして使用、設定時間で割込みを掛けます。
ADCで取得したデーはをタイマ0の設定データとして使用します。
割込みルーチン内ではDAC処理を行います。
ただ、ADC処理と、割込みによるオーバーヘッド等で処理時間を消費してしまいます。
その分高域生成が制限される事になります。
方法②DAC処理をメインループに持ってきた
データ生成はRA2/INTによる割込みルーチン内で行う事としました。
生成方法はADC出力や入力ポートからのデータを使用する事にします。
メインループが単純化し、比較的高速でDAC処理ができます。
タイマ0をウエイトとして使用しますが、オーバーフローフラグをチェックしてるだけです。
低域はもちろん、①の方法より高域生成も可能と思われます。
RA2/INTによる割込みを、データ変更された時のみ発生させる必要があります。
その方法がPIC1個では思い浮かばず、苦し紛れに手動でやってみたら・・・
あまりにも使い勝手が悪いので、ボツとなりました。
②方式の欠点はPICの追加等で解決可能と思われます。
どのみち、PIC1個で実用性を考えるのは、ちょっと苦しいです。
しかし、かなり色々とプログラム実験ができ、楽しめました。
例によって超簡単な(手抜きとも言う)回路を作ります。
それからの、各種実験プログラム作成で~す。
8ピンDIPソケット2個+CR類の基板となりました。
回路図(と言う程の物でもないですが)は左記です。
ただの実験基板なので、電圧フォロアは無くても実験可能です。
しかし、基板がスカスカで寂しいので付けました・・・
ソケットも大量に在庫していますしね。
実験基板が出来れば、それに合わせてプログラムを作るだけです。
もちろん、ブレッドボードでDACルーチンの基本動作実験を事前に行っています。
実験基板なので、RCフィルタは不要です。
Rf=33KΩ、Cf=0.001uFでカットオフ周波数が約5KHZとなります。
このフィルタの挿入で波形のギザギザが結構丸くなります。
カットオフ周波数近辺では少し減衰しますが、サイン波に近くなります。
プログラム構想(と言う程の物でも無いですが・・・)
DAC処理と時間待ち処理と時間待ちデータ変更処理の3点が主なプログラムです。
まずはPIC1個で処理する、簡単実験回路対応と言う事が前提です。
大まかにメインループと割込み処理の2本立てを考えてみました。
DAC処理を、そのどちらに持ってくるかで、各処理方法が別れます。
方法①DAC処理を割込みルーチンに持ってきた
ボリウムぐりぐりで周波数可変したい、と言う単純な要求で作成しました。
メインループはADC処理をしているだけとなります。
タイマ0をインタバルタイマとして使用、設定時間で割込みを掛けます。
ADCで取得したデーはをタイマ0の設定データとして使用します。
割込みルーチン内ではDAC処理を行います。
ただ、ADC処理と、割込みによるオーバーヘッド等で処理時間を消費してしまいます。
その分高域生成が制限される事になります。
方法②DAC処理をメインループに持ってきた
データ生成はRA2/INTによる割込みルーチン内で行う事としました。
生成方法はADC出力や入力ポートからのデータを使用する事にします。
メインループが単純化し、比較的高速でDAC処理ができます。
タイマ0をウエイトとして使用しますが、オーバーフローフラグをチェックしてるだけです。
低域はもちろん、①の方法より高域生成も可能と思われます。
RA2/INTによる割込みを、データ変更された時のみ発生させる必要があります。
その方法がPIC1個では思い浮かばず、苦し紛れに手動でやってみたら・・・
あまりにも使い勝手が悪いので、ボツとなりました。
②方式の欠点はPICの追加等で解決可能と思われます。
どのみち、PIC1個で実用性を考えるのは、ちょっと苦しいです。
しかし、かなり色々とプログラム実験ができ、楽しめました。
↑ 実験基板①出力画像 1KHZ 2Vpp
条件
垂直軸 0.5V/DIV 水平軸 0.2ms/DIV
DAC出力波形は実験基板②の画像と同じです
もちろん低域の波形は段々になっています。
それは実験基板②出力も同じです。
↑ 実験基板①出力画像 4KHZ 1Vpp
条件
垂直軸 0.5V/DIV 水平軸 50us/DIV
減衰がありますが、カットオフに近いせいか割ときれいです。
方法①DAC処理を割込みルーチンに持ってきた
これは②のプログラムが出来てから、それを再配置と修正で作っています。
当初はADC出力値=TMR0設定値としてました。
そしてJP0-JP2の3ビットでプリスケーラ値が変更できるようにしていました。
高域は6KHZ程度まで生成しますが、プリスケーラ半固定では操作もしずらいです。
また、プリスケーラは分周比を小さくすると、TMR0値によっては誤動作します。
とりあえず、ボリウムぐりぐりで生成周波数可変しますので、一瞬面白いです。
しかし、ボリウムの操作性の悪さが仇で、すぐ飽きました・・・
そして、実験基板②の製作とプログラミングに行ってしまいましたとさ・・・
実験基板②の目途が付いたので、再度舞い戻っていました。
今度は簡単にですが、設定最適化ルーチンを作成してみました。
これを直結していたADC出力とタイマ0の間に挿入しました。
これが思いのほか効果的で、悪かったボリウム操作感が格段に良くなりました。
生成周波数は約70HZ~4KHZとしています。
また、ジャンパSWは使用しません。
これで何とか、ボリウムぐりぐりで遊べるようになりましたです。
因みにこのルーチン、気合を入れてやると、さらに良くなると思いますが・・・
どうせメインルーチンは暇を持て余していますしね。
しかしちょっと面倒くさそう・・・と言うか自分時間が無い・・・
プログラム内容は超シンプルですので、特に言う事はありませんです・・・
ここではDAC処理が割込み処理ルーチンに配置されています。
メインループはADC処理とデータ最適化処理と時間つぶし処理となっています。。
タイマ0がインタバルタイマ割込みとして働き、生成周波数を仕切っています。
詳細はソースファイルのコメント欄をご参照して下さい。
コメントをなるべく多く記載してあります。
実は実験回路①は公表には至らなくなる所でした・・・
当初この、①割込みでDAC処理、②メインループでDAC処理、いずれもイマイチでした。
よって、何とか使える実験回路②のみで公表とするかなと、そんな流れ至ってました。
実験回路②のコントロール側PIC16F1823のプリスケーラ設定部分は手動切替です。
これは当初自動切替にしようかとプログラムしていたのです。
所が、手動切替の方が自由に周波数生成できるので、ボツになりました。
そのボツになったプログラムが、ここに左遷?栄転?されてきたのでした。
その結果、実験回路①そのものがボツになるのを最適化ルーチンが救ってくれました。
方法②メインループにDAC処理を持ってきてみた
出力波形は1周期を32分割しますので、32回ループで1周期となります。
最大可聴域の20KHZを生成するには、1ループ約1.5us・・・って、ムリ
高域の生成周波数はメインループの時間で、ほぼ決まってしまいます。
いかに短くて長く制御可能なループ方法を、無い知恵を絞り考えましたです (^_^;)
と言う訳で、メインループをなるべく簡単(=早い)にする事。
生成周波数設定ルーチンが、普段はメインループの負担にならない様にする事。
PICの速度とDACモジュール処理を考えると、10KHZ生成を目標とするのが現実的。
以上を中心に実験的にプログラミングする事に・・・
DACデータ出力時間間隔(すなわち1ループの時間管理)の方法
ループ間ウエイト時間制御には、当初ただの減算カウンタで処理していました。
しかし、どうにもイマイチなので、タイマ0をウエイトに使用する事にしました。
これはプログラムに関係なく動きますので、減算カウンタより好都合です。
プリスケーラ制御で、8ビットデータでも、広い可変幅が設定できそうです。
メインループ内では、TMR0オーバーフローフラグを監視するだけです。
よって、かなりループのソースコードも実行時間も短縮でき、FBです。
さらに時間節約のため、DACサブルーチンはメインループに埋込みました。
これにより、DAC制御含むメインループは17サイクル(2.125us)となりました。
TMR0のオーバーフロー時間はPS=1/16で最速2usです。
DAC処理とループで1.5us消費しますので、PS=1/8以下で最高速となります。
よって高域は計算上何とか10KHZ越えを生成できる計算になります。
実際は12KHZ生成が何とか可能でした。
タイマ0設定対応表を見れば分かりますが、 →対応表へ行く
プリスケール値を変えれば、低域生成は自在です。
自転車で言うならば、TMR0設定値はペダルを漕ぐ力、PS値は変速機の様なものです。
生成周波数設定(可変)ルーチン
このルーチンは、外部からの8ビットデータを取り込む事を基本としてます。
RA2/INT割込みにより起動し、その取得データをTMR0への設定値とします。
これにより、256段階で広く生成周波数を変化できます。
プリスケーラの設定値も変化させますと、さらに広く生成周波数を変化可能です。
しかしながら、PIC1個でのその方法が思い浮かびませんでした・・・
苦肉の策として、ADCとボリウムで8ビットデータを取得する事にしました。
よって、普段はメインループを回すだけとし、生成周波数に影響しないです。
しかしこのルーチンが起動した時だけ生成周波数に影響を与えます。
と言う事は割込みルーチンで変更データをセットしなければなりません。
しかしADC入力電圧が変わった時のみに割込む方法が思い浮かばなかった・・・
よって、ボリウムを動かしてから手動で割込みを掛け、設定値を変更する事としました。
何か間抜けな操作方法・・・ (-_-;)
一時は4ビット16種類のプリセット周波数で誤魔化そうとも思ったのですが、やめました。
事実上、お手上げ状態に陥ったのでした・・・ (-_-;)
と言う訳で、PIC2個を使用した実験回路②へ続くのだ~
これは②のプログラムが出来てから、それを再配置と修正で作っています。
当初はADC出力値=TMR0設定値としてました。
そしてJP0-JP2の3ビットでプリスケーラ値が変更できるようにしていました。
高域は6KHZ程度まで生成しますが、プリスケーラ半固定では操作もしずらいです。
また、プリスケーラは分周比を小さくすると、TMR0値によっては誤動作します。
とりあえず、ボリウムぐりぐりで生成周波数可変しますので、一瞬面白いです。
しかし、ボリウムの操作性の悪さが仇で、すぐ飽きました・・・
そして、実験基板②の製作とプログラミングに行ってしまいましたとさ・・・
実験基板②の目途が付いたので、再度舞い戻っていました。
今度は簡単にですが、設定最適化ルーチンを作成してみました。
これを直結していたADC出力とタイマ0の間に挿入しました。
これが思いのほか効果的で、悪かったボリウム操作感が格段に良くなりました。
生成周波数は約70HZ~4KHZとしています。
また、ジャンパSWは使用しません。
これで何とか、ボリウムぐりぐりで遊べるようになりましたです。
因みにこのルーチン、気合を入れてやると、さらに良くなると思いますが・・・
どうせメインルーチンは暇を持て余していますしね。
しかしちょっと面倒くさそう・・・と言うか自分時間が無い・・・
プログラム内容は超シンプルですので、特に言う事はありませんです・・・
ここではDAC処理が割込み処理ルーチンに配置されています。
メインループはADC処理とデータ最適化処理と時間つぶし処理となっています。。
タイマ0がインタバルタイマ割込みとして働き、生成周波数を仕切っています。
詳細はソースファイルのコメント欄をご参照して下さい。
コメントをなるべく多く記載してあります。
実は実験回路①は公表には至らなくなる所でした・・・
当初この、①割込みでDAC処理、②メインループでDAC処理、いずれもイマイチでした。
よって、何とか使える実験回路②のみで公表とするかなと、そんな流れ至ってました。
実験回路②のコントロール側PIC16F1823のプリスケーラ設定部分は手動切替です。
これは当初自動切替にしようかとプログラムしていたのです。
所が、手動切替の方が自由に周波数生成できるので、ボツになりました。
そのボツになったプログラムが、ここに左遷?栄転?されてきたのでした。
その結果、実験回路①そのものがボツになるのを最適化ルーチンが救ってくれました。
方法②メインループにDAC処理を持ってきてみた
出力波形は1周期を32分割しますので、32回ループで1周期となります。
最大可聴域の20KHZを生成するには、1ループ約1.5us・・・って、ムリ
高域の生成周波数はメインループの時間で、ほぼ決まってしまいます。
いかに短くて長く制御可能なループ方法を、無い知恵を絞り考えましたです (^_^;)
と言う訳で、メインループをなるべく簡単(=早い)にする事。
生成周波数設定ルーチンが、普段はメインループの負担にならない様にする事。
PICの速度とDACモジュール処理を考えると、10KHZ生成を目標とするのが現実的。
以上を中心に実験的にプログラミングする事に・・・
DACデータ出力時間間隔(すなわち1ループの時間管理)の方法
ループ間ウエイト時間制御には、当初ただの減算カウンタで処理していました。
しかし、どうにもイマイチなので、タイマ0をウエイトに使用する事にしました。
これはプログラムに関係なく動きますので、減算カウンタより好都合です。
プリスケーラ制御で、8ビットデータでも、広い可変幅が設定できそうです。
メインループ内では、TMR0オーバーフローフラグを監視するだけです。
よって、かなりループのソースコードも実行時間も短縮でき、FBです。
さらに時間節約のため、DACサブルーチンはメインループに埋込みました。
これにより、DAC制御含むメインループは17サイクル(2.125us)となりました。
TMR0のオーバーフロー時間はPS=1/16で最速2usです。
DAC処理とループで1.5us消費しますので、PS=1/8以下で最高速となります。
よって高域は計算上何とか10KHZ越えを生成できる計算になります。
実際は12KHZ生成が何とか可能でした。
タイマ0設定対応表を見れば分かりますが、 →対応表へ行く
プリスケール値を変えれば、低域生成は自在です。
自転車で言うならば、TMR0設定値はペダルを漕ぐ力、PS値は変速機の様なものです。
生成周波数設定(可変)ルーチン
このルーチンは、外部からの8ビットデータを取り込む事を基本としてます。
RA2/INT割込みにより起動し、その取得データをTMR0への設定値とします。
これにより、256段階で広く生成周波数を変化できます。
プリスケーラの設定値も変化させますと、さらに広く生成周波数を変化可能です。
しかしながら、PIC1個でのその方法が思い浮かびませんでした・・・
苦肉の策として、ADCとボリウムで8ビットデータを取得する事にしました。
よって、普段はメインループを回すだけとし、生成周波数に影響しないです。
しかしこのルーチンが起動した時だけ生成周波数に影響を与えます。
と言う事は割込みルーチンで変更データをセットしなければなりません。
しかしADC入力電圧が変わった時のみに割込む方法が思い浮かばなかった・・・
よって、ボリウムを動かしてから手動で割込みを掛け、設定値を変更する事としました。
何か間抜けな操作方法・・・ (-_-;)
一時は4ビット16種類のプリセット周波数で誤魔化そうとも思ったのですが、やめました。
事実上、お手上げ状態に陥ったのでした・・・ (-_-;)
と言う訳で、PIC2個を使用した実験回路②へ続くのだ~
実験回路2
PIC1個では、DAC制御で精いっぱいなので、2個使用すれば良い事になります。
さすれば、コントロール側のPICは余裕ができるので、色々できそうです。
生成側のPIC(12F1822)はDACコントロールをひたすら行います。
割込み時(RA2/INT)のみ、タイマ0のPS値とTMR0値を変更します。
DAC出力1ポート、パラレル通信に5ポート使用します。
コントロール側PIC(16F1823)はデータ生成を行います。
ADC入力に1ポート、プリセット用に4ポート、データ通信に5ポート使用します。
ロータリーエンコーダと7セグ周波数表示を付けたかったのですが・・・
今回は実験なので、最低限の構成です・・・ (^_^;)
実験回路①に14ピンPICを追加しただけです。
そうです、あえてシンプルにしています。(ウソです、面倒なだけです・・・)
プリセット用ポートには4ビットのロータリーDIPスイッチを付けました。
これは、VRモードではTMR0プリスケーラの設定値を指定します。
プリセットモードでは、16種類の周波数を選択します。
余ったポートにLEDを付けましたが、今の所用途不明です。
簡単にですが、オペアンプによる電圧フォロアとローパスフィルタも付けました。
カットオフ周波数は約11KHZに設定しました。
これでは低域では波形のキザギザは消えませんが少し鈍ります。
高域では割とサイン波に近くなりましたが、出力電圧が低下します。
また、負荷を接続すると、ひずみが少し出ます。
まずはこれでもラジオや無線機の修理等には使えるかもしれません・・・
目標(仕様)
発生周波数 10HZ~10KHZ (実際は最大12KHZまで可)
発生波形 疑似サイン波
プリセット周波数(正確ではありません)
00 100HZ 01 300HZ 02 500HZ
03 800HZ 04 1KHZ 05 1.3KHZ
06 1.5KHZ 07 1.8KHZ 08 2KHZ
09 2.5KHZ 10 3KHZ 11 3.5KHZ
12 4KHZ 13 5KHZ 14 8KHZ
15 10KHZ
PIC1個では、DAC制御で精いっぱいなので、2個使用すれば良い事になります。
さすれば、コントロール側のPICは余裕ができるので、色々できそうです。
生成側のPIC(12F1822)はDACコントロールをひたすら行います。
割込み時(RA2/INT)のみ、タイマ0のPS値とTMR0値を変更します。
DAC出力1ポート、パラレル通信に5ポート使用します。
コントロール側PIC(16F1823)はデータ生成を行います。
ADC入力に1ポート、プリセット用に4ポート、データ通信に5ポート使用します。
ロータリーエンコーダと7セグ周波数表示を付けたかったのですが・・・
今回は実験なので、最低限の構成です・・・ (^_^;)
実験回路①に14ピンPICを追加しただけです。
そうです、あえてシンプルにしています。(ウソです、面倒なだけです・・・)
プリセット用ポートには4ビットのロータリーDIPスイッチを付けました。
これは、VRモードではTMR0プリスケーラの設定値を指定します。
プリセットモードでは、16種類の周波数を選択します。
余ったポートにLEDを付けましたが、今の所用途不明です。
簡単にですが、オペアンプによる電圧フォロアとローパスフィルタも付けました。
カットオフ周波数は約11KHZに設定しました。
これでは低域では波形のキザギザは消えませんが少し鈍ります。
高域では割とサイン波に近くなりましたが、出力電圧が低下します。
また、負荷を接続すると、ひずみが少し出ます。
まずはこれでもラジオや無線機の修理等には使えるかもしれません・・・
目標(仕様)
発生周波数 10HZ~10KHZ (実際は最大12KHZまで可)
発生波形 疑似サイン波
プリセット周波数(正確ではありません)
00 100HZ 01 300HZ 02 500HZ
03 800HZ 04 1KHZ 05 1.3KHZ
06 1.5KHZ 07 1.8KHZ 08 2KHZ
09 2.5KHZ 10 3KHZ 11 3.5KHZ
12 4KHZ 13 5KHZ 14 8KHZ
15 10KHZ
実験回路2
PIC12F1822のソースファイル
12f1822_afgen02.asm
実験回路2
PIC16F1823のソースファイル
は下記です
手動PS切替VRモード
16f1823_afcon01.asm
おまけ↓
自動変速VRモード
16f1823_afcon01a.asm
プリスケーラとTMR0との組合せ表
PIC12F1822のソースファイル
12f1822_afgen02.asm
実験回路2
PIC16F1823のソースファイル
は下記です
手動PS切替VRモード
16f1823_afcon01.asm
おまけ↓
自動変速VRモード
16f1823_afcon01a.asm
プリスケーラとTMR0との組合せ表
実験回路2 周波数生成用PIC12F1822のプログラム
実験回路1方法②のプログラムを少々変更、余計なルーチンやコメントは削除しました。
ここは制御PICからのデータでDACのコントロールを行います。
データはRA2/INT割込みが掛った時のみ取得し、タイマ0の再設定を行います。
タイマによる間欠的な割込みを掛けている訳ではありません。
通常はDACへひたすらデータを書き込むループを構成しています。
よって、メインループは、かなりシンプルです。
データ転送プロトコルについてはソースファイルを参照して下さい。
実験回路2 制御用PIC16F1823のプログラム
14ピンのPIC16F1823を使用してますが、もちろん16F688でも可能です。
そのままICソケットに差し込んでも、ハードウェア的に大丈夫です。
当然、プログラムは一部変更等が必要ですが。
ここは周波数データの生成と12F1822へ割込みデータ転送を行います。
内容はA/DコンバータとデジタルI/O操作のみです。
データ変更をチェックし、それが発生したら、送信するだけです。
データ変更が無い場合、データ転送は行いません。
データ転送は4ビットパラレルで、全長12ビットを3回に分けて転送しています。
ボリウムだけでは周波数が分からないので、プリセットデータを設定可能としました。
こちらのプリセットモードの方が生成周波数が、予め判るので使い易いかも。
ボリウムモードとプリセットモードは、スイッチによる切替となります。
送信データは12ビット長データとなっています。
その内8ビットはTMR0設定値、3ビットでタイマ0プリスケール値設定となっています。
残り1ビットは、ちょっとした制御フラグに使用しています。
プリセットデータ設定に関しては、組合せ表を参考に作成しています。 組合せ表へ行く
タイマ0設定値+1us程度で計算・設定していますが、概ね計算値と合っています。
その他詳細はソースファイルのコメントを参照して下さい。
実験回路1方法②のプログラムを少々変更、余計なルーチンやコメントは削除しました。
ここは制御PICからのデータでDACのコントロールを行います。
データはRA2/INT割込みが掛った時のみ取得し、タイマ0の再設定を行います。
タイマによる間欠的な割込みを掛けている訳ではありません。
通常はDACへひたすらデータを書き込むループを構成しています。
よって、メインループは、かなりシンプルです。
データ転送プロトコルについてはソースファイルを参照して下さい。
実験回路2 制御用PIC16F1823のプログラム
14ピンのPIC16F1823を使用してますが、もちろん16F688でも可能です。
そのままICソケットに差し込んでも、ハードウェア的に大丈夫です。
当然、プログラムは一部変更等が必要ですが。
ここは周波数データの生成と12F1822へ割込みデータ転送を行います。
内容はA/DコンバータとデジタルI/O操作のみです。
データ変更をチェックし、それが発生したら、送信するだけです。
データ変更が無い場合、データ転送は行いません。
データ転送は4ビットパラレルで、全長12ビットを3回に分けて転送しています。
ボリウムだけでは周波数が分からないので、プリセットデータを設定可能としました。
こちらのプリセットモードの方が生成周波数が、予め判るので使い易いかも。
ボリウムモードとプリセットモードは、スイッチによる切替となります。
送信データは12ビット長データとなっています。
その内8ビットはTMR0設定値、3ビットでタイマ0プリスケール値設定となっています。
残り1ビットは、ちょっとした制御フラグに使用しています。
プリセットデータ設定に関しては、組合せ表を参考に作成しています。 組合せ表へ行く
タイマ0設定値+1us程度で計算・設定していますが、概ね計算値と合っています。
その他詳細はソースファイルのコメントを参照して下さい。
↑ DAC生成波形画像
7.6HZ 2Vpp
条件
垂直軸 0.5V/DIV
水平軸 10ms/DIV
PS=1/128
TMR0=00H
FVR=2V
↑ DAC生成波形画像
100HZ 2Vpp
条件
垂直軸 0.5V/DIV
水平軸 1ms/DIV
↑ DAC生成波形画像
1KHZ 2Vpp
条件
垂直軸 0.5V/DIV
水平軸 0.2ms/DIV
↑ ローパスフィルタ通過後の波形
1KHZ 2Vpp
条件
垂直軸 0.5V/DIV
水平軸 0.2ms/DIV
↑ DAC生成波形画像
5KHZ 2Vpp
条件
垂直軸 0.5V/DIV
水平軸 50us/DIV
↑ ローパスフィルタ通過後の波形
5KHZ 2Vpp
条件
垂直軸 0.5V/DIV
水平軸 50us/DIV
↑ ローパスフィルタ通過後の波形
10KHZ 約1.4Vpp
↑ DAC生成波形画像
12KHZ 2Vpp
条件
垂直軸 0.5V/DIV
水平軸 50us/DIV
PS=1/1
TMR0=FFH
FVR=2V
↑ ローパスフィルタ通過後の波形
使用方法
2種類のモードがあり、スイッチで切り替えて使用します。
手動PS切替VRモード (自動変速VRモードに変更可能)
ボリウムの電圧値をADCで読み、00H~FFHのTMR0用データを生成します。
ロータリーDIPスイッチではタイマ0のプリスケーラ値1/1~1/128を設定します。
当初は、ADC出力値を適正なTMR0値とPS値の組合せに自動変換してから、
その最適化データを生成側PICに転送するつもりでした。
ところが、余計な事をしない方が実験には都合が良いので、ボツになりました。
しかしながら、そのルーチンは実験回路①の、方法①で採用となりました。
そのルーチンはソースに存在しますので、1行変更のみで使用可能です。
プリセットモード
予めプリセットされた、TMR0値とPS値組合せによるデータを転送します。
16種類しか指定できませんが、ちょっと使う分には十分と思われます。
1KHZにおけるDAC出力とフィルタ出力の波形比較
カットオフから離れているので、出力電圧減衰は少ないです。
その分、波形整形はイマイチです。
5KHZにおけるDAC出力とフィルタ出力の波形比較
電圧減衰も少なく、波形もそこそこきれいになってきました。
10KHZにおけるフィルタ出力
電圧減衰が発生し、約1.4Vpp程度になりましたが、波形はきれいです。
12KHZにおけるDAC出力とフィルタ出力の波形比較
電圧減衰が大きくなりますが、波形はきれいなサイン波です。
2種類のモードがあり、スイッチで切り替えて使用します。
手動PS切替VRモード (自動変速VRモードに変更可能)
ボリウムの電圧値をADCで読み、00H~FFHのTMR0用データを生成します。
ロータリーDIPスイッチではタイマ0のプリスケーラ値1/1~1/128を設定します。
当初は、ADC出力値を適正なTMR0値とPS値の組合せに自動変換してから、
その最適化データを生成側PICに転送するつもりでした。
ところが、余計な事をしない方が実験には都合が良いので、ボツになりました。
しかしながら、そのルーチンは実験回路①の、方法①で採用となりました。
そのルーチンはソースに存在しますので、1行変更のみで使用可能です。
プリセットモード
予めプリセットされた、TMR0値とPS値組合せによるデータを転送します。
16種類しか指定できませんが、ちょっと使う分には十分と思われます。
1KHZにおけるDAC出力とフィルタ出力の波形比較
カットオフから離れているので、出力電圧減衰は少ないです。
その分、波形整形はイマイチです。
5KHZにおけるDAC出力とフィルタ出力の波形比較
電圧減衰も少なく、波形もそこそこきれいになってきました。
10KHZにおけるフィルタ出力
電圧減衰が発生し、約1.4Vpp程度になりましたが、波形はきれいです。
12KHZにおけるDAC出力とフィルタ出力の波形比較
電圧減衰が大きくなりますが、波形はきれいなサイン波です。
実験回路2結果考察
実験回路①でも同じですが、低域で音が悪いです (-_-;)
正弦波を発生する、アナログ低周波発振器とは比較にならないです。
操作感は上限周波数まで、比較的自由に生成でき、良くなりました。
VRモードではぐりぐりと周波数変化が可能で、気持ち良いです。
低域は自在ですし、高域は間隔が荒くなりますが、12KHZまで生成可能です。
しかし、このままでは発生周波数が分からないのが難点です。
自動変速VRモードでは、目盛を付けると大雑把な周波数が把握できるかも・・・
プリセットモードでは出力周波数が設定されているため、多少は使えそうです。
今の所、使用しているロータリーDIPスイッチの信頼性が乏しいのが難点です。
今後の方向性
①周波数カウンタや設定データ表示を付ける。
②プリセットモードで、信頼性のある多接点ロータリスイッチを使用する
③生成波形の種類を増やす、等々
結果
PIC内蔵DACで低周波を生成するというのが実験目的でした。
簡単かつ超安価な回路で、生成周波数も概ね正確にプログラム可能です。
まあ当初の目的は、かろうじてクリアできたのではと考えています。
当局の技術では素人レベルの実験ではありましたが・・・
PIC16F18xxシリーズのプログラミングが、ちょっとだけ分かったのが最大の収穫だったかも。
実験回路①でも同じですが、低域で音が悪いです (-_-;)
正弦波を発生する、アナログ低周波発振器とは比較にならないです。
操作感は上限周波数まで、比較的自由に生成でき、良くなりました。
VRモードではぐりぐりと周波数変化が可能で、気持ち良いです。
低域は自在ですし、高域は間隔が荒くなりますが、12KHZまで生成可能です。
しかし、このままでは発生周波数が分からないのが難点です。
自動変速VRモードでは、目盛を付けると大雑把な周波数が把握できるかも・・・
プリセットモードでは出力周波数が設定されているため、多少は使えそうです。
今の所、使用しているロータリーDIPスイッチの信頼性が乏しいのが難点です。
今後の方向性
①周波数カウンタや設定データ表示を付ける。
②プリセットモードで、信頼性のある多接点ロータリスイッチを使用する
③生成波形の種類を増やす、等々
結果
PIC内蔵DACで低周波を生成するというのが実験目的でした。
簡単かつ超安価な回路で、生成周波数も概ね正確にプログラム可能です。
まあ当初の目的は、かろうじてクリアできたのではと考えています。
当局の技術では素人レベルの実験ではありましたが・・・
PIC16F18xxシリーズのプログラミングが、ちょっとだけ分かったのが最大の収穫だったかも。