任意の電子回路をシュミレーションし、PLCコードに置き換える画期的なアプリ「Simulink PLC Coder」
Q.1 入力波がAsinωtであるコレクタ接地回路と出力波をGo言語で表してほしい。
Go言語で入力波形を模倣して出力するプログラムを作成する場合、PLCの実際の入出力と接続することは難しいですが、シミュレーションとして入力波形を生成し、出力として模倣する形でコレクタ接地回路の動作を表すことができます。
以下のコードでは、単純に入力波形をサイン波として生成し、それをそのまま出力する形でコレクタ接地回路の動作を再現しています。シミュレーションのため、サンプリング間隔ごとに値を取得して出力する処理を行っています。
```go
package main
import (
"fmt"
"math"
"time"
)
// 定数
const (
Amplitude = 1.0 // 振幅
Frequency = 1.0 // 周波数 (Hz)
SampleRate = 100 // サンプリングレート (サンプル数/秒)
)
func main() {
// サンプリング周期を計算
sampleInterval := 1.0 / SampleRate
t := 0.0
// シミュレーション実行
for i := 0; i < SampleRate*5; i++ { // 5秒間のサンプリング
// 入力波形生成 (A*sin(ωt))
input := Amplitude * math.Sin(2*math.Pi*Frequency*t)
// コレクタ接地回路の出力 (エミッタフォロワーを模倣)
output := input // 実際には少し減衰があるが、ここでは理想的な出力とする
// 結果を出力
fmt.Printf("Time: %.3f sec, Input: %.3f, Output: %.3f
", t, input, output)
// 時間を更新
t += sampleInterval
// サンプリング間隔に合わせてスリープ
time.Sleep(time.Duration(sampleInterval * float64(time.Second)))
}
}
```
### コードの解説
1. **定数の設定**: 振幅 (`Amplitude`)、周波数 (`Frequency`)、およびサンプリングレート (`SampleRate`) を設定します。これにより、入力波形が決定されます。
2. **サンプリング周期の計算**: サンプリング間隔は `1.0 / SampleRate` で計算され、`sampleInterval` に格納されます。
3. **ループでシミュレーション**: `for` ループで時間を進めながら、入力と出力の波形を生成して表示します。ここで、理想的なコレクタ接地回路と仮定し、入力波形をそのまま出力波形にしています。
4. **結果の出力**: `fmt.Printf` を使って、時刻、入力、出力の値を表示します。
5. **サンプリング間隔のスリープ**: 実際の時間間隔に合わせて `time.Sleep` を使用しています。
このコードを実行すると、入力波形(サイン波)と出力波形が時間経過に応じて表示され、理想的なエミッタフォロワー回路における入出力の関係が模倣されます。
Q.2 出力波のグラフを描いて
Go言語で波形のグラフを描画するには、グラフ描画のライブラリを使うのが便利です。代表的なライブラリとして `gonum/plot` があり、これを使用すると簡単に波形をプロットできます。
以下に、`gonum/plot` を使って入力波と出力波をプロットするコードを示します。このコードは、入力波形と出力波形を計算し、波形のグラフを `output.png` に保存します。
### 前提条件
`gonum/plot` ライブラリをインストールするには、以下のコマンドを実行してください:
```sh
go get gonum.org/v1/plot/...
```
### コード例
以下が `gonum/plot` を使って入力波形と出力波形を描画するサンプルコードです。
```go
package main
import (
"math"
"time"
"gonum.org/v1/plot"
"gonum.org/v1/plot/plotter"
"gonum.org/v1/plot/vg"
)
// 定数
const (
Amplitude = 1.0 // 振幅
Frequency = 1.0 // 周波数 (Hz)
SampleRate = 100 // サンプリングレート (サンプル数/秒)
Duration = 1.0 // グラフの表示時間 (秒)
)
func main() {
// サンプリング周期の計算
sampleInterval := 1.0 / SampleRate
numSamples := int(Duration * SampleRate)
// 入力波形と出力波形のデータポイントを格納するスライス
inputData := make(plotter.XYs, numSamples)
outputData := make(plotter.XYs, numSamples)
// 波形データを生成
t := 0.0
for i := 0; i < numSamples; i++ {
// 入力波形生成 (A * sin(ωt))
input := Amplitude * math.Sin(2*math.Pi*Frequency*t)
// コレクタ接地回路の出力 (エミッタフォロワーを模倣)
output := input
// データをスライスに格納
inputData[i].X = t
inputData[i].Y = input
outputData[i].X = t
outputData[i].Y = output
// 時間を更新
t += sampleInterval
}
// プロットの生成
p := plot.New()
p.Title.Text = "Input and Output Waveforms"
p.X.Label.Text = "Time (s)"
p.Y.Label.Text = "Amplitude"
// 入力波形のプロット
inputLine, err := plotter.NewLine(inputData)
if err != nil {
panic(err)
}
inputLine.Color = plotter.DefaultLineStyle.Color // デフォルトカラー
inputLine.LineStyle.Width = vg.Points(1)
// 出力波形のプロット
outputLine, err := plotter.NewLine(outputData)
if err != nil {
panic(err)
}
outputLine.Color = plotter.DefaultLineStyle.Color // 出力波の色
outputLine.LineStyle.Width = vg.Points(1)
outputLine.LineStyle.Dashes = []vg.Length{vg.Points(2), vg.Points(2)} // 出力波の線を破線に設定
// プロットに追加
p.Add(inputLine, outputLine)
p.Legend.Add("Input", inputLine)
p.Legend.Add("Output", outputLine)
// グラフの保存
if err := p.Save(8*vg.Inch, 4*vg.Inch, "output.png"); err != nil {
panic(err)
}
// 完了メッセージ
time.Sleep(1 * time.Second) // 描画完了を待つ
println("出力波のグラフが output.png として保存されました。")
}
```
### コードの解説
1. **定数の設定**: 振幅、周波数、サンプリングレート、表示時間を定義します。
2. **データ生成**: 指定されたサンプリングレートと時間範囲に基づいて、入力波形 ( A sin(omega t) ) を計算し、それを出力波形としてコピーしています。
3. **プロットの生成**: `gonum/plot` を使ってプロットを設定します。`plotter.NewLine` を使って `inputData` と `outputData` をプロットし、それぞれ異なる線のスタイル(入力は実線、出力は破線)で描画します。
4. **グラフの保存**: `output.png` ファイルとしてグラフを保存します。
### 実行結果
このコードを実行すると、`output.png` というファイルに入力波と出力波がプロットされます。理想的には、入力波と出力波は同じ波形になります。