C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

PLCから読出し

[トピック内 13 記事 (1 - 13 表示)]  << 0 >>

■100826 / inTopicNo.1)  PLCから読出し
  
□投稿者/ たけ (3回)-(2022/10/31(Mon) 13:46:00)

分類:[C#] 

read ボタンを押すとPLC(KEYENCE KV7500) からDM0の値を読んでtext1.textに
表示をするまでできたのですが DM0〜DM9までの英数文字列20文字を
読み込むにはどこを変えればよろしいでしょうか




private void btn_read_Click(object sender, EventArgs e)
        {
            string host = "192.168.3.1";
            int port = 8501;

            TcpClient tcp = new TcpClient();
            tcp.Connect(host, port);
            if (tcp.Connected)
            {
                Console.WriteLine("サーバー({0}:{1})と接続しました({2}:{3})",
                ((IPEndPoint)tcp.Client.RemoteEndPoint).Address,
                ((IPEndPoint)tcp.Client.RemoteEndPoint).Port,
                ((IPEndPoint)tcp.Client.LocalEndPoint).Address,
                ((IPEndPoint)tcp.Client.LocalEndPoint).Port);
            }

            NetworkStream ns = tcp.GetStream();
            ns.ReadTimeout = 10000;
            ns.WriteTimeout = 10000;

            string sendMsg = "RD DM000";
            Encoding enc = Encoding.ASCII;
            byte[] sendBytes = enc.GetBytes(sendMsg + '\r');

            ns.Write(sendBytes, 0, sendBytes.Length);
            Console.WriteLine(sendMsg);

            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            byte[] resBytes = new byte[256];
            int resSize = 0;
            do
            {
                resSize = ns.Read(resBytes, 0, resBytes.Length);
                if (resSize == 0)
                {
                    Console.WriteLine("サーバーが切断しました。");
                    break;
                }
                ms.Write(resBytes, 0, resSize);
            } while (ns.DataAvailable || resBytes[resSize - 1] != '\n');

            string resMsg = enc.GetString(ms.GetBuffer(), 0, (int)ms.Length);
            ms.Close();

            resMsg = resMsg.TrimEnd('\n');

            textbox1.Text = resMsg;

            ns.Close();
            tcp.Close();

        }
}

引用返信 編集キー/
■100827 / inTopicNo.2)  Re[1]: PLCから読出し
□投稿者/ kiku (304回)-(2022/10/31(Mon) 16:22:09)
No100826 (たけ さん) に返信
> read ボタンを押すとPLC(KEYENCE KV7500) からDM0の値を読んでtext1.textに
> 表示をするまでできたのですが DM0〜DM9までの英数文字列20文字を
> 読み込むにはどこを変えればよろしいでしょうか

どこがどのようにわからないのですか?
DM0を読みだせていれば内容を理解していると思うのですが
理解していないということでしょうか?
ということであればどこが理解できていないのでしょうか?

方法としては2つあると思います。
方法1
 DM0が読みだせたので、DM1〜DM9もコマンドを変えながら繰り返していく。

方法2
 現在RDコマンドを使っていますが、
 マニュアルが手元にないので間違っているかもですが、
 連続データ読み出しができるコマンドがあったはずです。
 そのコマンドでDM0〜DM9までの1コマンドで取得できるはずです。
 メーカからマニュアルを取得し、どんなコマンド形式なのかを確認してください。

引用返信 編集キー/
■100828 / inTopicNo.3)  Re[2]: PLCから読出し
□投稿者/ kiku (305回)-(2022/10/31(Mon) 17:10:19)
No100827 (kiku さん) に返信
> ■No100826 (たけ さん) に返信
> 方法2
>  現在RDコマンドを使っていますが、
>  マニュアルが手元にないので間違っているかもですが、
>  連続データ読み出しができるコマンドがあったはずです。
>  そのコマンドでDM0〜DM9までの1コマンドで取得できるはずです。
>  メーカからマニュアルを取得し、どんなコマンド形式なのかを確認してください。

string sendMsg = "RDS DM000 10";

上記でたぶん連続データ読み出しになると思います。
RDSは、連続データ読み出しの指定。
末尾の10は、10個連続で読みだすという意味。
応答は、半角スペース区切りで10個連続で返ってくるはず。
引用返信 編集キー/
■100829 / inTopicNo.4)  Re[1]: PLCから読出し
□投稿者/ KOZ (350回)-(2022/10/31(Mon) 17:28:36)
No100826 (たけ さん) に返信
>             } while (ns.DataAvailable || resBytes[resSize - 1] != '\n');

ns.DataAvailable を見てループを抜けるのはやめたほうがいいです。
パケットが長くなると、分割して届くので、未受信のテキストがあるのにループを抜けてしまう可能性があります。
デリミタまできっちり受信しましょう。

よく見かけるコードですが、不具合が起こったことはないんでしょうかね・・・

引用返信 編集キー/
■100830 / inTopicNo.5)  Re[2]: PLCから読出し
□投稿者/ たけ (5回)-(2022/10/31(Mon) 17:37:21)
No100829 (KOZ さん) に返信
> ■No100826 (たけ さん) に返信
>> } while (ns.DataAvailable || resBytes[resSize - 1] != '\n');
>
> ns.DataAvailable を見てループを抜けるのはやめたほうがいいです。
> パケットが長くなると、分割して届くので、未受信のテキストがあるのにループを抜けてしまう可能性があります。
> デリミタまできっちり受信しましょう。
>
> よく見かけるコードですが、不具合が起こったことはないんでしょうかね・・・


ありがとうございます
数字を読んでいるときは大丈夫でしたが DM0〜DM9 の英数文字を読みだそうとすると
textbox1.text に数字で表示してしまいます
文字で表示するにはどうしたらいいでしょうか
引用返信 編集キー/
■100831 / inTopicNo.6)  Re[3]: PLCから読出し
□投稿者/ KOZ (351回)-(2022/10/31(Mon) 17:47:52)
No100830 (たけ さん) に返信
> ありがとうございます
> 数字を読んでいるときは大丈夫でしたが DM0〜DM9 の英数文字を読みだそうとすると
> textbox1.text に数字で表示してしまいます
> 文字で表示するにはどうしたらいいでしょうか

改変後のソースがわからないと何ともいえないですが、相手から数字が送られてきているのでは?
読み取ったデータを確認してみましょう、

あと、kiku さんが提案された、連続読み出しは試してみましたか?

引用返信 編集キー/
■100832 / inTopicNo.7)  Re[3]: PLCから読出し
□投稿者/ たけ (6回)-(2022/10/31(Mon) 17:49:33)

PLCの方に DM0="AA" DM1="BB" DM2="CC" 〜という風に入っているのですが
読みだすとtextbox1.textに "16705 16962 17219 17476 17733 17990 18247 18504 18761 19018"が入りました

textbox1.textに "AABBCCDDEEFFGGHHIIJJ"と入れたいのですが
どこを変更すればいいでしょうか

引用返信 編集キー/
■100833 / inTopicNo.8)  Re[4]: PLCから読出し
□投稿者/ KOZ (352回)-(2022/10/31(Mon) 18:42:35)
No100832 (たけ さん) に返信
> PLCの方に DM0="AA" DM1="BB" DM2="CC" 〜という風に入っているのですが
> 読みだすとtextbox1.textに "16705 16962 17219 17476 17733 17990 18247 18504 18761 19018"が入りました

16705 = &H4141 → Chr(&H41) + Chr(&H41) = AA
16962 = &H4242 → Chr(&H42) + Chr(&H42) = BB

こういう仕様なんでしょうか?

> textbox1.textに "AABBCCDDEEFFGGHHIIJJ"と入れたいのですが
> どこを変更すればいいでしょうか

これでは作業依頼ですね。なんぼもらえるんかしら?

冗談はさておき、手順を説明すると

(1) 得られた文字列を空白文字で Split して配列にする
(2) それぞれの要素を Integer に変換する(Integer.Parse)
(3) (2) を文字列に変換。値を value とすると Chr((value >> 8) And &HFF) & Chr(value And &HFF)
(4) (3) の値をすべてくっつける

という手順になります。
引用返信 編集キー/
■100834 / inTopicNo.9)  Re[5]: PLCから読出し
□投稿者/ KOZ (353回)-(2022/10/31(Mon) 18:53:46)
No100833 (KOZ) に返信

しまった C# だった。

> (3) (2) を文字列に変換。値を value とすると Chr((value >> 8) And &HFF) & Chr(value And &HFF)

new string(new char[] { (char)(value >> 8 & 0xff), (char)(value & 0xff) })

です。
引用返信 編集キー/
■100835 / inTopicNo.10)  Re[4]: PLCから読出し
□投稿者/ たけ (7回)-(2022/11/01(Tue) 11:03:13)
分からず聞いてしまいました
勉ありがとうございました強しながらやってみます
ありがとうございました
解決済み
引用返信 編集キー/
■100836 / inTopicNo.11)  Re[5]: PLCから読出し
□投稿者/ KOZ (354回)-(2022/11/01(Tue) 13:22:11)
No100835 (たけ さん) に返信

上に書いたロジックは、私の予想です。
マニュアルは確認されましたか?
解決済み
引用返信 編集キー/
■100851 / inTopicNo.12)  Re[6]: PLCから読出し
□投稿者/ たけ (8回)-(2022/11/03(Thu) 16:47:57)
No100836 (KOZ さん) に返信
> ■No100835 (たけ さん) に返信
> 
> 上に書いたロジックは、私の予想です。
> マニュアルは確認されましたか?



ありがとうございます
調べて書いてみました

DMを1個読み込む時は
最後のtextbox2.text に"AA"と表示できるようにまでなりました

ですがDMを2個読み込むとエラーになります
textbox1.text の中身が"16705 16962"になっていました

DMを1個読んでは文字に変換して、それを2回繰り返して
引っ付けるしかないでしょうか



 private void btn_capture_Click(object sender, EventArgs e)
        {
            Console.WriteLine("START");
            string host = "192.168.3.1";
            int port = 8501;

            TcpClient tcp = new TcpClient();
            tcp.Connect(host, port);
            if (tcp.Connected)
            {
                Console.WriteLine("サーバー({0}:{1})と接続しました({2}:{3})",
                ((IPEndPoint)tcp.Client.RemoteEndPoint).Address,
                ((IPEndPoint)tcp.Client.RemoteEndPoint).Port,
                ((IPEndPoint)tcp.Client.LocalEndPoint).Address,
                ((IPEndPoint)tcp.Client.LocalEndPoint).Port);
            }

            NetworkStream ns = tcp.GetStream();
            ns.ReadTimeout = 10000;
            ns.WriteTimeout = 10000;

            //string sendMsg = "WR R000 0";
            string sendMsg = "RDS DM000 1";// RDS DM000 2
            Encoding enc = Encoding.ASCII;
            byte[] sendBytes = enc.GetBytes(sendMsg + '\r');

            ns.Write(sendBytes, 0, sendBytes.Length);
            Console.WriteLine(sendMsg);

            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            byte[] resBytes = new byte[256];
            int resSize = 0;
            do
            {
                resSize = ns.Read(resBytes, 0, resBytes.Length);
                if (resSize == 0)
                {
                    Console.WriteLine("サーバーが切断しました。");
                    break;
                }
                ms.Write(resBytes, 0, resSize);
            } while (ns.DataAvailable || resBytes[resSize - 1] != '\n');

            string resMsg = enc.GetString(ms.GetBuffer(), 0, (int)ms.Length);
            ms.Close();

            resMsg = resMsg.TrimEnd('\n');
            Console.WriteLine(resMsg);//12850<==読出数
            textbox1.Text = resMsg;



            int a = Convert.ToInt32(textbox1.Text);
            string b = new string(new char[] { (char)(a >> 8 & 0xff), (char)(a & 0xff) });

            textBox2.Text = b;



            ns.Close();
            tcp.Close();

引用返信 編集キー/
■100852 / inTopicNo.13)  Re[7]: PLCから読出し
□投稿者/ とっちゃん (767回)-(2022/11/03(Thu) 17:29:09)
No100851 (たけ さん) に返信
> ありがとうございます
> 調べて書いてみました
>
> DMを1個読み込む時は
> 最後のtextbox2.text に"AA"と表示できるようにまでなりました
>
> ですがDMを2個読み込むとエラーになります
> textbox1.text の中身が"16705 16962"になっていました
>
> DMを1個読んでは文字に変換して、それを2回繰り返して
> 引っ付けるしかないでしょうか
>
DM一つの場合は、特に区切りがなく1セット分(ASCIIで"16705"が送られてくる)が送られてきて
複数の場合は" "で区切られて送られてきているということだと思います。

であれば、送られてきたデータを文字列化した後 resMsg.Split(' ') とセパレータごとに分離して
その文字列単位で数値化->上下バイトに分解して文字列化とすれば、意図した値になると思います。

具体的には以下のような感じ(bytes以外は同じ変数名を使ってます)

byte[] bytes = resMsg.Split( ' ' ).Select( _ => Convert.ToInt32( _ ) ).SelectMany( _ => new byte[] { (byte)((_ >> 8) & 0xFF), (byte)(_ & 0xFF) } ).ToArray();
string b = Encoding.ASCII.GetString( bytes, 0, bytes.Length );

textBox2.Text = b;

resMsg の代わりに textBox1.Text を使っても同じです。

引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