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

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

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

Re[4]: デジタルI/Oを待つには


(過去ログ 88 を表示中)

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

■52730 / inTopicNo.1)  デジタルI/Oを待つには
  
□投稿者/ キーサン (11回)-(2010/08/23(Mon) 16:32:40)

分類:[.NET 全般] 

パソコンに、外部デジタルI/O機器を接続しまして、
信号が0V→24Vに遷移した時に、処理を行うことをしたいと考えています。

信号を待つ事を、別スレッドによりポーリングで待ちたいと考えて、
ネット上を見まわして、書いてみました。
しかし、全く自信が持てません。そんなの危ないよ!みたいな突っ込みをお願いします。

特に、別スレッド処理内の「while(true)」と、アプリケーションが終わらせる時に
何もしないと別スレッドが止まらないので、仕方なく加えたForm_Closingイベント内の
thread.Abort();が気になっています。
この辺をアドバイスいただければありがたいです。

using System.Threading;

Thread thread;
public Form1()
{
InitializeComponent();

//別スレッドの生成とスタート
thread = new Thread(new ThreadStart(ThreadFunction));
thread.Start();
}
private void ThreadFunction()
{
while (true)
{
Thread.Sleep(1); //1msecおきに信号確認をしたいと思っています。
//信号の確認→処理
//(略)
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//別スレッドを停止
thread.Abort();
}
引用返信 編集キー/
■52731 / inTopicNo.2)  Re[1]: デジタルI/Oを待つには
□投稿者/ なちゃ (463回)-(2010/08/23(Mon) 17:41:53)
スレッドの停止は、ループ条件をメンバ変数などにするような形が簡単でしょう。
Abortは避けた方がいいです。

ところで、そのデジタル機器の信号の変化の頻度はどの程度のものですか?
Windowsでは確実に決められた頻度で状態をチェックするのは困難です。
チェック間隔が開いてしまったら信号の変化を見落としたりしそうですが。

引用返信 編集キー/
■52747 / inTopicNo.3)  Re[1]: デジタルI/Oを待つには
□投稿者/ オショウ (550回)-(2010/08/24(Tue) 00:28:39)
No52730 (キーサン さん) に返信
> パソコンに、外部デジタルI/O機器を接続しまして、
> 信号が0V→24Vに遷移した時に、処理を行うことをしたいと考えています。
>
> 信号を待つ事を、別スレッドによりポーリングで待ちたいと考えて、
> ネット上を見まわして、書いてみました。
> しかし、全く自信が持てません。そんなの危ないよ!みたいな突っ込みをお願いします。

  そのボード?のメーカーと型式は?

  提供されている機能・ドライバー・ソフトウェアで、I/Oが変化
  したらエベントを発生させれるものもありますし、コールバック関
  数を登録してその関数を呼ばせることで、やりたいことは可能です。

  スレッドでポーリングする場合は・・・やり方は、いろいろありま
  すので、まずは頑張って下さい。

※ 私はもっぱらインターフェース社のデジタルI/Oボードか、
  コンテック社のものを使ってます。

以上。参考まで
引用返信 編集キー/
■52750 / inTopicNo.4)  Re[2]: デジタルI/Oを待つには
□投稿者/ キーサン (12回)-(2010/08/24(Tue) 08:16:18)
なちゃさん、オショウさんありがとうございます。

> スレッドの停止は、ループ条件をメンバ変数などにするような形が簡単でしょう。
> Abortは避けた方がいいです。

つまりこれは、スレッド内の
while(true)
を、bool型のflagという変数を作り、
while(flag)
とでもして、外部から停止を制御するべきなんですね。
なるほどです。

> ところで、そのデジタル機器の信号の変化の頻度はどの程度のものですか?
> Windowsでは確実に決められた頻度で状態をチェックするのは困難です。
> チェック間隔が開いてしまったら信号の変化を見落としたりしそうですが。

信号は、変わったら変わりっぱなしなので見落としは大丈夫だと思います。
ただ、信号が変化したらなるべく早く動作をしたいので高頻度でチェックしたいな
って思っています。


>   そのボード?のメーカーと型式は?
>
>   提供されている機能・ドライバー・ソフトウェアで、I/Oが変化
>   したらエベントを発生させれるものもありますし、コールバック関
>   数を登録してその関数を呼ばせることで、やりたいことは可能です。

はい。とりあえずインターフェースのを買いました。
確かに、インターフェースのはイベントがありまして、それを使用しようかと
考えました。ところが、純粋なデジタルI/OではなくFA用ネットワーク用で
同様に使用したいボードがありまして、それはイベントが無いんです。
なので、インターフェースのも同様にスレッドでやりたいなって考えました。


