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

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

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

Re[7]: 電圧の変化をチャートで表示する方法


(過去ログ 155 を表示中)

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

■90131 / inTopicNo.1)  電圧の変化をチャートで表示する方法
  
□投稿者/ みどり (1回)-(2019/02/11(Mon) 21:31:04)

分類:[.NET 全般] 

ADコンバーターを使ってある機器の電圧をPCで取り込んでいます。

例えば、
1秒おきに電圧を取得し、
10分間に渡って、その電圧の変化をチャートで表示し、
10分経過後は、first in first outで
最初に入ったデータを廃棄しつつ、後から取得したデータを表示するというようなことをしたいと考えています。

10分経過前のコードは非常に簡単で、
要素数600の配列を用意し、
要素1から順番に取得した電圧を格納しつつ、
その配列をチャート表示すれば実現できます。

一方で、10分間経過後は、
要素1〜599に格納されたデータを一つ後ろの要素(2〜600)にシフトさせた上で
要素1に新しいデータを格納する
というような操作が必要だと思います。

要素数が600くらいだと大したことないと思いますが
更に要素数が増えてくると処理が重たくなると思います。

もっと簡便にチャート表示できる方法があれば
ご教授いただけないでしょうか?


引用返信 編集キー/
■90132 / inTopicNo.2)  Re[1]: 電圧の変化をチャートで表示する方法
□投稿者/ キングダム (4回)-(2019/02/11(Mon) 22:40:00)
No90131 (みどり さん) に返信

サイズが固定のFIFOを作れば要素数増えても処理が遅くなることはないですよ

値を追加するときにFIFOのサイズを調べて所定のサイズ以上であれば先っちょから
値を一つ取り出してしっぽに値を追加するって感じで


引用返信 編集キー/
■90135 / inTopicNo.3)  Re[2]: 電圧の変化をチャートで表示する方法
□投稿者/ Azulean (1032回)-(2019/02/12(Tue) 06:09:59)
要素の移動がどうしても気になる場合は、リングバッファという言葉を調べてみてください。
追加/上書きする時の位置が1つずつずれていく、取り出すときの先頭位置が変わっていく形になります。
引用返信 編集キー/
■90137 / inTopicNo.4)  Re[1]: 電圧の変化をチャートで表示する方法
□投稿者/ WebSurfer (1760回)-(2019/02/12(Tue) 09:21:59)
No90131 (みどり さん) に返信

「チャート」と言うのは Microsoft の .NET のライブラリに含まれる Chart
の Windows Forms 用のことですか?

そうだとして、サンプルは持っていて見ることはできますか?
引用返信 編集キー/
■90139 / inTopicNo.5)  Re[2]: 電圧の変化をチャートで表示する方法
□投稿者/ みどり (3回)-(2019/02/12(Tue) 10:22:39)
リングバッファーというものは知っているのですが、
これはVB.NETでも実装することが可能でしょうか?

検索して調べてみると

C#らしきコードは見つかったのですが

https://ufcpp.net/study/algorithm/col_circular.html
https://qiita.com/gushwell/items/9e07156514d81d773640

これは自分でコードを書くしかないでしょうか?

どれを使えば良いでしょうか?


チャートというのはもちろんWindows Forms 用のものです。
サンプルというか今まで何度もChartコントロールを使ったプログラムは作成しているので
これの作り方は問題ありません。

引用返信 編集キー/
■90140 / inTopicNo.6)  Re[3]: 電圧の変化をチャートで表示する方法
□投稿者/ WebSurfer (1761回)-(2019/02/12(Tue) 10:53:21)
No90139 (みどり さん) に返信

> サンプルというか今まで何度もChartコントロールを使ったプログラムは作成しているので
> これの作り方は問題ありません。

「作り方は問題ありません」と言い切れるほど自信をお持ちのようですが・・・

何にせよ、サンプルは持っていないということですか?

Chart サンプルに含まれるいろいろな情報を含めて Chart の知識は十分なので、サンプル
など見る必要はない・・・とまでは言い切れないならサンプルを入手して見てみてはどう
かと思うのですが。

サンプルの Working with Data > Real Time Data の中に Real Time Data (Thread Safe)
と Real Time Data (Timer) という 2 つのサンプルがありますが、前者のサンプルがやり
たいことに近いような気がします。

前者のサンプルのスクリーンショットを自分のサイトに保存して、その url を以下に書い
ておきますので見てください。

http://surferonwww.info/BlogEngine/image.axd?picture=2019%2f2%2fChart.jpg

そんなもの十分承知ということでしたら失礼。


引用返信 編集キー/
■90141 / inTopicNo.7)  Re[4]: 電圧の変化をチャートで表示する方法
□投稿者/ ぼーちゃん (6回)-(2019/02/12(Tue) 10:54:53)
System.Collections.Generic.Queue<T>というジェネリッククラスのキューがあるのでそれを使えばよいのでは。
ToArrayメソッドで要素全体を配列として取得できます。
上限600のとき、601個が追加(エンキュー)されたら最古の要素を削除(デキュー)
するという処理は自分で書かないといけないですけどネットにサンプルがありました。

https://takachan.hatenablog.com/entry/2018/01/02/044400

ただQueue<T>はスレッドセーフでないので、もし電圧値の追加が別スレッドから
行われるような場合、並列処理に対応したConcurrentQueue<T> を使ったほうがいいです。

https://docs.microsoft.com/ja-jp/dotnet/api/system.collections.concurrent.concurrentqueue-1?view=netframework-4.7.2
引用返信 編集キー/
■90143 / inTopicNo.8)  Re[3]: 電圧の変化をチャートで表示する方法
□投稿者/ Azulean (1033回)-(2019/02/12(Tue) 12:49:34)
No90139 (みどり さん) に返信
> リングバッファーというものは知っているのですが、
> これはVB.NETでも実装することが可能でしょうか?

できます。
リングバッファ自体は言語に依存しない考え方なので。

もっとも、Queue を使えば、Capacity(最大容量)を変えない限り、リングバッファと同じ効果が手軽に得られそうです。
引用返信 編集キー/
■90145 / inTopicNo.9)  Re[3]: 電圧の変化をチャートで表示する方法
□投稿者/ WebSurfer (1763回)-(2019/02/12(Tue) 14:59:26)
No90139 (みどり さん) に返信

Chart サンプルの入手方法インストール方法を書いた記事を紹介しておきます。
興味があったら見てください。

Chart Samples
http://surferonwww.info/BlogEngine/post/2016/02/14/chart-samples.aspx
引用返信 編集キー/
■90152 / inTopicNo.10)  Re[4]: 電圧の変化をチャートで表示する方法
□投稿者/ みどり (4回)-(2019/02/12(Tue) 19:43:23)
2019/02/12(Tue) 19:44:52 編集(投稿者)
2019/02/12(Tue) 19:44:48 編集(投稿者)

<pre><pre>WebSurfer さん

ありがとうございます。

確かにこの方法ならできそうな気がしましたので
試してみました。


まず、C#のものをそのままビルドして試してみたのですが


</pre></pre>
引用返信 編集キー/
■90153 / inTopicNo.11)  Re[5]: 電圧の変化をチャートで表示する方法
□投稿者/ みどり (5回)-(2019/02/12(Tue) 19:46:52)
WebSurfer さん

ありがとうございます。

確かにこの方法ならできそうな気がしましたので
試してみました。


まず、C#のものをそのままビルドして試してみたのですが



fileIn = new StreamReader(fileName);

というところで以下のエラーが出てしまい実行できませんでした。

型 'System.IO.FileNotFoundException' のハンドルされていない例外が mscorlib.dll で発生しました

追加情報:ファイル 'D:\desktop\Windows Forms Samples Environment for Microsoft Chart Controls\cs_langDef.xml' が見つかりませんでした。





仕方なく、VBのコードを少し改良したところ、うまくビルドできました。


ただし、ResumeとSuspendのところで警告メッセージが出てしまいます。

警告	BC40000	'Public Overloads Sub [Resume]()' は廃止されています: 'Thread.Resume has been deprecated.  Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources.  http://go.microsoft.com/fwlink/?linkid=14202'。
警告	BC40000	'Public Overloads Sub Suspend()' は廃止されています: 'Thread.Suspend has been deprecated.  Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources.  http://go.microsoft.com/fwlink/?linkid=14202'。

どうも、これらのコードの使用をいまのVSが推奨していないようです。

一体、どのように書き換えたら良いでしょうか?




Public Class Form1


    Private addDataRunner As Thread
    Private rand As New Random()
    ' Private chart3 As System.Windows.Forms.DataVisualization.Charting.Chart
    Public Delegate Sub AddDataDelegate()
    Public addDataDel As AddDataDelegate


    Private minValue, maxValue As DateTime


    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load


        Dim addDataThreadStart As New ThreadStart(AddressOf AddDataThreadLoop)
        addDataRunner = New Thread(addDataThreadStart)

        addDataDel = New AddDataDelegate(AddressOf AddData)

    End Sub 'RealTimeSample_Load

    Private Sub startTrending_Click(sender As Object, e As System.EventArgs) Handles startTrending.Click
        ' Disable all controls on the form
        startTrending.Enabled = False
        ' and only Enable the Stop button
        stopTrending.Enabled = True

        ' Predefine the viewing area of the chart
        minValue = DateTime.Now
        maxValue = minValue.AddSeconds(120)

        Chart2.ChartAreas(0).AxisX.Minimum = minValue.ToOADate()
        Chart2.ChartAreas(0).AxisX.Maximum = maxValue.ToOADate()

        ' Reset number of series in the chart.
        Chart2.Series.Clear()

        ' create a line chart series
        Dim newSeries As New Series("Series1")
        newSeries.ChartType = SeriesChartType.Line
        newSeries.BorderWidth = 2
        newSeries.Color = Color.OrangeRed
        newSeries.XValueType = ChartValueType.DateTime
        Chart2.Series.Add(newSeries)

        ' start worker threads.
        If addDataRunner.IsAlive = True Then
            addDataRunner.Resume()
        Else
            addDataRunner.Start()
        End If
    End Sub 'startTrending_Click 

    Private Sub stopTrending_Click(sender As Object, e As System.EventArgs) Handles stopTrending.Click
        If addDataRunner.IsAlive = True Then
            addDataRunner.Suspend()
        End If

        ' Enable all controls on the form
        startTrending.Enabled = True
        ' and only Disable the Stop button
        stopTrending.Enabled = False
    End Sub 'stopTrending_Click



    '/ Main loop for the thread that adds data to the chart.
    '/ The main purpose of this function is to Invoke AddData
    '/ function every 1000ms (1 second).
    Private Sub AddDataThreadLoop()
        While True
            Chart2.Invoke(addDataDel)

            Thread.Sleep(1000)
        End While
    End Sub 'AddDataThreadLoop

    Public Sub AddData()
        Dim timeStamp As DateTime = DateTime.Now

        Dim ptSeries As Series
        For Each ptSeries In Chart2.Series
            AddNewPoint(timeStamp, ptSeries)
        Next ptSeries
    End Sub 'AddData

    '/ The AddNewPoint function is called for each series in the chart when
    '/ new points need to be added.  The new point will be placed at specified
    '/ X axis (Date/Time) position with a Y value in a range +/- 1 from the previous
    '/ data point's Y value, and not smaller than zero.
    Public Sub AddNewPoint(timeStamp As DateTime, ptSeries As System.Windows.Forms.DataVisualization.Charting.Series)
        Dim newVal As Double = 0

        If ptSeries.Points.Count > 0 Then
            newVal = ptSeries.Points((ptSeries.Points.Count - 1)).YValues(0) + (rand.NextDouble() * 2 - 1)
        End If

        If newVal < 0 Then
            newVal = 0
        End If
        ' Add new data point to its series.
        ptSeries.Points.AddXY(timeStamp.ToOADate(), rand.Next(10, 20))

        ' remove all points from the source series older than 1.5 minutes.
        Dim removeBefore As Double = timeStamp.AddSeconds((CDbl(90) * -1)).ToOADate()
        'remove oldest values to maintain a constant number of data points
        While ptSeries.Points(0).XValue < removeBefore
            ptSeries.Points.RemoveAt(0)
        End While

        Chart2.ChartAreas(0).AxisX.Minimum = ptSeries.Points(0).XValue
        Chart2.ChartAreas(0).AxisX.Maximum = DateTime.FromOADate(ptSeries.Points(0).XValue).AddMinutes(2).ToOADate()

        Chart2.Invalidate()
    End Sub 'AddNewPoint

    '/ Clean up any resources being used.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If (addDataRunner.ThreadState And ThreadState.Suspended) = ThreadState.Suspended Then
            addDataRunner.Resume()
        End If
        addDataRunner.Abort()

        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub 'Dispose




End Class


引用返信 編集キー/
■90154 / inTopicNo.12)  Re[6]: 電圧の変化をチャートで表示する方法
□投稿者/ キングダム (6回)-(2019/02/12(Tue) 22:16:45)
No90153 (みどり さん) に返信

addDataRunner.Suspend()
addDataRunner.Resume()

これらですね、Suspendはスレッドを一時停止するもので
Resumeはスレッドを再開するものです

スレッドの機能として呼ばれるまで待機してるぜ的なものがあるはずなので
それを使えばよいです

> Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources.

エラーメッセージみるとMonitorやMutex, Event, Semaphoreを使ってちょということみたいですね
どれがいんでしょうね

引用返信 編集キー/
■90155 / inTopicNo.13)  Re[7]: 電圧の変化をチャートで表示する方法
□投稿者/ キングダム (7回)-(2019/02/13(Wed) 00:02:18)
とりいそぎ、MonitorとEventを完全に理解しました

Monitorの場合はロックをとって
条件をチェックするループをぐるぐる回してその中で
Monitor.Wait(lockObject)を呼ぶことで待機できます

再開するときはロックをとって条件を設定して
Monitor.PulseAll(lockObject)を呼べばよいです

Monitor
https://paiza.io/projects/RBB8HoQLhliwXS0O1TihFQ?language=vb


Eventの場合はWaitOne()で待機
Set()で再開って感じです

Event
https://paiza.io/projects/-pb8dXvfoaM5qHwGheXW9A?language=vb


Eventが良さそうですよ

MutexとSemaphoreはロックの代わりに使えるのさってことみたいですけど
今回の用途にどう役立てるのかよくわかりませんでした

引用返信 編集キー/
■90157 / inTopicNo.14)  Re[6]: 電圧の変化をチャートで表示する方法
□投稿者/ WebSurfer (1766回)-(2019/02/13(Wed) 08:13:06)
No90153 (みどり さん) に返信

> まず、C#のものをそのままビルドして試してみたのですが
>
> fileIn = new StreamReader(fileName);
>
> というところで以下のエラーが出てしまい実行できませんでした。
>
> 型 'System.IO.FileNotFoundException' のハンドルされていない例外が mscorlib.dll で発生しました
>
> 追加情報:ファイル 'D:\desktop\Windows Forms Samples Environment for Microsoft Chart Controls\cs_langDef.xml' が見つかりませんでした。
>

私が紹介した記事「Chart Samples」読んでないのでは?

フォルダ名が C# のままではダメなんですよ。


引用返信 編集キー/
■90202 / inTopicNo.15)  Re[7]: 電圧の変化をチャートで表示する方法
□投稿者/ みどり (6回)-(2019/02/16(Sat) 21:29:32)
皆様、どうもありがとうございます。

スレッド処理の方はエラー内容のところに解決策が書かれていましたね。
すいません、見落としていました。

あと、フォルダー名は最初からCsharpとかにしておいてほしかったです。
デフォルトで読み込めないものをアップしているなんて
マイクロソフトは何を考えているんでしょうか・・・?

とりあえず、閉めさせていただきます。

解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -