2014年6月28日土曜日

PICで正弦波を

またまたPICネタであります。

キーヤーは最後の詰めに入っていますが、その前にプログラムしたDDS-VFO トランシーバー制御システムにもサイドトーンをPIC内部で発生させようと考えています。ただ単にブザーオンオフではつまらないので、正弦波に近いトーンをPICから直接発生させるといいなと思いました。

波形発生方法としては、1つのポート系列をすべてつかってラダー抵抗で8bitD/A変換する方法とPIC内蔵のPWMモジュールを使う方法がありますが、ポート数の関係からPWMモジュールでやってみることにしました。専用のD/A変換ICを使うのもよいですが、PIC単独でやらせたいので今回は却下です。

 PWMモジュールを使う場合は搬送波の周波数を高くする必要があるためキーヤーのクロック周波数4MHzでは600Hzのまともな正弦波はつくれません(AFフィルター通せば正弦波になりますがそれではあまり面白くない(笑))。なのでキーヤープログラムのほうは搬送波そのものを600Hz周辺で発生させています。もちろん方形波ですがサウンダを鳴らす分には方形波でも問題ないのでこのままにしてます。今回は対象をDDS-VFOトランシーバー制御システムに使っている18F26K22 32MHzに想定して、同じPICを使って実験してみました。

 プログラムにあたってまず、搬送波周波数をどうするかです。PWMはある一定のパルス幅をもつ搬送波のデューティーサイクルをプログラムのデータに従って変化させることで出力レベルを変化させるという方法です。搬送波のタイミングで波形が分割される(サンプリングされる)というイメージで、ある正弦波の一周期に対する分割は細かいほど元の波形がより正確に再現できるというわけです。

どこかの情報ですと(出所失念^^;)出力したい最大周波数の20倍以上が必要とのこと。サイドトーンとして使われる周波数は400~800Hz程度なので搬送波周波数は最低16kHzということになります。それよりも高ければ高いほどよさそうですが、その分波形データが必要になるのとPWMのデューティーサイクルの階調が制限されます(PICのクロック周波数は一定なので)。っていうもろもろの要素を鑑みた結果大体32kHzあたりが妥当のようです。

そうなると、正弦波1周期分で800Hzなら40、400Hzなら80分割のデータを用意できればOKです。600Hzでは整数で分割できないので、近いところで約615kHzの52分割データ用意としました。

PWMの出力はDDS-VFOシステムでの空きピンを割り当てます。今回はPWM出力可能なRB4ピン(CCP1/P1D)とし、PWMタイムベースをTimer4に設定。この条件で各レジスタ設定値をメイン関数内の初期化プロセスに記述していきます。その後のループ処理内には、Timer4のタイミングフラグが立つごとにあらかじめ用意した正弦波のデータを順々に読み込ませてデューティーサイクル設定レジスタ(CCPR1L)にコピーするという処理を書き込みます。

正弦波データをプログラムで計算させるのは8ビットPICではきついので、あらかじめ表計算ソフトで算出したデータをromに入れておくことにします。計算方法は、1周期360度を分割数で割った角度ごとのsinまたはcos値を求めてそれぞれに1を加え(負の数をなくすため)階調(今回は250階調にしました)の半分を乗算し、小数点以下を四捨五入して整数化した値を1元配列におさめます。階調は10ビットまで指定できますが、上位2ビット分は別のレジスタになるのでデータを2元配列にするなど少々手間がかかります。
 
表計算ソフトでデータ作成 400Hzと800Hzは共通です なぜだかわかりますよね
 あとは、お決まりのconfigビットの設定文、クロック関連、ポート関連のレジスタを記述していきます。

そうやって出来上がったプログラムをPickit3で注入しました。

お城で観察。

RB4ポート出力波形 パルス幅が徐々に変化してますね

ポートから適当なRCフィルタを通した波形 ギザギザ^^;

スピーカーから出てくる音は正弦波に近い結構澄んだ音になってます。ギザギザは搬送波の成分なのでスピーカーでは出力されませんからね。

比較的簡単に正弦波もどきは出せるようです。18F26K22ではプログラムメモリ消費も微々たるものなので、DDS-VFOトランシーバー制御システムのサイドトーン発生プログラムに採用しようと思います。

以下サンプルプログラムです。出力周波数600Hz(正確には615Hz)

//
// 18F26K22 PWM Tone Generator
// JL1VNQ/HARU
//
// PWM base frequency 32kHz, Tone frequency 800Hz, 40 divisions = 9 degree
// PWM base frequency 32kHz, Tone frequency 600(615)Hz, 52 divisions = 6.92307 degree
// PWM base frequency 32kHz, Tone frequency 400Hz, 80 divisions = 4.5 degree
// resolution nearly 10bits (1000steps < 1024)
//

#include    <xc.h>

#pragma config FOSC = INTIO67, PLLCFG = ON, PRICLKEN = ON, FCMEN = OFF, IESO = OFF
#pragma config PWRTEN = OFF, BOREN = SBORDIS, BORV = 190
#pragma config WDTEN = OFF
#pragma config MCLRE = INTMCLR, HFOFST = OFF, PBADEN = ON
#pragma config XINST = OFF, STVREN = ON, LVP = OFF, DEBUG = OFF
#pragma config CP1 = OFF, CP0 = OFF, CP2 = OFF, CP3 = OFF
#pragma config CPB = OFF, CPD = OFF
#pragma config WRT1 = OFF, WRT0 = OFF, WRT2 = OFF, WRT3 = OFF
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF
#pragma config EBTR1 = OFF, EBTR0 = OFF, EBTR2 = OFF, EBTR3 = OFF
#pragma config EBTRB = OFF

#define EEPROM_SIZE     1024
#define _XTAL_FREQ      32000000

#define PWM_OUT PORTB,4        // CCS1/P1D

const unsigned char SIN400[80]={
    125,135,145,154,164,173,182,190,198,206,
    213,220,226,232,236,240,244,247,248,250,
    250,250,248,247,244,240,236,232,226,220,
    213,206,198,190,182,173,164,154,145,135,
    125,115,105,96,86,77,68,60,52,44,
    37,30,24,18,14,10,6,3,2,0,
    0,0,2,3,6,10,14,18,24,30,
    37,44,52,60,68,77,86,96,105,115
};

const unsigned char SIN600[52]={       // divisions number is "multiple of 4" recomended
    125,140,155,169,183,196,208,219,228,236,
    242,246,249,250,249,246,242,236,228,219,
    208,196,183,169,155,140,125,110,95,81,
    67,54,42,31,22,14,8,4,1,0,
    1,4,8,14,22,31,42,54,67,81,
    95,110
};

void main(void){
   
    OSCCON = 0x64;          // 8MHz internal clock, primary clock (IMPORTANT!! NOT SELECT "internal OSC" for PLL)
    OSCCON2 = 0x04;            // OSC drive circuit on
    OSCTUNE = 0x40;            // 4xPLL enable, calibration = 0

    ANSELA = 0x00;
    ANSELB = 0x00;
    ANSELC = 0x00;
   
    TRISA = 0x00;
    TRISB = 0x00;
    TRISC = 0x00;
    TRISE = 0x08;
   
    CCP1CON = 0x0C;            // PWM mode
    CCPTMRS0 = 0x01;           // TMR4 use for PWM time base
    PSTR1CON = 0x08;           // only P1D

    T4CON = 0x04;              // prescaler 0, postscaler 0, TMR4ON
    PR4 = 249;                 // 32kHz, resolution 1000steps
    CCPR1L = 125;              // Duty cycle initialize
   
    while(1){       
        static unsigned char i = 0;
        if(PIR5bits.TMR4IF){
            PIR5bits.TMR4IF = 0;
            i++;
            CCPR1L = SIN600[i];
            if(i > 51) i = 0;
        }
    }
}


2014年6月17日火曜日

PICで作るキーヤー

ここのところ週末の予定が空かず、移動運用もしばらくお休み中です。
そんな中各PICのプログラムをちまちまと進めています。

いま主に進めているのが、キーヤーのプログラムです。いまさら?って感じかもしれませんが、コンテストや移動運用のときにリグ内蔵のキーヤーでは機能的に十分でも即時に速度調整などが難しく、別によく使っているKD1JV TriBand CW transceiverやTX-136の内蔵キーヤーもフィーリングがどうも自分にはあわないため、ある程度機能も充実させたものを自分で作ろうというのが製作意図です。

ハード的には、PICは16F1827の1本でI2CキャラクタLCD表示器(AE-AQM0802)、設定用ロータリーエンコーダ、サイドトーン出力とPTT出力、メッセージメモリ選択ボタンつきで、単三乾電池2本の3V動作としました。


ソフトウエアによるキーヤーの仕様は、

・キーヤー動作モード:Iambic A, B, バグキーエミュレーション, メッセージメモリー
・長短点メモリあり(50%),長短点比3:1
・符号送出速度:10~60WPMで1WPMステップ可変
・PTT出力:セミ(200msec delay)/フルブレークイン
・パドル極性:ノーマル/リバース
・サイドトーン:PWMモジュールによる出力(周波数400,600,800Hz),ミュート
・メニュー呼び出し,ロータリーエンコーダによる各設定とEEPROMへ保存による設定値の保持
・60キャラクター(スペース除く)x 4chのメッセージメモリ記録,再生
・スリープ機能

とまぁ結構盛り沢山になりました。

ソフトウエアはCで記述し、Microchip社純正のXC8コンパイラで実行ファイルを作ってPickit3でPICに転送しています。

今のところメッセージ記録部分とスリープ機能の実装が残るだけとなっていますが、完成したら一部DDS-VFOシステムに取り込むほか、プログラムの流れや実行ファイルを後日公開してみようかなと思います。途中経過のソースファイルは、すでにGoogle+のコミュニティにぼちぼち公開していますので興味のある方は登録してみてください。

もっとプログラミングに慣れたら、オープン開発のサイトにも登録を考えてみたいのですが、果たしてどうなることやら...

ソースの一部 各スイッチ状態をタイマー0割り込みで1msec毎に監視して状態フラグを立てる

BBで仮組み状態 消費電流は無負荷動作時1.6mA

LCD付きでこの消費電流なら乾電池動作いけそうかな。スクイーズ動作も自分の感覚の基準では合格点といったところです。

2014年6月10日火曜日

やりたいことがいろいろあって

やりたいことがたくさんありすぎると、逆にどれも進まなくなってしまうという状態になりがちではないでしょうか。優先順位をつけるのもままならず、折角時間あってもただただ無為に過ごしてしまうという罠にはまっているようです。

そんなわけでとりあえずはやりたいこと、または現在やりかけていることをおさらいしてみることに。

まずは、

136kHz帯の24時間稼動グラバーの設置

アンテナは同調型Mini-whipとし、受信機はDC型のSDRを自作してUSBサウンドモジュールを接続したRaspberry Piで取り込みスナップショットをアップロードするという計画です。Linux用のQRSS受信ソフトはglferとLOPORAがありますが、LOPORAはスナップショットが撮れるので必要なライブラリとソフトをインストールして起動はできるところまでこぎつけましたが、サウンド入力がうまくできなくてそこで今はとまっています。

TX-136の汎用FSK対応について

WSQやJT-9などの多値FSKモード対応のためDDSの周波数レジスタを1bit単位で外部からコントロールできるようにTX-136のファームウエアを再度変更する必要があります。プログラム修正はできましたが、まだ本体のPICを書き換えて検証していません。ファームウエア更新に伴いコントローラー側にも修正が必要で、一応アセンブリで書きなおしましたがたぶんバグ取りなどに時間がかかりそうなので保留中です。

CWトランシーバー用DDS VFOシステムと新型キーヤー


DDS VFOシステムのプログラムはほぼ完成して、ユニバーサル基板にアナログ部分とともに試作はじめようという段階、新型キーヤーはメッセージメモリなど残った機能の実装に向けて目下プログラム中。いまのところこれが一番近々完成しそうな案件です。

136kHzアンテナ用の2代目ローディングコイルの製作

100円ショップで見つけた径高さともに12cmの円筒形プラスチック製お味噌入れをボビンにして、すでに取り寄せた1kg巻き1mm径PEWを3層ピラミッド巻きにして小型高インダクタンスなコイルを作って車を使わない136kHz移動運用を実現したいと思っていますが、PEWで3層ピラミッド巻きは難しそうです。2層巻きではボビンに両面テープを巻きつけて最下層の線を固定しながら巻くことができますが、3層では2層目の固定に逐一接着剤が必要そうです。

などなど、無線電子工作関連以外にもいくつかあります(苦笑)

自分がもう一人欲しいですhi

2014年5月31日土曜日

WSQ試運転その1

WSQでの通信がにわかに1.9MHzで行われるようになったので、こちらもリグにつないでとにかく電波が出せるようにしてみました。

WSQのモデファイ版をPCにダウンロードしてUSB経由でIC7200Mに接続し、USBデータモードにして音声入力をUSBに指定、WSQの設定でaudio input/outputをUSB sound codecに指定するだけで準備は完了です。COMポートを指定するとリグの送受切り替えもできるようなのですが、IC-7200MのUSBシリアル変換器がつながっているCOM3ポートを指定してもソフト側で制御できないため本体マイクのPTTスイッチで当座手動で送受切り替えをしました。

30日の20時ごろから1.9076MHzでしばらくVVVを出していましたが、掲示板などの情報によると1.909MHzでCQなど出ているとのことでQSYしワッチすると、JA1PKG局がCQ出されていたのでコールしてみました(Po30W, Antenna 9mH SRA)

中段でJA1PKG局からのコールバックあり
当局宛にM(TMO式)のレポートを送ってくれました。こちらもゴミ文字がかなり混ざっていたのでMを送りました。QSBのためか最後の確認が文字化けしてわかりませんでした。

使用した感触としては自宅ではノイズの関係でデコードはかなり難しいと考えられました。その後twitterで10MHz帯へQSYのリクエストがあり、JJ2RON局、JE4SMQ局2局とQSOトライしましたが、さすがに10MHzとなるとQRHにより信号がしばしばデコード枠をはみ出しこちらもデコードが厳しかったです。

ゴミ文字はアルファベットの小文字が多く(小文字は1シンボル、大文字そのほかはほとんどが2シンボルのためではないかと思われます)、使用アルファベットを大文字にしてみましたが、文字化けなどやはりなかなか全部おがきれいにデコードするというわけではなく、さらに設定の吟味が必要に思えました。

136kHzでWSQによる交信が行われたようですが、さしあたって136kHzではGenesisRadioG11を使ってWSQの運用をしていこうと思います。TX-136の場合は33シフトをRS232Cシリアル通信で直接DDSに周波数レジスタ変更コマンドを送ることで実現できます。以前のWSPR,DFCW用にシフトコマンドをTX-136のファームウエアに追加変更しましたが、このままではステップが荒いため、DDSの周波数レジスタを最小単位で変更できるように新たにファームウエアを変更する必要があります。当然コントローラーのプログラムも変更が必要です。

G11ではvirtual audio cableを使ってSDRソフトとWSQ側を接続しサンプリングレートを96kHz、バッファを最大の2048KBにして送信も問題なくできるようになりましたが、相変わらずWSQ側で送受の切り替えができないのが不便でした。

送信出力は7~8Wとちょっと心もとないですが、移動運用のときにG11も持参してWSQの追試を行おうと考えています。

2014年5月27日火曜日

136kHz帯におけるデジタルモード

136kHz掲示板を覗くとどなたからかWSQというデジタルQSOモードが紹介されにわかに話題になり、早速トライされた方もいらっしゃったようです。

WSQはMFSKモードですがトーンの階調が33もあるのでTX-136ではおそらく現時点では直接的に変調がかけられません(JT9の9階調なら何とかなりそうですが、33階調ともなるとDDSの周波数切り替えステップ幅とWSQのシフト幅との誤差が無視できなくなってしまうと考えます)。

というわけでまずは2つのPCにソフトをインストール、送信をスピーカーでトーンを鳴らして、受信をマイクで拾うようにしてプチデモンストレーションしてみました。

 デスクトップPCからノートPCへ送信中 なかなか面白い

ある程度音を絞ってもほとんどデコードできています。占有帯域幅も100Hz以内になるので136kHz帯や1.9MHz帯での運用は可能です。

もし実際に136kHzで試してみるとしたら久々にGenesisRadio G11の出番となりますが、ピークで8Wしか出ないのでいささか心許ないです。3エリアに移動するとしたら一応持参することにしようかなと思っていますが果たして1エリアまで届くのでしょうか...

QSO可能なデジタルモードはほかにJT9やJASONなどがありますが、いまのところWSQよりもJT9あたりがこのバンドのデジタルQSOモードとして適切ではないのかと個人的には思います。時間や送出内容の制限はあるものの、QSOに必要十分な情報を比較的短い時間で送れますし、自由度が高くても結局やり取りする内容が同じならば占有帯域が狭いほうが混信回避という面で有利なのではないかと思います。

しかし、これを使って136kHz帯でラグチューするのもまたそれはそれで面白いかもしれません。(笑)

念のためDDSを使った直接FSKで実現しようとするとどうなのかと、脳内で検討してみました。WSQは33階調1ステップあたり1.953125Hzシフトということですが、これは1000/2^9 (=512)Hzですので、AD9834を採用する場合基準発振を32.768MHzにして周波数レジスタを2^4(=16)ずつシフトするようにプログラムを書けば可能です。

 WSQがメインストリームになりそうなら検討してみたいところですが、基準発信器が32.768MHzだとTCXOは特注になりそうです。

まだ20MHzのが残っているというに^^;