>   スレッドでポーリングする場合は・・・やり方は、いろいろありま
>   すので、まずは頑張って下さい。

はい。がんばります!
引用返信 編集キー/
■52756 / inTopicNo.5)  Re[3]: デジタルI/Oを待つには
□投稿者/ オショウ (551回)-(2010/08/24(Tue) 10:02:11)
> はい。とりあえずインターフェースのを買いました。
> 確かに、インターフェースのはイベントがありまして、それを使用しようかと
> 考えました。ところが、純粋なデジタルI/OではなくFA用ネットワーク用で
> 同様に使用したいボードがありまして、それはイベントが無いんです。
> なので、インターフェースのも同様にスレッドでやりたいなって考えました。

  型式は?
  私はボードに関連してインターフェース社のサイトからGPC-2000を入手し
  IFCDIOクラス(これを.NET用と言われると困る)を作り直して、使ってま
  す。

  レベル信号なので、その信号の立ち上がりエッジだけを監視すると言う事
  ですが、高精度と言う意味合いであれば、ノイズって大丈夫?とお聞きし
  たい。PLCとかの信号であれば、100msくらいの1ショット信号を監視し
  て・・・みたいなこともできますが。

  私の自作IFCDIOクラスの一部(スレッドのところ)を参考に載せておきま
  す。ほかの部分との兼ね合いもありますが、流用して下さい。
  (VB.NETです)

  2種類のスレッドがありますが、何をどうしているのかは・・・
  解読して(推測して)みて下さい。Win32 APIも使ってます。

  因みに、TimerThreadの方は、ボードのタイマーイベントを使って機能する
  コールバック的なスレッドとなってます。

#Region "Private Thread"

    Private Sub MonitorThread(ByVal obj As Object)

        Dim dwEventBuf As Integer
        Dim Overlapped As OVERLAPPED
        Dim bRet As Boolean
        Dim iRet As Integer
        Dim dtBuff() As Integer
        Dim dtBit() As Boolean
        Dim dtBak() As Boolean
        Dim BitCount As Integer

        bMonitorJob = True

        BitCount = DirectCast(obj, Integer)

        ReDim dtBuff(BitCount - 1)
        ReDim dtBit(BitCount - 1)
        ReDim dtBak(BitCount - 1)

        For i As Integer = 0 To BitCount - 1
            dtBak(i) = False
        Next

        Overlapped = New OVERLAPPED()
        With Overlapped
            .hEvent = CreateEvent(0, True, False, 0)
            .Internal = 0
            .InternalHigh = 0
            .offset = 0
            .OffsetHigh = 0
        End With

        RaiseEvent MonitorError(MONITOR_ERROR.MonitorStart)

        While bMonitorJob
            iRet = DioEventRequestPending(hDevice, &H10, dwEventBuf, Overlapped)
            If iRet <> FBIDIO_ERROR_IO_PENDING Then
                RaiseEvent MonitorError(MONITOR_ERROR.EventRequesError)
                bMonitorJob = False
                Exit While
            End If

            If bMonitorJob = False Then
                Exit While
            End If

            iRet = WaitForSingleObject(Overlapped.hEvent, TimeoutInterval)
            If iRet = 0 Then
                iRet = DioInputPoint(hDevice, dtBuff, 1, BitCount)
                If iRet <> 0 Then
                    RaiseEvent MonitorError(MONITOR_ERROR.InputPointError)
                Else
                    For i As Integer = 0 To BitCount - 1
                        If dtBuff(i) <> 0 Then
                            dtBit(i) = True
                            dtNow(i) = True
                        Else
                            dtBit(i) = False
                            dtNow(i) = False
                        End If
                    Next

                    bRet = False
                    For i As Integer = 0 To BitCount - 1
                        If dtBit(i) <> dtBak(i) Then
                            bRet = True
                        End If
                    Next
                    If bRet Then
                        For i As Integer = 0 To BitCount - 1
                            dtBak(i) = dtBit(i)
                        Next
                        RaiseEvent ChangeBit(dtBit, BitCount)
                    End If
                End If
            Else
                RaiseEvent MonitorError(MONITOR_ERROR.WaitError)
                bMonitorJob = False
                Exit While
            End If
        End While

        iRet = DioSetIrqMask(hDevice, &H0)
        If iRet <> 0 Then
            RaiseEvent MonitorError(MONITOR_ERROR.MaskResetError)
        End If

        CloseHandle(Overlapped.hEvent)

        RaiseEvent MonitorError(MONITOR_ERROR.MonitorStop)

    End Sub

    Private Sub TimerThread(ByVal obj As Object)

        Dim dwEventBuf As Integer
        Dim Overlapped As OVERLAPPED
        Dim iRet As Integer
        Dim dtBuff() As Integer
        Dim dtBit() As Boolean
        Dim BitCount As Integer

        bTimerJob = True

        BitCount = DirectCast(obj, Integer)

        ReDim dtBuff(BitCount - 1)
        ReDim dtBit(BitCount - 1)

        Overlapped = New OVERLAPPED()
        With Overlapped
            .hEvent = CreateEvent(IntPtr.Zero, True, False, String.Empty)
            .Internal = 0
            .InternalHigh = 0
            .offset = 0
            .OffsetHigh = 0
        End With

        RaiseEvent MonitorError(MONITOR_ERROR.MonitorStart)

        While bTimerJob
            iRet = DioEventRequestPending(hDevice, &H10, dwEventBuf, Overlapped)
            If iRet <> FBIDIO_ERROR_IO_PENDING Then
                RaiseEvent MonitorError(MONITOR_ERROR.EventRequesError)
                bTimerJob = False
                Exit While
            End If

            If bTimerJob = False Then
                Exit While
            End If

            iRet = WaitForSingleObject(Overlapped.hEvent, TimeoutInterval)
            If iRet = 0 Then
                iRet = DioInputPoint(hDevice, dtBuff, 1, BitCount)
                If iRet <> 0 Then
                    RaiseEvent MonitorError(MONITOR_ERROR.InputPointError)
                Else
                    For i As Integer = 0 To BitCount - 1
                        If dtBuff(i) <> 0 Then
                            dtBit(i) = True
                            dtNow(i) = True
                        Else
                            dtBit(i) = False
                            dtNow(i) = False
                        End If
                    Next
                    RaiseEvent TimerEvent(dtBit, BitCount)
                End If
            Else
                RaiseEvent MonitorError(MONITOR_ERROR.WaitError)
                bTimerJob = False
                Exit While
            End If
        End While

        iRet = DioSetIrqMask(hDevice, &H0)
        If iRet <> 0 Then
            RaiseEvent MonitorError(MONITOR_ERROR.MaskResetError)
        End If

        CloseHandle(Overlapped.hEvent)

        Overlapped = Nothing

        ReDim dtBit(-1)
        ReDim dtBuff(-1)

        RaiseEvent MonitorError(MONITOR_ERROR.MonitorStop)

    End Sub

#End Region

以上。

引用返信 編集キー/
■52783 / inTopicNo.6)  Re[4]: デジタルI/Oを待つには
□投稿者/ キーサン (13回)-(2010/08/24(Tue) 14:52:13)
オショウさんありがとうございます!

>   型式は?
>   私はボードに関連してインターフェース社のサイトからGPC-2000を入手し
>   IFCDIOクラス(これを.NET用と言われると困る)を作り直して、使ってま
>   す。

インターフェースのは、LPC-284122を買いました。
それから、他に使いたいのはPCIeバスのCC-Linkボードです。
CC-Linkボードなんて、VB2005対応!って書いてあったので
それならC#も行けるだろうって思ってたら、
ついていたのがアンマネージなDLLで、mdfunc.vbというファイルがついていて
中身は、Declare の嵐。
一応、書きなおして使っています。
なので、インターフェースのもポーリングで見て回るしかないかなって思っています。

作りたいのは簡単な計測機なんですが、PLCからの指令によって動くように
したいだけなんです。
PLCはパソコンが動作中信号をOFFするまで待ちますので、
ノイズも全く心配していません。
ただ、PLCからの指令にはなるべく迅速に処理をスタートさせたいなって
思っています。
なので、高頻度で見に行きたいなって思っています。


>   私の自作IFCDIOクラスの一部(スレッドのところ)を参考に載せておきま
>   す。ほかの部分との兼ね合いもありますが、流用して下さい。
>   (VB.NETです)
>
>   2種類のスレッドがありますが、何をどうしているのかは・・・
>   解読して(推測して)みて下さい。Win32 APIも使ってます。

なるほど、いろいろ考えられてコーディングされていらっしゃいますね。
いくつか見た事がないものがありますが、ゆっくり調べながらいきますね。
とても参考になりました。
ありがとうございます。

またよろしくお願いします。
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -