« カテリナ彗星Catalina (C/2013 US10)はほんとうに肉眼で見えるの? 光度等級-高度-方位角-月との離角 | トップページ | JAXAのデータではやぶさ/スイングバイの視位置を予測する »

2015年10月29日 (木)

掩蔽観測用GPS/1PPS発光器(弐) - LED駆動ユニット - プログラム(PIC16F648A)(訂正版)

掩蔽観測用GPS/1PPS発光器(弐) - LED駆動ユニット - プログラム(PIC16F648A)」に書いたプログラムは古いもので今使っているPICのバイナリと違うことはわかったのですが、PICのバイナリに対するソースが見つかりませんでした。

ソースはなくなったものとあきらめていたのですが、今日ひょんなことから出てきました。

GE-612TとGM-5157Aで挙動が違うことの理由もはっきりしました(つまりこれまでの推測は間違ってました)

--------

関連

  「掩蔽観測用GPS/1PPS発光器(弐) - LED駆動ユニット - 配線図
  「掩蔽観測用GPS/1PPS発光器(弐) - LED駆動ユニット - プログラム(PIC16F648A)
  「掩蔽観測用GPS/1PPS発光器(弐) - 潜入・出現時刻の求め方
  「掩蔽観測用GPS/1PPS発光器(弐/参) - LED駆動ユニット - 使い方

  「時刻標準について
  「GPS受信モジュールあれこれ

  「過去記事の一覧(測定、電子工作、天文計算): セッピーナの趣味の天文計算
  「記事一覧(測定): セッピーナの趣味の天文計算

	LIST	P=pic16f648a
#include	

; このプログラムを作成するにあたって ;  ほよほよさん(http://ameblo.jp/ringworldengineer/)の記事 ;     「GPGGAメッセージからUTC Timeを取り出す 」 ;      http://ameblo.jp/ringworldengineer/entry-11727597759.html ; を参考にさせていただきました。 ; 特に測位情報の読み込みの部分はそのまま再利用させていただいています。 ; ; 以上ここに記し謝意を表します。 ; 測位情報の秒、十秒の値を三色LEDで表示します。 ; 測位情報から得られる時刻は遅れがあるので1秒プラスして次の1PPS信号のとき表示に使います。 ; いろいろ小うるさいことを書いてあるのは1PPS信号によるLEDの発光を掩蔽時刻の決定に使うからです。 ; また1PPS信号のパルス幅が0.1秒であることはカメラのセンサー走査時間や露出時間の調査にも使います。 ; ピンアサイン - 括弧内はDIPのピン番号 ; LEDはアノードコモンを使っています。 ; 三色LEDのRGBは電流制限抵抗を介してPICに接続してあります ; LEDのコモンピンは1PPSでドライブされるTrをとおしてVDDに接続してあります。 ; **重要** PICの処理はLEDの色、明るさを変えるためだけに行っています。 ; 処理が1PPSによる発光点滅のタイミングに影響することはありません。 ; 色の説明 ;   白: データを一度も受信していない ;   赤: 00秒台、10秒台 (前半50ms) ;   赤: 毎0秒、3秒、6秒 (後半50ms) ;   緑: 20秒台、30秒台 (前半50ms) ;   緑: 毎1秒、4秒、7秒 (後半50ms) ;   青: 40秒台、50秒台 (前半50ms) ;   青: 毎2秒、5秒、8秒 (後半50ms) ;   黄: フレームエラー  ;   紫: オーバーランエラー ;   水色: バグってます (^^;; ;   1PPS信号がないときはLEDは発光しないことに注意してください。  ; 電気的特性 ; ; 使い方によってはあんまりマージンがとれないケースがありそうです。 ; 特にSchmitt TriggerのVIHはかなり高いので注意が必要です。 ; RX(07)がこれに該当しGM-316のTXDじゃドライブできなかったような.... ; GE-612TはのTXD/VOHの実測値は3.0Vでした。なかなかきびしい値です。 ; 確実な動作を確保するためにコンパレーター等の使用をおすすめします。 ; 例えば秋月電子通商で購入できるNJM2903だと ;  オープンコレクタ出力 ;   出力飽和電圧: 標準0.2V、最大0.4V (ISINK=3mA) ;   出力リーク電流: 最大1uA (Vo=5V) ; です。 ; ; TTL buffer ;   VIL(Max) 0.8V(VDD:4.8V) 0.5V(VDD:3.6V) 0.8V(参考:TTL) ;   VIH(Min) 2.0V(VDD:4.8V) 1.7V(VDD:3.6V) 2.0V(参考:TTL) ; Schmitt Trigger input ;   VIL(Max) 0.9V(VDD:4.8V) 0.7V(VDD:3.6V) ;   VIH(Min) 3.9V(VDD:4.8V) 2.9V(VDD:3.6V) ; I/O ports (Except RA4) ;   VOL(Max) 0.6V(VDD:4.8V) 0.6V(VDD:3.6V) (IOL= 8.5mA) 0.4V(参考:TTL) ;   VOH(Min) 4.1V(VDD:4.8V) 2.9V(VDD:3.6V) (IOH=-3.0mA) 2.4V(参考:TTL) ;   (以上はPIC16F627A/628A/648A Data Sheetを参考もとに計算しました) ;   (Max値は切り捨て、Min値は切り上げです) ; ; ピンアサイン ; RA0(17) R ; RA1(18) G ; RA2(01) B ; RA3(02) OUT 発光の終了時に光量を増大させるために使います ; RA4(03) - Open Drain ; RA5(04) - Vpp/MCLR ; RA6(15) - ; RA7(16) - ; RB0(06) IN 1PPS(負論理)入力 ; RB1(07) - RX ; RB2(08) - TX ; RB3(09) IN 一位の桁を表示しない場合はLowにします。 ; RB4(10) IN 十位の桁を表示しない場合はLowにします。 ; RB5(11) - ; RB6(12) - PGC ; RB7(13) - PGD ; VSS(05) - VSS ; VDD(14) - VDD ; _INTOSC_OSC_NOCLKOUT と _MCLRE_OFF を同時に指定すると警告されます (^^;; __CONFIG _INTOSC_OSC_NOCLKOUT & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _BOREN_OFF & _LVP_OFF & _CPD_OFF & _CP_OFF ; Messageが出るのが嫌いなのでBank1のレジスタは再定義してあります。 ; 再定義してあるレジスタをバンク切り替えなしに使っていたらどこか間違ってます。 _OPTION EQU H'01' _TRISA EQU H'05' _TRISB EQU H'06' _PIE1 EQU H'0C' _TXSTA EQU H'18' _SPBRG EQU H'19' CBLOCK 20h SAVE_W ; 割り込みルーチンのレジスタ退避用 SAVE_S ; 〃 ほんとはスタックにすべきだと思います。 BUF ; 受信データのバッファ CPtr ; 比較文字列位置 ; "$"からの文字数です。"$"があるところを0とします。 CCmp ; 文字列比較ステータス 一致したら CCmp<0>=1 LST1PPS ; 直前の1PPSの状態を保存します。 0:Low,1:High ICNT ; 1PPS信号が出力されてからの割り込み回数(一回が4msに相当します) S01N ; 1秒先の一秒の位 NCH H10 ; 時上位 = 間接アドレス指定の先頭アドレス H01 ; 時下位 M10 ; 分上位 M01 ; 分下位 S10 ; 秒上位 S01 ; 秒下位 PRD ; ピリオド S00100 ; 秒小数点以下1桁目 S00010 ; 秒小数点以下2桁目 S00001 ; 秒小数点以下3桁目(GE-612Tにはありません) ENDFSR ; 間接アドレス指定のリミット ENDC ORG H'0000' GOTO INIT ; 割り込みルーチン(タイマー割り込み用) ORG H'0004' ; レジスタの退避 ; 割り込みの使い方 http://www.picfun.com/pic08.html を参考にさせていただきました。 ; 二種類以上の割り込みがあるときこれでいいのか?スタックを使うべき?         MOVWF   SAVE_W         SWAPF   STATUS,W         MOVWF   SAVE_S ; MOVF S01,W ; CALL SETP01 ; MOVWF PORTA ; GOTO PEND ; 1PPS信号(負論理=LOWになったときが1PPS信号の出力です)の状態を調べます。 BTFSS PORTB,0 GOTO LOWS ; 1PPS信号はHigh BSF LST1PPS,0 GOTO PUTCOL ; 1PPS信号はLow LOWS BTFSS LST1PPS,0 GOTO PUTCOL ; 1PPS信号がHighからLowに変化したとき BCF LST1PPS,0 CLRF ICNT PUTCOL BTFSS ICNT,7 INCF ICNT,F ; 1PPS信号出力後にPORTAを十秒の桁のデータで書き換えます。 ; このデータは次の1PPS出力時に表示されます。 MOVF ICNT,W SUBLW 0x64 BTFSS STATUS,Z GOTO DSPsec INCF S01,W MOVWF S01N MOVF S01,W SUBLW 0x08 BTFSS STATUS,Z GOTO CHK9S MOVLW 0x07 MOVWF PORTA GOTO PEND CHK9S MOVF S01,W SUBLW 0x09 BTFSC STATUS,Z INCF S10,F ; 50秒だったら次は60秒となるがかまわないです(テーブルで対応) BTFSS PORTB,4 GOTO PEND MOVF S10,W CALL SETP10 MOVWF PORTA GOTO PEND ; 1PPS出力後50ms程度たったらLEDを秒の一桁の位の色に変えます。 DSPsec MOVF ICNT,W SUBLW 0x0C BTFSS STATUS,Z GOTO FLLED BTFSS PORTB,3 GOTO PEND MOVF S01N,W CALL SETP01 MOVWF PORTA GOTO PEND ; LED発光終了直前の光量増加の開始タイミングを決定します。 ; タイミング決定が雑なコーディングですが光量増加の回路はもっと雑なのでだいじょうぶです (^^;; FLLED MOVF ICNT,w SUBLW 0x12 BTFSS STATUS,Z GOTO PEND ; BSF PORTA,3 ; このコーディングは要検討 PEND ; 一定時間ごとに割り込みをしたいときはここでタイマーを再開します。 ; なおUSARTの割り込みのときはこういう操作は不要です。 BCF     INTCON,T0IF ; 退避していたレジスタを戻します。 ; 割り込みの使い方は http://www.picfun.com/pic08.html を参考にさせていただきました。 ENDI SWAPF   SAVE_S,W MOVWF   STATUS SWAPF   SAVE_W,F SWAPF   SAVE_W,W RETFIE ; 10秒の位を表示するときの発光パターン、最初の50msくらいだけ光ります。 ; "0"で点灯です ; b'0000TBGR' SETP10 ANDLW 0x0F ADDWF PCL,F RETLW b'00000110' ; 0x00 R RETLW b'00000110' ; 0x01 R RETLW b'00000101' ; 0x02 G RETLW b'00000101' ; 0x03 G RETLW b'00000011' ; 0x04 B RETLW b'00000011' ; 0x05 B RETLW b'00000110' ; 0x06 R 59秒の次は60秒と考えているので.... ; ここから下は実際にはないデータです。バグったときヘンな動きをしないように入れてあります。 ; 水色に発光します。本来は表示されない色です。 RETLW b'00000001' ; 0x07 RETLW b'00000001' ; 0x08 RETLW b'00000001' ; 0x09 RETLW b'00000001' ; 0x0A RETLW b'00000001' ; 0x0B RETLW b'00000001' ; 0x0C ; ここから下はエラー時の発光色です RETLW b'00000010' ; 0x0D 紫: フレームエラー RETLW b'00000100' ; 0x0E 黄: オーバーランエラー RETLW b'00000000' ; 0x0F 白: データを一度も受信していない ; 1秒の位を表示するときの発光パターン、後半の50msくらいだけ光ります。 ; "0"で点灯です ; b'0000TBGR' SETP01 ANDLW 0x0F ADDWF PCL,F RETLW b'00000110' ; 0x00 R RETLW b'00000101' ; 0x01 G RETLW b'00000011' ; 0x02 B RETLW b'00000110' ; 0x03 R RETLW b'00000101' ; 0x04 G RETLW b'00000011' ; 0x05 B RETLW b'00000110' ; 0x06 R RETLW b'00000101' ; 0x07 G RETLW b'00000011' ; 0x08 B RETLW b'00000111' ; 0x09 - RETLW b'00000110' ; 0x0A R ; ここから下は実際にはないデータです。バグったときヘンな動きをしないように入れてあります。 ; 水色に発光します。本来は表示されない色です。 RETLW b'00000001' ; 0x0B RETLW b'00000001' ; 0x0C ; ここから下はエラー時の発光色です RETLW b'00000010' ; 0x0D 紫: フレームエラー RETLW b'00000100' ; 0x0E 黄: オーバーランエラー RETLW b'00000000' ; 0x0F 白: データを一度も受信していない ; 時刻を1秒進めます。 PLUS1S INCF S01,F SUBLW 0x0A BTFSS STATUS,Z RETURN CLRF S01 INCF S10,F SUBLW 0x06 BTFSS STATUS,Z RETURN CLRF S10 RETURN ; 電源投入後の実行ポイント ; CLRWDT はタイマー割り込みを行うための準備です ; (データシートにこうしろと書いてありました) INIT CLRWDT ; Bank1 ------------------------------- BSF STATUS,RP0 ; タイマーのプリスケーラ-分周比 ; 1PPS信号出力後にPORTAを書き換えるためにタイマーを使います。 ; b'00000000' 1:2 ; b'00000010' 1:4 ; b'00000010' 1:8 ; b'00000011' 1:16 ; b'00000100' 1:32 ; b'00000101' 1:64 ; b'00000110' 1:128 ; b'00000111' 1:256 MOVLW b'00000011' ; 256us * 16 = 4ms (4MHz) MOVWF _OPTION ; RA3は発光の最後で光量を大きくするタイミングを示します。 MOVLW   B'00100000' MOVWF   _TRISA ; 理想的な光量制御は次のような方法です。 ; センサーの縦ピクセル数をpx、センサーの走査時間をTS[sec]、1PPSの発光時間をT0[sec]としたとき ; 発光開始後t[sec]経ったときの光量は定常状態を1としたとき ;   2^(TS/t-1)  (0.0005 < t < TS) ;   2^(TS/(T0-t)-1)  (T0-TS < t < T0-0.0005) ; とします。 ; 定常状態とは 0.0005 < t < T0-0.0005 の範囲を言います。 ; 現実にこうするのはなかなか難しいと思います。最大電流を定常状態の200倍くらいにできれば ; 理想の状態と見分けはつかず、数十倍にできれば実用上は問題ないと思われます。 ; ちなみに順方向電流の絶対最大定格が20mAのLEDで10ms以下デューティ比100で50mAまでOKでした。 ; ; 余談ですがPIC等を使いPWMで光量調整してもいいと思います。 ; その場合は1PPSの発光開始をトリガーに割り込みを行い次の制約を守るようにコーディングすべきでしょう。 ; 1. 原則として1PPS発光の開始、終了のタイミングをPICで制御しない。 ; 2. 原則として1PPS発光の開始、終了瞬間に発光がOFFにならないようにコーディングする。 ; 1PPSの発光の開始/終了をPICで制御する場合は(星食観測に使うことを前提に) ; 本来の1PPSとタイミングのずれが0.0001秒以下であることを検証(実測)すべきと思います。 ; またこの条件であれば周波数が20kHz以上の場合2.は気にすることはなくなります。 ; ただ0.000001秒以上の精度があるとされるものをわざわざ精度を落として使うこともないと思います。 ; ; USARTを使うために<2:1>をセットします。 ; さらにRB0から1PPS信号を読み取るため<0>を、表示状態の変更のため<3:4>セットします。 ; (表示切替のタイミングを図るためですからほんとは1PPS信号による割り込みを使うべきです) MOVLW   B'11011111' MOVWF   _TRISB         ; Bank0 ------------------------------- BCF     STATUS,RP0 MOVLW B'00000111' MOVWF CMCON ; LED全点灯(この状態が見えたら $GPRMCメッセージを受け取れていません) MOVLW 0x00 MOVWF PORTA MOVLW 0x0F MOVWF S10 MOVWF S01 ; タイマー割り込みの周期の設定(プリスケーラ-はOPTIONにあります) MOVLW 0x00 MOVWF TMR0 ; CLRFだとプリスケーラ-も? ==> データシート ; 全般的な割り込み許可 BSF INTCON,GIE ; タイマー割り込み許可 BSF INTCON,T0IE ; ペリフェラルの割り込み許可(USARTの割り込みを許可する場合にセットします) BSF INTCON,PEIE ; Bank1 ------------------------------- BSF     STATUS,RP0 ; USARTも割り込みで処理するときは_PIE1

をセットします。 ; BSF _PIE1,RCIE ; USART(送信)も割り込みで処理するときは_PIE1

をセットします。 ; BSF _PIE1,TXIE ; 非同期通信 BCF _TXSTA,SYNC ; ボーレートジュネレーターをHigh設定しします。 ; こちらの方がボーレートの誤差が出にくい(はず)です。 BSF _TXSTA,BRGH ; ボーレートジュネレータの設定です ; 4MHzクロック、4800bpsの場合です(データシートの計算式と表参照) ; GM-316  デフォルト通信速度 ; MOVLW 0x33 ; 4MHzクロック、9600bpsの場合です(データシートの計算式と表参照) ; GE-612T デフォルト通信速度 MOVLW 0x19 MOVWF _SPBRG ; パリティーなし(送信) BCF _TXSTA,TX9 ; USART(送信)の使用を可能にします。 BSF _TXSTA,TXEN ; Bank0 ------------------------------- BCF     STATUS,RP0 ; パリティーなし(受信) BCF RCSTA,RX9 ; USART(受信)の使用を可能にします。 BSF RCSTA,SPEN ; 連続受信可(意味はよくわからないがデータシートにはこうしろと書いてあったような....) BSF RCSTA,CREN ; 1PPS信号状態を初期化します。 ; 1PPS信号は最初は出力されていないのでそれに合わせます。 BSF LST1PPS,0 ; ICNTは0x80以上になるとカウントアップされません。 BSF ICNT,7 ; ポインタと比較のステータスをクリアします。 CLRF CPtr CLRF CCmp CLRF NCH ; 受信データがあるかチェックします。 MAIN BTFSS PIR1,RCIF GOTO MAIN ; フレームエラーがあるかチェックします。 BTFSC RCSTA,FERR GOTO M_FERR ; オーバーランエラーがあるかチェックします。 BTFSC RCSTA,OERR GOTO M_OERR ; "$GPRMC"の文字列を探しそのあとにある分秒のデータを取得し表示します。 ; メッセージは"$GPRMC,HHMMSS.SS,......"の形式になっています。 ; 1文字受信 MOVF RCREG,W MOVWF BUF ; このあたりの処理はほよほよさん(http://ameblo.jp/ringworldengineer/)の記事 ;     「GPGGAメッセージからUTC Timeを取り出す 」 ;      http://ameblo.jp/ringworldengineer/entry-11727597759.html ; を参考にしました。というかほとんどそのままパクってます (^^;; ; 英語のコメントがついているところがそうです。 ; 日本語のコメントのところが私の書いたところです。日本語のコメントだけだったりもします。 ; 受信した文字を文字列"$GPRMC,"のCPtr番目と比較してていきます。 ; 一致しないときはCPtrをクリアしまた最初から比較です。 CmprT BTFSC CCmp,0 ;Keyword match flag on? GOTO CmprT_3 ;時刻(HHMMSS)を取り込みます。 MOVF CPtr,W ;no, load compare character pointer CALL Trig ;get compare character SUBWF BUF,W ;compare character BTFSC STATUS,Z ;Character match? GOTO CmprT_1 ;yes, matched CLRF CPtr ;not matched GOTO MAIN ; 比較対象文字列のCPtr番目の次の文字が0であるか調べます。 ; もし0なら比較文字列と一致するメッセージを受信したことがわかります。 ; 0でないときは次の文字を取り込みます。 CmprT_1 INCF CPtr,F MOVF CPtr,W CALL Trig XORLW 0 BTFSC STATUS,Z ;All match? GOTO CmprT_2 ;yes, matched GOTO MAIN ; 比較対象文字列と完全に一致しました。 ; 時刻データを取り込む準備をします。 CmprT_2 BSF CCmp,0 ;Keyword match flag on MOVLW H10 MOVWF FSR ; 間接アドレス指定を使って順に格納します。 CLRF NCH GOTO MAIN ; ','が現れたら時刻の取り込みをやめます。 ; 時刻(HHMMSS)を取り込みます。 CmprT_3 MOVF BUF,W MOVWF TXREG ; 時刻データは","をセパレータとして出力していきます。 MOVLW ',' SUBWF BUF,W BTFSS STATUS,Z GOTO SVCHR BCF CCmp,0 GOTO MAIN SVCHR MOVF BUF,W ANDLW 0x0F MOVWF INDF INCF FSR,F ; MOVLW FSR ; こっちの方がいいはず? ; SUBLW ENDFSR INCF NCH,F MOVF NCH,W ; 不要なはず? SUBLW 0x0A BTFSS STATUS,Z GOTO MAIN BCF CCmp,0 GOTO MAIN ; ここに来るのは意図していない状況なんですが... ; "$GPRMC,"を探すためのテーブルです。 ; "DT"は文字列から"RETLW ..."の繰り返しを作るマクロです。 Trig ADDWF PCL,F DT "$GPRMC,",0 ; フレームエラー ; ボーレートが間違っているかシリアルデータの品質に問題があります。 ; データを読み込むことによってRCSTA

はクリアされます。 ; エラー処理は適当です。 M_FERR MOVLW 0x0E MOVWF S10 MOVWF S01 MOVF RCREG,W GOTO MAIN ; オーバーランエラー ; 処理が間に合っていない? ; RCSTA

をクリアして再度セットします。 ; エラー処理は適当です。 M_OERR BCF RCSTA,CREN BSF RCSTA,CREN MOVLW 0x0D MOVWF S10 MOVWF S01 GOTO MAIN END

« カテリナ彗星Catalina (C/2013 US10)はほんとうに肉眼で見えるの? 光度等級-高度-方位角-月との離角 | トップページ | JAXAのデータではやぶさ/スイングバイの視位置を予測する »

時刻と時間」カテゴリの記事

コメント

この記事へのコメントは終了しました。

トラックバック

« カテリナ彗星Catalina (C/2013 US10)はほんとうに肉眼で見えるの? 光度等級-高度-方位角-月との離角 | トップページ | JAXAのデータではやぶさ/スイングバイの視位置を予測する »

フォト

サイト内検索

  • 記事を探されるんでしたらこれがいちばん早くて確実です。私も使ってます (^^;; 検索窓が表示されるのにちょっと時間がかかるのはどうにかしてほしいです。

新着記事

リンク元別アクセス数

  • (アクセス元≒リンク元、原則PCのみ・ドメイン別、サイト内等除く)

人気記事ランキング

  • (原則PCのみ、直近2週間)
無料ブログはココログ