
人々は美しいプレゼンテーションが好きです。 美しい写真、テキスト、スライドの変更。 美しい画像を使用すると、情報を人にすばやく転送し、最も重要な情報を伝えることができます。 私たちは皆それを知っています。 「ハリネズミとヘビを横切る」方法を考えていますか?
マイクロコントローラーまたはFPGA内で発生するプロセスをコンピューターモニターで視覚化する方法は? または、マイクロコントローラーまたはFPGAに実装されたオートメーションシステム全体で何が起こっているかを表示するにはどうすればよいですか?
実際、正解はわかっています。SCADAシステムを使用する必要があります。
SCADAは、監視制御とデータ収集、監視制御とデータ収集です。 しかし、私たちは簡単な方法を探しているのではなく、自転車を少し発明したいと考えています。
センサーから受け取ったデータとコントロールボードから受け取ったデータを表示する簡単な方法を共有したいと思います。
ここでは、まず、3つのコンポーネントを分離する必要があります。
- データ転送プロトコル。 コントローラーからコンピューターに送信される情報を何らかの方法でエンコードする必要があります。
- 自動化システム、マイクロコントローラーまたはFPGAのファームウェア。 このモジュールは、センサーの測定値を収集し、「美しい形」で表示するためにコンピューターに転送する必要があります
- 視覚化ソフトウェア。 センサーのステータスと値を表示します。 たぶん、何らかのグラフィックを構築しているのでしょう。
だから、私が伝えようとするために。
データ転送プロトコル。
現在、コンピューターまたはラップトップにデバイスを接続するための物理的な可能性は2つだけです。イーサネット/ WiFiまたはUSBを介したネットワーク接続です。 「実際の」パラレルポートとシリアルポートはほとんど過去のものです。 彼らにとっては簡単でした。 もちろん、見るとまだ見つかります。 しかし、この方向に考えない方がいいです。
これまでのところイーサネット。 ネットワークを介した伝送には、通常、コントローラーにTCP / IPスタックドライバーが必要です。これにより、通常はLinuxまたはucLinuxのOSが存在します。 次に、ネットワークセットアップインターフェイスが必要です。IPアドレスは何ですか? 静的ですか、動的ですか? どのマスクとゲートウェイ? 一般に、実装と構成はそれほど簡単ではありません。
USBははるかに単純に見えますが、多くの落とし穴があります:デバイスのどのクラス/サブクラスですか? 彼はドライバーが必要ですか?それとも同じWindowsの標準ドライバーが使用されていますか?
繰り返しになりますが、最も簡単な方法は、USB経由でシリアルポートを使用することです。 最も単純なケースでは、USB2Serialのようなコードがあります。 まあ、またはボードとコントローラーの開発者にとって素晴らしいオプションとして-さまざまなFTDIチップ。
OK、USB経由でシリアルポートを選択します。 もしそうなら、データ転送は一連の文字の形で行われます。 さらに簡単です:センサーの測定値は、「SENSOR_NAME = VALUE」という形式の行の形式で送信できます
このアプローチを使用すると、ポーリングされるセンサーの数を簡単に増やし、タイプを簡単に変更できます。 トレーラーまたはリードスイッチの状態は、たとえば、「but0 = 1」または「but1 = 0」という行の形式で送信されます。 温度値は、文字列「t0 = 36.6」の形式で送信できます。 行は、キャリッジリターン文字0x0D 0x0Aで最も簡単に区切られます。
そのため、最初はコンピューター上の視覚化プログラムさえ必要ありません。 Puttyのようなターミナルプログラムを実行するだけで、コントローラーからセンサーの読み取り値を確認できます。
コントローラー
私のコントローラーはアルテラCyclone III FPGAに基づいています。 実際、これは開発者に知られているMars rover2ボードです。 私はすでにそれで実行されたプロジェクトのいくつかについて書きました。 たとえば、このボードでクリーンなFPGA FMラジオトランスミッターを作成したら、 また、 USBトラッカーも作成しました。 他のプロジェクトがあります。
そのようなボードは次のとおりです。

ボードにはすでに2つのボタンがあります。これらは私の実験の最初の2つのセンサーです。
また、ds18b20温度計チップを接続しました-これは2番目のセンサーです。
ADCボードを使用して、まだ何を知らないかを測定することもできます。 これまでのところ、これはセンサーではなく可変抵抗器です。
FTDI FT2232HLマイクロサーキットが既にボード上にあることが重要です。これにより、仮想シリアルポートの形でUSB経由でコンピューターと通信できます。 転送速度はすでに12Mbit / sです。 これは条件付きで1.2 MB /秒です。 たとえば、ボードがセンサーを100ミリ秒ごとにポーリングする場合、ポーリングごとに100Kバイトを超えるデータをコンピューターに転送できることがわかります。 結構。
ボードとFPGA Cyclone IIIのプロジェクトについては説明しません。 これについては別の記事があります。 この記事では、データがどのようにポーリングされ、結果がシリアルポート経由でコンピューターに転送されるかについて詳しく説明します。 コンピューターで実行されるセンサー値を視覚化するためのプログラムである3番目のコンポーネントの検討に移る方が良いでしょう。
データ視覚化プログラム。
ここで私はすべてを迅速かつ簡単にしたかった。 書き込み、変更、補足が簡単になるように、プログラムを書くものは何ですか?
私はPythonを選びましたが、正直なところ、経験はありません。 それはちょうど良いようです。 harazhiteliの一人が言ったように(申し訳ありませんが、私は誰を覚えていません)-「私のpythonのトレーニング」もしたいと思います。
したがって、プログラムはグラフィカルであるため、組み込みのTkinter pythonを試します。 シリアルポートを操作するためにpyserialを使用します。
センサーの種類ごとに独自のクラスを作成します。
最も単純なクラスはバイナリセンサーです。 ボタン、トレーラー、リードスイッチを使用できます。 その値は0または1です。対応するPythonセンサーBinSensorクラスは2つの状態のみを表示します。 各州が独自のイメージを描くことをお勧めします。 画像は、背景画像の上にあるプログラムウィンドウの固定座標に添付されます。

値「0」が到着するとすぐに、最初の画像が表示されます。 値「1」が来ると、2番目の画像が表示されます。 画像は何でも構いません -それはすべて私たちの想像力次第です。
このクラスは次のとおりです。
#!/usr/bin/env python import Tkinter from Tkinter import * root = Tk() class BinSensor: def __init__(self,name,img0,img1,x,y): self.name=name self.x=x self.y=y self.img0=PhotoImage(file=img0) self.img1=PhotoImage(file=img1) self.val=0 self.label_img=Label(root,image=self.img0) self.label_img.place(x=self.x,y=self.y) def set(self,state): if(self.val==state): return self.val=state if( int(state)==0 ): self.label_img.configure(image=self.img0) else: self.label_img.configure(image=self.img1)
クラスがインスタンス化されるときに呼び出される__init__関数には、パラメーターが渡されます。
名前-センサー名
Img0およびimg1は、センサーの状態を表示するために使用される画像ファイルの名前です。
Xとyは、センサーが表示されるウィンドウの座標です。
センサーオブジェクトを作成すると、画像付きのラベルがすぐに作成され、Tkinterウィンドウに配置されます。
set関数は文字列パラメーターを取ります-これはセンサーの新しい状態「0」または「1」です。 新しい値に応じて、ラベル内の画像が再構成され、別の画像に変更されます。 一般に、それですべてです。
同様に、2番目のvBarSensorクラスが実装されます。
class vBarSensor: def __init__(self,name,scale,min,max,x,y,w,h): self.name=name self.scale=scale self.x=x self.y=y self.h=h self.val=min self.min=min self.max=max self.delta=max-min h1=self.h*(self.val-self.min)/self.delta h0=self.h-h1 self.canv0 = Canvas(root, width = w, height = h0, bg = "lightblue", bd=1, relief='ridge') self.canv1 = Canvas(root, width = w, height = h1, bg = "red", bd=1, relief='ridge') self.barLabel = Label(root, text = "0") self.canv0.place(x=self.x,y=self.y) self.canv1.place(x=self.x,y=self.y+h0) self.barLabel.place(x=self.x,y=self.y+h+5) def set(self,newval): #newval is signed hex string like "83A5" val=int(newval,16) if(val>0x7fff): val=-val val=val/self.scale if(self.val==val): return self.val=val h1=self.h*(self.val-self.min)/self.delta h0=self.h-h1 self.barLabel.configure(text=str(self.val)) self.canv0.configure(height = h0) self.canv1.configure(height = h1) self.canv1.place(y=self.y+h0)
このクラスは、温度計タイプのセンサーをグラフィカルに表します。 センサーからの値は、特定の範囲で異なる場合があります。 また、このクラスのインスタンスを作成するときに、センサーの名前を指定する必要があります。 さらに、温度計には可能な最小値と最大値があり、視覚化ウィンドウで列の座標、列の幅と高さも示します。
温度計のコラムは、下の赤と上のライトの2つの部分で構成されています。
1つのTkinterキャンバスを作成し、その上にこれらの列を描画することは可能ですが、何らかの理由で間違っていました。 異なる色の2つのキャンバスを作成し、set()関数でそれらの垂直サイズを変更します。 原則として、これは重要ではありません。 動作します。 ちなみに、視覚化ウィンドウで温度計の画像を正確に表示する場合は、ウィンドウの背景画像にそれを描画し、その上にvBarSensorインスタンスを配置できます。

おそらくいいでしょう。
センサーの測定値を表示し、それらを経時的に変更するために、別のGridDisplayクラスを作成しました。 不要な詳細で記事をオーバーロードしないように、ここではソースコードを引用しません。 サイトからプロジェクト全体をダウンロードする必要があるのは、アルテラQuartus IIのFPGAのソースです。
しかし、おそらくメインプログラムalls.pyが表示されます。 ここには多くのものはありません:
#!/usr/bin/env python import sensor from sensor import * import serial from serial import * class AllSensors: def __init__(self): #open serial port self.s=serial.Serial("COM27",115200,timeout=10) #load background image self.bgnd=PhotoImage(file="bgnd.gif") self.label_bgnd=Label(root,image=self.bgnd) self.label_bgnd.place(x=0,y=0) #add all sensors and indicators self.all=[] self.all.append( BinSensor("b0","f0.gif","f1.gif",32,32) ) self.all.append( BinSensor("b1","f0.gif","f1.gif",32,128) ) self.all.append( vBarSensor("a0",1,0,255,128,32,32,160) ) self.all.append( GridDisplay("t0",16,-55,125,10,16,180,32,256,160) ) def set(self,name,val): for sens in self.all: if(sens.name==name): sens.set(val) return def setline(self,line): p=line.split("=") if(len(p)==2): self.set( p[0], p[1] ) def run(self): while(1): line=self.s.readline() line=line.rstrip() #print(line) self.setline(line) root.update() a=AllSensors() a.run()
このプログラムでは、読み取り用にシリアルポートを開きます。 背景画像をウィンドウにロードします。 利用可能なすべてのセンサーのリストを作成します。 次に、ポートから行を読み取り、それらを逆アセンブルして、センサーの名前で対応するクラスインスタンスに新しい値を渡します。
Pythonからプログラムを実行するのは簡単です。「allsをインポートする」 。allsはメインプログラムの名前であるalls.pyファイルです。 これは私のプログラムが今どのように見えるかです:

すべての仕組みを示すビデオを次に示します(心配しないで、温度センサーを加熱するためにそこのドライヤーをオンにしますので、音をねじ込む方が良いです)。
アプリケーションの「スケルトン」が機能しているので、フロアプランとそこにインストールされているセンサーの詳細な図面に進むことができます。