したらばTOP ■掲示板に戻る■ 全部 1-100 最新50 | |

■■■20レス以内で済むF-BASICの質問はこちらへ■■■

1F橋:2003/12/19(金) 20:48
20レス以内程度(20回程度の投稿)で終わりそうなF-BASICの質問はこちらでお願いします
短い質問のスレッドがいくつも立つより1つのスレッドで固まっていた方が長期に渡り見ることができ
かつ保存も簡単かと…

(いや…私だけでなく…皆さんも簡単のはずなんですが…(汗(笑)))

掲示板の内容の長期保存にご協力頂ける様よろしくお願いします

613k5:2015/10/22(木) 09:00:47
丁寧にありがとうございます。

この機器は"D"を送ると、4行(1行がバイト)のデータが送られてくる単純なものだと理解しています。GW-BASICでも確認しています。

さっそくテストサンプルを実行してみました。

「受信バッファが空でない!」

の表示で終了してしまいます。

この行をコメントアウトして実行すると、!!受信始!!のループに入りますが、データの送信が始まらないので、ここから先には進みません。

これは、デジタルマルチメータのバッファに何か残っているということなのですね。ケーブルの結線を調べてみます。

614598:2015/10/23(金) 05:13:57
>>613
 その通り単純なもので、"D"文字列を受けて計測データを文字列で送信する
仕組みで、PC側の状態はおかまいなしで送信するものと思われます。

※GW-BASICの",rs"オプションが気になりますが。
(RS suppresses detection of RTS(Request To Send))


 「受信バッファが空でない!」の行は念のため入れたもので、動作テストを連続で
行った場合とか、まあ無くは無いかと・・。それにNUL charを受信したとのご報告の
件もあるので。 引っかかるとは思いませんでしたが。
本当に入っているのかは「?」ですけど。OPEN時にバッファをフラッシュしないのか?

 とりあえずその行は次のように変更して、画面にそのデータを表示させてみましょう。

if not eof(1) then R$(0)=input$(LOF(1),#1):print "受信??";R$(0):R$(0)=""

 次にコマンド送信ですが、送信バッファに溜まったままで測定器へは送信されていない
可能性も考えられなくはありません。これはprint# を前の形に戻すと変わるかもしれません。

print#2,"D" '←←←print#2,"D";chr$(13);

 そして、print#を変更しても戻しても「!!受信始!!」後のループで進まない
場合は一度、受信チェックのループ行を外してみます。

'while lof(1) < 14*4 :print ... ←コメントアウト


 そして、ここまで変更して、print#を変更しても戻してもうまく受信できない場合は、
さらに変更します。

※表示される受信データはうまく改行されないためおそらく表示がおかしくなると思います。
※もし「wait 100」を外すと「データバイト数」の値が増えるようなら・・考えます..。

print:print"!!受信始!!"
wait 100
R$(0)=input$(LOF(1),#1)
print "データバイト数=";len(R$(0))
print R$(0)
close
stop :end

615名無しさん:2015/10/23(金) 23:44:35
本当にいろいろとありがとうございます。

ケーブルを調べてみたのですが、普通のストレートでした。


今日は別の計測機で、F-BASICでデータが取る出せるか見てみました。

その計測器に送るコマンドはこのようなものでした。

asc(22)asc(02)[命令]asc(03)asc(13)asc(10)
<SYN><STX>[命令]<ETX><CR><LF>

これを文字列(TEST$)で作って

print#2,TEST$

としたのですが、残念ながら何も表示されません。

ただ、これをファイルに保存して、teratermでファイル転送(バイナリ)とすると計測器からのデータが表示されます。仰るように、「送信バッファに溜まったままで測定器へは送信されていない」のかも知れません。次は"D"だけのバイナリファイルを作って、teratermのファイル転送(バイナリ)をしてみます。

616598:2015/10/24(土) 06:34:13
>>615
Win32 APIを使ってCOM1シリアルポートに“残っている”通信条件設定を
取得するプログラムです。(ただし一部表示していない情報があります)
※なお、送受信バッファサイズなどは取得できません(別のAPI関数が必要なので)。

このプログラムを次の各段階毎に実行して、設定状態に違いがあれば、
なにか手がかりになるかもしれません。
1.Windows 起動直後
2.GW-BASICの受信サンプル実行で正常受信した後
3.F-BASICで一回オープン"COM0:(S7N2N7NNN)"クローズした後

注意:declare文は長いため途中で改行してますので、つないで
一行にして翻訳してください。


#define NULL BYVAL 0

'// fBitFields as long のビット定義
#define FBinary &H1 '//0 BINARY MODE, WINDOWSでは常に1
#define fParity &H2 '//1 パリティチェック
#define fOutxCtsFlow &H4 '//2 CTS output フロー制御
#define fOutxDsrFlow &H8 '//3 DSR output フロー制御
#define fDtrControl &H30 '//4:2 DTR フロー制御タイプ
'-DTR_CONTROL_DISABLE 0
'-DTR_CONTROL_ENABLE 1
'-DTR_CONTROL_HANDSHAKE 2
#define fDsrSensitivity &H40 '//6 DSR sensitivity
#define fTXContinueOnXoff &H80 '//7 XOFF continues Tx
#define fOutX &H100 '//8 XON/XOFF output フロー制御
#define fInX &H200 '//9 XON/XOFF input フロー制御
#define fErrorChar &H400 '//10 enable error replacement
#define fNull &H800 '//11 NULL BYTES 受信を破棄する
#define FRTSCONTROL &H3000 '//12:2 RTS フロー制御タイプ
'-RTS_CONTROL_DISABLE 0
'-RTS_CONTROL_ENABLE 1
'-RTS_CONTROL_HANDSHAKE 2
'-RTS_CONTROL_TOGGLE 3
#define fAbortOnError &H4000 '//14 abort reads/writes on error
'fDummy2 '//15:17 reserved

Type T_DCB
DCBlength As Long
BaudRate As Long
fBitFields As Long ' Bits
wReserved As Integer
XonLim As Integer
XoffLim As Integer
ByteSize As Byte
Parity As Byte
StopBits As Byte
XonChar As Byte
XoffChar As Byte
ErrorChar As Byte
EofChar As Byte
EvtChar As Byte
wReserved1 As Integer
end type

declare function CREATEFILE lib "kernel32" alias "CreateFileA" (byval LPFILENAME as string,
byval DESACC as long, byval SHAREMODE as long,
byref LPSECUATTR as any, byval CREDISPOS as long,
byval FLAGSATTR as long, byval HTEMPLFILE as long) as long

declare function CLOSEHANDLE lib "kernel32" alias "CloseHandle" (byval HOBJECT as long) as long
declare function GETCOMMSTATE lib "kernel32" alias "GetCommState" (byval NCID as long,
LPDCB as T_DCB) as long
declare function SETCOMMSTATE lib "kernel32" alias "SetCommState" (byval HCOMMDEV as long,
LPDCB as T_DCB) as long

#define GENERIC_READ (-CLNG(&HFFFFFFFF - &H80000000)-1)
#define GENERIC_WRITE &H40000000
#define OPEN_EXISTING 3
#define FILE_SHARE_READ &H1
#define FILE_SHARE_WRITE &H2
#define INVALID_HANDLE_VALUE -1

617598:2015/10/24(土) 06:36:18
>>616 の続きです。

declare function TEST1_CBIT(V as long,B as long) as long
function TEST1_CBIT(V as long,B as long) as long
var I as long,J as long
TEST1_CBIT=V
if B=0 then error 5:exit function
if B<0 then error 11:exit function '未実装
I=B :J=1
do while (I mod 2 = 0)
J=J * 2 : I=I \ 2
loop
TEST1_CBIT=(V and B) \ J
if ((V and B) mod J) <> 0 then error 21
end function

declare sub TEST1_GetState()
sub TEST1_GETSTATE()

var RES as long
var hfile as long
var DCB as T_DCB
var F as long

HFILE=INVALID_HANDLE_VALUE
HFILE = CREATEFILE("COM1", (GENERIC_READ or GENERIC_WRITE), 0, NULL, OPEN_EXISTING, 0, NULL)
if HFILE= INVALID_HANDLE_VALUE then print "Error:open失敗":exit sub

RES=GetCommState(hfile, DCB)
if RES=0 then
print "Error:GetCommState"
RES=CLOSEHANDLE(HFILE)
else
RES=CLOSEHANDLE(HFILE)

if DCB.DCBLENGTH<>len(T_DCB) then print "!!DCBlength(hex)=";DCB.DCBLENGTH
'**取得結果の表示**
F=DCB.FBITFIELDS '*bit分解必要
print "fBitFields(16進数)=";hex$(DCB.FBITFIELDS)
print "fOutxCtsFlow=";TEST1_CBIT(F, FOUTXCTSFLOW)
print "fOutxDsrFlow=";TEST1_CBIT(F, FOUTXDSRFLOW)
print "fDtrControl=";TEST1_CBIT(F, FDTRCONTROL);"(DTR フロー制御タイプ:0..2)"
print "fDsrSensitivity=";TEST1_CBIT(F, FDSRSENSITIVITY)
print "fErrorChar=";TEST1_CBIT(F, FERRORCHAR) ;"(エラー時文字置き換える)"
print "fNull=";TEST1_CBIT(F, fnULL) ;" (NULL BYTES 受信を破棄する=1)"
print "fRtsControl=";TEST1_CBIT(F, FRTSCONTROL) ;" (RTS フロー制御:0..3)"
print "fAbortOnError=";TEST1_CBIT(F, FABORTONERROR)
print
print "ByteSize=";DCB.BYTESIZE
print "StopBits=";DCB.STOPBITS ;" (stopビット:0=1,1=1.5,2)"
print "ErrorChar(16進)=";hex$(DCB.ERRORCHAR)
print "EofChar(16進)=";hex$(DCB.EOFCHAR)
print "EvtChar(16進)=";hex$(DCB.EVTCHAR)
endif
end sub

'-----
TEST1_GETSTATE '←取得処理の実行
print "終了します。なにかキーを押してください。"
while inkey$="":wend
end

618598:2015/10/24(土) 06:51:23
追伸、実行結果の画面のテキストをクリップボードにコピーできます。
操作方法はALT+SPACEキー入力でコントロールメニューが表示
されるので、一番下の「コピー(Y)」-「テキスト(T)」を選択。

619598:2015/10/24(土) 08:17:56
>>615

>>616 の手順を一部訂正します。
>このプログラムを次の各段階毎に実行して、設定状態に違いがあれば、
>なにか手がかりになるかもしれません。
--
1.Windows 起動直後
2.(1回目)F-BASICで一回オープン"COM0:(S7N2N7NNN)"クローズした後
3.GW-BASICの受信サンプル実行で正常受信した後
4.(2回目)F-BASICで一回オープン"COM0:(S7N2N7NNN)"クローズした後
--以上、訂正です。

620名無しさん:2015/10/24(土) 16:54:52
ありがとうございます
(なんとお礼をしたらいいか)

早速、月曜日に研究室に行ったらやってみます。

これまで違う計測機器やモデムの簡単な制御をF-BASICでやったことはあるのですが、

PRINT #2,"D"

を実行すると

D(CR)(LF)
44 0d 0a

の3バイトのコードがCOMに送らると思っていました。処理系によって違うのか不思議に思っています。それ以外にタイミングなどの問題があるのかもしれません。シリアル制御は奥が深そうです

621名無しさん:2015/10/24(土) 23:32:36
>※GW-BASICの",rs"オプションが気になりますが。
>(RS suppresses detection of RTS(Request To Send))
QuickBasicのマニュアルにも"RTSを抑制する"とありましたが、「抑制」とはどういう意味で使われているのでしょうね。いままでよくわからずに使っていました。

RTS信号をめぐる混乱
http://d.hatena.ne.jp/licheng/20130530/p1
http://www15.atpages.jp/limz80msx/program/rs232c.html

622名無しさん:2015/10/25(日) 04:32:44
>>620

行端(行末)コードで使われている制御コード(コントロールコード)
CRはキャリッジリターン、LFはラインフィード。

これらはテレタイプ端末(電動機械式タイプライタ)の時代にまで遡り、
TTY通信とか言ってましたっけ。

CR+LFで「復帰改行」。これはタイプライタ(プリンタ)の動きの制御のため、
キャリッジ(紙をはさんで左右に動く機構)を1行の先頭の方へ戻し、
次に紙を送り出す(紙を次の行へ進める)。

今の時代、画面での改行や単に1行分のデータの末端を示すのなら
コード1つで十分なので、CRかLFのみにすれば通信量(費用・時間)が節約できると。

そのため、通信ソフト類ではどの改行コードを使うか設定する機能を持つ。

その昔、CP/Mが改行コードに「CR+LF」採用したので結果的に、MS-DOSも
「CR+LF」になったらしい。
MS-DOS上のF-BASICも当然そうなったと。

623名無しさん:2015/10/25(日) 12:08:17
行末コードはよるトラブルの元になりますね。MACはCR,UnixはLF,MS-DOSはCR/LFですが、CP/MはPDPの影響でCR/LFを採用したんでしたっけ。

F-BASICもCOMポートをバイナリモードでopenして、fwriteとかfreadが使えると嬉しいのですが。

624名無しさん:2015/10/26(月) 10:00:09
おはようございます

さっそく、COM1の通信条件設定を調べるプログラムを実行してみました。


1.Windows 起動直後
2.(1回目)F-BASICで一回オープン"COM0:(S7N2N7NNN)"クローズした後
3.GW-BASICの受信サンプル実行で正常受信した後
4.(2回目)F-BASICで一回オープン"COM0:(S7N2N7NNN)"クローズした後
5.GW-BASICの受信サンプル実行で正常受信した後


あれれ、STOP BITが1になっていますね。


1回目

fBitFields(16進数)=1011
fOutxCtsFlow= 0
fOutxDsrFlow= 0
fDtrControl= 1 (DTR フロー制御タイプ:0..2)
fDsrSensitivity= 0
fErrorChar= 0 (エラー時文字置き換える)
fNull= 0 (NULL BYTES 受信を破棄する=1)
fRtsControl= 1 (RTS フロー制御:0..3)
fAbortOnError= 0
ByteSize= 7
StopBits= 0 (stopビット:0=1,1=1.5,2)
ErrorChar(16進)=0
EofChar(16進)=0
EvtChar(16進)=0
終了します。なにかキーを押してください。


2回目
fBitFields(16進数)=1011
fOutxCtsFlow= 0
fOutxDsrFlow= 0
fDtrControl= 1 (DTR フロー制御タイプ:0..2)
fDsrSensitivity= 0
fErrorChar= 0 (エラー時文字置き換える)
fNull= 0 (NULL BYTES 受信を破棄する=1)
fRtsControl= 1 (RTS フロー制御:0..3)
fAbortOnError= 0
ByteSize= 7
StopBits= 2 (stopビット:0=1,1=1.5,2)
ErrorChar(16進)=0
EofChar(16進)=0
EvtChar(16進)=0
終了します。なにかキーを押してください。

625名無しさん:2015/10/26(月) 10:00:50
3回目
fBitFields(16進数)=1
fOutxCtsFlow= 0
fOutxDsrFlow= 0
fDtrControl= 0 (DTR フロー制御タイプ:0..2)
fDsrSensitivity= 0
fErrorChar= 0 (エラー時文字置き換える)
fNull= 0 (NULL BYTES 受信を破棄する=1)
fRtsControl= 0 (RTS フロー制御:0..3)
fAbortOnError= 0
ByteSize= 5
StopBits= 0 (stopビット:0=1,1=1.5,2)
ErrorChar(16進)=0
EofChar(16進)=0
EvtChar(16進)=0
終了します。なにかキーを押してください。

4回目
fBitFields(16進数)=1011
fOutxCtsFlow= 0
fOutxDsrFlow= 0
fDtrControl= 1 (DTR フロー制御タイプ:0..2)
fDsrSensitivity= 0
fErrorChar= 0 (エラー時文字置き換える)
fNull= 0 (NULL BYTES 受信を破棄する=1)
fRtsControl= 1 (RTS フロー制御:0..3)
fAbortOnError= 0
ByteSize= 7
StopBits= 2 (stopビット:0=1,1=1.5,2)
ErrorChar(16進)=0
EofChar(16進)=0
EvtChar(16進)=0
終了します。なにかキーを押してください。



5回目
fBitFields(16進数)=1011
fOutxCtsFlow= 0
fOutxDsrFlow= 0
fDtrControl= 1 (DTR フロー制御タイプ:0..2)
fDsrSensitivity= 0
fErrorChar= 0 (エラー時文字置き換える)
fNull= 0 (NULL BYTES 受信を破棄する=1)
fRtsControl= 1 (RTS フロー制御:0..3)
fAbortOnError= 0
ByteSize= 7
StopBits= 0 (stopビット:0=1,1=1.5,2)
ErrorChar(16進)=0
EofChar(16進)=0
EvtChar(16進)=0
終了します。なにかキーを押してください。

626598:2015/10/26(月) 11:22:21
>>625
えーと、
3回目(GW-BASIC1回目)と5回目(GW-BASIC2回目)、なんか違ようですが
なぜなんだろう?。

fDtrControl= 0 (DTR フロー制御タイプ:0..2)
fRtsControl= 0 (RTS フロー制御:0..3)
ByteSize= 5

fDtrControl= 1 (DTR フロー制御タイプ:0..2)
fRtsControl= 1 (RTS フロー制御:0..3)
ByteSize= 7

1回目(起動直後)と5回目(GW-BASIC2回目)が同じなので、
これは初期状態に戻ったということかな・・。

次に、F-BASICと3回目(GW-BASIC1回目)との違い。

[FB]
fDtrControl= 1 (DTR フロー制御タイプ:0..2)
fRtsControl= 1 (RTS フロー制御:0..3)
ByteSize= 7
StopBits= 2 (stopビット:0=1,1=1.5,2)

[GW]
fDtrControl= 0 (DTR フロー制御タイプ:0..2)
fRtsControl= 0 (RTS フロー制御:0..3)
ByteSize= 5
StopBits= 0 (stopビット:0=1,1=1.5,2)


うーーーん、fRtsControlがカギなんだろうか。

このデジタルマルチメータ側のシリアル端子の動作を勘違いしていたのかも。
 PC側の状態を見ないのではなくて、PC側の状態で測定データを送信するか
どうかを決めるが、PC側には自分の状態を知らせないから無視してコマンド送信
しなさいということかもしれない。

するとRS-232C間を、半二重通信でやりとりしなさいということかもしれない。

627名無しさん:2015/10/26(月) 17:17:01
ありがとうございます。

もう一度やってみました。

最初ににポートのopen/closeをした後にGW-BSIACを実行し、シリアルポートの状態を調べ、その後にポートのopen/closeをした後にシリアルポートの状態を調べ、さらにGW-BSIACを実行した後にシリアルポートの状態を調べています。

ポートのopen/close

var CM$
baud 0,9600
CM$="COM0:(S7N2N7NNN)"
open CM$ for output as #2
open CM$ for input as #1
close
end

1回目
fBitFields(16進数)=1
fOutxCtsFlow= 0
fOutxDsrFlow= 0
fDtrControl= 0 (DTR フロー制御タイプ:0..2)
fDsrSensitivity= 0
fErrorChar= 0 (エラー時文字置き換える)
fNull= 0 (NULL BYTES 受信を破棄する=1)
fRtsControl= 0 (RTS フロー制御:0..3)
fAbortOnError= 0
ByteSize= 5
StopBits= 0 (stopビット:0=1,1=1.5,2)
ErrorChar(16進)=0
EofChar(16進)=0
EvtChar(16進)=0


2回目
fBitFields(16進数)=1011
fOutxCtsFlow= 0
fOutxDsrFlow= 0
fDtrControl= 1 (DTR フロー制御タイプ:0..2)
fDsrSensitivity= 0
fErrorChar= 0 (エラー時文字置き換える)
fNull= 0 (NULL BYTES 受信を破棄する=1)
fRtsControl= 1 (RTS フロー制御:0..3)
fAbortOnError= 0
ByteSize= 7
StopBits= 2 (stopビット:0=1,1=1.5,2)
ErrorChar(16進)=0
EofChar(16進)=0
EvtChar(16進)=0


3回目
fBitFields(16進数)=1011
fOutxCtsFlow= 0
fOutxDsrFlow= 0
fDtrControl= 1 (DTR フロー制御タイプ:0..2)
fDsrSensitivity= 0
fErrorChar= 0 (エラー時文字置き換える)
fNull= 0 (NULL BYTES 受信を破棄する=1)
fRtsControl= 1 (RTS フロー制御:0..3)
fAbortOnError= 0
ByteSize= 7
StopBits= 0 (stopビット:0=1,1=1.5,2)
ErrorChar(16進)=0
EofChar(16進)=0
EvtChar(16進)=0


fDtrControl= 0 (DTR フロー制御タイプ:0..2)
fDtrControl= 1 (DTR フロー制御タイプ:0..2)
fDtrControl= 1 (DTR フロー制御タイプ:0..2)

fRtsControl= 0 (RTS フロー制御:0..3)
fRtsControl= 1 (RTS フロー制御:0..3)
fRtsControl= 1 (RTS フロー制御:0..3)

ByteSize= 5
ByteSize= 7
ByteSize= 7

StopBits= 0 (stopビット:0=1,1=1.5,2)
StopBits= 2 (stopビット:0=1,1=1.5,2)
StopBits= 0 (stopビット:0=1,1=1.5,2)


うーん、なんでこんなに設定が変わるのかわかりません。
変わっていないのは、StopBitsが1になっていることだけです。

628名無しさん:2015/10/26(月) 19:28:10
こんばんは

元のGW-BASICに返ってみました

open "com1:9600,n,7,2,rs,cs,ds,cd" as #2

QuickBasicのマニュアルによる、これらのオプションの意味は下記の通り

rs:RTSの検知を抑制
cs:CTSのタイムアウトを抑制
ds:DSRのタイムアウトを抑制
cd:DCDのタイムアウトを抑制


この中で、csとcdのオプションは省いてもデータは読み取れました。

open "com1:9600,n,7,2,rs,ds" as #2

これをF-BASICにすると、


OPEN "COM0:(S7N2N7NN,CS0,DS0)" as #2

となると思うんですが、これでもまだ読めません。
うーん、近くまで来ていると思うのですが、また明日挑戦してみます

629598:2015/10/27(火) 04:22:26
>>628
F-BASICがopen時設定したCOMポートへの通信条件設定を強制変更する
プログラムです。fRtsControlの設定を変更しています。

注:これは >616 のプログラムの後ろに続きます。(つまり >617 を差し替える)

#define RTS_CONTROL_DISABLE &H0
#define RTS_CONTROL_TOGGLE &H3

private declare function ADDR(byref A as long) as long
function ADDR(A as long) as long
'print "test=";hex$(varadr(A))
ADDR=A
end function
declare function _PBGETDCBNO alias "_$PbGetDCBNo@4" (byval FILENO as long) as long
declare function _PBGETDCB alias "_$PbGetDCB@4" (byval FBDCBNO as long) as long
declare function FB63_GETFILEHANDLE bdecl (byval FILENO as integer) as long
function FB63_GETFILEHANDLE (byval FILENO as integer) as long
var FBDCBNO as long, FBDCBDATA as long
FB63_GETFILEHANDLE= INVALID_HANDLE_VALUE
select case FILENO
case 1 to 255
FBDCBNO= -1
FBDCBNO= _PBGETDCBNO(clng(FILENO))
if FBDCBNO = -1 then error 57:exit function
FBDCBDATA=0
FBDCBDATA=_PBGETDCB(FBDCBNO)
if FBDCBDATA = 0 then error 60:exit function
FB63_GETFILEHANDLE=FBDCBDATA
FBDCBDATA=FBDCBDATA+&H108 'オフセット
FB63_GETFILEHANDLE=ADDR(byval FBDCBDATA)
case else
error 50
end select
end function

declare sub TEST2_SETSTATE(byval FILENO%)
sub TEST2_SETSTATE(byval FILENO%)
var RES as long
var DCB as T_DCB, HFILE as long
var F as long, M as long

HFILE= FB63_GETFILEHANDLE(FILENO%)
if HFILE=0 or HFILE=-1 then HFILE=INVALID_HANDLE_VALUE

if HFILE= INVALID_HANDLE_VALUE then print "Error:open":exit sub
RES=GetCommState(hfile, DCB) 'ポートの設定取得
if res=0 then
print "Error:GetCommState"
else
if DCB.DCBLENGTH<>len(T_DCB) then print "!!DCBlength(hex)=";DCB.DCBLENGTH
print "fBitFields(16進数)変更前=";hex$(DCB.FBITFIELDS)

'**ここで設定を変更する**
F=DCB.FBITFIELDS '*bit毎設定必要
'----fRtsControl----
F=F and (not FRTSCONTROL) 'ビット消去
M=FRTSCONTROL :M=M and (M \ 2) '※下位ビットを残す
M=M * RTS_CONTROL_TOGGLE '設定値
F=F or M 'ビット設定
print "fRtsControl書換";RTS_CONTROL_TOGGLE ;" (RTS フロー制御:0..3)"
'--------
DCB.FBITFIELDS=F '設定
'****
print "fBitFields(16進数)変更後=";hex$(DCB.FBITFIELDS)

'設定を強制更新する
RES=SetCommState(hfile, DCB)
if res=0 then
print "Error:SetCommState"
endif
endif
end sub

'--------
var CM$, R$(4-1)
baud 0,9600
CM$="COM0:(S7N2N7NNN)"
open CM$ for output as #2 : open CM$ for input as #1
TEST2_SETSTATE 2 '←ファイル番号のCOM設定を強制変更する
WAIT 100

if not eof(1) then print "!!受信バッファが空でない!"

print"!!送信始!!"
print#2,"D";chr$(13);
wait 50
while eof(1) :print"*"; :wend ' 受信開始までループ
print:print"!!受信始!!"
wait 5
while lof(1) < 14*4 :print"."; :wait 5 :wend ' 全フレーム受信までループ
print:print"!!受信終!!"
line input#1,R$(0) :print "!!Frame-1入力"
line input#1,R$(1) :print "!!Frame-2入力"
line input#1,R$(2) :print "!!Frame-3入力"
line input#1,R$(3) :print "!!Frame-4入力"
close
stop:end

630名無しさん:2015/10/27(火) 09:14:21
ありがとうございました。
作成していただいたプログラムでデータを計測器から読み込むことができました。

これが実行結果です。

fRtsControl書換 3 (RTS フロー制御:0..3)
fBitFields(16進数)変更後=3011
!!受信バッファが空でない!
!!送信始!!
!!受信始!!
!!受信終!!
!!Frame-1入力
!!Frame-2入力
!!Frame-3入力
!!Frame-4入力
AC 096.01 V 13
13
FR 00.060 kHz 13
dB 041.86 dBm 13
中断しました com_cond2.bas[165行]
任意のキーを押してください

もし、可能でしたら、計測器と通信できなかった理由を教えていただけると勉強になります。


ここからは報告です。

連続したデータが欲しいので、FOR NEXTのループを作りました。
下記がその中の命令です。

>print#2,"D";chr$(13);
>line input#1,R$(0) :print "!!Frame-1入力"
>line input#1,R$(1) :print "!!Frame-2入力"
>line input#1,R$(2) :print "!!Frame-3入力"
>line input#1,R$(3) :print "!!Frame-4入力"

実行すると、一番最初に読み込んだデータ(R$(0))の先頭に00(NULL)が2バイト付いていました。

(00)(00)AC 096.01 V 13

R$(1)〜R$(3)は問題ありません。

そして、2番目ループ以降は00(NULL)が1バイトになりました。
(00)AC 096.01 V 13

R$(1)〜R$(3)は問題ありません。

プログラムで取ってしまえば問題ないのですが、このNULLが少し気になります。

今回はありがとうございました。
本当に助かりました。

631名無しさん:2015/10/28(水) 12:02:26
>>630  まずは原因の方から。
最初に推定するための情報を列挙します。
通信条件設定の表示テスト結果 >624-625 >626 から違いを見ると、
[fDtrControl]
0=DTR_CONTROL_DISABLE (DTRは常にOFF)←[GW-BASIC]
1=DTR_CONTROL_ENEBLE (DTRは常にON) ←[F-BASIC]
[fRtsControl]
0=RTS_CONTROL_DISABLE (RTSは常にOFF)←[GW-BASIC]
1=RTS_CONTROL_ENABLE (RTSは常にON) ←[F-BASIC]
そして >611 のデジタルマルチメータのデータ通信資料、(コネクタに無い信号線がある)
そして >621 のRS-232Cの関連情報、QuickBasicの通信条件オプション(,rs)

 次に通信条件設定の内容とテストの状況から、要因を探ります。

・F-BASICで受信時に「[27]システムに異常があります」原因不明エラーで受信不能。
ただ、ヌル(00h)が受信されていた。とりあえず受信不可能ではないらしい。
・ケーブルは普通にストレート。問題なし。
・ポートはマザーボードのものでUSB変換ではないし、GW-BASICで使えている。
・デジタルマルチメータ側端子には無い信号線がある。
・ハードウェアフロー制御はなし。→(通信量的に必要ないし無用な製品製造コスト)
・DSRの状態はPC側で無視している。
・CTSは?。PC側でCTS監視による送信フローはしない設定。→たぶんPC側ですべて無視。
・DTRはON/OFFどちらでも反応(受信)はする。→たぶん無視している。
・GW-BASICの通信条件オプション(,rs)→PC側でRTS関連のなにかを無視して通信している。
・RTSが常時OFFでもGW-BASICで正常通信できる。→無視しているのか?
・RTSが常時ONのF-BASICではデータ受信できない。→なぜ?。では完全無視ではない!。

可能性1-コマンド送信ができないまたは送信したが無視される。
$A-送信ができない。→DSRは無視、CTSは見ない。だから送信できないことはないだろう。
$B-送信したコマンドが無視される。→なぜ?。print# は変更しても変わらなかった。
$→それでは別の要因でABいずれかの問題が発生か?→要因は何か?設定違いはRTS、DTR。
可能性2-データ受信ができないまたは送って来ない。
$A-受信ができない。→RTS常時ONだから?。そもそも受信できないはずがない・・。
$B-データを送って来ない。→RTS常時ONだから?。なぜ?。
$C-送って来たデータをPC側が無視した?。→DSRは無視しているはずだし、Aに同じ。
$→要因は何か?設定違いはRTS、DTR。

 これらから原因を推測すると、
DTRの可能性は低そう。DTR常時OFFで動くし、フロー制御なし設定なのだから。
ただしDTRをONにしていると(PC側の機種の判断材料)動作が変更されるのなら話は別だが…。
RTSの可能性が濃厚。それにF-BASICには",rs"オプションに当てはまりそうなものは無い。

RTSの違いが原因だと仮定して、とりあえずRTSをGW-BASICと同じく常時OFFに設定すればよい。
RTSがONだと送信または受信に支障が出るとすると、
  送 受
OFF○ ○(これは成功)
ON × - 送信で失敗と仮定だと→コマンド送信失敗ではデータが来ない…。
ON ○ × 受信で失敗と仮定だと→ONでも送信できるが、受信は失敗。
ON × × 両方失敗と仮定→常時OFFでなければ失敗。

ただ、送信時と受信時でON/OFFが異なれば受信成功するという可能性もまだある。
そのような場合のRTS(Request To Send)の動きは半二重通信方式の場合が考えられる。
半二重通信では送信と受信を同時には行えず、送信する時にはONにする。
これに該当しそうな設定は、次のものらしい。
3=RTS_CONTROL_TOGGLE (トグル)
(有効な送信用Bytes(データ)があればRTSをONにする。バッファのデータを
すべて送信した後、RTSをOFFにする。)

 とりあえずの結論としては、RTS_CONTROL_TOGGLEに設定してみるか、
RTS_CONTROL_DISABLE (RTSは常にOFF)にできれば通信はできると予想。

632名無しさん:2015/10/29(木) 02:57:36
>>630
 今回の問題は、GW-BASICというよりIBM PC初期の時代に依存している
・RS-232Cの制御線をほとんど無視して使わない、簡略化した通信。
・IBM PCが世界のすべて。IBM PCの都合(制約)にあわせる。
(IBM PCのシリアルポートは「シリアルポート」であって厳密にはRS-232C準拠ではない。)
・機器側に省略された制御線があるので普通の全二重通信はできないし、
使う前提ともしていない。(RS-232C準拠と言えない)
・通信電文は短かく、ハードウェアフロー制御(全二重通信)はない。
・送出した通信電文が欠落などしないという前提。

・通信は必ずPC側から始まる。(だから全二重通信なんていらない)
・半二重通信もどきで十分だ。(さらに簡略化している)
・簡略化しているので相手の通信状態なんて原則無視。
・この簡略化した通信方法は低い製造コストでIBM PCと通信できるように最適化。
(その方法がバッドノウハウで長年継承されている。)

・F-BASICは半二重通信方式をサポートしない。
(たとえば半二重モデム側が問題吸収する必要がある)
・F-BASICはRS-232C準拠といえない通信手順は使用する前提としていない。


ゆえに通信条件設定をF-BASICから強制的に変更しなければならない。
[fRtsControl]
0=RTS_CONTROL_DISABLE (RTSは常にOFF)←[GW-BASIC]
1=RTS_CONTROL_ENABLE (RTSは常にON) ←[F-BASIC]

633598:2015/10/29(木) 03:43:08
>>630
>プログラムで取ってしまえば問題ないのですが、このNULLが少し気になります。

 00(NULL)についてですが、いくつか可能性を挙げてみると、

・RTSをONにすると送ってくる。(なにかの対策のための動作?)
・RTSの変化に応じて送ってくる。(制御線を使わないので、代替の応答としている。)
・測定データ送信時の先触れとして送っている。(データ受信取りこぼしを防ぐため?)
・PC側から送信したコマンドを受領した意味で応答している。
・なにかのタイミングで定期的に送っている。(制御線を使わないので、生存証明。)

 おそらくGW-BASICなどでは内部の処理で、受け取った00(NULL)を捨てているので、
表にあらわれないのではないかと推測します。

 対策として次の個所(TEST2_SETSTATEの中)にプログラムを追加してください。
#'**ここで設定を変更する**
#F=DCB.FBITFIELDS '*bit毎設定必要
#'----fRtsControl----
##(省略)#

$$←←←ここに挿入$$
DCB.FBITFIELDS=F '設定

$$
'----fNull----
M=fnULL '設定値
F=F or M 'ビット設定
print "fNull書換";" (NULL BYTES 受信を破棄する)"
$$

 つぎにデータ受信本体プログラムのこの行を変更。
(変更前)if not eof(1) then print "Error:受信バッファが空でない!"
(変更後)if not eof(1) then R$(0)=input$(LOF(1),#1):R$(0)="" '最初のNULL受信破棄

 つぎにclose命令の後にこの1行を追加。
#close
TEST1_SETSTATE_NULLCHAR CM$ 'COMポートのfNull設定解除する

 最後に、以下のプログラムを追加します。(TEST2_SETSTATE〜end subの後ろ、var CM$, R$(4-1)の前)

declare sub TEST1_SETSTATE_NULLCHAR(FDSCRP$, byval SW%= 0)
sub TEST1_SETSTATE_NULLCHAR(FDSCRP$, byval SW%)
var RES as long, DCB as T_DCB
var HFILE as long
var F as long, M as long
var DEVNAME$

if SW%<0 then SW%=0
if SW%> 1 then SW%=1
select case ucase$(left$(FDSCRP$,5))
case "COM0:"
DEVNAME$="COM1"
case "COM1:"
DEVNAME$="COM2"
case "COM2:"
DEVNAME$="COM3"
case "COM3:"
DEVNAME$="COM4"
case "COM4:"
DEVNAME$="COM5"
case else
error 55 :exit sub
end select

HFILE=INVALID_HANDLE_VALUE
HFILE = CREATEFILE(DEVNAME$, (GENERIC_READ or GENERIC_WRITE), 0, NULL, OPEN_EXISTING, 0, NULL)
if HFILE= INVALID_HANDLE_VALUE then print "Error:open失敗":exit sub

RES=GetCommState(hfile, DCB)
if res=0 then
print "Error:GetCommState"
RES=CLOSEHANDLE(HFILE)
else
if DCB.DCBLENGTH<>len(T_DCB) then print "!!DCBlength(hex)=";DCB.DCBLENGTH

'**ここで設定を変更する**
F=DCB.FBITFIELDS '*bit毎設定必要
'----fNull----
F=F and (not fnULL) 'ビット消去
M=fnULL
M=M * clng(SW%) '設定値
F=F or M 'ビット設定

if DCB.FBITFIELDS <> F then
print "fBitFields(16進数)変更前=";hex$(DCB.FBITFIELDS)
DCB.FBITFIELDS=F '設定
print "fBitFields(16進数)変更後=";hex$(DCB.FBITFIELDS)

'設定を更新する
RES=SetCommState(hfile, DCB)
if res=0 then
print "Error:SetCommState"
endif
endif
RES=CLOSEHANDLE(HFILE)
endif
end sub

634名無しさん:2015/10/29(木) 18:31:47
丁寧な説明ありがとうございます。

ちょっとバタバタしていて、ちゃんとした返信が返せません。
すぐに落ち着きますので、すこしの間失礼します。

635名無しさん:2015/10/30(金) 03:12:00
>>630
>>633
修正です。 >633 の説明の「TEST1_SETSTATE_NULLCHAR CM$」から最後までは
取り消します。替わりに再オープン/クローズしてください。

#close
open CM$ for output as #2 :close #2 ' 通信設定を再初期化

 むだに見えますが、fNull の設定は解除しておいたほうがよいので。

636名無しさん:2015/10/30(金) 16:36:49
遅くなって申し訳ありません。

#632のまとめがとても参考になりました。

つまり、この計測器は簡略化された半二重通信でPCと通信をする仕様になっているので、F-BASICから通信条件を変更する必要がある。

このプログラムを実行すると、

fRtsControl書換 3 (RTS フロー制御:0..3)

と表示されるので、

3=RTS_CONTROL_TOGGLE

ということで、RTSフロー制御にTOGGLEが指定されています。

このTOGGLEというモードは(恥ずかしながら)知らなかったので調べてみたところ、

http://www.geocities.jp/terukat/_geo_contents_/win/comm.html
トグルの場合、 受信バッファにデータがなければ RTS がOFFになり、 データがあればONになります。

とあります。つまり、ここでRTSをOFFにしているという理解でよろしいでしょうか。

月曜日に、新しくコーディングしていただいたプログラムを走らせてみます。

637598:2015/10/31(土) 03:56:11
>>636
>つまり、この計測器は簡略化された半二重通信でPCと通信をする仕様になっているので

 はい、そのいう状態だと判断しました。
通信用LSIチップとしては同時に送・受信バッファの処理はできるのでしょうけれど。

>このプログラムを実行すると、fRtsControl書換 3 (RTS フロー制御:0..3)

 はい、fRtsControlという項目を RTS_CONTROL_TOGGLE(値は3)に書き換えて
Windows API のSetCommState (kernel32.DLL内)を実行してWindows経由でシリアルドライバを
設定します。

 「RTS_CONTROL_TOGGLE(トグル)モード」については、わたしもまったく知りませんでした。

で、このモード、
Windows“では”サポートされているらしく、 >624 のテスト結果ご報告にあるように
GW-BASICでは、RTS_CONTROL_DISABLE(値はゼロ)つまり、RTSは常時OFFに設定しています。
GW-BASICやQBASICでも、トグルモードは持っていないと思われ、
RTS_CONTROL_DISABLEにしています。昔はOUT命令でI/Oポートをじかに叩く制御方法が
とられたこともあるようです。

 常時OFFでいいのなら、F-BASICで問題が起こらなくてもと思うのですが、実態は
計測器側が受け取ったRTSの状態を見て、通信を保留していると推察されます。
常時ONのときだめになるので、おそらくは測定データ送信時。
PCからコマンド送信は制御線無視してのいきなり送りつけOKだが
測定データ送信は制御線を(ちゃんと?)見てから送り返していると。

 ならば常時OFFで実用上問題ないと。通信規約上はおかしいけど。
 そのいう状態だと判断しました。


>トグルの場合、 受信バッファにデータがなければ RTS がOFFになり、

 それは参照先記載の誤りで「送信バッファ」だと解釈しました。
たぶん「ハンドシェイク」の説明文につられて書き間違えていると。
 ( >621 の参照Webページ参照)

 原文はつぎのとおりです。
RTS_CONTROL_TOGGLE (0x03): トグルモード
Specifies that the RTS line will be high if bytes are available for transmission.
After all buffered bytes have been sent, the RTS line will be low.


テストプログラム >633 (+ >635 訂正)では、設定にさらにfNullの項をONにするよう
追加します。ただ、設定前に受信したNULL(00h)はそのままでしょうから、
「!!受信バッファが・・」への対処は必要なままでしょう。

※「fn」で始まる変数名はF-BASICの言語仕様上、使用できません。この追加部分にある
fnULLは(変数でもFN関数(*に見えるが)でもない)、#define 文によって
プリプロセッサで処理されているため、成立しています。

638名無しさん:2015/10/31(土) 11:30:55
おはようございます
詳細な解説ありがとうございます。

私なりに今回の通信手順を考えてみたのですが、

PCはRTSをONにする
PCは計測機に"D"を送る

PCの送信バッファが空になるので、RTSはOFFになる
計測機は"D"を受け取った後にPCのRTSがOFFになっていれば計測値をPCに送る
PCは計測値を受け取る

PCはRTSをONにする
PCは計測機に"D"を送る(print "D")

以下、繰り返し

*最初(最後)の2つステップはPRINT "D"の際に連続して行われる

たしかに半二重通信になっているので、これがRTSを使った半二重通信ということになるんでしょうね。

今回は全二重通信を前提としたWindowsのRS-232で半二重通信を行うために、工夫していただいたと思うのですが、最初から、RS-485のインターフェイスを使えば、そのままcomポートにアクセスが可能なのでしょうか。

http://www.ratocsystems.com/products/subpage/usb70.html
http://www3.contec.co.jp/B2B/ConIWCatProductPage_B2B.process?Merchant_Id=1&amp;Section_Id=6&amp;Catalog_Id=6&amp;Product_Id=1429

639名無しさん:2015/10/31(土) 13:38:02
このサイトでは、このような通信手順を「ゲート制御」とよばれています。

http://webcache.googleusercontent.com/search?q=cache:nR9WV32YowQJ:https://social.msdn.microsoft.com/Forums/ja-JP/2922a81b-d439-4a70-aaa6-28c43a63833f/com%3Fforum%3Dvcgeneralja%2Bwindows+rts+rs-485+RTS_CONTROL_TOGGLE&amp;lr=lang_ja&amp;client=safari&amp;rls=en&amp;hl=ja&amp;tbs=lr:lang_1ja&amp;prmd=ivns&amp;strip=1&amp;vwsrc=0

たしかに、PCではなくマイコンで制御するならその方がシンプルですよね。パソコン(当時はPC-98)を使いはじめて、30年も経とうとしているのに知りませんでした。

640名無しさん:2015/10/31(土) 14:25:23
このサイトでは、このような通信手順を「ゲート制御」とよばれています。

http://webcache.googleusercontent.com/search?q=cache:nR9WV32YowQJ:https://social.msdn.microsoft.com/Forums/ja-JP/2922a81b-d439-4a70-aaa6-28c43a63833f/com%3Fforum%3Dvcgeneralja%2Bwindows+rts+rs-485+RTS_CONTROL_TOGGLE&amp;lr=lang_ja&amp;client=safari&amp;rls=en&amp;hl=ja&amp;tbs=lr:lang_1ja&amp;prmd=ivns&amp;strip=1&amp;vwsrc=0

たしかに、PCではなくマイコンで制御するならその方がシンプルですよね。パソコン(当時はPC-98)を使いはじめて、30年も経とうとしているのに知りませんでした。

641598:2015/11/01(日) 05:04:14
>>638
>WindowsのRS-232で半二重通信を行うために、工夫していただいたと思うのですが、
>RS-485のインターフェイスを使えば、そのままcomポートにアクセスが可能なのでしょうか。

 RS-485(EIA-485)は、二本線一組とする平衡型伝送路で差動式の信号でやりとりし、
電気的特性はまったく異なる。
コネクタ形状やピン配置は別規格に分かれて定義。

 通信規約(プロトコル)は、RS-232から流用したものが多いものの製品次第というところで
しょうか。

 また、半二重と全二重についてもどこを指しているのかによって意味合いが異なるので、
要注意です。(RS-232でもそうですが)

仮想COMポート側から見て全二重通信のハードウェアフロー制御ONでも使用可能であれば
普通に使えるということになるかと思います。

参考情報:(アイ・ビー・エス・ジャパン株式会社、サイト内)
http://www.ibsjapan.co.jp/tech/details/rs-422-485/rs-422-485-double.html


 ソフトウェアの条件としては、
・仮想COMドライバにより、アプリケーションからは通常のCOMポートのように見えること。
(専用デバイスドライバのプロパティまたは専用ユーテリティで、COMポート番号割り当てが
固定で設定できること。)
・Win32 APIのコミュニケーション関数系(SetCommStateなど)やCreateFile関数などで
使用できること。(あるいはVB6のコントロール(MSComm)対応ならたぶんOK)

・RTS_CONTROL_TOGGLEモードが使用可能かどうかは問い合わせ確認が必要だと思います。
(もし対応不可でかつRTS_CONTROL_TOGGLEモードが必要な場合は、RTS等をその都度個別に
ON/OFF制御する処理を行う必要があり、その場合のF-BASIC実行時の影響は不明です。)

・専用デバイスドライバ(仮想COMドライバ)や専用ユーティリティの対応OSをご確認ください。
・F-BASICで使用できるCOMポートは1から5まで。(F-BASIC中の指定は"COM0:"から"CON4:")
・通信ボーレートが普通のCOMポートを越える高速レートはF-BASICで使用できないかも
しれません。(未確認事項)


○REX-USB70
※機器側I/Fは、ハード実験用向けネジ式端子台(計7ピン)。
〜〜抜粋〜〜(注:2012年2月版より)
本製品は内部でRTS/CTS DTR/DSRが処理されており、ドライバ・レシーバのON/OFF制御に
RTSとDTRを次のように設定します。
RS-455(半二重):送信時 RTSをON。受信時 RTSをOFF、DTRをON。※「RTSモード」時の場合
RS-455(全二重):送信時 RTSをON。受信時 DTRをON。

〜〜抜粋〜〜
RS485の場合はDTRを常時OMにして通常自分が送信したデータを自分で受けて
送信したデータが正しいかを確認します。
〜〜〜〜〜〜

●2015年3月出荷分からの新機能
半二重使用時、トランスミッターの自動制御モードをサポート。
 半二重通信での送信設定は、トランスミッターをRTS信号により制御する「RTSモード」の
ほか、トランスミッターが自動で送信可能状態になる「自動制御モード」の選択も可能。
本体側面のDIPスイッチ3にてモードの切り替えをおこないます。(出荷時はOFF(RTSモード))


○COM-1PD(USB)H
9ピンD-SUBコネクタ(オス)の採用により、9ピンD-SUBコネクタ(メス)のケーブルに
接続できます。
データ伝送モード(全二重、半二重)は、スイッチ(DIP SW)を切り替えることで設定を
変更できます。

〜〜抜粋〜〜
半二重、全二重の切り替えや全二重時のRTS/CTSの切り替えは、データ伝送モード用
設定スイッチ(DIP SW)で設定できます。設定は、ビット1 - 6で設定します。

半二重:
 データラインはTxDだけとなり本製品のRTS信号により、送信/受信モードを
切り替えることができます。
全二重/RTS,CTSを自己ループさせる:
 接続機器にRTS, CTS信号が無い場合、この設定にすると本製品のRTS信号をアクティブに
することで、CTS信号がアクティブになります。
全二重/RTS,CTSを相手装置と接続する:
 接続機器のRTS, CTS信号と接続して使用します。

〜〜抜粋〜〜
RTS+, RTS-, CTS+, CTS-の制御線をソフトウェアで制御や監視が可能です。
〜〜〜〜〜〜

642名無しさん:2015/11/01(日) 05:30:43
>>639
「ゲート制御」ですか...

知らないことなのでわからないのですがEIA-485の向こう側、伝送路と言えばいいので
しょうか、そこのドライバ・レシーバの切り替え(送受信の切り替え)の制御のことを
指しているのではと愚考いたします。
送信の一組(TxD+,TxD-)のみで、送信も受信も行う場合の切り替えることかと。

643名無しさん:2015/11/01(日) 10:41:56
ありがとうございます。

実際に製品を借りるか買って試してみる必要がありそうですね。
しばらく、RTS_CONTROL_TOGGLEを使いこなせるか、F-BASICのプログラムをしてみます。この手法は、計測器で使うにはノイズにも強そうですね。

644名無しさん:2015/11/02(月) 11:32:50
おはようございます。

プログラムを実行してみました。

1回目に出てくる(null)(null)は(null)になりましたが、やはり1レコードの最初にくっついているnullはそのままです。これはいつも行頭についているので、trimで取れますので問題ありません。それからフローのタイミングが合わなくなるのか、時々、"!!送信始!!"の表示後にハングします。下記が新たに633書いていただいたコードです。

declare sub TEST2_SETSTATE(byval FILENO%)
sub TEST2_SETSTATE(byval FILENO%)
var RES as long
var DCB as T_DCB, HFILE as long
var F as long, M as long

HFILE= FB63_GETFILEHANDLE(FILENO%)
if HFILE=0 or HFILE=-1 then HFILE=INVALID_HANDLE_VALUE

if HFILE= INVALID_HANDLE_VALUE then print "Error:open":exit sub
RES=GetCommState(hfile, DCB) 'ポートの設定取得
if res=0 then
print "Error:GetCommState"
else
if DCB.DCBLENGTH<>len(T_DCB) then print "!!DCBlength(hex)=";DCB.DCBLENGTH
print "fBitFields(16進数)変更前=";hex$(DCB.FBITFIELDS)

'**ここで設定を変更する**
F=DCB.FBITFIELDS '*bit毎設定必要
'----fRtsControl----
F=F and (not FRTSCONTROL) 'ビット消去
M=FRTSCONTROL :M=M and (M \ 2) '※下位ビットを残す
M=M * RTS_CONTROL_TOGGLE '設定値
F=F or M 'ビット設定
print "fRtsControl書換";RTS_CONTROL_TOGGLE ;" (RTS フロー制御:0..3)"
'--------
DCB.FBITFIELDS=F '設定

'----fNull----
M=fnULL '設定値
F=F or M 'ビット設定
print "fNull書換";" (NULL BYTES 受信を破棄する)"

'****
print "fBitFields(16進数)変更後=";hex$(DCB.FBITFIELDS)

'設定を強制更新する
RES=SetCommState(hfile, DCB)
if res=0 then
print "Error:SetCommState"
endif
endif
end sub

645名無しさん:2015/11/03(火) 01:43:50
>>644
えっ? プログラム「'----fNull----」〜〜 の挿入位置が違っているのでは。

#DCB.FBITFIELDS=F '設定  ←この行の手前(上側)です。

設定すべき値は、「fBitFields(16進数)変更後」の表示値が3811になります。


ハングアップについては、
先頭のNUL(00h)読み飛ばしの後にWAIT 50をいれてみてください。

直らない場合は、一旦、先頭のNUL(00h)読み飛ばしをやめてみてください。
(元に戻す)if not eof(1) then print "Error:受信バッファが空でない!"


TRIM$関数系では00hは排除できないと思うのですが。

646名無しさん:2015/11/03(火) 10:23:16
おはようございます。

>プログラム「'----fNull----」〜〜 の挿入位置が違っているのでは。
すみません、「$$←←←ここに挿入$$」の意味を読み切れませんでした。
明日、そこを直してみます。

こんな感じでprint文を使って送受信バッファの内容を見ているんですが、問題はないようです。WAITは入れています。

print eof(1), eof(2)
print #2,"D"
print eof(1), eof(2)
line input#1,R$(0)
print eof(1), eof(2)

ハングアップはこの2行の間です。
(eofは両方とも-1を返す)

print eof(1), eof(2)
line input#1,R$(0)

> TRIM$関数系では00hは排除できないと思うのですが。
そうでしたか。TRIM$は20hだけでしたか。

647名無しさん:2015/11/03(火) 12:05:03
>>646
 あ、“$”が「この間、省略」に見えたんですね、すみません。

>print eof(1), eof(2)
 確認がとれていないのですが、EOF関数・LOF関数はたぶん受信バッファしか取れないはず。

 TRIM$関数系は日本語対応で、半角空白および全角空白に作用します。

それで、ハングアップについてですが、可能性についていくつか。
・EOF(1)で真が返される間(空)はLINE INPUT#1 の実行は避けなければならない。
(とりあえずは受信タイムアウトの設定をしない限り)
・PRINT#2,"D" で処理後、ただちにデータが送り返されるわけではない。
(測定値確定と送信用測定データ作成、送受信切り替えのタイムラグ)
・コマンド"D"[CR]とコマンド"D"[CR/LF]とで、計測機側の動作の影響が不明。
・コマンド送信後、すべてのデータ受信を完了しないうちに次のコマンドを送ると問題の可能性。
・もし、コマンド送信-データ受信を一度に複数回おこなっている場合は、
計測機側の処理限界を超えた可能性。
・コマンド送信後、測定対象物や計測機側の問題で「欠測」した場合。この動作は不明。

・「コマンド送信 〜 データ受信完了」の一連のサイクルを高速で繰り返してはならない。
資料( >611 )より、
Caution:
For exact measurement and good communication with PC, use “data request” signal
once per one second.
Data Conversion time:
Data Conversion time is based on conversion time of ADC included in DMM and is 2 or
3 times per one second.
[翻訳]
注意:正確な測定とPCとの良好な通信のためには、1秒に1度「データ要求」信号を使用する。
データ変換時間:データ変換時間は、DMM内蔵ADC(訳注:アナログ-デジタル変換)の変換時間を
基本として、1秒あたり2〜3回である。
[了]


 最後に文字列先頭のNUL(00h)を除去する関数プログラム例を。(空白は除去しません)
(使用例): R$(0)=LTRIMCTRL$(R$(0))


declare function LTRIMCTRL bdecl (S as string) as string
function LTRIMCTRL$ (S$)
'機能:引数で指定された文字列の左側の制御コード等を取り除きます。
var I as long ,P as long ,N as long
LTRIMCTRL$=S$
N=len(S$)
if N=0 then exit function
P=0 :I=0
do
I=I+1
select case asc(mid$(S$,I,1))
case is < &H20
case &H7F,&HFF
case else
exit do
end select
P=P+1
loop while I < N
if P > 0 then LTRIMCTRL$=mid$(S$,P+1)
end function

648名無しさん:2015/11/04(水) 13:18:39
いつもありがとうございます。

そっそく、プログラムを修正しました。

NULLも取れ、ハングアップも少なくなりました
wait 50 --> wait 100 にすればもっとよくなりそうです。
長い間、お世話になりました。

ところで、マルチメーターの箱の中にFDを見つけました。これは計測をするためのGUIソフト(DMM_4660)が入っていて、これを使った後のシリアルの状態をみてみました。fBitFieldsの値(0811)をみると、fRtsControlはしていないみたいです。気づくのが遅れてすみません。


新プログラム実行後
fBitFields(16進数)=3811
fOutxCtsFlow= 0
fOutxDsrFlow= 0
fDtrControl= 1 (DTR フロー制御タイプ:0..2)
fDsrSensitivity= 0
fErrorChar= 0 (エラー時文字置き換える)
fNull= 1 (NULL BYTES 受信を破棄する=1)
fRtsControl= 3 (RTS フロー制御:0..3)
fAbortOnError= 0
ByteSize= 7
StopBits= 2 (stopビット:0=1,1=1.5,2)
ErrorChar(16進)=0
EofChar(16進)=0
EvtChar(16進)=0
終了します。なにかキーを押してください。


DMM_4660実行後
fBitFields(16進数)=811
fOutxCtsFlow= 0
fOutxDsrFlow= 0
fDtrControl= 1 (DTR フロー制御タイプ:0..2)
fDsrSensitivity= 0
fErrorChar= 0 (エラー時文字置き換える)
fNull= 1 (NULL BYTES 受信を破棄する=1)
fRtsControl= 0 (RTS フロー制御:0..3)
fAbortOnError= 0
ByteSize= 7
StopBits= 2 (stopビット:0=1,1=1.5,2)
ErrorChar(16進)=0
EofChar(16進)=0
EvtChar(16進)=0
終了します。なにかキーを押してください。

649名無しさん:2015/11/04(水) 21:44:18
今日、他の計測器を使っていて気づいたことなのですが、計測器からデータを読み出す時に、line input#でやるとハングアップする(待ち状態が続く)のですが、INPUT$でやると問題なく読み出せました。

その時も、INPUT$で指定したバイト数が、受信データと同じか少なければ読み出せるのですが、多いとline input#と同じになりました。

明日、もう一度、チェックしてみます。

650名無しさん:2015/11/05(木) 01:11:10
>>648
>これを使った後のシリアルの状態をみてみました。fBitFieldsの値(0811)をみると、fRtsControlはしていないみたいです。

 GUIソフト(DMM_4660)、これはfRtsControlはDisable(RTS常時OFF)です。
GW-BASICの場合と同じです。違いはfNullが有効になっていますね。
あ、fDtrControl=1も違いますね。

GW-BASICではMS-DOS環境が対象であり、DMM_4660はWindows環境が対象であることが、
違いに出ています。

純正品といってもよいサンプルGUIソフト(DMM_4660)の設定がこうなっているということは
fRtsControlの設定が何であれ、NUL(00h)は送られてくるという証左かもしれません。


 fNullを有効にした場合は、使用後無効にするようにしてください。
これは他のソフトの安全のためです。
F-BASICの場合はとりあえずOPEN/CLOSEを再度行えば無効に再設定されます。


>>649
 それは正常な動作です。通信相手の区別はありません。
LINE INPUT#は。改行コードを得る(かたぶんEOFコードを得る)まで処理が戻ってきません。
ゆえにもしも通信時改行コードが文字化けした場合は、永久的に処理が戻ってこなくなります。
INPUT$関数は通信時指定された文字数(バイト数またはオクテット数)を得るまで処理が
戻ってきません。

通信においてはいつ相手が残り(続き)のデータを送信してくるかは事前にわからないため
そのような動作になっています。

651名無しさん:2015/11/05(木) 15:49:54
いつもありがとうございます。

>GW-BASICではMS-DOS環境が対象であり、DMM_4660はWindows環境が対象
うーん、考察が深いです。そこまで考えませんでした。

>LINE INPUT#は。改行コードを得る(かたぶんEOFコードを得る)まで処理が戻ってきません。
>INPUT$関数は通信時指定された文字数(バイト数またはオクテット数)を得るまで処理が戻ってきません。
恥ずかしながら、これまで、INPUT$、LINE INPUT#、INPUT#の違いはあまり考えておりませんでした。

いろいろとお世話になって、とりあえずデータのロギングは問題なくなりました。
ハングアップもほとんどなくなりました。
ありがとうございました。
もう一つ相談したいことがあるのですが、それは別にします。
今後とも、よろしくお願いします。

652名無しさん:2015/11/06(金) 03:34:39
>>651
 こちらこそテスト調査に協力いただきありがとうごさいます。
おかげでRS-232C問題の回避策を実証できました。

653名無しさん:2015/11/06(金) 08:37:38
こちらこそ、勉強になりました。

ここも参考にさせていただきました。
http://infoseek_rip.g.ribbon.to/spectrum123.at.infoseek.co.jp/vb/vb_2/vb_2.htm

EscapeCommFunctionを使うと直接RTSのON/OFFができるみたいです。

ここのP.32にF-BAISCのサンプルもあったので、時間が取れたらやってみようと思います。
http://www.fmworld.net/product/soft/fbasic/faq/faq.pdf

654名無しさん:2015/11/06(金) 09:26:45
F-BASICを使って、1秒とか、0.5秒間隔で計測器からデータを読み出しています。
今はwaitを使っているのですが、もう少し精度(1/100〜1/1000程度)が欲しい。
GPSを接続して、PPSをもらうという方法もあるのですが、いつも衛星にアクセスする必要があります。
何か簡単に使える方法をご存知でしたら、教えてください。

655598:2015/11/06(金) 09:48:04
>>653
あら、FILEATTR関数があったのね。車輪の再発明しちゃいました。

656名無しさん:2015/11/06(金) 11:03:33
>>654
WindowsやPC/AT機に時刻正確性を求められても・・

WAIT命令は100分の1秒単位ですが、

とりあえずはAPIのSleepEx関数を使うとか。一応は1ミリ秒単位の指定ですが。
https://msdn.microsoft.com/ja-jp/library/cc429359.aspx


計測間隔をできるだけ正確にということであれば、次のような感じでどうでしょう

・まず、プログラム変更
1.受信バッファを大きくする。
CM$="COM0:(S7N2N7NNN,RB4096)"
open CM$ for output as #2 : open CM$ for input as #1

2.送信コマンドをWAIT命令をはさんで一定間隔で連続で送る。
最低限の送受信時間からコマンド送信間隔を試算すると、
スタートビット(1)+データ長(7)+ストップビット(2)=計10bit
受信データ14*4フレーム+送信コマンド(2)=計58キャラクタ
580÷9600bps=約6〜7/100秒
※実際は計測器側の測定データ作成時間も必要なので、当然これよりは
時間がかかる。

for I%=1 to 50
print#2,"D";chr$(13);
wait 10
next I%

3.あとで一括して受信バッファから取得する。
for I%=1 to 50
line input#1,R$(0, I%)
line input#1,R$(1, I%)
line input#1,R$(2, I%)
line input#1,R$(3, I%)
next I%

・次に実行時
1.プログラムを起動する。ただし、まだ計測開始しない。
(このとき、F-BASIC開発環境経由ではなく、実行プログラムを直接起動すること)

2.タスクマネージャを呼び出して、[プロセス]のタブから当該実行プログラムを
探して、右クリック-[優先度の設定]-[高(H)]とか[リアルタイム(R)]に設定。
※少しでも正確性をあげるため。

3.計測開始を指示。

657名無しさん:2015/11/06(金) 11:20:29
>>654
>>656
http://www.tokineko.net/realtime/page1.html

658名無しさん:2015/11/06(金) 21:14:59

>受信バッファを大きくする
あ、これいいですね。
さっそく試してみます。

>送信コマンドをWAIT命令をはさんで一定間隔で連続で送る。
これもやってみます。

今は、waitで微調整しています。

計測データは時系列なので内挿してもいいかなと思っています。
そうなると、times$の分解能が1/100秒くらいならいいんですが。
と思って、ヘルプを見たらMILLITIMEという関数があるんですね。
これを使ったら何とかなるかもしれません。

659名無しさん:2015/11/07(土) 05:07:31
MILLITIMEはミリ秒単位に再計算しているので場合によるけど
直接GetLocalTimeで要るとこだけ記録したほうが無駄がないかも。

660名無しさん:2015/11/09(月) 04:56:41
waitで調整するより「タイマーコントロール」使う方法も考えてみては

661名無しさん:2015/11/09(月) 14:44:25
ご教授、ありがとうございます。

>直接GetLocalTimeで要るとこだけ記録したほうが無駄がないかも。
すいません、Windows APIはほとんど使ったことがないのですが、マニュアルを読んでみます。

>waitで調整するより「タイマーコントロール」使う方法も考えてみては
これも初耳なのですが、ヘルプに「タイマーコントロールへの操作」という項がありますので、これを使えばいいのかな。これはGUIでしか使えないのでしょうか?もうちょっと情報を調べてみます。

662名無しさん:2015/11/10(火) 03:37:28
>>661
F-BASIC/Winの場合はGUIと非GUIというような単純な区分けではありません。
WindowsのGUIの上で、従来互換のテキスト・グラフィック画面をエミュレートする
「テキストモード」と互換性をなくすかわりにWindowsの基本機能に近い形で従来命令を
使うモードとに分かれます。

F-BASICでは従来の「手続き型」とGUIで使う「イベント駆動型」のどちらの書き方も
できます。
極端なことをすれば混在させることもある程度はできます。
テキスト画面にGUIの「ボタン」があるなんてことも。
従来の手続き型のみで似たようなことをするとON MOUSE命令やMOUSE関数やINKEY$関数を
駆使してあれこれプログラムをすることになってしまいます。

本題に戻りまして、
「タイマーコントロール」ですが、『コントロール』とはいってもそれは便宜上の
ことで、Windowsの側から発生するタイマー通知の経路をウィンドウメッセージとして
受けているためです。
F-BASIC実行環境がタイマー通知を受けるための環境作りを裏方として準備してくれる
わけです。

従来BASICでいえば、インターバル割り込み命令(INTERVAL ON命令・ON INTERVAL GOSUB命令、
INTERVAL命令)とWAIT’I’命令を使う方法と基本的な考え方は同じです。

タイマーコントロールを使うにはまず「空の」フォームを作らないといけません。
(もし、すでに作って使っているならそれ(のコピー)を使えばいいです。)
そのフォームの中のどこでもいいのでタイマーコントロールを置きます。

次にフォームに置いた(見た目そっけない)タイマーコントロールをダブルクリックする
と中身が空のプログラム(イベントプロシージャ)が作成されます。
それを丸ごとコピーして、自分のプログラムに挿入します。元のイベントプロシージャは
不要なので保存せずに閉じてください。

これが言わば「ON INTERVAL GOSUB」の飛び先の中身に相当します。

とりあずフォームを作るための参考資料
http://www.fmworld.net/product/soft/fbasic/gpib/
 ワンポイントレッスン集  第一回「実行画面を大きくしよう」

663名無しさん:2015/11/10(火) 17:15:04
ありがとうございます。

フォームは作ったことがないので一から勉強してみます。
たしかにこれができると、世界が広がりそうですね。
マニュアルはあるんですが、CD付きの参考書が見当たらないので、これを探してみます。

>そのフォームの中のどこでもいいのでタイマーコントロールを置きます。
フォームは作れそうなんですが、ここから勉強のはじまりです。

664598:2015/11/11(水) 06:54:30
サンプルです。動くかどうかは謎ですが。実行時間26秒
(TEST2_SETSTATEサンプル必須)
なお、処理時間最優先のため、実行経過の表示はありません。
#include "windows.bi"

var FRUN as long,FEND as long
var TT&(50), RR$(4-1, 50) as string * 13 'データ保管領域確保
var TIMER1 as object
var CM$, R$(4-1), CNT1&, CNT2&, I&
TIMER1.ATTACH GETDLGITEM("TIMER1")
TIMER1.SETINTERVAL 50 ' (10ms単位)

baud 0,9600
CM$="COM0:(S7N2N7NNN)"
open CM$ for output as #2 : open CM$ for input as #1
TEST2_SETSTATE 2 '←ファイル番号の対応COM設定を強制変更する
wait 100
if not eof(1) then R$(0)=input$(lof(1),#1):R$(0)="" '最初の(00h)を捨てる
while CHECKEVENT :CALLEVENT :wend
TIMER1.ENABLE -1 'タイマー通知開始

*LOOP1
'イベント発生して処理されるまで待つ(かつ変数FRUNでタイマーイベントを待つ)
while FRUN=0 :WAITEVENT :wend
if FEND then *ENDING '中止して終了する
CNT1&=CNT1&+1
print#2,"D";chr$(13);
TT&(CNT1&)=millitime ' 00:00:00からの通算時間の値(1ms単位)

if CHECKEVENT then CALLEVENT
wait 10 '受信データ作成待ち
while eof(1) and FEND=0 :CALLEVENT :wend ' 受信開始までループ
if FEND then *ENDING

if lof(1) < 14 and FEND=0 then wait 5 :CALLEVENT ' 1行受信までもう少し待つ
if CHECKEVENT then CALLEVENT
if lof(1) < 14 then
print "!!データ受信エラー!!";lof(1)
R$(0)="":if lof(1) <> 0 then R$(0)=input$(lof(1),#1)
R$(1)="":R$(2)="":R$(3)=""
else
line input#1,R$(0) :if CHECKEVENT then CALLEVENT
line input#1,R$(1) :line input#1,R$(2) :line input#1,R$(3)
endif
RR$(0,CNT1&)=R$(0):RR$(1,CNT1&)=R$(1):RR$(2,CNT1&)=R$(2):RR$(3,CNT1&)=R$(3)
CNT2&=CNT2&+1

while CHECKEVENT :CALLEVENT :wend '未処理イベントの処理
FRUN=0 '次のタイマー通知へ
if CNT1& < 50 then *LOOP1 '繰り返し

*ENDING
if CHECKOBJECT(TIMER1) then TIMER1.ENABLE 0 'タイマー停止
if CHECKEVENT then CALLEVENT
if CHECKOBJECT(TIMER1) then TIMER1.DETACH 'オブジェクトと切り離し
close

gosub *SAVEDATA 'データ保存の作業
erase TT&, RR$ :CNT1&=0:CNT2&=0
while CHECKEVENT :CALLEVENT :wend
stop:end

*SAVEDATA
'**このサブルーチンでデータを保存 例:バイナリ形式で
'**for I&=1 to CNT2&:fwrite #3,TT&(I&)
'**fwrite #3,RR$(0,I&)
'**fwrite #3,RR$(1,I&):fwrite #3,RR$(2,I&):fwrite #3,RR$(3,I&):next

'これはテスト:データ画面表示
for I&=1 to 50:print TT&(I&),RR$(0,I&);RR$(1,I&);RR$(2,I&);RR$(3,I&):next
return

'================================================================
' タイマーイベント プロシージャ
declare sub TIMER1_TIMER edecl ()
sub TIMER1_TIMER()
shared FRUN as long, FEND as long
shared TIMER1 as object
var RES as long
'print "Test:タイマー";time$
if FRUN then
TIMER1.ENABLE 0 'タイマー停止
FRUN=-1:FEND=-1 '終了
RES=MESSAGEBOX("TIMER1","処理時間があふれました!",0,0)
exit sub
end if
FRUN=-1 'タイマー通知があった
end sub
'================================================================
' メインフォーム が閉じられようとしている
declare sub MAINFORM_QUERYCLOSE edecl ( CANCEL%, byval MODE% )
sub MAINFORM_QUERYCLOSE( CANCEL%, byval MODE% )
shared FRUN as long, FEND as long
FRUN=-1
FEND=-1 '処理終了させる
end sub

665名無しさん:2015/11/11(水) 10:22:32
ありがとうございます。

いきなり本題に入るのは敷居が高いので、作成していただいたプログラムに入る前に準備をしてみたいと思い、下記を参考にしてフォームを作ってみました。これはOK.
http://www.fmworld.net/product/soft/fbasic/gpib/

次に時計マークのアイコン(タイマーコントロール)を選択してフォームに貼りつけ。
[TIMER]と書かれたアイコンがフォームに表示されます。
これをダブルクリックすると、ウィンドウが開いて、プログラムが書けるようになりました。
ここに print "hello" としても画面に表示されない。
ちょっとマニュアルを探して勉強してみます。早く参考書も探さなくては。

666名無しさん:2015/11/12(木) 04:31:17
>>665
>ここに print "hello" としても画面に表示されない。

 ヘルプの「タイマーコントロールへの操作」にあるようにATTACHやENABLEをしているなら
たぶんイベントチェックのループを実行していないから。
 いちから作成する場合は、プロジェクト ウィザードで作成すると一通り新規作成されます。
(メニュー:プロジェクト(P)-ウィザード(W)) 注:既存の.BASファイルとかつぶさないように。
ヘルプで「イベント駆動処理プログラムの作成手順」を検索して参照。

#include "windows.bi"

while 1:WAITEVENT:wend

これが作成されたイベントチェックするループです。これを見て疑問に思うでしょう。
『あれ、無限にループしているのにこれを実行するとタイマーが動くの?』
WAITEVENTは、WAIT“I”命令(割り込み処理発生まで停止する)に似ています。

 イベントチェックのループ(メッセージ処理)とは何か、たとえ話をすると、

 あなたはWindowsさんからのはがき(タイマー通知)が郵便配達されてくるのを待っています。
でもいつ到着するかなんてわかりません。郵便受けの前で待ちつづけるわけには・・。
 そこである人(イベントチェックするループ)に依頼します。
「郵便受けで待って届いたら持ってきて。」その人は根気よく待ちました。
やがて配達人がきてあちこちの郵便受けに、はがきを一枚づつ投函していきます。
 自分の郵便受け(自分が作成したプログラム)の中にはがきの束を見つけたので、
その人はその束を持って戻り、はがきの到着した順番に宛て名を見て、皆に配り始めました。
(*順番にとはいっても「至急」とスタンプされたものは優先し、「新装開店」だとか
後まわしでいいようなものは最後にしたり、「同じ割引券のはがき」は一つにまとめたりと、
この人、できる秘書さんかも)
「これはAさん..これはBさん、これはまたAさん宛てです・・」やがてあなたの前にきて、
「はがき(タイマー通知)が届いてました、速やかに処理してください。」あなたははがきを
待ってはいたのですが、いろいろとほかにやることがあるのでその後で見ようとしました。
 ですが、この人はあなたの前から一歩も動こうとしません。不思議に思い理由を問うと
『あなた様がはがきを読んだことをしかと確認し、必要であればご返事をいただくまでが
私の役目です。速やかに処理してください。』と言われてしまいした。
その強い意思に射抜かれあわてる、あなた。
モタモタしていると、向こうの方からCさんやDさんたちの声が漏れてきました。
「まだはがきがあるじゃないか、おれたち宛てのものはあるのないの、どうなってるの!?」

667名無しさん:2015/11/16(月) 08:32:19
こんにちは

返信が遅くなって申し訳ありません。
そして、わかりやすいイベントチェックのループのたとえ話ありがとうございます。

>いちから作成する場合は、プロジェクト ウィザードで作成すると一通り新規作成されます。
これでやってみます。

とりあえず、少しまとまった時間が取れれば。ダイアログにタイマーの設定時間:1/100単位と実行回数を書き換えられるようにして、実行ボタンを押せばtime$を画面に表示するプログラムを作ろうと思います。

668名無しさん:2015/11/16(月) 09:20:25
>>667
タイマー間隔をシビアにした場合、画面に表示することが、
時間間隔の乱れの要因になることがあるかもしれません。
フォームを作成したF-BASIC/Winのテキスト表示は遅い
ということもありますし。
(画面表示速度改善については586番,592番あたり参照)

669名無しさん:2015/11/17(火) 02:09:42
ハード・ソフト両面で環境の差の影響が大きいのですが、参考値として
PRINT命令でMILLITIME関数で取得する数値に影響する度合いを
試してみました。条件はフォームを作成してフォント変更・サイズを大きくします。
80桁24行の互換モードで画面のグラフイックの機能設定はONのまま。
PRINT命令で4文字出力(改行なし)を連続実行してどの程度で
MILLITIME関数の値が変わるかテスト。
なおテストした環境でのMILLITIME関数の計測分解能は10msでした。

テスト結果、最大でも、PRINT命令 70回程度。平均としてはその半分程度。

なお、テキストのスクロールを発生させた場合は、即影響が出ます。

670k5:2016/01/06(水) 11:51:33
こんにちは

昨年はたいへんお世話になりました。

ずっと他の仕事に追いまくられて、F=BASICのイベント型プログラムに取り掛かれません。
もちろん、頭の切り替えができないという情けない現状もあります。

少しだけ時間ができたので、「ON INTERVAL GOSUB」を使ってみました。
INTERVALを5秒くらいにして実行させてみると、1時間で5〜10秒ほどずれました。

cls

interval 5.0 '60秒毎に割り込みます.
on interval gosub *KAKE
interval on
do
loop
interval off
stop
end
'

*KAKE

print date$,time$

return

これでもいいのですが、もう少し何とかならないだろうかと、こんな簡単なプログラムにしました。
(とても稚拙でお恥ずかしい)


cls

KANKAKU=5.0

OWARI = (date*86400+millitime/1000.0)+KANKAKU

do

NOW =(date*86400)+(millitime/1000.0)

if NOW >= OWARI then print date$,time$,millitime:OWARI=NOW+KANKAKU

loop

input AAA$

stop
end

これで実行すると、前よりはましみたいです。
もう少し、頑張ってみますので、
今年もよろしくお願いします。

671名無しさん:2016/01/08(金) 12:49:18
>>670
>INTERVALを5秒くらいにして実行させてみると、1時間で5〜10秒ほどずれました。

確かにずれていきますね。TIME割り込み命令の方で毎回つぎの5秒後を設定する方法にして
みましたが同じ結果でした。

> NOW =(date*86400)+(millitime/1000.0)

これは単精度変数だと有効桁数が足りないので、数ヵ月後には数値が狂うのでは?
millitimeも秒未満の桁が削れていく?

そこは、こんな感じでしょうか。年越しもできるし。

OWARI =(millitime/1000.0)
do
NOW =(millitime/1000.0):if NOW < OWARI then NOW=NOW+86400
if NOW >= OWARI+KANKAKU then print date$,time$,millitime :OWARI=NOW
loop


5秒で数百万回時計を見にいくというのも・・・ CPU100% ...。

672名無しさん:2016/01/08(金) 13:16:19
>>670
長くなってしまいましたが..。millitimeの時刻読み取りを減らして見ました。
---それでも数万回、時刻読み取りするけど。
(例えるとゴルフでパターを刻んでいくようなもの)
1. interval割り込みで、4秒(以内)待ち。
2. WAITで0.1秒単位待ち。
3. 回数限定無限ループで時間つぶし。(for MUGEN_CC=・・)←※外した方が定時性はあがる。
4. 豪腕でループぶん回してmillitimeを読み続けて時刻合わせ。


deflng A-Z 'ここから暗黙の型を32bit整数型にします。
var KANKAKU, OWARI, NOW
var MUGEN_CC, MUGEN_NN, MUGEN_NN2
var KAISU%

cls
gosub *MUGENSENS

KANKAKU=5
print time$, millitime/1000#
gosub *JUSTTIME
print time$, millitime/1000#

KAISU%=0 :do while KAISU% < 720 '実行回数
gosub *JUSTTIME '時刻合わせ
print date$,time$,millitime

'*** input AAA$

KAISU%=KAISU%+1 :loop
'
stop:end
*KAKE: print date$,time$ :return
'
*JUSTTIME2:return
*JUSTTIME
OWARI=KANKAKU-(time mod KANKAKU)
if OWARI >= 2 then '差が2秒以上あるならば、
interval OWARI-1 '秒単位の割り込み。ただし1秒残す。
on interval gosub *JUSTTIME2
interval on
waiti '設定している割り込みが発生するまで停止します。
interval off
end if
OWARI=1000-(millitime mod 1000)
if OWARI >= 100 then
wait (OWARI \ 100)*10 '1/100秒単位:0.1秒粗く待つ
endif
OWARI=1000-(millitime mod 1000)
if MUGEN_NN then for MUGEN_CC=(MUGEN_NN / 1000)*(OWARI \ 10)*10 to 0 step -1:MUGEN_NN=MUGEN_NN:next

if KANKAKU-((millitime \ 1000) mod KANKAKU)>= 2 then print "Time Over!!"
OWARI=1000-(millitime mod 1000)
MUGEN_CC=0
do 'ループしてmillitimeを秒単位チェック待ち
MUGEN_CC=MUGEN_CC+1
NOW=(millitime \ 1000) mod KANKAKU
loop until NOW=0
return
'
*MUGENSENS2 :MUGEN_NN=MUGEN_CC :return
*MUGENSENS
interval 1
on interval gosub *MUGENSENS2
MUGEN_CC=0:MUGEN_NN=0
interval on
waiti '1回目発生待ち
for KAISU%=1 to 3
do '2回目以降でループ回数カウント
MUGEN_CC=MUGEN_CC+1
loop until MUGEN_NN
if MUGEN_NN < MUGEN_NN2 or MUGEN_NN2=0 then MUGEN_NN2=MUGEN_NN
MUGEN_NN=0:MUGEN_CC=0
next KAISU%
MUGEN_NN=MUGEN_NN2
interval off
return
end

673k5:2016/01/09(土) 19:59:19
こんにちは

今年もよろしくおねがいします。

>これは単精度変数だと有効桁数が足りないので、
書き込んだ後で、倍精度に直しました。
そうすると、大体1/250秒ほどの精度で時間を取れるようです。

if NOW >= OWARI+KANKAKU
この方法の場合、計測間隔の精度はいいのですが、時間的確度はだんだん正の方にずれて行ってしまいます。やはり、millitimeを基本に計測間隔±0.005秒とかの設定にした方がいいみたいです。ただし、この方法では一度ずれてしまうと、戻らなくなる可能性があります。

考え付くのは、最初に計測間隔と計測のトータル時間を決め、millitimeのリストを作って、±閾値で決めて行く方がいいのかな。あるいは、

if NOW >= OWARI+KANKAKU

のあとで、差分を求めて、その差分を次の間隔から差し引くということです。
つまり、5.1秒だったなら、次は4.9秒にするということです。

>millitimeの時刻読み取りを減らして見ました。
これ頂きます。waitだけ使うともっと簡単になりますね。

>(例えるとゴルフでパターを刻んでいくようなもの)
あ、いい例えですね。

それにしてもBASICは素晴らしい。
これで、USBシリアル変換のケーブルが使えれば、もっといいんですけど。

674671:2016/01/10(日) 04:27:34
>>673
>millitimeを基本に計測間隔±0.005秒とかの設定にした方がいいみたいです

そのようですね。PCの時計は使用状況(連続稼動時間・休止時間)によりますが、
だいたい月差30秒程度だと思うので。

時刻精度はOS・ハード構成によって違うでしょうから。Windows Vista以降だと
ハードウェアで「高精度イベントタイマー」を使えますが。

>millitimeのリストを作って、±閾値で決めて行く ・・・

>if NOW >= OWARI+KANKAKU のあとで、差分を求めて、その差分を次の間隔から差し引く

方法はどちらでもいいと思いますが、
「時刻(定刻)」、「時間(間隔)」のどちらを重視するかということですね。
基準となる時刻はなにを採り、どうやって取得するのか、
取れないのならどうやって近似値を作り出すか。


毎5秒として、つぎのようなパターンは許容できるのか?
・04.99秒・09.99秒(つまりマイナス方向、-0.01)の振れは許容できるのか
(見た目の1秒差:時刻05秒のはずが04秒に)。
・04.99秒・10.01秒(つまりプラスマイナス両振れ、間隔としては0.01の2倍の差)は。
・たとえば日本標準時から「平均的にほぼ一定」で時刻が進んでいくまたは遅れていく。
・仮定として、他の計測データとのなんらかの照合をすると時刻・時間の基準が違うが。
・millitimeを補正した場合、PC上の日付時刻と、補正日付時刻と、二重に日付時刻が生じるが
何らかの証跡として問題ないか。

差分補正はどう処置するのが問題に。
・04.99秒なので次は+0.01補正したのに、09.95秒だった。次は+0.05か+0.06か+0.04補正か。
・04.97秒なので補正していったら09.98秒、15.99秒、次はいきなり20.50秒になった。
-0.50補正を行うのか。
・04.90秒なので補正したらなぜか11.00秒になった。異常値として破棄するのか

○差分補正の欠点は誤差が蓄積されて長時間はもたないこと。誤差をさらに差分補正…。


>USBシリアル変換のケーブルが使えれば
仮想COMポート(COM1からCOM5まで)で割り当てができてハイパーターミナルから使えるもの
なら使えるかもしれない。

675k5:2016/01/10(日) 10:00:10
>「時刻(定刻)」、「時間(間隔)」のどちらを重視するかということですね。
定刻を基本に、間隔が揃っているのが好ましいです。

たとえば、初期値として「時間(間隔)」と計測期間(回数)を与えると、計測するべき時刻(定刻)」は自ずから決まってくるので、それをmillitimeで見ればいいかなと。この場合、時間の触れが+方向に限定されるのが少し気になるところ。

millitimeを一日まわして気づいたのですが、時間によってmillitimeの揺らぎ精度が違うみたいです。1/100になったり、1/1000になったり。割り込みやデーモンとの関係があるんでしょうね。やはり、目標値を1/100秒程度がいいところなのかも知れません。あくまでもmillitimeとtime$は同じハードから時刻を得ているというのが前提ですが。

仮想COMポートとしては認識しているんですが、相手側のシリアルコントローラと相性が悪いのか。使えないことがおおいです。電圧値が違うからなんでしょうか。間にレベルコンバーターなどを入れれば動くのかな。

676671:2016/01/11(月) 03:20:15
>>675
>それをmillitimeで見ればいいかなと。この場合、時間の触れが+方向に限定されるのが少し気になる

millitimeを見張って『仮に時刻ぴったり』にできたとしても、
結局それは「過ぎ去りし時間」で+方向にだけぶれるのはいたしかないこと。
マイナス方向もありということは、時刻ぴったりの『少し前』に合わせるようなもの。
では『少し前』とはどうやって定義して決めるのかが課題。


>あくまでもmillitimeとtime$は同じハードから時刻を得ているというのが前提ですが。

millitimeとtimeは取得元は同じです。

WindowsではPCのRTCは精度が悪いので起動後、別のハード機構からの情報で
カウントして算出しているそうです。
タイマ割り込みより、millitimeの方が若干精度が高いということ。

タイマ割り込みはWindowsの互換性維持のため、精度は低いままです。


>millitimeを一日まわして気づいたのですが、時間によってmillitimeの揺らぎ精度が違うみたいです。

非リアルタイム系OSの宿命です。そもそもmillitimeを取得する行為そのもの、そして結果を
画面等に出力すること自体が「ゆらぎ」の発生源のひとつなのですから。

>やはり、目標値を1/100秒程度がいいところなのかも知れません

いかに無限ループでmillitimeを観測しようと、プリエンティブなマルチタスクOSなので、
どこかで実行権を剥奪されるので、タスク切り換え単位以下の精度を維持しつづけることは
できないので、計測時間範囲で平均値を維持するのがやっとのはずです。
まあ極論、OSをWindows Ver.3.1、F-BASIC for Windows (V3.1)にすればということですが。


>割り込みやデーモンとの関係があるんでしょうね
そういうことですね、高精度を維持したければ、
割り込みがかかる不要なハードはすべてドライバ無効化(USBなんぞ禁止)、
不要な「サービス」はすべて停止、スクリーンセーバ等禁止、省電力機能禁止、
ウイルス対策ソフトなど常駐モノは完全にキル。
NTPによる時刻同期も当然禁止。ネットワークもハード(NIC)ごと停止。
メモリ(RAM)が大量にあるならば仮想記憶のスワップファイルをゼロに。

計測中は一切画面に経過表示せず、計測データはディスクに書かずメモリに保持、
「ペンキ塗りたて」ならぬ「マウス・キーボード触るな」
張り紙が必要な精度ですね。

>電圧値が違うからなんでしょうか。間にレベルコンバーターなどを入れれば動くのかな。
うーん、USB変換ケーブルタイプはそんな感じなんですか...
電圧に関して規定がゆるいですからね。
PC/AT機のシリアルポートはケープル長が2m〜3mが限界だとかいう虚弱ぶり。
そんなのをみならっているんでしょうかね。

RS-232なら規格限界値15mだったっけ?

677k5:2016/01/11(月) 11:12:39
LinuxでGPSを使ったNTPサーバーを運用する場合、大まかな時間(1秒)はntpであわせて、それ以下はGPSから来るPPSであわせるので、これが簡単でいいところななのかと思っています。

いろいろと考えてみると、計測間隔は1/100〜1/10程度の精度で時刻は1秒以内という辺りがよさそうです。つまり、3日間連続で計測していても、定刻は秒レベルではあっている。time$で確度、millitimeで精度を確保すると。明日にでもやってみます。

>うーん、USB変換ケーブルタイプはそんな感じなんですか...
>電圧に関して規定がゆるいですからね。
USB変換チップとドライバとシリアル機器側のコントローラの組み合わせみたいですが、F-BASICを使うとほとんど動かないみたいです。実験する時は、古いシリアルポート付のノートPCを使っています。

678名無しさん:2016/01/14(木) 09:03:45
こんにちは

昨日は、times$が更新(10秒ごと)された直後のmillitimeを見てみました。
こんな簡単なプログラムです。

cls

do
if right$(time$,1)="0" then gosub *KAKE
if right$(time$,1)<>"0" then flg=1
loop
stop
end
'

*KAKE

if FLG=1 then print time$,millitime:FLG=0

return

8時間ほど走らせた結果、millitimeの末尾4桁はほとんど0000でした。

14:50:50 53450000
14:51:00 53460000
14:51:10 53470000
14:51:20 53480000
14:51:30 53490000
14:51:40 53500000
14:51:50 53510000
14:52:00 53520000
14:52:10 53530000
14:52:20 53540000
14:52:30 53550000
14:52:40 53560000
14:52:50 53570000
14:53:00 53580000
14:53:10 53590000
14:53:20 53600000
14:53:30 53610000

あくまでもPCのタイマーの表示ですが。F-Basicのmillitimeは貴重な命令ですね。

679名無しさん:2016/01/15(金) 01:56:54
>>678
>8時間ほど走らせた結果、millitimeの末尾4桁はほとんど0000でした。


 millitimeとtimeは取得元は同じで、直近上方に丸めることはないと思いますので、
millitimeの末尾3〜4桁(おそらく最後の1/1000の位は除き)がゼロでないというのは
無いはずです。

この場合、注目すべき点は、 ほ・と・ん・ど が0000であること。
ということは、0000でないものが存在しえたということ。

それは単純に豪腕ループでtime$を常時監視続けただけでは回避できないということ。


timeの時刻精度では1〜2時間でGPS取得との差異が許容誤差範囲を超えるのでは?

680名無しさん:2016/01/15(金) 03:01:18
本当に出会える出会い系ランキング
http://bit.ly/1MVgwpz

681名無しさん:2016/01/15(金) 04:13:42
>>680 :名無しさん :2016/01/15(金) 03:01:18
過疎板には貼っても無意味

682名無しさん:2016/01/15(金) 09:04:48
ちなみにprint文の前にwait100を入れると、末尾4桁は0100になりました。
millitimeでやっても同じみたいです。
if millitime mod 10000 = 0 then gosub *KAKE

ただ、print文を入れるとかなり揺らぐみたいです。
あまり深くは考えずに、間隔はtimeでやって、時刻はRTCとNTPに任せます。

>timeの時刻精度では1〜2時間でGPS取得との差異が許容誤差範囲を超えるのでは?
一日で1秒以内とすると、1/10万程度の精度になるんですね。GPS受信機の内蔵時計の精度が30ns程度と言われていますので、これだと1年で1秒くらいですか。たしかに、GPS受信機の大部分が位置情報ではなく時間同期に使われているというのは納得です。

最近は高精度のクロックが売られるようになったので、これでも使ってみるかな(冗談です)
http://www.microsemi.com/products/timing-synchronization-systems/time-frequency-references/chip-scale-atomic-clock

683名無しさん:2016/01/16(土) 04:24:08
>>682
末尾4桁(0000)とは正確なハード環境みたいですね。

>ただ、print文を入れるとかなり揺らぐみたいです。

テキスト画面のスクロールが発生するとかなりのペナルティをくらいます。(>669)

経過表示を入れるのならスクロールをしないように先頭行に戻して上書きで表示する
方法をとる必要があるでしょう。


>GPS受信機の大部分が位置情報ではなく時間同期に使われているというのは納得です。

GPSは基準時刻との時差そのものがカギ。相対性理論による補正を必要とする世界。
位置情報は新鮮な地図(高低差)と補正がカギ。

684k5:2016/01/16(土) 10:12:44
>末尾4桁(0000)とは正確なハード環境みたいですね。
DELLのワークステーションです。

>経過表示を入れるのならスクロールをしないように先頭行に戻して
>上書きで表示する方法をとる必要があるでしょう。
そうします。

>GPSは基準時刻との時差そのものがカギ。相対性理論による補正を必要とする世界。
特殊と一般、両方使われていますね。私のフィールドでは時差も使いますが、位相差も使います。2台のGPSで同じ信号を受信してその位相差で相対位置を求めます。

Linuxでもbasicが動かないかと調べていたら、freeBasicという処理系があるようです。これはQBコンパチみたいなので、少し期待しています。

685名無しさん:2016/01/16(土) 10:50:20
>>684
>2台のGPSで同じ信号を受信してその位相差で相対位置を求めます。

そういう使いかたがあるんですね。

Linuxの方がタイムスライスの粒度が細かいので、向いているでしょうね。

686k5:2016/03/20(日) 13:03:40
また、相談させてください。

GPSから1秒ごとに出力されるデータを読み込んでPCのディスクに書き込んでいます。
データは文字で90バイトほどの固定長です。
プログラムはこんな感じです。


baud 0,9600
open "COM0:" for input as #1
open "nmea.txt" for create as #2

do

line input #1,GPGGA$
open "nmea.txt" for create as #2
print #2,GPGGA$

loop

しばらく(10分ほど)は動くのですが、読み出すタイミングが悪いのか、やがてプログラムがハングアップしてしまいます。フロー制御も、OFF、xon/off、ハードと試してみたのですが同じです。仕方がないので、teratermのログとして保存していますが、やはりプログラムから直接読めた方が便利です。

計測機器から一定時間で流れてくるデータを読む方法って、やはりイベント駆動型にした方がいいんでしょうか。

687名無しさん:2016/03/20(日) 19:31:46
女に年収バレた結果www
http://bit.ly/1R5A6lq

688名無しさん:2016/03/23(水) 04:14:49
>>686
対症療法としては10分たつ前にCOM0: をcloseして再オープンしてみるとか。


ハングアップするならline input# でしょうから、こんなかんじだとどうでしょうか。
(*改行コード含め90バイトとして。)

CHK_TIME%=((time mod 60)+2) mod 60 'リミットをおよそ2秒後に設定
do while lof(1) < 90
if (time mod 60) = CHK_TIME% then print "**受信エラー**" :exit do
loop
if lof(1) < 90 then GPGGA$=input$(lof(1), #1) else GPGGA$=input$(90, #1)

if right$(GPGGA$,1)=chr$(13) then GPGGA$=left$(GPGGA$, len(GPGGA$) - 1)

689k5:2016/03/23(水) 10:24:09
ありがとうございます。教えていただいたコードを組み込んで実行したところ、30分を経過してもまだ止まっていません。今日一日、ログをとり続けてみます。またご報告します。

690k5:2016/03/23(水) 19:44:23
こんばんは

8時間たっても動いています。
このコードは大切に使わせていただきます。
ありがとうございました。

691名無しさん:2016/03/26(土) 03:05:55
【キャリア】40歳になってようやくわかる8つのこと。
http://bit.ly/22ru7TF

692名無しさん:2016/03/27(日) 04:29:54
プログラム(>672)は
KANKAKUを1秒に設定にすると正常に動作しないので、サブルーチンを修正しておきます。
それから*MUGENSENSおよび*MUGENSENS2サブルーチンは削除します。
処理内容は変更しました。
1. interval割り込みで、2秒未満まで待ち。
2. WAITで0.1秒単位待ち。
3. 指定時刻まで残り時間が0.1秒近くある場合は一回WAITで待って、完了とする。
4. 3の処理をしない場合に限り、豪腕でループぶん回してmillitimeを読み続けて時刻合わせ。

ソフト・ハード両環境によるが、次の1行を順次変更することで精度を上げられるかもしれません。
→→ if OWARI>=30 and OWARI < 100 then wait (1+(OWARI \ 10)) :return
1. if OWARI>=30 and OWARI < 100 then wait (0+(OWARI \ 10)) :return
2. if OWARI>=30 and OWARI < 100 then wait (0+(OWARI \ 10))
3.コメントアウトしてプログラムから外す。
※2、3の変更案は、負荷がかかります。


*JUSTTIME2:return
*JUSTTIME
OWARI=millitime
if (OWARI mod 1000)>=900 and KANKAKU>=2 then
OWARI=1000-(OWARI mod 1000)
wait 1+(OWARI \ 10) 'ここは越えるようにする
endif
OWARI=KANKAKU-((millitime \ 1000) mod KANKAKU)
if OWARI >= 2 then '差が2秒以上あるならば、
interval OWARI-1 '秒単位の割り込み。ただし1秒残す。
on interval gosub *JUSTTIME2
interval on
waiti '設定している割り込みが発生するまで停止します。
interval off
end if
OWARI=1000-(millitime mod 1000)
if OWARI >= 100 then
wait (OWARI \ 100)*10 '1/100秒単位:0.1秒粗く待つ
endif

OWARI=1000-(millitime mod 1000)
if OWARI>= 100 then MUGEN_CC=-1:return '←TIME OVER!!
OWARI=millitime
if KANKAKU-((OWARI \ 1000) mod KANKAKU)>= 2 then
MUGEN_CC=-1 :return '←TIME OVER!!
OWARI=1000-(OWARI mod 1000)
else
OWARI=1000-(OWARI mod 1000)
endif

OWARI=1000-(millitime mod 1000)
MUGEN_CC=0
if OWARI >= 100 then return
if OWARI>=30 and OWARI < 100 then wait (1+(OWARI \ 10)) :return
if KANKAKU < 2 then
do 'ループしてmillitimeを秒未満チェック待ち
MUGEN_CC=MUGEN_CC+1
NOW=(millitime mod 1000)
loop until NOW<900
else
do 'ループしてmillitimeを秒単位チェック待ち
MUGEN_CC=MUGEN_CC+1
NOW=(millitime \ 1000) mod KANKAKU
loop until NOW=0
endif
return

693k5:2016/03/30(水) 09:29:23
さっそく、このコードで試してみました、
この精度(確度)で十分です。
ありがとうございました。


deflng A-Z 'ここから暗黙の型を32bit整数型にします。
var KANKAKU, OWARI, NOW
var MUGEN_CC, MUGEN_NN, MUGEN_NN2
var KAISU%

cls
'gosub *MUGENSENS

KANKAKU=5
print time$, millitime/1000#
gosub *JUSTTIME
print time$, millitime/1000#

KAISU%=0 :do while KAISU% < 720 '実行回数
gosub *JUSTTIME '時刻合わせ
print date$,time$,millitime

'*** input AAA$

KAISU%=KAISU%+1 :loop
'
stop:end
*KAKE: print date$,time$ :return
'
*JUSTTIME2:return
*JUSTTIME
OWARI=millitime
if (OWARI mod 1000)>=900 and KANKAKU>=2 then
OWARI=1000-(OWARI mod 1000)
wait 1+(OWARI \ 10) 'ここは越えるようにする
endif
OWARI=KANKAKU-((millitime \ 1000) mod KANKAKU)
if OWARI >= 2 then '差が2秒以上あるならば、
interval OWARI-1 '秒単位の割り込み。ただし1秒残す。
on interval gosub *JUSTTIME2
interval on
waiti '設定している割り込みが発生するまで停止します。
interval off
end if
OWARI=1000-(millitime mod 1000)
if OWARI >= 100 then
wait (OWARI \ 100)*10 '1/100秒単位:0.1秒粗く待つ
endif

OWARI=1000-(millitime mod 1000)
if OWARI>= 100 then MUGEN_CC=-1:return '←TIME OVER!!
OWARI=millitime
if KANKAKU-((OWARI \ 1000) mod KANKAKU)>= 2 then
MUGEN_CC=-1 :return '←TIME OVER!!
OWARI=1000-(OWARI mod 1000)
else
OWARI=1000-(OWARI mod 1000)
endif

OWARI=1000-(millitime mod 1000)
MUGEN_CC=0
if OWARI >= 100 then return
if OWARI>=30 and OWARI < 100 then wait (1+(OWARI \ 10)) :return
if KANKAKU < 2 then
do 'ループしてmillitimeを秒未満チェック待ち
MUGEN_CC=MUGEN_CC+1
NOW=(millitime mod 1000)
loop until NOW<900
else
do 'ループしてmillitimeを秒単位チェック待ち
MUGEN_CC=MUGEN_CC+1
NOW=(millitime \ 1000) mod KANKAKU
loop until NOW=0
endif
return

694k5:2016/03/30(水) 09:44:54
最近の計測器でbluetoothで接続するタイプが増えているみたいです。たしかに配線が楽ですからね。windowsの場合はCOMポート接続ができるようです。このCOMポートをF-BASICからアクセスすることができるか、とても興味があります。

誰か、使ったことはありますか?

週末にでもbluetoothが使えるノートPCとbluetooth I/Fの簡単な温度計が借りられるので、F-BASICで使えるかテストしてみます。

695名無しさん:2016/03/30(水) 23:36:54
帰りにロジテックのBluetoothアダプタを買ってきて使ったところ、問題なくcomポートをF-BASICで使うことができました。これはとっても快適です。

購入したBluetoothアダプタはロジテックのLBT-UAN04C2という製品です。
http://bbs.kakaku.com/bbs/K0000373744/

RS-232CをBluetoothで無線化するアダプターが少々高いですが、コードの引き回しや延長距離などを考えると、これはいいです。興味のある方は、ぜひぜひ使ってみて下さい。

696名無しさん:2016/03/31(木) 06:03:14
>>694,695
試用レポート、ありがとうございます。

無線化すると便利だけれどプログラム上は通信エラーの対応処理の省略が
しづらい。

697名無しさん:2016/03/31(木) 09:42:49
そうなんですか、USBシリアル変換ケーブルが全滅状態で、RS232ポートがついているパソコンも少なくなっている時勢に、シリアル通信が出来るのはとても嬉しいです。

あとは、シリアルをBluetoothで無線化するアダプターがもっと安くなればいいなと。今は2万ほどしますからね。安いのは1万ほどであるみたいです。

Linuxを使ってCとかシェルスクリプトでも書いてみたんですが、やはりBASICは慣れているので、細かいところまで融通が利きます。これでまだしばらく、F-BASICが使えそうです。

698名無しさん:2016/04/01(金) 03:30:42
会社クビになって奨学金返済できなくなったんだが契約書にヤバイ文章が見つかった
http://bit.ly/1R5zV9T

699名無しさん:2016/04/01(金) 03:55:31
>>697
まあ、実際は電波を遮る物体が通るとかしなければ、
シリアル通信の速度程度では障害にはならないでしょうから
通信エラーは無視できるリスクでしょう。

物理的なシリアルポートに接続する無線化アダプターでは、
ケーブルなしの直結(ゼロ距離)なので、結果的に
USB-シリアル変換タイプより問題がおきにくいのかもしれません。

ソフトウェア上はBluetoothのシリアル通信のプロファイル(SPP)で
仮想的なシリアルポートとしてやりとりします。

700名無しさん:2016/04/01(金) 08:46:40
Bluetoothは2.4G帯を使うので、電子レンジとかとの干渉はないかと思っているんですが、今のところ大丈夫みたいです。

ただ、Bluetoothのドライバーが作り出す仮想シリアルポートはよくわからなくて、F-BASICではcom5にしないとアクセスできなかったりします。com3とかにすると、その入力装置は使えないというメッセージが出ます。OSやドライバーを作っている会社などの相性があるのも知れません。この辺りは、しばらく手探りが続いてゆきそうです。

701名無しさん:2016/04/02(土) 04:30:59
周波数ホッピングとか軍採用技術が使われているので速度低下ですむかと。

com1からcom4ポートはBIOS設定の関連もあると思います。
オンボードのポートが1つで(Fax)モデムカード等がないなら、
com2, 4ポートが使えるかも。
F-BASICではcom5ポート("COM4:")までしか対応していません。
ps. 仮想COMポートをオープンするのに "\\.\com9" 形式があるらしいの
ですが、オープンはできてもcomポートとしては使えないだろうし。

702名無しさん:2016/04/03(日) 00:16:16
>周波数ホッピングとか軍採用技術が使われているので速度低下ですむかと。
拡散スペクトラムですね。その昔は、話しに聞いているだけでした。身近なところではGPSが一番最初でしたか。CDMAより早かったと思います。

>com1からcom4ポートはBIOS設定の関連もあると思います。
>オンボードのポートが1つで(Fax)モデムカード等がないなら、
>com2, 4ポートが使えるかも。
うーん、この辺り不は不明です。

さきほど、同じプログラムをWindows10(64bit)で動作させましたが、他のポートでも問題なく動いています。このノートPCはbluetoothが標準装備されているので、純正ドライバーによる仮想comポートによる通信が安定しているみたいです。3rdパーティのドライバーとの相性がよくないのかも知れません。本を取り寄せて、bluetoothのお勉強をしなくては。

703名無しさん:2016/04/09(土) 17:17:33
友人関係全部切った結果
http://bit.ly/1Sepcun

704名無しさん:2016/04/11(月) 00:29:31
本当に出会える出会い系ランキング
http://bit.ly/1OgYRt7

705名無しさん:2016/04/11(月) 09:16:26
>688

CHK_TIME%=((time mod 60)+2) mod 60 'リミットをおよそ2秒後に設定
do while lof(1) < 90
if (time mod 60) = CHK_TIME% then print "**受信エラー**" :exit do
loop
if lof(1) < 90 then GPGGA$=input$(lof(1), #1) else GPGGA$=input$(90, #1)

if right$(GPGGA$,1)=chr$(13) then GPGGA$=left$(GPGGA$, len(GPGGA$) - 1)


いつもお世話になります。
せっかくなんで、このコードの意味を解説していただけると勉強になります。
恥ずかしながら、自分なりに読んでみました。

*ここから始まり

CHK_TIME%=((time mod 60)+2) mod 60 'リミットをおよそ2秒後に設定
*現在の通算秒数を分に換算して、そのあまり秒に2秒を足してを待機する上限時間を求める。最後の(mod 60)の意味がよくわかりません。

do while lof(1) < 90
if (time mod 60) = CHK_TIME% then print "**受信エラー**" :exit do
loop

受信バッファが90バイトに達するまで読み込む。
もし、その間に上限時間を超えたらdoープを抜ける

if lof(1) < 90 then GPGGA$=input$(lof(1), #1) else GPGGA$=input$(90, #1)
もし、受信バッファが90バイトに達していなければGPGGA$に入っているだけ代入する。
そうでなければ、、受信バッファから90バイトをGPGGA$に代入する

if right$(GPGGA$,1)=chr$(13) then GPGGA$=left$(GPGGA$, len(GPGGA$) - 1)
GPGGA$の行末コードを削除する

よろしくお願いします。

706688:2016/04/12(火) 02:57:29
問題の有るコードではあるのですが――。疑問点に回答します。

>>705
>最後の(mod 60)の意味がよくわかりません。

これは通算秒数から剰余計算で秒部分(0〜59秒)を取り出した後、
現在時刻が58〜59秒だった場合、2を加算して2秒後を求めただけだと60秒以上になるため。
ラウンドアップへの対処。

>受信バッファが90バイトに達するまで読み込む。

処理1件分のデータが受信バッファにたまるまで『あえて読まずに』待つ。
2秒程度の時間切れ条件判断はもしもの場合の保険。

>もし、受信バッファが90バイトに達していなければGPGGA$に入っているだけ代入する。

補足説明すると、受信データが90バイト固定長以外のデータが受信された場合や途中までしか
送られてこなかったような場合など、とりあえず処理継続することを優先する意図があります。

本来はIF文で場合分けする必要はない(GPGGA$=input$(lof(1), #1)のみですむ)のですが、
問題原因がデータの形式にあった場合などのための対処への意図を含めた結果です。


実際にデータを読み込む処理をしているこの2行についてですが、

>if lof(1) < 90 then GPGGA$=input$(lof(1), #1) else GPGGA$=input$(90, #1)
>
>if right$(GPGGA$,1)=chr$(13) then GPGGA$=left$(GPGGA$, len(GPGGA$) - 1)
>GPGGA$の行末コードを削除する

90バイトそろっているのであれば、
ごく普通にLINE INPUT#1,GPGGA$ ひとつで済ませてもよいとは思いますが、
問題を確実に回避することを優先して、LINE INPUT# を使わないという選択肢をとりました。

707名無しさん:2016/04/12(火) 09:11:22

丁寧な解説、ありがとうございます。

(mod 60)の意味、そうだったんですね。
理解できました。

シリアル通信がbluetoothなどで仮想化されたり、計測器もコントローラーとセンサー部分が無線モデムを使ったシリアル通信をしていると、パケットの衝突などが起きて、データが一定時間流れてこない状況が時たま発生します。伝統的な実物のシリアルケーブルならLINE INPUT#で苦なく読めたデータもこのように工夫しないといけないのですね。教えていただいてとても勉強になりました。今後ともよろしくお願いします。

708688:2016/04/13(水) 02:44:42
>>707
>計測器もコントローラーとセンサー部分が無線モデムを使ったシリアル通信をしていると、
>パケットの衝突などが起きて、データが一定時間流れてこない状況が時たま発生します。

なるほど、昨今そういった状況になっているのですね。

 ただ、「(ある/一定)時間流れてこない」といった状況でLINE INPUT# が使えない
わけではないはずです。COMポートに対してのLINE INPUT#は、改行コードが流れてくるまで、
「F-BASIC内部でいろいろ処理しながら」待ち続けるのが仕様です。
(ただしopen命令でタイムアウト指定をしない場合)
改行コードが文字化けしない限りは問題ないはずなのです。

問題の発生要因は、RS/CSなどの制御線の制御タイミングが関わっていると見るのが妥当です。

シリアル通信プロファイル(SPP)による通信のエミュレートや、計測器側の動作も含め、
相性問題もあるかもしれません。

709名無しさん:2016/04/13(水) 17:40:05

>なるほど、昨今そういった状況になっているのですね。
PCからはシリアルポートがなくなりつつありますが、周辺機器ではまだまだ現役ですからね。

>シリアル通信プロファイル(SPP)による通信のエミュレートや、
>計測器側の動作も含め、相性問題もあるかもしれません。
SPPの品質はスタックの出来次第らしいです。東芝やモトローラーのが評判いいです。もう東芝は外販していないみたいですが、bluetooth付のdynabookは安定していると聞いています。またもうディスコンになった東芝のusbドングルもプレミアがついて驚くほどの高値です。

710名無しさん:2016/04/15(金) 16:54:56
本当に出会える出会い系ランキング
http://bit.ly/1OgYRt7

711名無しさん:2016/04/20(水) 15:28:30
本当に出会える出会い系ランキング
http://bit.ly/1OgYRt7

712名無し:2017/02/24(金) 23:18:46
何方か教えて下さい、長く使用してなかったのですが、思い付きでfbasicをWidows7に入れてみたら結構動くのが解って、
今いろいろ試して楽しんでいます、使ったことの無い Choosefont(****,0,0) 命令の書き方が解りません。
**** の部分にはガイドでは「フォント」と書いてありますが、何方か詳しく教えて頂けませんか、フォント名の変更に
苦労してます。


新着レスの表示


名前: E-mail(省略可)

※書き込む際の注意事項はこちら

※画像アップローダーはこちら

(画像を表示できるのは「画像リンクのサムネイル表示」がオンの掲示板に限ります)

掲示板管理者へ連絡 無料レンタル掲示板